【问题标题】:How to draw using a bitmap context如何使用位图上下文进行绘制
【发布时间】:2012-04-08 04:35:35
【问题描述】:

我遵循了sample code on Apple's Quartz programming guide(清单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。

在这个例子中,我只是简单地从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

【问题讨论】:

  • 对不起。这个问题可能不在主题范围内,但是您如何在 Objective-c 中使用此示例代码?方法格式不在 Objective-c 中。我刚刚开始学习quartzcore,如果您能回答我的问题,我将不胜感激。谢谢。
  • @user1681701 Apple 的 Quartz 是 C API,因此“格式”是 C,Objective-C 完全支持。

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


【解决方案1】:

您对如何在屏幕上绘制内容感到困惑。您需要某种视图——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);

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

【讨论】:

  • 我读到位图绘图不需要 UIView,这就是我使用这种方法的原因,因为无论我使用哪种视图技术,我都想绘制。
  • 你到底在读什么?是的,您可以在不使用 UIView 的情况下绘制位图。但这并不意味着结果会自动显示在屏幕上——你仍然需要一些代码来做到这一点,通常的方法是使用某种 UIView...
  • 感谢库尔特;我这里的代码是 Quartz 2D 编程指南的逐字记录,所以我猜测并非所有 Apple 的示例代码都值得密切关注。
  • 代码here?你实际上稍微改变了它——原来的有CGContextDrawImage(myContext, myBoundingBox, myImage),所以它把图像绘制到一个不同的上下文中。你是对的,它仍然有那个虚假的CGBitmapContextGetDatafree,不过;我将提交一个错误,因为它显然是错误的。
  • ...再看一遍,实际上并没有错,只是令人困惑。他们的代码正在分配bitmapData,所以完成后由他们决定free。如今,您可以让 CGBitmapContext 管理自己的数据,方法是将 NULL 作为第一个参数传递给 CGBitmapContextCreate - 通常这样更容易。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

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

    但是,这只是意味着使用UIImageView drawRect: 方法进行屏幕绘图。 我怀疑在drawRect: 之外是否有任何Apple 认可的方法可以在屏幕上绘图。

    【讨论】:

    猜你喜欢
    • 2014-04-11
    • 1970-01-01
    • 2013-05-04
    • 1970-01-01
    • 2018-07-10
    • 2013-07-29
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多