0

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

何が悪いのか分かりますか?何か提案があればよろしくお願いします。

4

0 に答える 0