📄 gifimage.java
字号:
switch (code) { case 0x2C: // image separator readImage(); break; case 0x21: // extension code = in.read(); switch (code) { case 0xf9: // graphics control extension readGraphicControlExt(); break; case 0xff: // application extension readBlock(); skip(); // don't care break; default: // uninteresting extension skip(); } break; default: done = true; break; } } } /** * Reads next frame image */ protected void readImage() throws IOException { ix = readShort(); // (sub)image position & size iy = readShort(); iw = readShort(); ih = readShort(); int packed = in.read(); lctFlag = (packed & 0x80) != 0; // 1 - local color table flag interlace = (packed & 0x40) != 0; // 2 - interlace flag // 3 - sort flag // 4-5 - reserved lctSize = 2 << (packed & 7); // 6-8 - local color table size m_bpc = newBpc(m_gbpc); if (lctFlag) { m_curr_table = readColorTable((packed & 7) + 1); // read table m_bpc = newBpc((packed & 7) + 1); } else { m_curr_table = m_global_table; } if (transparency && transIndex >= m_curr_table.length / 3) transparency = false; if (transparency && m_bpc == 1) { // Acrobat 5.05 doesn't like this combination byte tp[] = new byte[12]; System.arraycopy(m_curr_table, 0, tp, 0, 6); m_curr_table = tp; m_bpc = 2; } boolean skipZero = decodeImageData(); // decode pixel data if (!skipZero) skip(); Image img = null; try { img = new ImgRaw(iw, ih, 1, m_bpc, m_out); PdfArray colorspace = new PdfArray(); colorspace.add(PdfName.INDEXED); colorspace.add(PdfName.DEVICERGB); int len = m_curr_table.length; colorspace.add(new PdfNumber(len / 3 - 1)); colorspace.add(new PdfString(m_curr_table)); PdfDictionary ad = new PdfDictionary(); ad.put(PdfName.COLORSPACE, colorspace); img.setAdditional(ad); if (transparency) { img.setTransparency(new int[]{transIndex, transIndex}); } } catch (Exception e) { throw new ExceptionConverter(e); } img.setOriginalType(Image.ORIGINAL_GIF); img.setOriginalData(fromData); img.setUrl(fromUrl); GifFrame gf = new GifFrame(); gf.image = img; gf.ix = ix; gf.iy = iy; frames.add(gf); // add image to frame list //resetFrame(); } protected boolean decodeImageData() throws IOException { int NullCode = -1; int npix = iw * ih; int available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, count, i, datum, data_size, first, top, bi; boolean skipZero = false; if (prefix == null) prefix = new short[MaxStackSize]; if (suffix == null) suffix = new byte[MaxStackSize]; if (pixelStack == null) pixelStack = new byte[MaxStackSize+1]; m_line_stride = (iw * m_bpc + 7) / 8; m_out = new byte[m_line_stride * ih]; int pass = 1; int inc = interlace ? 8 : 1; int line = 0; int xpos = 0; // Initialize GIF data stream decoder. data_size = in.read(); clear = 1 << data_size; end_of_information = clear + 1; available = clear + 2; old_code = NullCode; code_size = data_size + 1; code_mask = (1 << code_size) - 1; for (code = 0; code < clear; code++) { prefix[code] = 0; suffix[code] = (byte) code; } // Decode GIF pixel stream. datum = bits = count = first = top = bi = 0; for (i = 0; i < npix; ) { if (top == 0) { if (bits < code_size) { // Load bytes until there are enough bits for a code. if (count == 0) { // Read a new data block. count = readBlock(); if (count <= 0) { skipZero = true; break; } bi = 0; } datum += (block[bi] & 0xff) << bits; bits += 8; bi++; count--; continue; } // Get the next code. code = datum & code_mask; datum >>= code_size; bits -= code_size; // Interpret the code if ((code > available) || (code == end_of_information)) break; if (code == clear) { // Reset decoder. code_size = data_size + 1; code_mask = (1 << code_size) - 1; available = clear + 2; old_code = NullCode; continue; } if (old_code == NullCode) { pixelStack[top++] = suffix[code]; old_code = code; first = code; continue; } in_code = code; if (code == available) { pixelStack[top++] = (byte) first; code = old_code; } while (code > clear) { pixelStack[top++] = suffix[code]; code = prefix[code]; } first = suffix[code] & 0xff; // Add a new string to the string table, if (available >= MaxStackSize) break; pixelStack[top++] = (byte) first; prefix[available] = (short) old_code; suffix[available] = (byte) first; available++; if (((available & code_mask) == 0) && (available < MaxStackSize)) { code_size++; code_mask += available; } old_code = in_code; } // Pop a pixel off the pixel stack. top--; i++; setPixel(xpos, line, pixelStack[top]); ++xpos; if (xpos >= iw) { xpos = 0; line += inc; if (line >= ih) { if (interlace) { do { pass++; switch (pass) { case 2: line = 4; break; case 3: line = 2; inc = 4; break; case 4: line = 1; inc = 2; break; default: // this shouldn't happen line = ih - 1; inc = 0; } } while (line >= ih); } else { line = ih - 1; // this shouldn't happen inc = 0; } } } } return skipZero; } protected void setPixel(int x, int y, int v) { if (m_bpc == 8) { int pos = x + iw * y; m_out[pos] = (byte)v; } else { int pos = m_line_stride * y + x / (8 / m_bpc); int vout = v << (8 - m_bpc * (x % (8 / m_bpc))- m_bpc); m_out[pos] |= vout; } } /** * Resets frame state for reading next image. */ protected void resetFrame() { // it does nothing in the pdf context //boolean transparency = false; //int delay = 0; } /** * Reads Graphics Control Extension values */ protected void readGraphicControlExt() throws IOException { in.read(); // block size int packed = in.read(); // packed fields dispose = (packed & 0x1c) >> 2; // disposal method if (dispose == 0) dispose = 1; // elect to keep old image if discretionary transparency = (packed & 1) != 0; delay = readShort() * 10; // delay in milliseconds transIndex = in.read(); // transparent color index in.read(); // block terminator } /** * Skips variable length blocks up to and including * next zero length block. */ protected void skip() throws IOException { do { readBlock(); } while (blockSize > 0); } static class GifFrame { Image image; int ix; int iy; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -