Why Do iOS Thumbnail Images Turn Weird? Unraveling the Mystery

Lee young-jun
5 min readDec 12, 2023

--

One of my apps generates thumbnails for images. When I attempted to create them using ImageContext, some of the images appeared strange, being either upside-down or right-side-left.

imageOrientation

Fortunately, I could find out how to know the camera orientation when the images were taken.

UIImage has imageOrientation.

public enum Orientation : Int, @unchecked Sendable {
case up = 0
case down = 1
case left = 2
case right = 3
case upMirrored = 4
case downMirrored = 5
case leftMirrored = 6
case rightMirrored = 7
}

And default orientation is up .

Graphic Context

How to get thumbnail image?
Draw a new image with the original image and a reduced size.

To draw Image, I should use the graphic context.

size : CGSize
...
UIGraphicsBeginImageContext(size);

You would already realized by the wordBegin . I had to end the image context also.

defer{
UIGraphicsEndImageContext();
}

Move Origin

Before start drawing, we should move origin. Origin is (0,0) position of drawing.

context!.translateBy(x: ..., y: ...);

Default position is 0,0.

Scale

I used scaleBy, with the argument x representing the width and y representing the height. It means if x is 0.5, the width will be scaled down to half.

context!.scaleBy(x: 0.5 y: 1);

Draw

The last task is drawing. I had to draw the image with CGImage, not UIImage. However, I didn’t have to know about CGImage; we can get CGImage with the cgImage property of UIImage.

context!.draw(originalImage.cgImage!, in: CGRect(origin: CGPoint.zero, size: size));

Final Image

Now, the drawing is finished. So, how can we obtain the new image? Retrieve the image from the current image.

let newImage = UIGraphicsGetImageFromCurrentImageContext();

Restore

If the real-world material is like this

Up

and the imageOrientation is set to Orientation.up, the captured image will appear upside-down.

I thought the default is Portrait.

However, when the image orientation is up, the device orientation is landscape left.

Let’s place the cgImage on the 2D graphic coordinate plane.

The reason the image is upside-down is that the cgImage is a raw image without orientation information.

https://www.quora.com/Does-a-camera-obscura-produce-an-inverted-image-If-yes-then-why

How to restore the image?
First, translate the image.

context!.translateBy(x: 1, y: size.height);

Second, flip it along the Y-axis.

context!.scaleBy(x: 1, y: -1);

When the scale value is less than zero, drawing will be opposite direction.

Right

I thought if the picture is taken with the device in landscape orientation to the left,

The image will be captured as follows:

Place the image on the coordinate.

Differently from the down case, in this time, rotate the image first.

context.rotate(by: CGFloat(Double.pi / 2));

I used M_PI_2, but it is deprecated now.

Next, flip it by Y-axis.

context.scaleBy(x: 1, y: -1);

Wait…! Why not like x: -1? It was flipped horizontally. Because since rotating the context, axes were swapped.

Left

If I took the photo after rotating the device left,

The cgImage will look like this.

Left is more complex.
Let’s start again. Rotate the image left.

ctx.rotate(by: -CGFloat(Double.pi / 2));

Flip it to get the originally rotated version.

ctx.scaleBy(x: 1, y: -1);

However, I couldn’t see anything because the final image is out of bounds. Move it within the bounds.

ctx.translateBy(x: -size.height, y: -size.width);

Why I had to move it in the negative direction? Because when I swapped axes, directions were also swapped.

It also means width is swapped with height.

size: CGSize(width: size.height, height: size.width))

I also created an example. Check this github repository.

If you found this post helpful, please give it a round of applause 👏. Explore more iOS-related content in my other posts.

For additional insights and updates, check out my LinkedIn profile. Thank you for your support!

References

--

--

No responses yet