【问题标题】:how can I save an NSImageView layer to a PNG on disk?如何将 NSImageView 图层保存到磁盘上的 PNG?
【发布时间】:2011-11-27 09:57:40
【问题描述】:

我正在尝试进行以下批处理:

  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 对象和 UI 对象之间(我知道我在 OS X Cocoa 中,它不是 UIKit,到目前为止我也没有使用 CG 的东西)我不知道如何打开上面变成一个png。

【问题讨论】:

    标签: cocoa core-graphics nsdata nsimage


    【解决方案1】:

    您根本不应该使用视图,因为您不需要在屏幕上显示。您应该使用屏幕外位图(NSBitmapImageRep)并使用绘图命令来绘制图像。

    在 Cocoa 中绘图有两种选择。最简单的方法是使用NSBezierPath 和朋友等各种Cocoa 绘图类。另一种选择是更强大但更底层和更复杂的 Quartz API,它们不是面向对象的,而是使用 C 函数语法。

    这是一个如何使用 Cocoa 绘图来做你想做的事情的例子:

    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);
    }
    

    【讨论】:

    • 实际上我可能会选择 Quartz 方法,因为它更像是我更熟悉的 OpenGL。但这种方式也有效。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2021-07-01
    • 1970-01-01
    • 2011-10-31
    • 2016-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多