objective-cmacosnsimagensimageviewnsbitmapimagerep

Scale Up NSImage and Save


I would like to scale up an image that's 64px to make it 512px (Even if it's blurry or pixelized)

I'm using this to get the image from my NSImageView and save it:

NSData *customimageData = [[customIcon image] TIFFRepresentation];
    NSBitmapImageRep *customimageRep = [NSBitmapImageRep imageRepWithData:customimageData];


    customimageData = [customimageRep representationUsingType:NSPNGFileType properties:nil];



    NSString* customBundlePath = [[NSBundle mainBundle] pathForResource:@"customIcon" ofType:@"png"];
    [customimageData writeToFile:customBundlePath atomically:YES];

I've tried setSize: but it still saves it 64px.

Thanks in advance!


Solution

  • You can't use the NSImage's size property as it bears only an indirect relationship to the pixel dimensions of an image representation. A good way to resize pixel dimensions is to use the drawInRect method of NSImageRep:

     - (BOOL)drawInRect:(NSRect)rect
    

    Draws the entire image in the specified rectangle, scaling it as needed to fit.

    Here is a image resize method (creates a new NSImage at the pixel size you want).

    - (NSImage*) resizeImage:(NSImage*)sourceImage size:(NSSize)size
    {
    
        NSRect targetFrame = NSMakeRect(0, 0, size.width, size.height);     
        NSImage* targetImage = nil;
        NSImageRep *sourceImageRep =
        [sourceImage bestRepresentationForRect:targetFrame
                                       context:nil
                                         hints:nil];
    
        targetImage = [[NSImage alloc] initWithSize:size];
    
        [targetImage lockFocus];
        [sourceImageRep drawInRect: targetFrame];
        [targetImage unlockFocus];
    
    return targetImage; 
    }
    

    It's from a more detailed answer I gave here: NSImage doesn't scale

    Another resize method that works is the NSImage method drawInRect:fromRect:operation:fraction:respectFlipped:hints

    - (void)drawInRect:(NSRect)dstSpacePortionRect 
              fromRect:(NSRect)srcSpacePortionRect 
             operation:(NSCompositingOperation)op 
              fraction:(CGFloat)requestedAlpha 
        respectFlipped:(BOOL)respectContextIsFlipped 
                 hints:(NSDictionary *)hints
    

    The main advantage of this method is the hints NSDictionary, in which you have some control over interpolation. This can yield widely differing results when enlarging an image. NSImageHintInterpolation is an enum that can take one of five values…

        enum {
           NSImageInterpolationDefault = 0,
           NSImageInterpolationNone = 1,
           NSImageInterpolationLow = 2,
           NSImageInterpolationMedium = 4,
           NSImageInterpolationHigh = 3
        };
        typedef NSUInteger NSImageInterpolation;
    

    Using this method there is no need for the intermediate step of extracting an imageRep, NSImage will do the right thing...

    - (NSImage*) resizeImage:(NSImage*)sourceImage size:(NSSize)size
    {
        NSRect targetFrame = NSMakeRect(0, 0, size.width, size.height);
        NSImage*  targetImage = [[NSImage alloc] initWithSize:size];
    
        [targetImage lockFocus];
    
        [sourceImage drawInRect:targetFrame
                       fromRect:NSZeroRect       //portion of source image to draw 
                      operation:NSCompositeCopy  //compositing operation
                       fraction:1.0              //alpha (transparency) value
                 respectFlipped:YES              //coordinate system
                          hints:@{NSImageHintInterpolation:
         [NSNumber numberWithInt:NSImageInterpolationLow]}];
    
        [targetImage unlockFocus];
    
        return targetImage;
    }