Tod*_*orf 6 macos cocoa core-graphics objective-c quartz-2d
Mac OS X 10.7.4
我正在绘制通过创建的屏幕外图形上下文+[NSGraphicsContext graphicsContextWithBitmapImageRep:].
当我使用NSBezierPath类绘制到这个图形上下文时,一切都按预期工作.
但是,当我使用CGContextRefC函数绘制到这个图形上下文时,我看不到我的绘图结果.什么都行不通.
由于我不打算进入的原因,我真的需要使用CGContextRef函数(而不是Cocoa NSBezierPath类).
我的代码示例如下所示.我试图画一个简单的"X".一次使用NSBezierPath,一次使用CGContextRefC函数.第一笔中风起作用,第二笔中风不起作用.我究竟做错了什么?
NSRect imgRect = NSMakeRect(0.0, 0.0, 100.0, 100.0);
NSSize imgSize = imgRect.size;
NSBitmapImageRep *offscreenRep = [[[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
pixelsWide:imgSize.width
pixelsHigh:imgSize.height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bitmapFormat:NSAlphaFirstBitmapFormat
bytesPerRow:0
bitsPerPixel:0] autorelease];
// set offscreen context
NSGraphicsContext *g = [NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep];
[NSGraphicsContext setCurrentContext:g];
NSImage *img = [[[NSImage alloc] initWithSize:imgSize] autorelease];
CGContextRef ctx = [g graphicsPort];
// lock and draw
[img lockFocus];
// draw first stroke with Cocoa. this works!
NSPoint p1 = NSMakePoint(NSMaxX(imgRect), NSMinY(imgRect));
NSPoint p2 = NSMakePoint(NSMinX(imgRect), NSMaxY(imgRect));
[NSBezierPath strokeLineFromPoint:p1 toPoint:p2];
// draw second stroke with Core Graphics. This doesn't work!
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, 0.0, 0.0);
CGContextAddLineToPoint(ctx, imgSize.width, imgSize.height);
CGContextClosePath(ctx);
CGContextStrokePath(ctx);
[img unlockFocus];
Run Code Online (Sandbox Code Playgroud)
Kur*_*vis 26
您没有指定查看结果的方式.我假设你正在看NSImage img而不是NSBitmapImageRep offscreenRep.
当您调用时[img lockFocus],您将当前更改为NSGraphicsContext要绘制的上下文img.所以,NSBezierPath绘图进入img,这就是你所看到的.CG绘图进入offscreenRep你没有看到的.
不是将焦点锁定到NSImage并绘制到NSImage中,而是创建一个NSImage并将offscreenRep添加为其代表之一.
NSRect imgRect = NSMakeRect(0.0, 0.0, 100.0, 100.0);
NSSize imgSize = imgRect.size;
NSBitmapImageRep *offscreenRep = [[[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
pixelsWide:imgSize.width
pixelsHigh:imgSize.height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bitmapFormat:NSAlphaFirstBitmapFormat
bytesPerRow:0
bitsPerPixel:0] autorelease];
// set offscreen context
NSGraphicsContext *g = [NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:g];
// draw first stroke with Cocoa
NSPoint p1 = NSMakePoint(NSMaxX(imgRect), NSMinY(imgRect));
NSPoint p2 = NSMakePoint(NSMinX(imgRect), NSMaxY(imgRect));
[NSBezierPath strokeLineFromPoint:p1 toPoint:p2];
// draw second stroke with Core Graphics
CGContextRef ctx = [g graphicsPort];
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, 0.0, 0.0);
CGContextAddLineToPoint(ctx, imgSize.width, imgSize.height);
CGContextClosePath(ctx);
CGContextStrokePath(ctx);
// done drawing, so set the current context back to what it was
[NSGraphicsContext restoreGraphicsState];
// create an NSImage and add the rep to it
NSImage *img = [[[NSImage alloc] initWithSize:imgSize] autorelease];
[img addRepresentation:offscreenRep];
// then go on to save or view the NSImage
Run Code Online (Sandbox Code Playgroud)
我想知道为什么每个人都写这么复杂的代码来绘制图像.除非你关心图像的确切位图表示(通常你不关心!),否则不需要创建一个.您可以创建一个空白图像并直接绘制到它.在这种情况下,系统将创建适当的位图表示(或者可能是PDF表示或系统认为更适合绘图的任何内容).
init方法的文档
- (instancetype)initWithSize:(NSSize)aSize
Run Code Online (Sandbox Code Playgroud)
从MacOS 10.0开始存在但仍未被弃用,清楚地说:
使用此方法初始化图像对象后,您需要在尝试绘制图像之前提供图像内容.您可以将焦点锁定在图像上并绘制到图像,也可以显式添加您创建的图像表示.
所以这就是我编写代码的方式:
NSRect imgRect = NSMakeRect(0.0, 0.0, 100.0, 100.0);
NSImage * image = [[NSImage alloc] initWithSize:imgRect.size];
[image lockFocus];
// draw first stroke with Cocoa
NSPoint p1 = NSMakePoint(NSMaxX(imgRect), NSMinY(imgRect));
NSPoint p2 = NSMakePoint(NSMinX(imgRect), NSMaxY(imgRect));
[NSBezierPath strokeLineFromPoint:p1 toPoint:p2];
// draw second stroke with Core Graphics
CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort];
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, 0.0, 0.0);
CGContextAddLineToPoint(ctx, imgRect.size.width, imgRect.size.height);
CGContextClosePath(ctx);
CGContextStrokePath(ctx);
[image unlockFocus];
Run Code Online (Sandbox Code Playgroud)
这就是所有人.
graphicsPort实际上是void *:
@property (readonly) void * graphicsPort
Run Code Online (Sandbox Code Playgroud)
并记录为
由图形端口表示的低级,特定于平台的图形上下文.
这可能是一切,但最后的说明
在OS X中,这是Core Graphics上下文,一个
CGContextRef对象(opaque类型).
此属性已在10.10中弃用,以支持新属性
@property (readonly) CGContextRef CGContext
Run Code Online (Sandbox Code Playgroud)
仅适用于10.10及更高版本.如果你必须支持旧系统,那么仍然可以使用graphicsPort.
@Robin Stewart 的解决方案对我来说效果很好。我能够将其压缩为 NSImage 扩展名。
extension NSImage {
convenience init(size: CGSize, actions: (CGContext) -> Void) {
self.init(size: size)
lockFocusFlipped(false)
actions(NSGraphicsContext.current!.cgContext)
unlockFocus()
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
let image = NSImage(size: CGSize(width: 100, height: 100), actions: { ctx in
// Drawing commands here for example:
// ctx.setFillColor(.white)
// ctx.fill(pageRect)
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14402 次 |
| 最近记录: |