/**
  * {@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);
   }
 }
Esempio n. 2
0
    void setHistogram(ImagePlus imp, int j) {
      ImageProcessor ip = imp.getProcessor();
      ImageStatistics stats = ImageStatistics.getStatistics(ip, AREA + MODE, null);
      int maxCount2 = 0;
      histogram = stats.histogram;
      for (int i = 0; i < stats.nBins; i++)
        if ((histogram[i] > maxCount2) && (i != stats.mode)) maxCount2 = histogram[i];
      hmax = stats.maxCount;
      if ((hmax > (maxCount2 * 1.5)) && (maxCount2 != 0)) { // GL 1.5 was 2
        hmax = (int) (maxCount2 * 1.1); // GL 1.1 was 1.5
        histogram[stats.mode] = hmax;
      }
      os = null;
      ColorModel cm = ip.getColorModel();
      if (!(cm instanceof IndexColorModel)) return;
      IndexColorModel icm = (IndexColorModel) cm;
      int mapSize = icm.getMapSize();
      if (mapSize != 256) return;
      byte[] r = new byte[256];
      byte[] g = new byte[256];
      byte[] b = new byte[256];
      icm.getReds(r);
      icm.getGreens(g);
      icm.getBlues(b);
      hColors = new Color[256];

      if (isRGB) {
        if (j == 0) {
          for (int i = 0; i < 256; i++) hColors[i] = new Color(i & 255, 0 & 255, 0 & 255);
        } else if (j == 1) {
          for (int i = 0; i < 256; i++) hColors[i] = new Color(0 & 255, i & 255, 0 & 255);
        } else if (j == 2) {
          for (int i = 0; i < 256; i++) hColors[i] = new Color(0 & 255, 0 & 255, i & 255);
        }
      } else {
        if (j == 0) {
          for (int i = 0; i < 256; i++) hColors[i] = new Color(r[i] & 255, g[i] & 255, b[i] & 255);
        } else if (j == 1) {
          for (int i = 0; i < 256; i++)
            // hColors[i] = new Color(127-i/2&255, 127+i/2&255, 127-i/2&255);
            hColors[i] = new Color(192 - i / 4 & 255, 192 + i / 4 & 255, 192 - i / 4 & 255);
        } else if (j == 2) {
          for (int i = 0; i < 256; i++) hColors[i] = new Color(i & 255, i & 255, 0 & 255);
        }
      }
    }
  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;
  }
  /*
   * This is converted from the native version. The java version is
   * much faster when we have JIT.
   */
  private boolean parseImage(
      int relx,
      int rely,
      int width,
      int height,
      boolean interlace,
      int initCodeSize,
      byte block[],
      byte rasline[],
      IndexColorModel model) {
    int OUTCODELENGTH = 4097;

    int clearCode = (1 << initCodeSize);
    int eofCode = clearCode + 1;
    int bitMask;
    int curCode;
    int outCount = OUTCODELENGTH;

    /* Variables used to form reading data */
    boolean blockEnd = false;
    int remain = 0;
    int byteoff = 0;
    int accumbits = 0;
    int accumdata = 0;

    /* Variables used to decompress the data */
    int codeSize = initCodeSize + 1;
    int maxCode = 1 << codeSize;
    int codeMask = maxCode - 1;
    int freeCode = clearCode + 2;
    int code = 0;
    int oldCode = 0;
    char prevChar = 0;

    // int blockLength = 0;
    int blockLength = 0;

    /* Variables used for writing pixels */
    int x = width;
    int y = 0;
    int off = 0;
    int passinc = interlace ? 8 : 1;
    int passht = passinc;
    int len;

    bitMask = model.getMapSize() - 1;

    /* Read codes until the eofCode is encountered */
    for (; ; ) {
      if (accumbits < codeSize) {
        boolean lastByte = false;
        /* fill the buffer if needed */
        while (remain < 2) {
          if (blockEnd) {
            /* Sometimes we have one last byte to process... */
            if (remain == 1 && accumbits + 8 >= codeSize) {
              break;
            }

            if (off > 0) {
              //                             sendPixels(relx, rely+y, width, passht, rasline,
              // model);
              sendPixels(relx, rely + y, width, 1, rasline, model);
            }
            /* quietly accept truncated GIF images */
            return false;
          }
          /* move remaining bytes to the beginning of the buffer */
          block[0] = block[byteoff];
          byteoff = 0;

          /* fill the block */
          len = readBytes(block, remain, blockLength + 1);

          remain += blockLength;
          if (len > 0) {
            remain -= (len - 1);
            blockLength = 0;
          } else {
            blockLength = (block[remain] & 0xff);
          }
          if (blockLength == 0) {
            blockEnd = true;
          }
        }

        /* 2 bytes at a time saves checking for accumbits < codeSize.
         * We know we'll get enough and also that we can't overflow
         * since codeSize <= 12.
         */
        if (!lastByte) {
          remain -= 2;
          accumdata += (block[byteoff++] & 0xff) << accumbits;
          accumbits += 8;
          accumdata += (block[byteoff++] & 0xff) << accumbits;
          accumbits += 8;
        } else {
          remain--;
          accumdata += (block[byteoff++] & 0xff) << accumbits;
          accumbits += 8;
        }
      }

      /* Compute the code */
      code = accumdata & codeMask;
      accumdata >>= codeSize;
      accumbits -= codeSize;

      /*
       * Interpret the code
       */
      if (code == clearCode) {
        /* Clear code sets everything back to its initial value, then
         * reads the immediately subsequent code as uncompressed data.
         */

        /* Note that freeCode is one less than it is supposed to be,
         * this is because it will be incremented next time round the
         * loop
         */
        freeCode = clearCode + 1;
        codeSize = initCodeSize + 1;
        maxCode = 1 << codeSize;
        codeMask = maxCode - 1;

        /* Continue if we've NOT reached the end, some Gif images
         * contain bogus codes after the last clear code.
         */
        if (y < height) {
          continue;
        }

        /* pretend we've reached the end of the data */
        code = eofCode;
      }

      if (code == eofCode) {
        /* make sure we read the whole block of pixels. */
        while (!blockEnd) {
          if (readBytes(block, 0, blockLength + 1) != 0) {
            /* quietly accept truncated GIF images */
            return false;
          }
          blockLength = block[blockLength];
          blockEnd = (blockLength == 0);
        }
        return true;
      }

      /* It must be data: save code in CurCode */
      curCode = code;
      /* Whenever it gets here outCount is always equal to
      OUTCODELENGTH, so no need to reset outCount. */
      // outCount = OUTCODELENGTH;

      /* If greater or equal to freeCode, not in the hash table
       * yet; repeat the last character decoded
       */
      if (curCode >= freeCode) {
        if (curCode > freeCode) {
          /*
           * if we get a code too far outside our range, it
           * could case the parser to start traversing parts
           * of our data structure that are out of range...
           */
          /*In native version: goto flushit;*/
          while (!blockEnd) {
            if (readBytes(block, 0, blockLength + 1) != 0) {
              /* quietly accept truncated GIF images */
              return false;
            }
            blockLength = block[blockLength];
            blockEnd = (blockLength == 0);
          }
          return true;
        }
        curCode = oldCode;
        outCode[--outCount] = (byte) prevChar;
      }

      /* Unless this code is raw data, pursue the chain pointed
       * to by curCode through the hash table to its end; each
       * code in the chain puts its associated output code on
       * the output queue.
       */
      while (curCode > bitMask) {
        outCode[--outCount] = suffix[curCode];
        if (outCount == 0) {
          /*
           * In theory this should never happen since our
           * prefix and suffix arrays are monotonically
           * decreasing and so outCode will only be filled
           * as much as those arrays, but I don't want to
           * take that chance and the test is probably
           * cheap compared to the read and write operations.
           * If we ever do overflow the array, we will just
           * flush the rest of the data and quietly accept
           * the GIF as truncated here.
           */
          // In native version: goto flushit;
          while (!blockEnd) {
            if (readBytes(block, 0, blockLength + 1) != 0) {
              /* quietly accept truncated GIF images */
              return false;
            }
            blockLength = block[blockLength];
            blockEnd = (blockLength == 0);
          }
          return true;
        }
        curCode = prefix[curCode];
      }

      /* The last code in the chain is treated as raw data. */
      prevChar = (char) curCode;
      outCode[--outCount] = (byte) prevChar;

      /* Now we put the data out to the Output routine. It's
       * been stacked LIFO, so deal with it that way...
       */
      len = OUTCODELENGTH - outCount; /* This is why I commented out
                                               the code that resets outCount. */
      while (--len >= 0) {
        rasline[off++] = outCode[outCount++];

        /* Update the X-coordinate, and if it overflows, update the
         * Y-coordinate
         */
        if (--x == 0) {
          int count;

          /* If a non-interlaced picture, just increment y to the next
           * scan line.  If it's interlaced, deal with the interlace as
           * described in the GIF spec.  Put the decoded scan line out
           * to the screen if we haven't gone past the bottom of it
           */
          //                    count = sendPixels(relx, rely+y, width, passht, rasline, model);
          count = sendPixels(relx, rely + y, width, 1, rasline, model);

          if (count <= 0) {
            /* Nobody is listening any more. */
            return false;
          }

          x = width;
          off = 0;
          /*  pass        inc     ht      ystart */
          /*   0           8      8          0   */
          /*   1           8      4          4   */
          /*   2           4      2          2   */
          /*   3           2      1          1   */
          y += passinc;
          while (y >= height) {
            passinc = passht;
            passht >>= 1;
            y = passht;
            if (passht == 0) {
              // In native version: goto flushit;
              while (!blockEnd) {
                if (readBytes(block, 0, blockLength + 1) != 0) {
                  /* quietly accept truncated GIF images */
                  return false;
                }
                blockLength = block[blockLength] & 0xff;
                blockEnd = (blockLength == 0);
              }
              return true;
            }
          }
        }
      }

      /* Build the hash table on-the-fly. No table is stored in the file. */
      prefix[freeCode] = (short) oldCode;
      suffix[freeCode] = (byte) prevChar;
      oldCode = code;
      /* Point to the next slot in the table.  If we exceed the
       * maxCode, increment the code size unless
       * it's already 12.  If it is, do nothing: the next code
       * decompressed better be CLEAR
       */
      if (++freeCode >= maxCode) {
        if (codeSize < 12) {
          codeSize++;
          maxCode <<= 1;
          codeMask = maxCode - 1;
        } else {
          /* Just in case */
          freeCode = maxCode - 1;
        }
      }
    }
  }
Esempio n. 6
0
 Color getColor(int index) {
   IndexColorModel cm = (IndexColorModel) imp.getProcessor().getColorModel();
   // IJ.write(""+index+" "+(new Color(cm.getRGB(index))));
   return new Color(cm.getRGB(index));
 }