/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*-
* Reads GIF images from an InputStream and reports the
* image data to an InputStreamImageSource object.
*
* The algorithm is copyright of CompuServe.
*/
/**
* Gif Image converter
*
* @author Arthur van Hoff
* @author Jim Graham
*/
private static final boolean verbose = false;
int num_global_colors;
byte[] global_colormap;
byte[] saved_image;
int global_width;
int global_height;
int global_bgpixel;
}
/**
* An error has occurred. Throw an exception.
*/
throw new ImageFormatException(s1);
}
/**
* Read a number of bytes into a buffer.
* @return number of bytes that were not read due to EOF or error
*/
while (len > 0) {
try {
if (n < 0) {
break;
}
off += n;
len -= n;
} catch (IOException e) {
break;
}
}
return len;
}
}
}
/**
* produce an image from the stream.
*/
try {
readHeader();
int totalframes = 0;
int frameno = 0;
int nloops = -1;
int disposal_method = 0;
int delay = -1;
boolean loopsRead = false;
boolean isAnimation = false;
while (!aborted) {
int code;
case EXBLOCK:
case EX_GRAPHICS_CONTROL: {
byte buf[] = new byte[6];
return;//error("corrupt GIF file");
}
return;//error("corrupt GIF file (GCE size)");
}
// Get the index of the transparent color
isAnimation = true;
}
} else {
trans_pixel = -1;
}
break;
}
case EX_COMMENT:
case EX_APPLICATION:
default:
boolean loop_tag = false;
while (true) {
if (n <= 0) {
break;
}
byte buf[] = new byte[n];
return;//error("corrupt GIF file");
}
if (code == EX_COMMENT) {
} else if (code == EX_APPLICATION) {
if (loop_tag) {
if (loopsRead) {
}
else {
loopsRead = true;
}
} else {
loop_tag = false;
}
}
loop_tag = true;
}
}
}
if (code == EX_COMMENT) {
}
if (loop_tag && !isAnimation) {
isAnimation = true;
}
break;
case -1:
return; //error("corrupt GIF file");
}
break;
case IMAGESEP:
if (!isAnimation) {
}
try {
delay)) {
return;
}
} catch (Exception e) {
if (verbose) {
e.printStackTrace();
}
return;
}
frameno++;
totalframes++;
break;
default:
case -1:
if (verbose) {
if (code == -1) {
" frame " + frameno);
} else {
+ code + "].");
}
}
if (frameno == 0) {
return;
}
// NOBREAK
case TERMINATOR:
try {
}
saved_image = null;
saved_model = null;
frameno = 0;
break;
} catch (IOException e) {
return; // Unable to reset input buffer
}
}
+ " frames: " + frameno
+ " total: " + totalframes);
}
return;
}
}
} finally {
close();
}
}
/**
* Read Image header
*/
// Create a buffer
byte buf[] = new byte[13];
// Read the header
throw new IOException();
}
// Check header
error("not a GIF file.");
}
// Global width&height
// colormap info
// no global colormap so make up our own
// If there is a local colormap, it will override what we
// have here. If there is not a local colormap, the rules
// for GIF89 say that we can use whatever colormap we want.
// This means that we should probably put in a full 256 colormap
// at some point. REMIND!
num_global_colors = 2;
global_bgpixel = 0;
}
else {
}
// Read colors
throw new IOException();
}
}
}
/**
* The ImageConsumer hints flag for a non-interlaced GIF image.
*/
private static final int normalflags =
/**
* The ImageConsumer hints flag for an interlaced GIF image.
*/
private static final int interlaceflags =
private static native void initIDs();
static {
/* ensure that the necessary native libraries are loaded */
initIDs();
}
boolean interlace, int initCodeSize,
if (y < 0) {
height += y;
y = 0;
}
if (y + height > global_height) {
height = global_height - y;
}
if (height <= 0) {
return 1;
}
// rasline[0] == pixel at coordinate (x,y)
// rasline[width] == pixel at coordinate (x+width, y)
if (x < 0) {
rasbeg = -x;
width += x; // same as (width -= rasbeg)
} else {
rasbeg = 0;
// width -= 0; // same as (width -= rasbeg)
x2 = x; // same as (x2 = x + rasbeg)
}
// rasline[rasbeg] == pixel at coordinate (x2,y)
// rasline[width] == pixel at coordinate (x+width, y)
// rasline[rasbeg + width] == pixel at coordinate (x2+width, y)
}
if (width <= 0) {
return 1;
}
// rasline[rasbeg] == pixel at coordinate (x2,y)
// rasline[rasend] == pixel at coordinate (x2+width, y)
} else if (save) {
}
}
} else {
// We have to do this the hard way - only transmit
// the non-transparent sections of the line...
// Fix for 6301050: the interlacing is ignored in this case
// in order to avoid artefacts in case of animated images.
int runstart = -1;
int count = 1;
if (runstart >= 0) {
i - runstart, 1,
runstart, 0);
if (count == 0) {
break;
}
}
runstart = -1;
} else {
if (runstart < 0) {
runstart = i;
}
if (save) {
}
}
}
if (runstart >= 0) {
runstart, 0);
}
return count;
}
} else if (save) {
}
return count;
}
/**
* Read Image data
*/
throws IOException
{
abort();
return false;
}
long tm = 0;
if (verbose) {
}
// Allocate the buffer
// Read the image descriptor
throw new IOException();
}
/*
* Majority of gif images have
* same logical screen and frame dimensions.
* Also, Photoshop and Mozilla seem to use the logical
* screen dimension (from the global stream header)
* if frame dimension is invalid.
*
* We use similar heuristic and trying to recover
* frame width from logical screen dimension and
* frame offset.
*/
width = global_width - x;
}
height = global_height - y;
}
// We read one extra byte above so now when we must
// transfer that byte as the first colormap byte
// and manually read the code size when we are done
// Read local colors
throw new IOException();
}
// Now read the "real" code size byte which follows
// the local color table
throw new IOException();
}
if (trans_pixel >= num_local_colors) {
// Fix for 4233748: extend colormap to contain transparent pixel
}
0, false, trans_pixel);
if (trans_pixel >= num_global_colors) {
// Fix for 4233748: extend colormap to contain transparent pixel
}
0, false, trans_pixel);
}
// Notify the consumers
if (first) {
}
/*
* If height of current image is smaller than the global height,
* fill the gap with transparent pixels.
*/
if (tpix >= 0) {
byte trans_rasline[] = new byte[global_width];
for (int i=0; i<global_width;i++) {
trans_rasline[i] = tpix;
}
0, 0);
}
}
}
// allocate the raster data
if (verbose) {
}
if (initCodeSize >= 12) {
if (verbose) {
}
return false;
}
if (!ret) {
abort();
}
if (verbose) {
+ "ms");
}
return ret;
}
return newcm;
}
}
class GifFrame {
private static final boolean verbose = false;
int disposal_method;
int delay;
int x;
int y;
int width;
int height;
boolean initialframe;
IndexColorModel cm, int x, int y, int w, int h) {
this.disposal_method = dm;
this.initialframe = init;
this.x = x;
this.y = y;
this.width = w;
this.height = h;
}
private void setPixels(int x, int y, int w, int h,
}
public boolean dispose() {
return false;
} else {
if (delay > 0) {
try {
if (verbose) {
}
} catch (InterruptedException e) {
return false;
}
} else {
}
}
if (x < 0) {
width += x;
x = 0;
}
if (x + width > global_width) {
width = global_width - x;
}
if (width <= 0) {
} else {
if (y < 0) {
height += y;
y = 0;
}
if (y + height > global_height) {
height = global_height - y;
}
if (height <= 0) {
}
}
switch (disposal_method) {
case DISPOSAL_PREVIOUS:
if (saved_image != null) {
y * global_width + x, global_width);
}
break;
case DISPOSAL_BGCOLOR:
byte tpix;
model = trans_model;
new byte[4], 0, true);
trans_model = model;
}
tpix = 0;
} else {
}
if (tpix != 0) {
for (int i = 0; i < width; i++) {
}
}
// clear saved_image using transparent pixels
// this will be used as the background in the next display
}
break;
case DISPOSAL_SAVE:
break;
}
}
return true;
}
}