CGImageDestinationCreateWithData doubles pixel dimension

Viewed 32

If I create a UIImage 'image' from a JPEG file selection in iOS using

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

      let info = convertFromUIImagePickerControllerInfoKeyDictionary(info)

        if let image = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.originalImage)] as? UIImage {
            
           
      }
}

And then create a data object from image using

imageData = image.jpegData(compressionQuality:1.0)

and then add some properties using

func addImageProperties(imageData: Data, properties: CFDictionary) -> Data {                
        if let source = CGImageSourceCreateWithData(imageData as CFData, nil) {
            if let uti = CGImageSourceGetType(source) {
                let destinationData = NSMutableData()
               
                if let destination = CGImageDestinationCreateWithData(destinationData, uti, 1, nil) {
                    CGImageDestinationAddImageFromSource(destination, source, 0, properties)
                    if CGImageDestinationFinalize(destination) == false {
                        return imageData // return input data if error
                    }
                    let destinationDataResult = destinationData as Data
                    return destinationDataResult
                }
            }
        }
        return imageData // return input data if error
    }

and then save the data to a file using

func saveImageDataAsImage(_ data: Data) {
        var newImageIdentifier: String!

        PHPhotoLibrary.shared().performChanges{
          
                let assetRequest = PHAssetCreationRequest.forAsset()
                assetRequest.addResource(with: .photo, data: data, options: nil)
                newImageIdentifier = assetRequest.placeholderForCreatedAsset!.localIdentifier

        } completionHandler: { (success, error) in
            DispatchQueue.main.async(execute: {
                if success, let newAsset = PHAsset.fetchAssets(withLocalIdentifiers: [newImageIdentifier], options: nil).firstObject {
                    // ...
                } else {
                    // ...
                }
            })

        }
    }

The resulting file has twice the width and height in pixels of the original selected file. How can I retain the original file width and height while adding the required metadata?

1 Answers

The loaded image (with UIImage.scale = 1.0) was being processed before saved in the following code, which reset the UIImage.scale value to 2.0. Code to reset UIImage.scale after this it did not change the image.cgImage size, but changing the line let scale = UIScreen.main.scale to let scale:CGFloat = 1.0 in the code resulted in the saved image having the same pixel dimensions as the input image.

func textToImage(drawText: String, inImage: UIImage, atPoint: CGPoint, textColor: UIColor, textFont: UIFont, backColor: UIColor) -> UIImage{

    // Setup the font specific variables
    //var textColor = UIColor.white
    //var textFont = UIFont(name: "Helvetica Bold", size: 12)!

    // Setup the image context using the passed image
    let scale = UIScreen.main.scale// change to  let scale:CGFloat = 1.0 to fix problem
    UIGraphicsBeginImageContextWithOptions(inImage.size, false, scale)

    // Setup the font attributes that will be later used to dictate how the text should be drawn
    let textFontAttributes = [
        NSAttributedString.Key.font: textFont,
        NSAttributedString.Key.foregroundColor: textColor,
        NSAttributedString.Key.backgroundColor: backColor,
    ]

    // Put the image into a rectangle as large as the original image
    inImage.draw(in: CGRect(x: 0, y: 0, width: inImage.size.width, height: inImage.size.height))

    // Create a point within the space that is as bit as the image
    var rect = CGRect(x: atPoint.x, y: atPoint.y, width: inImage.size.width, height: inImage.size.height)

    // Draw the text into an image
    drawText.draw(in: rect, withAttributes: textFontAttributes)

    // Create a new image out of the images we have created
    var newImage = UIGraphicsGetImageFromCurrentImageContext()

    // End the context now that we have the image we need
    UIGraphicsEndImageContext()

    //Pass the image back up to the caller
    return newImage!

}
Related