从RGBA像素字节数据重构UIImage的问题

时间:2011-08-24 12:56:36

标签: uiimage pixel alpha rgba

我需要从单个灰度图像(红橙黄等)

创建12个彩色图像

源图像实际上是PNG,RGBA:

enter image description here

我正在使用我找到的库(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 - 整个库只是带有标题的文件)我看不出问题出在哪里。

这是渲染输出:

enter image description here

正如你所看到的,C在F之前的G之前被渲染,因此它被矩形夹在两边。

2 个答案:

答案 0 :(得分:1)

alpha透明度问题已在最新的github push上修复。 https://github.com/PaulSolt/UIImage-Conversion/blob/master/ImageHelper.m

修复是使用以下代码,并在函数的bitmapInfo中对kCGImageAlphaPremultipliedLast进行逻辑OR运算。除了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);

答案 1 :(得分:0)

我正在尝试使用该库,但在复制图像而不是正确的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];