UIImageWriteToSavedPhotosAlbum保存时支持透明度的PNG格式吗?

17

我正在使用UIImageWriteToSavedPhotosAlbum将UIImage保存到用户的相册中。问题是该图像没有透明度且为JPG格式。虽然我已经正确设置了像素数据以具有透明度,但似乎没有办法以支持透明度的格式保存。有什么想法?

编辑:无法实现这一点,但有其他方法向用户提供PNG图像。其中之一是将图像保存在文档目录中(如下所述)。完成后,可以通过电子邮件发送、保存在数据库中等方式使用它。除非是有损非透明JPG,否则您无法将其保存到相册中(目前)。

5个回答

45

SO问题所指出的,有一种简单方法可以将PNG保存到您的相册中:

UIImage* image = ...;                                     // produce your image
NSData* imageData =  UIImagePNGRepresentation(image);     // get png representation
UIImage* pngImage = [UIImage imageWithData:imageData];    // rewrap
UIImageWriteToSavedPhotosAlbum(pngImage, nil, nil, nil);  // save to photo album

15

这是我以前注意到并在约一年前向Apple开发者论坛报告的问题。据我所知,它仍然是一个未解决的问题。

如果您有时间,请花点时间在Apple Bug Report上提交功能请求。如果更多人报告此问题,则苹果公司更有可能修复这种方法以输出非损失性、支持 alpha 的 PNG。

编辑

如果您可以在内存中组合图像,我认为以下内容将起到作用或至少让您开始:

- (UIImage *) composeImageWithWidth:(NSInteger)_width andHeight:(NSInteger)_height {
    CGSize _size = CGSizeMake(_width, _height);
    UIGraphicsBeginImageContext(_size);

    // Draw image with Quartz 2D routines over here...

    UIImage *_compositeImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return _compositeImage;
}

//
// cf. https://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/FilesandNetworking/FilesandNetworking.html#//apple_ref/doc/uid/TP40007072-CH21-SW20
//

- (BOOL) writeApplicationData:(NSData *)data toFile:(NSString *)fileName {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    if (!documentsDirectory) {
        NSLog(@"Documents directory not found!");
        return NO;
    }
    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:fileName];
    return ([data writeToFile:appFile atomically:YES]);
}

// ...

NSString *_imageName = @"myImageName.png";
NSData *_imageData = [NSData dataWithData:UIImagePNGRepresentation([self composeImageWithWidth:100 andHeight:100)];

if (![self writeApplicationData:_imageData toFile:_imageName]) {
    NSLog(@"Save failed!");
}

完成了。据说有一种方法可以以非损失格式将图片保存到文档文件夹中。你知道怎么做吗? - Eli
我已经更新了我的答案。希望这能帮助你入门。 - Alex Reynolds
太棒了!效果非常好。这张图片是PNG格式的,具有透明度,我只需要找到它就可以了。 - Eli
我不明白这是如何工作的。原始图像数据的引用在哪里?从代码中看,似乎创建了一个“空白”图像,并指定了高度和宽度。我想传入来自相机的UIImage对象。 - Daddy
请查看下面的链接 https://dev59.com/BXI_5IYBdhLWcg3wMf9_#10279075,它可以与 UIImageWriteToSavedPhotosAlbum 一起使用,无需保存到文档文件夹。 - Jonny
在你投票之前,你看了回答的日期,对吧? - Alex Reynolds

8

在Swift 5中:

func pngFrom(image: UIImage) -> UIImage {
    let imageData = image.pngData()!
    let imagePng = UIImage(data: imageData)!
    return imagePng
}

6

我创建了一个UIImage的扩展,实现了安全解包:

扩展

extension UIImage {
    func toPNG() -> UIImage? {
        guard let imageData = self.pngData() else {return nil}
        guard let imagePng = UIImage(data: imageData) else {return nil}
        return imagePng
    }
}

用法:

let image = //your UIImage
if let pngImage = image.toPNG() {
     UIImageWriteToSavedPhotosAlbum(pngImage, nil, nil, nil)
}

4
作为UIImageWriteToSavedPhotosAlbum的替代方案,可以使用PHPhotoLibrary直接写入PNG数据。以下是一个名为“saveToPhotos”的UIImage扩展,它可以实现此功能:
extension UIImage {

    func saveToPhotos(completion: @escaping (_ success:Bool) -> ()) {

        if let pngData = self.pngData() {

            PHPhotoLibrary.shared().performChanges({ () -> Void in

                let creationRequest = PHAssetCreationRequest.forAsset()
                let options = PHAssetResourceCreationOptions()

                creationRequest.addResource(with: PHAssetResourceType.photo, data: pngData, options: options)

            }, completionHandler: { (success, error) -> Void in

                if success == false {

                    if let errorString = error?.localizedDescription  {
                        print("Photo could not be saved: \(errorString))")
                    }

                    completion(false)
                }
                else {
                    print("Photo saved!")

                    completion(true)
                }
            })
        }
        else {
            completion(false)
        }

    }
}

使用方法:

    if let image = UIImage(named: "Background.png") {
        image.saveToPhotos { (success) in
            if success {
                // image saved to photos
            }
            else {
                // image not saved
            }
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接