/******************************************************************************* * <copyright> * * Copyright (c) 2005, 2013 SAP AG. * 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: * SAP AG - initial API, implementation and documentation * fvelasco - Bug 396247 - ImageDescriptor changes * mwenz - Bug 413139 - Visibility of convertImageToBytes in DefaultSaveImageFeature * * </copyright> * *******************************************************************************/ package org.eclipse.graphiti.ui.internal.services.impl; import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Collection; import org.eclipse.graphiti.ui.internal.GraphitiUIPlugin; import org.eclipse.graphiti.ui.internal.platform.ExtensionManager; import org.eclipse.graphiti.ui.platform.IImageProvider; import org.eclipse.graphiti.ui.platform.PlatformImageProvider; import org.eclipse.graphiti.ui.services.IImageService; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.ImageLoader; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.RGB; import org.eclipse.ui.plugin.AbstractUIPlugin; /** * @noinstantiate This class is not intended to be instantiated by clients. * @noextend This class is not intended to be subclassed by clients. */ public class ImageService implements IImageService { public ImageDescriptor getImageDescriptorForId(String providerId, String imageId) { if (imageId == null || providerId == null) return null; String registryKey = makeKey(providerId, imageId); ImageRegistry imageRegistry = GraphitiUIPlugin.getDefault().getImageRegistry(); ImageDescriptor imageDescriptor = imageRegistry.getDescriptor(registryKey); if (imageDescriptor != null) { return imageDescriptor; } imageDescriptor = createImageDescriptorForId(providerId, imageId); return imageDescriptor; } public Image getImageForId(String providerId, String imageId) { if (imageId == null || providerId == null) return null; String registryKey = makeKey(providerId, imageId); // if image already available take it ImageRegistry imageRegistry = GraphitiUIPlugin.getDefault().getImageRegistry(); Image result = imageRegistry.get(registryKey); if (result != null && !result.isDisposed()) { return result; } createImageDescriptorForId(providerId, imageId); Image image = imageRegistry.get(registryKey); // now there is an image // registered if (image == null) { throw new IllegalStateException("No image could be retrieved for imageId '" + imageId + "'"); //$NON-NLS-1$ //$NON-NLS-2$ } return image; } public void removeImageFromRegistry(String key) { ImageRegistry imageRegistry = GraphitiUIPlugin.getDefault().getImageRegistry(); imageRegistry.remove(key); } public ImageDescriptor getPlatformImageDescriptorForId(String imageId) { if (imageId == null) return null; String registryKey = makePlatformKey(imageId); ImageRegistry imageRegistry = GraphitiUIPlugin.getDefault().getImageRegistry(); ImageDescriptor imageDescriptor = imageRegistry.getDescriptor(registryKey); if (imageDescriptor != null) { return imageDescriptor; } imageDescriptor = createPlatformImageDescriptorForId(imageId); return imageDescriptor; } public Image getPlatformImageForId(String imageId) { if (imageId == null) return null; String registryKey = makePlatformKey(imageId); // if image already available take it ImageRegistry imageRegistry = GraphitiUIPlugin.getDefault().getImageRegistry(); Image result = imageRegistry.get(registryKey); if (result != null && !result.isDisposed()) { return result; } createPlatformImageDescriptorForId(imageId); Image image = imageRegistry.get(registryKey); // now there is an image // registered if (image == null) { throw new IllegalStateException("No image could be retrieved for imageId '" + imageId + "'"); //$NON-NLS-1$ //$NON-NLS-2$ } return image; } public byte[] convertImageToBytes(Image image, int format) { ByteArrayOutputStream result = new ByteArrayOutputStream(); try { ImageData imDat = null; // Save as GIF is only working if not more than 256 colors are used // in the image if (format == SWT.IMAGE_GIF) { imDat = create8BitIndexedPaletteImage(image); } if (imDat == null) { imDat = image.getImageData(); } ImageLoader imageLoader = new ImageLoader(); imageLoader.data = new ImageData[] { imDat }; try { imageLoader.save(result, format); } catch (SWTException e) { String error = "Depth: " + Integer.toString(image.getImageData().depth) + "\n" + "X: " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + Integer.toString(image.getImageData().x) + "\n" + "Y: " + Integer.toString(image.getImageData().y); //$NON-NLS-1$ //$NON-NLS-2$ throw new IllegalStateException(error, e); } } catch (Exception e) { throw new IllegalStateException(e); } finally { image.dispose(); } return result.toByteArray(); } /** * This method fixes a problem for ImageDescriptors. It returns a corrected * ImageDescriptor for problematic ImageDescriptors. * <p> * There is a problem with transparent GIFs. If the RGB value of the * transparent color index is identical to the RGB value of other colors * indices in the palette, then all those color indices are considered as * transparent. So as a result the transparency seems to be on an RGB value * instead of a color index. */ private ImageDescriptor fixImageDescriptor(ImageDescriptor descriptor) { // Typically the incoming ImageDescriptor is an URLImageDescriptor. The following lines create an ImageDataImageDescriptor // from it, which basically describes the same image. But that one works. So there seems to be an error in the // URLImageDescriptor. ImageData data = descriptor.getImageData(); return ImageDescriptor.createFromImageData(data); } private ImageDescriptor createImageDescriptorForId(String providerId, String imageId) { if (imageId == null || providerId == null) return null; String registryKey = makeKey(providerId, imageId); // if image descriptor already exists return it ImageRegistry imageRegistry = GraphitiUIPlugin.getDefault().getImageRegistry(); ImageDescriptor imageDescriptor = imageRegistry.getDescriptor(registryKey); if (imageDescriptor != null) { return imageDescriptor; } // try get the image-location from the image-providers Collection<IImageProvider> imageProviders = ExtensionManager.getSingleton() .getImageProvidersForDiagramTypeProviderId(providerId); for (IImageProvider imageProvider : imageProviders) { String imageFilePath = imageProvider.getImageFilePath(imageId); if (imageFilePath != null) { String pluginId = imageProvider.getPluginId(); if (pluginId != null) { // try to create Image from ImageDescriptor (initialize the ImageRegistry on the fly) imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(pluginId, imageFilePath); } break; } } if (imageDescriptor == null) { imageDescriptor = ImageDescriptor.getMissingImageDescriptor(); } imageDescriptor = fixImageDescriptor(imageDescriptor); imageRegistry.put(registryKey, imageDescriptor); return imageDescriptor; } private ImageDescriptor createPlatformImageDescriptorForId(String imageId) { if (imageId == null) return null; String registryKey = makePlatformKey(imageId); // if image descriptor already exists return it ImageRegistry imageRegistry = GraphitiUIPlugin.getDefault().getImageRegistry(); ImageDescriptor imageDescriptor = imageRegistry.getDescriptor(registryKey); if (imageDescriptor != null) { return imageDescriptor; } // try get the image-location from the image-providers IImageProvider platformImageProvider = ExtensionManager.getSingleton().getPlatformImageProvider(); String imageFilePath = platformImageProvider.getImageFilePath(imageId); if (imageFilePath != null) { String pluginId = platformImageProvider.getPluginId(); if (pluginId != null) { // try to create Image from ImageDescriptor (initialize the // ImageRegistry on the fly) imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(pluginId, imageFilePath); } } if (imageDescriptor == null) { imageDescriptor = ImageDescriptor.getMissingImageDescriptor(); } imageDescriptor = fixImageDescriptor(imageDescriptor); imageRegistry.put(registryKey, imageDescriptor); return imageDescriptor; } private String makeKey(String dtp, String imageId) { return dtp + "||" + imageId; } private String makePlatformKey(String imageId) { return makeKey(PlatformImageProvider.ID, imageId); } private ImageData create8BitIndexedPaletteImage(Image image) { int upperboundWidth = image.getBounds().width; int upperboundHeight = image.getBounds().height; ImageData imageData = image.getImageData(); // determine number of used colors ArrayList<Integer> colors = new ArrayList<Integer>(); for (int x = 0; x < upperboundWidth; x++) { for (int y = 0; y < upperboundHeight; y++) { int color = imageData.getPixel(x, y); Integer colorInteger = new Integer(color); if (!colors.contains(colorInteger)) colors.add(colorInteger); } } // at the moment this is only working if not more than 256 colors are // used in the image if (colors.size() > 256) { throw new IllegalStateException( "Image contains more than 256 colors. \n Automated color reduction is currently not supported."); //$NON-NLS-1$ } // create an indexed palette RGB[] rgbs = new RGB[256]; for (int i = 0; i < 256; i++) rgbs[i] = new RGB(255, 255, 255); for (int i = 0; i < colors.size(); i++) { int pixelValue = ((colors.get(i))).intValue(); int red = (pixelValue & imageData.palette.redMask) >>> Math.abs(imageData.palette.redShift); int green = (pixelValue & imageData.palette.greenMask) >>> Math.abs(imageData.palette.greenShift); int blue = (pixelValue & imageData.palette.blueMask) >>> Math.abs(imageData.palette.blueShift); rgbs[i] = new RGB(red, green, blue); } // create new imageData PaletteData palette = new PaletteData(rgbs); ImageData newImageData = new ImageData(imageData.width, imageData.height, 8, palette); // adjust imageData with regard to the palette for (int x = 0; x < upperboundWidth; x++) { for (int y = 0; y < upperboundHeight; y++) { int color = imageData.getPixel(x, y); newImageData.setPixel(x, y, colors.indexOf(new Integer(color))); } } return newImageData; } }