IndexColorModel model = global_model; if ((block[8] & COLORMAPMASK) != 0) { // 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 int num_local_colors = 1 << ((block[8] & 0x7) + 1); // Read local colors byte[] local_colormap = new byte[num_local_colors * 3]; local_colormap[0] = block[9]; if (readBytes(local_colormap, 1, num_local_colors * 3 - 1) != 0) { throw new IOException(); } // Now read the "real" code size byte which follows // the local color table if (readBytes(block, 9, 1) != 0) { throw new IOException(); } if (trans_pixel >= num_local_colors) { // Fix for 4233748: extend colormap to contain transparent pixel num_local_colors = trans_pixel + 1; local_colormap = grow_colormap(local_colormap, num_local_colors); } model = new IndexColorModel(8, num_local_colors, local_colormap, 0, false, trans_pixel); } else if (model == null || trans_pixel != model.getTransparentPixel()) { if (trans_pixel >= num_global_colors) { // Fix for 4233748: extend colormap to contain transparent pixel num_global_colors = trans_pixel + 1; global_colormap = grow_colormap(global_colormap, num_global_colors); } model = new IndexColorModel(8, num_global_colors, global_colormap, 0, false, trans_pixel); global_model = model; } // Notify the consumers if (first) { if (global_width == 0) global_width = width; if (global_height == 0) global_height = height; setDimensions(global_width, global_height); setProperties(props); setColorModel(model); headerComplete(); } if (disposal_method == GifFrame.DISPOSAL_SAVE && saved_image == null) { saved_image = new byte[global_width * global_height]; /* * If height of current image is smaller than the global height, * fill the gap with transparent pixels. */ if ((height < global_height) && (model != null)) { byte tpix = (byte)model.getTransparentPixel(); if (tpix >= 0) { byte trans_rasline[] = new byte[global_width]; for (int i=0; i<global_width;i++) { trans_rasline[i] = tpix; } setPixels(0, 0, global_width, y, model, trans_rasline, 0, 0); setPixels(0, y+height, global_width, global_height-height-y, model, trans_rasline, 0, 0); } } } int hints = (interlace ? interlaceflags : normalflags); setHints(hints); curframe = new GifFrame(this, disposal_method, delay, (curframe == null), model, x, y, width, height); // allocate the raster data byte rasline[] = new byte[width]; if (verbose) { System.out.print("Reading a " + width + " by " + height + " " + (interlace ? "" : "non-") + "interlaced image..."); } int initCodeSize = ExtractByte(block, 9); if (initCodeSize >= 12) { if (verbose) { System.out.println("Invalid initial code size: " + initCodeSize); } return false; } boolean ret = parseImage(x, y, width, height, interlace, initCodeSize, block, rasline, model); if (!ret) { abort(); } if (verbose) { System.out.println("done in " + (System.currentTimeMillis() - tm) + "ms"); } return ret; } public static byte[] grow_colormap(byte[] colormap, int newlen) { byte[] newcm = new byte[newlen * 3]; System.arraycopy(colormap, 0, newcm, 0, colormap.length); return newcm; }} class GifFrame { private static final boolean verbose = false; private static IndexColorModel trans_model; static final int DISPOSAL_NONE = 0x00; static final int DISPOSAL_SAVE = 0x01; static final int DISPOSAL_BGCOLOR = 0x02; static final int DISPOSAL_PREVIOUS = 0x03; GifImageDecoder decoder; int disposal_method; int delay; IndexColorModel model; int x; int y; int width; int height; boolean initialframe; public GifFrame(GifImageDecoder id, int dm, int dl, boolean init, IndexColorModel cm, int x, int y, int w, int h) { this.decoder = id; this.disposal_method = dm; this.delay = dl; this.model = cm; 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, ColorModel cm, byte[] pix, int off, int scan) { decoder.setPixels(x, y, w, h, cm, pix, off, scan); } public boolean dispose() { if (decoder.imageComplete(ImageConsumer.SINGLEFRAMEDONE, false) == 0) { return false; } else { if (delay > 0) { try { if (verbose) { System.out.println("sleeping: "+delay); } Thread.sleep(delay); } catch (InterruptedException e) { return false; } } else { Thread.yield(); } if (verbose && disposal_method != 0) { System.out.println("disposal method: "+disposal_method); } int global_width = decoder.global_width; int global_height = decoder.global_height; if (x < 0) { width += x; x = 0; } if (x + width > global_width) { width = global_width - x; } if (width <= 0) { disposal_method = DISPOSAL_NONE; } else { if (y < 0) { height += y; y = 0; } if (y + height > global_height) { height = global_height - y; } if (height <= 0) { disposal_method = DISPOSAL_NONE; } } switch (disposal_method) { case DISPOSAL_PREVIOUS: byte[] saved_image = decoder.saved_image; IndexColorModel saved_model = decoder.saved_model; if (saved_image != null) { setPixels(x, y, width, height, saved_model, saved_image, y * global_width + x, global_width); } break; case DISPOSAL_BGCOLOR: byte tpix; if (model.getTransparentPixel() < 0) { model = trans_model; if (model == null) { model = new IndexColorModel(8, 1, new byte[4], 0, true); trans_model = model; } tpix = 0; } else { tpix = (byte) model.getTransparentPixel(); } byte[] rasline = new byte[width]; if (tpix != 0) { for (int i = 0; i < width; i++) { rasline[i] = tpix; } } // clear saved_image using transparent pixels // this will be used as the background in the next display if( decoder.saved_image != null ) { for( int i = 0; i < global_width * global_height; i ++ ) decoder.saved_image[i] = tpix; } setPixels(x, y, width, height, model, rasline, 0, 0); break; case DISPOSAL_SAVE: decoder.saved_model = model; break; } } return true; }}Lines 501–753 of 753. Previous lines
IndexColorModel model = global_model; if ((block[8] & COLORMAPMASK) != 0) { // 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 int num_local_colors = 1 << ((block[8] & 0x7) + 1); // Read local colors byte[] local_colormap = new byte[num_local_colors * 3]; local_colormap[0] = block[9]; if (readBytes(local_colormap, 1, num_local_colors * 3 - 1) != 0) { throw new IOException(); } // Now read the "real" code size byte which follows // the local color table if (readBytes(block, 9, 1) != 0) { throw new IOException(); } if (trans_pixel >= num_local_colors) { // Fix for 4233748: extend colormap to contain transparent pixel num_local_colors = trans_pixel + 1; local_colormap = grow_colormap(local_colormap, num_local_colors); } model = new IndexColorModel(8, num_local_colors, local_colormap, 0, false, trans_pixel); } else if (model == null || trans_pixel != model.getTransparentPixel()) { if (trans_pixel >= num_global_colors) { // Fix for 4233748: extend colormap to contain transparent pixel num_global_colors = trans_pixel + 1; global_colormap = grow_colormap(global_colormap, num_global_colors); } model = new IndexColorModel(8, num_global_colors, global_colormap, 0, false, trans_pixel); global_model = model; } // Notify the consumers if (first) { if (global_width == 0) global_width = width; if (global_height == 0) global_height = height; setDimensions(global_width, global_height); setProperties(props); setColorModel(model); headerComplete(); } if (disposal_method == GifFrame.DISPOSAL_SAVE && saved_image == null) { saved_image = new byte[global_width * global_height]; /* * If height of current image is smaller than the global height, * fill the gap with transparent pixels. */ if ((height < global_height) && (model != null)) { byte tpix = (byte)model.getTransparentPixel(); if (tpix >= 0) { byte trans_rasline[] = new byte[global_width]; for (int i=0; i<global_width;i++) { trans_rasline[i] = tpix; } setPixels(0, 0, global_width, y, model, trans_rasline, 0, 0); setPixels(0, y+height, global_width, global_height-height-y, model, trans_rasline, 0, 0); } } } int hints = (interlace ? interlaceflags : normalflags); setHints(hints); curframe = new GifFrame(this, disposal_method, delay, (curframe == null), model, x, y, width, height); // allocate the raster data byte rasline[] = new byte[width]; if (verbose) { System.out.print("Reading a " + width + " by " + height + " " + (interlace ? "" : "non-") + "interlaced image..."); } int initCodeSize = ExtractByte(block, 9); if (initCodeSize >= 12) { if (verbose) { System.out.println("Invalid initial code size: " + initCodeSize); } return false; } boolean ret = parseImage(x, y, width, height, interlace, initCodeSize, block, rasline, model); if (!ret) { abort(); } if (verbose) { System.out.println("done in " + (System.currentTimeMillis() - tm) + "ms"); } return ret; } public static byte[] grow_colormap(byte[] colormap, int newlen) { byte[] newcm = new byte[newlen * 3]; System.arraycopy(colormap, 0, newcm, 0, colormap.length); return newcm; } } class GifFrame { private static final boolean verbose = false; private static IndexColorModel trans_model; static final int DISPOSAL_NONE = 0x00; static final int DISPOSAL_SAVE = 0x01; static final int DISPOSAL_BGCOLOR = 0x02; static final int DISPOSAL_PREVIOUS = 0x03; GifImageDecoder decoder; int disposal_method; int delay; IndexColorModel model; int x; int y; int width; int height; boolean initialframe; public GifFrame(GifImageDecoder id, int dm, int dl, boolean init, IndexColorModel cm, int x, int y, int w, int h) { this.decoder = id; this.disposal_method = dm; this.delay = dl; this.model = cm; 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, ColorModel cm, byte[] pix, int off, int scan) { decoder.setPixels(x, y, w, h, cm, pix, off, scan); } public boolean dispose() { if (decoder.imageComplete(ImageConsumer.SINGLEFRAMEDONE, false) == 0) { return false; } else { if (delay > 0) { try { if (verbose) { System.out.println("sleeping: "+delay); } Thread.sleep(delay); } catch (InterruptedException e) { return false; } } else { Thread.yield(); } if (verbose && disposal_method != 0) { System.out.println("disposal method: "+disposal_method); } int global_width = decoder.global_width; int global_height = decoder.global_height; if (x < 0) { width += x; x = 0; } if (x + width > global_width) { width = global_width - x; } if (width <= 0) { disposal_method = DISPOSAL_NONE; } else { if (y < 0) { height += y; y = 0; } if (y + height > global_height) { height = global_height - y; } if (height <= 0) { disposal_method = DISPOSAL_NONE; } } switch (disposal_method) { case DISPOSAL_PREVIOUS: byte[] saved_image = decoder.saved_image; IndexColorModel saved_model = decoder.saved_model; if (saved_image != null) { setPixels(x, y, width, height, saved_model, saved_image, y * global_width + x, global_width); } break; case DISPOSAL_BGCOLOR: byte tpix; if (model.getTransparentPixel() < 0) { model = trans_model; if (model == null) { model = new IndexColorModel(8, 1, new byte[4], 0, true); trans_model = model; } tpix = 0; } else { tpix = (byte) model.getTransparentPixel(); } byte[] rasline = new byte[width]; if (tpix != 0) { for (int i = 0; i < width; i++) { rasline[i] = tpix; } } // clear saved_image using transparent pixels // this will be used as the background in the next display if( decoder.saved_image != null ) { for( int i = 0; i < global_width * global_height; i ++ ) decoder.saved_image[i] = tpix; } setPixels(x, y, width, height, model, rasline, 0, 0); break; case DISPOSAL_SAVE: decoder.saved_model = model; break; } } return true; } }