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