简体   繁体   English

在 UIImage 中改变只是 .scale?

[英]Changing JUST .scale in UIImage?

Here, I'm creating a typical graphic (it's full-screen size, on all devices) on the fly...在这里,我正在动态创建一个典型的图形(它是全屏尺寸,在所有设备上)...

func buildImage()->UIImage
        {
        let wrapperA:UIView = say, a picture
        let wrapperB:UIView = say, some text to go on top
                
        let mainSize = basicImage.bounds.size
        
        UIGraphicsBeginImageContextWithOptions(mainSize, false, 0.0)
        
        basicImage.drawHierarchy(in: basicImage.bounds, afterScreenUpdates:true)
        wrapperA.drawHierarchy(in: wrapperA.bounds, afterScreenUpdates:true)
        wrapperB.drawHierarchy(in: wrapperB.bounds, afterScreenUpdates: true)
        
        let result:UIImage? = UIGraphicsGetImageFromCurrentImageContext()
        
        UIGraphicsEndImageContext()
        
        // so we've just created a nice big image for some reason,
        // no problem so far

        print( result?.scale  )
        
        // I want to change that image to have a scale of 1.
        // I don't know how to do that, so I actually just
        // make a new identical one, with scale of 1
        
        let resultFixed:UIImage = UIImage(cgImage: result!.cgImage!,
                            scale: 1.0,
                            orientation: result!.imageOrientation)
        
        print( resultFixed.scale )
        
        print("Let's use only '1-scale' images to upload to things like Instagram")
        
        // return result
        return resultFixed
        
        // be sure to ask on SO if there's a way to
        // just "change the scale" rather than make new.
        }

I need the final image to be .scale of 1 - but .scale is a read only property.我需要最终图像的.scale为 1 - 但.scale是只读属性。

The only thing I know how to do is make a whole new image copy ... but set the scale to 1 as it's being created.我唯一知道如何做的是制作一个全新的图像副本……但在创建时将比例设置为 1。

Is there a better way?有没有更好的办法?


Handy tip -小贴士——

This was motivated by: say you're saving a large image to the user's album, and also allowing UIActivityViewController so as to post to (example) Instagram.这是出于以下原因:假设您将大图像保存到用户的相册,并且还允许 UIActivityViewController 发布到(示例)Instagram。 As a general rule, it seems to be best to make the scale 1 before sending to (example) Instagram;作为一般规则,在发送到(示例)Instagram 之前,最好将比例设为 1; if the scale is say 3 you actually just get the top-left 1/3 of the image on your Instagram post.如果比例是 3,您实际上只是在 Instagram 帖子中获得图像的左上角 1/3。 In terms of saving it to the iOS photo album, it does seem to be harmless (perhaps, better in some ways) to set the scale to 1. (I only say "better" as, if the image is, example, ultimately say emailed to a friend on PC, it can cause less confusion if the scale is 1.) Interestingly though, if you just use the iOS Photos album, and take a scale 2 or 3 image, and share it to Instagram: it does in fact appear properly on Instagram!在将它保存到 iOS 相册方面,将比例设置为 1 似乎是无害的(也许在某些方面更好)。(我只说“更好”,因为如果图像是,例如,最终说通过电子邮件发送给 PC 上的朋友,如果比例为 1,则可以减少混淆。)但有趣的是,如果您只使用 iOS 相册,并拍摄比例为 2 或 3 的图像,然后将其分享到 Instagram:实际上确实如此正确出现在 Instagram 上! (perhaps Apple's Photos indeed knows it os best to make it scale 1, before sending it to somewhere like Instagram!). (也许 Apple 的照片确实知道在将其发送到 Instagram 之类的地方之前最好将其缩放为 1!)。

As you say, the scale property of UIImage is read-only – therefore you cannot change it directly. 正如您所说, UIImagescale属性是只读的 - 因此您无法直接更改它。

However, using UIImage 's init(cgImage:scale:orientation) initialiser doesn't really copy the image – the underlying CGImage that it's wrapping (which contains the actual bitmap data) is still the same instance. 但是,使用UIImageinit(cgImage:scale:orientation)初始化器并不真正复制图像 - 它包装的底层CGImage (包含实际的位图数据)仍然是同一个实例。 It's only a new UIImage wrapper that is created. 它只是一个新的UIImage包装器。

Although that being said, you could cut out the intermediate UIImage wrapper in this case by getting the CGImage from the context directly through CGContext 's makeImage() method. 虽然如此,在这种情况下,您可以通过直接通过CGContextmakeImage()方法从上下文中获取CGImage来剪切中间UIImage包装器。 For example: 例如:

func buildImage() -> UIImage? {

    // ...

    let mainSize = basicImage.bounds.size

    UIGraphicsBeginImageContextWithOptions(mainSize, false, 0.0)
    defer {
        UIGraphicsEndImageContext()
    }

    // get the current context
    guard let context = UIGraphicsGetCurrentContext() else { return nil }

    // -- do drawing here --

    // get the CGImage from the context by calling makeImage() – then wrap in a UIImage
    // through using Optional's map(_:) (as makeImage() can return nil)
    // by default, the scale of the UIImage is 1.
    return context.makeImage().map(UIImage.init(cgImage:))
}

顺便说一句,您可以更改结果图像的比例,从而创建新图像

let newScaleImage = UIImage(cgImage: oldScaleImage.cgImage!, scale: 1.0, orientation: oldScaleImage.imageOrientation)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM