2009-04-16 4 views
2

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

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

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

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

Сегодня я задал пару вопросов, пытаясь понять это, но я просто подумал, давайте зададим вопрос, на который я действительно хочу ответить, и посмотрим, сможет ли кто-нибудь ответить на него.

У нас есть способ сделать это. Я должен упустить что-то немое. Что это?

ответ

1

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

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

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

Edit: Technical Q&A QA1509 Getting the pixel data from a CGImage object состояния:

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

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

+0

Это не помогает, потому что оно фактически не отображает изображения вообще. Таким образом, это не касается объектов CGImage. У меня уже есть код для чтения файлов группы 4 и их записи, предполагая, что у меня есть данные 1Bit. Мне нужно получить данные из CGImage таким образом, что я могу написать TIFF ... –

+0

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

+0

Ну, я действительно не могу получить двоичные данные из CGImage ... Я могу СОХРАНИТЬ документ в другом формате, но я бы предпочел не сохранять, а затем конвертировать ... –

1

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

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

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

+0

Это цель C, а не C++, я думаю. –

+0

Да - но почему это проблема? Objective-C является строгим надмножеством C, и, как вы можете видеть, вы можете легко переносить Objective-C-код в функцию C, а затем использовать его из C-кода. Факт, что Apple делает это для некоторых своих C API-интерфейсов - оберните функции C вокруг реализации Objective-C. –

+0

Автореализация объекта вызовет спам Консоли и утечку памяти (в этом случае довольно значительная), когда нет пула авторезистов. –

2

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

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 
+0

Является ли это Objective C или C++? Это похоже на странную комбинацию. В C++ я не думаю, что сжатие 4 работает. Он дает несжатый ... –

+0

Язык, на который вы пишете, не повлияет на поведение API. Это Objective-C. Я переписал его как чистый C для вас. – user96459

+0

Хорошо, отредактирован до чистого C. Он должен скомпилироваться как C++. CGImageDestination покрывает libtiff и передает сжатие без помех. Я обнаружил, что мне нужно явно передать глубину == 1 и изображение в оттенках серого, чтобы заставить его работать. Если вы google для libtiff и «CCITT Group 4», вы увидите, что некоторые люди задают вопросы об этом. – user96459