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でこれができなかったら驚くでしょう...


注意、これは私の前の質問hereへのフォローアップの質問です。


更新(提案に従って) 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 の原点を 0.5,0.5 に変更してみてください。それ以外の場合、Quartz は各ピクセルの色を隣接する 4 つのフィクセルに分配します。

対象画像の色空間を設定します。色空間が異なるため、見た目がわずかに異なる可能性があります。

さまざまなレンダリング インテントを試して、どちらが最良の結果を得るかを確認します。知覚的対相対的な測色などです。4 つのオプションがあると思います。

JPEG と PNG を保存すると、色が変更されるとのことです。

JPEG保存時の圧縮レベルを指定できます。0.8 や 0.9 などで試してください。1.0 で圧縮せずに JPEG を保存することもできますが、PNG には明らかな利点があります。CGImageDesinationAddImage のオプション ディクショナリで圧縮レベルを指定します。

最後に、彼女の助けがなければ、DTS で TSI を開く必要があります。DTS は、あなたが求めているガイダンスを確実に提供してくれます。

于 2012-12-17T06:08:05.690 に答える
2

通常の問題は、トリミング サイズが float であるのに、画像のピクセルが整数であるということです。cocoa はそれを自動的に補間します。

サイズと座標が整数であることを確認するには、それらを床、丸め、または天井にする必要があります。

これが役立つ場合があります。

于 2012-12-10T14:01:04.550 に答える
0

I am doing EXIF deleting of JPG files and I think I caught the reason:

All losses and changes come from the re-compress of your image during saving to file.

You may notice the change too if you just to save the whole image again. What I am to do is to read the original JPG and re-compress it to a quality that take equivalent file size.

于 2014-02-22T13:36:27.153 に答える