Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CoreGraphics resizing function from iOS (UIImage) to MacOS (NSImage) #46

Open
alelordelo opened this issue Apr 22, 2021 · 6 comments
Open

Comments

@alelordelo
Copy link

Hi Matthias,

Were you able to run your helper functions on MacOS? I replaced iOS (UIImage) to MacOS (NSImage), and got almost everything to work... Only the cgImage.bitsPerPixel part I didn't find a MacOS equivalent.

Have you tried running it on MacOS?

Cheers from Sweden!
Alex

https://stackoverflow.com/questions/67202976/coregraphics-resizing-function-from-ios-uiimage-to-macos-nsimage

What I did:
Code bellow

Problem:
Getting error on this line of code: let bytesPerPixel = cgImage.bitsPerPixel / bitsPerComponent

Error:
Value of type '(UnsafeMutablePointer?, NSGraphicsContext?, [NSImageRep.HintKey : Any]?) -> CGImage?' (aka '(Optional, Optional, Optional<Dictionary<NSImageRep.HintKey, Any>>) -> Optional') has no member 'bitsPerPixel'

iOS: UIImage

extension UIImage {
    
    // Resizeing using CoreGraphics
    func resize(to size:CGSize) -> UIImage? {
        
        let cgImage = self.cgImage!

        let destWidth = Int(size.width)
        let destHeight = Int(size.height)
        let bitsPerComponent = 8
        let bytesPerPixel = cgImage.bitsPerPixel / bitsPerComponent
        let destBytesPerRow = destWidth * bytesPerPixel
        
        let context = CGContext(data: nil,
                                width: destWidth,
                                height: destHeight,
                                bitsPerComponent: bitsPerComponent,
                                bytesPerRow: destBytesPerRow,
                                space: cgImage.colorSpace!,
                                bitmapInfo: cgImage.bitmapInfo.rawValue)!
        context.interpolationQuality = .high
        context.draw(cgImage, in: CGRect(origin: CGPoint.zero, size: size))
        return context.makeImage().flatMap { UIImage(cgImage: $0) }
    }
}

MacOS: NSImage

extension NSImage {
    
    // Resizeing using CoreGraphics
    func resize(to size:CGSize) -> NSImage? {
        
        let cgImage = self.cgImage

        let destWidth = Int(size.width)
        let destHeight = Int(size.height)
        let bitsPerComponent = 8
        let bytesPerPixel = cgImage.bitsPerPixel / bitsPerComponent
        let destBytesPerRow = destWidth * bytesPerPixel
        
        let context = CGContext(data: nil,
                                width: destWidth,
                                height: destHeight,
                                bitsPerComponent: bitsPerComponent,
                                bytesPerRow: destBytesPerRow,
                                space: cgImage.colorSpace!,
                                bitmapInfo: cgImage.bitmapInfo.rawValue)!
        context.interpolationQuality = .high
        context.draw(cgImage, in: CGRect(origin: CGPoint.zero, size: size))
        return context.makeImage().flatMap { NSImage(cgImage: $0) }
    }
}
@hollance
Copy link
Owner

CGImage should work both on iOS and macOS. It looks like you forgot to unwrap self.cgImage, since the error message is about using an optional, not about CGImage itself.

@alelordelo
Copy link
Author

Thanks Matthias!

I unwrapped self.cgImage, but got same error.

Looks like bitsPerPixel is only available for iOS... : /

Any idea what would be MacOS equivalent to bitsPerPixel?

/* Return the number of bits/pixel of `image'. */

**@available(iOS 2.0, *)**
public var bitsPerPixel: Int { get }

Value of type '(UnsafeMutablePointer?, NSGraphicsContext?, [NSImageRep.HintKey : Any]?) -> CGImage?' (aka '(Optional<UnsafeMutablePointer>, Optional, Optional<Dictionary<NSImageRep.HintKey, Any>>) -> Optional') has no member 'bitsPerPixel'

@hollance
Copy link
Owner

Ah I see what's going on, NSImage.cgImage is not a property but a function. Namely the function:

func cgImage(forProposedRect proposedDestRect: UnsafeMutablePointer<NSRect>?, context referenceContext: NSGraphicsContext?, hints: [NSImageRep.HintKey : Any]?) -> CGImage?

You're trying to call bitsPerPixel on the function itself, not on the CGImage that comes out of the function. ;-)

@alelordelo
Copy link
Author

thanks for spotting that Matthias! : )

Weird that UIImage.cgImage is a property, and NSImage.cgImage is a function.

Im a bit lost here... Do you have any idea what the final resize function would look like for MacOS?

@hollance
Copy link
Owner

Check out this StackOverflow answer: https://stackoverflow.com/questions/11949250/how-to-resize-nsimage

@alelordelo
Copy link
Author

Thanks again!

Finally made it work with some help from Apple, this is the final function in case you also need. : )

// Resizeing using CoreGraphics
  func resize(to size:CGSize) -> NSImage? {
       
       let cgImage: CGImage = self.cgImage( forProposedRect: nil,  context: nil, hints: nil)!

       let destWidth = Int(size.width)
       let destHeight = Int(size.height)
       let bitsPerComponent = 8
       let bytesPerPixel = cgImage.bitsPerPixel / bitsPerComponent
       let destBytesPerRow = destWidth * bytesPerPixel
       
       let context = CGContext(data: nil,
                               width: destWidth,
                               height: destHeight,
                               bitsPerComponent: bitsPerComponent,
                               bytesPerRow: destBytesPerRow,
                               space: cgImage.colorSpace!,
                               bitmapInfo: cgImage.bitmapInfo.rawValue)!
       context.interpolationQuality = .high
       context.draw(cgImage, in: CGRect(origin: CGPoint.zero, size: size))
       return context.makeImage().flatMap { NSImage(cgImage: $0, size: NSSize(width: 1024, height: 1024)) }
   }
   

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants