In this application, I have a method that reads in an image and writes it back 
out with a different resolution.  This resolution is specified by the user via 
a textfield in a sheet.

On Leopard, the method works as expected; whatever value for the resolution is 
specified is what is actually used to write out the image.

But on Snow Leopard....sigh.  The client has asked that this textfield's value 
default to "250", indicating the image should be written out with a DPI of 250 
pixels/inch.  When that value is used, the resulting image does NOT have a 
resolution of 250, but rather "72.05 x 72.03 pixels/inch" as indicated by 
Preview's Info window.  GraphicConverter and Photoshop agree with this.  I 
tried various values, including 249, 248, 245, and 239--all these resulted in 
the "wrong" value, but lo and behold "240" *works*.

I've posted the method at <http://paste.lisp.org/display/91743>, so you can 
turn on line numbers for easy reference, but I'll also paste it here for easy 
discussion:

- (void)exportImageDefinition:(AMImageDefinition *)imageDefinition
                  destination:(NSString *)destination
                    retouched:(BOOL)retouched
              revertRetouched:(BOOL)revertRetouch
                      cropped:(BOOL)cropped
                revertCropped:(BOOL)revertCrop
                   resolution:(float)resolution
                 recompressed:(BOOL)recompressed
                     fileType:(NSString *)fileType
                     settings:(void *)settings
              appendExtension:(BOOL)appendExtension
                    writePath:(NSString *)writePath
                stripMetadata:(BOOL)stripMetadata
{
   NSString  *imagePath = nil, *savePath = writePath;
   BOOL      isDir;

   if (retouched) {
      imagePath = [imageDefinition retouchedImagePathForSource:retouchedSource];
      if (revertRetouch && !imagePath) {
         imagePath = [imageDefinition imagePath];
      }
   }
   else {
      imagePath = ((![imageDefinition 
retouchedImagePathForSource:retouchedSource] || revertRetouch) ? 
                   [imageDefinition imagePath] : nil);
   }

   if (!recompressed) {
      // The fileType may be wrong, because it just blindly takes whatever the 
menu says, without
      // checking whether it *should* be recompressed or not.
      NSString   *extension = [imagePath pathExtension];
      fileType = [self fileTypeForExtension:extension];
   }
   OSType  creator = '8BIM' /* Photoshop */, typeCode = [self 
typeCodeForFileType:fileType];
   
   if ([[NSFileManager defaultManager] fileExistsAtPath:savePath 
isDirectory:&isDir] && isDir) {
      savePath = [savePath stringByAppendingPathComponent:[[imagePath 
lastPathComponent] 
                                                           
stringByDeletingPathExtension]];

      if (!recompressed) {
         if ([imagePath pathExtension] != nil) {
            savePath = [savePath stringByAppendingPathExtension:[imagePath 
pathExtension]];
         }
      }
   }

   if (recompressed && imagePath && (!cropped || [imageDefinition 
regionOfInterest])) {
      CGImageSourceRef      imageSource = 
CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:imagePath], NULL);
      NSMutableDictionary   *imageProperties = nil;
      NSImage               *image = nil;
      CGImageRef            imageRef = NULL;

      @try {
         if (CGImageSourceGetCount(imageSource) > 0) {
            imageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
            CIImage *ciImage = [CIImage imageWithCGImage:imageRef];

            imageProperties = [NSMutableDictionary dictionaryWithDictionary:
               [(NSDictionary *)CGImageSourceCopyPropertiesAtIndex(imageSource, 
0, NULL) autorelease]];

            // clean up after our CGImage
            CGImageRelease(imageRef);
            imageRef = NULL;
            // convert image into nsImage
            if (ciImage != nil)
               image = [NSImageCreateWithCIImage(ciImage, imageProperties) 
autorelease];
         }
      }

      // clean up
      @finally {
         CFRelease(imageSource);
         imageSource = NULL;
      }

      // cancel the export if we can't open the image
      if (image != nil) {
         // configure the exporter
         //[exporter setSettings:settings];

         if (appendExtension) {
            NSString   *extension = [self extensionForFileType:fileType];
            if (extension != nil) {
               savePath = [savePath stringByAppendingPathExtension:extension];
            }
         }

         if (resolution == 0) {
            // This will be non-zero when cropping has been requested; if it's 
zero, don't actually
            // change the value, but use what the current value is.
            // Could probably just as easily use DPIWidth or TIFF:XResolution 
or TIFF:YResolution
            resolution = [[imageProperties valueForKey:@"DPIHeight"] 
floatValue];
         }
         
         if (cropped) {
            VIImageStyle *imageStyle = [[[VIImageStyle alloc] 
initWithPropertyList:
                                         [[imageDefinition 
propertiesForDestination:destination]
                                          objectForKey:@"Image Style"]]
                                        autorelease];
            NSAffineTransform   *translateTransform = [NSAffineTransform 
transform];
            NSAffineTransform   *scaleTransform = [NSAffineTransform transform];
            NSBezierPath      *framePath = [imageStyle framePath];
            NSBezierPath      *maskPath = [imageStyle maskPath];

            NSPoint   offset = NSZeroPoint;
            if (maskPath) {
               offset = NSMakePoint(-NSMinX([maskPath bounds]), 
-NSMinY([maskPath bounds]));
            }
            else if (framePath) {
               offset = NSMakePoint(NSMinX([framePath bounds]), 
NSMinY([framePath bounds]));
            }

            NSSize   croppedSize;
            if (maskPath) {
               croppedSize = [maskPath bounds].size;
            }
            else if (framePath) {
               croppedSize = [framePath bounds].size;
            }
            else {
               croppedSize = [image size];
            }
            NSImage *croppedImage = nil;

            croppedSize = NSMakeSize(croppedSize.width * (resolution / 72.0),
                                     croppedSize.height * (resolution / 72.0));

            [scaleTransform scaleBy:(resolution / 72.0)];
            [translateTransform translateXBy:offset.x yBy:offset.y];

            croppedImage = [[[NSImage alloc] initWithSize:croppedSize] 
autorelease];

            [croppedImage setCacheMode:NSImageCacheNever];
            [croppedImage setScalesWhenResized:NO];
            [croppedImage setDataRetained:YES];

            [croppedImage lockFocus];
            @try {
               NSGraphicsContext *context = [NSGraphicsContext currentContext];

               [context setShouldAntialias:YES];
               [context setImageInterpolation:NSImageInterpolationHigh];

               [scaleTransform concat];
               [translateTransform concat];

               if ([imageStyle regionOfInterest] && [imageDefinition 
regionOfInterest]) {
                  [[[imageDefinition regionOfInterest] 
transformToRegionOfInterest:[imageStyle regionOfInterest]]
                   concat];
               }

               [image drawAtPoint:NSZeroPoint
                         fromRect:NSMakeRect(0, 0, [image size].width, [image 
size].height)
                        operation:NSCompositeCopy
                         fraction:1.0];
            }

            @finally {
               [croppedImage unlockFocus];
            }
            image = croppedImage;
         }

         if (stripMetadata == YES) {
            imageProperties = [NSMutableDictionary dictionary];
         }

         // set the resolution for the exported image
         [imageProperties setValue:[NSNumber numberWithFloat:resolution] 
                            forKey:(NSString *)kCGImagePropertyDPIHeight];
         [imageProperties setValue:[NSNumber numberWithFloat:resolution] 
                            forKey:(NSString *)kCGImagePropertyDPIWidth];
         [imageProperties setValue:[NSNumber numberWithFloat:1.0] 
                            forKey:(NSString 
*)kCGImageDestinationLossyCompressionQuality];
         [imageProperties setValue:[NSNumber numberWithLong:creator] 
forKey:NSFileHFSCreatorCode];
         [imageProperties setValue:[NSNumber numberWithLong:typeCode] 
forKey:NSFileHFSTypeCode];
         [imageProperties setValue:[NSNumber numberWithFloat:resolution] 
forKeyPath:@"{TIFF}.XResolution"];
         [imageProperties setValue:[NSNumber numberWithFloat:resolution] 
forKeyPath:@"{TIFF}.YResolution"];

         NSError   *error = nil;
         [[NSFileManager defaultManager] removeItemAtPath:savePath 
error:&error];
         // export the image
         if (!NSImageWriteToURL([NSURL fileURLWithPath:savePath], image, 
(CFStringRef)fileType, imageProperties)) {
            NSLog(@"Couldn't export image to %@", savePath);
         }
         else if (batchEditing) {
            [batchEditMonitor monitorFile:savePath 
                          imageDefinition:imageDefinition 
                             importSource:autoImportSource];
         }
      }
   }
   else if (!recompressed && imagePath) {
      [[NSFileManager defaultManager] removeItemAtPath:savePath error:nil];
      [[NSFileManager defaultManager] copyPath:imagePath toPath:savePath 
handler:nil];
      if (batchEditing) {
         [batchEditMonitor monitorFile:savePath 
                       imageDefinition:imageDefinition 
                          importSource:autoImportSource];
      }
   }
}


Any and all tips, suggestions, comments, etc. are greatly appreciated.
Thanks!
randy_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to