Converting UIImage to jpegData - [Metal] 9072 by 12198 iosurface is too large for GPU

Hi,

I'm trying to convert images picked from the users camera roll into jpegData for me to upload to a server.

I'm doing the following to covert to Data:

let imageData: Data? = uiImage.jpegData(compressionQuality: 0)

This works fine when converting screenshots. But when I attempt to convert an image taken using the device's camera. It gives me the following error:

[Metal] 9072 by 12198 iosurface is too large for GPU

It still converts it into data, but the data then just contains a blank image. Not the selected image.

I'm at a loss with where to go with this one, I've tried converting HEIC preloaded onto the device's bundle and it works fine. But when using ones selected from the camera roll, I get the stated error.

Any help would be appreciated. This is the sample code I'm using to test the issue. (I'm aware it's quite pointless in this form)

func convertImage(image: Image?) -> Image? {   //1
    let key = "\(String.random(length: 15))"


    let uiImage: UIImage = image.asUIImage()
    let imageData: Data? = uiImage.jpegData(compressionQuality: 0)

    guard let imageData = imageData else { return nil }
    
    let encodedImage = imageData.base64EncodedString()
    
    let fileManager = FileManager.default
    let documentsPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
    let localImageUrl = (documentsPath?.appendingPathComponent(key))
    guard let localImageUrl = localImageUrl else {
        return nil
    }
    try! encodedImage.write(to: localImageUrl, atomically: true, encoding: String.Encoding.utf8)
    
    
    guard let fileContents = try? String(contentsOf: localImageUrl) else {
        return nil
    }

    let dataDecoded : Data = Data(base64Encoded: fileContents, options: .ignoreUnknownCharacters)!
    let decodedimage = UIImage(data: dataDecoded)
    
    return (Image(uiImage: decodedimage ?? UIImage(named: "placeholder")!))
}
import SwiftUI

struct UploadTesting: View {
    @ObservedObject var crViewModel = ChatroomsViewModel()
    
    @State var showImagePicker = false
    @State var selectedImage: Image? = nil
    
    @State var convertedImage: Image?
    var body: some View {
        VStack {
            Button("Select") {
                showImagePicker.toggle()
            }
            
            selectedImage?.resizable().scaledToFit().frame(width: 300, height: 300)
            
            Button("Convert") {


                convertedImage = crViewModel.convertImage(image: selectedImage)
            }
            
            convertedImage?.resizable().scaledToFit().frame(width: 200, height: 200).background(Color.red)
        }
        .sheet(isPresented: $showImagePicker) {
            ImagePicker(image: $selectedImage)
        }

    }
}

Video of issue: https://streamable.com/h0uqly

Can you share the image which causes the issue?

What is going on in ImagePicker? What type is Image? The device's camera should give an image a lot smaller than 9072 by 12198.

If you want to support images that large, try CGImageDestination. For example:


struct ImageDestination {
    
    let outputData = CFDataCreateMutable(nil, 0)!
    let cgImageDestination: CGImageDestination
        
    init?(type: UTType, count: Int = 1) {
        guard let d = CGImageDestinationCreateWithData(outputData, type.identifier as CFString, count, nil)
        else { return nil }
        self.cgImageDestination = d
    }
    
    mutating func addImage(_ image: CGImage) {
        CGImageDestinationAddImage(cgImageDestination, image, nil)
    }
    
    mutating func finalize() throws {
        guard CGImageDestinationFinalize(cgImageDestination) else {
            throw DocumentFailure.savingUnknown
        }
    }

}


/// usage:

let imageCG = uiImage.cgImage!
var dest = ImageDestination(type: .jpeg)!
dest.addImage(imageCG)
dest.finalize()

// your data
dest.outputData

I think you should use .jpegData(compressionQuality: 1) instead of .jpegData(compressionQuality: 0) if you don't want to compress the image.

Did you ever figure this out? Experiencing the same problem myself.

I have similar issue.Don't know how to solve it.

Converting UIImage to jpegData - [Metal] 9072 by 12198 iosurface is too large for GPU
 
 
Q