从 RGBA 像素字节数据重建 UIImage 时出现问题
我需要从单个灰度图像(红色、橙色、黄色等)创建 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 之前渲染,因此它的两侧都被矩形剪掉了。
I need to create 12 coloured images from a single greyscale image ( red orange yellow etc )
Source image is actually a PNG, RGBA:
I'm using a library I found ( https://github.com/PaulSolt/UIImage-Conversion/ ) to break the UIImage into a RGBA byte array which I then process pixel by pixel, and use the same library to reconstitute a new UIImage.
This is my code:
- (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;
}
Problem is that I'm not getting the alpha channel back -- it is setting it to opaque everywhere.
If I simply pass the source image back on the first line, it renders correctly, so the problem is not with the source image.
If I inspect the alpha component of the first pixel, I find it is 0 (ie transparent) at all points in the process, as it should be. I even put in an extra test as you can see -- once I have my final UIImage I again break it into a RGBA bitmap and inspect the same element. It is still 0.
So it seems there must be some bug in the convertUIImageToBitmapRGBA8 method. it looks like there must be some setting on the resultant UIImage which is making it think it is opaque everywhere.
But looking through the source code for this method ( https://github.com/PaulSolt/UIImage-Conversion/blob/master/ImageHelper.m -- the whole library is just this file with its header ) I cannot see where the problem might be.
This is the rendering output:
As you can see, the C was rendered before the G before the F, hence it is clipped on both sides by the rectangles.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Alpha 透明度问题已在最新的 github 推送中得到修复。 https://github.com/PaulSolt/UIImage-Conversion/blob/master /ImageHelper.m
修复方法是使用以下代码与函数中 bitmapInfo 中的 kCGImageAlphaPremultipliedLast 进行逻辑或运算。除了 CGImageRef 之外,还使用了 bitmapInfo 来增加 CGContextRef。两个 bitmapInfo 参数的格式应相同。
代码摘录:
The alpha transparency problem has been fixed on the latest github push. https://github.com/PaulSolt/UIImage-Conversion/blob/master/ImageHelper.m
The fix was to use the following code with kCGImageAlphaPremultipliedLast logically ORed in the bitmapInfo in the function. The bitmapInfo was also used increasing the CGContextRef, in addition to the CGImageRef. The formats should be the same for both bitmapInfo parameters.
Code excerpt:
我正在尝试使用该库,但在复制图像而不是正确的 Alpha 通道中,我收到了混乱。 损坏的图像
代码:
I'm trying to use that library, but in copy image instead of correct alpha channel i receive a mess. broken image
Code: