Details

    • Type: Bug
    • Status: Open
    • Priority: P4
    • Resolution: Unresolved
    • Affects Version/s: 7
    • Fix Version/s: tbd
    • Component/s: client-libs
    • Labels:

      Description

      FULL PRODUCT VERSION :
      java version "1.7.0_02"
      Java(TM) SE Runtime Environment (build 1.7.0_02-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 22.0-b10, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      GIFImageReader can not read some GIF images,
      because GIFImageReader has two bugs in LZW decoder.

      1. LZW encoder can output the codes after the tree becomes full, without outputting the clearCode(for example it is 256, in 256-color gif image).

      Good LZW encoder determines the timing of outputting the clearCode by the compression rate. if useing the old tree becomes good compression rate, Good LZW encoder does not output the clearCode. if not so, Good LZW encoder outputs the clearCode.

      however, GIFImageReader is based on the wrong assumption, that is LZW encoder always outputs the clearCode before tree becomes overflow.

      when GIFImageReader reads a image which is created by Good LZW encoder, it causes ArrayIndexOutOfBoundsException.


      2. textbookish LZW decoder is drop the first code. it does not attach to the tree.

      however, GIFImageReader attachs first code to the tree. so tree is always broken.

      I understand the part which should be corrected.
      however I don't understand why GIFImageReader can read images with broken tree.

      show other implementation of GIF decoder, you will be able to be judged whether I am right or wrong.

      http://www.java2s.com/Code/Java/2D-Graphics-GUI/GiffileEncoder.htm
      http://mxr.mozilla.org/mozilla-central/source/image/decoders/nsGIFDecoder2.cpp

      both implementations assign NullCode(-1) to oldCode at first, and they drop the first code.


      paste part of corrected GIFImageReader#read(int, ImageReadParam)

                  final int NULL_CODE = -1;
                  int code, oldCode = NULL_CODE;

                  int[] prefix = new int[4096];
                  byte[] suffix = new byte[4096];
                  byte[] initial = new byte[4096];
                  int[] length = new int[4096];
                  byte[] string = new byte[4096];

                  initializeStringTable(prefix, suffix, initial, length);
                  int tableIndex = (1 << initCodeSize) + 2;
                  int codeSize = initCodeSize + 1;
                  int codeMask = (1 << codeSize) - 1;

                  while (!abortRequested()) {
                      code = getCode(codeSize, codeMask);

                      if (code == clearCode) {
                          initializeStringTable(prefix, suffix, initial, length);
                          tableIndex = (1 << initCodeSize) + 2;
                          codeSize = initCodeSize + 1;
                          codeMask = (1 << codeSize) - 1;

                          code = getCode(codeSize, codeMask);
                          oldCode = NULL_CODE;
                          if (code == eofCode) {
                              // Inform IIOReadProgressListeners of end of image
                              processImageComplete();
                              return theImage;
                          }
                      } else if (code == eofCode) {
                          // Inform IIOReadProgressListeners of end of image
                          processImageComplete();
                          return theImage;
                      } else {
                          int newSuffixIndex;
                          if (code < tableIndex) {
                              newSuffixIndex = code;
                          } else { // code == tableIndex
                              newSuffixIndex = oldCode;
                              if (code != tableIndex) {
                                  // warning - code out of sequence
                                  // possibly data corruption
                                  processWarningOccurred("Out-of-sequence code!");
                              }
                          }

                          if (NULL_CODE != oldCode && tableIndex < 4096) {
                              int ti = tableIndex;
                              int oc = oldCode;

                              prefix[ti] = oc;
                              suffix[ti] = initial[newSuffixIndex];
                              initial[ti] = initial[oc];
                              length[ti] = length[oc] + 1;

                              ++tableIndex;
                              if ((tableIndex == (1 << codeSize)) &&
                                  (tableIndex < 4096)) {
                                  ++codeSize;
                                  codeMask = (1 << codeSize) - 1;
                              }
                          }
                      }

                      // Reverse code
                      int c = code;
                      int len = length[c];
                      for (int i = len - 1; i >= 0; i--) {
                          string[i] = suffix[c];
                          c = prefix[c];
                      }

                      outputPixels(string, len);
                      oldCode = code;
                  }



      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      I have some gif images which reproduce this bug.
      I can mail it.


      REPRODUCIBILITY :
      This bug can be reproduced always.

      CUSTOMER SUBMITTED WORKAROUND :
      case 1 no workaround.
      case 2 use GifDecoder in
      http://www.java2s.com/Code/Java/2D-Graphics-GUI/GiffileEncoder.htm

        Attachments

          Activity

            People

            • Assignee:
              jdv Jayathirth D V
              Reporter:
              webbuggrp Webbug Group
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Imported:
                Indexed: