Back to index

wims  3.65+svn20090927
Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes | Package Attributes
rene.util.PngEncoder Class Reference
Collaboration diagram for rene.util.PngEncoder:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 PngEncoder ()
 Class constructor.
 PngEncoder (Image image)
 Class constructor specifying Image to encode, with no alpha channel encoding.
 PngEncoder (Image image, boolean encodeAlpha)
 Class constructor specifying Image to encode, and whether to encode alpha.
 PngEncoder (Image image, boolean encodeAlpha, int whichFilter)
 Class constructor specifying Image to encode, whether to encode alpha, and filter to use.
 PngEncoder (Image image, boolean encodeAlpha, int whichFilter, int compLevel)
 Class constructor specifying Image source to encode, whether to encode alpha, filter to use, and compression level.
void setImage (Image image)
 Set the image to be encoded.
void setDPI (double dpi)
byte[] pngEncode (boolean encodeAlpha)
 Creates an array of bytes that is the PNG equivalent of the current image, specifying whether to encode alpha or not.
byte[] pngEncode ()
 Creates an array of bytes that is the PNG equivalent of the current image.
void setEncodeAlpha (boolean encodeAlpha)
 Set the alpha encoding on or off.
boolean getEncodeAlpha ()
 Retrieve alpha encoding status.
void setFilter (int whichFilter)
 Set the filter to use.
int getFilter ()
 Retrieve filtering scheme.
void setCompressionLevel (int level)
 Set the compression level to use.
int getCompressionLevel ()
 Retrieve compression level.

Static Public Attributes

static final boolean ENCODE_ALPHA = true
 Constant specifying that alpha channel should be encoded.
static final boolean NO_ALPHA = false
 Constant specifying that alpha channel should not be encoded.
static final int FILTER_NONE = 0
 Constants for filters.
static final int FILTER_SUB = 1
static final int FILTER_UP = 2
static final int FILTER_LAST = 2

Protected Member Functions

byte[] resizeByteArray (byte[] array, int newLength)
 Increase or decrease the length of a byte array.
int writeBytes (byte[] data, int offset)
 Write an array of bytes into the pngBytes array.
int writeBytes (byte[] data, int nBytes, int offset)
 Write an array of bytes into the pngBytes array, specifying number of bytes to write.
int writeInt2 (int n, int offset)
 Write a two-byte integer into the pngBytes array at a given position.
int writeInt4 (int n, int offset)
 Write a four-byte integer into the pngBytes array at a given position.
int writeByte (int b, int offset)
 Write a single byte into the pngBytes array at a given position.
int writeString (String s, int offset)
 Write a string into the pngBytes array at a given position.
void writeHeader ()
 Write a PNG "IHDR" chunk into the pngBytes array.
void writePhys ()
 Write a PNG "pHYs" chunk into the pngBytes array.
void filterSub (byte[] pixels, int startPos, int width)
 Perform "sub" filtering on the given row.
void filterUp (byte[] pixels, int startPos, int width)
 Perform "up" filtering on the given row.
boolean writeImageData ()
 Write the image data into the pngBytes array.
void writeEnd ()
 Write a PNG "IEND" chunk into the pngBytes array.

Protected Attributes

byte[] pngBytes
byte[] priorRow
byte[] leftBytes
Image image
int width
int bytePos
int hdrPos
CRC32 crc = new CRC32()
long crcValue
boolean encodeAlpha
int filter
int bytesPerPixel
int compressionLevel
double DPI = 300

Package Attributes

int height
int maxPos
int dataPos
int endPos

Detailed Description

Definition at line 45 of file PngEncoder.java.


Constructor & Destructor Documentation

Class constructor.

  

Definition at line 76 of file PngEncoder.java.

    {
        this( null, false, FILTER_NONE, 0 );
    }
rene.util.PngEncoder.PngEncoder ( Image  image) [inline]

Class constructor specifying Image to encode, with no alpha channel encoding.

Parameters:
imageA Java Image object which uses the DirectColorModel
See also:
java.awt.Image

Definition at line 87 of file PngEncoder.java.

    {
        this(image, false, FILTER_NONE, 0);
    }
rene.util.PngEncoder.PngEncoder ( Image  image,
boolean  encodeAlpha 
) [inline]

Class constructor specifying Image to encode, and whether to encode alpha.

Parameters:
imageA Java Image object which uses the DirectColorModel
encodeAlphaEncode the alpha channel? false=no; true=yes
See also:
java.awt.Image

Definition at line 99 of file PngEncoder.java.

    {
        this(image, encodeAlpha, FILTER_NONE, 0);
    }
rene.util.PngEncoder.PngEncoder ( Image  image,
boolean  encodeAlpha,
int  whichFilter 
) [inline]

Class constructor specifying Image to encode, whether to encode alpha, and filter to use.

Parameters:
imageA Java Image object which uses the DirectColorModel
encodeAlphaEncode the alpha channel? false=no; true=yes
whichFilter0=none, 1=sub, 2=up
See also:
java.awt.Image

Definition at line 112 of file PngEncoder.java.

    {
        this( image, encodeAlpha, whichFilter, 0 );
    }
rene.util.PngEncoder.PngEncoder ( Image  image,
boolean  encodeAlpha,
int  whichFilter,
int  compLevel 
) [inline]

Class constructor specifying Image source to encode, whether to encode alpha, filter to use, and compression level.

Parameters:
imageA Java Image object
encodeAlphaEncode the alpha channel? false=no; true=yes
whichFilter0=none, 1=sub, 2=up
compLevel0..9
See also:
java.awt.Image

Definition at line 127 of file PngEncoder.java.

    {
        this.image = image;
        this.encodeAlpha = encodeAlpha;
        setFilter( whichFilter );
        if (compLevel >=0 && compLevel <=9)
        {
            this.compressionLevel = compLevel;
        }
    }

Here is the call graph for this function:


Member Function Documentation

void rene.util.PngEncoder.filterSub ( byte[]  pixels,
int  startPos,
int  width 
) [inline, protected]

Perform "sub" filtering on the given row.

Uses temporary array leftBytes to store the original values of the previous pixels. The array is 16 bytes long, which will easily hold two-byte samples plus two-byte alpha.

Parameters:
pixelsThe array holding the scan lines being built
startPosStarting position within pixels of bytes to be filtered.
widthWidth of a scanline in pixels.

Definition at line 456 of file PngEncoder.java.

    {
        int i;
        int offset = bytesPerPixel;
        int actualStart = startPos + offset;
        int nBytes = width * bytesPerPixel;
        int leftInsert = offset;
        int leftExtract = 0;
        byte current_byte;

        for (i=actualStart; i < startPos + nBytes; i++)
        {
            leftBytes[leftInsert] =  pixels[i];
            pixels[i] = (byte) ((pixels[i] - leftBytes[leftExtract]) % 256);
            leftInsert = (leftInsert+1) % 0x0f;
            leftExtract = (leftExtract + 1) % 0x0f;
        }
    }

Here is the caller graph for this function:

void rene.util.PngEncoder.filterUp ( byte[]  pixels,
int  startPos,
int  width 
) [inline, protected]

Perform "up" filtering on the given row.

Side effect: refills the prior row with current row

Parameters:
pixelsThe array holding the scan lines being built
startPosStarting position within pixels of bytes to be filtered.
widthWidth of a scanline in pixels.

Definition at line 483 of file PngEncoder.java.

    {
        int     i, nBytes;
        byte    current_byte;

        nBytes = width * bytesPerPixel;

        for (i=0; i < nBytes; i++)
        {
            current_byte = pixels[startPos + i];
            pixels[startPos + i] = (byte) ((pixels[startPos  + i] - priorRow[i]) % 256);
            priorRow[i] = current_byte;
        }
    }

Here is the caller graph for this function:

Retrieve compression level.

Returns:
int in range 0-9

Definition at line 275 of file PngEncoder.java.

    {
        return compressionLevel;
    }

Retrieve alpha encoding status.

Returns:
boolean false=no, true=yes

Definition at line 228 of file PngEncoder.java.

    {
        return encodeAlpha;
    }

Retrieve filtering scheme.

Returns:
int (see constant list)

Definition at line 252 of file PngEncoder.java.

    {
        return filter;
    }
byte [] rene.util.PngEncoder.pngEncode ( boolean  encodeAlpha) [inline]

Creates an array of bytes that is the PNG equivalent of the current image, specifying whether to encode alpha or not.

Parameters:
encodeAlphaboolean false=no alpha, true=encode alpha
Returns:
an array of bytes, or null if there was a problem

Definition at line 162 of file PngEncoder.java.

    {
        byte[]  pngIdBytes = { -119, 80, 78, 71, 13, 10, 26, 10 };
        int     i;

        if (image == null)
        {
            return null;
        }
        width = image.getWidth( null );
        height = image.getHeight( null );
        
        /*
         * start with an array that is big enough to hold all the pixels
         * (plus filter bytes), and an extra 200 bytes for header info
         */
        pngBytes = new byte[((width+1) * height * 3) + 200];

        /*
         * keep track of largest byte written to the array
         */
        maxPos = 0;

        bytePos = writeBytes( pngIdBytes, 0 );
        hdrPos = bytePos;
        writeHeader();
              writePhys();
              dataPos = bytePos;
        if (writeImageData())
        {
                     writeEnd();
            pngBytes = resizeByteArray( pngBytes, maxPos );
        }
        else
        {
            pngBytes = null;
        }
        return pngBytes;
    }

Here is the call graph for this function:

Here is the caller graph for this function:

byte [] rene.util.PngEncoder.pngEncode ( ) [inline]

Creates an array of bytes that is the PNG equivalent of the current image.

Alpha encoding is determined by its setting in the constructor.

Returns:
an array of bytes, or null if there was a problem

Definition at line 208 of file PngEncoder.java.

    {
        return pngEncode( encodeAlpha );
    }
byte [] rene.util.PngEncoder.resizeByteArray ( byte[]  array,
int  newLength 
) [inline, protected]

Increase or decrease the length of a byte array.

Parameters:
arrayThe original array.
newLengthThe length you wish the new array to have.
Returns:
Array of newly desired length. If shorter than the original, the trailing elements are truncated.

Definition at line 288 of file PngEncoder.java.

    {
        byte[]  newArray = new byte[newLength];
        int     oldLength = array.length;

        System.arraycopy( array, 0, newArray, 0,
            Math.min( oldLength, newLength ) );
        return newArray;
    }

Here is the caller graph for this function:

void rene.util.PngEncoder.setCompressionLevel ( int  level) [inline]

Set the compression level to use.

Parameters:
level0 through 9

Definition at line 262 of file PngEncoder.java.

    {
        if ( level >= 0 && level <= 9)
        {
            this.compressionLevel = level;
        }
    }
void rene.util.PngEncoder.setDPI ( double  dpi) [inline]

Definition at line 152 of file PngEncoder.java.

    {  DPI=dpi;
    }
void rene.util.PngEncoder.setEncodeAlpha ( boolean  encodeAlpha) [inline]

Set the alpha encoding on or off.

Parameters:
encodeAlphafalse=no, true=yes

Definition at line 218 of file PngEncoder.java.

    {
        this.encodeAlpha = encodeAlpha;
    }
void rene.util.PngEncoder.setFilter ( int  whichFilter) [inline]

Set the filter to use.

Parameters:
whichFilterfrom constant list

Definition at line 238 of file PngEncoder.java.

    {
        this.filter = FILTER_NONE;
        if ( whichFilter <= FILTER_LAST )
        {
            this.filter = whichFilter;
        }
    }

Here is the caller graph for this function:

void rene.util.PngEncoder.setImage ( Image  image) [inline]

Set the image to be encoded.

Parameters:
imageA Java Image object which uses the DirectColorModel
See also:
java.awt.Image
java.awt.image.DirectColorModel

Definition at line 146 of file PngEncoder.java.

    {
        this.image = image;
        pngBytes = null;
    }
int rene.util.PngEncoder.writeByte ( int  b,
int  offset 
) [inline, protected]

Write a single byte into the pngBytes array at a given position.

Parameters:
nThe integer to be written into pngBytes.
offsetThe starting point to write to.
Returns:
The next place to be written to in the pngBytes array.

Definition at line 382 of file PngEncoder.java.

    {
        byte[] temp = { (byte) b };
        return writeBytes( temp, offset );
    }

Here is the call graph for this function:

Here is the caller graph for this function:

int rene.util.PngEncoder.writeBytes ( byte[]  data,
int  offset 
) [inline, protected]

Write an array of bytes into the pngBytes array.

Note: This routine has the side effect of updating maxPos, the largest element written in the array. The array is resized by 1000 bytes or the length of the data to be written, whichever is larger.

Parameters:
dataThe data to be written into pngBytes.
offsetThe starting point to write to.
Returns:
The next place to be written to in the pngBytes array.

Definition at line 309 of file PngEncoder.java.

    {
        maxPos = Math.max( maxPos, offset + data.length );
        if (data.length + offset > pngBytes.length)
        {
            pngBytes = resizeByteArray( pngBytes, pngBytes.length +
                Math.max( 1000, data.length ) );
        }
        System.arraycopy( data, 0, pngBytes, offset, data.length );
        return offset + data.length;
    }

Here is the call graph for this function:

Here is the caller graph for this function:

int rene.util.PngEncoder.writeBytes ( byte[]  data,
int  nBytes,
int  offset 
) [inline, protected]

Write an array of bytes into the pngBytes array, specifying number of bytes to write.

Note: This routine has the side effect of updating maxPos, the largest element written in the array. The array is resized by 1000 bytes or the length of the data to be written, whichever is larger.

Parameters:
dataThe data to be written into pngBytes.
nBytesThe number of bytes to be written.
offsetThe starting point to write to.
Returns:
The next place to be written to in the pngBytes array.

Definition at line 333 of file PngEncoder.java.

    {
        maxPos = Math.max( maxPos, offset + nBytes );
        if (nBytes + offset > pngBytes.length)
        {
            pngBytes = resizeByteArray( pngBytes, pngBytes.length +
                Math.max( 1000, nBytes ) );
        }
        System.arraycopy( data, 0, pngBytes, offset, nBytes );
        return offset + nBytes;
    }

Here is the call graph for this function:

void rene.util.PngEncoder.writeEnd ( ) [inline, protected]

Write a PNG "IEND" chunk into the pngBytes array.

Definition at line 639 of file PngEncoder.java.

    {
        bytePos = writeInt4( 0, bytePos );
        bytePos = writeString( "IEND", bytePos );
        crc.reset();
        crc.update("IEND".getBytes());
        crcValue = crc.getValue();
        bytePos = writeInt4( (int) crcValue, bytePos );
    }

Here is the call graph for this function:

Here is the caller graph for this function:

void rene.util.PngEncoder.writeHeader ( ) [inline, protected]

Write a PNG "IHDR" chunk into the pngBytes array.

Definition at line 406 of file PngEncoder.java.

    {
        int startPos;

        startPos = bytePos = writeInt4( 13, bytePos );
        bytePos = writeString( "IHDR", bytePos );
        width = image.getWidth( null );
        height = image.getHeight( null );
        bytePos = writeInt4( width, bytePos );
        bytePos = writeInt4( height, bytePos );
        bytePos = writeByte( 8, bytePos ); // bit depth
        bytePos = writeByte( (encodeAlpha) ? 6 : 2, bytePos ); // direct model
        bytePos = writeByte( 0, bytePos ); // compression method
        bytePos = writeByte( 0, bytePos ); // filter method
        bytePos = writeByte( 0, bytePos ); // no interlace
        crc.reset();
        crc.update( pngBytes, startPos, bytePos-startPos );
        crcValue = crc.getValue();
        bytePos = writeInt4( (int) crcValue, bytePos );
    }

Here is the call graph for this function:

Here is the caller graph for this function:

Write the image data into the pngBytes array.

This will write one or more PNG "IDAT" chunks. In order to conserve memory, this method grabs as many rows as will fit into 32K bytes, or the whole image; whichever is less.

Returns:
true if no errors; false if error grabbing pixels

Definition at line 507 of file PngEncoder.java.

    {
        int rowsLeft = height;  // number of rows remaining to write
        int startRow = 0;       // starting row to process this time through
        int nRows;              // how many rows to grab at a time

        byte[] scanLines;       // the scan lines to be compressed
        int scanPos;            // where we are in the scan lines
        int startPos;           // where this line's actual pixels start (used for filtering)

        byte[] compressedLines; // the resultant compressed lines
        int nCompressed;        // how big is the compressed area?

        int depth;              // color depth ( handle only 8 or 32 )

        PixelGrabber pg;

        bytesPerPixel = (encodeAlpha) ? 4 : 3;

        Deflater scrunch = new Deflater( compressionLevel );
        ByteArrayOutputStream outBytes = 
            new ByteArrayOutputStream(1024);
            
        DeflaterOutputStream compBytes =
            new DeflaterOutputStream( outBytes, scrunch );
        try
        {
              nRows = (64*32768-1) / (width*(bytesPerPixel+1));
            
              int[] pixels = new int[width * nRows];

            while (rowsLeft > 0)
            {
              if (nRows>=rowsLeft) nRows=rowsLeft;
              
                 pg = new PixelGrabber(image, 0, startRow,
                    width, nRows, pixels, 0, width);
                try {
                    pg.grabPixels();
                }
                catch (Exception e) {
                    System.err.println("interrupted waiting for pixels!");
                    return false;
                }
                if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
                    System.err.println("image fetch aborted or errored");
                    return false;
                }

                /*
                 * Create a data chunk. scanLines adds "nRows" for
                 * the filter bytes. 
                 */
                scanLines = new byte[width * nRows * bytesPerPixel +  nRows];

                if (filter == FILTER_SUB)
                {
                    leftBytes = new byte[16];
                }
                if (filter == FILTER_UP)
                {
                    priorRow = new byte[width*bytesPerPixel];
                }

                scanPos = 0;
                startPos = 1;
                for (int i=0; i<width*nRows; i++)
                {
                    if (i % width == 0)
                    {
                        scanLines[scanPos++] = (byte) filter; 
                        startPos = scanPos;
                    }
                    scanLines[scanPos++] = (byte) ((pixels[i] >> 16) & 0xff);
                    scanLines[scanPos++] = (byte) ((pixels[i] >>  8) & 0xff);
                    scanLines[scanPos++] = (byte) ((pixels[i]      ) & 0xff);
                    if (encodeAlpha)
                    {
                        scanLines[scanPos++] = (byte) ((pixels[i] >> 24) & 0xff );
                    }
                    if ((i % width == width-1) && (filter != FILTER_NONE))
                    {
                        if (filter == FILTER_SUB)
                        {
                            filterSub( scanLines, startPos, width );
                        }
                        if (filter == FILTER_UP)
                        {
                            filterUp( scanLines, startPos, width );
                        }
                    }
                }

                /*
                 * Write these lines to the output area
                 */
                compBytes.write( scanLines, 0, scanPos );


                startRow += nRows;
                rowsLeft -= nRows;
            }
            compBytes.close();

            /*
             * Write the compressed bytes
             */
            compressedLines = outBytes.toByteArray();
            nCompressed = compressedLines.length;

            crc.reset();
            bytePos = writeInt4( nCompressed, bytePos );
            bytePos = writeString("IDAT", bytePos );
            crc.update("IDAT".getBytes());
            bytePos = writeBytes( compressedLines, nCompressed, bytePos );
            crc.update( compressedLines, 0, nCompressed );

            crcValue = crc.getValue();
            bytePos = writeInt4( (int) crcValue, bytePos );
            scrunch.finish();
            return true;
        }
        catch (IOException e)
        {
            System.err.println( e.toString());
            return false;
        }
    }

Here is the call graph for this function:

Here is the caller graph for this function:

int rene.util.PngEncoder.writeInt2 ( int  n,
int  offset 
) [inline, protected]

Write a two-byte integer into the pngBytes array at a given position.

Parameters:
nThe integer to be written into pngBytes.
offsetThe starting point to write to.
Returns:
The next place to be written to in the pngBytes array.

Definition at line 352 of file PngEncoder.java.

    {
        byte[] temp = { (byte)((n >> 8) & 0xff),
            (byte) (n & 0xff) };
        return writeBytes( temp, offset );
    }

Here is the call graph for this function:

int rene.util.PngEncoder.writeInt4 ( int  n,
int  offset 
) [inline, protected]

Write a four-byte integer into the pngBytes array at a given position.

Parameters:
nThe integer to be written into pngBytes.
offsetThe starting point to write to.
Returns:
The next place to be written to in the pngBytes array.

Definition at line 366 of file PngEncoder.java.

    {
        byte[] temp = { (byte)((n >> 24) & 0xff),
            (byte) ((n >> 16) & 0xff ),
            (byte) ((n >> 8) & 0xff ),
            (byte) ( n & 0xff ) };
        return writeBytes( temp, offset );
    }

Here is the call graph for this function:

Here is the caller graph for this function:

void rene.util.PngEncoder.writePhys ( ) [inline, protected]

Write a PNG "pHYs" chunk into the pngBytes array.

Definition at line 430 of file PngEncoder.java.

       {
              int startPos;

              startPos = bytePos = writeInt4( 9, bytePos );
              bytePos = writeString( "pHYs", bytePos );
              int dots=(int)(DPI*39.37);
              bytePos = writeInt4( dots, bytePos );
              bytePos = writeInt4( dots, bytePos );
              bytePos = writeByte( 1, bytePos ); // bit depth
              crc.reset();
              crc.update( pngBytes, startPos, bytePos-startPos );
              crcValue = crc.getValue();
              bytePos = writeInt4( (int) crcValue, bytePos );
       }

Here is the call graph for this function:

Here is the caller graph for this function:

int rene.util.PngEncoder.writeString ( String  s,
int  offset 
) [inline, protected]

Write a string into the pngBytes array at a given position.

This uses the getBytes method, so the encoding used will be its default.

Parameters:
nThe integer to be written into pngBytes.
offsetThe starting point to write to.
Returns:
The next place to be written to in the pngBytes array.
See also:
java.lang.String::getBytes()

Definition at line 398 of file PngEncoder.java.

    {
        return writeBytes( s.getBytes(), offset );
    }

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 62 of file PngEncoder.java.

Definition at line 68 of file PngEncoder.java.

Definition at line 69 of file PngEncoder.java.

CRC32 rene.util.PngEncoder.crc = new CRC32() [protected]

Definition at line 64 of file PngEncoder.java.

Definition at line 65 of file PngEncoder.java.

Definition at line 63 of file PngEncoder.java.

double rene.util.PngEncoder.DPI = 300 [protected]

Definition at line 70 of file PngEncoder.java.

Constant specifying that alpha channel should be encoded.

Definition at line 48 of file PngEncoder.java.

Definition at line 66 of file PngEncoder.java.

Definition at line 63 of file PngEncoder.java.

int rene.util.PngEncoder.filter [protected]

Definition at line 67 of file PngEncoder.java.

final int rene.util.PngEncoder.FILTER_LAST = 2 [static]

Definition at line 55 of file PngEncoder.java.

final int rene.util.PngEncoder.FILTER_NONE = 0 [static]

Constants for filters.

Definition at line 52 of file PngEncoder.java.

final int rene.util.PngEncoder.FILTER_SUB = 1 [static]

Definition at line 53 of file PngEncoder.java.

final int rene.util.PngEncoder.FILTER_UP = 2 [static]

Definition at line 54 of file PngEncoder.java.

int rene.util.PngEncoder.hdrPos [protected]

Definition at line 63 of file PngEncoder.java.

Definition at line 61 of file PngEncoder.java.

Image rene.util.PngEncoder.image [protected]

Definition at line 60 of file PngEncoder.java.

byte [] rene.util.PngEncoder.leftBytes [protected]

Definition at line 59 of file PngEncoder.java.

Definition at line 62 of file PngEncoder.java.

Constant specifying that alpha channel should not be encoded.

Definition at line 50 of file PngEncoder.java.

byte [] rene.util.PngEncoder.pngBytes [protected]

Definition at line 57 of file PngEncoder.java.

byte [] rene.util.PngEncoder.priorRow [protected]

Definition at line 58 of file PngEncoder.java.

int rene.util.PngEncoder.width [protected]

Definition at line 61 of file PngEncoder.java.


The documentation for this class was generated from the following file: