]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/gfx/ImageUtils.java
Sync git svn branch with SVN repository r33269.
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / gfx / ImageUtils.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 /*\r
13  * Created on 12.11.2005\r
14  * @author Toni Kalajainen \r
15  */\r
16 package org.simantics.utils.ui.gfx;\r
17 \r
18 import java.awt.image.BufferedImage;\r
19 import java.awt.image.ColorModel;\r
20 import java.awt.image.ComponentColorModel;\r
21 import java.awt.image.DirectColorModel;\r
22 import java.awt.image.IndexColorModel;\r
23 import java.awt.image.WritableRaster;\r
24 import java.nio.ByteBuffer;\r
25 \r
26 import org.eclipse.swt.graphics.ImageData;\r
27 import org.eclipse.swt.graphics.PaletteData;\r
28 import org.eclipse.swt.graphics.RGB;\r
29 \r
30 public class ImageUtils {\r
31 \r
32     public final static PaletteData RGB24 = new PaletteData(0xff, 0xff00, 0xff0000);\r
33 \r
34     public static ImageData convertPaletteToRGB24(ImageData data) {\r
35         return convertPalette(data, RGB24, 24);\r
36     }\r
37 \r
38     /**\r
39      * Converts image data to RGB format\r
40      * \r
41      * @param data source data\r
42      * @return result data\r
43      */\r
44     public static ImageData convertPalette(ImageData data, PaletteData newPalette, int newDepth) {\r
45         if (paletteDataEquals(data.palette, newPalette))\r
46             return data;\r
47         ImageData result = new ImageData(data.width, data.height, newDepth, newPalette);\r
48         boolean hasAlpha = data.alphaData != null;\r
49         int width = data.width;\r
50         int height = data.height;\r
51         // Very slow operation\r
52         for (int y = 0; y < height; y++)\r
53             for (int x = 0; x < width; x++) {\r
54                 // convert RGBs\r
55                 RGB rgb = data.palette.getRGB(data.getPixel(x, y));\r
56                 result.setPixel(x, y, result.palette.getPixel(rgb));\r
57 \r
58                 // convert alpha\r
59                 if (hasAlpha) {\r
60                     int alpha = data.getAlpha(x, y);\r
61                     result.setAlpha(x, y, alpha);\r
62                 }\r
63             }\r
64         return result;\r
65     }\r
66 \r
67     /**\r
68      * Convert Device-independent image data format from one format to another.\r
69      * \r
70      * @param sourceImage source image, it must contain image data\r
71      * @param destImage destination image, it must be empty image\r
72      */\r
73     // public static void convertImageData(ImageData sourceImage, ImageData\r
74     // destImage) {\r
75     // int swid = sourceImage.width;\r
76     // int shei = sourceImage.height;\r
77     // int dwid = destImage.width;\r
78     // int dhei = destImage.height;\r
79     //        \r
80     // // resize\r
81     // if (swid!=dwid || shei!=dhei)\r
82     // sourceImage = sourceImage.scaledTo(dwid, dhei);\r
83     //        \r
84     // // Convert palette\r
85     // PaletteData spal = sourceImage.palette;\r
86     // PaletteData dpal = destImage.palette;\r
87     // }\r
88     public static boolean paletteDataEquals(PaletteData p1, PaletteData p2) {\r
89         if (p1.isDirect != p2.isDirect)\r
90             return false;\r
91         if (!p1.isDirect) {\r
92             RGB rgb1[] = p1.colors;\r
93             RGB rgb2[] = p2.colors;\r
94             if (rgb1.length != rgb2.length)\r
95                 return false;\r
96             for (int i = 0; i < rgb1.length; i++)\r
97                 if (rgb1[i].blue != rgb2[i].blue || rgb1[i].green != rgb2[i].green || rgb1[i].red != rgb2[i].red)\r
98                     return false;\r
99             return true;\r
100         }\r
101 \r
102         if (p1.blueMask != p2.blueMask)\r
103             return false;\r
104         if (p1.blueShift != p2.blueShift)\r
105             return false;\r
106         if (p1.greenMask != p2.greenShift)\r
107             return false;\r
108         if (p1.greenMask != p2.greenMask)\r
109             return false;\r
110         if (p1.redMask != p2.redMask)\r
111             return false;\r
112         if (p1.redShift != p2.redShift)\r
113             return false;\r
114 \r
115         return true;\r
116     }\r
117 \r
118     // ks. org.eclipse.gmf.runtime.draw2d.ui.render.image.ImageConverter\r
119     // Sama toiminnallisuus, mutta GMF riippuvuus\r
120     public static BufferedImage convertToAWT(ImageData data) {\r
121         ColorModel colorModel = null;\r
122         PaletteData palette = data.palette;\r
123         if (palette.isDirect) {\r
124             // has alpha and is 24bit (others are not supported)\r
125             if (data.alphaData != null && data.depth==24) {\r
126                 colorModel = new DirectColorModel(data.depth+8, palette.redMask, palette.greenMask, palette.blueMask, 0xff000000);\r
127                 BufferedImage bufferedImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(data.width, data.height), false, null);\r
128                 WritableRaster raster = bufferedImage.getRaster();\r
129                 int[] pixelArray = new int[4];\r
130                 for (int y = 0; y < data.height; y++) {\r
131                     for (int x = 0; x < data.width; x++) {\r
132                         int pixel = data.getPixel(x, y);\r
133                         RGB rgb = palette.getRGB(pixel);\r
134                         pixelArray[0] = rgb.red;\r
135                         pixelArray[1] = rgb.green;\r
136                         pixelArray[2] = rgb.blue;\r
137                         pixelArray[3] = data.getAlpha(x, y);\r
138                         raster.setPixels(x, y, 1, 1, pixelArray);\r
139                     }\r
140                 }\r
141                 return bufferedImage;\r
142             } else {\r
143                 // FIXME: this does not work with 16bit images (colors are wrong)\r
144                 colorModel = new DirectColorModel(data.depth, palette.redMask, palette.greenMask, palette.blueMask);\r
145                 BufferedImage bufferedImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(data.width, data.height), false, null);\r
146                 WritableRaster raster = bufferedImage.getRaster();\r
147                 int[] pixelArray = new int[3];\r
148                 for (int y = 0; y < data.height; y++) {\r
149                     for (int x = 0; x < data.width; x++) {\r
150                         int pixel = data.getPixel(x, y);\r
151                         RGB rgb = palette.getRGB(pixel);\r
152                         pixelArray[0] = rgb.red;\r
153                         pixelArray[1] = rgb.green;\r
154                         pixelArray[2] = rgb.blue;\r
155                         raster.setPixels(x, y, 1, 1, pixelArray);\r
156                     }\r
157                 }\r
158                 return bufferedImage;\r
159             }\r
160         } else {\r
161             RGB[] rgbs = palette.getRGBs();\r
162             byte[] red = new byte[rgbs.length];\r
163             byte[] green = new byte[rgbs.length];\r
164             byte[] blue = new byte[rgbs.length];\r
165             for (int i = 0; i < rgbs.length; i++) {\r
166                 RGB rgb = rgbs[i];\r
167                 red[i] = (byte) rgb.red;\r
168                 green[i] = (byte) rgb.green;\r
169                 blue[i] = (byte) rgb.blue;\r
170             }\r
171             if (data.transparentPixel != -1) {\r
172                 colorModel = new IndexColorModel(data.depth, rgbs.length, red, green, blue, data.transparentPixel);\r
173             } else {\r
174                 colorModel = new IndexColorModel(data.depth, rgbs.length, red, green, blue);\r
175             }\r
176             BufferedImage bufferedImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(data.width, data.height), false, null);\r
177             WritableRaster raster = bufferedImage.getRaster();\r
178             int[] pixelArray = new int[1];\r
179             for (int y = 0; y < data.height; y++) {\r
180                 for (int x = 0; x < data.width; x++) {\r
181                     int pixel = data.getPixel(x, y);\r
182                     pixelArray[0] = pixel;\r
183                     raster.setPixel(x, y, pixelArray);\r
184                 }\r
185             }\r
186             return bufferedImage;\r
187         }\r
188     }\r
189 \r
190     public static ImageData convertToSWT(BufferedImage bufferedImage) {\r
191         if (bufferedImage.getColorModel() instanceof DirectColorModel) {\r
192             DirectColorModel colorModel = (DirectColorModel) bufferedImage.getColorModel();\r
193             PaletteData palette = new PaletteData(colorModel.getRedMask(), colorModel.getGreenMask(), colorModel.getBlueMask());\r
194             ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette);\r
195             WritableRaster raster = bufferedImage.getRaster();\r
196             int[] pixelArray = { 0, 0, 0, 255 };\r
197             for (int y = 0; y < data.height; y++) {\r
198                 for (int x = 0; x < data.width; x++) {\r
199                     raster.getPixel(x, y, pixelArray);\r
200                     int pixel = palette.getPixel(new RGB(pixelArray[0], pixelArray[1], pixelArray[2]));\r
201                     data.setPixel(x, y, pixel);\r
202                     data.setAlpha(x, y, pixelArray[3]);\r
203                 }\r
204             }\r
205             return data;\r
206         } else if (bufferedImage.getColorModel() instanceof IndexColorModel) {\r
207             IndexColorModel colorModel = (IndexColorModel) bufferedImage.getColorModel();\r
208             int size = colorModel.getMapSize();\r
209             byte[] reds = new byte[size];\r
210             byte[] greens = new byte[size];\r
211             byte[] blues = new byte[size];\r
212             colorModel.getReds(reds);\r
213             colorModel.getGreens(greens);\r
214             colorModel.getBlues(blues);\r
215             RGB[] rgbs = new RGB[size];\r
216             for (int i = 0; i < rgbs.length; i++) {\r
217                 rgbs[i] = new RGB(reds[i] & 0xFF, greens[i] & 0xFF, blues[i] & 0xFF);\r
218             }\r
219             PaletteData palette = new PaletteData(rgbs);\r
220             ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette);\r
221             data.transparentPixel = colorModel.getTransparentPixel();\r
222             WritableRaster raster = bufferedImage.getRaster();\r
223             int[] pixelArray = new int[1];\r
224             for (int y = 0; y < data.height; y++) {\r
225                 for (int x = 0; x < data.width; x++) {\r
226                     raster.getPixel(x, y, pixelArray);\r
227                     data.setPixel(x, y, pixelArray[0]);\r
228                 }\r
229             }\r
230             return data;\r
231         }  else if (bufferedImage.getColorModel() instanceof ComponentColorModel) {\r
232                 // works with BufferedImage.TYPE_3BYTE_BGR\r
233                  ComponentColorModel colorModel = (ComponentColorModel)bufferedImage.getColorModel();\r
234                  PaletteData palette = new PaletteData(0xFF0000, 0x00FF00, 0x0000FF);\r
235              ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette);\r
236              WritableRaster raster = bufferedImage.getRaster();\r
237              int[] pixelArray = { 0, 0, 0, 255 };\r
238              for (int y = 0; y < data.height; y++) {\r
239                  for (int x = 0; x < data.width; x++) {\r
240                      raster.getPixel(x, y, pixelArray);\r
241                      int pixel = palette.getPixel(new RGB(pixelArray[0], pixelArray[1], pixelArray[2]));\r
242                      data.setPixel(x, y, pixel);\r
243                      data.setAlpha(x, y, pixelArray[3]);\r
244                  }\r
245              }\r
246              return data;\r
247         }\r
248         return null;\r
249     }\r
250 \r
251     /**\r
252      * Creates ImageData from RGBA byte array\r
253      * \r
254      * @param width width of the image\r
255      * @param height height of the image\r
256      * @param data data of the image\r
257      * @return <code>ImageData</code>\r
258      */\r
259     public static ImageData _getImageDataFromRGBA(int width, int height, byte[] data) {\r
260         // these seem to do nothing, r and b channels are flipped anyways\r
261         int redMask = 0x0000ff00;\r
262         int greenMask = 0x00ff0000;\r
263         int blueMask = 0xff000000;\r
264         PaletteData paletteData = new PaletteData(redMask, greenMask, blueMask);\r
265         // flipping r and b channels\r
266         int maxByte = width * height * 4;\r
267         byte t;\r
268         for (int i = 0; i < maxByte; i += 4) {\r
269             t = data[i];\r
270             data[i] = data[i + 2];\r
271             data[i + 2] = t;\r
272         }\r
273         ImageData imageData = new ImageData(width, height, 32, paletteData, 4, data);\r
274         // TODO add alpha channel\r
275         // imageData.alphaData = xyz\r
276         return imageData;\r
277     }\r
278     \r
279     \r
280     /**\r
281      * Converts ImageData to RGB(A) ByteBuffer\r
282      * @param imageData\r
283      * @param buffer\r
284      */\r
285     public static void convertToRGBA(ImageData imageData, ByteBuffer buffer) {\r
286         int width = imageData.width;\r
287         int height = imageData.height;\r
288         if (!imageData.palette.isDirect || imageData.depth != 24) {\r
289                 ImageUtils.convertPaletteToRGB24(imageData);\r
290         }\r
291         boolean hasAlpha = false;\r
292         if (imageData.alphaData != null) {\r
293                 hasAlpha = true;\r
294         }\r
295         int index;\r
296         RGB rgb;\r
297         for (int j = 0; j < height; j++) {\r
298                 for (int i = 0; i < width; i++) {\r
299                          index = j*width + i;\r
300                          rgb = imageData.palette.getRGB(imageData.getPixel(i, j));\r
301                          buffer.put((byte)rgb.red);\r
302                          buffer.put((byte)rgb.green);\r
303                          buffer.put((byte)rgb.blue);\r
304                          if (hasAlpha) {\r
305                                  buffer.put(imageData.alphaData[index]);\r
306                          }\r
307                 }\r
308         }\r
309         \r
310     }\r
311 \r
312 }\r