/**
  * {@collect.stats} Filters an IndexColorModel object by running each entry in its color tables
  * through the filterRGB function that RGBImageFilter subclasses must provide. Uses coordinates of
  * -1 to indicate that a color table entry is being filtered rather than an actual pixel value.
  *
  * @param icm the IndexColorModel object to be filtered
  * @exception NullPointerException if <code>icm</code> is null
  * @return a new IndexColorModel representing the filtered colors
  */
 public IndexColorModel filterIndexColorModel(IndexColorModel icm) {
   int mapsize = icm.getMapSize();
   byte r[] = new byte[mapsize];
   byte g[] = new byte[mapsize];
   byte b[] = new byte[mapsize];
   byte a[] = new byte[mapsize];
   icm.getReds(r);
   icm.getGreens(g);
   icm.getBlues(b);
   icm.getAlphas(a);
   int trans = icm.getTransparentPixel();
   boolean needalpha = false;
   for (int i = 0; i < mapsize; i++) {
     int rgb = filterRGB(-1, -1, icm.getRGB(i));
     a[i] = (byte) (rgb >> 24);
     if (a[i] != ((byte) 0xff) && i != trans) {
       needalpha = true;
     }
     r[i] = (byte) (rgb >> 16);
     g[i] = (byte) (rgb >> 8);
     b[i] = (byte) (rgb >> 0);
   }
   if (needalpha) {
     return new IndexColorModel(icm.getPixelSize(), mapsize, r, g, b, a);
   } else {
     return new IndexColorModel(icm.getPixelSize(), mapsize, r, g, b, trans);
   }
 }
  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();
          }

          int rassize = width * height;
          byte[] rasfill = new byte[rassize];
          if (tpix != 0) {
            for (int i = 0; i < rassize; i++) {
              rasfill[i] = tpix;
            }
          }
          //		setPixels(x, y, width, height, model, rasfill, 0, 0);
          setPixels(x, y, width, height, model, rasfill, 0, width);
          break;
        case DISPOSAL_SAVE:
          decoder.saved_model = model;
          break;
      }
    }
    return true;
  }
  /** Read Image data */
  private boolean readImage(boolean first, int disposal_method, int delay) throws IOException {
    if (curframe != null && !curframe.dispose()) {
      abort();
      return false;
    }

    long tm = 0;

    if (verbose) {
      tm = System.currentTimeMillis();
    }

    // Allocate the buffer
    byte block[] = new byte[256 + 3];

    // Read the image descriptor
    if (readBytes(block, 0, 10) != 0) {
      throw new IOException();
    }
    int x = ExtractWord(block, 0);
    int y = ExtractWord(block, 2);
    int width = ExtractWord(block, 4);
    int height = ExtractWord(block, 6);
    boolean interlace = (block[8] & INTERLACEMASK) != 0;

    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();
      }
      model = new IndexColorModel(8, num_local_colors, local_colormap, 0, false, trans_pixel);
    } else if (model == null || trans_pixel != model.getTransparentPixel()) {
      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];
    }

    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...");
    }

    boolean ret =
        parseImage(x, y, width, height, interlace, ExtractByte(block, 9), block, rasline, model);

    if (!ret) {
      abort();
    }

    if (verbose) {
      System.out.println("done in " + (System.currentTimeMillis() - tm) + "ms");
    }

    return ret;
  }