UIImage的质量

时间:2016-04-19 15:08:40

标签: ios swift uiimage

我正在使用此函数调整各种图像的大小:

    func resizeImage(image: UIImage) -> UIImage {
        var actualHeight: CGFloat = image.size.height
        var actualWidth: CGFloat = image.size.width

        let maxHeight: CGFloat = 600.0
        let maxWidth: CGFloat = text.frame.size.width - 10

        var imgRatio: CGFloat = actualWidth / actualHeight
        let maxRatio: CGFloat = maxWidth / maxHeight
        let compressionQuality: CGFloat = 0.5
        //50 percent compression
        if actualHeight > maxHeight || actualWidth > maxWidth {
            if imgRatio < maxRatio {
                //adjust width according to maxHeight
                imgRatio = maxHeight / actualHeight
                actualWidth = imgRatio * actualWidth
                actualHeight = maxHeight
            }
            else if imgRatio > maxRatio {
                //adjust height according to maxWidth
                imgRatio = maxWidth / actualWidth
                actualHeight = imgRatio * actualHeight
                actualWidth = maxWidth
            }
            else {
                actualHeight = maxHeight
                actualWidth = maxWidth
            }
        }
        let rect: CGRect = CGRectMake(0.0, 0.0, actualWidth, actualHeight)
        UIGraphicsBeginImageContext(rect.size)
        image.drawInRect(rect)
        let img: UIImage = UIGraphicsGetImageFromCurrentImageContext()
        let imageData: NSData = UIImageJPEGRepresentation(img, compressionQuality)!
        UIGraphicsEndImageContext()

        return UIImage(data: imageData)!
    }

但是质量太可怕了....下面是我得到的照片:

enter image description here

我认为图像的质量因压缩质量而异...?从上面的代码中可以看出,我现在已经达到了0.5,但即使我将其改为1,质量仍然很糟糕?

任何想法,

非常感谢。

1 个答案:

答案 0 :(得分:2)

您应该使用UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)代替。它将使用您设备的正确比例。您正在使用的版本(没有选项)使用默认比例因子1.0。使用...WithOptions()变体并传入0.0作为比例,默认为设备的本机比例。请注意,这可能不是您想要的。

其次,您可以使用AVMakeRectWithAspectRatioInsideRect()来计算目标尺寸。第三,您不需要进行JPEG编码,您可以直接返回生成的图像。

结合起来,这大大简化了您的代码:

func resizeImage(image: UIImage) -> UIImage {
  let maxSize = CGSize(
    width: text.frame.size.width - 10, 
    height: 600.0
  )
  let newSize = AVMakeRectWithAspectRatioInsideRect(
    image.size, 
    CGRect(origin: CGPointZero, size: maxSize)
  ).size
  UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
  image.drawInRect(CGRect(origin: CGPointZero, size: newSize))
  let scaled = UIGraphicsGetImageFromCurrentImageContext()
  UIGraphicsEndImageContext()
  return scaled
}

编辑:这是我在项目中使用的UIImage的扩展名:

extension UIImage {
    /**
     Returns an scaled version of self that fits within the provided bounding box.
     It retains aspect ratio, and also retains the rendering mode.
     - parameter size: The target size, in point
     - parameter scale: Optional target scale. If omitted, uses the scale of input image
     - returns: A scaled image
     */
    func imageFittingSize(size: CGSize, scale: CGFloat? = nil) -> UIImage {
        let newSize = AVMakeRectWithAspectRatioInsideRect(self.size, CGRect(origin: CGPointZero, size: size)).size
        UIGraphicsBeginImageContextWithOptions(newSize, false, scale ?? self.scale)
        self.drawInRect(CGRect(origin: CGPointZero, size: newSize))
        let scaled = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return scaled.imageWithRenderingMode(renderingMode)
    }
}

你可以像这样的图像调用它:

let maxSize = CGSize(width: text.frame.size.width - 10, height: 600.0)
let scaled = image.imageFittingSize(maxSize)