简体   繁体   中英

Generated CGImage always blurry

So I've been working on a little "drawing" app where the user can draw images onto a grid canvas (creating pixel art, basically). I wanted to create a function that exports this canvas (Consider this to be an array of UIColor s, which I then convert into a RawPixel , a simple color container that I need because the actual RGB values need to be UInt8 so I can save it to a CGImage).

So far so good. What I wanted to do was to give the user the option to save their current drawing as an image to Photos. And here's where the issue begins. This is the image that is drawn on screen:

实际图纸

But when I export this, this is how the image looks like... super blurry and very tiny. Now, with the tiny-ness I can work with, but the blurriness I don't know how to fix.

在此处输入图片说明

I have actually taken the generated CGImage and put it in a UIImageView , and set imgViewQR.layer.magnificationFilter = kCAFilterNearest , and then it looked crystal clear. But I want this particular behaviour to persist when I save the drawing to the Photos app. I really don't know where to search for, so any help would be greatly appreciated!!!

This is the method I use to load the "canvas" with the associated colors and how I save it to Photos.

    var rawPixelArray = [RawPixel]()

    guard let canvasColorArray = self.canvasView?.canvas.getPixelColorArray(),
        let canvasWidth = self.canvasView?.canvas.getAmountOfPixelsForWidth(),
        let canvasHeight = self.canvasView?.canvas.getAmountofPixelsForHeight() else {
            return
    }

    canvasColorArray.forEach { (color) in
        let rawPixel = RawPixel(inputColor: color)
        rawPixelArray.append(rawPixel)
    }

    let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
    var data = rawPixelArray
    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
    guard let dataProvider = CGDataProvider(data: NSData(bytes: &data,
                                                         length: data.count * MemoryLayout<RawPixel>.size)
        ) else { return }

    guard let exportedCGImage = CGImage.init(width: canvasWidth, height: canvasHeight, bitsPerComponent: 8, bitsPerPixel: 32, bytesPerRow: canvasWidth * (MemoryLayout<RawPixel>.size), space: rgbColorSpace, bitmapInfo: bitmapInfo, provider: dataProvider, decode: nil, shouldInterpolate: false, intent: .defaultIntent) else {
        print("CGImage could not be created.")
        return
    }

    let exportedUIImage = UIImage(cgImage: exportedCGImage)
    let imageView = UIImageView(image: exportedUIImage)

    UIImageWriteToSavedPhotosAlbum(imageView.image!, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)

Alright, so what I found as a solution in the end is the following (It's kinda a hack, but it works and everything is crystal clear when it comes to pixel edges now PLUS you can actually export it to any size of actual image you want!):

    let exportedUIImage = UIImage(cgImage: exportedCGImage)
    let imageView = UIImageView(image: exportedUIImage)
    imageView.layer.magnificationFilter = kCAFilterNearest
    imageView.frame = CGRect(x: 5, y: 5, width: yourDesiredWidth, height: yourDesiredHeight) 
//just remember to yourDesiredWidth and yourDesiredHeight according to your actual drawing width/drawing height. 

    UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, imageView.isOpaque, 0.0)
    imageView.drawHierarchy(in: imageView.bounds, afterScreenUpdates: true)
    let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

So what I do is, I basically create a (invisible) UIImageView, turn the magnificationFilter to kCAFilterNearest , which generates a crispy, clear image, and then simply screenshot it and save it to Photos.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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