Image gets wrong resolution value on Snow Leopard
Image gets wrong resolution value on Snow Leopard
- Subject: Image gets wrong resolution value on Snow Leopard
- From: Randall Meadows <email@hidden>
- Date: Mon, 7 Dec 2009 17:58:03 -0700
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 (email@hidden)
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:
This email sent to email@hidden