与uiimageWriteTosavedPhotosalBum一起,将透明uiimage保存到图库中的不正确保存到照片库

发布于 2025-02-13 06:28:44 字数 2373 浏览 1 评论 0原文

我有一个函数 prapalpha() 可以修剪透明度定义的额外空间。

func cropAlpha() -> UIImage {
    let cgImage = self.cgImage!
    
    let width = cgImage.width
    let height = cgImage.height
    
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let bytesPerPixel:Int = 4
    let bytesPerRow = bytesPerPixel * width
    let bitsPerComponent = 8
    let bitmapInfo: UInt32 = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue

    guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo),
          let ptr = context.data?.assumingMemoryBound(to: UInt8.self)
    else { return self }

    context.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: width, height: height))
    
    var minX = width
    var minY = height
    var maxX: Int = 0
    var maxY: Int = 0
    
    for x in 1 ..< width {
        for y in 1 ..< height {
            let i = bytesPerRow * Int(y) + bytesPerPixel * Int(x)
            let a = CGFloat(ptr[i + 3]) / 255.0
            
            if a == 1 {
                if (x < minX) { minX = x }
                if (x > maxX) { maxX = x }
                if (y < minY) { minY = y }
                if (y > maxY) { maxY = y }
            }
        }
    }
    
    let rect = CGRect(x: CGFloat(minX),y: CGFloat(minY), width: CGFloat(maxX - minX), height: CGFloat(maxY-minY))
    
    let croppedImage = self.cgImage!.cropping(to: rect)!
    let ret = UIImage(cgImage: croppedImage)

    return ret
}

此功能返回的图像具有透明的元素,我将其放在ImageView:presenerimageview.image = imagepng中。它按照应有的效果。但是,当我尝试将UIImage保存到照片库时,透明的背景转弯 white

let image = maskedImage?.cropAlpha()
    
let imagePNGData = image!.pngData()
let imagePNG = UIImage(data: imagePNGData!)

UIImageWriteToSavedPhotosAlbum(imagePNG!, nil, nil, nil)

如果我不使用该函数,我会得到结果i want 太多浪费的空间。我不明白可能是什么原因。有什么想法吗?

I have a function cropAlpha() that trims the extra space defined by the transparency.

func cropAlpha() -> UIImage {
    let cgImage = self.cgImage!
    
    let width = cgImage.width
    let height = cgImage.height
    
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let bytesPerPixel:Int = 4
    let bytesPerRow = bytesPerPixel * width
    let bitsPerComponent = 8
    let bitmapInfo: UInt32 = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue

    guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo),
          let ptr = context.data?.assumingMemoryBound(to: UInt8.self)
    else { return self }

    context.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: width, height: height))
    
    var minX = width
    var minY = height
    var maxX: Int = 0
    var maxY: Int = 0
    
    for x in 1 ..< width {
        for y in 1 ..< height {
            let i = bytesPerRow * Int(y) + bytesPerPixel * Int(x)
            let a = CGFloat(ptr[i + 3]) / 255.0
            
            if a == 1 {
                if (x < minX) { minX = x }
                if (x > maxX) { maxX = x }
                if (y < minY) { minY = y }
                if (y > maxY) { maxY = y }
            }
        }
    }
    
    let rect = CGRect(x: CGFloat(minX),y: CGFloat(minY), width: CGFloat(maxX - minX), height: CGFloat(maxY-minY))
    
    let croppedImage = self.cgImage!.cropping(to: rect)!
    let ret = UIImage(cgImage: croppedImage)

    return ret
}

The image returned by this function has transparent elements and I put it in the ImageView: presenterImageView.image = imagePNG. It works as it should. But when I try to save UIImage to Photo Gallery, transparent background turns white.

let image = maskedImage?.cropAlpha()
    
let imagePNGData = image!.pngData()
let imagePNG = UIImage(data: imagePNGData!)

UIImageWriteToSavedPhotosAlbum(imagePNG!, nil, nil, nil)

If I don't use that function, I get the result I want, but the image has too much wasted space. I don't understand what could be the reason. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

那片花海 2025-02-20 06:28:44

问题是uiimageWriteTosavedPhotosalBum无法正确处理uiimage premultipliped alpha(或至少保存这样的图像的结果不是您所期望的)和您的裁剪方法的使用方法Premultiplelast格式。您还不能仅仅将CGIMAGEALPHAINFO更改为非企业格式,因为它不受支持(您会看到错误cgbitmapcontextcreate:如果尝试使用该错误,请尝试使用该格式。 )。但是,您可以做的是将裁剪的图像转换为ciimage,毫无疑问的alpha,然后转换回uiimage。为此,您的保存代码可能看起来像以下内容(但是,如果您打算在最终应用中使用它,我建议删除该代码中的武力):

let image = maskedImage?.cropAlpha()

let ciImage = CIImage(image: image!)!.unpremultiplyingAlpha()
let uiImage = UIImage(ciImage: ciImage)
    
let imagePNGData = uiImage.pngData()
let imagePNG = UIImage(data: imagePNGData!)

UIImageWriteToSavedPhotosAlbum(imagePNG!, nil, nil, nil)

The problem is that UIImageWriteToSavedPhotosAlbum does not handle properly saving a UIImage with premultiplied alpha (or at least the result of saving such image is not what you expect) and your cropping method uses premultipliedLast format. You also can't just simply change CGImageAlphaInfo to a non-premultiplied format because it is not supported there (you will see an error CGBitmapContextCreate: unsupported parameter combination if you try that). But what you can do is convert the cropped image to CIImage, unpremultiply alpha and convert back to UIImage. To do that your saving code could look like below (however I recommend removing force unwrapping from this code if you plan to use it in final app):

let image = maskedImage?.cropAlpha()

let ciImage = CIImage(image: image!)!.unpremultiplyingAlpha()
let uiImage = UIImage(ciImage: ciImage)
    
let imagePNGData = uiImage.pngData()
let imagePNG = UIImage(data: imagePNGData!)

UIImageWriteToSavedPhotosAlbum(imagePNG!, nil, nil, nil)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文