-2

Im using the following extension method to resize an image.When it comes to large resolution images the output size remains 1000x1000 pixels even when I set the output size to 500x500 pixels

extension NSImage {
    func resizeImage(width: CGFloat, _ height: CGFloat) -> NSImage {
        let img = NSImage(size: CGSize(width:width, height:height))

        img.lockFocus()
        let ctx = NSGraphicsContext.current
        ctx?.imageInterpolation = .high
        self.draw(in: NSMakeRect(0, 0, width, height), from: NSMakeRect(0, 0, size.width, size.height), operation: .copy, fraction: 1)
        img.unlockFocus()

        return img
    }

What im I doing wrong? Please advice

UPDATE:

//SAVING 



for x in fileArray  {


            var image = NSImage(contentsOf:x)!
            let imageURL=outdir+"/"+"xxx"
            image=image.resizeImage(width: CGFloat(rwidth), CGFloat(rheight))
            saveimage(xdata: image, imageURL: imageURL, format: fileformat)

            }

func saveimage(xdata:NSImage,imageURL:String,format:String) -> Bool
    {


        let bMImg = NSBitmapImageRep(data: (xdata.tiffRepresentation)!)
        switch format {
        case ".png":
            let filepath=URL(fileURLWithPath: imageURL+".png")
            let dataToSave = bMImg?.representation(using: NSBitmapImageRep.FileType.png, properties: [NSBitmapImageRep.PropertyKey.compressionFactor : 1])
            do
            {
                try  dataToSave?.write(to: filepath)
                return true

            } catch
            {
                return false
            }
        case ".jpg":
            let filepath=URL(fileURLWithPath: imageURL+".jpg")
             let dataToSave = bMImg?.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [NSBitmapImageRep.PropertyKey.compressionFactor : 1])
            do
            {
                try  dataToSave?.write(to:filepath)
                return true

            } catch
            {
               return false
            }
        case ".tif":
            let filepath=URL(fileURLWithPath: imageURL+".tif")
            let dataToSave = bMImg?.representation(using: NSBitmapImageRep.FileType.tiff, properties: [NSBitmapImageRep.PropertyKey.compressionFactor : 1])
            do
            {
                try  dataToSave?.write(to:filepath)
                return true

            } catch
            {
                return false
            }
        case ".bmp":
            let filepath=URL(fileURLWithPath: imageURL+".bmp")
            let dataToSave = bMImg?.representation(using: NSBitmapImageRep.FileType.bmp, properties: [NSBitmapImageRep.PropertyKey.compressionFactor : 1])
            do
            {
                try  dataToSave?.write(to:filepath)
                return true

            } catch
            {
                return false
            }
        case ".gif":
             let filepath=URL(fileURLWithPath: imageURL+".gif")
            let dataToSave = bMImg?.representation(using: NSBitmapImageRep.FileType.gif, properties: [NSBitmapImageRep.PropertyKey.compressionFactor : 1])
            do
            {
                try  dataToSave?.write(to:filepath)
                return true

            } catch
            {
                return false
            }

        default:

            return true
        }

    }
techno
  • 6,100
  • 16
  • 86
  • 192
  • Can't reproduce. I ran this code: `let img1 = NSImage(named: NSImage.Name(rawValue: "marsSurface.jpg")); print(img1!.size); let img2 = img1?.resizeImage(width: 500, 500); print(img2!.size)` and I got `(2074, 2074)` followed by `(500.0, 500.0)`. – matt Jun 01 '18 at 18:16
  • I also displayed the resulting `img2` in an image view in my interface and it is indeed only 500x500. – matt Jun 01 '18 at 18:20
  • @matt Please see the update.Im referring to the saved image. – techno Jun 01 '18 at 18:25
  • @matt Please try with this image http://files.all-free-download.com//downloadfiles/wallpapers/1920_1200/leonardo_dicaprio_4k_5k_17218.jpg – techno Jun 01 '18 at 18:27
  • Duplicate of https://stackoverflow.com/questions/17507170/how-to-save-png-file-from-nsimage-retina-issues ? – matt Jun 01 '18 at 18:34
  • @matt Guess so, upon removing img.lockfocus() from resize code I get null error when saving image 'Unexpectedly found nil while unwrapping an Optional value' – techno Jun 01 '18 at 18:44
  • Well, the point is simply that you have to downsize in another way, as in this answer: https://stackoverflow.com/a/32106120/341994 – matt Jun 01 '18 at 19:48
  • @matt Thanks ,I will check and get back tomorrow. – techno Jun 01 '18 at 19:49

1 Answers1

0

The problem is that you are not taking into account the scale of the image you're creating.

You have a Retina screen. When you call lockFocus and draw into the resulting graphics context, the graphics context has double-resolution. Thus, a size of 500x500 results in an underlying bitmap of 1000x1000. That doesn't matter for purposes of display; to the extent that it does matter, it's a good thing.

But when you proceed to save the image data to disk, you throw away the knowledge that this is a double-resolution image, and you simply save the bitmap — which is 1000x1000.

You should look at Apple's documentation on how to deal with high-resolution images, e.g. https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/APIs/APIs.html

matt
  • 515,959
  • 87
  • 875
  • 1,141