从Leptonica的Pix结构创buildUIImage

我想在我的iOS应用程序中使用Leptonica库来处理图像。

有谁知道如何从Leptonica的Pix结构中的原始数据创buildUIImage

 /*-------------------------------------------------------------------------* * Basic Pix * *-------------------------------------------------------------------------*/ struct Pix { l_uint32 w; /* width in pixels */ l_uint32 h; /* height in pixels */ l_uint32 d; /* depth in bits */ l_uint32 wpl; /* 32-bit words/line */ l_uint32 refcount; /* reference count (1 if no clones) */ l_int32 xres; /* image res (ppi) in x direction */ /* (use 0 if unknown) */ l_int32 yres; /* image res (ppi) in y direction */ /* (use 0 if unknown) */ l_int32 informat; /* input file format, IFF_* */ char *text; /* text string associated with pix */ struct PixColormap *colormap; /* colormap (may be null) */ l_uint32 *data; /* the image data */ }; typedef struct Pix PIX; 

谢谢!

首先,您可能想要查看: 将Leptonica Pix对象转换为QPixmap(或其他图像对象)

我们想要的是findPix和UIImage支持的常见格式,从Pix转换为通用格式,然后从通用格式转换为UIImage。

从查看Leptonica库,看起来像常见的支持格式是GIF,JPEG,TIFF,BMP和PNG。 JPEG将是有损的,GIF和PNG都将导致CPU额外的工作(当我们将Pix转换为UIImage时,将会有额外的编码/解码周期)。 由于这些原因,我在下面的例子中select了TIFF。 如果不行的话,我会用PNG去的。

计划如下:

  • 1)从Pix转换为字节缓冲区
  • 2)把字节缓冲区存储到一个NSData中
  • 3)将该数据传递给NSImage

它看起来像pixWriteMem()函数是我们需要的#1(只要支持它被编译到库中)。

通过查看库中包含的示例代码,看起来我们负责释放pixWriteMem()的输出 – 因此,我们将传入YES到NSData的freeWhenDone:参数中。

像这样(警告:未经testing的代码):

 UIImage *GetImageFromPix(Pix *thePix) { UIImage *result = nil; l_uint8 *bytes = NULL; size_t size = 0; if (0 == pixWriteMem(&bytes, &size, thePix, IFF_TIFF)) { NSData *data = [[NSData alloc] initWithBytesNoCopy:bytes length:(NSUInteger)size freeWhenDone:YES]; result = [UIImage imageWithData:data]; [data release]; } return result; } 

写出中间文件格式。 并重新读入,是一种简单而低效的方法,用于将Pix内存中的数据结构转换为UIImage数据结构(或内存中图像的任何其他容器)。

如果中间文件表示是压缩的(例如,png),则计算效率特别低,因为图像数据在写出之前必须经历压缩,并且在读入之后解压缩到未压缩的光栅。

结构Pix转换为结构X的有效方法是填充X(图像大小,深度,分辨率,文本等)中的元数据字段,如果图像是彩色映射的,则为结构X生成色彩映射,将Pix公约中的栅格数据映射到X公约。 最后一个是唯一棘手的部分,因为您需要考虑以下两个内存中的光栅表示:

(1)栅格线的填充(Pix填充到4个字节)
(2)多分量像素的存储(Pix在每个像素内依次存储每个分量)
(3)3分量像素的大小,如rgb(Pix使用4个字节:rgba)
(4)多字节像素的字节顺序(Pix使用确定rgba字节顺序的macros)
(5)像素顺序:对于图像中从左到右的Pix,它们按每个32位字从MSB到LSB的顺序存储

结构Pix的规范在leptonica src文件pix.h中给出。

这里有一个实现(32 bpp – > UIImage)

 - (UIImage *)imageFromPix:(Pix *)pix { l_uint32 width = pixGetWidth(pix); l_uint32 height = pixGetHeight(pix); l_uint32 bitsPerPixel = pixGetDepth(pix); l_uint32 bytesPerRow = pixGetWpl(pix) * 4; l_uint32 bitsPerComponent = 8; if (pixSetSpp(pix, 4) == 0) { bitsPerComponent = bitsPerPixel / pixGetSpp(pix); } l_uint32 *pixData = pixGetData(pix); CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixData, bytesPerRow * height, NULL); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGImage *cgImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpace, kCGBitmapByteOrderDefault, provider, NULL, NO, kCGRenderingIntentDefault); CGDataProviderRelease(provider); CGColorSpaceRelease(colorSpace); UIImage *image = [UIImage imageWithCGImage:cgImage]; return image; } 

如果你想转换1 bpp图像(阈值为exapmle)

 - (UIImage *)imageFrom1bppPix:(Pix *)pix { Pix *pix32 = pixUnpackBinary(pix, 32, 0); UIImage *image = [self imageFromPix:pix32]; pixDestroy(&pix32); return image; } 

在Tesseract-OCR-iOS repo中有一个UIImage和Pix对象之间的转换实现。

请参阅G8Tesseract.m中的以下方法:

  • - (UIImage *)imageFromPix:(Pix *)pix
  • - (Pix *)pixForImage:(UIImage *)image