我需要将 16bpp 灰度位图数据转换为 8bpp。mac os x 不支持我的图像文件格式,因此我将 NSBitmapImageRep 子类化。我已经实现了这个方法imageRepWithData:
+ (id)imageRepWithData:(NSData *)data {
NSLog(@"imageRepWithData called");
if (data.length < 2) return nil;
NSString *magicNumberP5 = @"P5";
const unsigned char *mnP5 = (const unsigned char *)[magicNumberP5 UTF8String];
unsigned char headerBuffer[2];
[data getBytes:headerBuffer length:2];
if (memcmp(mnP5, headerBuffer, 2) != 0) {
NSLog(@"It is not supported pgm file format.");
return nil;
}
NSArray *pgmParameters = [self extractPgmHeader:data];
// width in pixels
NSInteger width = [[pgmParameters objectAtIndex:0] integerValue];
// height in pixels
NSInteger height = [[pgmParameters objectAtIndex:1] integerValue];
// imageData contains bytes of Bitmap only. Without header
NSData *imageData = [pgmParameters objectAtIndex:3];
// Number of bytes in bitmap (length)
NSUInteger imageLength = [imageData length];
// calculate number bytes per component
size_t bytesPerCompontent = imageLength / (width * height) * 8;
// calculate number of bytes per pixel
size_t bytesPerPixel = bytesPerCompontent;
// calculate number of bytes per row
size_t bytesPerRow = width * (imageLength / (width * height));
// tmp test
NSData *eightBitBitmapData = [RWTPGMRep convert16BppTo8BppFromBitmapData:imageData];
// end of tmp test
CGDataProviderRef provider =
CGDataProviderCreateWithCFData((CFDataRef)CFBridgingRetain(imageData));
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericGrayGamma2_2);
CGImageRef imageRef = CGImageCreate(width,
height,
bytesPerCompontent,
bytesPerPixel,
bytesPerRow,
colorSpace,
kCGImageAlphaNone,
provider,
NULL,
false,
kCGRenderingIntentDefault);
CGColorSpaceRelease(colorSpace);
CGDataProviderRelease(provider);
if (imageRef == NULL) {
NSLog(@"CGImageCreate() failed!");
}
RWTPGMRep *imageRep = [[RWTPGMRep alloc] initWithCGImage:imageRef];
if (imageRep == nil) {
NSLog(@"imageRep is NULL");
}
return imageRep;
}
所以我可以显示这个图像,其中像素由 2 个字节编码......
但我需要将此图像转换为 8bpp 为此我写了一个方法convert16BppTo8BppFromBitmapData:
+ (NSData *)convert16BppTo8BppFromBitmapData:(NSData *)sixteenBitBitmapData
{
// number of pixels
NSUInteger size = [sixteenBitBitmapData length] / sizeof(UInt16);
// allocate memory for 16bpp array
UInt16 *array16 = malloc(size * sizeof(UInt16));
UInt16 *array16Ptr = array16;
// get bytes to array16
[sixteenBitBitmapData getBytes:array16
length:(size * sizeof(UInt16))];
// allocate memory for 8bpp array (converted values of pixels)
UInt8 *array8 = malloc(size * sizeof(UInt8));
UInt8 *array8Ptr = array8;
// convert 16bpp values to 8bpp values
NSUInteger i = size;
while (i--) {
*array8Ptr++ = (UInt8)((*array16Ptr++) >> 8);
}
// pack an array8 into NSData object
NSData *eightBitBitmapData = [NSData dataWithBytes:array8
length:size];
return eightBitBitmapData;
}
我已经检查了该方法,它似乎可以正常工作...仅出于测试目的,我修改了我的imageRepWithData:
方法以使用 8bpp 创建 imageRef 并显示转换后的图像...这是我的更改:
// tmp test
NSData *eightBitBitmapData = [RWTPGMRep convert16BppTo8BppFromBitmapData:imageData];
size_t bytesPerCompontent8 = eightBitBitmapData.length / (width * height) * 8;
size_t bytesPerPixel8 = bytesPerCompontent8;
size_t bytesPerRow8 = (width * (eightBitBitmapData.length / (width * height)));
CGDataProviderRef provider =
CGDataProviderCreateWithCFData((CFDataRef)CFBridgingRetain(eightBitBitmapData));
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericGrayGamma2_2);
CGImageRef imageRef = CGImageCreate(width,
height,
bytesPerCompontent8,
bytesPerPixel8,
bytesPerRow8,
colorSpace,
kCGImageAlphaNone,
provider,
NULL,
false,
kCGRenderingIntentDefault);
// end of tmp test
但结果并不像我预期的那样......我显示的 16bpp 图像看起来像:http: //i40.tinypic.com/2isa9tx.png
我的图像转换为 8bb 位图看起来像:http: //i39.tinypic.com/as8c3.png
你知道出了什么问题吗?如果有任何建议,我将不胜感激。