如何在Cocoa应用程序中设置导出的JPEG图像的每英寸像素数?

时间:2012-02-10 17:02:20

标签: objective-c macos cocoa

我有一个Cocoa Mac图像编辑应用程序,可让用户导出JPEG图像。我目前正在使用以下代码将这些图像导出为JPEG文件:

//this is user specified
NSInteger resolution;

NSImage* savedImage = [[NSImage alloc] initWithSize:NSMakeSize(600, 600)];
[savedImage lockFocus];
//draw here 
[savedImage unlockFocus];

NSBitmapImageRep* savedImageBitmapRep = [NSBitmapImageRep imageRepWithData:[savedImage TIFFRepresentationUsingCompression:NSTIFFCompressionNone factor:1.0]];

NSDictionary* properties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithFloat:1.0], NSImageCompressionFactor, nil];

//holds the jpeg file
NSData * imageData = nil;
imageData = [savedImageBitmapRep representationUsingType:NSJPEGFileType properties:properties];

但是,我希望用户能够为此JPEG图像提供每英寸像素(就像在Photoshop的导出选项中一样)。我需要在上面的代码中修改哪些内容来为导出的JPEG调整此值?

2 个答案:

答案 0 :(得分:3)

对于NSImageNSImageRep,您不直接设置分辨率,而是设置大小。 对于size,numberOfPixels和分辨率,以下等式成立:

size = numberOfPixels * 72.0 / resolution

size是一个长度,用单位inch/72表示。 (sizeresolution是浮点数)。您可以看到,对于dpi = 72大小的图像,numberOfPixels的数字相同(但含义非常不同)。

创建NSBitmapImageRep后,可以设置所需分辨率的大小:

NSBitmapImageRep* savedImageBitmapRep = . . . ; // create the new rep
NSSize newSize;
newSize.width = [savedImageBitmapRep pixelsWide] * 72.0 / resolution;  // x-resolution
newSize.height = [savedImageBitmapRep pixelsHigh] * 72.0 / resolution;  // y-resolution
[savedImageBitmapRep setSize:newSize];
// save the rep

两个评论:你真的需要lockFocus / unlockFocus方式吗?构建新NSBitmapImageRep的首选方法是使用NSGraphicsContext。见:http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg74857.html

并且:TIFFRepresentation使用NSBitmapImageRep非常节省时间和空间。另有10.6 方式存在并且不需要任何费用,因为lockFocus和unlockFocus创建了一个类NSCGImageSnapshotRep的对象,它在引擎盖下是一个CGImage。 (在10.6之前的操作系统版本中,它是NSCachedImageRep。)以下是:

[anImage lockFocus];
// draw something
[anImage unlockFocus];
// now anImage contains an NSCGImageSnapshotRep
CGImageRef cg = [anImage CGImageForProposedRect:NULL context:nil hints:nil];
NSBitmapImageRep *newRep = [[NSBitmapImageRep alloc] initWithCGImage:cg];
// set the resolution
// here you may NSLog anImage, cg and newRep
// save the newRep
// release the newRep if needed

答案 1 :(得分:2)

我找不到使用NSImage API的方法,但CGImage可以通过设置kCGImagePropertyDPIHeight / Width来实现。

我还设置了kCGImageDestinationLossyCompressionQuality,我认为它与NSImageCompressionFactor相同。

//this is user specified
NSInteger resolution = 100;

NSImage* savedImage = [[NSImage alloc] initWithSize:NSMakeSize(600, 600)];
[savedImage lockFocus];
//draw here 
[savedImage unlockFocus];

NSBitmapImageRep* savedImageBitmapRep = [NSBitmapImageRep imageRepWithData:[savedImage TIFFRepresentationUsingCompression:NSTIFFCompressionNone factor:1.0]];

NSDictionary* properties = [NSDictionary dictionaryWithObjectsAndKeys:
                            [NSNumber numberWithFloat:1.0], kCGImageDestinationLossyCompressionQuality,
                            [NSNumber numberWithInteger:resolution], kCGImagePropertyDPIHeight,
                            [NSNumber numberWithInteger:resolution], kCGImagePropertyDPIWidth,
                            nil];

NSMutableData* imageData = [NSMutableData data];
CGImageDestinationRef imageDest =  CGImageDestinationCreateWithData((CFMutableDataRef) imageData, kUTTypeJPEG, 1, NULL);
CGImageDestinationAddImage(imageDest, [savedImageBitmapRep CGImage], (CFDictionaryRef) properties);
CGImageDestinationFinalize(imageDest);

// Do something with imageData
if (![imageData writeToFile:[@"~/Desktop/test.jpg" stringByExpandingTildeInPath] atomically:NO])
    NSLog(@"Failed to write imageData");