从Leptonica的Pix结构创建UIImage

时间:2012-01-26 03:00:52

标签: objective-c ios uiimage pix

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

有人知道如何从Leptonica的UIImage结构中的原始数据创建Pix

/*-------------------------------------------------------------------------*
 *                              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;

谢谢!

4 个答案:

答案 0 :(得分:0)

首先,您可能需要查看:Convert Leptonica Pix Object to QPixmap ( or other image object )

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

通过查看Leptonica库,看起来常见的支持格式是GIF,JPEG,TIFF,BMP和PNG。 JPEG将是有损的,并且GIF和PNG将导致CPU的额外工作(当我们从Pix转换为UIImage时将存在额外的编码/解码周期)。出于这些原因,我在下面的示例中选择了TIFF。如果它不起作用,我会选择PNG。

计划如下:

  • 1)从Pix转换为字节缓冲区
  • 2)取字节缓冲区并将其存储到NSData
  • 3)将该数据传递给NSImage

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

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

这样的事情(警告:未经测试的代码):

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;
}

答案 1 :(得分:0)

写出中间文件格式。读回来,是一种简单但效率低下的方法,用于从Pix内存数据结构转换为UIImage数据结构(或内存中图像的许多容器中的任何其他容器)。

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

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

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

struct pix的规范在leptonica src文件pix.h中给出。

答案 2 :(得分:0)

这是一个实现(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;
}

答案 3 :(得分:0)

在Tesseract-OCR-iOS仓​​库中有UIImage和Pix对象之间的转换实现。

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