首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >drawRect优化

drawRect优化
EN

Stack Overflow用户
提问于 2012-09-20 14:51:49
回答 1查看 1K关注 0票数 0

我正在开发一个应用程序,允许用户选择一个图像(相机或图库),然后用手指在该图像上进行绘图。他们画的区域变成了面具的透明部分。然后,在第一图像下面绘制第二图像。

我一直在努力提高性能,特别是在iPad 3上,我似乎遇到了困难。我是iOS和目标C的新手。

所以我的问题是:我能做些什么来提高我的应用程序的绘图性能?

我使用本教程作为代码的起点。

首先,我绘制一个缓存上下文:

代码语言:javascript
复制
- (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:

代码语言:javascript
复制
- (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性能

CGContextDrawImage在iPhone 4上非常慢

用CATiledLayer和CoreGraphics CGContextDrawImage绘图

iPhone:如何向UIView的根层添加层以显示具有content属性的图像?

iPhone CGContextDrawImage和UIImageJPEGRepresentation大大减慢了应用程序

任何帮助都是非常感谢的!

谢谢,凯文

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-09-20 15:32:45

我可以给你一些提示,但是你需要做一些实验,看看问题出在哪里(使用仪器):

  • 不要假设您需要绘制整个视图-当您需要脏某个区域时,请使用setNeedsDisplayInRect。然后在drawRect中只更新脏区域。
  • 以上所示意味着您的maskRef要小得多,而且易于构建。
  • 而不是“self.original CGImage”,使用CGImageCreateWithImageInRect()创建一个较小的子区域映像,它允许您选择图像的一个分段,然后结合掩码使用该较小的图像。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12515269

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档