FileDocCategorySizeDatePackage
ImageDataFactory.javaAPI DocphoneME MR2 API (J2ME)31265Wed May 02 18:00:08 BST 2007javax.microedition.lcdui

ImageDataFactory

public class ImageDataFactory extends Object implements AbstractImageDataFactory
ImageFactory implementation based on putpixel graphics library and stores data on Java heap.

Fields Summary
private static final byte[]
pngHeader
PNG Header Data
private static final byte[]
jpegHeader
JPEG Header Data
private static final byte[]
rawHeader
RAW Header Data
private static ImageDataFactory
imageDataFactory
ImageDataFactory singleton used for ImageData creation.
Constructors Summary
Methods Summary
private voidcreateImageFromStream(ImageData data, java.io.InputStream stream)
Populates an immutable ImageData from decoded data obtained from an InputStream. This method blocks until all image data has been read and decoded. After this method completes (whether by returning or by throwing an exception) the stream is left open and its current position is undefined.

param
data The ImageData to be populated
param
stream the name of the resource containing the image data in one of the supported image formats
throws
NullPointerException if stream is null
throws
java.io.IOException if an I/O error occurs, if the image data cannot be loaded, or if the image data cannot be decoded


        if (stream == null) {
            throw new java.io.IOException();
        } else {
            /*
             * Allocate an array assuming available is correct.
             * Only reading an EOF is the real end of file
             * so allocate an extra byte to read the EOF into.
             * If available is incorrect, increase the buffer
             * size and keep reading.
             */
            int l = stream.available();
            byte[] buffer = new byte[l+1];
            int length = 0;

            // TBD: Guard against an implementation with incorrect available
            while ((l = stream.read(buffer, length, buffer.length-length))
                   != -1) {
                length += l;
                if (length == buffer.length) {
                    byte[] b = new byte[buffer.length + 4096];
                    System.arraycopy(buffer, 0, b, 0, length);
                    buffer = b;
                }
            }

            stream.close();

            try {
                decode(data, buffer, 0, length);
            } catch (IllegalArgumentException e) {
                throw new java.io.IOException();
            }
        }
    
public ImageDatacreateImmutableCopy(ImageData mutableSource)
Creates an immutable ImageData from a mutableSource ImageData. If the source image data is mutable, an immutable copy is created and returned. If the source image data is immutable, the implementation may simply return it without creating a new image. If an immutable source image data contains transparency information, this information is copied to the new image data unchanged.

This method is useful for placing the contents of mutable images into Choice objects. The application can create an off-screen image using the {@link #createImage(int, int) createImage(w, h)} method, draw into it using a Graphics object obtained with the {@link #getGraphics() getGraphics()} method, and then create an immutable copy of it with this method. The immutable copy may then be placed into Choice objects.

param
mutableSource the source mutable image to be copied
return
the new immutable image data
throws
NullPointerException if source is null

        int width  = mutableSource.getWidth();
        int height = mutableSource.getHeight();
        int length = width * height * 2;

        return  new ImageData(width, height, false,
                              mutableSource.getPixelData());
    
public ImageDatacreateImmutableImageData(byte[] imageBytes, int imageOffset, int imageLength)
Creates an immutable ImageData which is decoded from the data stored in the specified byte array at the specified offset and length. The data must be in a self-identifying image file format supported by the implementation, such as PNG.

The imageoffset and imagelength parameters specify a range of data within the imageData byte array. The imageOffset parameter specifies the offset into the array of the first data byte to be used. It must therefore lie within the range [0..(imageData.length-1)]. The imageLength parameter specifies the number of data bytes to be used. It must be a positive integer and it must not cause the range to extend beyond the end of the array. That is, it must be true that imageOffset + imageLength < imageData.length.

This method is intended for use when loading an image from a variety of sources, such as from persistent storage or from the network.

param
imageBytes the array of image data in a supported image format
param
imageOffset the offset of the start of the data in the array
param
imageLength the length of the data in the array
return
the created image
throws
ArrayIndexOutOfBoundsException if imageOffset and imageLength specify an invalid range
throws
NullPointerException if imageData is null
throws
IllegalArgumentException if imageData is incorrectly formatted or otherwise cannot be decoded

        ImageData data = new ImageData();
        // parse the pixel data
        decode(data, imageBytes, imageOffset, imageLength);
        return data;
    
public ImageDatacreateImmutableImageData(ImageData dataSource, int x, int y, int w, int h, int transform)
Creates an immutable ImageData using pixel data from the specified region of a source ImageData, transformed as specified.

The source image dara may be mutable or immutable. For immutable source image data, transparency information, if any, is copied to the new image data unchanged.

On some devices, pre-transformed images may render more quickly than images that are transformed on the fly using drawRegion. However, creating such images does consume additional heap space, so this technique should be applied only to images whose rendering speed is critical.

The transform function used must be one of the following, as defined in the {@link javax.microedition.lcdui.game.Sprite Sprite} class:
Sprite.TRANS_NONE - causes the specified image region to be copied unchanged
Sprite.TRANS_ROT90 - causes the specified image region to be rotated clockwise by 90 degrees.
Sprite.TRANS_ROT180 - causes the specified image region to be rotated clockwise by 180 degrees.
Sprite.TRANS_ROT270 - causes the specified image region to be rotated clockwise by 270 degrees.
Sprite.TRANS_MIRROR - causes the specified image region to be reflected about its vertical center.
Sprite.TRANS_MIRROR_ROT90 - causes the specified image region to be reflected about its vertical center and then rotated clockwise by 90 degrees.
Sprite.TRANS_MIRROR_ROT180 - causes the specified image region to be reflected about its vertical center and then rotated clockwise by 180 degrees.
Sprite.TRANS_MIRROR_ROT270 - causes the specified image region to be reflected about its vertical center and then rotated clockwise by 270 degrees.

The size of the returned image will be the size of the specified region with the transform applied. For example, if the region is 100 x 50 pixels and the transform is TRANS_ROT90, the returned image will be 50 x 100 pixels.

Note: If all of the following conditions are met, this method may simply return the source Image without creating a new one:

  • the source image is immutable;
  • the region represents the entire source image; and
  • the transform is TRANS_NONE.

param
dataSource the source image data to be copied from
param
x the horizontal location of the region to be copied
param
y the vertical location of the region to be copied
param
w the width of the region to be copied
param
h the height of the region to be copied
param
transform the transform to be applied to the region
return
the new, immutable image
throws
NullPointerException if image is null
throws
IllegalArgumentException if the region to be copied exceeds the bounds of the source image
throws
IllegalArgumentException if either width or height is zero or less
throws
IllegalArgumentException if the transform is not valid


        ImageData dataDest = null;

        if ((transform & Image.TRANSFORM_SWAP_AXIS) ==
            Image.TRANSFORM_SWAP_AXIS) {
            dataDest = new ImageData(h, w, false, false,
                                     dataSource.hasAlpha());
        } else {
            dataDest = new ImageData(w, h, false, false,
                                     dataSource.hasAlpha());
        }


        // Copy either the Java or romized data to its own array
        loadRegion(dataDest, dataSource, x, y, w, h, transform);

        return dataDest;
    
public ImageDatacreateImmutableImageData(int[] rgb, int width, int height, boolean processAlpha)
Creates an immutable ImageData from a sequence of ARGB values, specified as 0xAARRGGBB. The ARGB data within the rgb array is arranged horizontally from left to right within each row, row by row from top to bottom. If processAlpha is true, the high-order byte specifies opacity; that is, 0x00RRGGBB specifies a fully transparent pixel and 0xFFRRGGBB specifies a fully opaque pixel. Intermediate alpha values specify semitransparency. If the implementation does not support alpha blending for image rendering operations, it must replace any semitransparent pixels with fully transparent pixels. (See Alpha Processing for further discussion.) If processAlpha is false, the alpha values are ignored and all pixels must be treated as fully opaque.

Consider P(a,b) to be the value of the pixel located at column a and row b of the Image, where rows and columns are numbered downward from the top starting at zero, and columns are numbered rightward from the left starting at zero. This operation can then be defined as:


P(a, b) = rgb[a + b * width]; 

for


0 <= a < width
0 <= b < height 

param
rgb an array of ARGB values that composes the image
param
width the width of the image
param
height the height of the image
param
processAlpha true if rgb has an alpha channel, false if all pixels are fully opaque
return
the created ImageData
throws
NullPointerException if rgb is null.
throws
IllegalArgumentException if either width or height is zero or less
throws
ArrayIndexOutOfBoundsException if the length of rgb is less than width * height.

        ImageData data = new ImageData(width, height, false, false,
                                       processAlpha);
        loadRGB(data, rgb);

        return data;
    
public ImageDatacreateImmutableImageData(int imageDataArrayPtr, int imageDataArrayLength)
Function to decode an ImageData from romized data.

param
imageDataArrayPtr native pointer to image data as Java int
param
imageDataArrayLength length of image data array
return
ImageData created from romized data.
throws
IllegalArgumentException if the id is invalid


        ImageData data = new ImageData();
        if (!loadRomizedImage(data, imageDataArrayPtr,
                    imageDataArrayLength)) {
            throw new IllegalArgumentException();
        }
        return data;
    
public ImageDatacreateImmutableImageData(java.io.InputStream stream)
Creates an immutable image from decoded image data obtained from an InputStream. This method blocks until all image data has been read and decoded. After this method completes (whether by returning or by throwing an exception) the stream is left open and its current position is undefined.

param
stream the name of the resource containing the image data in one of the supported image formats
return
the created image
throws
NullPointerException if stream is null
throws
java.io.IOException if an I/O error occurs, if the image data cannot be loaded, or if the image data cannot be decoded


        ImageData data = new ImageData();
        createImageFromStream(data, stream);
        return data;
    
public ImageDatacreateOffScreenImageData(int width, int height)
Creates a new, mutable image for off-screen drawing. Every pixel within the newly created image is white. The width and height of the image must both be greater than zero.

param
width the width of the new image, in pixels
param
height the height of the new image, in pixels
return
the created image

        return new ImageData(width, height, true, true, false);
    
public ImageDatacreateResourceImageData(java.lang.String name)
Creates an immutable ImageData from decoded image data obtained from the named resource. The name parameter is a resource name as defined by {@link Class#getResourceAsStream(String) Class.getResourceAsStream(name)}. The rules for resolving resource names are defined in the Application Resource Files section of the java.lang package documentation.

param
name the name of the resource containing the image data in one of the supported image formats
return
the created image data
throws
NullPointerException if name is null
throws
java.io.IOException if the resource does not exist, the data cannot be loaded, or the image data cannot be decoded

        ImageData data = new ImageData();

        /*
         * Load native image data from cache and create
         * image, if available. If image is not cached,
         * proceed to load and create image normally.
         */
        if (!loadCachedImage(data, name)) {
            createImageFromStream(data,
                                  ImageData.class.getResourceAsStream(name));
        }

        return data;
    
private voiddecode(ImageData imageData, byte[] imageBytes, int imageOffset, int imageLength)
Function to decode an ImageData from byte data.

param
imageData the ImageData to populate
param
imageBytes the array of image data in a supported image format
param
imageOffset the offset of the start of the data in the array
param
imageLength the length of the data in the array
throws
IllegalArgumentException if the data is not formatted correctly

        // check if it is a PNG image
        if (headerMatch(pngHeader, imageBytes, imageOffset, imageLength)) {
            // image type is PNG
            decodePNG(imageData, imageBytes, imageOffset, imageLength);
        } else if (headerMatch(jpegHeader, imageBytes,
                               imageOffset, imageLength)) {
            // image type is JPEG
            decodeJPEG(imageData, imageBytes, imageOffset, imageLength);
        } else if (headerMatch(rawHeader, imageBytes,
                               imageOffset, imageLength)) {
            // image type is RAW
            decodeRAW(imageData, imageBytes, imageOffset, imageLength);
        } else {
            // does not match supported image type
            throw new IllegalArgumentException();
        }
    
private voiddecodeJPEG(ImageData imageData, byte[] imageBytes, int imageOffset, int imageLength)
Function to decode an ImageData from JPEG data.

param
imageData the ImageData to be populated
param
imageBytes the array of image data in a supported image format
param
imageOffset the offset of the start of the data in the array
param
imageLength the length of the data in the array

        // find the format of the image data
        if (imageLength < jpegHeader.length + 8) {
            throw new IllegalArgumentException();
        }

        int width = 0;
        int height = 0;

        /**
         * Find SOF (Start Of Frame) marker:
         * format of SOF
         *   2 bytes    Marker Identity  (0xff 0xc<N>)
         *   2 bytes    Length of block
         *   1 byte     bits/sample
         *   2 bytes    Image Height
         *   2 bytes    Image Width
         *   1 bytes    Number of components
         *   n bytes    the components
         *
         * Searching for the byte pair representing SOF is unsafe
         * because a prior marker might contain the SOFn pattern
         * so we must skip over the preceding markers.
         *
         * When editing this code, don't forget to make the appropriate changes
         * in src/lowlevelui/graphics_util/reference/native/gxutl_image_util.c.
         */
        int idx = imageOffset + 2;

        while (idx + 8 < imageOffset + imageLength) {
            if (imageBytes[idx] != (byte)0xff) {
                break;
            }

            if ((byte) (imageBytes[idx + 1] & 0xf0) == (byte) 0xc0) {
                byte code = imageBytes[idx + 1];

                if (code != (byte) 0xc4 || code != (byte) 0xcc) {
                    /* Big endian */
                    height = ((imageBytes[idx + 5] & 0xff) << 8) +
                            (imageBytes[idx + 6] & 0xff);
                    width = ((imageBytes[idx + 7] & 0xff) << 8) +
                            (imageBytes[idx + 8] & 0xff);
                    break;
                }
            }

            /* Go to the next marker */
            int field_len = ((imageBytes[idx + 2] & 0xff) << 8) +
                    (imageBytes[idx + 3] & 0xff);
            idx += field_len + 2;
        }

        if (width <= 0 || height <= 0) {
            throw new IllegalArgumentException();
        }

        imageData.initImageData(width, height, false, false);

        // load the decoded JPEG data into the pixelData array
        loadJPEG(imageData, imageBytes, imageOffset, imageLength);
    
private voiddecodePNG(ImageData imageData, byte[] imageBytes, int imageOffset, int imageLength)
Function to decode an ImageData from PNG data.

param
imageData the ImageData to be populated
param
imageBytes the array of image data in a supported image format
param
imageOffset the offset of the start of the data in the array
param
imageLength the length of the data in the array

        // find the format of the image data
        if (imageLength < pngHeader.length + 8) {
            throw new IllegalArgumentException();
        }

        int width = ((imageBytes[imageOffset + 16] & 0x0ff) << 24) +
                    ((imageBytes[imageOffset + 17] & 0x0ff) << 16) +
                    ((imageBytes[imageOffset + 18] & 0x0ff) <<  8) +
                    (imageBytes[imageOffset + 19] & 0x0ff);

        int height = ((imageBytes[imageOffset + 20] & 0x0ff) << 24) +
                     ((imageBytes[imageOffset + 21] & 0x0ff) << 16) +
                     ((imageBytes[imageOffset + 22] & 0x0ff) <<  8) +
                     (imageBytes[imageOffset + 23] & 0x0ff);

        if (width <= 0 || height <= 0) {
            throw new IllegalArgumentException();
        }

        imageData.initImageData(width, height, false, true);

        // load the decoded PNG data into the data byte arrays
        if (loadPNG(imageData, imageBytes, imageOffset, imageLength) ==
            false) {
            // if loadPNG returns false, the image contains
            // only opaque pixel and the alpha data is not needed
            imageData.removeAlpha();
        }
    
private voiddecodeRAW(ImageData imageData, byte[] imageBytes, int imageOffset, int imageLength)
Function to decode an ImageData from RAW data.

param
imageData the ImageData to be populated
param
imageBytes the array of image data in a supported image format
param
imageOffset the offset of the start of the data in the array
param
imageLength the length of the data in the array

        // find the format of the image data
        if (imageLength < rawHeader.length + 8) {
            throw new IllegalArgumentException();
        }
        loadRAW(imageData, imageBytes, imageOffset, imageLength);
    
public static AbstractImageDataFactorygetImageDataFactory()
Returns the singleton ImageDataFactory instance.

return
the singleton ImageDataFactory instance.


                   
        
        return imageDataFactory;
    
private booleanheaderMatch(byte[] header, byte[] imageData, int imageOffset, int imageLength)
Function to compare byte data to the given header

param
header header data to compare imageData with
param
imageData the array of image data in a supported image format
param
imageOffset the offset of the start of the data in the array
param
imageLength the length of the data in the array
return
true if the header.length bytes at imageData[imageOffset] are equal to the bytes in header array, false otherwise

        if (imageLength < header.length) {
            return false;
        }

        for (int i = 0; i < header.length; i++) {
            if (imageData[imageOffset + i] != header[i]) {
                return false;
            }
        }

        return true;
    
private booleanloadCachedImage(ImageData imageData, java.lang.String resName)
Load an ImageData from cache. The real work is done in the native function.

param
imageData The ImageData to be populated
param
resName Image resource name
return
true if image was loaded and created, false otherwise

        MIDletSuite midletSuite =
            MIDletStateHandler.getMidletStateHandler().getMIDletSuite();
        int suiteId = midletSuite.getID();

        return loadCachedImage0(imageData, suiteId, resName);
    
private native booleanloadCachedImage0(ImageData imageData, int suiteId, java.lang.String resName)
Native function to load native image data from cache and populate an immutable ImageData. pixelData and alphaData, width and height, will be set in native upon success.

param
imageData The ImageData to populate
param
suiteId The suite id
param
resName The image resource name
return
true if image was loaded and created, false otherwise

private native voidloadJPEG(ImageData imageData, byte[] imageBytes, int imageOffset, int imageLength)
Native function to load an ImageData from JPEG data.

param
imageData the ImageData to load to
param
imageBytes the array of image data in a supported image format
param
imageOffset the offset of the start of the data in the array
param
imageLength the length of the data in the array

private native booleanloadPNG(ImageData imageData, byte[] imageBytes, int imageOffset, int imageLength)
Native function to load an ImageData from PNG data.

param
imageData the ImageData to load to
param
imageBytes the array of image data in a supported image format
param
imageOffset the offset of the start of the data in the array
param
imageLength the length of the data in the array
return
true if there is alpha data

private native voidloadRAW(ImageData imgData, byte[] imageBytes, int imageOffset, int imageLength)
Native function to load an ImageData from RAW data.

param
imgData The ImageData to load to
param
imageBytes the array of image data in a RAW format

private native voidloadRGB(ImageData imgData, int[] rgb)
Native function to load an ImageData from ARGB data.

param
imgData The ImageData to load to
param
rgb the array of image data in a ARGB format

private native voidloadRegion(ImageData dest, ImageData source, int x, int y, int width, int height, int transform)
Copy either Java or romized data into another ImageData from an ImageData region.

param
dest the ImageData to copy to
param
source the source image to be copied from
param
x the horizontal location of the region to be copied
param
y the vertical location of the region to be copied
param
width the width of the region to be copied
param
height the height of the region to be copied
param
transform the transform to be applied to the region

private native booleanloadRomizedImage(ImageData data, int imageDataArrayPtr, int imageDataArrayLength)
Native function to load an ImageData directly out of the rom image.

param
data The ImageData to load to
param
imageDataArrayPtr native pointer to image data as Java int
param
imageDataArrayLength length of image data array
return
true if romized image was loaded successfully, false - otherwise