FileDocCategorySizeDatePackage
PngDecoder.javaAPI DocAndroid 1.5 API9233Wed May 06 22:41:54 BST 2009org.apache.harmony.awt.gl.image

PngDecoder

public class PngDecoder extends ImageDecoder
author
Oleg V. Khaschansky
version
$Revision$
date:
Jul 22, 2005

Fields Summary
private static final int
hintflags
private static final int
PNG_COLOR_TYPE_GRAY
private static final int
PNG_COLOR_TYPE_RGB
private static final int
PNG_COLOR_TYPE_PLTE
private static final int
PNG_COLOR_TYPE_GRAY_ALPHA
private static final int
PNG_COLOR_TYPE_RGBA
private static final int
INPUT_BUFFER_SIZE
private byte[]
buffer
byte[]
byteOut
int[]
intOut
private long
hNativeDecoder
int
imageWidth
int
imageHeight
int
colorType
int
bitDepth
byte[]
cmap
boolean
transferInts
int
dataElementsPerPixel
ColorModel
cm
int
updateFromScanline
int
numScanlines
Constructors Summary
public PngDecoder(DecodingImageSource src, InputStream is)

 // Number of scanlines to update

            

         

         
        super(src, is);
    
Methods Summary
private native longdecode(byte[] input, int bytesInBuffer, long hDecoder)

public voiddecodeImage()

        try {
            int bytesRead = 0;
            int needBytes, offset, bytesInBuffer = 0;
            // Read from the input stream
            for (;;) {
                needBytes = INPUT_BUFFER_SIZE - bytesInBuffer;
                offset = bytesInBuffer;

                bytesRead = inputStream.read(buffer, offset, needBytes);

                if (bytesRead < 0) { // Break, nothing to read from buffer, image truncated?
                    releaseNativeDecoder(hNativeDecoder);
                    break;
                }

                // Keep track on how much bytes left in buffer
                bytesInBuffer += bytesRead;
                hNativeDecoder = decode(buffer, bytesInBuffer, hNativeDecoder);
                // PNG decoder always consumes all bytes at once
                bytesInBuffer = 0;

                // if (bytesConsumed < 0)
                //break; // Error exit

                returnData();

                // OK, we decoded all the picture in the right way...
                if (hNativeDecoder == 0) {
                    break;
                }
            }

            imageComplete(ImageConsumer.STATICIMAGEDONE);
        } catch (IOException e) {
            throw e;
        } catch (RuntimeException e) {
            imageComplete(ImageConsumer.IMAGEERROR);
            throw e;
        } finally {
            closeStream();
        }
    
private static native voidinitIDs()

private static native voidreleaseNativeDecoder(long hDecoder)

private voidreturnData()

        // Send 1 or more scanlines to the consumer.
        if (numScanlines > 0) {
            // Native decoder could have returned
            // some data from the next pass, handle it here
            int pass1, pass2;
            if (updateFromScanline + numScanlines > imageHeight) {
                pass1 = imageHeight - updateFromScanline;
                pass2 = updateFromScanline + numScanlines - imageHeight;
            } else {
                pass1 = numScanlines;
                pass2 = 0;
            }

            transfer(updateFromScanline, pass1);
            if (pass2 != 0) {
                transfer(0, pass2);
            }
        }
    
private voidreturnHeader()

 // Called from native code
        setDimensions(imageWidth, imageHeight);

        switch (colorType) {
            case PNG_COLOR_TYPE_GRAY: {
                if (bitDepth != 8 && bitDepth != 4 && bitDepth != 2 && bitDepth != 1) {
                    // awt.3C=Unknown PNG color type
                    throw new IllegalArgumentException(Messages.getString("awt.3C")); //$NON-NLS-1$
                }

                // Create gray color model
                int numEntries = 1 << bitDepth;
                int scaleFactor = 255 / (numEntries-1);
                byte comps[] = new byte[numEntries];
                for (int i = 0; i < numEntries; i++) {
                    comps[i] = (byte) (i * scaleFactor);
                }
                cm = new IndexColorModel(/*bitDepth*/8, numEntries, comps, comps, comps);

                transferInts = false;
                break;
            }

            case PNG_COLOR_TYPE_RGB: {
                if (bitDepth != 8) {
                    // awt.3C=Unknown PNG color type
                    throw new IllegalArgumentException(Messages.getString("awt.3C")); //$NON-NLS-1$
                }

                cm = new DirectColorModel(24, 0xFF0000, 0xFF00, 0xFF);

                transferInts = true;
                break;
            }

            case PNG_COLOR_TYPE_PLTE: {
                if (bitDepth != 8 && bitDepth != 4 && bitDepth != 2 && bitDepth != 1) {
                    // awt.3C=Unknown PNG color type
                    throw new IllegalArgumentException(Messages.getString("awt.3C")); //$NON-NLS-1$
                }

                cm = new IndexColorModel(/*bitDepth*/8, cmap.length / 3, cmap, 0, false);

                transferInts = false;
                break;
            }

            case PNG_COLOR_TYPE_GRAY_ALPHA: {
                if (bitDepth != 8) {
                    // awt.3C=Unknown PNG color type
                    throw new IllegalArgumentException(Messages.getString("awt.3C")); //$NON-NLS-1$
                }

                cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY),
                        true, false,
                        Transparency.TRANSLUCENT,
                        DataBuffer.TYPE_BYTE);

                transferInts = false;
                dataElementsPerPixel = 2;
                break;
            }

            case PNG_COLOR_TYPE_RGBA: {
                if (bitDepth != 8) {
                    // awt.3C=Unknown PNG color type
                    throw new IllegalArgumentException(Messages.getString("awt.3C")); //$NON-NLS-1$
                }

                cm = ColorModel.getRGBdefault();

                transferInts = true;
                break;
            }
            default:
                // awt.3C=Unknown PNG color type
                throw new IllegalArgumentException(Messages.getString("awt.3C")); //$NON-NLS-1$
        }

        // Create output buffer
        if (transferInts) {
            intOut = new int[imageWidth * imageHeight];
        } else {
            byteOut = new byte[imageWidth * imageHeight * dataElementsPerPixel];
        }

        setColorModel(cm);

        setHints(hintflags);
        setProperties(new Hashtable<Object, Object>()); // Empty
    
private voidtransfer(int updateFromScanline, int numScanlines)

        if (transferInts) {
            setPixels(
                    0, updateFromScanline,
                    imageWidth, numScanlines,
                    cm, intOut,
                    updateFromScanline * imageWidth,
                    imageWidth
            );
        } else {
            setPixels(
                    0, updateFromScanline,
                    imageWidth, numScanlines,
                    cm, byteOut,
                    updateFromScanline * imageWidth * dataElementsPerPixel,
                    imageWidth * dataElementsPerPixel
            );
        }