从 RGBA 像素字节数据重建 UIImage 时出现问题

2024-03-10

我需要从单个灰度图像(红色、橙色、黄色等)创建 12 个彩色图像

源图像实际上是PNG、RGBA:

我正在使用我找到的一个库(https://github.com/PaulSolt/UIImage-Conversion/ 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 https://github.com/PaulSolt/UIImage-Conversion/blob/master/ImageHelper.m-- 整个库只是这个文件及其标头)我看不出问题可能出在哪里。

这是渲染输出:

正如您所看到的,C 在 G 之前渲染,在 F 之前渲染,因此它的两侧都被矩形剪掉了。


Alpha 透明度问题已在最新的 github 推送中得到修复。https://github.com/PaulSolt/UIImage-Conversion/blob/master/ImageHelper.m 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);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 RGBA 像素字节数据重建 UIImage 时出现问题 的相关文章

  • 如何使 MapView 对象透明(alpha)?

    All 我需要在 MapView 对象上显示信息 那里没有问题 问题是 有时 MapView 对象显示的地图详细信息在视觉上与我的叠加数据相竞争 因此 我想做的是提供一种通过使用 alpha 通道在视觉上 缩小 MapView 对象的方法
  • JavaScript 生成 dataURL 格式的透明 1X1 像素

    我想知道一种在 JavaScript 中生成单个像素并将其转换为 base64 的方法 理想的函数是 function createPixel hexColor opacity Calculate return base64DataURL
  • SwiftUI:UIImage(QRCode)在调用函数后未加载[重复]

    这个问题在这里已经有答案了 我花了很多时间试图诊断这个问题 但我完全陷入困境 也许我错过了一些非常明显的东西 已经尝试过 将返回的图像保存到磁盘以查看它是否正在生成 正确地 它是 添加彩色背景会呈现一个正方形 因此正在加载某些内容 将图像标
  • 使UIImage符合NSCopying协议

    问题很简单 我需要一个符合 NSCopying 协议的 UIImage 但我完全不知道从哪里开始实现这一点 你有什么指示可以帮助我吗 提前致谢 id copyWithZone NSZone zone return UIImage alloc
  • 如何创建和实现像素跟踪代码

    好吧 这是我一直在寻找的目标 众所周知 大多数广告和分析公司使用所谓的 像素 代码来跟踪网站浏览 交易 转化等 我确实知道它是如何工作的 问题是如何实现它 跟踪代码由几个部分组成 跟踪代码本身 这是用户在其网页上插入的代码部分 该代码的主要
  • 以 cm 为单位调整图像大小 C#

    我有一个要求 要求提供 10 X 6 88 厘米的图像 我知道我不能简单地将厘米转换为像素 因为一个像素大小取决于用户显示分辨率 我想知道是否有办法调整图像大小以达到该尺寸 以厘米为单位 我还需要保留图像扩展名 例如 无法将其转换为 pdf
  • 如何在 WPF 中拉伸位图而不平滑像素

    我正在开发用 WPF 编写的 SEM 图像处理应用程序 我有一个源自 Canvas 的图像显示控件 它使用 DrawingVisuals 显示图像和叠加层 每个 层 一个 它还使用应用于 DrawingVisuals 的缩放和平移变换来实现
  • 将两个 UIImage 合并为 1 个以保存到库

    我想知道如何将 2 个 uiimage 合并为 1 个 我想将最终产品保存到图书馆 为了保存图像 我使用了 UI 按钮 这是我如何保存 UIImageview image 的片段 IBAction getPhoto id sender UI
  • 将 CIELab 转换为 CIELCh(ab) 未产生正确结果

    我很难用计算器手动将 CIELab 转换为 CIELCh 根据http www easyrgb com en math php http www easyrgb com en math php 以下是通过从弧度到度数从 CIELab 到 C
  • UIView drawHierarchy 创建黑色图像

    我正在尝试转换我的习惯UIView into UIImage使用核心图形 但有时它会变成黑色 我的整个UIImage看起来像黑色图像 我注意到如果我的身高UIView无论生成的宽度是多少 都超过 4096UIImage会变黑 注1 我的习惯
  • 如何以编程方式创建 UIImage 视图 - Swift

    我正在尝试以编程方式创建 UIImage 视图 我有一个新视图 我尝试这样做 let imageName yourImage png yourview backgroundColor UIColor colorWithPatternImag
  • CIImage 的 PNG/JPEG 表示形式始终返回 nil

    我目前正在制作一个照片编辑应用程序 当用户选择照片时 会使用以下代码自动将其转换为黑白 func blackWhiteImage image UIImage gt Data print Starting black white let or
  • 绘制别名、像素完美的 1px 样条线(特别是 Catmull-Rom)

    简要背景 我正在开发一个基于 Web 的绘图应用程序 需要绘制穿过其控制点的 1px 粗样条线 我正在努力解决的问题是我需要绘制 p1 和 p2 之间的每个像素 就像我使用 1px 铅笔工具一样 因此 没有抗锯齿功能 一次一个像素 这需要手
  • 使用 ffmpeg 将带有 Alpha 的 .mov 转换为带有 alpha 的 .webm 时出现错误“使用 auto_alt_ref 进行透明度编码不起作用”

    我正在尝试将具有 alpha 透明度的 mov 文件转换为 webm 文件 并一直在关注此线程以寻求帮助 使用 ffmpeg 将带 Alpha 的 mov 转换为带 Alpha 的 VP9 Webm https stackoverflow
  • 如何检测位图中的红色像素

    android中的getPixels 是上下左右读取像素 还是左右上下读取像素 基本上是按行或列读取 如果我想知道图片中的红色值较高的位置 我可以这样做吗 我假设它是按列读取的 Bitmap thumbnail Bitmap data ge
  • 将 CMSampleBuffer 转换为 UIImage

    这是一个将 CMSampleBuffer 转换为 UIImage 的函数 来自 Apple 文档的代码 func imageFromSampleBuffer sampleBuffer CMSampleBuffer gt UIImage Ge
  • RGBA格式HEX转换成RGB格式HEX? PHP

    我想在 RGBA 格式的十六进制颜色之间来回转换 例如0xFF0000FF 和 RGB 格式的十六进制颜色 例如0xFF0000 在 PHP 中 我怎样才能做到这一点 这两个函数将满足您的需要 function rgbaToRgb rgba
  • 检查 UIImage 是否有 alpha(透明)颜色时出现问题

    我正在检查图像是否有透明区域 alpha 受到打击 我必须改变颜色UIImage 我已经实现了以下方法来检查图像是否有alpha or not BOOL checkAlpha UIImage image for int x 0 x lt i
  • 旋转UIImage自定义角度

    我想以自定义角度旋转 UIImage 不是 UIImageView 我跟着这个帖子 https stackoverflow com questions 917713 uiimage rotation custom degrees但这对我不起
  • 平滑地将渐变应用于 UIImage

    我正在尝试使用 CoreGraphic 将渐变应用于 UIImage 然而 我得到的结果不是很好 我想在图像底部创建一个黑色到透明的渐变 以便为我放置一些文本创建对比度 然而 我能够实现的渐变与图像不能很好地融合 你可以清楚地看到中心的分离

随机推荐