| Constructor: |
public PngEncoderB() {
this( null, false, false, FILTER_NONE, 0 );
}
|
public PngEncoderB(BufferedImage image) {
this(image, false, false, FILTER_NONE, 0);
}
Class constructor specifying BufferedImage to encode, with no alpha channel encoding. Parameters:
image - A Java BufferedImage object
|
public PngEncoderB(BufferedImage image,
boolean encodeAlpha) {
this( image, encodeAlpha, false, FILTER_NONE, 0 );
}
Class constructor specifying BufferedImage to encode, and whether to encode alpha. Parameters:
image - A Java BufferedImage object
encodeAlpha - Encode the alpha channel? false=no; true=yes
|
public PngEncoderB(BufferedImage image,
boolean encodeAlpha,
int whichFilter) {
this( image, encodeAlpha, false, whichFilter, 0 );
}
Class constructor specifying BufferedImage to encode, whether to encode alpha, and filter to use. Parameters:
image - A Java BufferedImage object
encodeAlpha - Encode the alpha channel? false=no; true=yes
whichFilter - 0=none, 1=sub, 2=up
|
public PngEncoderB(BufferedImage image,
boolean encodeAlpha,
boolean grayscale,
int whichFilter,
int compLevel) {
this.image = image;
this.encodeAlpha = encodeAlpha;
this.grayscale = grayscale;
setFilter( whichFilter );
if (compLevel >=0 && compLevel < =9)
{
this.compressionLevel = compLevel;
}
}
Class constructor specifying BufferedImage source to encode, whether to encode alpha, filter to use, and compression level Parameters:
image - A Java BufferedImage object
encodeAlpha - Encode the alpha channel? false=no; true=yes
grayscale - output with grayscale? false=no; true=yes
whichFilter - 0=none, 1=sub, 2=up
compLevel - 0..9
|
| Method from com.keypoint.PngEncoderB Detail: |
protected boolean establishStorageInfo() {
int dataBytes;
wRaster = image.getRaster();
dataBytes = wRaster.getNumDataElements();
tType = wRaster.getTransferType();
if (((tType == DataBuffer.TYPE_BYTE) && (dataBytes == 4)) ||
((tType == DataBuffer.TYPE_INT) && (dataBytes == 1)) )
{
if (grayscale)
bytesPerPixel = (encodeAlpha) ? 2 : 1;
else
bytesPerPixel = (encodeAlpha) ? 4 : 3;
}
else if ((tType == DataBuffer.TYPE_BYTE) && (dataBytes == 1))
{
bytesPerPixel = 1;
encodeAlpha = false; // one-byte samples
}
else
{
return false;
}
return true;
}
Get and set variables that determine how picture is stored.
Retrieves the writable raster of the buffered image,
as well its transfer type.
Sets number of output bytes per pixel, and, if only
eight-bit bytes, turns off alpha encoding. |
public byte[] pngEncode() {
return pngEncode( encodeAlpha );
}
Creates an array of bytes that is the PNG equivalent of the current image.
Alpha encoding is determined by its setting in the constructor. |
public byte[] pngEncode(boolean encodeAlpha) {
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 );
this.image = image;
if (!establishStorageInfo())
{
return 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();
writebKGD();
dataPos = bytePos;
if (writeImageData())
{
writeEnd();
pngBytes = resizeByteArray( pngBytes, maxPos );
}
else
{
pngBytes = null;
}
return pngBytes;
}
Creates an array of bytes that is the PNG equivalent of the current image, specifying whether to encode alpha or not. |
public void setImage(BufferedImage image) {
this.image = image;
pngBytes = null;
}
Set the BufferedImage to be encoded |
protected void writeHeader() {
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
if (grayscale)
bytePos = writeByte( (encodeAlpha) ? 4 : 0, bytePos );
else if (bytesPerPixel != 1)
bytePos = writeByte( (encodeAlpha) ? 6 : 2, bytePos ); // direct model
else
bytePos = writeByte( 3, bytePos ); // indexed
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 );
}
Write a PNG "IHDR" chunk into the pngBytes array. |
protected boolean writeImageData() {
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)
int readPos; // position from which source pixels are read
byte[] compressedLines; // the resultant compressed lines
int nCompressed; // how big is the compressed area?
byte[] pixels; // storage area for byte-sized pixels
int[] iPixels; // storage area for int-sized pixels
Deflater scrunch = new Deflater( compressionLevel );
ByteArrayOutputStream outBytes =
new ByteArrayOutputStream(1024);
DeflaterOutputStream compBytes =
new DeflaterOutputStream( outBytes, scrunch );
if (bytesPerPixel == 1 && !grayscale)
{
writePalette( (IndexColorModel) image.getColorModel() );
}
try
{
while (rowsLeft > 0)
{
nRows = Math.min( 32767 / (width*(bytesPerPixel+1)), rowsLeft );
// nRows = rowsLeft;
/*
* 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];
}
if (tType == DataBuffer.TYPE_BYTE)
{
pixels = (byte[]) wRaster.getDataElements(
0, startRow, width, nRows, null );
iPixels = null;
}
else
{
iPixels = (int[]) wRaster.getDataElements(
0, startRow, width, nRows, null );
pixels = null;
}
scanPos = 0;
readPos = 0;
startPos = 1;
for (int i=0; i< width*nRows; i++)
{
if (i % width == 0)
{
scanLines[scanPos++] = (byte) filter;
startPos = scanPos;
}
if (bytesPerPixel == 1)
{
scanLines[scanPos++] = pixels[readPos++];
}
else if (tType == DataBuffer.TYPE_BYTE)
{
scanLines[scanPos++] = pixels[readPos++];
if (grayscale)
readPos += 2;
else {
scanLines[scanPos++] = pixels[readPos++];
scanLines[scanPos++] = pixels[readPos++];
}
if (encodeAlpha)
{
scanLines[scanPos++] = pixels[readPos++];
}
else
{
readPos++;
}
}
else
{
scanLines[scanPos++] = (byte) ((iPixels[readPos] > > 16) & 0xff);
if (!grayscale) {
scanLines[scanPos++] = (byte) ((iPixels[readPos] > > 8) & 0xff);
scanLines[scanPos++] = (byte) ((iPixels[readPos] ) & 0xff);
}
if (encodeAlpha)
scanLines[scanPos++] = (byte) ((iPixels[readPos] > > 24) & 0xff );
readPos++;
}
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;
}
}
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. |
protected void writePalette(IndexColorModel icm) {
byte[] redPal = new byte[256];
byte[] greenPal = new byte[256];
byte[] bluePal = new byte[256];
byte[] allPal = new byte[768];
int i;
icm.getReds( redPal );
icm.getGreens( greenPal );
icm.getBlues( bluePal );
for (i=0; i< 256; i++)
{
allPal[i*3 ] = redPal[i];
allPal[i*3+1] = greenPal[i];
allPal[i*3+2] = bluePal[i];
}
bytePos = writeInt4( 768, bytePos );
bytePos = writeString( "PLTE", bytePos );
crc.reset();
crc.update("PLTE".getBytes());
bytePos = writeBytes( allPal, bytePos );
crc.update( allPal );
crcValue = crc.getValue();
bytePos = writeInt4( (int) crcValue, bytePos );
// tRNS chunk
if (icm.getTransparency() == IndexColorModel.BITMASK) {
int indtrans = icm.getTransparentPixel();
bytePos = writeInt4( indtrans + 1, bytePos );
bytePos = writeString( "tRNS", bytePos );
crc.reset();
crc.update("tRNS".getBytes());
for (i=0; i< indtrans; i++) {
bytePos = writeByte( 255, bytePos );
crc.update( 255 );
}
bytePos = writeByte( 0, bytePos );
crc.update( 0 );
crcValue = crc.getValue();
bytePos = writeInt4( (int) crcValue, bytePos );
} else if (icm.getTransparency() == IndexColorModel.TRANSLUCENT) {
byte[] alphaPal = new byte[256];
icm.getAlphas(alphaPal);
bytePos = writeInt4( 256, bytePos );
bytePos = writeString( "tRNS", bytePos );
crc.reset();
crc.update("tRNS".getBytes());
bytePos = writeBytes( alphaPal, bytePos );
crc.update( alphaPal );
crcValue = crc.getValue();
bytePos = writeInt4( (int) crcValue, bytePos );
}
}
|
protected void writebKGD() {
if (grayscale) {
int startPos = bytePos = writeInt4( 2, bytePos );
bytePos = writeString( "bKGD", bytePos );
bytePos = writeByte( 0, bytePos );
bytePos = writeByte( 0xFF, bytePos );
crc.reset();
crc.update( pngBytes, startPos, bytePos-startPos );
crcValue = crc.getValue();
bytePos = writeInt4( (int) crcValue, bytePos );
} else if (bytesPerPixel == 4) {
int startPos = bytePos = writeInt4( 6, bytePos );
bytePos = writeString( "bKGD", bytePos );
bytePos = writeByte( 0, bytePos );
bytePos = writeByte( 0xFF, bytePos );
bytePos = writeByte( 0, bytePos );
bytePos = writeByte( 0xFF, bytePos );
bytePos = writeByte( 0, bytePos );
bytePos = writeByte( 0xFF, bytePos );
crc.reset();
crc.update( pngBytes, startPos, bytePos-startPos );
crcValue = crc.getValue();
bytePos = writeInt4( (int) crcValue, bytePos );
} else {
// not implemented
}
}
Write a PNG "bKGD" chunk with the white color |