Resizing UIimages pulled from the Camera also ROTATES the UIimage?
Asked Answered
B

4

35

I am getting UIimages from the camera and assigning them to UIImageViews to be displayed. When I do this the camera gives me a 1200 x 1600 pixel image which I then assign to a UIImageView in my Application. The image is displayed as expected in the image view under this condition. However, when I attempt to RESIZE the retrieved UIImage before assigning it to the UIImageView, the image is resizing as expected but there IS a problem in that somewhere (in the RESIZING code?) my UIImage is getting ROTATED... As a result, when I assign the resized UIImage to a UIImageView the image is rotated 90 degrees and appears stretched as the aspect ratio (1200 x 1600 pixels) was unchanged...

I am using this to get a UIImage from the Camera:

- (void) imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{

        myImg = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
        myResizedImg = [self resizeImage:myImg width:400 height:533];
        [myImageView setImage:myResizedImg];

}

I am using this to resize it:

-(UIImage *)resizeImage:(UIImage *)anImage width:(int)width height:(int)height
{

    CGImageRef imageRef = [anImage CGImage];

    CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef);

    if (alphaInfo == kCGImageAlphaNone)
    alphaInfo = kCGImageAlphaNoneSkipLast;


    CGContextRef bitmap = CGBitmapContextCreate(NULL, width, height, CGImageGetBitsPerComponent(imageRef), 4 * width, CGImageGetColorSpace(imageRef), alphaInfo);

    CGContextDrawImage(bitmap, CGRectMake(0, 0, width, height), imageRef);

    CGImageRef ref = CGBitmapContextCreateImage(bitmap);
    UIImage *result = [UIImage imageWithCGImage:ref];

    CGContextRelease(bitmap);
    CGImageRelease(ref);

    return result;  
}

QUESTION: How do I RESIZE a UIImage pulled from the Camera WITHOUT rotating the pixels?

Bulley answered 11/8, 2009 at 13:11 Comment(0)
P
61

The reason your code doesn't work is because the imageOrientation on the code that you have is not being taken into account. Specifically, if the imageOrientation is right/left, then you need to both rotate the image and swap width/height. Here is some code to do this:

-(UIImage*)imageByScalingToSize:(CGSize)targetSize
{
    UIImage* sourceImage = self; 
    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;

    CGImageRef imageRef = [sourceImage CGImage];
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);

    if (bitmapInfo == kCGImageAlphaNone) {
        bitmapInfo = kCGImageAlphaNoneSkipLast;
    }

    CGContextRef bitmap;

    if (sourceImage.imageOrientation == UIImageOrientationUp || sourceImage.imageOrientation == UIImageOrientationDown) {
        bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    } else {
        bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    }   

    if (sourceImage.imageOrientation == UIImageOrientationLeft) {
        CGContextRotateCTM (bitmap, radians(90));
        CGContextTranslateCTM (bitmap, 0, -targetHeight);

    } else if (sourceImage.imageOrientation == UIImageOrientationRight) {
        CGContextRotateCTM (bitmap, radians(-90));
        CGContextTranslateCTM (bitmap, -targetWidth, 0);

    } else if (sourceImage.imageOrientation == UIImageOrientationUp) {
        // NOTHING
    } else if (sourceImage.imageOrientation == UIImageOrientationDown) {
        CGContextTranslateCTM (bitmap, targetWidth, targetHeight);
        CGContextRotateCTM (bitmap, radians(-180.));
    }

    CGContextDrawImage(bitmap, CGRectMake(0, 0, targetWidth, targetHeight), imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(bitmap);
    UIImage* newImage = [UIImage imageWithCGImage:ref];

    CGContextRelease(bitmap);
    CGImageRelease(ref);

    return newImage; 
}

This will resize your image and rotate it to the correct orientation. If you need the definition for radians, it is:

static inline double radians (double degrees) {return degrees * M_PI/180;}

The answer Daniel gave is also correct, but it suffers from the problem that it is not thread-safe, since you're using UIGraphicsBeginImageContext(). Since the above code only uses CG functions, you're all set. I also have a similar function to resize and do proper aspect fill on images - let me know if that's what you're looking for.

Note: I got the original function from this post, and did some modifications to make it work on JPEGs.

Precognition answered 11/8, 2009 at 19:23 Comment(2)
how can i use this code to fix orientation and then rotate to spec. degreeses?Stereoscopic
This code didn't seem to work for me; seems like the issue is that the photos treat the "up" orientation as matching a landscape photo taken with the home button on the right, while this code treats "up" as matching portrait.Fraser
A
12

I had this problem too with some of the code out there, i found this code that works, check it out, let me know what you find

+ (UIImage*)imageWithImage:(UIImage*)image 
               scaledToSize:(CGSize)newSize;
{
   UIGraphicsBeginImageContext( newSize );
   [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
   UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   return newImage;
}
Amethyst answered 11/8, 2009 at 13:14 Comment(4)
this code does not take the camera orientation into account. it simply scales the image to the specified size.Hemoglobin
no, but you can easily query for orientation and send the appropriate sizes in there...Amethyst
The orientation of newImage is always UIImageOrientationUp no matter what the orientation of image is, but the code is right, because drawInRect: take the orientation into account and make proper rotation inside.Lemay
This is also the method i use. The CGContextDrawImage call does not draw in proper orientation. The drawInRect call does. This saves all the work by using the call already designed for it.Newmint
H
2

Swift 3

I add this to didFinishPickingMediaWithInfo method and then use image without worrying for its rotation.

var image = info[UIImagePickerControllerOriginalImage] as! UIImage
if (image.imageOrientation != .up) {
  UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
  image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
  image = UIGraphicsGetImageFromCurrentImageContext()!
  UIGraphicsEndImageContext()
}
Hizar answered 29/12, 2016 at 14:11 Comment(0)
W
1

If you want to make a square image from a rectangle image (no matter horizontal or vertical) by cropping it by width or height in both sides, use my code. The difference is that I don't stretch, but I crop. I made it from the top code by modification:

//Cropping _image to fit it to the square by height or width

CGFloat a = _image.size.height;
CGFloat b = _image.size.width;
CGRect cropRect;

if (!(a==b)) {
    if (a<b) {
        cropRect = CGRectMake((b-a)/2.0, 0, a, a);
        b = a;
    }
    else if (b<a) {
        cropRect = CGRectMake(0, (a-b)/2.0, b, b);
        a = b;
    }

    CGImageRef imageRef = CGImageCreateWithImageInRect([_image CGImage], cropRect);

    UIImage* sourceImage = _image; 
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
    CGContextRef bitmap;
    if (sourceImage.imageOrientation == UIImageOrientationUp || sourceImage.imageOrientation == UIImageOrientationDown) {
        bitmap = CGBitmapContextCreate(NULL, a, a, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    } else {
        bitmap = CGBitmapContextCreate(NULL, a, a, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
    }

    if (sourceImage.imageOrientation == UIImageOrientationLeft) {
        CGContextRotateCTM (bitmap, radians(90));
        CGContextTranslateCTM (bitmap, 0, -a);

    } else if (sourceImage.imageOrientation == UIImageOrientationRight) {
        CGContextRotateCTM (bitmap, radians(-90));
        CGContextTranslateCTM (bitmap, -a, 0);

    } else if (sourceImage.imageOrientation == UIImageOrientationUp) {
        // NOTHING
    } else if (sourceImage.imageOrientation == UIImageOrientationDown) {
        CGContextTranslateCTM (bitmap, a, a);
        CGContextRotateCTM (bitmap, radians(-180.));
    }

    CGContextDrawImage(bitmap, CGRectMake(0, 0, a, a), imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(bitmap);
    _image = [UIImage imageWithCGImage:ref];
    CGImageRelease(imageRef);
}
Whirlabout answered 26/5, 2012 at 16:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.