/**
  * {@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);
   }
 }
예제 #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);
        }
      }
    }
  /*
   * 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;
        }
      }
    }
  }