title: How To Save PNG file From NSImage (retina issues) The Right Way?
body: <p>I am trying to save each image in an array as a .PNG file (also as the right size, without scaling up because of retina mac dpi issues) and can't seem to find a solution. NONE of the solutions at <a href="https://stackoverflow.com/questions/17507170/how-to-save-png-file-from-nsimage-retina-issues">How to save PNG file from NSImage (retina issues)</a> seem to be working for me. I've tried each one and each of them would still save a 72x72 file as 144x144 in retina .etc.</p>
  
  <p>More specifically I am looking for an NSImage category (yes, I am working in the Mac environment)</p>
  
  <p>I am trying to have the user Choose a directory to save them in and execute the saving of the images from array like this:</p>
  
  <pre><code>- (IBAction)saveImages:(id)sender {
      // Prepare Images that are checked and put them in an array
      [self prepareImages];
  
      if ([preparedImages count] == 0) {
          NSLog(@"We have no preparedImages to save!");
          NSAlert *alert = [[NSAlert alloc] init];
          [alert setAlertStyle:NSInformationalAlertStyle];
          [alert setMessageText:NSLocalizedString(@"Error", @"Save Images Error Text")];
          [alert setInformativeText:NSLocalizedString(@"You have not selected any images to create.", @"Save Images Error Informative Text")];
  
          [alert beginSheetModalForWindow:self.window
                            modalDelegate:self
                          didEndSelector:@selector(testDatabaseConnectionDidEnd:returnCode:
                                                     contextInfo:)
                              contextInfo:nil];
          return;
      } else {
          NSLog(@"We have prepared %lu images.", (unsigned long)[preparedImages count]);
      }
  
      // Save Dialog
      // Create a File Open Dialog class.
      //NSOpenPanel* openDlg = [NSOpenPanel openPanel];
      NSSavePanel *panel = [NSSavePanel savePanel];
  
      // Set array of file types
      NSArray *fileTypesArray;
      fileTypesArray = [NSArray arrayWithObjects:@"jpg", @"gif", @"png", nil];
  
      // Enable options in the dialog.
      //[openDlg setCanChooseFiles:YES];
      //[openDlg setAllowedFileTypes:fileTypesArray];
      //[openDlg setAllowsMultipleSelection:TRUE];
      [panel setNameFieldStringValue:@"Images.png"];
      [panel setDirectoryURL:directoryPath];
  
  
      // Display the dialog box.  If the OK pressed,
      // process the files.
      [panel beginWithCompletionHandler:^(NSInteger result) {
  
          if (result == NSFileHandlingPanelOKButton) {
              NSLog(@"OK Button!");
              // create a file manager and grab the save panel's returned URL
              NSFileManager *manager = [NSFileManager defaultManager];
              directoryPath = [panel URL];
              [[self directoryLabel] setStringValue:[NSString stringWithFormat:@"%@", directoryPath]];
  
              // then copy a previous file to the new location
  
              // copy item at URL was self.myURL
              // copy images that are created from array to this path
  
  
              for (NSImage *image in preparedImages) {
  #warning Fix Copy Item At URL to copy image from preparedImages array to save each one
                  NSString *imageName = image.name;
                  NSString *imagePath = [[directoryPath absoluteString] stringByAppendingPathComponent:imageName];
  
                  //[manager copyItemAtURL:nil toURL:directoryPath error:nil];
                  NSLog(@"Trying to write IMAGE: %@ to URL: %@", imageName, imagePath);
                  //[image writePNGToURL:[NSURL URLWithString:imagePath] outputSizeInPixels:image.size error:nil];
                  [self saveImage:image atPath:imagePath];
              }
              //[manager copyItemAtURL:nil toURL:directoryPath error:nil];
  
  
          }
      }];
  
      [preparedImages removeAllObjects];
  
      return;
  
  }
  </code></pre>
  
  <p>one user attempted to answer his by using this NSImage category but it does not produce any file or PNG for me.</p>
  
  <pre><code>@interface NSImage (SSWPNGAdditions)
  
  - (BOOL)writePNGToURL:(NSURL*)URL outputSizeInPixels:(NSSize)outputSizePx error:(NSError*__autoreleasing*)error;
  
  @end
  
  @implementation NSImage (SSWPNGAdditions)
  
  - (BOOL)writePNGToURL:(NSURL*)URL outputSizeInPixels:(NSSize)outputSizePx error:(NSError*__autoreleasing*)error
  {
      BOOL result = YES;
      NSImage* scalingImage = [NSImage imageWithSize:[self size] flipped:[self isFlipped] drawingHandler:^BOOL(NSRect dstRect) {
          [self drawAtPoint:NSMakePoint(0.0, 0.0) fromRect:dstRect operation:NSCompositeSourceOver fraction:1.0];
          return YES;
      }];
      NSRect proposedRect = NSMakeRect(0.0, 0.0, outputSizePx.width, outputSizePx.height);
      CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
      CGContextRef cgContext = CGBitmapContextCreate(NULL, proposedRect.size.width, proposedRect.size.height, 8, 4*proposedRect.size.width, colorSpace, kCGImageAlphaPremultipliedLast);
      CGColorSpaceRelease(colorSpace);
      NSGraphicsContext* context = [NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:NO];
      CGContextRelease(cgContext);
      CGImageRef cgImage = [scalingImage CGImageForProposedRect:&amp;proposedRect context:context hints:nil];
      CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)(URL), kUTTypePNG, 1, NULL);
      CGImageDestinationAddImage(destination, cgImage, nil);
      if(!CGImageDestinationFinalize(destination))
      {
          NSDictionary* details = @{NSLocalizedDescriptionKey:@"Error writing PNG image"};
          [details setValue:@"ran out of money" forKey:NSLocalizedDescriptionKey];
          *error = [NSError errorWithDomain:@"SSWPNGAdditionsErrorDomain" code:10 userInfo:details];
          result = NO;
      }
      CFRelease(destination);
      return result;
  }
  
  @end
  </code></pre>