Создание сжатого TIFF CCITT из CGImage - PullRequest
2 голосов
/ 17 апреля 2009

У меня есть CGImage (базовая графика, C / C ++). Это в оттенках серого. Ну, изначально это был ч / б, но CGImage может быть RGB. Это не должно иметь значения. Я хочу создать CCITT-Group 4 TIFF.

Я могу создать TIFF LZW (в оттенках серого или в цвете), создав пункт назначения с правильным словарем и добавив изображение. Нет проблем.

Однако, похоже, не существует эквивалентного значения kCGImagePropertyTIFFCompression для представления CCITT-4. Это должно быть 4, но это производит несжатый.

У меня есть процедура сжатия CCITT вручную, поэтому, если я могу получить двоичные (1 бит на пиксель) данные, я настроен. Но я не могу получить данные 1 BPP из CGImage. У меня есть код, который должен поместить CGImage в CGBitmapContext, а затем дать мне данные, но, похоже, он дает мне все черное.

Я задал пару вопросов сегодня, пытаясь понять, но я просто решил, давайте зададим вопрос, на который ДЕЙСТВИТЕЛЬНО хочу получить ответ, и посмотрим, сможет ли кто-нибудь ответить на него.

Должен быть способ сделать это. Я должен пропустить что-то глупое. Что это?

Ответы [ 3 ]

2 голосов
/ 27 апреля 2009

Похоже, что это работает и дает не совсем черный вывод. Может быть способ сделать это, который сначала не включает ручное преобразование в оттенки серого, но по крайней мере это работает!

static void WriteCCITTTiffWithCGImage_URL_(CGImageRef im, CFURLRef url) {
    // produce grayscale image
    CGImageRef grayscaleImage;
    {
        CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
        CGContextRef bitmapCtx = CGBitmapContextCreate(NULL, CGImageGetWidth(im), CGImageGetHeight(im), 8, 0, colorSpace, kCGImageAlphaNone);
        CGContextDrawImage(bitmapCtx, CGRectMake(0,0,CGImageGetWidth(im), CGImageGetHeight(im)), im);
        grayscaleImage = CGBitmapContextCreateImage(bitmapCtx);
        CFRelease(bitmapCtx);
        CFRelease(colorSpace);
    }

    // generate options for ImageIO. Man this sucks in C.
    CFMutableDictionaryRef options = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    {
        {
            CFMutableDictionaryRef tiffOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
            int fourInt = 4;
            CFNumberRef fourNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &fourInt);
            CFDictionarySetValue(tiffOptions, kCGImagePropertyTIFFCompression, fourNumber);
            CFRelease(fourNumber);

            CFDictionarySetValue(options, kCGImagePropertyTIFFDictionary, tiffOptions);

            CFRelease(tiffOptions);                
        }

        {
            int oneInt = 1;
            CFNumberRef oneNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &oneInt);

            CFDictionarySetValue(options, kCGImagePropertyDepth, oneNumber);

            CFRelease(oneNumber);
        }
    }

    // write file
    CGImageDestinationRef idst = CGImageDestinationCreateWithURL(url, kUTTypeTIFF, 1, NULL);
    CGImageDestinationAddImage(idst, grayscaleImage, options);
    CGImageDestinationFinalize(idst);

    // clean up
    CFRelease(idst);
    CFRelease(options);
    CFRelease(grayscaleImage);
}


Nepheli:tmp ken$ tiffutil -info /tmp/output.tiff 
Directory at 0x1200
  Image Width: 842 Image Length: 562
  Bits/Sample: 1
  Sample Format: unsigned integer
  Compression Scheme: CCITT Group 4 facsimile encoding
  Photometric Interpretation: "min-is-black"
  Orientation: row 0 top, col 0 lhs
  Samples/Pixel: 1
  Number of Strips: 1
  Planar Configuration: Not planar
1 голос
/ 27 апреля 2009

NSBitmapImageRep утверждает, что может генерировать сжатый TIFF CCITT FAX Group 4. Таким образом, что-то вроде этого может помочь (не проверено):

CFDataRef tiffFaxG4DataForCGImage(CGImageRef cgImage) {
  NSBitmapImageRep *imageRep =
      [[[NSBitmapImageRep alloc] initWithCGImage:cgImage] autorelease];
  NSData *tiffData =
      [imageRep TIFFRepresentationUsingCompression:NSTIFFCompressionCCITTFAX4
                                            factor:0.0f];
  return (CFDataRef) tiffData;
}

Эта функция должна возвращать искомые данные.

1 голос
/ 17 апреля 2009

ImageMagick может конвертировать из практически в любой формат изображения. Поскольку это открытый исходный код, вы можете прочитать исходный код и найти ответ на свой вопрос.

Вы даже можете использовать ImageMagick API в своем приложении, если вы используете C ++.

Edit:
Если вы можете получить данные из CGImage в любом формате (и это звучит так, как вы), вы можете использовать ImageMagick для преобразования их из любого формата, который вы получаете из CGImage, в любой другой формат, поддерживаемый ImageMagick (желаемый формат TIFF).

Edit: Технические вопросы и ответы QA1509 Получение данных пикселей из объекта CGImage состояния:

В Mac OS X 10.5 или более поздней версии был добавлен новый вызов, который позволяет вам получать фактические данные пикселей из объекта CGImage. Этот вызов CGDataProviderCopyData возвращает объект CFData, который содержит данные пикселей из рассматриваемого изображения.

Получив данные о пикселях, вы можете использовать ImageMagick для их преобразования.

...