UIImage looses its orientation while converting it

2020-04-27 08:16发布

问题:

I know there are tons of questions like this but their solutions don't work for me.

NOTE: The image is downloaded from the Internet. It isn't taken from iPhone's camera.

I have a UIImage. To do some image processing operations I use Metal and present the image in a MTKView. So, I convert the image into a CIImage. After doing all the modifications to the image I convert it back into CGImage and then into UIImage and save it.

As a result the saved image's orientation is wrong.

I'm not sure in which step it looses its orientation (when converting from UIImage into CIImage for adding to MTKView, or while converting from CIImage into CGImage and then into UIImage to save it). Because I'm not sure, bellow I provide everything I've tried for each steps:

For converting from UIImage into CIImage:

Initially I was simply converting the image in this way:

let let ciImage = CIImage(image: image)

Then I tried to use the following way:

  let ciImage = CIImage(image: image)?.oriented(forExifOrientation: imageOrientationToTiffOrientation(value: image.imageOrientation))

Here is the method imageOrientationToTiffOrientation's implementation (I found it here):

func imageOrientationToTiffOrientation(value: UIImageOrientation) -> Int32
{
    switch (value)
    {
    case .up:
        return 1
    case .down:
        return 3
    case .left:
        return 8
    case .right:
        return 6
    case .upMirrored:
        return 2
    case .downMirrored:
        return 4
    case .leftMirrored:
        return 5
    case .rightMirrored:
        return 7
    }
}

For converting from CIImage into CGImage and then into UIImage:

I convert CIImage into CGImage as usual:

let cgImage = context?.createCGImage(ciImage, from: ciImage.extent)

Then I convert cgImage into UIImage (imageToSave) this way:

let imageToSave = UIImage(cgImage: cgImage, scale: image.scale, orientation: imageOrientation)

imageOrientation and image.scale are the original image's orientation and scale.

As a result, the saved image still has a wrong orientatio.

Interestingly when I print those images orientations raw values, they are the same 0 which is the .up, however as I said, after saving, the orientation is wrong.

I'm quite confused why is this happening. If you have any suggestions about how to fix this, I would appreciate your help.

回答1:

The way to pick up the orientation from the original UIImage when creating a CIImage is to say:

let ciImage = CIImage(image: image, options: [.applyOrientationProperty:true])!

When you're done with the CIImage, save the data to disk with CIContext().writeJPEGRepresentation and the orientation metadata will be maintained.



回答2:

You can try this method

 func image(with image: UIImage?, scaledToSizeKeepingAspect newSize: CGSize) -> UIImage? {
    var newSize = newSize
    var imgHeight = Float(image?.size.height ?? 0.0)
    var imgWeight = Float(image?.size.width ?? 0.0)
    var fact: Float = 0.0
    if imgHeight > imgWeight {
        fact = Float(CGFloat(imgHeight) / newSize.width)
    } else {
        fact = Float(CGFloat(imgWeight) / newSize.height)
    }
    imgHeight = imgHeight / fact
    imgWeight = imgWeight / fact
    newSize = CGSize(width: CGFloat(imgWeight), height: CGFloat(imgHeight))
    UIGraphicsBeginImageContext(newSize)
    // Tell the old image to draw in this new context, with the desired
    // new size
    image?.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
        // Get the new image from the context
    let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
    // End the context
    UIGraphicsEndImageContext()
    // Return the new image.
    return newImage
}

Call method like this :

image(withImage: image, scaledToSizeKeepingAspect: image.size)

here image is UIImage object which image you want to change pass in this method.