GIFLoader (InputStream& in)
        : input (in),
          dataBlockIsZero (false), fresh (false), finished (false),
          currentBit (0), lastBit (0), lastByteIndex (0),
          codeSize (0), setCodeSize (0), maxCode (0), maxCodeSize (0),
          firstcode (0), oldcode (0), clearCode (0), endCode (0)
    {
        int imageWidth, imageHeight;
        if (! getSizeFromHeader (imageWidth, imageHeight))
            return;

        uint8 buf [16];
        if (in.read (buf, 3) != 3)
            return;

        int numColours = 2 << (buf[0] & 7);
        int transparent = -1;

        if ((buf[0] & 0x80) != 0)
            readPalette (numColours);

        for (;;)
        {
            if (input.read (buf, 1) != 1 || buf[0] == ';')
                break;

            if (buf[0] == '!')
            {
                if (readExtension (transparent))
                    continue;

                break;
            }

            if (buf[0] != ',')
                continue;

            if (input.read (buf, 9) == 9)
            {
                imageWidth  = (int) ByteOrder::littleEndianShort (buf + 4);
                imageHeight = (int) ByteOrder::littleEndianShort (buf + 6);

                numColours = 2 << (buf[8] & 7);

                if ((buf[8] & 0x80) != 0)
                    if (! readPalette (numColours))
                        break;

                image = Image (transparent >= 0 ? Image::ARGB : Image::RGB,
                               imageWidth, imageHeight, transparent >= 0);

                image.getProperties()->set ("originalImageHadAlpha", transparent >= 0);

                readImage ((buf[8] & 0x40) != 0, transparent);
            }

            break;
        }
    }
Example #2
0
/*
 * Class:     org_apache_harmony_awt_gl_image_GifDecoder
 * Method:    decode
 * Signature: ([BIJLorg/apache/harmony/awt/gl/image/GifDecoder$GifDataStream;Lorg/apache/harmony/awt/gl/image/GifDecoder$GifGraphicBlock;)I
 */
JNIEXPORT jint JNICALL Java_org_apache_harmony_awt_gl_image_GifDecoder_decode
(JNIEnv *env,
 jobject obj,
 jbyteArray jInput,
 jint bytesInBuffer,
 jlong hDecoder,
 jobject dataStream,
 jobject currBlock) {

    GIF_RETVAL retval = STATUS_OK;
    GifDecoder *decoder = getDecoder(env, obj, dataStream, (GifDecoder*) ((IDATA)hDecoder));
    int scanlinesDecoded;

    decoder->input = decoder->inputPtr =
                         (*env)->GetPrimitiveArrayCritical(env, jInput, 0);
    decoder->bytesInBuffer += bytesInBuffer;
    bytesInBuffer = decoder->bytesInBuffer;

    while(retval == STATUS_OK && decoder->bytesInBuffer > 0) {
        switch(decoder->state) {
        case STATE_INIT: {
            retval = readHeader(env, decoder);
            break;
        }

        case STATE_AT_GLOBAL_COLOR_TABLE: {
            retval = loadColorTable(env, decoder->jGlobalColorTable, decoder);
            break;
        }

        case STATE_AT_LOCAL_COLOR_TABLE: {
            retval = loadColorTable(env, NULL, decoder);
            break;
        }

        case STATE_BLOCK_BEGINNING: {
            unsigned char blockLabel = *(decoder->inputPtr);
            switch(blockLabel) {
            case EXTENSION_INTRODUCER:
                retval = readExtension(env, decoder, currBlock);
                break;
            case IMAGE_SEPARATOR:
                retval = readImageDescriptor(env, currBlock, decoder);
                break;
            case GIF_TRAILER:
                retval = STATUS_EOF;
                break;
            }
            break;
        }

        case STATE_STARTING_DECOMPRESSION: {
            retval = initDecompression(env, decoder, currBlock);
            break;
        }

        case STATE_DECOMPRESSING: {
            if(!decoder->interlace)
                retval = decompress(env, currBlock, decoder);
            else
                retval = decompressInterlaced(env, currBlock, decoder);
            break;
        }

        case STATE_READING_COMMENT: {
            retval = readComment(env, decoder);
            break;
        }

        case STATE_SKIPPING_BLOCKS: {
            retval = skipData(decoder);
            break;
        }

        default:
            // Should never execute this!
            break;
        }
    }

    // Copy unconsumed data to the start of the input buffer
    if(decoder->bytesInBuffer > 0) {
        memmove(decoder->input, decoder->inputPtr, decoder->bytesInBuffer);
    }

    (*env)->ReleasePrimitiveArrayCritical(env, jInput, decoder->input, 0);

    (*env)->SetIntField(
        env,
        obj,
        img_GIF_bytesConsumedID,
        bytesInBuffer - decoder->bytesInBuffer
    );

    if(decoder->stateVars.imageDataStarted) {
        if(!decoder->interlace) {
            scanlinesDecoded = decoder->pixelsDecoded / decoder->currentWidth -
                               decoder->oldPixelsDecoded / decoder->currentWidth;
            decoder->oldPixelsDecoded = decoder->pixelsDecoded;
        } else {
            if(retval == STATUS_LINE_COMPLETED && decoder->pass < MAX_PASS) {
                scanlinesDecoded = 1;
                if(decoder->currScanline >= 0)
                    (*env)->SetIntField(env, currBlock, img_GIF_gb_currYID, decoder->currScanline);

                decoder->scanlineOffset = 0;
            } else {
                scanlinesDecoded = 0;
            }
        }
    } else {
        scanlinesDecoded = 0;
    }

    if(retval == STATUS_FRAME_COMPLETED) {
        decoder->oldPixelsDecoded = decoder->pixelsDecoded = 0;
    }

    // Free the decoder if decoding is finished
    if(retval == STATUS_EOF) {
        free(decoder);
        decoder = NULL;
    }

    (*env)->SetLongField(env, obj, img_GIF_hNativeDecoderID, (jlong) ((IDATA)decoder));

    return scanlinesDecoded;
}