конвертировать между NSImage и Leptonica Pix

Я работаю над программой Cocoa OS X для очистки отсканированных страниц и хотел бы использовать для этого библиотеку Leptonica. подъем тяжестей. Я нашел некоторую информацию в этом сообщении, этот и вот этот. Я определенно могу получить CGImage из NSImage и записать данные в изображение Leptonica Pix. Моя проблема заключается в том, что в 75% случаев мое изображение выходит искаженным с рисунком типа столба парикмахерской (каждый последующий ряд пикселей сверху вниз изображения смещается все дальше и дальше вправо). Хотя иногда картинка выходит нормально. Я предполагаю, что я делаю что-то неправильно при настройке данных изображения, но на самом деле это не моя сильная сторона, поэтому мне трудно понять проблему. Я создаю изображение Pix, используя следующий код:

CGImageRef myCGImage = [processedImage CGImageForProposedRect:NULL context:NULL hints:NULL];
CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(myCGImage));
const UInt8 *imageData = CFDataGetBytePtr(data);

Pix *myPix = (Pix *) malloc(sizeof(Pix));
myPix->w = (int)CGImageGetWidth (myCGImage);
myPix->h = (int)CGImageGetHeight (myCGImage);
myPix->d = (int)CGImageGetBitsPerPixel(myCGImage);
myPix->wpl =  ((CGImageGetWidth (myCGImage)*CGImageGetBitsPerPixel(myCGImage))+31)/32;
myPix->informat = IFF_TIFF;
myPix->data = (l_uint32 *) imageData;
myPix->colormap = NULL;

Структура пикселей определяется следующим образом:

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

person bbrownd    schedule 17.12.2012    source источник


Ответы (1)


«Шаблон типа столба парикмахерской» — классический признак неправильного количества байтов в строке пиксельных данных.

Вы должны основывать wpl на значении, возвращаемом CGImageGetBytesPerRow. Вероятно:

myPix->wpl = CGImageGetBytesPerRow(myCGImage) / 4;

Есть несколько причин, по которым количество байтов на строку изображения будет отличаться от вашего предположения, основанного на CGImageGetWidth(). Например, оно может быть округлено из соображений производительности, или изображение может быть фрагментом более широкого изображения.

person Kurt Revis    schedule 17.12.2012
comment
Это также может быть не 8-битный RGBA на компонент. Он может использовать компоненты с плавающей запятой, 16-битные целочисленные компоненты или находиться в другом цветовом пространстве или в некоторой их комбинации. Некоторые комбинации могут даже дать вам четырехбайтовые пиксели, которые не являются RGBA (например, 8-битный CMYK и оттенки серого с плавающей запятой), поэтому вы не получите шаблон шеста парикмахера, но ваш результат будет выглядеть несколько странно. - person Peter Hosey; 18.12.2012