0

I'm taking UIImages and sending them over iOS' Multipeer framework. Here's the steps I take to do so:

/// Save images to filesystem before sending over Multipeer
func save(image: UIImage) -> ImageFile? {
    guard let imageDirectory = imageDirectory,
          ensureDirectoryExists(imageDirectory),
          let data = image.pngData() 
    else { 
        return nil 
    }

    let id = UUID()

    let filepath = (imageDirectory as NSString).appendingPathComponent(id.uuidString + ".png")
    let fileURL = URL(fileURLWithPath: filepath)

    do {
        try data.write(to: fileURL, options: .atomic)
    } catch {
        print(error)
    }

    return ImageFile(id: id, url: fileURL)
}

/// Send the photos that were saved to the filesystem over Multipeer
func sendImages() {
    for imageFile in imageFiles {
        session.sendResource(at: imageFile.url, name: imageFile.id.uuidString, to: session.peers)
    }
}

/// On receiving clients, load the image from the URL
func loadImage(at url: URL) -> UIImage? {
    do {
        let data = try Data(contentsOf: url)
        return UIImage(data: data)
    } catch {
        print(error)
    }

    return nil
}

The problem is some (not all) images come out on the receiving clients rotated 90º counterclockwise.

Is there something I should be doing differently when loading images from the filesystem, or saving to the filesystem? I'm guessing it has something to do with EXIF data, or maybe images that have been manually rotated?

Mark
  • 7,167
  • 4
  • 44
  • 68
  • Can you determine what is special about the UIImages that come out wrong? – matt Feb 22 '22 at 02:47
  • For example a UIImage has orientation information. https://developer.apple.com/documentation/uikit/uiimage/1624141-imageorientation But when you strip out the pngData, you throw that information away. I'm wondering if that's the issue here. – matt Feb 22 '22 at 02:50
  • https://stackoverflow.com/questions/7838699/save-uiimage-load-it-in-wrong-orientation – trndjc Feb 22 '22 at 03:32
  • I came across this problem with an image-editing script I made long ago and the solution was to switch on the `imageOrientation` property of the `UIImage` and rotate the image accordingly. – trndjc Feb 22 '22 at 03:38
  • I've read PNGs do not store orientation data so as matt points out `image.pngData()` probably strips out the EXIF information consisting of orientation. One quick fix you could try is replacing png with jpeg to see if this helps. Second option is to actually save and send the orientation data along with the image to the client. Matt has an answer on this: https://stackoverflow.com/a/54947641/1619193 and then another option to try is to `fix` the orientation: https://stackoverflow.com/a/27775741/1619193 and https://stackoverflow.com/questions/10600613/ios-image-orientation-has-strange-behavior – Shawn Frank Feb 22 '22 at 03:40
  • You have two options. A) Send a jpegData instead of pngData. jpegData will preserve the image orientation. B) If you really need to send a png you will need to create a new image context and redraw your image before getting the png data representation. Check this [Swift PNG Image being saved with incorrect orientation](https://stackoverflow.com/a/42098812/2303865) – Leo Dabus Feb 22 '22 at 05:03
  • Btw I am not sure if your image URL is not a fileURL but FIY you should always download remote resources asynchronously using URLSession dataTask or downloadTask. Never use `Data(contentsOf: URL)` to load non local resources. – Leo Dabus Feb 22 '22 at 05:07
  • if you `URL` is a `fileURL` you should use `UIImage(contentsOfFile:)` initializer. It loads the image data into memory and marks it as purgeable. – Leo Dabus Feb 22 '22 at 05:13
  • @LeoDabus that's odd, I tried that API originally but it failed to load the image. Only `Data(contentsOf: URL)` worked for me. The URL is a file URL that is served up by the Multipeer framework. – Mark Feb 23 '22 at 22:41

0 Answers0