Как я могу сохранить слой NSImageView в PNG на диске? - PullRequest
1 голос
/ 27 ноября 2011

Я пытаюсь выполнить следующую пакетную обработку:

  1. загрузить изображение
  2. масштабировать
  3. добавить к нему скругленную границу
  4. сохранить новый изображение в формате PNG

Пока я придумал это:

CGPoint center = CGPointMake(self.window.frame.size.width / 2., self.window.frame.size.height / 2.);
      [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
      NSImage * newThumbnail = [[NSImage alloc] initWithData:[NSData dataWithContentsOfURL:[files objectAtIndex:0]]];
      NSImageView *imageView = [[NSImageView alloc] initWithFrame:CGRectMake(center.x - (57/2.), center.y - (80/2.), 57, 80)];
      [imageView setWantsLayer:YES];

      imageView.layer.borderColor = [[NSColor blackColor] CGColor];
      imageView.layer.cornerRadius = 4;
      imageView.layer.masksToBounds = YES;
      imageView.layer.borderWidth = 1.0;
      imageView.image = newThumbnail;

А теперь я думаю, что мне не хватает, чтобы слой перерисовывался в некоторый контекст? может быть, что-то вроде [imageView.layer drawInContext: some context (NS o CG?)]; и сохранение этого контекста на диск. Но я в замешательстве:

в каком контексте,

переходить ли из контекста в NSData на диск,

или если мне нужно промежуточное изображение где-то перед сохранением.

В основном, между CALayers и CGLayers и объектами NS и объектами пользовательского интерфейса (я знаю, что я здесь в OS X Cocoa, и это не UIKit, и я также пока не использую CG), я понятия не имею, как включить выше в png.

1 Ответ

2 голосов
/ 28 ноября 2011

Вы не должны использовать представление вообще, так как вам не нужно отображать на экране. Вы должны использовать закадровое растровое изображение (NSBitmapImageRep) и использовать команды рисования для рисования изображения.

У вас есть два варианта с рисунком в Какао. Самый простой способ - использовать различные классы рисования Какао, такие как NSBezierPath и друзья. Другой вариант - более мощные, но и более низкоуровневые и сложные API-интерфейсы Quartz, которые не являются объектно-ориентированными, но используют синтаксис функции C.

Вот пример того, как делать то, что вы хотите, используя рисунок Какао:

NSImage* anImage = [NSImage imageNamed:@"Lenna.tiff"]; //or some other source

//create a bitmap at a specific size
NSRect offscreenRect = NSMakeRect(0.0, 0.0, 250.0, 250.0);
NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
                                                       pixelsWide:offscreenRect.size.width
                                                       pixelsHigh:offscreenRect.size.height
                                                    bitsPerSample:8
                                                  samplesPerPixel:4
                                                         hasAlpha:YES
                                                         isPlanar:NO
                                                   colorSpaceName:NSCalibratedRGBColorSpace
                                                     bitmapFormat:0
                                                      bytesPerRow:(4 * offscreenRect.size.width)
                                                     bitsPerPixel:32];

//save the current graphics context and lock focus on the bitmap
NSGraphicsContext* originalContext = [NSGraphicsContext currentContext];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext
                                      graphicsContextWithBitmapImageRep:bitmap]];
[NSGraphicsContext saveGraphicsState];

//clear the image rep. This is faster than filling with [NSColor clearColor].
unsigned char *bitmapData = [bitmap bitmapData];
if (bitmapData)
    bzero(bitmapData, [bitmap bytesPerRow] * [bitmap pixelsHigh]);

//create the border path
CGFloat borderWidth = 2.0;
CGFloat cornerRadius = 14.0;
NSRect borderRect = NSInsetRect(offscreenRect, borderWidth/2.0, borderWidth/2.0);
NSBezierPath* border = [NSBezierPath bezierPathWithRoundedRect:borderRect xRadius:cornerRadius yRadius:cornerRadius];
[border setLineWidth:borderWidth];

//set the border as a clipping path
[NSGraphicsContext saveGraphicsState];
[border addClip];

//scale and draw the image
[anImage setSize:offscreenRect.size];
[anImage drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
[NSGraphicsContext restoreGraphicsState];

//set the border color
[[NSColor blackColor] set];

//draw the border
[border stroke];

//restore the original graphics context
[NSGraphicsContext restoreGraphicsState];
[NSGraphicsContext setCurrentContext:originalContext];

//get PNG data from the image rep
NSData* pngData = [bitmap representationUsingType:NSPNGFileType properties:nil];
NSError* error;
if(![pngData writeToURL:[NSURL fileURLWithPath:[NSHomeDirectory() stringByAppendingPathComponent:@"test.png"]] options:NSDataWritingAtomic error:&error])
{
    NSLog(@"%@",error);
}
...