草庐IT

objective-c - UIImage 调整大小无法正常工作

coder 2023-09-20 原文

所以我一直在试图弄清楚我做错了一段时间,但我无法弄清楚。我想要完成的是:

  1. 使用UIImagePickerController拍照
  2. 拍摄生成的照片并剪掉顶部和底部,使其成为正方形(类似于 Instagram)
  3. UIButton 中显示该图像

出于某种原因,每次我拍摄照片时,它都会在 UIButton 中变形,并且看起来好像裁剪工作不正常。这就是我所做的。在 didFinishPickingMediaWithInfo 方法中,我有以下代码:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    //Copy the image to the userImage variable
    [picker dismissModalViewControllerAnimated:YES];
    userImage = nil;

    //Rotate & resize image
    userImage = [self resizeAndRotatePhoto:(UIImage *)[info objectForKey:UIImagePickerControllerOriginalImage]];
    NSLog(@"Userimage size, width: %f , height: %f", userImage.size.width , userImage.size.height);

    //Update the image form field with the image and set the image in the controller
    NSLog(@"Button size is height: %f , width: %f" , userImageAvatarButton.frame.size.height , userImageAvatarButton.frame.size.width);
   [userImageAvatarButton.layer setMasksToBounds:YES];
   [userImageAvatarButton.layer setCornerRadius:3.0];
   [userImageAvatarButton setImage:userImage forState:UIControlStateNormal];
}

我将暂时包含 resizeAndRotatePhoto 方法,但结果如下所示。另外,在上面的代码中,@property (strong) (UIImage *)userImage; 是在 ViewController 的头文件中定义的。日志输出还导致:

2012-05-07 17:38:07.995 NewApp[10666:707] Userimage size, width: 1936.000000 , height: 1936.000000
2012-05-07 17:38:08.000 NewApp[10666:707] Button size is height: 60.000000 , width: 60.000000

正如您在下图中看到的,它最终变形了。

关于resizeAndRotate方法,这里是:

- (UIImage *)resizeAndRotatePhoto:(UIImage *)source
{
if( source.imageOrientation == UIImageOrientationRight )
{
    source = [self rotateImage:source byDegrees:90];
}
if( userImage.imageOrientation == UIImageOrientationLeft)
{
    source = [self rotateImage:source byDegrees:-90];
}

CGFloat x,y;
CGFloat size;
if( source.size.width > source.size.height ){
    size = source.size.height;
    x = (source.size.width - source.size.height)/2;
    y = 0;
}
else {
    size = source.size.width;
    x = 0;
    y = (source.size.height - source.size.width)/2;
}


CGImageRef imageRef = CGImageCreateWithImageInRect([source CGImage], CGRectMake(x,y,size,size) );
return [UIImage imageWithCGImage:imageRef];
}

在这一点上,我不知道如何让这张图片不失真地显示出来。尽管系统说图像确实是正方形,但它似乎裁剪错误并显示错误。

最佳答案

我出于其他原因放弃了 vocaro.com 解决方案(该解决方案在使用非典型图像格式(例如 CMYK)时会崩溃)。

无论如何,我现在使用以下 UIImage 类别的 imageByScalingAspectFillSize 方法制作我的方形缩略图。

顺便说一下,这会自动应用设备主屏幕的比例(例如,UIButton 按钮在 Retina 设备上是 60x60 点,这将应用 2x(或 3x)的比例),即 120x120 或 180x180 的图像)。

UIImage+SimpleResize.h:

/*  UIImage+SimpleResize.h
 *
 *  Modified by Robert Ryan on 5/19/11.
 */

@import UIKit;

/** Image resizing category.
 *
 *  Modified by Robert Ryan on 5/19/11.
 *
 *  Inspired by http://ofcodeandmen.poltras.com/2008/10/30/undocumented-uiimage-resizing/
 *  but adjusted to support AspectFill and AspectFit modes.
 */

@interface UIImage (SimpleResize)

/** Resize the image to be the required size, stretching it as needed.
 *
 * @param size         The new size of the image.
 * @param contentMode  The `UIViewContentMode` to be applied when resizing image.
 *                     Either `UIViewContentModeScaleToFill`, `UIViewContentModeScaleAspectFill`, or
 *                     `UIViewContentModeScaleAspectFit`.
 *
 * @return             Return `UIImage` of resized image.
 */

- (UIImage * _Nullable)imageByScalingToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode;

/** Resize the image to be the required size, stretching it as needed.
 *
 * @param size         The new size of the image.
 * @param contentMode  The `UIViewContentMode` to be applied when resizing image.
 *                     Either `UIViewContentModeScaleToFill`, `UIViewContentModeScaleAspectFill`, or
 *                     `UIViewContentModeScaleAspectFit`.
 * @param scale        The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
 *
 * @return             Return `UIImage` of resized image.
 */

- (UIImage * _Nullable)imageByScalingToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode scale:(CGFloat)scale;

/** Crop the image to be the required size.
 *
 * @param bounds       The bounds to which the new image should be cropped.
 *
 * @return             Cropped `UIImage`.
 */

- (UIImage * _Nullable)imageByCroppingToBounds:(CGRect)bounds;

/** Crop the image to be the required size.
 *
 * @param bounds       The bounds to which the new image should be cropped.
 * @param scale        The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
 *
 * @return             Cropped `UIImage`.
 */

- (UIImage * _Nullable)imageByCroppingToBounds:(CGRect)bounds scale:(CGFloat)scale;

/** Resize the image to fill the rectange of the specified size, preserving the aspect ratio, trimming if needed.
 *
 * @param size    The new size of the image.
 *
 * @return        Return `UIImage` of resized image.
 */

- (UIImage * _Nullable)imageByScalingAspectFillSize:(CGSize)size;

/** Resize the image to fill the rectange of the specified size, preserving the aspect ratio, trimming if needed.
 *
 * @param size    The new size of the image.
 * @param scale   The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
 *
 * @return        Return `UIImage` of resized image.
 */

- (UIImage * _Nullable)imageByScalingAspectFillSize:(CGSize)size scale:(CGFloat)scale;

/** Resize the image to be the required size, stretching it as needed.
 *
 * @param size    The new size of the image.
 *
 * @return        Resized `UIImage` of resized image.
 */

- (UIImage * _Nullable)imageByScalingToFillSize:(CGSize)size;

/** Resize the image to be the required size, stretching it as needed.
 *
 * @param size    The new size of the image.
 * @param scale   The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
 *
 * @return        Resized `UIImage` of resized image.
 */

- (UIImage * _Nullable)imageByScalingToFillSize:(CGSize)size scale:(CGFloat)scale;

/** Resize the image to fit within the required size, preserving the aspect ratio, with no trimming taking place.
 *
 * @param size    The new size of the image.
 *
 * @return        Return `UIImage` of resized image.
 */

- (UIImage * _Nullable)imageByScalingAspectFitSize:(CGSize)size;

/** Resize the image to fit within the required size, preserving the aspect ratio, with no trimming taking place.
 *
 * @param size    The new size of the image.
 * @param scale   The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
 *
 * @return        Return `UIImage` of resized image.
 */

- (UIImage * _Nullable)imageByScalingAspectFitSize:(CGSize)size scale:(CGFloat)scale;

@end

UIImage+SimpleResize.m:

//  UIImage+SimpleResize.m
//
//  Created by Robert Ryan on 5/19/11.

#import "UIImage+SimpleResize.h"

@implementation UIImage (SimpleResize)

- (UIImage *)imageByScalingToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode {
    return [self imageByScalingToSize:size contentMode:contentMode scale:0];
}

- (UIImage *)imageByScalingToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode scale:(CGFloat)scale {
    if (contentMode == UIViewContentModeScaleToFill) {
        return [self imageByScalingToFillSize:size];
    }
    else if ((contentMode == UIViewContentModeScaleAspectFill) ||
             (contentMode == UIViewContentModeScaleAspectFit)) {
        CGFloat horizontalRatio   = self.size.width  / size.width;
        CGFloat verticalRatio     = self.size.height / size.height;
        CGFloat ratio;

        if (contentMode == UIViewContentModeScaleAspectFill)
            ratio = MIN(horizontalRatio, verticalRatio);
        else
            ratio = MAX(horizontalRatio, verticalRatio);

        CGSize  sizeForAspectScale = CGSizeMake(self.size.width / ratio, self.size.height / ratio);

        UIImage *image = [self imageByScalingToFillSize:sizeForAspectScale scale:scale];

        // if we're doing aspect fill, then the image still needs to be cropped

        if (contentMode == UIViewContentModeScaleAspectFill) {
            CGRect  subRect = CGRectMake(floor((sizeForAspectScale.width - size.width) / 2.0),
                                         floor((sizeForAspectScale.height - size.height) / 2.0),
                                         size.width,
                                         size.height);
            image = [image imageByCroppingToBounds:subRect];
        }

        return image;
    }

    return nil;
}

- (UIImage *)imageByCroppingToBounds:(CGRect)bounds {
    return [self imageByCroppingToBounds:bounds scale:0];
}

- (UIImage *)imageByCroppingToBounds:(CGRect)bounds scale:(CGFloat)scale {
    if (scale == 0) {
        scale = [[UIScreen mainScreen] scale];
    }
    CGRect rect = CGRectMake(bounds.origin.x * scale, bounds.origin.y * scale, bounds.size.width * scale, bounds.size.height * scale);
    CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], rect);
    UIImage *croppedImage = [UIImage imageWithCGImage:imageRef scale:scale orientation:self.imageOrientation];
    CGImageRelease(imageRef);
    return croppedImage;
}

- (UIImage *)imageByScalingToFillSize:(CGSize)size {
    return [self imageByScalingToFillSize:size scale:0];
}

- (UIImage *)imageByScalingToFillSize:(CGSize)size scale:(CGFloat)scale {
    UIGraphicsBeginImageContextWithOptions(size, false, scale);
    [self drawInRect:CGRectMake(0, 0, size.width, size.height)];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

- (UIImage *)imageByScalingAspectFillSize:(CGSize)size {
    return [self imageByScalingAspectFillSize:size scale:0];
}

- (UIImage *)imageByScalingAspectFillSize:(CGSize)size scale:(CGFloat)scale {
    return [self imageByScalingToSize:size contentMode:UIViewContentModeScaleAspectFill scale:scale];
}

- (UIImage *)imageByScalingAspectFitSize:(CGSize)size {
    return [self imageByScalingAspectFitSize:size scale:0];
}

- (UIImage *)imageByScalingAspectFitSize:(CGSize)size scale:(CGFloat)scale {
    return [self imageByScalingToSize:size contentMode:UIViewContentModeScaleAspectFit scale:scale];
}

@end

关于objective-c - UIImage 调整大小无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10491080/

有关objective-c - UIImage 调整大小无法正常工作的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  5. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  6. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  7. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  8. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  9. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  10. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

随机推荐