GuiDupas
GuiDupas

Reputation: 1701

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.

Upvotes: 0

Views: 1291

Answers (1)

GuiDupas
GuiDupas

Reputation: 1701

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!
}

Upvotes: 0

Related Questions