]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/gfx/ImageUtils.java
Fixed a bug related to the extent of variable frames (see test case)
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / gfx / ImageUtils.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 /*
13  * Created on 12.11.2005
14  * @author Toni Kalajainen 
15  */
16 package org.simantics.utils.ui.gfx;
17
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;
25
26 import org.eclipse.swt.graphics.ImageData;
27 import org.eclipse.swt.graphics.PaletteData;
28 import org.eclipse.swt.graphics.RGB;
29
30 public class ImageUtils {
31
32     public final static PaletteData RGB24 = new PaletteData(0xff, 0xff00, 0xff0000);
33
34     public static ImageData convertPaletteToRGB24(ImageData data) {
35         return convertPalette(data, RGB24, 24);
36     }
37
38     /**
39      * Converts image data to RGB format
40      * 
41      * @param data source data
42      * @return result data
43      */
44     public static ImageData convertPalette(ImageData data, PaletteData newPalette, int newDepth) {
45         if (paletteDataEquals(data.palette, newPalette))
46             return data;
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++) {
54                 // convert RGBs
55                 RGB rgb = data.palette.getRGB(data.getPixel(x, y));
56                 result.setPixel(x, y, result.palette.getPixel(rgb));
57
58                 // convert alpha
59                 if (hasAlpha) {
60                     int alpha = data.getAlpha(x, y);
61                     result.setAlpha(x, y, alpha);
62                 }
63             }
64         return result;
65     }
66
67     /**
68      * Convert Device-independent image data format from one format to another.
69      * 
70      * @param sourceImage source image, it must contain image data
71      * @param destImage destination image, it must be empty image
72      */
73     // public static void convertImageData(ImageData sourceImage, ImageData
74     // destImage) {
75     // int swid = sourceImage.width;
76     // int shei = sourceImage.height;
77     // int dwid = destImage.width;
78     // int dhei = destImage.height;
79     //        
80     // // resize
81     // if (swid!=dwid || shei!=dhei)
82     // sourceImage = sourceImage.scaledTo(dwid, dhei);
83     //        
84     // // Convert palette
85     // PaletteData spal = sourceImage.palette;
86     // PaletteData dpal = destImage.palette;
87     // }
88     public static boolean paletteDataEquals(PaletteData p1, PaletteData p2) {
89         if (p1.isDirect != p2.isDirect)
90             return false;
91         if (!p1.isDirect) {
92             RGB rgb1[] = p1.colors;
93             RGB rgb2[] = p2.colors;
94             if (rgb1.length != rgb2.length)
95                 return false;
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)
98                     return false;
99             return true;
100         }
101
102         if (p1.blueMask != p2.blueMask)
103             return false;
104         if (p1.blueShift != p2.blueShift)
105             return false;
106         if (p1.greenMask != p2.greenShift)
107             return false;
108         if (p1.greenMask != p2.greenMask)
109             return false;
110         if (p1.redMask != p2.redMask)
111             return false;
112         if (p1.redShift != p2.redShift)
113             return false;
114
115         return true;
116     }
117
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);
139                     }
140                 }
141                 return bufferedImage;
142             } else {
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);
156                     }
157                 }
158                 return bufferedImage;
159             }
160         } else {
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++) {
166                 RGB rgb = rgbs[i];
167                 red[i] = (byte) rgb.red;
168                 green[i] = (byte) rgb.green;
169                 blue[i] = (byte) rgb.blue;
170             }
171             if (data.transparentPixel != -1) {
172                 colorModel = new IndexColorModel(data.depth, rgbs.length, red, green, blue, data.transparentPixel);
173             } else {
174                 colorModel = new IndexColorModel(data.depth, rgbs.length, red, green, blue);
175             }
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);
184                 }
185             }
186             return bufferedImage;
187         }
188     }
189
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]);
203                 }
204             }
205             return data;
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);
218             }
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]);
228                 }
229             }
230             return data;
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]);
244                  }
245              }
246              return data;
247         }
248         return null;
249     }
250
251     /**
252      * Creates ImageData from RGBA byte array
253      * 
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>
258      */
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;
267         byte t;
268         for (int i = 0; i < maxByte; i += 4) {
269             t = data[i];
270             data[i] = data[i + 2];
271             data[i + 2] = t;
272         }
273         ImageData imageData = new ImageData(width, height, 32, paletteData, 4, data);
274         // TODO add alpha channel
275         // imageData.alphaData = xyz
276         return imageData;
277     }
278     
279     
280     /**
281      * Converts ImageData to RGB(A) ByteBuffer
282      * @param imageData
283      * @param buffer
284      */
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);
290         }
291         boolean hasAlpha = false;
292         if (imageData.alphaData != null) {
293                 hasAlpha = true;
294         }
295         int index;
296         RGB rgb;
297         for (int j = 0; j < height; j++) {
298                 for (int i = 0; i < width; i++) {
299                          index = j*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);
304                          if (hasAlpha) {
305                                  buffer.put(imageData.alphaData[index]);
306                          }
307                 }
308         }
309         
310     }
311
312 }