9

Objective-c/cocoa (OSX) 中是否有任何方法可以在不改变图像质量的情况下裁剪图像?

我非常接近解决方案,但我仍然可以在颜色中检测到一些差异。放大文本时我可以注意到它。这是我目前正在使用的代码:

    NSImage *target = [[[NSImage alloc]initWithSize:panelRect.size] autorelease];
    target.backgroundColor = [NSColor greenColor];
    //start drawing on target
    [target lockFocus];
    [NSGraphicsContext saveGraphicsState];
    [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationNone];
    [[NSGraphicsContext currentContext] setShouldAntialias:NO];

    //draw the portion of the source image on target image
    [source drawInRect:NSMakeRect(0,0,panelRect.size.width,panelRect.size.height)
              fromRect:NSMakeRect(panelRect.origin.x , source.size.height - panelRect.origin.y - panelRect.size.height, panelRect.size.width, panelRect.size.height)
             operation:NSCompositeCopy
              fraction:1.0];

    [NSGraphicsContext restoreGraphicsState];
    //end drawing
    [target unlockFocus];

    //create a NSBitmapImageRep
    NSBitmapImageRep *bmpImageRep = [[[NSBitmapImageRep alloc]initWithData:[target TIFFRepresentation]] autorelease];
    //add the NSBitmapImage to the representation list of the target
    [target addRepresentation:bmpImageRep];
    //get the data from the representation
    NSData *data = [bmpImageRep representationUsingType: NSJPEGFileType
                                             properties: imageProps];
    NSString *filename = [NSString stringWithFormat:@"%@%@.jpg", panelImagePrefix, panelNumber];
    NSLog(@"This is the filename: %@", filename);
    //write the data to a file
    [data writeToFile:filename atomically:NO];

这是原始图像和裁剪图像的放大比较:

原始图像 (原图——上图)

裁剪的图像 (裁剪图像 - 上图)

区别很难看出,但如果你在它们之间轻弹,你会注意到它。您也可以使用颜色选择器来注意差异。例如,图像底部行中最暗的像素是不同的阴影。

我也有一个完全按照我在 iOS 中想要的方式工作的解决方案。这是代码:

-(void)testMethod:(int)page forRect:(CGRect)rect{
    NSString *filePath = @"imageName";

    NSData *data = [HeavyResourceManager dataForPath:filePath];//this just gets the image as NSData
    UIImage *image = [UIImage imageWithData:data];

    CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], rect);//crop in the rect

    UIImage *result = [UIImage imageWithCGImage:imageRef scale:0 orientation:image.imageOrientation];
    CGImageRelease(imageRef);

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectoryPath = [paths objectAtIndex:0];

    [UIImageJPEGRepresentation(result, 1.0) writeToFile:[documentsDirectoryPath stringByAppendingPathComponent::@"output.jpg"] atomically:YES];
}

那么,有没有办法在 OSX 中裁剪图像,使裁剪后的图像完全不改变?也许我必须研究一个不同的库,但如果我不能用 Objective-C 做到这一点,我会感到惊讶......


注意,这是我之前的问题的后续问题


更新我已经尝试(根据建议)将 CGRect 值四舍五入为整数,但没有注意到差异。这是我使用的代码:

    [source drawInRect:NSMakeRect(0,0,(int)panelRect.size.width,(int)panelRect.size.height)
              fromRect:NSMakeRect((int)panelRect.origin.x , (int)(source.size.height - panelRect.origin.y - panelRect.size.height), (int)panelRect.size.width, (int)panelRect.size.height)
             operation:NSCompositeCopy
              fraction:1.0];

更新我尝试了 mazzaroth 代码,如果我将它保存为 png,它可以工作,但是如果我尝试将它保存为 jpeg,图像会失去质量。如此接近,但还不够接近。还是希望得到完整的答案...

4

4 回答 4

12

使用 CGImageCreateWithImageInRect。

// this chunk of code loads a jpeg image into a cgimage
// creates a second crop of the original image with CGImageCreateWithImageInRect
// writes the new cropped image to the desktop
// ensure that the xy origin of the CGRectMake call is smaller than the width or height of the original image

NSURL *originalImage = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"lockwood" ofType:@"jpg"]];
CGImageRef imageRef = NULL;

CGImageSourceRef loadRef = CGImageSourceCreateWithURL((CFURLRef)originalImage, NULL);
if (loadRef != NULL)
{
    imageRef = CGImageSourceCreateImageAtIndex(loadRef, 0, NULL);
    CFRelease(loadRef); // Release CGImageSource reference
}    
CGImageRef croppedImage = CGImageCreateWithImageInRect(imageRef, CGRectMake(200., 200., 100., 100.));

CFURLRef saveUrl = (CFURLRef)[NSURL fileURLWithPath:[@"~/Desktop/lockwood-crop.jpg" stringByExpandingTildeInPath]];
CGImageDestinationRef destination = CGImageDestinationCreateWithURL(saveUrl, kUTTypeJPEG, 1, NULL);
CGImageDestinationAddImage(destination, croppedImage, nil);

if (!CGImageDestinationFinalize(destination)) {
    NSLog(@"Failed to write image to %@", saveUrl);
}

CFRelease(destination);
CFRelease(imageRef);
CFRelease(croppedImage);

我还提出了一个要点:

https://gist.github.com/4259594

于 2012-12-11T15:58:30.470 回答
3

尝试将 drawInRect orign 更改为 0.5,0.5。否则 Quartz 会将每个像素颜色分配给相邻的 4 个固定点。

设置目标图像的色彩空间。您可能有不同的色彩空间,导致看起来略有不同。

尝试各种渲染意图,看看哪种效果最好,感知与相对比色等。我认为有 4 个选项。

您提到通过保存 JPEG 与 PNG 来修改颜色。

您可以在保存为 JPEG 时指定压缩级别。尝试使用 0.8 或 0.9 之类的东西。您还可以使用 1.0 保存不压缩的 JPEG,但 PNG 具有明显的优势。您在选项字典中为 CGImageDesinationAddImage 指定压缩级别。

最后——如果她没有帮助的话——你应该用 DTS 开一个 TSI,他们当然可以为你提供你所寻求的指导。

于 2012-12-17T06:08:05.690 回答
2

通常的问题是裁剪尺寸是浮动的,但图像像素是整数。可可自动插入它。

您需要对大小和坐标进行下限、舍入或上限,以确保它们是整数。

这可能会有所帮助。

于 2012-12-10T14:01:04.550 回答
0

我正在删除 JPG 文件的 EXIF,我想我明白了原因:

所有损失和更改都来自在保存到文件期间重新压缩图像。

如果您只是再次保存整个图像,您也可能会注意到更改。我要做的是阅读原始 JPG 并将其重新压缩到具有同等文件大小的质量。

于 2014-02-22T13:36:27.153 回答