在目标c中将位图从16bpp转换为8bpp

时间:2013-06-30 15:07:14

标签: objective-c bitmap pixel

我需要将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

你知道什么是错的吗?我会感谢任何建议。

0 个答案:

没有答案