简体   繁体   English

如何使用 bitmap 上下文进行绘制

[英]How to draw using a bitmap context

I have followed the sample code on Apple's Quartz programming guide (Listing 2-5) and (after correcting a couple typos in the code like a calloc with just one argument that should have been malloc ) I have this function defined above my @implementation :我遵循了Apple 的 Quartz 编程指南(清单 2-5)上的示例代码,并且(在更正了代码中的几个拼写错误后,例如calloc ,只有一个参数应该是malloc )我在我的 @implementation 上方定义了这个@implementation

CGContextRef MyCreateBitmapContext (int pixelsWide, int pixelsHigh){

CGContextRef    context = NULL;
CGColorSpaceRef colorSpace;
void *          bitmapData;
int             bitmapByteCount;
int             bitmapBytesPerRow;

bitmapBytesPerRow   = (pixelsWide * 4);// 1
bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);

colorSpace = CGColorSpaceCreateDeviceRGB();
bitmapData = malloc( bitmapByteCount );// 3
if (bitmapData == NULL)
{
    fprintf (stderr, "Memory not allocated!");
    return NULL;
}
context = CGBitmapContextCreate (bitmapData,// 4
                                 pixelsWide,
                                 pixelsHigh,
                                 8,      // bits per component
                                 bitmapBytesPerRow,
                                 colorSpace,
                                 kCGImageAlphaPremultipliedLast);
if (context== NULL)
{
    free (bitmapData);// 5
    fprintf (stderr, "Context not created!");
    return NULL;
}
CGColorSpaceRelease( colorSpace );// 6

return context;// 7
 }

Then I have a method as follows:然后我有一个方法如下:

-(void)testDrawCG{

CGRect myBoundingBox;// 1

CGContextRef myBitmapContext;
CGImageRef myImage;



myBoundingBox = CGRectMake (100, 100, 100, 100);// 2
myBitmapContext = MyCreateBitmapContext (400, 300);// 3
// ********** Your drawing code here ********** // 4
CGContextSetRGBFillColor (myBitmapContext, 1, 0, 0, 1);
CGContextFillRect (myBitmapContext, CGRectMake (0, 0, 200, 100 ));
CGContextSetRGBFillColor (myBitmapContext, 0, 0, 1, .5);
CGContextFillRect (myBitmapContext, CGRectMake (0, 0, 100, 200 ));
myImage = CGBitmapContextCreateImage (myBitmapContext);// 5
CGContextDrawImage(myBitmapContext, myBoundingBox, myImage);// 6
char *bitmapData = CGBitmapContextGetData(myBitmapContext); // 7
CGContextRelease (myBitmapContext);// 8
if (bitmapData) free(bitmapData); // 9
CGImageRelease(myImage);


 }

Everything compiles fine, but nothing appears when I call the method.一切都编译得很好,但是当我调用该方法时什么也没有出现。

My understanding is that unlike drawInRect which requires UIView to be in the picture (no pun intended), this bitmap drawing can take place from any type of class, even if you are not using UIKit.我的理解是,不像drawInRect需要 UIView 在图片中(没有双关语),这个 bitmap 绘图可以从任何类型的 class 进行,即使你没有使用 UIKit。

In this example, I simply calling the method from viewDidLoad as a test, but I'd think I can call it from anywhere, even an NSObject subclass, and expect to see something;在这个例子中,我只是从viewDidLoad调用方法作为测试,但我想我可以从任何地方调用它,甚至是 NSObject 子类,并期望看到一些东西; at least, that is what is suggested by Apple's docs.至少,苹果文档是这样建议的。 Any thoughts?有什么想法吗?

UPDATE : Further reading in the Apple docs led me to try this to create the context, rather than use the custom function previously defined:更新:进一步阅读 Apple 文档让我尝试创建上下文,而不是使用之前定义的自定义 function:

 //    myBitmapContext = MyCreateBitmapContext (400, 300);// 3
UIGraphicsBeginImageContext(myBoundingBox.size);
myBitmapContext=UIGraphicsGetCurrentContext();

However, the results are still nothing appearing on the screen.然而,结果仍然没有出现在屏幕上。 Additionally, I get this in the log even though I am not directly calling malloc :此外,即使我没有直接调用malloc ,我也会在日志中得到这个:

 malloc: *** error for object 0x102b1020: pointer being freed was not allocated*** set a breakpoint in malloc_error_break to debug

You're confused about what it takes to draw something on-screen.您对如何在屏幕上绘制内容感到困惑。 You need a view of some kind -- either a UIView in an iOS app, or an NSView in a Cocoa app.您需要某种视图UIView应用程序中的 UIView,或 Cocoa 应用程序中的NSView

Both kinds of views generally require that you draw into them by implementing the -drawRect: method.这两种视图通常都需要您通过实现-drawRect:方法来绘制它们。 You cannot (easily) draw into them at other times.你不能(轻易地)在其他时间吸引他们。 (This is a vast overgeneralization, really, but it's close enough.) (这是一个巨大的过度概括,真的,但它已经足够接近了。)

Alternatively, save your image to a file, then open the file.或者,将图像保存到文件中,然后打开该文件。 (For instance, wrap the CGImageRef in a UIImage , then use UIImagePNGRepresentation to create PNG data, then -[NSData writeToFile:atomically:] to write it to a file.) (例如,将UIImage包装在CGImageRef中,然后使用UIImagePNGRepresentation创建 PNG 数据,然后-[NSData writeToFile:atomically:]将其写入文件。)

Your code also has a few issues.您的代码也有一些问题。 -testDrawCG is OK until here: -testDrawCG ,直到这里:

    myImage = CGBitmapContextCreateImage (myBitmapContext);// 5

You've taken the contents of the bitmap context -- the two rectangles you drew earlier -- and created a CGImageRef from them.您已经获取了 bitmap 上下文的内容——您之前绘制的两个矩形——并从中创建了一个CGImageRef Think of this image as a snapshot of the context.将此图像视为上下文的快照。

    CGContextDrawImage(myBitmapContext, myBoundingBox, myImage);// 6

Now you're drawing that image back into the same context.现在您将该图像绘制相同的上下文中。 I have no idea why you would do this.我不知道你为什么要这样做。 Just skip it.跳过它。

    char *bitmapData = CGBitmapContextGetData(myBitmapContext); // 7

Now you're getting the raw data that backs the bitmap context.现在您将获得支持 bitmap 上下文的原始数据。 You don't need to do this.你不需要这样做。

    CGContextRelease (myBitmapContext);// 8

OK, you're done with the context, makes sense.好的,你已经完成了上下文,有道理。

    if (bitmapData) free(bitmapData); // 9

Don't do this!不要这样做! You did not get the data using a method with Create or Copy in the name, therefore you don't own it and you shouldn't free it.您没有使用名称中带有CreateCopy的方法获取数据,因此您不拥有它,也不应该释放它。

    CGImageRelease(myImage);

OK, fine, you're done with the image so you release it.好的,好的,你已经完成了图像,所以你释放它。 But since you did nothing useful with the image then it's no surprise that you don't see it appearing anywhere.但是由于您对图像没有做任何有用的事情,所以您看不到它出现在任何地方也就不足为奇了。

You need to draw the image ( myImage ) to a context that draws on the screen.您需要将图像 ( myImage ) 绘制到屏幕上绘制的上下文中。 Make a subclass of UIView and put your testDrawCG code into its drawRect: method. UIView的子类并将您的testDrawCG代码放入其drawRect:方法中。 Then, still in drawRect: , draw myImage to the view's context like this:然后,仍然在drawRect:中,将myImage绘制到视图的上下文中,如下所示:

CGContextDrawImage(UIGraphicsGetCurrentContext(), self.bounds, myImage);

You can draw to a bitmap at any time, but the drawing goes onto the bitmap. If you want to see what you drew, you'll still need to draw it to a UIView or CALayer, during the regular drawing cycle.您可以随时绘制到 bitmap,但绘制会转到 bitmap。如果您想查看绘制的内容,您仍然需要在常规绘制周期中将其绘制到 UIView 或 CALayer。

For total control over your drawing, follow rob mayoff's suggestion.要完全控制您的绘图,请遵循 rob mayoff 的建议。 If you just want to see what you're currently drawing, you can turn your CGImageRef to a UIImage , and display that within a UIImageView :如果您只想查看当前正在绘制的内容,可以将CGImageRef转换为UIImage ,并在UIImageView中显示它:

UIImage *image = [UIImage imageWithCGImage:myImage]; UIImage *image = [UIImage imageWithCGImage:myImage]; [someImageView setImage:image]; [someImageView setImage:image];

However, this just means that the drawing to screen happened with the UIImageView drawRect: method.然而,这仅意味着屏幕绘制发生在UIImageView drawRect:方法中。 I doubt there is any Apple-approved way to draw to the screen outside drawRect: .我怀疑是否有任何 Apple 批准的方法可以在drawRect:之外绘制到屏幕。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM