/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2004, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.ui.graphics;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.Transparency;
import java.awt.geom.PathIterator;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBufferByte;
import java.awt.image.DirectColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import javax.swing.Icon;
import org.eclipse.jface.resource.FontRegistry;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
/**
* Provides a bunch of Utility methods for converting between AWT and SWT
*
* @author jesse
* @since 1.1.0
*/
public final class AWTSWTImageUtils {
/**
* Convert an SWT Image to a BufferedImage - this one rips the ImageData
* out of the live Image; and then copies it into a BufferedImage.
*
*/
public static BufferedImage convertToAWT( Image image ){
ImageData data = image.getImageData();
return convertToAWT( data );
}
/**
* Converts an SWT ImageData to a BufferedImage - It isn't incredibly optimized so be careful :)
* <p>
* We should be able to use use JAI to produce a RenderedImage around
* the provided ImageData. It wound be a buffered image but it will be something
* that can efficiently be drawn when printing.
* </p>
* @return a Buffered Image
*/
public static BufferedImage convertToAWT(ImageData data) {
ColorModel colorModel = null;
PaletteData palette = data.palette;
if (palette.isDirect) {
// no alpha data?
if(data.alphaData==null) {
colorModel = new DirectColorModel(32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
BufferedImage bufferedImage = new BufferedImage(colorModel,
colorModel.createCompatibleWritableRaster(data.width, data.height),
false, null);
WritableRaster raster = bufferedImage.getRaster();
int[] pixelArray = new int[4];
for (int y = 0; y < data.height; y++) {
for (int x = 0; x < data.width; x++) {
int pixel = data.getPixel(x, y);
RGB rgb = palette.getRGB(pixel);
pixelArray[0] = rgb.red;
pixelArray[1] = rgb.green;
pixelArray[2] = rgb.blue;
if (pixel == data.transparentPixel) {
pixelArray[3]=0; // transparent
}
else {
pixelArray[3]=255; // opaque
}
raster.setPixels(x, y, 1, 1, pixelArray);
}
}
int w = bufferedImage.getWidth();
int h = bufferedImage.getHeight();
Raster ras = bufferedImage.getData();
for( int i = 0; i < w; i++ ) {
for( int j = 0; j < h; j++ ) {
double[] pixel = ras.getPixel(i, j, new double[4]);
}
}
return bufferedImage;
}
// image has alpha data, preserve it
else {
colorModel = new DirectColorModel(32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
BufferedImage bufferedImage = new BufferedImage(colorModel,
colorModel.createCompatibleWritableRaster(data.width, data.height),
false, null);
WritableRaster raster = bufferedImage.getRaster();
int[] pixelArray = new int[4];
for (int y = 0; y < data.height; y++) {
for (int x = 0; x < data.width; x++) {
int pixel = data.getPixel(x, y);
RGB rgb = palette.getRGB(pixel);
pixelArray[0] = rgb.red;
pixelArray[1] = rgb.green;
pixelArray[2] = rgb.blue;
pixelArray[3]=data.getAlpha(x,y);
raster.setPixels(x, y, 1, 1, pixelArray);
}
}
return bufferedImage;
}
//la paleta swt no es directa �?�?�?
// ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
// colorModel = new DirectColorModel(colorSpace, data.depth, palette.redMask,
// palette.greenMask, palette.blueMask, 0, false, DataBuffer.TYPE_INT);
//// colorModel = new DirectColorModel(data.depth, palette.redMask,
//// palette.greenMask, palette.blueMask);
// BufferedImage bufferedImage = new BufferedImage(colorModel,
// colorModel.createCompatibleWritableRaster(data.width,
// data.height), false, null);
// WritableRaster raster = bufferedImage.getRaster();
// int[] pixelArray = new int[3];
// for (int y = 0; y < data.height; y++) {
// for (int x = 0; x < data.width; x++) {
// int pixel = data.getPixel(x, y);
// RGB rgb = palette.getRGB(pixel);
// pixelArray[0] = rgb.red;
// pixelArray[1] = rgb.green;
// pixelArray[2] = rgb.blue;
// raster.setPixels(x, y, 1, 1, pixelArray);
// }
// }
// return bufferedImage;
} else {
RGB[] rgbs = palette.getRGBs();
byte[] red = new byte[rgbs.length];
byte[] green = new byte[rgbs.length];
byte[] blue = new byte[rgbs.length];
for (int i = 0; i < rgbs.length; i++) {
RGB rgb = rgbs[i];
red[i] = (byte) rgb.red;
green[i] = (byte) rgb.green;
blue[i] = (byte) rgb.blue;
}
if (data.transparentPixel != -1) {
colorModel = new IndexColorModel(data.depth, rgbs.length, red,
green, blue, data.transparentPixel);
} else {
colorModel = new IndexColorModel(data.depth, rgbs.length, red,
green, blue);
}
BufferedImage bufferedImage = new BufferedImage(colorModel,
colorModel.createCompatibleWritableRaster(data.width,
data.height), false, null);
WritableRaster raster = bufferedImage.getRaster();
int[] pixelArray = new int[1];
for (int y = 0; y < data.height; y++) {
for (int x = 0; x < data.width; x++) {
int pixel = data.getPixel(x, y);
pixelArray[0] = pixel;
raster.setPixel(x, y, pixelArray);
}
}
return bufferedImage;
}
}
/**
* Converts the shape to a path object. Remember to dispose of the path object when
* done.
*
* @param shape
* @return the shape converted to a {@link Path} object.
*/
public static Path convertToPath( Shape shape, Device device ) {
AWTSWTImageUtils.checkAccess();
PathIterator p = shape.getPathIterator(SWTGraphics.AFFINE_TRANSFORM);
return AWTSWTImageUtils.createPath(p, device);
}
public static Path createPath( PathIterator p, Device device ) {
if (p.isDone())
return null;
float[] current = new float[6];
Path path = new Path(device);
while( !p.isDone() ) {
int result = p.currentSegment(current);
switch( result ) {
case PathIterator.SEG_CLOSE:
path.close();
break;
case PathIterator.SEG_LINETO:
path.lineTo(current[0], current[1]);
break;
case PathIterator.SEG_MOVETO:
path.moveTo(current[0], current[1]);
break;
case PathIterator.SEG_QUADTO:
path.quadTo(current[0], current[1], current[2],
current[3]);
break;
case PathIterator.SEG_CUBICTO:
path.cubicTo( current[0], current[1], current[2],
current[3], current[4], current[5]);
break;
default:
}
p.next();
}
return path;
}
/**
* Creates an image with a depth of 24 and has a transparency channel.
*
* @param device device to use for creating the image
* @param width the width of the final image
* @param height the height of the final image
* @return an image with a depth of 24 and has a transparency channel.
*/
public static Image createDefaultImage( Device device, int width, int height ) {
AWTSWTImageUtils.checkAccess();
ImageData swtdata = null;
PaletteData palette;
int depth;
depth = 24;
palette = new PaletteData(0xFF0000, 0xFF00, 0xFF);
swtdata = new ImageData(width, height, depth, palette);
swtdata.transparentPixel = -1;
swtdata.alpha = -1;
swtdata.alphaData = new byte[swtdata.data.length];
for( int i = 0; i < swtdata.alphaData.length; i++ ) {
swtdata.alphaData[i] = 0;
}
return new Image(device, swtdata);
}
public static Image createDefaultImage( Display display, int width, int height ) {
AWTSWTImageUtils.checkAccess();
ImageData swtdata = null;
PaletteData palette;
int depth;
depth = 24;
palette = new PaletteData(0xFF0000, 0xFF00, 0xFF);
swtdata = new ImageData(width, height, depth, palette);
swtdata.transparentPixel = 0;
//swtdata.transparentPixel = -1;
swtdata.alpha = -1;
swtdata.alphaData = new byte[swtdata.data.length];
int j=2;
for( int i = 0; i < swtdata.alphaData.length; i++ ) {
swtdata.alphaData[i] = (byte) 255;
}
return new Image(display, swtdata);
}
/** Create a buffered image that can be be converted to SWTland later */
public static BufferedImage createBufferedImage( int w, int h ) {
//AWTSWTImageUtils.checkAccess();
return new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR_PRE);
}
public static Image createSWTImage( RenderedImage image, boolean transparent ) {
AWTSWTImageUtils.checkAccess();
ImageData data;
if( image instanceof BufferedImage ){
data=AWTSWTImageUtils.createImageData((BufferedImage)image);
}else
data = AWTSWTImageUtils.createImageData(image, transparent);
return new org.eclipse.swt.graphics.Image(Display.getDefault(), data);
}
public static ImageData createImageData( RenderedImage image, boolean transparent ) {
AWTSWTImageUtils.checkAccess();
ImageData swtdata = null;
int width = image.getWidth();
int height = image.getHeight();
PaletteData palette;
int depth;
depth = 24;
palette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
swtdata = new ImageData(width, height, depth, palette);
Raster raster = image.getData();
int numbands = raster.getNumBands();
int[] awtdata = raster.getPixels(0, 0, width, height, new int[width * height * numbands]);
int step = swtdata.depth / 8;
byte[] data = swtdata.data;
swtdata.transparentPixel = -1;
int baseindex = 0;
for( int y = 0; y < height; y++ ) {
int idx = ((0 + y) * swtdata.bytesPerLine) + (0 * step);
for( int x = 0; x < width; x++ ) {
int pixel = (x + (y * width));
baseindex = pixel * numbands;
data[idx++] = (byte) awtdata[baseindex + 2];
data[idx++] = (byte) awtdata[baseindex + 1];
data[idx++] = (byte) awtdata[baseindex];
if (numbands == 4 && transparent) {
swtdata.setAlpha(x, y, awtdata[baseindex + 3]);
}
}
}
return swtdata;
}
public static ImageDescriptor createImageDescriptor( final RenderedImage image,
final boolean transparent ) {
AWTSWTImageUtils.checkAccess();
return new ImageDescriptor(){
public ImageData getImageData() {
return createImageData(image, transparent);
}
};
}
/**
* Creates an image descriptor that from the source image.
*
* @param image source image
* @return an image descriptor that from the source image.
*/
public static ImageDescriptor createImageDescriptor( final BufferedImage image ) {
AWTSWTImageUtils.checkAccess();
return new ImageDescriptor(){
public ImageData getImageData() {
return AWTSWTImageUtils.createImageData(image);
}
};
}
/**
* Converts a BufferedImage to an SWT Image. You are responsible for disposing the created image. This
* method is faster than creating a SWT image from a RenderedImage so use this method if possible.
*
* @param image source image.
* @return a swtimage showing the source image.
*/
public static Image convertToSWTImage( BufferedImage image ) {
AWTSWTImageUtils.checkAccess();
ImageData data;
data = AWTSWTImageUtils.createImageData(image);
return new org.eclipse.swt.graphics.Image(Display.getDefault(), data);
}
/**
* Creates an ImageData from the 0,0,width,height section of the source BufferedImage.
* <p>
* This method is faster than creating the ImageData from a RenderedImage so use this method if possible.
* </p>
*
* @param image source image.
* @return an ImageData from the 0,0,width,height section of the source BufferedImage
*/
public static ImageData createImageData( BufferedImage image ) {
AWTSWTImageUtils.checkAccess();
int width = image.getWidth();
int height = image.getHeight();
if (image.getType() == BufferedImage.TYPE_3BYTE_BGR) {
int bands = image.getColorModel().getColorSpace().getNumComponents();
int depth = 24;
byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
PaletteData paletteData = new PaletteData(0x0000ff, 0x00ff00, 0xff0000);
ImageData data = new ImageData(width, height, depth, paletteData, width * bands, pixels);
return data;
}
else if (image.getType() == BufferedImage.TYPE_4BYTE_ABGR) {
int bands = image.getColorModel().getColorSpace().getNumComponents() + 1;
int depth = 32;
byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
PaletteData paletteData = new PaletteData(0x0000ff, 0x00ff00, 0xff0000);
ImageData data = new ImageData(width, height, depth, paletteData, width * bands, pixels);
// scanning darkly
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixel = image.getRGB(x, y);
int alpha_value = (pixel >> 24) & 0x000000FF;
data.setAlpha(x, y, alpha_value );
}
}
return data;
}
// else pixel by pixel
return createImageData((RenderedImage) image, image.getTransparency() != Transparency.OPAQUE);
}
/**
* Converts a RenderedImage to an SWT Image. You are responsible for disposing the created image. This
* method is slower than calling {@link SWTGraphics#createSWTImage(BufferedImage, int, int)}.
*
* @param image source image.
* @param width the width of the final image
* @param height the height of the final image
* @return a swtimage showing the 0,0,width,height rectangle of the source image.
*/
public static Image createSWTImage( RenderedImage image ) {
AWTSWTImageUtils.checkAccess();
ImageData data = AWTSWTImageUtils.createImageData(image);
return new org.eclipse.swt.graphics.Image(Display.getDefault(), data);
}
/**
* Creates an ImageData from the source RenderedImage.
* <p>
* This method is slower than using {@link createImageData}.
* </p>
*
* @param image source image.
* @return an ImageData from the source RenderedImage.
*/
public static ImageData createImageData( RenderedImage image ) {
AWTSWTImageUtils.checkAccess();
if( image instanceof BufferedImage )
return createImageData((BufferedImage)image);
int depth=24;
int width=image.getWidth();
int height=image.getHeight();
byte[] pixels = ((DataBufferByte) image.getTile(0, 0)
.getDataBuffer()).getData();
ImageData data = new ImageData(width, height, depth, new PaletteData(
0xff0000, 0x00ff00, 0x0000ff), width, pixels);
return data;
}
public static java.awt.Color swtColor2awtColor(GC gc, Color swt) {
java.awt.Color awt = new java.awt.Color(swt.getRed(), swt.getGreen(), swt.getBlue(), gc.getAlpha());
return awt;
}
static void checkAccess() {
if( Display.getCurrent() == null )
SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
}
/**
* Converts SWT FontData to a AWT Font
*
* @param fontData the font data
* @return the equivalent AWT font
*/
public static java.awt.Font swtFontToAwt( FontData fontData ) {
int style = java.awt.Font.PLAIN;
if ((fontData.getStyle() & SWT.BOLD) == SWT.BOLD) {
style = java.awt.Font.BOLD;
}
if ((fontData.getStyle() & SWT.ITALIC) == SWT.ITALIC) {
style |= java.awt.Font.ITALIC;
}
java.awt.Font font = new java.awt.Font(fontData.getName(), style, fontData.getHeight());
return font;
}
/**
* Converts an AWTFont to a SWT Font
*
* @param font and AWT Font
* @param fontRegistry
* @return the equivalent SWT Font
*/
public static org.eclipse.swt.graphics.Font awtFontToSwt( java.awt.Font font, FontRegistry fontRegistry ) {
String fontName = font.getFontName();
if (fontRegistry.hasValueFor(fontName)) {
return fontRegistry.get(fontName);
}
int style = 0;
if ((font.getStyle() & java.awt.Font.BOLD) == java.awt.Font.BOLD) {
style = SWT.BOLD;
}
if ((font.getStyle() & java.awt.Font.ITALIC) == java.awt.Font.ITALIC) {
style |= SWT.ITALIC;
}
FontData data = new FontData(fontName, font.getSize(), style);
fontRegistry.put(fontName, new FontData[]{data});
return fontRegistry.get(fontName);
}
/**
* Takes an AWT Font.
*
* @param style
* @return
*/
public static int toFontStyle( java.awt.Font f ){
int s = SWT.NORMAL;
if( f.isItalic()){
s = s | SWT.ITALIC;
}
if( f.isBold() ){
s = s | SWT.BOLD;
}
return s;
}
public static Icon imageDescriptor2awtIcon(final ImageDescriptor imageDescriptor) {
Icon awtIcon = new Icon(){
ImageData imageData = imageDescriptor.getImageData();
public int getIconHeight() {
return imageData.width;
}
public int getIconWidth() {
return imageData.height;
}
public void paintIcon( Component comp, Graphics g, int x, int y ) {
BufferedImage image = convertToAWT(imageData);
g.drawImage(image, x, y, null);
}
};
return awtIcon;
}
/**
* Converts a Swing {@link Icon} to an {@link ImageDescriptor}
*
* @param icon icon to convert
* @return an ImageDescriptor
*/
public static ImageDescriptor awtIcon2ImageDescriptor( final Icon icon ) {
ImageDescriptor descriptor = new ImageDescriptor(){
@Override
public ImageData getImageData() {
BufferedImage image = createBufferedImage(icon.getIconWidth(), icon.getIconHeight());
Graphics2D g = image.createGraphics();
try{
icon.paintIcon(null, g, 0, 0);
}finally{
g.dispose();
}
ImageData data = createImageData(image);
return data;
}
};
return descriptor;
}
}