Java 2D Graphics Reading Notes [2]

渲染引擎(Rendering Engine)

所谓渲染是这样一个过程,它处理一组图形,文本和图像的集合,然后计算出在屏幕或者打印机上的像素应该是什么颜色。图形,文本和图像被称为图元(graphics primitives),屏幕和打印机被称为输出设备(output devices),而负责处理这一绘制过程的就是所谓的渲染引擎,在Java 2D API中,其中的2D渲染引擎就是类Graphics2D,Graphics2D同时还表示一个绘制表层(drawing surface),该绘制表层可以是窗口的表面,可以是打印中的页面,还可以是离屏位图。

 

image

渲染引擎把图元绘制到输出设备上

 

渲染流水线(Rendering Pipeline)

渲染引擎的状态

渲染引擎使用内部的状态来决定如何将图元转换成像素颜色,Graphics2D的内部状态一共包括7种元素:

  1. paint 笔刷决定了图形如何填充
  2. stroke 笔画决定了图形的轮廓如何绘制
  3. font 字体决定了文本中的字符生成的图形的形状
  4. transformation 所有的图元在真正渲染前都会先执行几何变换
  5. composting rule 混合规则决定当前绘制的图元的颜色如何跟绘制表层的现有颜色进行混合
  6. clipping shape 裁剪区域决定了有效的绘制区域,如果为空,则整个绘制表层都可以被绘制
  7. rendering hints 渲染示意决定了渲染过程中的可能采用的不同演算法
    所谓渲染流水线就是渲染引擎处理图元绘制的一系列过程,下图显示了Graphics2D内部的7种状态如何影响渲染过程:

    image

    渲染流水线

    在Java 2D API中:

    • fill()方法用于图形的填充
    • draw()方法用于图形轮廓的绘制
    • drawString()方法用于绘制文本
    • drawImage()方法用于绘制图像

    整个绘制过程可分为5步,第一步主要取决于要绘制的图元:

    1. 对于绘制图形轮廓或者绘制文本,实际上都是生成一个轮廓的图形或者文本的图形,然后对生成的图形进行填充,所以实际上只有两种最基本的绘制,图形填充和图像绘制。而第一步就是对图形或者图像进行几何变换;
    2. 对图形进行光栅化,根据图形生成一个像素覆盖值(pixel coverage values)集合,值的大小由该像素跟图形区域的相交状况决定,光栅化的算法通常由渲染示意决定;
    3. 使用裁剪区域设置进行裁剪;
    4. 根据当前的笔刷设置进行图形填充(图像则直接跳过这一步);
    5. 跟绘制表层已有的颜色进行混合,最后输出混合后的颜色;

      Alpha, Alpha, Alpha!!!

      渲染是一个近似的过程。当你希望填充一个理想的图形时,实际上渲染引擎只能试图计算出输出设备的像素应该如何着色来得到一个最逼近绘制图形的结果。举例来说,假设程序要用纯色填充一个图形,有快速但是绘制质量不高的算法,也有绘制质量高但是速度较慢的算法。

      锯齿和反锯齿

      快速的算法就是只填充完全位于图形之内的像素。下图的R则采用了这种算法进行填充:

      image

      狗齿遍布的R

      好的算法则根据像素跟图形交叠的区域计算出一组像素覆盖值,然后以覆盖值作为比例系数来对像素进行着色,这种技术被称为反锯齿。

      image

      经过反锯齿算法渲染的R有着更平滑的边缘

      光栅器(Rasterizer)

      在渲染流水线中,光栅器负责将理想的图形转换成一组像素覆盖值,也就是所谓的alpha值,图像所有alpha值的集合被称为alpha通道。

      像素的alpha值决定了它的透明度,如果把alpha值看作是颜色的一部分,它就是颜色的透明程度。Alpha值位于0.0~1.0之间,0.0代表像素跟图形完全不交叠,1.0则代表像素完全位于图形之内,而反锯齿算法则为部分交叠的像素产生一个0.0~1.0之间的值。

      image

      光栅器使用反锯齿算法产生的alpha值

      然而最终像素的颜色的决定还不仅仅取决于绘制的图形,它还取决于如何跟原有的像素颜色进行混合。

       

      混合(Compositing)

      当光栅器为绘制的图形产生alpha值后,混合规则决定了待绘制的颜色如何跟绘制表层原有的颜色进行混合产生最终的输出颜色,混合规则其实就是一个方程式对每个像素进行计算,最简单的算法就是待绘制的颜色完全取代原有的颜色。

      image

      绘制新的图形到绘制表层

       

      坐标空间(Coordinate Space)

      Java 2D的图形被绘制一个笛卡尔坐标平面上,这个平面被称为所谓的用户空间(User Space)。当实际输出到显示器或者打印机时,用户空间坐标需要被转换成设备空间(Device Space)坐标,通常情况下,设备空间以1像素为1单位。一般而言,用户空间和设备空间是对齐的,默认情况下72个用户空间单位为1英寸,而显示器的DPI值默认刚好是72DPI。也就是说当输出设备是显示器,并且在默认设置下时,1用户空间单位刚好是1像素,并且用户空间到设备空间的转换比例刚好是1:1。(书中的最后一段比较难理解,只能是看到后面的章节再重新回顾这一段…)

      Advertisements