GifDecoderpublic class GifDecoder extends ImageDecoder
Fields Summary |
---|
private static final int | baseHints | private static final int | interlacedHints | static final int | IMPOSSIBLE_VALUE | private static final int | BUFFER_SIZE | private byte[] | buffer | GifDataStream | gifDataStream | GifGraphicBlock | currBlock | private long | hNativeDecoder | private int | bytesConsumed | private boolean | consumersPrepared | private Hashtable | properties | private boolean | forceRGB | private byte[] | screenBuffer | private int[] | screenRGBBuffer |
Methods Summary |
---|
private native int | decode(byte[] input, int bytesInBuffer, long hDecoder, org.apache.harmony.awt.gl.image.GifDecoder$GifDataStream dataStream, org.apache.harmony.awt.gl.image.GifDecoder$GifGraphicBlock currBlock)
| public void | decodeImage()
try {
int bytesRead = 0;
int needBytes, offset, bytesInBuffer = 0;
boolean eosReached = false;
GifGraphicBlock blockToDispose = null;
// Create new graphic block
if (currBlock == null) {
currBlock = new GifGraphicBlock();
gifDataStream.graphicBlocks.add(currBlock);
}
// Read from the input stream
for (;;) {
needBytes = BUFFER_SIZE - bytesInBuffer;
offset = bytesInBuffer;
bytesRead = inputStream.read(buffer, offset, needBytes);
if (bytesRead < 0) {
eosReached = true;
bytesRead = 0;
} // Don't break, maybe something left in buffer
// Keep track on how much bytes left in buffer
bytesInBuffer += bytesRead;
// Here we pass number of new bytes read from the input stream (bytesRead)
// since native decoder uses java buffer and doesn't have its own
// buffer. So it adds this number to the number of bytes left
// in buffer from the previous call.
int numLines = decode(
buffer,
bytesRead,
hNativeDecoder,
gifDataStream,
currBlock);
// Keep track on how much bytes left in buffer
bytesInBuffer -= bytesConsumed;
if (
!consumersPrepared &&
gifDataStream.logicalScreen.completed &&
gifDataStream.logicalScreen.globalColorTable.completed &&
(currBlock.imageData != null || // Have transparent pixel filled
currBlock.rgbImageData != null)
) {
prepareConsumers();
consumersPrepared = true;
}
if (bytesConsumed < 0) {
break; // Error exit
}
if (currBlock != null) {
if (numLines != 0) {
// Dispose previous image only before showing next
if (blockToDispose != null) {
blockToDispose.dispose();
blockToDispose = null;
}
currBlock.sendNewData(this, numLines);
}
if (currBlock.completed && hNativeDecoder != 0) {
blockToDispose = currBlock; // Dispose only before showing new pixels
currBlock = new GifGraphicBlock();
gifDataStream.graphicBlocks.add(currBlock);
}
}
if (hNativeDecoder == 0) {
break;
}
if (eosReached && numLines == 0) { // Maybe image is truncated...
releaseNativeDecoder(hNativeDecoder);
break;
}
}
} finally {
closeStream();
}
// Here all animation goes
// Repeat image loopCount-1 times or infinitely if loopCount = 0
if (gifDataStream.loopCount != 1) {
if (currBlock.completed == false) {
gifDataStream.graphicBlocks.remove(currBlock);
}
int numFrames = gifDataStream.graphicBlocks.size();
// At first last block will be disposed
GifGraphicBlock gb =
gifDataStream.graphicBlocks.get(numFrames-1);
ImageLoader.beginAnimation();
while (gifDataStream.loopCount != 1) {
if (gifDataStream.loopCount != 0) {
gifDataStream.loopCount--;
}
// Show all frames
for (int i=0; i<numFrames; i++) {
gb.dispose();
gb = gifDataStream.graphicBlocks.get(i);
// Show one frame
if (forceRGB) {
setPixels(
gb.imageLeft,
gb.imageTop,
gb.imageWidth,
gb.imageHeight,
ColorModel.getRGBdefault(),
gb.getRgbImageData(),
0,
gb.imageWidth
);
} else {
setPixels(
gb.imageLeft,
gb.imageTop,
gb.imageWidth,
gb.imageHeight,
null,
gb.imageData,
0,
gb.imageWidth
);
}
}
}
ImageLoader.endAnimation();
}
imageComplete(ImageConsumer.STATICIMAGEDONE);
| private int[] | getScreenRGBBuffer()
if (screenRGBBuffer == null) {
if (screenBuffer != null) {
int transparentColor =
gifDataStream.logicalScreen.globalColorTable.cm.getTransparentPixel();
transparentColor = transparentColor > 0 ? transparentColor : IMPOSSIBLE_VALUE;
screenRGBBuffer =
toRGB(
screenBuffer,
gifDataStream.logicalScreen.globalColorTable.colors,
transparentColor
);
} else {
int size = gifDataStream.logicalScreen.logicalScreenHeight *
gifDataStream.logicalScreen.logicalScreenWidth;
screenRGBBuffer = new int[size];
}
}
return screenRGBBuffer;
| private static native void | initIDs()
| private void | prepareConsumers()
GifLogicalScreen gls = gifDataStream.logicalScreen;
setDimensions(gls.logicalScreenWidth,
gls.logicalScreenHeight);
setProperties(properties);
currBlock = gifDataStream.graphicBlocks.get(0);
if (forceRGB) {
setColorModel(ColorModel.getRGBdefault());
} else {
setColorModel(gls.globalColorTable.getColorModel(currBlock.transparentColor));
}
// Fill screen buffer with the background or transparent color
if (forceRGB) {
int fillColor = 0xFF000000;
if (gls.backgroundColor != IMPOSSIBLE_VALUE) {
fillColor = gls.backgroundColor;
}
Arrays.fill(getScreenRGBBuffer(), fillColor);
} else {
int fillColor = 0;
if (gls.backgroundColor != IMPOSSIBLE_VALUE) {
fillColor = gls.backgroundColor;
} else {
fillColor = gls.globalColorTable.cm.getTransparentPixel();
}
screenBuffer = new byte[gls.logicalScreenHeight*gls.logicalScreenWidth];
Arrays.fill(screenBuffer, (byte) fillColor);
}
setHints(interlacedHints); // XXX - always random pixel order
| private static native void | releaseNativeDecoder(long hDecoder)
| void | setComment(java.lang.String newComment)
Object currComment = properties.get("comment"); //$NON-NLS-1$
if (currComment == null) {
properties.put("comment", newComment); //$NON-NLS-1$
} else {
properties.put("comment", (String) currComment + "\n" + newComment); //$NON-NLS-1$ //$NON-NLS-2$
}
setProperties(properties);
| private static native int[] | toRGB(byte[] imageData, byte[] colormap, int transparentColor)
|
|