绘制和提取图像 这个过程的下一步是用 Java 2D
绘制图像。首先取得它的 Graphics2D 上下文。可以用方法 createGraphics2D() 或者调用 getGraphics()
做到这一点。在这个上下文上绘制将会自动修改图像的像素数据。在绘制完成后,可以用方法 getRGB(int startX, int startY, int w,
int h, int rgbArray, int offset, int scansize)
容易且高效地提取图像的像素值。这个方法可以将图像中矩形区域的像素数据传输到一个整数数组中。getRGB() 方法的参数如下:
/** * Helper class allowing the use
of Java 2D on SWT or Draw2D graphical * context. * @author Yannick
Saillet */ public class Graphics2DRenderer { private static final
PaletteData PALETTE_DATA = new PaletteData(0xFF0000, 0xFF00,
0xFF);
/** RGB value to use as transparent color */ private static
final int TRANSPARENT_COLOR = 0x123456;
/** * Prepare to render on a
SWT graphics context. */ public void prepareRendering(GC gc)
{ org.eclipse.swt.graphics.Rectangle clip =
gc.getClipping(); prepareRendering(clip.x, clip.y, clip.width,
clip.height); }
/** * Prepare to render on a Draw2D graphics
context. */ public void prepareRendering(org.eclipse.draw2d.Graphics
graphics) { org.eclipse.draw2d.geometry.Rectangle clip
= graphics.getClip(new
org.eclipse.draw2d.geometry.Rectangle()); prepareRendering(clip.x, clip.y,
clip.width, clip.height); }
/** * Prepare the AWT offscreen image
for the rendering of the rectangular * region given as
parameter. */ private void prepareRendering(int clipX, int clipY, int
clipW, int clipH) { // check that the offscreen images are initialized and
large enough checkOffScreenImages(clipW, clipH); // fill the region in the
AWT image with the transparent color java.awt.Graphics awtGraphics =
awtImage.getGraphics(); awtGraphics.setColor(new
java.awt.Color(TRANSPARENT_COLOR)); awtGraphics.fillRect(clipX, clipY, clipW,
clipH); }
/** * Returns the Graphics2D context to
use. */ public Graphics2D getGraphics2D() { if (awtImage == null)
return null; return (Graphics2D) awtImage.getGraphics(); }
/** *
Complete the rendering by flushing the 2D renderer on a SWT graphical *
context. */ public void render(GC gc) { if (awtImage == null)
return;
/** *
Complete the rendering by flushing the 2D renderer on a Draw2D * graphical
context. */ public void render(org.eclipse.draw2d.Graphics graphics)
{ if (awtImage == null) return;
/** * Transfer a rectangular region from the AWT
image to the SWT image. */ private void transferPixels(int clipX, int
clipY, int clipW, int clipH) { int step = swtImageData.depth / 8; byte[]
data = swtImageData.data; awtImage.getRGB(clipX, clipY, clipW, clipH,
awtPixels, 0, clipW); for (int i = 0; i < clipH; i++) { int idx =
(clipY + i) * swtImageData.bytesPerLine + clipX * step; for (int j = 0; j
< clipW; j++) { int rgb = awtPixels[j + i * clipW]; for (int k =
swtImageData.depth - 8; k >= 0; k -= 8) { data[idx++] = (byte) ((rgb
>> k) & 0xFF); } } } if (swtImage != null)
swtImage.dispose(); swtImage = new Image(Display.getDefault(),
swtImageData); }
/** * Dispose the resources attached to this 2D
renderer. */ public void dispose() { if (awtImage != null)
awtImage.flush(); if (swtImage != null) swtImage.dispose(); awtImage =
null; swtImageData = null; awtPixels = null; }
/** * Ensure
that the offscreen images are initialized and are at least * as large as the
size given as parameter. */ private void checkOffScreenImages(int width,
int height) { int currentImageWidth = 0; int currentImageHeight = 0; if
(swtImage != null) { currentImageWidth =
swtImage.getImageData().width; currentImageHeight =
swtImage.getImageData().height; }
// if the offscreen images are too
small, recreate them if (width > currentImageWidth || height >
currentImageHeight) { dispose(); width = Math.max(width,
currentImageWidth); height = Math.max(height,
currentImageHeight); awtImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB); swtImageData = new ImageData(width, height, 24,
PALETTE_DATA); swtImageData.transparentPixel =
TRANSPARENT_COLOR; awtPixels = new int[width *
height]; } } }
Canvas canvas = new Canvas(shell,
SWT.NO_BACKGROUND); final Graphics2DRenderer renderer = new
Graphics2DRenderer();
canvas.addPaintListener(new PaintListener()
{ public void paintControl(PaintEvent e) { Point controlSize = ((Control)
e.getSource()).getSize();
GC gc = e.gc; // gets the SWT graphics context
from the event
renderer.prepareRendering(gc); // prepares the Graphics2D
renderer
// gets the Graphics2D context and switch on the
antialiasing Graphics2D g2d =
renderer.getGraphics2D(); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//
paints the background with a color gradient g2d.setPaint(new
GradientPaint(0.0f, 0.0f, java.awt.Color.yellow, (float) controlSize.x,
(float) controlSize.y, java.awt.Color.white)); g2d.fillRect(0, 0,
controlSize.x, controlSize.y);
// draws rotated text g2d.setFont(new
java.awt.Font("SansSerif", java.awt.Font.BOLD,
16)); g2d.setColor(java.awt.Color.blue);
g2d.translate(controlSize.x /
2, controlSize.y / 2); int nbOfSlices = 18; for (int i = 0; i <
nbOfSlices; i++) { g2d.drawString("Angle = " + (i * 360 / nbOfSlices) +
"u00B0", 30, 0); g2d.rotate(-2 * Math.PI / nbOfSlices); }
// now
that we are done with Java 2D, renders Graphics2D operation // on the SWT
graphics context renderer.render(gc);
// now we can continue with pure
SWT paint operations gc.drawOval(0, 0, controlSize.x,
controlSize.y); } });