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
何が悪いのか分かりますか?何か提案があればよろしくお願いします。