【问题标题】:iOS - UIImage with alpha has washed-out colors in MKOverlayRenderer on iOS13iOS - 带有 alpha 的 UIImage 在 iOS13 上的 MKOverlayRenderer 中褪色
【发布时间】:2020-02-04 00:31:26
【问题描述】:

我从 PNG 加载了带有 RGBA UIImageMKOverlayRenderer。图片透明部分的 alpha 值为 0,半透明部分的 alpha 值为 160。

但是,当我在地图上渲染图像时,颜色有点褪色,整个图像看起来像是在雾后面。此问题是在更新到 iOS 13 后发生的,旧版本可以正常工作。

我通过[UIImage imageNamed:@"some_img"];加载图片

我扩展了MKOverlayRenderer,并覆盖了drawMapRect 方法:

- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context { 
    UIImage * img = [UIImage imageNamed:@"some_img"];

    MKMapRect theMapRect = self.overlay.boundingMapRect;
    CGRect theRect = [self rectForMapRect:theMapRect];

    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextTranslateCTM(context, 0.0, -theRect.size.height);
    CGContextDrawImage(context, theRect, img.CGImage);
}

我尝试通过创建副本并使用以下公式手动处理 RGBA 像素,从图像中手动删除预乘 alpha(将 alpha 设置为 255 而不是 160):

CGImageRef sourceImage = img.CGImage;

CFDataRef theData;
theData = CGDataProviderCopyData(CGImageGetDataProvider(sourceImage));

UInt8 *pixelData = (UInt8 *) CFDataGetBytePtr(theData);

int dataLength = CFDataGetLength(theData);

for (int i = 0; i < dataLength; i += 4){
   uint8_t aHalf = pixelData[i + 3] / 2;
   pixelData[i + 0] = (pixelData[i + 0] * 255 + aHalf) / pixelData[i + 3];
   pixelData[i + 1] = (pixelData[i + 1] * 255 + aHalf) / pixelData[i + 3];
   pixelData[i + 2] = (pixelData[i + 2] * 255 + aHalf) / pixelData[i + 3];        
   pixelData[i + 3] = (pixelData[i + 3] == 0) ? 0 : 255;
}

CGContextRef context;
context = CGBitmapContextCreate(pixelData,
                                CGImageGetWidth(sourceImage),
                                CGImageGetHeight(sourceImage),
                                8,
                                CGImageGetBytesPerRow(sourceImage),
                                CGImageGetColorSpace(sourceImage),
                                kCGImageAlphaPremultipliedLast);

UIImage *newImage = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];

然后我在drawMapRect中设置CGContextSetAlpha(context, 0.6);

这部分解决了问题,但在较旧的 iOS 版本上,图像的透明度不如 iOS 13,而且整个过程需要时间。

【问题讨论】:

    标签: objective-c uiimage mkmapview alpha


    【解决方案1】:

    遇到了同样的问题:

    Apple 的回应是,这是由于渲染器中 CGContext 的颜色空间发生了变化。在 iOS 12 中使用了 RGB 颜色空间,但 iOS 13 现在使用的是线性 sRGB 颜色空间。

    我能够将我的源图像转换为使用带有 ImageMagick 的线性 sRGB,并且它们现在在呈现透明时显示正确的阴影。我不确定您是否拥有源图像,并且可以转换它们,但如果可以的话,应该可以解决您的问题。

    【讨论】:

    • sRGB 是非线性的。所以我不确定Linear sRGB是什么意思。您是否参考了 Apple 所说的内容?
    • @fmw42 以下是来自 Apple 开发人员技术支持的引述:“传递给叠加渲染器的 CGContext 上的颜色空间已经改变——它是 iOS 12 上设备的 RGB 颜色空间,但在 iOS 13 上,它现在使用线性 sRGB 颜色空间。对您来说最简单的事情是创建使用线性 sRGB 颜色空间的更新地图图像,并将该图像加载到 iOS 13 上,但为 iOS 12 保留现有图像。我承认我对此的了解非常有限,看来苹果工程师可能不小心加了一个“s”。
    • 我不明白什么是线性 sRGB? sRGB本质上是非线性的。抱歉,我想我无法提供更多帮助。
    猜你喜欢
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-30
    • 1970-01-01
    相关资源
    最近更新 更多