从 RGBA 像素字节数据重构 UIImage 的问题
Posted
技术标签:
【中文标题】从 RGBA 像素字节数据重构 UIImage 的问题【英文标题】:Problem reconstituting UIImage from RGBA pixel byte data 【发布时间】:2011-08-24 12:56:36 【问题描述】:我需要从一张灰度图像(红橙黄等)创建 12 张彩色图像
源图片其实是PNG,RGBA:
我正在使用我找到的一个库 (https://github.com/PaulSolt/UIImage-Conversion/) 将 UIImage 分解为一个 RGBA 字节数组,然后我逐个像素地处理它,并使用同一个库来重构一个新的 UIImage。
这是我的代码:
- (UIImage*) cloneWithTint3: (CGColorRef) cgTint
enum R, G, B, A ;
// - - -
assert( CGColorGetNumberOfComponents( cgTint ) == 4 );
const float* tint = CGColorGetComponents( cgTint );
// - - -
int w = self.size.width;
int h = self.size.height;
int pixelCount = w * h;
uint8_t* data = [UIImage convertUIImageToBitmapRGBA8: self];
for( int i=0; i < pixelCount ; i++ )
int offset = i << 2; // same as 4 * i but faster
float in_r = data[ offset + R ];
float in_g = data[ offset + G ];
float in_b = data[ offset + B ];
// float in_a = data[ offset + A ];
if( i == 0 )
printf( "ALPHA %d ", data[ offset + A ] ); // corner pixel has alpha 0
float greyscale = 0.30 * in_r + 0.59 * in_g + 0.11 * in_b;
data[ offset + R ] = (uint8_t) ( greyscale * tint[ R ] );
data[ offset + G ] = (uint8_t) ( greyscale * tint[ G ] );
data[ offset + B ] = (uint8_t) ( greyscale * tint[ B ] );
UIImage* imageNew = [UIImage convertBitmapRGBA8ToUIImage: data
withWidth: w
withHeight: h ];
free( data );
// test corner pixel
uint8_t* test = [UIImage convertUIImageToBitmapRGBA8: self];
for( int i=0; i < 1 ; i++ )
int offset = i << 2;
// float in_r = test[ offset + R ];
// float in_g = test[ offset + G ];
// float in_b = test[ offset + B ];
// float in_a = data[ offset + A ];
printf( "ALPHA %d ", test[ offset + A ] ); // corner pixel still has alpha 0
free( test );
return imageNew;
问题是我没有恢复 alpha 通道——它在任何地方都将其设置为不透明。
如果我只是在第一行将源图像传回,它会正确渲染,所以问题不在于源图像。
如果我检查第一个像素的 alpha 分量,我发现它在过程中的所有点都为 0(即透明),这是应该的。如您所见,我什至进行了额外的测试——一旦我有了最终的 UIImage,我再次将其分解为 RGBA 位图并检查相同的元素。还是 0。
看来 convertUIImageToBitmapRGBA8 方法中一定有一些错误。看起来在生成的 UIImage 上必须有一些设置,这使它认为它在任何地方都是不透明的。
但是通过查看这个方法的源代码(https://github.com/PaulSolt/UIImage-Conversion/blob/master/ImageHelper.m——整个库就是这个带有头文件的文件)我看不出问题出在哪里。
这是渲染输出:
如您所见,C 在 G 之前在 F 之前渲染,因此它的两边都被矩形剪裁了。
【问题讨论】:
我在这里把这个问题简化为一个最小的测试用例:***.com/questions/7177685/… 【参考方案1】:alpha 透明度问题已在最新的 github 推送中得到修复。 https://github.com/PaulSolt/UIImage-Conversion/blob/master/ImageHelper.m
修复方法是在函数的 bitmapInfo 中使用以下代码与 kCGImageAlphaPremultipliedLast 进行逻辑或运算。除了 CGImageRef 之外,还使用 bitmapInfo 来增加 CGContextRef。两个 bitmapInfo 参数的格式应该相同。
+ (UIImage *) convertBitmapRGBA8ToUIImage:(unsigned char *) buffer
withWidth:(int) width
withHeight:(int) height;
代码摘录:
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef iref = CGImageCreate(width,
height,
bitsPerComponent,
bitsPerPixel,
bytesPerRow,
colorSpaceRef,
bitmapInfo,
provider, // data provider
NULL, // decode
YES, // should interpolate
renderingIntent);
uint32_t* pixels = (uint32_t*)malloc(bufferLength);
if(pixels == NULL)
NSLog(@"Error: Memory not allocated for bitmap");
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpaceRef);
CGImageRelease(iref);
return nil;
CGContextRef context = CGBitmapContextCreate(pixels,
width,
height,
bitsPerComponent,
bytesPerRow,
colorSpaceRef,
bitmapInfo);
【讨论】:
【参考方案2】:我正在尝试使用该库,但在复制图像而不是正确的 Alpha 通道时,我收到一团糟。 broken image
代码:
UIImage *c = [UIImage imageNamed:@"head_diamond_c.png"];
unsigned char * rawData = [ImageHelper convertUIImageToBitmapRGBA8: c];
UIImage *copy = [ImageHelper convertBitmapRGBA8ToUIImage: rawData withWidth:c.size.width withHeight:c.size.height];
free(rawData);
itemImageView setImage:copy];
【讨论】:
以上是关于从 RGBA 像素字节数据重构 UIImage 的问题的主要内容,如果未能解决你的问题,请参考以下文章