library/src/main/java/com/felipecsl/gifimageview/library/GifDecoder.java
private Bitmap setPixels(GifFrame currentFrame, GifFrame previousFrame) {
    // Final location of blended pixels.
    final int[] dest = mainScratch;

    // clear all pixels when meet first frame
    if (previousFrame == null) {
      Arrays.fill(dest, 0);
    }

    // fill in starting image contents based on last image's dispose code
    if (previousFrame != null && previousFrame.dispose > DISPOSAL_UNSPECIFIED) {
      // We don't need to do anything for DISPOSAL_NONE, if it has the correct pixels so will our
      // mainScratch and therefore so will our dest array.
      if (previousFrame.dispose == DISPOSAL_BACKGROUND) {
        // Start with a canvas filled with the background color
        int c = 0;
        if (!currentFrame.transparency) {
          c = header.bgColor;
          if (currentFrame.lct != null && header.bgIndex == currentFrame.transIndex) {
            c = 0;
          }
        } else if (framePointer == 0) {
          // TODO: We should check and see if all individual pixels are replaced. If they are, the
          // first frame isn't actually transparent. For now, it's simpler and safer to assume
          // drawing a transparent background means the GIF contains transparency.
          isFirstFrameTransparent = true;
        }
        fillRect(dest, previousFrame, c);
      } else if (previousFrame.dispose == DISPOSAL_PREVIOUS) {
        if (previousImage == null) {
          fillRect(dest, previousFrame, 0);
        } else {
          // Start with the previous frame
          int downsampledIH = previousFrame.ih / sampleSize;
          int downsampledIY = previousFrame.iy / sampleSize;
          int downsampledIW = previousFrame.iw / sampleSize;
          int downsampledIX = previousFrame.ix / sampleSize;
          int topLeft = downsampledIY * downsampledWidth + downsampledIX;
          previousImage.getPixels(dest, topLeft, downsampledWidth,
              downsampledIX, downsampledIY, downsampledIW, downsampledIH);
        }
      }
    }

    // Decode pixels for this frame into the global pixels[] scratch.
    decodeBitmapData(currentFrame);

    int downsampledIH = currentFrame.ih / sampleSize;
    int downsampledIY = currentFrame.iy / sampleSize;
    int downsampledIW = currentFrame.iw / sampleSize;
    int downsampledIX = currentFrame.ix / sampleSize;
    // Copy each source line to the appropriate place in the destination.
    int pass = 1;
    int inc = 8;
    int iline = 0;
    boolean isFirstFrame = framePointer == 0;
    for (int i = 0; i < downsampledIH; i++) {
      int line = i;
      if (currentFrame.interlace) {
        if (iline >= downsampledIH) {
          pass++;
          switch (pass) {
            case 2:
              iline = 4;
              break;
            case 3:
              iline = 2;
              inc = 4;
              break;
            case 4:
              iline = 1;
              inc = 2;
              break;
            default:
              break;
          }
        }
        line = iline;
        iline += inc;
      }
      line += downsampledIY;
      if (line < downsampledHeight) {
        int k = line * downsampledWidth;
        // Start of line in dest.
        int dx = k + downsampledIX;
        // End of dest line.
        int dlim = dx + downsampledIW;
        if (k + downsampledWidth < dlim) {
          // Past dest edge.
          dlim = k + downsampledWidth;
        }
        // Start of line in source.
        int sx = i * sampleSize * currentFrame.iw;
        int maxPositionInSource = sx + ((dlim - dx) * sampleSize);
        while (dx < dlim) {
          // Map color and insert in destination.
          int averageColor;
          if (sampleSize == 1) {
            int currentColorIndex = ((int) mainPixels[sx]) & 0x000000ff;
            averageColor = act[currentColorIndex];
          } else {
            // TODO: This is substantially slower (up to 50ms per frame) than just grabbing the
            // current color index above, even with a sample size of 1.
            averageColor = averageColorsNear(sx, maxPositionInSource, currentFrame.iw);
          }
          if (averageColor != 0) {
            dest[dx] = averageColor;
          } else if (!isFirstFrameTransparent && isFirstFrame) {
            isFirstFrameTransparent = true;
          }
          sx += sampleSize;
          dx++;
        }
      }
    }

    // Copy pixels into previous image
    if (savePrevious && (currentFrame.dispose == DISPOSAL_UNSPECIFIED
        || currentFrame.dispose == DISPOSAL_NONE)) {
      if (previousImage == null) {
        previousImage = getNextBitmap();
      }
      previousImage.setPixels(dest, 0, downsampledWidth, 0, 0, downsampledWidth,
          downsampledHeight);
    }

    // Set pixels for current image.
    Bitmap result = getNextBitmap();
    result.setPixels(dest, 0, downsampledWidth, 0, 0, downsampledWidth, downsampledHeight);
    return result;
  }
private Bitmap setPixels(GifFrame currentFrame, GifFrame previousFrame) {
    // Final location of blended pixels.
    final int[] dest = mainScratch;

    // clear all pixels when meet first frame
    if (previousFrame == null) {
      Arrays.fill(dest, 0);
    }

    // fill in starting image contents based on last image's dispose code
    if (previousFrame != null && previousFrame.dispose > DISPOSAL_UNSPECIFIED) {
      // We don't need to do anything for DISPOSAL_NONE, if it has the correct pixels so will our
      // mainScratch and therefore so will our dest array.
      if (previousFrame.dispose == DISPOSAL_BACKGROUND) {
        // Start with a canvas filled with the background color
        int c = 0;
        if (!currentFrame.transparency) {
          c = header.bgColor;
          if (currentFrame.lct != null && header.bgIndex == currentFrame.transIndex) {
            c = 0;
          }
        } else if (framePointer == 0) {
          // TODO: We should check and see if all individual pixels are replaced. If they are, the
          // first frame isn't actually transparent. For now, it's simpler and safer to assume
          // drawing a transparent background means the GIF contains transparency.
          isFirstFrameTransparent = true;
        }
        fillRect(dest, previousFrame, c);
      } else if (previousFrame.dispose == DISPOSAL_PREVIOUS) {
        if (previousImage == null) {
          fillRect(dest, previousFrame, 0);
        } else {
          // Start with the previous frame
          int downsampledIH = previousFrame.ih / sampleSize;
          int downsampledIY = previousFrame.iy / sampleSize;
          int downsampledIW = previousFrame.iw / sampleSize;
          int downsampledIX = previousFrame.ix / sampleSize;
          int topLeft = downsampledIY * downsampledWidth + downsampledIX;
          previousImage.getPixels(dest, topLeft, downsampledWidth,
              downsampledIX, downsampledIY, downsampledIW, downsampledIH);
        }
      }
    }

    // Decode pixels for this frame into the global pixels[] scratch.
    decodeBitmapData(currentFrame);

    int downsampledIH = currentFrame.ih / sampleSize;
    int downsampledIY = currentFrame.iy / sampleSize;
    int downsampledIW = currentFrame.iw / sampleSize;
    int downsampledIX = currentFrame.ix / sampleSize;
    // Copy each source line to the appropriate place in the destination.
    int pass = 1;
    int inc = 8;
    int iline = 0;
    boolean isFirstFrame = framePointer == 0;
    for (int i = 0; i < downsampledIH; i++) {
      int line = i;
      if (currentFrame.interlace) {
        if (iline >= downsampledIH) {
          pass++;
          switch (pass) {
            case 2:
              iline = 4;
              break;
            case 3:
              iline = 2;
              inc = 4;
              break;
            case 4:
              iline = 1;
              inc = 2;
              break;
            default:
              break;
          }
        }
        line = iline;
        iline += inc;
      }
      line += downsampledIY;
      if (line < downsampledHeight) {
        int k = line * downsampledWidth;
        // Start of line in dest.
        int dx = k + downsampledIX;
        // End of dest line.
        int dlim = dx + downsampledIW;
        if (k + downsampledWidth < dlim) {
          // Past dest edge.
          dlim = k + downsampledWidth;
        }
        // Start of line in source.
        int sx = i * sampleSize * currentFrame.iw;
        int maxPositionInSource = sx + ((dlim - dx) * sampleSize);
        while (dx < dlim) {
          // Map color and insert in destination.
          int averageColor;
          if (sampleSize == 1) {
            int currentColorIndex = ((int) mainPixels[sx]) & 0x000000ff;
            averageColor = act[currentColorIndex];
          } else {
            // TODO: This is substantially slower (up to 50ms per frame) than just grabbing the
            // current color index above, even with a sample size of 1.
            averageColor = averageColorsNear(sx, maxPositionInSource, currentFrame.iw);
          }
          if (averageColor != 0) {
            dest[dx] = averageColor;
          } else if (!isFirstFrameTransparent && isFirstFrame) {
            isFirstFrameTransparent = true;
          }
          sx += sampleSize;
          dx++;
        }
      }
    }

    // Copy pixels into previous image
    if (savePrevious && (currentFrame.dispose == DISPOSAL_UNSPECIFIED
        || currentFrame.dispose == DISPOSAL_NONE)) {
      if (previousImage == null) {
        previousImage = getNextBitmap();
      }
      previousImage.setPixels(dest, 0, downsampledWidth, 0, 0, downsampledWidth,
          downsampledHeight);
    }

    // Set pixels for current image.
    Bitmap result = getNextBitmap();
    result.setPixels(dest, 0, downsampledWidth, 0, 0, downsampledWidth, downsampledHeight);
    return result;
  }
private Bitmap setPixels ( GifFrame currentFrame , GifFrame previousFrame ) { // Final location of blended pixels. final int [ ] dest = mainScratch ; // clear all pixels when meet first frame if ( previousFrame == null ) { Arrays . fill ( dest , 0 ) ; } // fill in starting image contents based on last image's dispose code if ( previousFrame != null && previousFrame . dispose > DISPOSAL_UNSPECIFIED ) { // We don't need to do anything for DISPOSAL_NONE, if it has the correct pixels so will our // mainScratch and therefore so will our dest array. if ( previousFrame . dispose == DISPOSAL_BACKGROUND ) { // Start with a canvas filled with the background color int c = 0 ; if ( ! currentFrame . transparency ) { c = header . bgColor ; if ( currentFrame . lct != null && header . bgIndex == currentFrame . transIndex ) { c = 0 ; } } else if ( framePointer == 0 ) { // TODO: We should check and see if all individual pixels are replaced. If they are, the // first frame isn't actually transparent. For now, it's simpler and safer to assume // drawing a transparent background means the GIF contains transparency. isFirstFrameTransparent = true ; } fillRect ( dest , previousFrame , c ) ; } else if ( previousFrame . dispose == DISPOSAL_PREVIOUS ) { if ( previousImage == null ) { fillRect ( dest , previousFrame , 0 ) ; } else { // Start with the previous frame int downsampledIH = previousFrame . ih / sampleSize ; int downsampledIY = previousFrame . iy / sampleSize ; int downsampledIW = previousFrame . iw / sampleSize ; int downsampledIX = previousFrame . ix / sampleSize ; int topLeft = downsampledIY * downsampledWidth + downsampledIX ; previousImage . getPixels ( dest , topLeft , downsampledWidth , downsampledIX , downsampledIY , downsampledIW , downsampledIH ) ; } } } // Decode pixels for this frame into the global pixels[] scratch. decodeBitmapData ( currentFrame ) ; int downsampledIH = currentFrame . ih / sampleSize ; int downsampledIY = currentFrame . iy / sampleSize ; int downsampledIW = currentFrame . iw / sampleSize ; int downsampledIX = currentFrame . ix / sampleSize ; // Copy each source line to the appropriate place in the destination. int pass = 1 ; int inc = 8 ; int iline = 0 ; boolean isFirstFrame = framePointer == 0 ; for ( int i = 0 ; i < downsampledIH ; i ++ ) { int line = i ; if ( currentFrame . interlace ) { if ( iline >= downsampledIH ) { pass ++ ; switch ( pass ) { case 2 : iline = 4 ; break ; case 3 : iline = 2 ; inc = 4 ; break ; case 4 : iline = 1 ; inc = 2 ; break ; default : break ; } } line = iline ; iline += inc ; } line += downsampledIY ; if ( line < downsampledHeight ) { int k = line * downsampledWidth ; // Start of line in dest. int dx = k + downsampledIX ; // End of dest line. int dlim = dx + downsampledIW ; if ( k + downsampledWidth < dlim ) { // Past dest edge. dlim = k + downsampledWidth ; } // Start of line in source. int sx = i * sampleSize * currentFrame . iw ; int maxPositionInSource = sx + ( ( dlim - dx ) * sampleSize ) ; while ( dx < dlim ) { // Map color and insert in destination. int averageColor ; if ( sampleSize == 1 ) { int currentColorIndex = ( ( int ) mainPixels [ sx ] ) & 0x000000ff ; averageColor = act [ currentColorIndex ] ; } else { // TODO: This is substantially slower (up to 50ms per frame) than just grabbing the // current color index above, even with a sample size of 1. averageColor = averageColorsNear ( sx , maxPositionInSource , currentFrame . iw ) ; } if ( averageColor != 0 ) { dest [ dx ] = averageColor ; } else if ( ! isFirstFrameTransparent && isFirstFrame ) { isFirstFrameTransparent = true ; } sx += sampleSize ; dx ++ ; } } } // Copy pixels into previous image if ( savePrevious && ( currentFrame . dispose == DISPOSAL_UNSPECIFIED || currentFrame . dispose == DISPOSAL_NONE ) ) { if ( previousImage == null ) { previousImage = getNextBitmap ( ) ; } previousImage . setPixels ( dest , 0 , downsampledWidth , 0 , 0 , downsampledWidth , downsampledHeight ) ; } // Set pixels for current image. Bitmap result = getNextBitmap ( ) ; result . setPixels ( dest , 0 , downsampledWidth , 0 , 0 , downsampledWidth , downsampledHeight ) ; return result ; }
Creates new frame image from current data (and previous frames as specified by their
disposition codes).
Creates new frame image from current data ( and previous frames as specified by their disposition codes ) .