Search code examples
objective-ccocoansimage

Cocoa, objective-c how to resize a png image?


I'm new to cocoa and what I'm trying to do is resize a NSImage, but it looks like I'm doing something wrong as my image's don't get resized. I had a look at the other questions and this approach looked like it should work:

- (void)scaleIcons:(NSString *)outputPath{
NSImage *anImage;
NSSize imageSize;
NSString *finalPath;

anImage = [self image];

imageSize = [anImage size];
imageSize.width = 512;
imageSize.height = 512;
[anImage setSize:imageSize];

finalPath = [outputPath stringByAppendingString:@"/icon_512x512.png"];

NSData *imageData = [anImage TIFFRepresentation];
NSBitmapImageRep *rep = [NSBitmapImageRep imageRepWithData:imageData];
NSData *dataToWrite = [rep representationUsingType:NSPNGFileType properties:nil];
[dataToWrite writeToFile:finalPath atomically:NO];
}

everything works, except the fact that my images don't get scaled. Could someone help a bit?


Solution

  • So your code snippet is omitting the operations actually required to scale/transform the image. Pass your image through a method such as this one before you try to save it:

    - (NSImage *)scaleImage:(NSImage *)image toSize:(NSSize)targetSize
    {
      if ([image isValid])
      {
        NSSize imageSize = [image size];
        float width  = imageSize.width;
        float height = imageSize.height;
        float targetWidth  = targetSize.width;
        float targetHeight = targetSize.height;
        float scaleFactor  = 0.0;
        float scaledWidth  = targetWidth;
        float scaledHeight = targetHeight;
    
        NSPoint thumbnailPoint = NSZeroPoint;
    
        if (!NSEqualSizes(imageSize, targetSize))
        {
          float widthFactor  = targetWidth / width;
          float heightFactor = targetHeight / height;
    
          if (widthFactor < heightFactor)
          {
            scaleFactor = widthFactor;
          }
          else
          {
            scaleFactor = heightFactor;
          }
    
          scaledWidth  = width  * scaleFactor;
          scaledHeight = height * scaleFactor;
    
          if (widthFactor < heightFactor)
          {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
          }
    
          else if (widthFactor > heightFactor)
          {
            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
          }
    
        NSImage *newImage = [[NSImage alloc] initWithSize:targetSize];
    
        [newImage lockFocus];
    
         NSRect thumbnailRect;
         thumbnailRect.origin = thumbnailPoint;
         thumbnailRect.size.width = scaledWidth;
         thumbnailRect.size.height = scaledHeight;
    
         [image drawInRect:thumbnailRect
                  fromRect:NSZeroRect
                 operation:NSCompositeSourceOver
                  fraction:1.0];
    
        [newImage unlockFocus];
      }
    
      return newImage;
    }
    

    If you integrate this into your existing method:

    - (void)scaleIcons:(NSString *)outputPath{
    
        NSSize outputSize = NSMakeSize(512.0f,512.0f);
        NSImage *anImage  = [self scaleImage:[self image] toSize:outputSize];
    
        NSString *finalPath = [outputPath stringByAppendingString:@"/icon_512x512.png"];
        NSData *imageData = [anImage TIFFRepresentation];
        NSBitmapImageRep *rep = [NSBitmapImageRep imageRepWithData:imageData];
        NSData *dataToWrite = [rep representationUsingType:NSPNGFileType properties:nil];
       [dataToWrite writeToFile:finalPath atomically:NO];
    }