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