--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+/*\r
+ * Created on 12.11.2005\r
+ * @author Toni Kalajainen \r
+ */\r
+package org.simantics.utils.ui.gfx;\r
+\r
+import java.awt.image.BufferedImage;\r
+import java.awt.image.ColorModel;\r
+import java.awt.image.ComponentColorModel;\r
+import java.awt.image.DirectColorModel;\r
+import java.awt.image.IndexColorModel;\r
+import java.awt.image.WritableRaster;\r
+import java.nio.ByteBuffer;\r
+\r
+import org.eclipse.swt.graphics.ImageData;\r
+import org.eclipse.swt.graphics.PaletteData;\r
+import org.eclipse.swt.graphics.RGB;\r
+\r
+public class ImageUtils {\r
+\r
+ public final static PaletteData RGB24 = new PaletteData(0xff, 0xff00, 0xff0000);\r
+\r
+ public static ImageData convertPaletteToRGB24(ImageData data) {\r
+ return convertPalette(data, RGB24, 24);\r
+ }\r
+\r
+ /**\r
+ * Converts image data to RGB format\r
+ * \r
+ * @param data source data\r
+ * @return result data\r
+ */\r
+ public static ImageData convertPalette(ImageData data, PaletteData newPalette, int newDepth) {\r
+ if (paletteDataEquals(data.palette, newPalette))\r
+ return data;\r
+ ImageData result = new ImageData(data.width, data.height, newDepth, newPalette);\r
+ boolean hasAlpha = data.alphaData != null;\r
+ int width = data.width;\r
+ int height = data.height;\r
+ // Very slow operation\r
+ for (int y = 0; y < height; y++)\r
+ for (int x = 0; x < width; x++) {\r
+ // convert RGBs\r
+ RGB rgb = data.palette.getRGB(data.getPixel(x, y));\r
+ result.setPixel(x, y, result.palette.getPixel(rgb));\r
+\r
+ // convert alpha\r
+ if (hasAlpha) {\r
+ int alpha = data.getAlpha(x, y);\r
+ result.setAlpha(x, y, alpha);\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ * Convert Device-independent image data format from one format to another.\r
+ * \r
+ * @param sourceImage source image, it must contain image data\r
+ * @param destImage destination image, it must be empty image\r
+ */\r
+ // public static void convertImageData(ImageData sourceImage, ImageData\r
+ // destImage) {\r
+ // int swid = sourceImage.width;\r
+ // int shei = sourceImage.height;\r
+ // int dwid = destImage.width;\r
+ // int dhei = destImage.height;\r
+ // \r
+ // // resize\r
+ // if (swid!=dwid || shei!=dhei)\r
+ // sourceImage = sourceImage.scaledTo(dwid, dhei);\r
+ // \r
+ // // Convert palette\r
+ // PaletteData spal = sourceImage.palette;\r
+ // PaletteData dpal = destImage.palette;\r
+ // }\r
+ public static boolean paletteDataEquals(PaletteData p1, PaletteData p2) {\r
+ if (p1.isDirect != p2.isDirect)\r
+ return false;\r
+ if (!p1.isDirect) {\r
+ RGB rgb1[] = p1.colors;\r
+ RGB rgb2[] = p2.colors;\r
+ if (rgb1.length != rgb2.length)\r
+ return false;\r
+ for (int i = 0; i < rgb1.length; i++)\r
+ if (rgb1[i].blue != rgb2[i].blue || rgb1[i].green != rgb2[i].green || rgb1[i].red != rgb2[i].red)\r
+ return false;\r
+ return true;\r
+ }\r
+\r
+ if (p1.blueMask != p2.blueMask)\r
+ return false;\r
+ if (p1.blueShift != p2.blueShift)\r
+ return false;\r
+ if (p1.greenMask != p2.greenShift)\r
+ return false;\r
+ if (p1.greenMask != p2.greenMask)\r
+ return false;\r
+ if (p1.redMask != p2.redMask)\r
+ return false;\r
+ if (p1.redShift != p2.redShift)\r
+ return false;\r
+\r
+ return true;\r
+ }\r
+\r
+ // ks. org.eclipse.gmf.runtime.draw2d.ui.render.image.ImageConverter\r
+ // Sama toiminnallisuus, mutta GMF riippuvuus\r
+ public static BufferedImage convertToAWT(ImageData data) {\r
+ ColorModel colorModel = null;\r
+ PaletteData palette = data.palette;\r
+ if (palette.isDirect) {\r
+ // has alpha and is 24bit (others are not supported)\r
+ if (data.alphaData != null && data.depth==24) {\r
+ colorModel = new DirectColorModel(data.depth+8, palette.redMask, palette.greenMask, palette.blueMask, 0xff000000);\r
+ BufferedImage bufferedImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(data.width, data.height), false, null);\r
+ WritableRaster raster = bufferedImage.getRaster();\r
+ int[] pixelArray = new int[4];\r
+ for (int y = 0; y < data.height; y++) {\r
+ for (int x = 0; x < data.width; x++) {\r
+ int pixel = data.getPixel(x, y);\r
+ RGB rgb = palette.getRGB(pixel);\r
+ pixelArray[0] = rgb.red;\r
+ pixelArray[1] = rgb.green;\r
+ pixelArray[2] = rgb.blue;\r
+ pixelArray[3] = data.getAlpha(x, y);\r
+ raster.setPixels(x, y, 1, 1, pixelArray);\r
+ }\r
+ }\r
+ return bufferedImage;\r
+ } else {\r
+ // FIXME: this does not work with 16bit images (colors are wrong)\r
+ colorModel = new DirectColorModel(data.depth, palette.redMask, palette.greenMask, palette.blueMask);\r
+ BufferedImage bufferedImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(data.width, data.height), false, null);\r
+ WritableRaster raster = bufferedImage.getRaster();\r
+ int[] pixelArray = new int[3];\r
+ for (int y = 0; y < data.height; y++) {\r
+ for (int x = 0; x < data.width; x++) {\r
+ int pixel = data.getPixel(x, y);\r
+ RGB rgb = palette.getRGB(pixel);\r
+ pixelArray[0] = rgb.red;\r
+ pixelArray[1] = rgb.green;\r
+ pixelArray[2] = rgb.blue;\r
+ raster.setPixels(x, y, 1, 1, pixelArray);\r
+ }\r
+ }\r
+ return bufferedImage;\r
+ }\r
+ } else {\r
+ RGB[] rgbs = palette.getRGBs();\r
+ byte[] red = new byte[rgbs.length];\r
+ byte[] green = new byte[rgbs.length];\r
+ byte[] blue = new byte[rgbs.length];\r
+ for (int i = 0; i < rgbs.length; i++) {\r
+ RGB rgb = rgbs[i];\r
+ red[i] = (byte) rgb.red;\r
+ green[i] = (byte) rgb.green;\r
+ blue[i] = (byte) rgb.blue;\r
+ }\r
+ if (data.transparentPixel != -1) {\r
+ colorModel = new IndexColorModel(data.depth, rgbs.length, red, green, blue, data.transparentPixel);\r
+ } else {\r
+ colorModel = new IndexColorModel(data.depth, rgbs.length, red, green, blue);\r
+ }\r
+ BufferedImage bufferedImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(data.width, data.height), false, null);\r
+ WritableRaster raster = bufferedImage.getRaster();\r
+ int[] pixelArray = new int[1];\r
+ for (int y = 0; y < data.height; y++) {\r
+ for (int x = 0; x < data.width; x++) {\r
+ int pixel = data.getPixel(x, y);\r
+ pixelArray[0] = pixel;\r
+ raster.setPixel(x, y, pixelArray);\r
+ }\r
+ }\r
+ return bufferedImage;\r
+ }\r
+ }\r
+\r
+ public static ImageData convertToSWT(BufferedImage bufferedImage) {\r
+ if (bufferedImage.getColorModel() instanceof DirectColorModel) {\r
+ DirectColorModel colorModel = (DirectColorModel) bufferedImage.getColorModel();\r
+ PaletteData palette = new PaletteData(colorModel.getRedMask(), colorModel.getGreenMask(), colorModel.getBlueMask());\r
+ ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette);\r
+ WritableRaster raster = bufferedImage.getRaster();\r
+ int[] pixelArray = { 0, 0, 0, 255 };\r
+ for (int y = 0; y < data.height; y++) {\r
+ for (int x = 0; x < data.width; x++) {\r
+ raster.getPixel(x, y, pixelArray);\r
+ int pixel = palette.getPixel(new RGB(pixelArray[0], pixelArray[1], pixelArray[2]));\r
+ data.setPixel(x, y, pixel);\r
+ data.setAlpha(x, y, pixelArray[3]);\r
+ }\r
+ }\r
+ return data;\r
+ } else if (bufferedImage.getColorModel() instanceof IndexColorModel) {\r
+ IndexColorModel colorModel = (IndexColorModel) bufferedImage.getColorModel();\r
+ int size = colorModel.getMapSize();\r
+ byte[] reds = new byte[size];\r
+ byte[] greens = new byte[size];\r
+ byte[] blues = new byte[size];\r
+ colorModel.getReds(reds);\r
+ colorModel.getGreens(greens);\r
+ colorModel.getBlues(blues);\r
+ RGB[] rgbs = new RGB[size];\r
+ for (int i = 0; i < rgbs.length; i++) {\r
+ rgbs[i] = new RGB(reds[i] & 0xFF, greens[i] & 0xFF, blues[i] & 0xFF);\r
+ }\r
+ PaletteData palette = new PaletteData(rgbs);\r
+ ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette);\r
+ data.transparentPixel = colorModel.getTransparentPixel();\r
+ WritableRaster raster = bufferedImage.getRaster();\r
+ int[] pixelArray = new int[1];\r
+ for (int y = 0; y < data.height; y++) {\r
+ for (int x = 0; x < data.width; x++) {\r
+ raster.getPixel(x, y, pixelArray);\r
+ data.setPixel(x, y, pixelArray[0]);\r
+ }\r
+ }\r
+ return data;\r
+ } else if (bufferedImage.getColorModel() instanceof ComponentColorModel) {\r
+ // works with BufferedImage.TYPE_3BYTE_BGR\r
+ ComponentColorModel colorModel = (ComponentColorModel)bufferedImage.getColorModel();\r
+ PaletteData palette = new PaletteData(0xFF0000, 0x00FF00, 0x0000FF);\r
+ ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette);\r
+ WritableRaster raster = bufferedImage.getRaster();\r
+ int[] pixelArray = { 0, 0, 0, 255 };\r
+ for (int y = 0; y < data.height; y++) {\r
+ for (int x = 0; x < data.width; x++) {\r
+ raster.getPixel(x, y, pixelArray);\r
+ int pixel = palette.getPixel(new RGB(pixelArray[0], pixelArray[1], pixelArray[2]));\r
+ data.setPixel(x, y, pixel);\r
+ data.setAlpha(x, y, pixelArray[3]);\r
+ }\r
+ }\r
+ return data;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Creates ImageData from RGBA byte array\r
+ * \r
+ * @param width width of the image\r
+ * @param height height of the image\r
+ * @param data data of the image\r
+ * @return <code>ImageData</code>\r
+ */\r
+ public static ImageData _getImageDataFromRGBA(int width, int height, byte[] data) {\r
+ // these seem to do nothing, r and b channels are flipped anyways\r
+ int redMask = 0x0000ff00;\r
+ int greenMask = 0x00ff0000;\r
+ int blueMask = 0xff000000;\r
+ PaletteData paletteData = new PaletteData(redMask, greenMask, blueMask);\r
+ // flipping r and b channels\r
+ int maxByte = width * height * 4;\r
+ byte t;\r
+ for (int i = 0; i < maxByte; i += 4) {\r
+ t = data[i];\r
+ data[i] = data[i + 2];\r
+ data[i + 2] = t;\r
+ }\r
+ ImageData imageData = new ImageData(width, height, 32, paletteData, 4, data);\r
+ // TODO add alpha channel\r
+ // imageData.alphaData = xyz\r
+ return imageData;\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Converts ImageData to RGB(A) ByteBuffer\r
+ * @param imageData\r
+ * @param buffer\r
+ */\r
+ public static void convertToRGBA(ImageData imageData, ByteBuffer buffer) {\r
+ int width = imageData.width;\r
+ int height = imageData.height;\r
+ if (!imageData.palette.isDirect || imageData.depth != 24) {\r
+ ImageUtils.convertPaletteToRGB24(imageData);\r
+ }\r
+ boolean hasAlpha = false;\r
+ if (imageData.alphaData != null) {\r
+ hasAlpha = true;\r
+ }\r
+ int index;\r
+ RGB rgb;\r
+ for (int j = 0; j < height; j++) {\r
+ for (int i = 0; i < width; i++) {\r
+ index = j*width + i;\r
+ rgb = imageData.palette.getRGB(imageData.getPixel(i, j));\r
+ buffer.put((byte)rgb.red);\r
+ buffer.put((byte)rgb.green);\r
+ buffer.put((byte)rgb.blue);\r
+ if (hasAlpha) {\r
+ buffer.put(imageData.alphaData[index]);\r
+ }\r
+ }\r
+ }\r
+ \r
+ }\r
+\r
+}\r