ios - 调整大小和裁剪 2 个图像影响原始图像质量

标签 ios swift uiimage

假设我在 UIViewController 上有一个 UIImage 的对象,我想从 Controller 设置图像。基本上我想做的是,将两张图片合并在一起,第一张图片是蓝色的 5 星:

enter image description here

第二张图片是灰色的 5 星:

enter image description here

它用于对图像进行评级。由于最大评分是 5,那么我必须将它乘以 20 得到 100 分,以便于计算。更多细节逻辑请看代码。

所以我有这个(BM_RatingHelper.swift):

static func getRatingImageBasedOnRating(rating: CGFloat, width: CGFloat, height: CGFloat) -> UIImage {
    // available maximum rating is 5.0, so we have to multiply it by 20 to achieve 100.0 point
    let ratingImageWidth = ( width / 100.0 ) * ( rating * 20.0 )

    // get active rating image
    let activeRatingImage = BM_ImageHelper.resize(UIImage(named: "StarRatingFullActive")!, targetSize: CGSize(width: width, height: height))
    let activeRatingImageView = UIImageView(frame: CGRectMake(0, 0, ratingImageWidth, height));
    activeRatingImageView.image = BM_ImageHelper.crop(activeRatingImage, x: 0, y: 0, width: ratingImageWidth, height: height);

    // get inactive rating image
    let inactiveRatingImage = BM_ImageHelper.resize(UIImage(named: "StarRatingFullInactive")!, targetSize: CGSize(width: width, height: height))
    let inactiveRatingImageView = UIImageView(frame: CGRectMake(ratingImageWidth, 0, ( 100.0 - ratingImageWidth ), height));
    inactiveRatingImageView.image = BM_ImageHelper.crop(inactiveRatingImage, x: ratingImageWidth, y: 0, width: ( 100.0 - ratingImageWidth ), height: height);

    // combine the images
    let ratingView = UIView.init(frame: CGRect(x: 0, y: 0, width: width, height: height))
    ratingView.backgroundColor = BM_Color.colorForType(BM_ColorType.ColorWhiteTransparent)
    ratingView.addSubview(activeRatingImageView)
    ratingView.addSubview(inactiveRatingImageView)

    return ratingView.capture()
}

BM_ImageHelper.swift:

import UIKit

class BM_ImageHelper: NSObject {

    // http://stackoverflow.com/questions/158914/cropping-an-uiimage
    static func crop(image: UIImage, x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) -> UIImage {
        let rect = CGRect(x: x, y: y, width: width, height: height)
        let imageRef = CGImageCreateWithImageInRect(image.CGImage, rect)!
        let croppedImage = UIImage(CGImage: imageRef)
        return croppedImage
    }

    // http://iosdevcenters.blogspot.com/2015/12/how-to-resize-image-in-swift-in-ios.html
    static func resize(image: UIImage, targetSize: CGSize) -> UIImage {
        let size = image.size
        let widthRatio  = targetSize.width  / image.size.width
        let heightRatio = targetSize.height / image.size.height

        // Figure out what our orientation is, and use that to form the rectangle
        var newSize: CGSize

        if(widthRatio > heightRatio) {
            newSize = CGSizeMake(size.width * heightRatio, size.height * heightRatio)
        } else {
            newSize = CGSizeMake(size.width * widthRatio,  size.height * widthRatio)
        }

        // This is the rect that we've calculated out and this is what is actually used below
        let rect = CGRectMake(0, 0, newSize.width, newSize.height)

        // Actually do the resizing to the rect using the ImageContext stuff
        UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
        image.drawInRect(rect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage
    }
}

extension UIView {

    // http://stackoverflow.com/a/34895760/897733
    func capture() -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.frame.size, self.opaque, UIScreen.mainScreen().scale)
        self.layer.renderInContext(UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return image
    }

}

我调用该函数(假设需要填充的图像是 ratingImage):

self.ratingImage.image =
    BM_RatingHelper.getRatingImageBasedOnRating(3.7, width: 100.0, height: 20.0)

代码运行完美,但合并后的图像质量太低,尽管我使用了高质量图像。这是 3.7 评级的图像:

enter image description here

我应该怎么做才能在不损失原始质量的情况下合并图像?谢谢。

最佳答案

在您的 BM_ImageHelper.resize 方法中,它给出了比例 1.0。它应该是设备的屏幕比例。

改成

UIGraphicsBeginImageContextWithOptions(newSize, false,  UIScreen.mainScreen().scale)

更新

同时更改裁剪方法以解决比例问题,例如

static func crop(image: UIImage, x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) -> UIImage {
    let transform = CGAffineTransformMakeScale(image.scale, image.scale)
    let rect = CGRect(x: x, y: y, width: width, height: height)
    let transformedCropRect = CGRectApplyAffineTransform(rect, transform);
    let imageRef = CGImageCreateWithImageInRect(image.CGImage, transformedCropRect)!
    let croppedImage = UIImage(CGImage: imageRef, scale: image.scale, orientation: image.imageOrientation)

    return croppedImage
}

关于ios - 调整大小和裁剪 2 个图像影响原始图像质量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35788458/

相关文章:

ios - 如何在Expo中更新iOS SDK版本

ios - UIImage.DrawInRect 导致错误/通知

swift - 从远程 LSR 文件创建 UIImage

swift - Childadded 检索一个 key

ios - 让 Firebase Cloud 消息传递快速运行

ios - 在 Swift 3 中获取 Google Drive iOS 基本目录中的文件夹列表?

ios - 正确裁剪和缩放 UIImage

c# - 我可以在 Xamarin 上使用 WPF 的全屏 UI 吗?

ios - 如何在 iOS App Bundle 中创建非本地化资源

iPhone - NSDate 格式 : strange values for times and timezones