从相机中获取的 UIimages 调整大小后也会旋转 UIimage?

35
我从相机获取UIimages并将其分配给UIImageViews以显示。当我这样做时,相机会给我一张1200 x 1600像素的图片,然后我将其分配给应用程序中的UIImageView。在这种情况下,图片如预期地显示在图像视图中。但是,当我尝试在将检索到的UIImage分配给UIImageView之前调整大小时,图像会按预期进行调整大小,但是在某个地方(在调整大小代码中?)我的UIImage会旋转... 因此,当我将调整大小后的UIImage分配给UIImageView时,图像会旋转90度,并且显示为拉伸的状态,因为纵横比(1200 x 1600像素)没有改变... 我正在使用以下方法从相机获取UIImage:
- (void) imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{

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

}

我正在使用这个来进行调整大小:

-(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;  
}

问题:如何在不旋转像素的情况下调整从相机中获取的UIImage的大小?

4个回答

61

你的代码无法正常工作是因为它没有考虑到图像方向。具体来说,如果图像方向是右/左,则需要旋转图像并交换宽度/高度。这是一些完成此操作的代码:

-(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; 
}

这将调整您的图片大小并将其旋转到正确的方向。如果您需要弧度的定义,它是:

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

丹尼尔所提供的答案也是正确的,但它存在一个问题,它不是线程安全的,因为您正在使用UIGraphicsBeginImageContext()。由于上面的代码仅使用CG函数,因此可以放心使用。我还有一个类似的函数来调整大小并对图像进行适当的填充-如果这正是您要寻找的,请告诉我。

注意:我从这篇文章中获得了原始函数,并进行了一些修改以使其在JPEG上工作。


如何使用这段代码来修正方向并旋转到特定的角度? - Pion
2
这段代码对我似乎没有起作用;问题似乎在于照片将“向上”方向视为与主页按钮在右侧拍摄的横向照片相匹配,而此代码将“向上”视为与纵向照片相匹配。 - Ben Wheeler

12

我也遇到了这个问题,之前看到一些代码,但都不行。后来找到了这段代码,可以使用。试试看吧,让我知道你的发现。

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

   return newImage;
}

此代码不考虑相机方向,仅将图像缩放到指定大小。 - npellow
不,但你可以轻松查询方向并发送相应的尺寸。 - Daniel
1
无论image的方向如何,newImage的方向始终为UIImageOrientationUp,但代码是正确的,因为drawInRect:考虑了方向并在内部进行适当的旋转。 - KudoCC
这也是我使用的方法。CGContextDrawImage调用不会以正确的方向绘制,而drawInRect调用则可以。通过使用已经为此设计的调用,可以节省所有工作。 - Ben

2

Swift 3

我将以下代码添加到didFinishPickingMediaWithInfo方法中,然后使用image而不必担心其旋转问题。

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()
}

1
如果您想通过在两侧裁剪宽度或高度来将矩形图像(无论是横向还是纵向)制作成正方形图像,请使用我的代码。不同之处在于我不会拉伸,而是裁剪。我是通过修改顶部代码制作的。
//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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接