使用QImage的高质量渲染

发布: 2008-08-12 23:37

       在绘图的时候,我们可能要面对速度和精确的平衡。例如,在X11和Max OS X上,在QWidget或者Qpixmap上绘图依赖于平台的本地绘图引擎。在X11上,要保证与X服务器的通信最少,仅有绘图命令被传递而不是实现的图象数据。这种方法的主要缺点是Qt受平台的本地支持所限制:
在X11平台上,你抗钜齿功能和小型坐标支持仅当X服务器上有Xrender 扩展才可用。
       在 Mac OS X平台上,本地别名图形引擎使用与X11和Windows平台不同的绘制多边形的算法,因而也就有稍微不同的结果。
       当精确比效率更重时,我们可以向一个QImage上绘图并把结果拷贝到屏幕上。这总是使用Qt自己的内部绘图引擎,在所有的平台都能给出一致的结果。唯一的限制是我们要绘制的QImage必须在创建的时候给出QImage::Format_RGB32或者QImage::Format_ARGB32_Premultiplied。
       左乘ARGB32格式几乎与传统的RGB32格式(0xaarrggbb),不同之处是红、绿、蓝通过是与alpha通过左乘的。这意味着它的RGB值是它的alpha值从0开始的倍数,它的alpha值的一般范围是从0x00到0xFF。例如,一个50%透明的蓝色在ARGB32格式中表示为0x7F0000FF,但是在左乘ARGB32格式中表示为0x7F00007F,类似地,一个75%透明的在ARGB32格式中为0x3F008000的深绿色,在左乘ARGB32格式中则为0x3F002000。
       假设我们希望使用抗钜齿功能来画一个物件,并且我们 希望在没有X Render扩展的X11系统上获得较好的结果。原始的paintEvent()处理器,它用于抗钜齿功能但依赖于X Render,它看上去可能像下面这样:

[code type="cpp-qt"]
void MyWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
draw(&painter);
}
[/code]

       下面是使用Qt的平台无关的图形引擎重写过的物件的paintEvent()函数:

[code type="cpp-qt"]
void MyWidget::paintEvent(QPaintEvent *event)
{
QImage image(size(), QImage::Format_ARGB32_Premultiplied);
QPainter imagePainter(&image);
imagePainter.initFrom(this);
imagePainter.setRenderHint(QPainter::Antialiasing, true);
imagePainter.eraseRect(rect());
draw(&imagePainter);
imagePainter.end();
QPainter widgetPainter(this);
widgetPainter.drawImage(0, 0, image);
}
[/code]

       我们创建了一个与该物件尺寸相同的左乘ARGB32格式的QImage,还有一个在该图象上绘图的QPainter。initFrom()调用初始化绘图器、背景和基于物件的字体。我们像正常情况一样使用该QPainter执行绘图,并且在最后我们重新使用该QPainter对象把该图象拷贝到物件中。
       这种方法在所有平台上都能产生一致的高质量的结果,但要除了字体的渲染,因为这取决于所安装的字体。
       默认的组合模式为QImage::CompositionMode_SourceOver,意思是源象素(我们正在画的象素)迭加到目的象素(已存在的象素),在这种方式中源象素中的alpha成分定义了它的透明度。图8.11展示了使用不同模式在检查模式上绘制一个半透明蝴蝶的结果。
图8.11 QPainter的合成模式


       组合模式使用QPainter::setCompositionMode()设置。例如,下面是如何创建一个包含XOR组合的蝴蝶和该检查模式。

[code type="cpp-qt"]
QImage resultImage = checkerPatternImage;
QPainter painter(&resultImage);
painter.setCompositionMode(QPainter::CompositionMode_Xor);
painter.drawImage(0, 0, butterflyImage);
[/code]

       一个要注意的问题是QImage::CompositionMode_Xor操作使用了alpha通过。这意味着如果我们对该白色(0xFFFFFFFF)自身执行XOR操作,我们将得到一个透明色(0x00000000),而不是黑色(0xFF000000)。




原文: http://qtchina.tk/?q=node/240

Powered by zexport