1

Currently, we are using PHPickerViewController + CGImage for efficient memory usage consideration - https://christianselig.com/2020/09/phpickerviewcontroller-efficiently/

However, we are getting "unsupported file format 'org.webmproject.webp'" error, while trying to save CGImage in webp format.

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    picker.dismiss(animated: true)
    guard !results.isEmpty else { return }

    for result in results {
        result.itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.image.identifier) { (url, error) in
            guard let url = url else { return }
            
            let options: [CFString: Any] = [
                kCGImageSourceCreateThumbnailFromImageAlways: true,
                kCGImageSourceCreateThumbnailWithTransform: true,
                kCGImageSourceShouldCacheImmediately: true,
                kCGImageSourceThumbnailMaxPixelSize: 512
            ]

            guard let imageSource = CGImageSourceCreateWithURL(url as NSURL, nil) else { return }

            let image = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as CFDictionary)
            
            //
            // No issue in dealing with UTType.jpeg.identifier and UTType.png.identifier.
            // destUrl is type URL.
            //
            guard let destination = CGImageDestinationCreateWithURL(destUrl as CFURL, UTType.webP.identifier, 1, nil) else { return }
            CGImageDestinationAddImage(destination, image!, nil)
            CGImageDestinationFinalize(destination)
        }
    }
}

We face no issue in saving CGImage in UTType.jpeg.identifier format and UTType.png.identifier format.

May I know how can we save CGImage in webp format without issue? Thank you.

Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875
  • The obviously conclusion is that Core Graphics can't create webp images - it is an unsupported format. Use PNG or JPEG or write your own code to convert a CGImage to webp. – Paulw11 Aug 16 '21 at 11:51
  • @Paulw11 But, any idea why there isn't any issue, if we read a webp image file into a CGImage, and save it to png/ jpeg using `CGImageSourceCreateWithURL`, `CGImageSourceCreateThumbnailAtIndex` and `CGImageSourceCreateImageAtIndex`? The only issue is when written CGImage back to webp format... – Cheok Yan Cheng Aug 17 '21 at 10:56
  • The error message says that it isn't supported, so I guess it isn't supported. Maybe reading is but writing isn't? – Paulw11 Aug 17 '21 at 12:05
  • Does this answer your question? [How to get WebP images from gallery with PHPicker](https://stackoverflow.com/questions/68255880/how-to-get-webp-images-from-gallery-with-phpicker) – Alexandre Fenyo Nov 01 '22 at 16:09

2 Answers2

0

webp is not supported for encoding.

You can use function like this to list supported types:

void listImageCodecs(void){
    CFArrayRef mySourceTypes = CGImageSourceCopyTypeIdentifiers();
    CFShow(mySourceTypes);
    CFArrayRef myDestinationTypes = CGImageDestinationCopyTypeIdentifiers();
    CFShow(myDestinationTypes);
}

On my system I have such a result:

(
    "public.jpeg",
    "public.png",
    "com.compuserve.gif",
    "com.canon.tif-raw-image",
    "com.adobe.raw-image",
    "com.dxo.raw-image",
    "com.canon.cr2-raw-image",
    "com.canon.cr3-raw-image",
    "com.leafamerica.raw-image",
    "com.hasselblad.fff-raw-image",
    "com.hasselblad.3fr-raw-image",
    "com.nikon.raw-image",
    "com.nikon.nrw-raw-image",
    "com.pentax.raw-image",
    "com.samsung.raw-image",
    "com.sony.raw-image",
    "com.sony.sr2-raw-image",
    "com.sony.arw-raw-image",
    "com.epson.raw-image",
    "com.kodak.raw-image",
    "public.tiff",
    "public.jpeg-2000",
    "com.apple.atx",
    "org.khronos.astc",
    "org.khronos.ktx",
    "public.avci",
    "public.heic",
    "public.heics",
    "public.heif",
    "com.canon.crw-raw-image",
    "com.fuji.raw-image",
    "com.panasonic.raw-image",
    "com.panasonic.rw2-raw-image",
    "com.leica.raw-image",
    "com.leica.rwl-raw-image",
    "com.konicaminolta.raw-image",
    "com.olympus.sr-raw-image",
    "com.olympus.or-raw-image",
    "com.olympus.raw-image",
    "com.phaseone.raw-image",
    "com.microsoft.ico",
    "com.microsoft.bmp",
    "com.apple.icns",
    "com.adobe.photoshop-image",
    "com.microsoft.cur",
    "com.truevision.tga-image",
    "com.ilm.openexr-image",
    "org.webmproject.webp",
    "com.sgi.sgi-image",
    "public.radiance",
    "public.pbm",
    "public.mpo-image",
    "public.pvr",
    "com.microsoft.dds",
    "com.apple.pict"
)
(
    "public.jpeg",
    "public.png",
    "com.compuserve.gif",
    "public.tiff",
    "public.jpeg-2000",
    "com.apple.atx",
    "org.khronos.ktx",
    "org.khronos.astc",
    "com.microsoft.dds",
    "public.heic",
    "public.heics",
    "com.microsoft.ico",
    "com.microsoft.bmp",
    "com.apple.icns",
    "com.adobe.photoshop-image",
    "com.adobe.pdf",
    "com.truevision.tga-image",
    "com.ilm.openexr-image",
    "public.pbm",
    "public.pvr"
)

Oldes
  • 937
  • 1
  • 9
  • 24
0

I was in a similar issue where the new PHPickerViewController failed to import images with org.webmproject.webp extension. Although the above question asks why CGImage with UTType.webP.identifier fails to save, for folks who just wants to import an image with org.webmproject.webp extension without caring about the output extension here is a simple solution.

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    
    var images: [UIImage] = []
    var urls: [URL] = []
    let itemProviders = results.map(\.itemProvider)
    
    let dispatchGroup = DispatchGroup()
    UIApplication.shared.keyWindow?.lock()
    
    for itemProvider in itemProviders {
        guard let typeIdentifier = itemProvider.registeredTypeIdentifiers.first else {
            continue
        }

        dispatchGroup.enter()
        
        if itemProvider.hasItemConformingToTypeIdentifier(UTType.movie.identifier) {
            itemProvider.loadFileRepresentation(forTypeIdentifier: typeIdentifier) { url, err in
                
                if let url = url {
                    if let newTempUrl = CacheManager.shared.saveAssetToTempDirectory(url: url) {
                        urls.append(newTempUrl)
                        dispatchGroup.leave()
                    } else {
                        dispatchGroup.leave()
                    }
                }
            }
        } else if typeIdentifier == "org.webmproject.webp" || itemProvider.canLoadObject(ofClass: UIImage.self) {
            itemProvider.loadFileRepresentation(forTypeIdentifier: typeIdentifier) { url, err in
                
                if let url = url {
                    if let data = try? Data(contentsOf: url) {
                        if let image = UIImage(data: data) {
                            images.append(image)
                        }
                    }
                    dispatchGroup.leave()
                }
            }
        } else {
            dispatchGroup.leave()
        }
    }
    
    dispatchGroup.notify(queue: .main) {
        /// You have the images or video urls for use here
        /// images & urls
    }
}
Amrit Sidhu
  • 1,870
  • 1
  • 18
  • 32