swiftmacosresizensimagensbitmapimagerep

Swift - OSX - resize NSImage data


I am trying to resize a NSImage to use it with parse as a PFFile and I need to change its dimension to reduce its data size it but it is not working. The resized image resizes the width and height inside Swift but it keeps the same dimensions from the original image.

The image is a JPG with 2560 x 1706 and 721 KB.

When I pass it to data it keeps the same dimensions and gos to 5.7 MB

Here is my code:

let fotoNSImage = NSImage(byReferencing: url)

let fotoNSImageRedim = redimensionaNSImage(imagem: fotoNSImage, tamanho: NSSize(width: 200, height: 200))

let fotoNSImageRep = NSBitmapImageRep(data: (fotoNSImageRedim.tiffRepresentation)!)

let fotoNSImagePng = fotoNSImageRep!.representation(using: NSBitmapImageRep.FileType.png, properties: [:])

let fotoProduto = FotoProduto(foto: PFFile(data: fotoNSImagePng!)!, categorias: [])

The method to resize de image:

static func redimensionaNSImage(imagem: NSImage, tamanho: NSSize) -> NSImage {

    var ratio: Float = 0.0
    let imageWidth = Float(imagem.size.width)
    let imageHeight = Float(imagem.size.height)
    let maxWidth = Float(tamanho.width)
    let maxHeight = Float(tamanho.height)

    if (imageWidth > imageHeight) {
        // Landscape
        ratio = maxWidth / imageWidth;
    }
    else {
        // Portrait
        ratio = maxHeight / imageHeight;
    }

    // Calculate new size based on the ratio
    let newWidth = imageWidth * ratio
    let newHeight = imageHeight * ratio

    // Create a new NSSize object with the newly calculated size
    let newSize: NSSize = NSSize(width: Int(newWidth), height: Int(newHeight))

    // Cast the NSImage to a CGImage
    var imageRect: CGRect = CGRect(x: 0, y: 0, width: Int(newWidth), height: Int(newHeight))
    let imageRef = imagem.cgImage(forProposedRect: &imageRect, context: nil, hints: nil)

    // Create NSImage from the CGImage using the new size
    let imageWithNewSize = NSImage(cgImage: imageRef!, size: newSize)

    // Return the new image
    return imageWithNewSize
}

I have already tried the following approaches without success.

1 - Change the pixelWide and pixelHigh directly on fotoNSImagePng:

fotoNSImageRep?.pixelsWide = 200
fotoNSImageRep?.pixelsHigh = 133

2 - Creating a new NSBitmapImageRep and replace the image representation with it:

let rep = NSBitmapImageRep(bitmapDataPlanes: nil,
                           pixelsWide: 200,
                           pixelsHigh: 133,
                           bitsPerSample: 8,
                           samplesPerPixel: 4,
                           hasAlpha: true,
                           isPlanar: false,
                           colorSpaceName: NSDeviceRGBColorSpace,
                           bytesPerRow: Int(newSize.width * 4),
                           bitsPerPixel: 32)

3 - Follow this approach: How to resize - resample - change file size - NSImage

4 - Change the NSBitmapImageRep size values:

fotoNSImageRep?.size.width = 200
fotoNSImageRep?.size.height = 133

Nothing has worked so far.


Solution

  • I have modified the method that resizes the image

    static func redimensionaNSImage(imagem: NSImage, tamanho: NSSize) -> NSImage {
    
        var ratio: Float = 0.0
        let imageWidth = Float(imagem.size.width)
        let imageHeight = Float(imagem.size.height)
        let maxWidth = Float(tamanho.width)
        let maxHeight = Float(tamanho.height)
    
        // Get ratio (landscape or portrait)
        if (imageWidth > imageHeight) {
            // Landscape
            ratio = maxWidth / imageWidth;
        }
        else {
            // Portrait
            ratio = maxHeight / imageHeight;
        }
    
        // Calculate new size based on the ratio
        let newWidth = imageWidth * ratio
        let newHeight = imageHeight * ratio
    
        let imageSo = CGImageSourceCreateWithData(imagem.tiffRepresentation! as CFData, nil)
        let options: [NSString: NSObject] = [
            kCGImageSourceThumbnailMaxPixelSize: max(imageWidth, imageHeight) * ratio as NSObject,
            kCGImageSourceCreateThumbnailFromImageAlways: true as NSObject
        ]
        let size1 = NSSize(width: Int(newWidth), height: Int(newHeight))
        let scaledImage = CGImageSourceCreateThumbnailAtIndex(imageSo!, 0, options as CFDictionary).flatMap {
            NSImage(cgImage: $0, size: size1)
        }
    
        return scaledImage!
    }