1

我遵循了Apple 的 Quartz 编程指南(清单 2-5)中的示例代码,并且(在更正了代码中的几个错别字之后,比如calloc只使用一个应该是的参数malloc)我在我的上面定义了这个函数@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,此位图绘制也可以从任何类型的类中进行。

在这个例子中,我只是简单地调用方法 fromviewDidLoad作为测试,但我想我可以从任何地方调用它,甚至是 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
4

3 回答 3

6

你对在屏幕上绘制东西需要什么感到困惑。你需要某种视图——要么是UIView在 iOS 应用程序中,要么是NSView在 Cocoa 应用程序中。

这两种视图通常都需要您通过实现-drawRect:方法来绘制它们。你不能(轻易地)在其他时候吸引他们。(这确实是一个巨大的过度概括,但它已经足够接近了。)

或者,将图像保存到文件中,然后打开该文件。(例如,将 包装CGImageRef在 a 中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);

好的,好的,你已经完成了图像,所以你释放它。但是由于您对图像没有做任何有用的事情,因此您没有看到它出现在任何地方也就不足为奇了。

于 2012-04-08T05:08:15.837 回答
0

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

CGContextDrawImage(UIGraphicsGetCurrentContext(), self.bounds, myImage);
于 2012-04-08T04:58:23.303 回答
0

您可以随时绘制位图,但绘图会出现在位图上。如果您想查看您绘制的内容,您仍然需要在常规绘制周期中将其绘制到 UIView 或 CALayer。

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

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

然而,这仅仅意味着绘制到屏幕是使用该UIImageView drawRect:方法发生的。 我怀疑是否有任何 Apple 认可的方式可以在外面的屏幕上绘制drawRect:

于 2012-04-08T05:06:16.147 回答