private byte readImageDescriptor(InputStream is) throws Exception { int nindex = 0; byte ides[] = new byte[9]; IOUtils.readFully(is, ides, 0, 9); image_x = (ides[nindex++] & 0xff) | ((ides[nindex++] & 0xff) << 8); image_y = (ides[nindex++] & 0xff) | ((ides[nindex++] & 0xff) << 8); width = (ides[nindex++] & 0xff) | ((ides[nindex++] & 0xff) << 8); height = (ides[nindex++] & 0xff) | ((ides[nindex++] & 0xff) << 8); return ides[nindex++]; }
private void readLocalPalette(InputStream is, int num_of_color) throws Exception { int index1 = 0; int bytes2read = num_of_color * 3; byte brgb[] = new byte[bytes2read]; IOUtils.readFully(is, brgb, 0, bytes2read); rgbColorPalette = new int[num_of_color]; for (int i = 0; i < num_of_color; i++) rgbColorPalette[i] = ((255 << 24) | ((brgb[index1++] & 0xff) << 16) | ((brgb[index1++] & 0xff) << 8) | (brgb[index1++] & 0xff)); }
void readHeader(InputStream is) throws Exception { int nindex = 0; byte bhdr[] = new byte[13]; IOUtils.readFully(is, bhdr, 0, 13); for (int i = 0; i < 3; i++) signature[i] = bhdr[nindex++]; for (int i = 0; i < 3; i++) version[i] = bhdr[nindex++]; screen_width = ((bhdr[nindex++] & 0xff) | ((bhdr[nindex++] & 0xff) << 8)); screen_height = ((bhdr[nindex++] & 0xff) | ((bhdr[nindex++] & 0xff) << 8)); flags = bhdr[nindex++]; bgcolor = bhdr[nindex++]; aspectRatio = bhdr[nindex++]; // The end }
private byte[] readFrame(InputStream is) throws Exception { // One time read of global scope data if (gifHeader == null) { if (!readGlobalScopeData(is)) return null; } resetFrameParameters(); int image_separator = 0; do { image_separator = is.read(); if (image_separator == -1 || image_separator == 0x3b) { // End of stream LOGGER.info("End of stream!"); return null; } if (image_separator == 0x21) // (!) Extension Block { int func = is.read(); int len = is.read(); if (func == 0xf9) { // Graphic Control Label - identifies the current block as a Graphic Control // Extension int packedFields = is.read(); // Determine the disposal method disposalMethod = ((packedFields & 0x1c) >> 2); LOGGER.info( "Disposal method: {}", (disposalMethod == 0) ? "UNSPECIFIED" : (disposalMethod == 1) ? "LEAVE_AS_IS" : (disposalMethod == 2) ? "RESTORE_TO_BACKGROUND" : (disposalMethod == 3) ? "RESTORE_TO_PREVIOUS" : "TO_BE_DEFINED"); userInputFlag = ((packedFields & 0x02) >> 1); LOGGER.info("User input flag: {}", (userInputFlag == 0) ? "INPUT_NONE" : "INPUT_SET"); delay = IOUtils.readUnsignedShort(is); LOGGER.info("Delay: {} miliseconds", delay * 10); // Read transparent color index int transparent_color_index = is.read(); // Check for transparent color flag if ((packedFields & 0x01) == 0x01) { transparencyFlag = GIFFrame.TRANSPARENCY_INDEX_SET; LOGGER.info("transparent gif..."); transparent_color = transparent_color_index; } len = is.read(); // len=0, block terminator! } // GIF87a specification mentions the repetition of multiple length // blocks while GIF89a gives no specific description. For safety, here // a while loop is used to check for block terminator! while (len != 0) { IOUtils.skipFully(is, len); len = is.read(); // len=0, block terminator! } } } while (image_separator != 0x2c); // "," byte flags2 = readImageDescriptor(is); boolean hasLocalColorMap = false; if ((flags2 & 0x80) == 0x80) { hasLocalColorMap = true; // A local color map is present LOGGER.info("local color map is present"); bitsPerPixel = (flags2 & 0x07) + 1; colorsUsed = (1 << bitsPerPixel); LOGGER.info("{} color image", colorsUsed); readLocalPalette(is, colorsUsed); } if (!hasLocalColorMap) rgbColorPalette = globalColorPalette; if (transparencyFlag == GIFFrame.TRANSPARENCY_INDEX_SET && transparent_color < colorsUsed) rgbColorPalette[transparent_color] &= 0x00ffffff; if ((flags2 & 0x40) == 0x40) { LOGGER.info("Interlaced gif image!"); return decodeLZWInterLaced(is); } return decodeLZW(is); }