从CGImage生成CCITT压缩的TIFF

时间:2009-04-16 22:14:05

标签: c++ macos core-graphics cgimage

我有一个CGImage(核心图形,C / C ++)。这是灰度。好吧,原来它是B / W,但CGImage可能是RGB。那应该没关系。我想创建一个CCITT-Group 4 TIFF。

我可以通过使用正确的字典创建目的地并添加图像来创建LZW TIFF(灰度或彩色)。没问题。

但是,似乎没有等效的kCGImagePropertyTIFFCompression值来表示CCITT-4。应该是4,但这会产生未压缩的。

我有一个手动CCITT压缩例程,所以如果我能得到二进制(每像素1位)数据,我就设置了。但我似乎无法从CGImage中获取1个BPP数据。我有代码,应该将CGImage放入CGBitmapContext,然后给我数据,但它似乎给我全黑。

今天我已经问了几个问题试图解决这个问题,但我想,让我们问一下我真正想要回答的问题,看看是否有人可以回答。

有一种方法可以做到这一点。我必须失去一些愚蠢的东西。它是什么?

3 个答案:

答案 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

答案 1 :(得分:1)

ImageMagick可以转换为几乎任何图像格式。由于它是开源的,您可以去阅读source code以找到问题的答案。

如果使用C ++,您甚至可以在应用中使用ImageMagick API

修改
如果你能以任何格式从CGImage获取数据(并且它听起来像你可以),你可以使用ImageMagick将它从你从CGImage获得的格式转换为ImageMagick支持的任何其他格式(你想要的TIFF格式)。

修改 Technical Q&A QA1509 Getting the pixel data from a CGImage object州:

  

在Mac OS X 10.5或更高版本中,添加了一个新调用,允许您从CGImage对象获取实际像素数据。此调用CGDataProviderCopyData返回包含相关图像中像素数据的CFData对象。

获得像素数据后,您可以使用ImageMagick进行转换。

答案 2 :(得分:1)

NSBitmapImageRep声称能够生成CCITT FAX Group 4压缩TIFF。所以这样的事情可能会成功(未经测试):

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

此函数应返回您寻找的数据。