0

私は、ユーザーが画像(カメラまたはギャラリー)を選択し、その画像を指で描くことができるアプリケーションに取り組んでいます。彼らが描く領域は、マスクの透明な部分になります。次に、2番目の画像が最初の画像の下に描画されます。

私は特にiPad3でパフォーマンスの向上に取り組んできましたが、壁にぶつかったようです。私はiOSとObjective-Cを初めて使用します。

だから私の質問は:私のアプリケーションの描画パフォーマンスを改善するために何ができますか?

このチュートリアルをコードの開始点として使用しました。

まず、キャッシュコンテキストに描画します。

- (void) drawToCache {
    CGRect dirtyPoint1;
    CGRect dirtyPoint2;
    UIColor *color;

    if (point1.x > -1){
        hasDrawn = YES;

        maskContext = CGLayerGetContext(maskLayer);
        blackBackgroundContext = CGLayerGetContext(blackBackgroundLayer);

        if (!doUndo){
            color = [UIColor whiteColor];
            CGContextSetBlendMode(maskContext, kCGBlendModeColor);
        }
        else{
            color = [UIColor clearColor];
            CGContextSetBlendMode(maskContext, kCGBlendModeClear);
        }

        CGContextSetShouldAntialias(maskContext, YES);

        CGContextSetRGBFillColor(blackBackgroundContext, 0.0, 0.0, 0.0, 1.0);
        CGContextFillRect(blackBackgroundContext, self.bounds);

        CGContextSetStrokeColorWithColor(maskContext, [color CGColor]);
        CGContextSetLineCap(maskContext, kCGLineCapRound);
        CGContextSetLineWidth(maskContext, brushSize);

        double x0 = (point0.x > -1) ? point0.x : point1.x; //after 4 touches we should have a back anchor point, if not, use the current anchor point
        double y0 = (point0.y > -1) ? point0.y : point1.y; //after 4 touches we should have a back anchor point, if not, use the current anchor point
        double x1 = point1.x;
        double y1 = point1.y;
        double x2 = point2.x;
        double y2 = point2.y;
        double x3 = point3.x;
        double y3 = point3.y;

        double xc1 = (x0 + x1) / 2.0;
        double yc1 = (y0 + y1) / 2.0;
        double xc2 = (x1 + x2) / 2.0;
        double yc2 = (y1 + y2) / 2.0;
        double xc3 = (x2 + x3) / 2.0;
        double yc3 = (y2 + y3) / 2.0;

        double len1 = sqrt((x1-x0) * (x1-x0) + (y1-y0) * (y1-y0));
        double len2 = sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1));
        double len3 = sqrt((x3-x2) * (x3-x2) + (y3-y2) * (y3-y2));

        double k1 = len1 / (len1 + len2);
        double k2 = len2 / (len2 + len3);

        double xm1 = xc1 + (xc2 - xc1) * k1;
        double ym1 = yc1 + (yc2 - yc1) * k1;
        double xm2 = xc2 + (xc3 - xc2) * k2;
        double ym2 = yc2 + (yc3 - yc2) * k2;

        double smooth_value = 0.5;
        float ctrl1_x = xm1 + (xc2 - xm1) * smooth_value + x1 - xm1;
        float ctrl1_y = ym1 + (yc2 - ym1) * smooth_value + y1 - ym1;
        float ctrl2_x = xm2 + (xc2 - xm2) * smooth_value + x2 - xm2;
        float ctrl2_y = ym2 + (yc2 - ym2) * smooth_value + y2 - ym2;

        CGContextMoveToPoint(maskContext, point1.x, point1.y);
        CGContextAddCurveToPoint(maskContext, ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y, point2.x, point2.y);
        CGContextStrokePath(maskContext);

        dirtyPoint1 = CGRectMake(point1.x-(brushSize/2), point1.y-(brushSize/2), brushSize, brushSize);
        dirtyPoint2 = CGRectMake(point2.x-(brushSize/2), point2.y-(brushSize/2), brushSize, brushSize);
        [self setNeedsDisplayInRect:CGRectUnion(dirtyPoint1, dirtyPoint2)];
    }
}

そして私のdrawRect:

- (void)drawRect:(CGRect)rect {
    CGRect imageRect = CGRectMake(0, 0, 1024, 668);
    CGSize size =  CGSizeMake(1024, 668);

    //Draw the user touches to the context, this creates a black and white image to convert into a mask
    UIGraphicsBeginImageContext(size);
    CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(), YES);
    CGContextDrawLayerInRect(UIGraphicsGetCurrentContext(), imageRect, blackBackgroundLayer);
    CGContextDrawLayerInRect(UIGraphicsGetCurrentContext(), imageRect, maskLayer);
    CGImageRef maskRef = CGBitmapContextCreateImage(UIGraphicsGetCurrentContext());
    UIGraphicsEndImageContext();

    //Make the mask
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef), CGImageGetHeight(maskRef), CGImageGetBitsPerComponent(maskRef), CGImageGetBitsPerPixel(maskRef), CGImageGetBytesPerRow(maskRef), CGImageGetDataProvider(maskRef), NULL, false);
    //Mask the user image
    CGImageRef masked = CGImageCreateWithMask([self.original CGImage], mask);

    UIGraphicsBeginImageContext(size);
    CGContextDrawLayerInRect(UIGraphicsGetCurrentContext(), imageRect, backgroundTextureLayer);
    CGImageRef background = CGBitmapContextCreateImage(UIGraphicsGetCurrentContext());
    UIGraphicsEndImageContext();

    //Flip the context so everything is right side up
    CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, 668);
    CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0);

    //Draw the background on the context
    CGContextDrawImage(UIGraphicsGetCurrentContext(), imageRect, background);

    //Draws the mask on the context
    CGContextDrawImage(UIGraphicsGetCurrentContext(), imageRect, masked);

    //Release everything to prevent memory leaks
    CGImageRelease(background);
    CGImageRelease(maskRef);
    CGImageRelease(mask);
    CGImageRelease(masked);
}

私は昨日これらの質問を調査するのに費やしました:

CGContextFillRectとCGContextDrawImageのパフォーマンスを向上させるにはどうすればよいですか

iPhone4ではCGContextDrawImageが非常に遅い

CoreGraphicsCGContextDrawImageを使用したCATiledLayerでの描画

iPhone:UIViewのルートレイヤーにレイヤーを追加して、contentプロパティを持つ画像を表示するにはどうすればよいですか?

iPhoneCGContextDrawImageとUIImageJPEGRepresentationはアプリケーションを大幅に遅くします

どんな助けでも大歓迎です!

ありがとう、ケビン

4

1 に答える 1

2

私はあなたにいくつかのヒントを与えることができますが、あなたは問題がどこにあるかを確かめるために実験する必要があります(Instrumentsを使用して):

  • ビュー全体を描画する必要があるとは限りません。一部の領域をダーティにする必要がある場合は、setNeedsDisplayInRectを使用してください。次に、drawRectでダーティエリアのみを更新します。

  • 上記は、maskRefがはるかに小さく、構築が容易であることを意味します

  • '[self.original CGImage]'の代わりに、CGImageCreateWithImageInRect()を使用して小さいサブ領域画像を作成します。これにより、画像のサブセクションを選択し、その小さい画像をマスクと組み合わせて使用​​できます。

于 2012-09-20T15:32:45.587 に答える