如何使用位图上下文绘制

时间:2012-04-08 04:35:36

标签: objective-c core-graphics quartz-graphics quartz-2d

我已经跟随sample code on Apple's Quartz programming guide(清单2-5)和(在代码中纠正了几个拼写错误,例如calloc,只有一个应该是malloc的参数)I我的@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
 }

然后我有一个方法如下:

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


 }

一切都很好,但是当我打电话给方法时什么都没有出现。

我的理解是,与drawInRect不同,它需要UIView在图片中(没有双关语),这个位图绘制可以从任何类型的类中进行,即使你没有使用UIKit。

在这个例子中,我只是从viewDidLoad调用方法作为测试,但我认为我可以从任何地方调用它,甚至是NSObject子类,并期望看到一些东西;至少,这是Apple的文档建议的。有什么想法吗?

更新:Apple文档中的进一步阅读使我尝试创建上下文,而不是使用之前定义的自定义函数:

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

然而,结果仍然没有出现在屏幕上。另外,即使我没有直接调用malloc

,我也会在日志中得到此信息
 malloc: *** error for object 0x102b1020: pointer being freed was not allocated*** set a breakpoint in malloc_error_break to debug

3 个答案:

答案 0 :(得分:6)

你对在屏幕上绘制内容所需的内容感到困惑。您需要某种视图 - iOS应用中的UIView或Cocoa应用中的NSView

这两种视图通常都要求您通过实现-drawRect:方法来绘制它们。你不能(很容易)在其他时间吸引他们。 (这是一个巨大的过度概括,真的,但它足够接近。)

或者,将图像保存到文件中,然后打开文件。 (例如,将CGImageRef包裹在UIImage中,然后使用UIImagePNGRepresentation创建PNG数据,然后-[NSData writeToFile:atomically:]将其写入文件。)

您的代码也存在一些问题。 -testDrawCG在此之前就可以了:

    myImage = CGBitmapContextCreateImage (myBitmapContext);// 5

您已经获取了位图上下文的内容 - 您之前绘制的两个矩形 - 并从中创建了CGImageRef。将此图像视为上下文的快照。

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

现在您将该图像绘制回相同的上下文。我不知道你为什么要这样做。跳过它。

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

现在,您将获得支持位图上下文的原始数据。你不需要这样做。

    CGContextRelease (myBitmapContext);// 8

好的,你完成了上下文,有道理。

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

不要这样做!您没有使用名称中包含CreateCopy的方法获取数据,因此您不拥有它,也不应该将其释放。

    CGImageRelease(myImage);

好的,很好,你完成了图像,所以你发布它。但是,由于你没有对图像做任何有用的事情,所以你不会看到它出现在任何地方也就不足为奇了。

答案 1 :(得分:0)

您需要将图像(myImage)绘制到在屏幕上绘制的上下文中。创建UIView的子类,并将testDrawCG代码放入其drawRect:方法中。然后,仍然在drawRect:中,将myImage绘制到视图的上下文中,如下所示:

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

答案 2 :(得分:0)

您可以随时绘制位图,但绘图会进入位图。如果你想看看你画了什么,你仍然需要在常规绘图周期中将它绘制到UIView或CALayer。

要完全控制您的绘图,请遵循rob mayoff的建议。如果您只想查看当前正在绘制的内容,可以将CGImageRef变为UIImage,并在UIImageView内显示:

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

但是,这只是意味着使用UIImageView drawRect:方法进行了绘图到屏幕。我怀疑是否有任何Apple批准的方式在屏幕外绘制drawRect: