【问题标题】:iOS to Mac GraphicContext Explanation/ConversioniOS to Mac GraphicContext 解释/转换
【发布时间】:2012-08-31 23:52:47
【问题描述】:

我已经在 iOS 上编程两年了,从来没有在 mac 上编程。我正在开发一个小实用程序来处理我在 iOS 开发中的一些简单图像需求。无论如何,我在 iOS 中有可以完美运行的工作代码,但我完全不知道 mac 的等价物是什么。

我尝试了很多不同的方法,但我真的不明白如何在 Mac 上的“drawRect:”方法之外启动图形上下文。在 iPhone 上,我只使用 UIGraphicsBeghinImageContext()。我知道其他帖子说过要使用 lockFocus/unlockFocus,但我不确定如何准确地满足我的需要。哦,我真的很想念 UIImage 的“CGImage”属性。我不明白为什么 NSImage 不能有一个,尽管听起来比这有点棘手。

这是我在 iOS 上的工作代码——基本上它只是从蒙版创建一个反射图像并将它们组合在一起:

    UIImage *mask = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"Mask_Image.jpg" ofType:nil]];
    UIImage *image = [UIImage imageNamed::@"Test_Image1.jpg"];
    UIGraphicsBeginImageContextWithOptions(mask.size, NO, [[UIScreen mainScreen]scale]);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(ctx, 0.0, mask.size.height);
    CGContextScaleCTM(ctx, 1.f, -1.f);
    [image drawInRect:CGRectMake(0.f, -mask.size.height, image.size.width, image.size.height)];
    UIImage *flippedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CGImageRef maskRef = mask.CGImage;
    CGImageRef maskCreate = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                              CGImageGetHeight(maskRef),
                                              CGImageGetBitsPerComponent(maskRef),
                                              CGImageGetBitsPerPixel(maskRef),
                                              CGImageGetBytesPerRow(maskRef),
                                              CGImageGetDataProvider(maskRef), NULL, false);
    CGImageRef masked = CGImageCreateWithMask([flippedImage CGImage], maskCreate);

    CGImageRelease(maskCreate);

    UIImage *maskedImage = [UIImage imageWithCGImage:masked];
    CGImageRelease(masked);

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(image.size.width, image.size.height + (image.size.height * .5)), NO, [[UIScreen mainScreen]scale]);

    [image drawInRect:CGRectMake(0,0, image.size.width, image.size.height)];
    [maskedImage drawInRect:CGRectMake(0, image.size.height, maskedImage.size.width, maskedImage.size.height)];

    UIImage *anotherImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext(); 

//do something with anotherImage

对于在 Mac 上(简单地)实现这一点有什么建议吗?

【问题讨论】:

  • 简单:(CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]
  • 这会启动图形上下文吗?如果是这样,我如何将图像绘制到其中并检索它们(如 UIGraphicsGetImageFromCurrentImageContext())。另外,我将如何在 NSImage 和 CGI​​mage 之间切换?
  • 添加了 Swift 版本:stackoverflow.com/a/34361216/1226095

标签: ios macos core-graphics converter cgcontext


【解决方案1】:

这是一个将蓝色圆圈绘制到 NSImage 中的简单示例(我在此示例中使用 ARC,添加保留/释放以适应口味)

NSSize size = NSMakeSize(50, 50);

NSImage* im = [[NSImage alloc] initWithSize:size];
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc]
                            initWithBitmapDataPlanes:NULL
                                          pixelsWide:size.width
                                          pixelsHigh:size.height
                                       bitsPerSample:8
                                     samplesPerPixel:4
                                            hasAlpha:YES
                                            isPlanar:NO
                                      colorSpaceName:NSCalibratedRGBColorSpace
                                         bytesPerRow:0
                                        bitsPerPixel:0];

[im addRepresentation:rep];

[im lockFocus];

CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort];
CGContextClearRect(ctx, NSMakeRect(0, 0, size.width, size.height));
CGContextSetFillColorWithColor(ctx, [[NSColor blueColor] CGColor]);
CGContextFillEllipseInRect(ctx, NSMakeRect(0, 0, size.width, size.height));

[im unlockFocus];

[[im TIFFRepresentation] writeToFile:@"/Users/USERNAME/Desktop/foo.tiff" atomically:NO];

主要区别在于,在 OS X 上,您首先必须创建图像,然后才能开始绘制;在 iOS 上,您创建上下文,然后从中提取图像。

基本上,lockFocus 使当前上下文成为图像,您直接在其上绘制,然后使用图像。

我不完全确定这是否能回答你所有的问题,但我认为它至少是其中的一部分。

【讨论】:

  • 所以我有点想这就是锁定焦点的作用,但我该怎么做像翻转图像这样的事情呢?我试图翻转上下文,然后在其中绘制图像,但图像总是正面朝上。另一件事,TIFF 是我可以保存的唯一格式吗?
  • 上帝保佑你,@cobbal!
【解决方案2】:

嗯,这是UIGraphicsBeginImageContextWithOptions上的注释:

UIGraphicsBeginImageContextWithOptions

使用指定选项创建基于位图的图形上下文。

在 iOS 中也可以使用的 OS X 等价物(UIGraphicsBeginImageContextWithOptions 可能是一个包装器)是CGBitmapContextCreate

声明为:

CGContextRef CGBitmapContextCreate (
   void *data,
   size_t width,
   size_t height,
   size_t bitsPerComponent,
   size_t bytesPerRow,
   CGColorSpaceRef colorspace,
   CGBitmapInfo bitmapInfo
);

虽然它是一个 C API,但您可以将 CGBitmapContext 视为 CGContext 的子类。它渲染到像素缓冲区,而 CGContext 渲染到抽象目标。

对于UIGraphicsGetImageFromCurrentImageContext,您可以使用CGBitmapContextCreateImage 并传递您的位图上下文来创建CGImage。

【讨论】:

    【解决方案3】:

    这是Cobbal's answer 的 Swift(2.1 / 10.11 API 兼容)版本

        let size = NSMakeSize(50, 50);
        let im = NSImage.init(size: size)
    
        let rep = NSBitmapImageRep.init(bitmapDataPlanes: nil,
            pixelsWide: Int(size.width),
            pixelsHigh: Int(size.height),
            bitsPerSample: 8,
            samplesPerPixel: 4,
            hasAlpha: true,
            isPlanar: false,
            colorSpaceName: NSCalibratedRGBColorSpace,
            bytesPerRow: 0,
            bitsPerPixel: 0)
    
        im.addRepresentation(rep!)
        im.lockFocus()
    
        let rect = NSMakeRect(0, 0, size.width, size.height)
        let ctx = NSGraphicsContext.currentContext()?.CGContext
        CGContextClearRect(ctx, rect)
        CGContextSetFillColorWithColor(ctx, NSColor.blackColor().CGColor)
        CGContextFillRect(ctx, rect)
    
        im.unlockFocus()
    

    【讨论】:

      【解决方案4】:

      Swift3 版本的Cobbal's answer

         let size = NSMakeSize(50, 50);
          let im = NSImage.init(size: size)
      
          let rep = NSBitmapImageRep.init(bitmapDataPlanes: nil,
                                          pixelsWide: Int(size.width),
                                          pixelsHigh: Int(size.height),
                                          bitsPerSample: 8,
                                          samplesPerPixel: 4,
                                          hasAlpha: true,
                                          isPlanar: false,
                                          colorSpaceName: NSCalibratedRGBColorSpace,
                                          bytesPerRow: 0,
                                          bitsPerPixel: 0)
      
      
         im.addRepresentation(rep!)
          im.lockFocus()
      
          let rect = NSMakeRect(0, 0, size.width, size.height)
          let ctx = NSGraphicsContext.current()?.cgContext
          ctx!.clear(rect)
          ctx!.setFillColor(NSColor.black.cgColor)
          ctx!.fill(rect)
      
          im.unlockFocus()
      

      【讨论】:

        猜你喜欢
        • 2012-05-10
        • 1970-01-01
        • 2012-04-18
        • 2012-01-30
        • 2021-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-06
        相关资源
        最近更新 更多