我需要将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;
}
我检查了那个方法,它看起来像corectly ...只是为了测试目的我修改了我的imageRepWithData:
方法来创建8bpp的imageRef并显示转换后的图像...这是我的更改:< / p>
// 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
你知道什么是错的吗?我会感谢任何建议。