UIImage - 如何修改图像的一部分并用修改后的版本替换原始图像?

时间:2015-02-12 19:16:31

标签: ios objective-c uiimage core-graphics

我以递归方式(使用计时器)对UIImageView中的图像应用蒙版,我想根据用户触摸屏幕的位置在某个区域应用蒙版。

要定义该区域,用户触摸屏幕并读取触摸当前位置。此位置定义了我想要修改的区域的中心。

到目前为止,我只能使用CGImageCreateWithMask将蒙版应用于整个图像。我用来应用掩码的代码是:

- (UIImage *)maskImageWithCurrentContext:(UIImage *)image withMask:(UIImage *)maskImage{
    UIImage *maskedImage;

    float width = image.size.width;
    float height = image.size.height;

    CGRect rect = CGRectMake(0, 0, width, height);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0, height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CGImageRef maskRef = maskImage.CGImage;
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                    CGImageGetHeight(maskRef),
                                    CGImageGetBitsPerComponent(maskRef),
                                    CGImageGetBitsPerPixel(maskRef),
                                    CGImageGetBytesPerRow(maskRef),
                                    CGImageGetDataProvider(maskRef),
                                    NULL,
                                    false);

    CGImageRef masked = CGImageCreateWithMask(image.CGImage, mask);

    CGContextDrawImage(context, rect, masked);

    maskedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CGImageRelease(mask);
    CGImageRelease(masked);

    return maskedImage;
}

我调用该方法的方式是self.imageViewGelo.image = [self maskImageWithCurrentContext:self.imageViewGelo.image withMask:self.imageMask];(在触摸视图时激活的计时器内部),然后将生成的图像应用于我想要修改的视图。

我面临的问题是,我希望得到整个图像的区域,将遮罩应用于它,然后在原始图像中应用新区域,以显示修改。例如,如果我有一个尺寸为1024x768的图像,并且用户用坐标(300,200)触摸该点,我想选择尺寸为50x50的区域,应用蒙版,然后将得到的图像放在同一区域。

我使用的面具几乎都是黑色的,并且有一些区域略微更多"光" (就像真正的深色灰色),以便产生缓慢融冰的效果。

我已经阅读过文档并搜索了几个小时有关任何类似问题,但没有运气。

在iPad 4上运行的上述代码的性能,定时器设置为每0.1秒触发一次(仅测试值)非常好,没有任何内存问题和相对较低的处理器使用率。

如果有人可以帮我解决这个问题,请提前多多感谢。

1 个答案:

答案 0 :(得分:0)

最后,我的代码按照我的意图运行。

首先,我使用基于Matt在following post.中提供的代码来裁剪用户触摸的位置中的部分图像。谢谢Matt。 :)

裁剪图片的代码是:

- (UIImage *)cropImage:(UIImage *)original{
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(kSizeMaskImageWidth, kSizeMaskImageHeight), NO, original.scale);

    [original drawAtPoint:CGPointMake(-((int)touchLocation.x - kSizeMaskImageWidth / 2), -((int)touchLocation.y - kSizeMaskImageHeight / 2))];
    UIImage *cropped = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return cropped;
}

接下来,我在完全相同的位置绘制一个透明矩形,具有完全相同的尺寸,在那里我应用我在前面的代码中获得的裁剪图像。为实现这一切,我使用以下代码:

- (UIImage *)maskImageWithCurrentContext:(UIImage *)originalImage withMask:(UIImage *)maskImage inCroppedImage:(UIImage *)croppedImage{
    float width = originalImage.size.width;
    float height = originalImage.size.height;

    CGRect rect = CGRectMake(0, 0, width, height);
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, originalImage.scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0, height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CGImageRef maskRef = maskImage.CGImage;
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                    CGImageGetHeight(maskRef),
                                    CGImageGetBitsPerComponent(maskRef),
                                    CGImageGetBitsPerPixel(maskRef),
                                    CGImageGetBytesPerRow(maskRef),
                                    CGImageGetDataProvider(maskRef),
                                    NULL,
                                    false);

    CGImageRef masked = CGImageCreateWithMask(croppedImage.CGImage, mask);

    CGContextDrawImage(context, rect, originalImage.CGImage);
    CGContextClearRect(context, CGRectMake(((int)touchLocation.x - kSizeMaskImageWidth / 2), height - ((int)touchLocation.y + kSizeMaskImageHeight / 2), kSizeMaskImageWidth, kSizeMaskImageHeight));
    CGContextDrawImage(context, CGRectMake(((int)touchLocation.x - kSizeMaskImageWidth / 2), height - ((int)touchLocation.y + kSizeMaskImageHeight / 2), kSizeMaskImageWidth, kSizeMaskImageHeight), masked);

    UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CGImageRelease(mask);
    CGImageRelease(masked);

    return maskedImage;
}

使用此代码绘制原始图像,然后在原始图像的顶部绘制透明矩形,最后在透明矩形内绘制裁剪后的图像。

我在视网膜iPad上的触摸位置有一些问题,因为触摸是通过点检测到的。当我试图绘制图像时,有时位置是x,5,所以我必须将它转换为int,以便摆脱小数位。

现在我实现了冰融化的效果,使用计时器递归地应用蒙版,并将其应用于用户触摸屏幕的位置。 :)

作为最后一点,由于检测到的触摸比我正在使用的定时器间隔检测得快,我在绘制前禁用视图中的触摸,并在绘制完成后再次启用它们。