1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
13 * Created on 12.11.2005
14 * @author Toni Kalajainen
16 package org.simantics.utils.ui.gfx;
18 import java.awt.image.BufferedImage;
19 import java.awt.image.ColorModel;
20 import java.awt.image.ComponentColorModel;
21 import java.awt.image.DirectColorModel;
22 import java.awt.image.IndexColorModel;
23 import java.awt.image.WritableRaster;
24 import java.nio.ByteBuffer;
26 import org.eclipse.swt.graphics.ImageData;
27 import org.eclipse.swt.graphics.PaletteData;
28 import org.eclipse.swt.graphics.RGB;
30 public class ImageUtils {
32 public final static PaletteData RGB24 = new PaletteData(0xff, 0xff00, 0xff0000);
34 public static ImageData convertPaletteToRGB24(ImageData data) {
35 return convertPalette(data, RGB24, 24);
39 * Converts image data to RGB format
41 * @param data source data
44 public static ImageData convertPalette(ImageData data, PaletteData newPalette, int newDepth) {
45 if (paletteDataEquals(data.palette, newPalette))
47 ImageData result = new ImageData(data.width, data.height, newDepth, newPalette);
48 boolean hasAlpha = data.alphaData != null;
49 int width = data.width;
50 int height = data.height;
51 // Very slow operation
52 for (int y = 0; y < height; y++)
53 for (int x = 0; x < width; x++) {
55 RGB rgb = data.palette.getRGB(data.getPixel(x, y));
56 result.setPixel(x, y, result.palette.getPixel(rgb));
60 int alpha = data.getAlpha(x, y);
61 result.setAlpha(x, y, alpha);
68 * Convert Device-independent image data format from one format to another.
70 * @param sourceImage source image, it must contain image data
71 * @param destImage destination image, it must be empty image
73 // public static void convertImageData(ImageData sourceImage, ImageData
75 // int swid = sourceImage.width;
76 // int shei = sourceImage.height;
77 // int dwid = destImage.width;
78 // int dhei = destImage.height;
81 // if (swid!=dwid || shei!=dhei)
82 // sourceImage = sourceImage.scaledTo(dwid, dhei);
85 // PaletteData spal = sourceImage.palette;
86 // PaletteData dpal = destImage.palette;
88 public static boolean paletteDataEquals(PaletteData p1, PaletteData p2) {
89 if (p1.isDirect != p2.isDirect)
92 RGB rgb1[] = p1.colors;
93 RGB rgb2[] = p2.colors;
94 if (rgb1.length != rgb2.length)
96 for (int i = 0; i < rgb1.length; i++)
97 if (rgb1[i].blue != rgb2[i].blue || rgb1[i].green != rgb2[i].green || rgb1[i].red != rgb2[i].red)
102 if (p1.blueMask != p2.blueMask)
104 if (p1.blueShift != p2.blueShift)
106 if (p1.greenMask != p2.greenShift)
108 if (p1.greenMask != p2.greenMask)
110 if (p1.redMask != p2.redMask)
112 if (p1.redShift != p2.redShift)
118 // ks. org.eclipse.gmf.runtime.draw2d.ui.render.image.ImageConverter
119 // Sama toiminnallisuus, mutta GMF riippuvuus
120 public static BufferedImage convertToAWT(ImageData data) {
121 ColorModel colorModel = null;
122 PaletteData palette = data.palette;
123 if (palette.isDirect) {
124 // has alpha and is 24bit (others are not supported)
125 if (data.alphaData != null && data.depth==24) {
126 colorModel = new DirectColorModel(data.depth+8, palette.redMask, palette.greenMask, palette.blueMask, 0xff000000);
127 BufferedImage bufferedImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(data.width, data.height), false, null);
128 WritableRaster raster = bufferedImage.getRaster();
129 int[] pixelArray = new int[4];
130 for (int y = 0; y < data.height; y++) {
131 for (int x = 0; x < data.width; x++) {
132 int pixel = data.getPixel(x, y);
133 RGB rgb = palette.getRGB(pixel);
134 pixelArray[0] = rgb.red;
135 pixelArray[1] = rgb.green;
136 pixelArray[2] = rgb.blue;
137 pixelArray[3] = data.getAlpha(x, y);
138 raster.setPixels(x, y, 1, 1, pixelArray);
141 return bufferedImage;
143 // FIXME: this does not work with 16bit images (colors are wrong)
144 colorModel = new DirectColorModel(data.depth, palette.redMask, palette.greenMask, palette.blueMask);
145 BufferedImage bufferedImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(data.width, data.height), false, null);
146 WritableRaster raster = bufferedImage.getRaster();
147 int[] pixelArray = new int[3];
148 for (int y = 0; y < data.height; y++) {
149 for (int x = 0; x < data.width; x++) {
150 int pixel = data.getPixel(x, y);
151 RGB rgb = palette.getRGB(pixel);
152 pixelArray[0] = rgb.red;
153 pixelArray[1] = rgb.green;
154 pixelArray[2] = rgb.blue;
155 raster.setPixels(x, y, 1, 1, pixelArray);
158 return bufferedImage;
161 RGB[] rgbs = palette.getRGBs();
162 byte[] red = new byte[rgbs.length];
163 byte[] green = new byte[rgbs.length];
164 byte[] blue = new byte[rgbs.length];
165 for (int i = 0; i < rgbs.length; i++) {
167 red[i] = (byte) rgb.red;
168 green[i] = (byte) rgb.green;
169 blue[i] = (byte) rgb.blue;
171 if (data.transparentPixel != -1) {
172 colorModel = new IndexColorModel(data.depth, rgbs.length, red, green, blue, data.transparentPixel);
174 colorModel = new IndexColorModel(data.depth, rgbs.length, red, green, blue);
176 BufferedImage bufferedImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(data.width, data.height), false, null);
177 WritableRaster raster = bufferedImage.getRaster();
178 int[] pixelArray = new int[1];
179 for (int y = 0; y < data.height; y++) {
180 for (int x = 0; x < data.width; x++) {
181 int pixel = data.getPixel(x, y);
182 pixelArray[0] = pixel;
183 raster.setPixel(x, y, pixelArray);
186 return bufferedImage;
190 public static ImageData convertToSWT(BufferedImage bufferedImage) {
191 if (bufferedImage.getColorModel() instanceof DirectColorModel) {
192 DirectColorModel colorModel = (DirectColorModel) bufferedImage.getColorModel();
193 PaletteData palette = new PaletteData(colorModel.getRedMask(), colorModel.getGreenMask(), colorModel.getBlueMask());
194 ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette);
195 WritableRaster raster = bufferedImage.getRaster();
196 int[] pixelArray = { 0, 0, 0, 255 };
197 for (int y = 0; y < data.height; y++) {
198 for (int x = 0; x < data.width; x++) {
199 raster.getPixel(x, y, pixelArray);
200 int pixel = palette.getPixel(new RGB(pixelArray[0], pixelArray[1], pixelArray[2]));
201 data.setPixel(x, y, pixel);
202 data.setAlpha(x, y, pixelArray[3]);
206 } else if (bufferedImage.getColorModel() instanceof IndexColorModel) {
207 IndexColorModel colorModel = (IndexColorModel) bufferedImage.getColorModel();
208 int size = colorModel.getMapSize();
209 byte[] reds = new byte[size];
210 byte[] greens = new byte[size];
211 byte[] blues = new byte[size];
212 colorModel.getReds(reds);
213 colorModel.getGreens(greens);
214 colorModel.getBlues(blues);
215 RGB[] rgbs = new RGB[size];
216 for (int i = 0; i < rgbs.length; i++) {
217 rgbs[i] = new RGB(reds[i] & 0xFF, greens[i] & 0xFF, blues[i] & 0xFF);
219 PaletteData palette = new PaletteData(rgbs);
220 ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette);
221 data.transparentPixel = colorModel.getTransparentPixel();
222 WritableRaster raster = bufferedImage.getRaster();
223 int[] pixelArray = new int[1];
224 for (int y = 0; y < data.height; y++) {
225 for (int x = 0; x < data.width; x++) {
226 raster.getPixel(x, y, pixelArray);
227 data.setPixel(x, y, pixelArray[0]);
231 } else if (bufferedImage.getColorModel() instanceof ComponentColorModel) {
232 // works with BufferedImage.TYPE_3BYTE_BGR
233 ComponentColorModel colorModel = (ComponentColorModel)bufferedImage.getColorModel();
234 PaletteData palette = new PaletteData(0xFF0000, 0x00FF00, 0x0000FF);
235 ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette);
236 WritableRaster raster = bufferedImage.getRaster();
237 int[] pixelArray = { 0, 0, 0, 255 };
238 for (int y = 0; y < data.height; y++) {
239 for (int x = 0; x < data.width; x++) {
240 raster.getPixel(x, y, pixelArray);
241 int pixel = palette.getPixel(new RGB(pixelArray[0], pixelArray[1], pixelArray[2]));
242 data.setPixel(x, y, pixel);
243 data.setAlpha(x, y, pixelArray[3]);
252 * Creates ImageData from RGBA byte array
254 * @param width width of the image
255 * @param height height of the image
256 * @param data data of the image
257 * @return <code>ImageData</code>
259 public static ImageData _getImageDataFromRGBA(int width, int height, byte[] data) {
260 // these seem to do nothing, r and b channels are flipped anyways
261 int redMask = 0x0000ff00;
262 int greenMask = 0x00ff0000;
263 int blueMask = 0xff000000;
264 PaletteData paletteData = new PaletteData(redMask, greenMask, blueMask);
265 // flipping r and b channels
266 int maxByte = width * height * 4;
268 for (int i = 0; i < maxByte; i += 4) {
270 data[i] = data[i + 2];
273 ImageData imageData = new ImageData(width, height, 32, paletteData, 4, data);
274 // TODO add alpha channel
275 // imageData.alphaData = xyz
281 * Converts ImageData to RGB(A) ByteBuffer
285 public static void convertToRGBA(ImageData imageData, ByteBuffer buffer) {
286 int width = imageData.width;
287 int height = imageData.height;
288 if (!imageData.palette.isDirect || imageData.depth != 24) {
289 ImageUtils.convertPaletteToRGB24(imageData);
291 boolean hasAlpha = false;
292 if (imageData.alphaData != null) {
297 for (int j = 0; j < height; j++) {
298 for (int i = 0; i < width; i++) {
300 rgb = imageData.palette.getRGB(imageData.getPixel(i, j));
301 buffer.put((byte)rgb.red);
302 buffer.put((byte)rgb.green);
303 buffer.put((byte)rgb.blue);
305 buffer.put(imageData.alphaData[index]);