虽然可以查询图像的PNG(UIImagePNGRepresentation()
)或JPEG(UIImageJPEGRepresentation()
)表示,但这些函数返回适合于将图像存储为文件格式的数据。它们包括文件头和标记数据,内部块和压缩,数据不是用于逐字节操作的。当您计划执行图像处理时,您需要从上下文中提取字节数组。清单3-6显示了如何去做。
此函数将图像绘制到上下文中,然后使用CGBitmapContextGetData()
检索源字节。它将这些字节复制到NSData
实例,并将该实例返回给调用者。
将输出数据包装到NSData
对象中可以绕过有关内存分配,初始化和管理的问题。虽然你可能最终在基于C的API(如Accelerate)中使用这些数据,但是你可以从Objective-C的角度来这样做。
Note
这里讨论的字节处理不意味着要使用Core Image,它有自己的一套技术和实践。
创建上下文
在本书中,您已经遇到了CGBitmapContextCreate()
函数。它需要七个参数来定义如何创建上下文。在大多数情况下,你可以把它当作变化很小的样板。以下是参数和您需要提供的值的细节描述:
- void * data - 通过将
NULL
传递给第一个参数,您要求Quartz代表您分配内存。 Quartz然后在该内存上执行自己的管理,因此您不必显式分配或释放它。您可以通过调用CGBitmapContextGetData()
访问数据,这是清单3-6中为了填充它创建的NSData
对象。正如名字中的get所示,这个函数读取数据,但不复制它,否则会干扰它的内存管理。 - size_t width和size_t height - 接下来的两个参数是图像宽度和高度。size_t类型在iOS上定义为unsigned long。清单3-6将从源图像尺寸检索到的宽和高传递到
CGBitmapContextCreate()
。 - size_t bitsPerComponent - 在UIKit中,使用8位字节(uint_8),因此除非您有其他令人信服的理由否则只需传递8。Quartz 2D编程指南列出了所有支持的像素格式,其中可以包括5位,16位和32位components。 component是指单个信道的信息。ARGB数据每像素使用四个分量。灰度数据使用一个(无alpha通道数据)或两个(带alpha通道数据)分量。
- size_t bytesPerRow - 将行的大小乘以每个组件的字节数,以计算每行的字节数。 通常,您为ARGB图像传递
width * 4
,为straight(不包含alpha信息的)灰度图像传递width
。特别注意这个值,它不只是作为参数有用,您还可以使用它来计算字节数组中任何像素的(x,y)偏移量,即(y * bytesPerRow + x)。 - CGColorSpaceRef colorspace - 你传递的颜色空间Quartz会使用它来创建位图上下文,典型的是设备RGB或设备灰色。
- CGBitmapInfo bitmapInfo - 此参数指定位图使用的Alpha通道的样式。作为经验法则,对彩色图像使用
kCGImageAlphaPremultipliedFirst
,对于灰度使用kCGImageAlphaNone
。如果你好奇这些,请参阅Quartz 2D编程指南,以获得更完整的选项列表。在iOS 7和更高版本中,确保将任何alpha设置转换为(CGBitmapInfo
)以避免编译器问题。
清单 3-6 Extracting Bytes
1 | NSData *BytesFromRGBImage(UIImage *sourceImage) |
Note
当响应速度是关键时,不要等待
UIImage
实例及其底层CGImage
表示解压缩。通过CGImageSource
加载您的CGImage
实例来启用解压缩图像的缓存。这个实现是ImageIO框架的一部分,使您能够指定一个选项来缓存解压缩数据(kCGImageSourceShouldCache
)。这会提升绘图性能,虽然是以更多的额外存储做为代价的。有关详细信息,请参见www.cocoanetics.com/2011/10/avoid-image-decompression-sickness。
本文翻译自《iOS Drawing Practical UIKit Solutions》作者:Erica Sadun,翻译:Cheng Dong。如果觉得本书不错请购买支持正版:亚马逊购买传送门,本书所有源代码可在GitHub上下载。译者虽然力求做到信,达,雅,但是由于时间仓促加之译者水平十分有限,文中难免会出现不正确,不准确,词不达意,难于理解的地方,还望各位批评指正,共同进步,谢谢。转载请注明出处。