我有一个32位NSBitmapImageRep
,其alpha通道基本上是1位值(像素打开或关闭)。
我想将此位图保存为具有透明度的8位PNG文件。如果我使用-representationUsingType:properties:
的{{1}}方法并传入NSBitmapImageRep
,则会创建一个32位的PNG,这不是我想要的。
我知道可以读取8位PNG,它们在预览中打开没有问题,但是是否可以使用任何内置的Mac OS X API编写这种类型的PNG文件?如果有必要,我很高兴下载到Core Image甚至QuickTime。对NSPNGFileType
文档的粗略检查没有发现任何明显的内容。
修改
我已经开始对这个问题表示赏心悦目,如果有人可以提供一个32位CGImage
的工作源代码并写入一个透明度为1位的256色PNG,那就是你的了。
答案 0 :(得分:2)
pnglib
怎么样?它非常轻巧,易于使用。
答案 1 :(得分:1)
使用低级API的一个很好的参考是Programming With Quartz
以下部分代码基于该书中的示例。
注意:这是未经测试的代码,仅作为起点......
- (NSBitmapImageRep*)convertImageRep:(NSBitmapImageRep*)startingImage{
CGImageRef anImage = [startingImage CGImage];
CGContextRef bitmapContext;
CGRect ctxRect;
size_t bytesPerRow, width, height;
width = CGImageGetWidth(anImage);
height = CGImageGetHeight(anImage);
ctxRect = CGRectMake(0.0, 0.0, width, height);
bytesPerRow = (width * 4 + 63) & ~63;
bitmapData = calloc(bytesPerRow * height, 1);
bitmapContext = createRGBBitmapContext(width, height, TRUE);
CGContextDrawImage (bitmapContext, ctxRect, anImage);
//Now extract the image from the context
CGImageRef bitmapImage = nil;
bitmapImage = CGBitmapContextCreateImage(bitmapContext);
if(!bitmapImage){
fprintf(stderr, "Couldn't create the image!\n");
return nil;
}
NSBitmapImageRep *newImage = [[NSBitmapImageRep alloc] initWithCGImage:bitmapImage];
return newImage;
}
上下文创建功能:
CGContextRef createRGBBitmapContext(size_t width, size_t height, Boolean needsTransparentBitmap)
{
CGContextRef context;
size_t bytesPerRow;
unsigned char *rasterData;
//minimum bytes per row is 4 bytes per sample * number of samples
bytesPerRow = width*4;
//round up to nearest multiple of 16.
bytesPerRow = COMPUTE_BEST_BYTES_PER_ROW(bytesPerRow);
int bitsPerComponent = 2; // to get 256 colors (2xRGBA)
//use function 'calloc' so memory is initialized to 0.
rasterData = calloc(1, bytesPerRow * height);
if(rasterData == NULL){
fprintf(stderr, "Couldn't allocate the needed amount of memory!\n");
return NULL;
}
// uses the generic calibrated RGB color space.
context = CGBitmapContextCreate(rasterData, width, height, bitsPerComponent, bytesPerRow,
CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB),
(needsTransparentBitmap ? kCGImageAlphaPremultipliedFirst :
kCGImageAlphaNoneSkipFirst)
);
if(context == NULL){
free(rasterData);
fprintf(stderr, "Couldn't create the context!\n");
return NULL;
}
//Either clear the rect or paint with opaque white,
if(needsTransparentBitmap){
CGContextClearRect(context, CGRectMake(0, 0, width, height));
}else{
CGContextSaveGState(context);
CGContextSetFillColorWithColor(context, getRGBOpaqueWhiteColor());
CGContextFillRect(context, CGRectMake(0, 0, width, height));
CGContextRestoreGState(context);
}
return context;
}
用法是:
NSBitmapImageRep *startingImage; // assumed to be previously set.
NSBitmapImageRep *endingImageRep = [self convertImageRep:startingImage];
// Write out as data
NSData *outputData = [endingImageRep representationUsingType:NSPNGFileType properties:nil];
// somePath is set elsewhere
[outputData writeToFile:somePath atomically:YES];
答案 2 :(得分:1)
答案 3 :(得分:0)
要尝试的一件事是创建一个8位的NSBitmapImageRep,然后将数据复制到它。
这实际上需要做很多工作,因为你必须自己计算颜色索引表。
答案 4 :(得分:0)
CGImageDestination
是你的低级图像写作的人,但我不知道它是否支持这种特定的能力。