从 Leptonica 的 Pix 结构创建 UIImage

发布于 2024-12-28 19:13:54 字数 1455 浏览 2 评论 0原文

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

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

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

谢谢!

I want to use Leptonica library in my iOS app to process images.

Does anybody knows how can I create UIImage from the raw data in Leptonica's Pix structure:

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

?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

陌上青苔 2025-01-04 19:13:55

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

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

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

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

src文件pix.h中给出了struct Pix的规范。

Writing out to an intermediary file format. and reading back in, is a simple but inefficient method for converting from a Pix in-memory data structure to a UIImage data structure (or any other of the many containers for images in memory).

It is particularly inefficient computationally if the intermediate file representation is compressed (e.g., png), because the image data has to undergo compression before writing it out and decompression to an uncompressed raster after reading it back in.

The efficient method to convert a struct Pix to a struct X is to fill in the metadata fields in X (the image size, depth, resolution, text, etc), generate a colormap for struct X if the image is colormapped, and convert the image raster data from the Pix convention to the X convention. This last is the only tricky part, because you need to consider the following for each of the two in-memory raster representations:

(1) Padding for raster lines (Pix is padded to 4 bytes)
(2) Storage of multi-component pixels (Pix stores each component sequentially within each pixel)
(3) Size of 3-component pixels, such as rgb (Pix uses 4 bytes: rgba)
(4) Byte order for multi-byte pixels (Pix uses macros that determine the rgba byte order)
(5) Pixel order: for Pix, from left to right in the image, they are stored in order from the MSB to the LSB in each 32 bit word

A specification for struct Pix is given in the leptonica src file pix.h.

画离情绘悲伤 2025-01-04 19:13:55

这里有一个实现(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 图像(例如阈值)

- (UIImage *)imageFrom1bppPix:(Pix *)pix
{
    Pix *pix32 = pixUnpackBinary(pix, 32, 0);

    UIImage *image = [self imageFromPix:pix32];

    pixDestroy(&pix32);

    return image;
}

Here an implementation (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;
}

If you want to convert 1 bpp image(thresholded for exapmle)

- (UIImage *)imageFrom1bppPix:(Pix *)pix
{
    Pix *pix32 = pixUnpackBinary(pix, 32, 0);

    UIImage *image = [self imageFromPix:pix32];

    pixDestroy(&pix32);

    return image;
}
吖咩 2025-01-04 19:13:55

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

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

  • <一href="https://github.com/gali8/Tesseract-OCR-iOS/blob/c7ad56d6544839b2f84c7ffde8fa42efe2312405/TesseractOCR/G8Tesseract.mm#L861" rel="nofollow noreferrer"><代码>- (UIImage *)imageFromPix:(Pix *)pix
  • <代码>-(像素*)pixForImage:(UIImage *)图像

There's an implementation for conversion between UIImage and Pix objects in the Tesseract-OCR-iOS repo.

See the following methods in G8Tesseract.m:

雨落□心尘 2025-01-04 19:13:54

首先,您可能需要查看:Convert Leptonica Pix对象到QPixmap(或其他图像对象)

我们想要的是找到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;
}

First, you might want to check out: Convert Leptonica Pix Object to QPixmap ( or other image object )

What we want is to find common formats that both Pix and UIImage support, convert from Pix to that common format, and then convert from the common format to UIImage.

From looking at the Leptonica library, it looks like the common supported formats are GIF, JPEG, TIFF, BMP, and PNG. JPEG will be lossy, and GIF and PNG will both result in additional work by the CPU (there will be an additional encode/decode cycle when we convert from Pix to UIImage). For these reasons, I chose TIFF in the example below. If it doesn't work, I would go with PNG.

The plan is as follows:

  • 1) Convert from Pix to a byte buffer
  • 2) Take the byte buffer and store it into an NSData
  • 3) Pass that data into NSImage

It looks like the pixWriteMem() function is what we need for #1 (provided that support for it was compiled into the library).

From looking at the example code included with the library, it looks like we are responsible for freeing the output of pixWriteMem() - hence, we will pass YES into NSData's freeWhenDone: argument.

Something like this (warning: untested code):

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文