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