![JAR search and dependency download from the Maven repository](/logo.png)
org.eclipse.swt.graphics.Image Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2002, 2015 Innoopract Informationssysteme GmbH and others.
* 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:
* Innoopract Informationssysteme GmbH - initial API and implementation
* EclipseSource - ongoing development
* Rüdiger Herrmann - bug 334511
******************************************************************************/
package org.eclipse.swt.graphics;
import java.io.IOException;
import java.io.InputStream;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.eclipse.rap.rwt.internal.application.ApplicationContextImpl;
import org.eclipse.rap.rwt.internal.service.ContextProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.internal.graphics.InternalImage;
import org.eclipse.swt.internal.graphics.InternalImageFactory;
import org.eclipse.swt.internal.widgets.IDisplayAdapter;
import org.eclipse.swt.widgets.Display;
/**
* Instances of this class are graphics which have been prepared
* for display on a specific device. That is, they are to display
* on widgets with, for example, Button.setImage()
.
*
* If loaded from a file format that supports it, an
* Image
may have transparency, meaning that certain
* pixels are specified as being transparent when drawn. Examples
* of file formats that support transparency are GIF and PNG.
*/
public class Image extends Resource implements Drawable {
/**
* The internal resource.
* (Warning: This field is platform dependent)
*
* IMPORTANT: This field is not part of the SWT
* public API. It is marked public only so that it can be shared
* within the packages provided by SWT. It is not available on all
* platforms and should never be accessed from application code.
*
*
* @noreference This field is not intended to be referenced by clients.
*/
public final InternalImage internalImage;
/* This constructor is called by ImageFactory#createImageInstance() */
private Image( Device device, InternalImage internalImage ) {
super( device );
this.internalImage = internalImage;
}
/**
* Constructs an instance of this class by loading its representation
* from the specified input stream. Throws an error if an error
* occurs while loading the image, or if the result is an image
* of an unsupported type. Application code is still responsible
* for closing the input stream.
*
* This constructor is provided for convenience when loading a single
* image only. If the stream contains multiple images, only the first
* one will be loaded. To load multiple images, use
* ImageLoader.load()
.
*
* This constructor may be used to load a resource as follows:
*
*
* static Image loadImage (Display display, Class clazz, String string) {
* InputStream stream = clazz.getResourceAsStream (string);
* if (stream == null) return null;
* Image image = null;
* try {
* image = new Image (display, stream);
* } catch (SWTException ex) {
* } finally {
* try {
* stream.close ();
* } catch (IOException ex) {}
* }
* return image;
* }
*
*
* @param device the device on which to create the image
* @param stream the input stream to load the image from
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if device is null and there is no current device
* - ERROR_NULL_ARGUMENT - if the stream is null
*
* @exception SWTException
* - ERROR_IO - if an IO error occurs while reading from the stream
* - ERROR_INVALID_IMAGE - if the image stream contains invalid data
* - ERROR_UNSUPPORTED_DEPTH - if the image stream describes an image with an unsupported depth
* - ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format
*
* @exception SWTError
* - ERROR_NO_HANDLES if a handle could not be obtained for image creation
*
* @since 1.3
*/
public Image( Device device, InputStream stream ) {
super( checkDevice( device ) );
if( stream == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
internalImage = findInternalImage( stream );
}
/**
* Constructs an instance of this class by loading its representation
* from the file with the specified name. Throws an error if an error
* occurs while loading the image, or if the result is an image
* of an unsupported type.
*
* This constructor is provided for convenience when loading
* a single image only. If the specified file contains
* multiple images, only the first one will be used.
*
* @param device the device on which to create the image
* @param fileName the name of the file to load the image from
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if device is null and there is no current device
* - ERROR_NULL_ARGUMENT - if the file name is null
*
* @exception SWTException
* - ERROR_IO - if an IO error occurs while reading from the file
* - ERROR_INVALID_IMAGE - if the image file contains invalid data
* - ERROR_UNSUPPORTED_DEPTH - if the image file describes an image with an unsupported depth
* - ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format
*
* @exception SWTError
* - ERROR_NO_HANDLES if a handle could not be obtained for image creation
*
* @since 1.3
*/
public Image( Device device, String fileName ) {
super( checkDevice( device ) );
if( fileName == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
internalImage = findInternalImage( fileName );
}
/**
* Constructs a new instance of this class based on the
* provided image, with an appearance that varies depending
* on the value of the flag. The possible flag values are:
*
* - {@link SWT#IMAGE_COPY}
* - the result is an identical copy of srcImage
* - {@link SWT#IMAGE_DISABLE}
* - the result is a copy of srcImage which has a disabled look
* - {@link SWT#IMAGE_GRAY}
* - the result is a copy of srcImage which has a gray scale look
*
*
* @param device the device on which to create the image
* @param srcImage the image to use as the source
* @param flag the style, either IMAGE_COPY
, IMAGE_DISABLE
or IMAGE_GRAY
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if device is null and there is no current device
* - ERROR_NULL_ARGUMENT - if srcImage is null
* - ERROR_INVALID_ARGUMENT - if the flag is not one of
IMAGE_COPY
, IMAGE_DISABLE
or IMAGE_GRAY
* - ERROR_INVALID_ARGUMENT - if the image has been disposed
*
* @exception SWTException
* - ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon, or is otherwise in an invalid state
* - ERROR_UNSUPPORTED_DEPTH - if the depth of the image is not supported
*
* @exception SWTError
* - ERROR_NO_HANDLES if a handle could not be obtained for image creation
*
* @since 1.3
*/
public Image( Device device, Image srcImage, int flag ) {
super( checkDevice( device ) );
if( srcImage == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
if( srcImage.isDisposed() ) {
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
Rectangle rect = srcImage.getBounds();
switch( flag ) {
case SWT.IMAGE_COPY:
internalImage = srcImage.internalImage;
break;
case SWT.IMAGE_DISABLE: {
ImageData data = srcImage.getImageData();
PaletteData palette = data.palette;
RGB[] rgbs = new RGB[ 3 ];
rgbs[ 0 ] = device.getSystemColor( SWT.COLOR_BLACK ).getRGB();
rgbs[ 1 ] = device.getSystemColor( SWT.COLOR_WIDGET_NORMAL_SHADOW ).getRGB();
rgbs[ 2 ] = device.getSystemColor( SWT.COLOR_WIDGET_BACKGROUND ).getRGB();
ImageData newData = new ImageData( rect.width, rect.height, 8, new PaletteData( rgbs ) );
newData.alpha = data.alpha;
newData.alphaData = data.alphaData;
newData.maskData = data.maskData;
newData.maskPad = data.maskPad;
if( data.transparentPixel != -1 ) {
newData.transparentPixel = 0;
}
/* Convert the pixels. */
int[] scanline = new int[ rect.width ];
int[] maskScanline = null;
ImageData mask = null;
if( data.maskData != null ) {
mask = data.getTransparencyMask();
}
if( mask != null ) {
maskScanline = new int[ rect.width ];
}
int redMask = palette.redMask;
int greenMask = palette.greenMask;
int blueMask = palette.blueMask;
int redShift = palette.redShift;
int greenShift = palette.greenShift;
int blueShift = palette.blueShift;
for( int y = 0; y < rect.height; y++ ) {
int offset = y * newData.bytesPerLine;
data.getPixels( 0, y, rect.width, scanline, 0 );
if( mask != null ) {
mask.getPixels( 0, y, rect.width, maskScanline, 0 );
}
for( int x = 0; x < rect.width; x++ ) {
int pixel = scanline[ x ];
if( !( ( data.transparentPixel != -1 && pixel == data.transparentPixel )
|| ( mask != null && maskScanline[ x ] == 0 ) ) )
{
int red, green, blue;
if( palette.isDirect ) {
red = pixel & redMask;
red = ( redShift < 0 ) ? red >>> -redShift : red << redShift;
green = pixel & greenMask;
green = ( greenShift < 0 ) ? green >>> -greenShift : green << greenShift;
blue = pixel & blueMask;
blue = ( blueShift < 0 ) ? blue >>> -blueShift : blue << blueShift;
} else {
red = palette.colors[ pixel ].red;
green = palette.colors[ pixel ].green;
blue = palette.colors[ pixel ].blue;
}
int intensity = red * red + green * green + blue * blue;
if( intensity < 98304 ) {
newData.data[ offset ] = ( byte )1;
} else {
newData.data[ offset ] = ( byte )2;
}
}
offset++ ;
}
}
internalImage = findInternalImage( newData );
break;
}
case SWT.IMAGE_GRAY: {
ImageData data = srcImage.getImageData();
PaletteData palette = data.palette;
ImageData newData = data;
if( !palette.isDirect ) {
/* Convert the palette entries to gray. */
RGB[] rgbs = palette.getRGBs();
for( int i = 0; i < rgbs.length; i++ ) {
if( data.transparentPixel != i ) {
RGB color = rgbs[ i ];
int red = color.red;
int green = color.green;
int blue = color.blue;
int intensity = ( red + red + green + green + green + green + green + blue ) >> 3;
color.red = color.green = color.blue = intensity;
}
}
newData.palette = new PaletteData( rgbs );
} else {
/* Create a 8 bit depth image data with a gray palette. */
RGB[] rgbs = new RGB[ 256 ];
for( int i = 0; i < rgbs.length; i++ ) {
rgbs[ i ] = new RGB( i, i, i );
}
newData = new ImageData( rect.width, rect.height, 8, new PaletteData( rgbs ) );
newData.alpha = data.alpha;
newData.alphaData = data.alphaData;
newData.maskData = data.maskData;
newData.maskPad = data.maskPad;
if( data.transparentPixel != -1 ) {
newData.transparentPixel = 254;
}
/* Convert the pixels. */
int[] scanline = new int[ rect.width ];
int redMask = palette.redMask;
int greenMask = palette.greenMask;
int blueMask = palette.blueMask;
int redShift = palette.redShift;
int greenShift = palette.greenShift;
int blueShift = palette.blueShift;
for( int y = 0; y < rect.height; y++ ) {
int offset = y * newData.bytesPerLine;
data.getPixels( 0, y, rect.width, scanline, 0 );
for( int x = 0; x < rect.width; x++ ) {
int pixel = scanline[ x ];
if( pixel != data.transparentPixel ) {
int red = pixel & redMask;
red = ( redShift < 0 ) ? red >>> -redShift : red << redShift;
int green = pixel & greenMask;
green = ( greenShift < 0 ) ? green >>> -greenShift : green << greenShift;
int blue = pixel & blueMask;
blue = ( blueShift < 0 ) ? blue >>> -blueShift : blue << blueShift;
int intensity = ( red + red + green + green + green + green + green + blue ) >> 3;
if( newData.transparentPixel == intensity ) {
intensity = 255;
}
newData.data[ offset ] = ( byte )intensity;
} else {
newData.data[ offset ] = ( byte )254;
}
offset++ ;
}
}
}
internalImage = findInternalImage( newData );
break;
}
default:
internalImage = null;
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
break;
}
}
/**
* Constructs an instance of this class from the given
* ImageData
.
*
* @param device the device on which to create the image
* @param imageData the image data to create the image from (must not be null)
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if device is null and there is no current device
* - ERROR_NULL_ARGUMENT - if the image data is null
*
* @exception SWTException
* - ERROR_UNSUPPORTED_DEPTH - if the depth of the ImageData is not supported
*
*
* @since 1.3
*/
public Image( Device device, ImageData imageData ) {
super( checkDevice( device ) );
if( imageData == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
internalImage = findInternalImage( imageData );
}
/**
* Constructs an empty instance of this class with the
* specified width and height. The result may be drawn upon
* by creating a GC and using any of its drawing operations,
* as shown in the following example:
*
* Image i = new Image(device, width, height);
* GC gc = new GC(i);
* gc.drawRectangle(0, 0, 50, 50);
* gc.dispose();
*
*
* Note: Some platforms may have a limitation on the size
* of image that can be created (size depends on width, height,
* and depth). For example, Windows 95, 98, and ME do not allow
* images larger than 16M.
*
*
* @param device the device on which to create the image
* @param width the width of the new image
* @param height the height of the new image
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if device is null and there is no current device
* - ERROR_INVALID_ARGUMENT - if either the width or height is negative or zero
*
* @exception SWTError
* - ERROR_NO_HANDLES if a handle could not be obtained for image creation
*
* @since 1.4
*/
public Image( Device device, int width, int height ) {
super( checkDevice( device ) );
if( width <= 0 || height <= 0 ) {
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
Color white = device.getSystemColor( SWT.COLOR_WHITE );
PaletteData palette = new PaletteData( new RGB[] { white.getRGB() } );
ImageData imageData = new ImageData( width, height, 8, palette );
internalImage = findInternalImage( imageData );
}
/**
* Returns the bounds of the receiver. The rectangle will always
* have x and y values of 0, and the width and height of the
* image.
*
* @return a rectangle specifying the image's bounds
*
* @exception SWTException
* - ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
* - ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon
*
*/
public Rectangle getBounds() {
if( isDisposed() ) {
SWT.error( SWT.ERROR_GRAPHIC_DISPOSED );
}
return internalImage.getBounds();
}
/**
* Returns an ImageData
based on the receiver
* Modifications made to this ImageData
will not
* affect the Image.
*
* @return an ImageData
containing the image's data and attributes
*
* @exception SWTException
* - ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
* - ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon
*
*
* @see ImageData
* @since 1.3
*/
public ImageData getImageData() {
if( isDisposed() ) {
SWT.error( SWT.ERROR_GRAPHIC_DISPOSED );
}
ImageData result;
if( device != null ) {
ApplicationContextImpl applicationContext = getApplicationContext();
result = applicationContext.getImageDataFactory().findImageData( internalImage );
} else {
result = internalImage.getImageData();
}
return result;
}
/**
* Sets the color to which to map the transparent pixel.
*
* There are certain uses of Images
that do not support
* transparency (for example, setting an image into a button or label).
* In these cases, it may be desired to simulate transparency by using
* the background color of the widget to paint the transparent pixels
* of the image. This method specifies the color that will be used in
* these cases. For example:
*
* Button b = new Button();
* image.setBackground(b.getBackground());
* b.setImage(image);
*
*
* The image may be modified by this operation (in effect, the
* transparent regions may be filled with the supplied color). Hence
* this operation is not reversible and it is not legal to call
* this function twice or with a null argument.
*
* This method has no effect if the receiver does not have a transparent
* pixel value.
*
*
* @param color the color to use when a transparent pixel is specified
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if the color is null
* - ERROR_INVALID_ARGUMENT - if the color has been disposed
*
* @exception SWTException
* - ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
*
* @since 1.3
*/
public void setBackground( Color color ) {
if( isDisposed() ) {
SWT.error( SWT.ERROR_GRAPHIC_DISPOSED );
}
if( color == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
if( color.isDisposed() ) {
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
// do nothing
}
/**
* Returns the color to which to map the transparent pixel, or null if
* the receiver has no transparent pixel.
*
* There are certain uses of Images that do not support transparency
* (for example, setting an image into a button or label). In these cases,
* it may be desired to simulate transparency by using the background
* color of the widget to paint the transparent pixels of the image.
* Use this method to check which color will be used in these cases
* in place of transparency. This value may be set with setBackground().
*
*
* @return the background color of the image, or null if there is no
* transparency in the image
*
* @exception SWTException
* - ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
*
* @since 1.3
*/
public Color getBackground() {
if( isDisposed() ) {
SWT.error( SWT.ERROR_GRAPHIC_DISPOSED );
}
// do nothing
return null;
}
private void writeObject( ObjectOutputStream stream ) throws IOException {
if( device == null ) {
throw new NotSerializableException( getClass().getName() );
}
new ImageSerializer( this ).writeObject( stream );
}
private void readObject( ObjectInputStream stream ) throws IOException, ClassNotFoundException {
new ImageSerializer( this ).readObject( stream );
}
private ApplicationContextImpl getApplicationContext() {
Display display = ( Display )device;
IDisplayAdapter adapter = display.getAdapter( IDisplayAdapter.class );
return (ApplicationContextImpl)adapter.getUISession().getApplicationContext();
}
private static InternalImage findInternalImage( ImageData imageData ) {
return getInternalImageFactory().findInternalImage( imageData );
}
private static InternalImage findInternalImage( InputStream stream ) {
return getInternalImageFactory().findInternalImage( stream );
}
private static InternalImage findInternalImage( String fileName ) {
return getInternalImageFactory().findInternalImage( fileName );
}
private static InternalImageFactory getInternalImageFactory() {
return ContextProvider.getApplicationContext().getInternalImageFactory();
}
}