Return an updated UIImageView

SayI have a function that will receive a UIImage as an argument, perform the logic inside it and then return it updated
So I came up with something like this:

  func processImage(image: UIImage?) -> UIImage? {
         if let image = image, let cgImage = image.cgImage {
            let width = cgImage.width
            let height = cgImage.height

            let colorSpace = CGColorSpaceCreateDeviceRGB()
            let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)

            if let context = CGContext(data: nil,
                                       width: width,
                                       height: height,
                                       bitsPerComponent: 8,
                                       bytesPerRow: 4 * width,
                                       space: colorSpace,
                                       bitmapInfo: bitmapInfo.rawValue) {

                context.draw(cgImage, in: CGRect(x: 0, y: 0, width: CGFloat(width), height: CGFloat(height)))

                if let data = context.data {
                    let buffer = data.bindMemory(to: UInt8.self, capacity: width * height * 4)

                    for i in 0..<(width * height) {
                        let pixelIndex = i * 4
                        let red = buffer[pixelIndex]
                        let green = buffer[pixelIndex + 1]
                        let blue = buffer[pixelIndex + 2]

                        if isSystemGrayPixel(red: red, green: green, blue: blue) {
                            // Convert systemGray to systemPink
                            buffer[pixelIndex] = 255  // R component
                            buffer[pixelIndex + 1] = 182  // G component
                            buffer[pixelIndex + 2] = 193  // B component
                        }
                    }

                    if let modifiedCGImage = context.makeImage() {
                        let processedImage = UIImage(cgImage: modifiedCGImage)
                        return processedImage
                    }
                }
            }
        }

        return image
    }

insde it I have called a helper function that will conditionally check if it contains .systemGrey and if so than change it as I

    func isSystemGrayPixel(red: UInt8, green: UInt8, blue: UInt8) -> Bool {
        let systemGrayColor = UIColor.systemBlue
        let ciSystemGrayColor = CIColor(color: systemGrayColor)

       
        let tolerance: CGFloat = 10.0 / 255.0

        let redDiff = abs(ciSystemGrayColor.red - CGFloat(red) / 255.0)
        let greenDiff = abs(ciSystemGrayColor.green - CGFloat(green) / 255.0)
        let blueDiff = abs(ciSystemGrayColor.blue - CGFloat(blue) / 255.0)

        return redDiff <= tolerance && greenDiff <= tolerance && blueDiff <= tolerance
    }

When I try to save it into a saveCanvas I will show in the console that the entry is saved but when i try to retrieve it later I will get nil This is my saveCanvas to serve as a reference


  @objc func saveCanvas(_ sender: Any)   {
        guard let canvas = Canvas(name: "", canvas: mainImageView, numOfPages: 0) else {
            return
        }
     
        var savedImageView2 =  UIImageView()
        savedImageView2.image = mainImageView.image?.copy() as? UIImage
        
        let updatedImage = processImage(image: savedImageView2.image)
        
        canvas.canvas.image = updatedImage
      
        // array that stores UIimageView gobally defined
        canvasArray.append(canvas)
        
        if canvasArray.count > 0 {
            canvasArray.forEach{ canvas in
                print("\(canvas.canvas == savedImageView )")

            print("clicked button \( canvasArray) ")
                      
            }
        }
    }

I am expecting to retrieve each iteration of canvasArray when i call it later in another function(which worked fine before I created the processImage function) . Like I said the purpose of processImage is to check if my UIImage contains .systemGrey and i so returned updated as I defined inside my isSystemGrayPixel function. Is there anything you might consider I do different rather do in my processImage to make it work as expected?

Replies

Does this help to solve your problem?

https://codermite.com/t/issue-with-saving-processed-images-in-swift-uiimage-becomes-nil

  • @Paradigm777 Well kinda but I relize that the issue actually lies on a resetPressed function which sets the 'mainUIView' to nil. This function is intended to provide a clean canvas for subsequent operations but inadvertently results in the content stored in the 'canvasArray' being set to nil as well. I tried to avoid this by saving a copy of it in my saveCanvas function in this segment savedImageView2.image = mainImageView.image?.copy() as? UIImage

  • Just for reference this is my resetPressed function

      @objc func resetPressed(_ sender: Any) {
            
            mainImageView.image = nil
            
        }
    

    Any Ideas or suggestions on how to keep my resetPressed from affecting what is being saved in my saveCanvas function of my code would be much appreciated!

  • Never mind I found out that the issue lies on how my savedImageView2 is initialize inside my saveCanvas function. All I had to do was to store the copy of mainImageView inside if the UIImageView(image: mainImageView.image?.copy() as? UIImage) object just like that instead of doing it separately.

Add a Comment

As Paradigm777 explained, problem is likely in

canvas.canvas.image = updatedImage

You copy the reference (pointer) of the UIImage (not UIImageView) , not the content. Hence the advice to use copy.

However, could you show complete code so we can try to reproduce ?

Note: a bit confusing (in naming) to have a canvas property inside canvas…