CodeV

3.3-提取图片部分区域

与将图像数据压缩为较小版本的缩略图不同,子图像是以与原始图像相同的分辨率检索生成图像的部分区域。图3-3显示了雪貂头部的详细版本,从图像的左上角提取。放大的子图像突出显示提取的部分。正如你所看到的,你不能添加分辨率; 当放大时,结果变得模糊。

图3-3

图3-3底部图像是提取自原始图像的一部分的子图像。 Public domain images courtesy of the National Park Service

清单3-3显示了创建此子图像的函数。它使用简单的Quartz函数CGImageCreateWithImageInRect()从原始内容构建其新图像。在这种情况下使用Quartz而不是UIKit提供了一个现成的单一功能。

当您使用此Core Graphics函数时,矩形将使用CGRectIntegral()自动调整为像素线。 然后与原始图像矩形相交,因此不会出现子矩形落在原始图像边界之外。这节省了大量的工作。 所有你需要做的是将由函数返回的CGImageRef转换为UIImage实例。

当您的参考矩形是为Retina系统定义时,并且您正在以Quartz坐标提取数据时,会出现一个缺陷。为此,我在清单3-3中添加了第二个函数,它完全在UIKit中运行,而不是在坐标系之间转换矩形,它假定您引用的矩形是以点而不是像素定义的。当你询问一个图像的边界,然后围绕它的中心建立一个矩形时,这是很重要的。如果你忘记了从点到像素的转换,那么视网膜图像的“中心”实际上可能更接近它的左上角。通过换用UIKit框架,你规避了整个问题,从而确保你提取的图片的bit(数据)是你真正想要的部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
UIImage *ExtractRectFromImage(UIImage *sourceImage, CGRect subRect)
{
// Extract image
CGImageRef imageRef = CGImageCreateWithImageInRect(sourceImage.CGImage, subRect);
if (imageRef != NULL)
{
UIImage *output = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return output;
}

NSLog(@"Error: Unable to extract subimage");
return nil;
}

// This is a little less flaky
// when moving to and from Retina images
UIImage *ExtractSubimageFromRect(UIImage *sourceImage, CGRect rect)
{
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 1);
CGRect destRect = CGRectMake(-rect.origin.x, -rect.origin.y,sourceImage.size.width, sourceImage.size.height);
[sourceImage drawInRect:destRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

本文翻译自《iOS Drawing Practical UIKit Solutions》作者:Erica Sadun,翻译:Cheng Dong。如果觉得本书不错请购买支持正版:亚马逊购买传送门,本书所有源代码可在GitHub上下载。译者虽然力求做到信,达,雅,但是由于时间仓促加之译者水平十分有限,文中难免会出现不正确,不准确,词不达意,难于理解的地方,还望各位批评指正,共同进步,谢谢。转载请注明出处。