示例#1
0
static void decode_new_frame(gs_image_file_t *image, int new_frame)
{
	if (!image->animation_frame_cache[new_frame]) {
		int last_frame;

		/* if looped, decode frame 0 */
		last_frame = (new_frame < image->last_decoded_frame) ?
			0 : image->last_decoded_frame + 1;

		/* decode missed frames */
		for (int i = last_frame; i < new_frame; i++) {
			if (gif_decode_frame(&image->gif, i) != GIF_OK)
				return;
		}

		/* decode actual desired frame */
		if (gif_decode_frame(&image->gif, new_frame) == GIF_OK) {
			size_t pos = new_frame * image->gif.width *
				image->gif.height * 4;
			image->animation_frame_cache[new_frame] =
				image->animation_frame_data + pos;

			memcpy(image->animation_frame_cache[new_frame],
					image->gif.frame_image,
					image->gif.width *
					image->gif.height * 4);

			image->last_decoded_frame = new_frame;
		}
	}

	image->cur_frame = new_frame;
}
示例#2
0
/* gifReadImage: Reads an image from a memory buffer.
   Returns: non-zero if successful.
*/
int gifReadImage(int w, int h, int d, char* bits, char *data, int nBytes) {
  gif_bitmap_callback_vt bitmap_callbacks = {
    bitmap_create,
    bitmap_destroy,
    bitmap_get_buffer,
    bitmap_set_opaque,
    bitmap_test_opaque,
    bitmap_modified
  };

  gif_animation gif;
  gif_result code;

  formWidth = w;
  formHeight = h;
  formBits = bits;

  /* create our gif animation */
  gif_create(&gif, &bitmap_callbacks);

  /* begin decoding */
  do {
    code = gif_initialise(&gif, nBytes, data);
    if (code != GIF_OK && code != GIF_WORKING) {
      DBG("gif_initialise failure");
      return 0;
    }
  } while (code != GIF_OK);

  if(gif.width != w || gif.height != h || gif.frame_count != 1 || d != 32) {
    DBG("image format mismatch");
    return 0;
  }

  code = gif_decode_frame(&gif, 0);
  if (code != GIF_OK) {
    DBG("gif_decode_frame error");
    return 0;
  }

  /* clean up */
  gif_finalise(&gif);

  return 1;
}
示例#3
0
/**
 * Updates the GIF bitmap to display the current frame
 *
 * \param c  the content to update
 */
static gif_result nsgif_get_frame(nsgif_content *gif)
{
	int previous_frame, current_frame, frame;
	gif_result res = GIF_OK;

	current_frame = gif->current_frame;
	if (!nsoption_bool(animate_images)) {
		current_frame = 0;
	}

	if (current_frame < gif->gif->decoded_frame)
		previous_frame = 0;
	else
		previous_frame = gif->gif->decoded_frame + 1;

	for (frame = previous_frame; frame <= current_frame; frame++) {
		res = gif_decode_frame(gif->gif, frame);
	}

	return res;
}
示例#4
0
static bool init_animated_gif(gs_image_file_t *image, const char *path)
{
	bool is_animated_gif = true;
	gif_result result;
	uint64_t max_size;
	size_t size;
	FILE *file;

	image->bitmap_callbacks.bitmap_create = bi_def_bitmap_create;
	image->bitmap_callbacks.bitmap_destroy = bi_def_bitmap_destroy;
	image->bitmap_callbacks.bitmap_get_buffer = bi_def_bitmap_get_buffer;
	image->bitmap_callbacks.bitmap_modified = bi_def_bitmap_modified;
	image->bitmap_callbacks.bitmap_set_opaque = bi_def_bitmap_set_opaque;
	image->bitmap_callbacks.bitmap_test_opaque = bi_def_bitmap_test_opaque;

	gif_create(&image->gif, &image->bitmap_callbacks);

	file = os_fopen(path, "rb");
	if (!file) {
		blog(LOG_WARNING, "Failed to open file '%s'", path);
		goto fail;
	}

	fseek(file, 0, SEEK_END);
	size = (size_t)os_ftelli64(file);
	fseek(file, 0, SEEK_SET);

	image->gif_data = bmalloc(size);
	fread(image->gif_data, 1, size, file);

	do {
		result = gif_initialise(&image->gif, size, image->gif_data);
		if (result < 0) {
			blog(LOG_WARNING, "Failed to initialize gif '%s', "
					"possible file corruption", path);
			goto fail;
		}
	} while (result != GIF_OK);

	if (image->gif.width > 4096 || image->gif.height > 4096) {
		blog(LOG_WARNING, "Bad texture dimensions (%dx%d) in '%s'",
				image->gif.width, image->gif.height, path);
		goto fail;
	}

	max_size = (uint64_t)image->gif.width * (uint64_t)image->gif.height *
		(uint64_t)image->gif.frame_count * 4LLU;

	if ((uint64_t)get_full_decoded_gif_size(image) != max_size) {
		blog(LOG_WARNING, "Gif '%s' overflowed maximum pointer size",
				path);
		goto fail;
	}

	image->is_animated_gif = (image->gif.frame_count > 1 && result >= 0);
	if (image->is_animated_gif) {
		gif_decode_frame(&image->gif, 0);

		image->animation_frame_cache = bzalloc(
				image->gif.frame_count * sizeof(uint8_t*));
		image->animation_frame_data = bzalloc(
				get_full_decoded_gif_size(image));

		for (unsigned int i = 0; i < image->gif.frame_count; i++) {
			if (gif_decode_frame(&image->gif, i) != GIF_OK)
				blog(LOG_WARNING, "Couldn't decode frame %u "
						"of '%s'", i, path);
		}

		gif_decode_frame(&image->gif, 0);

		image->cx = (uint32_t)image->gif.width;
		image->cy = (uint32_t)image->gif.height;
		image->format = GS_RGBA;
	} else {
		gif_finalise(&image->gif);
		bfree(image->gif_data);
		image->gif_data = NULL;
		is_animated_gif = false;
		goto not_animated;
	}

	image->loaded = true;

fail:
	if (!image->loaded)
		gs_image_file_free(image);
not_animated:
	if (file)
		fclose(file);

	return is_animated_gif;
}
示例#5
0
_bitmap _imageFile::readBitmap( _optValue<_u32> page )
{
    // Check if not-existing
    if( !this->isExisting() )
        return _bitmap();

    _mimeType mimeType = this->getRealMime();

    if( mimeType == _mime::image_png )
    {
        if( this->bufferedImage )
            return *bufferedImage;

        _bitmap result;

        YsRawPngDecoder* pngDecoder = new YsRawPngDecoder;

        pngDecoder->Decode( this->filename.c_str() );

        if( pngDecoder->wid > 0 && pngDecoder->hei > 0 && pngDecoder->rgba != NULL )
        {
            // Allocate bitmap
            result = _bitmap( pngDecoder->wid , pngDecoder->hei );

            // Get size of Data (in bytes)(every pixel consists of u8 red, u8 green, u8 blue, u8 alpha)
            _u32		size = pngDecoder->wid * pngDecoder->hei;
            _pixelArray	base = result.getBitmap();
            _u8*		source = pngDecoder->rgba;

            do {
                _u8 r = *source++;
                _u8 g = *source++;
                _u8 b = *source++;
                bool a = *source++ > 127;
                *base++ = _color::fromRGB8(r,g,b,a);
            } while( --size > 0 );
        }

        // Delete the decoder
        delete pngDecoder;

        if( this->buffer ) {
            this->bufferedImage = new _bitmap( move(result) );
            return *this->bufferedImage;
        }
        return move(result);
    }
    else if( mimeType == _mime::image_jpeg )
    {
        if( this->bufferedImage )
            return *bufferedImage;

        _bitmap result;

        _u32 size = this->getSize();
        _byte* data = new _byte[size];
        this->read( data , size );

        Jpeg::Decoder* jpgDecoder = new Jpeg::Decoder( data , size );

        if ( jpgDecoder->GetResult() == Jpeg::Decoder::OK )
        {
            result = _bitmap( jpgDecoder->GetWidth() , jpgDecoder->GetHeight() );

            if( jpgDecoder->IsColor() )
            {
                _u32 size = jpgDecoder->GetImageSize();
                _u8* rgb = jpgDecoder->GetImage();
                _pixelArray dest = result.getBitmap();

                do {
                    _u8 r = *rgb++;
                    _u8 g = *rgb++;
                    _u8 b = *rgb++;
                    *dest++ = _color::fromRGB8(r,g,b);
                    size -= 3;
                } while( size > 0 );
            }
            else
            {
                _u32 size = jpgDecoder->GetImageSize();
                _u8* rgb = jpgDecoder->GetImage();
                _pixelArray dest = result.getBitmap();

                do {
                    *dest++ = _color::fromBW8( *rgb++ );
                } while( --size > 0 );
            }
        }
        delete[] data;
        delete jpgDecoder;

        if( this->buffer ) {
            this->bufferedImage = new _bitmap( move(result) );
            return *this->bufferedImage;
        }
        return move(result);
    }
    else if( mimeType == _mime::image_bmp )
    {
        if( this->bufferedImage )
            return *bufferedImage;

        _bitmap result;

        _u32 size = this->getSize();
        _byte* data = new _byte[size];
        this->read( data , size );

        _u32 width;
        _u32 height;

        _pixelArray pixeldata = GenericBMPDecoder::decode( data , size , width , height );

        if ( pixeldata != nullptr ) {
            result = _bitmap( width , height );
            memcpy16( result.getBitmap() , pixeldata , width * height );
            delete[] pixeldata;
        }

        delete[] data;

        if( this->buffer ) {
            this->bufferedImage = new _bitmap( move(result) );
            return *this->bufferedImage;
        }
        return move(result);
    }
    else if( mimeType == _mime::image_ico )
    {
        _byte* data;
        if( this->bufferedData )
            data = this->bufferedData;
        else
        {
            _u32 size = this->getSize();
            data = new _byte[size];
            this->read( data , size );
        }

        _u32 width;
        _u32 height;

        _bitmap result;

        _u8* pixeldata = GenericIcoDecoder::decode( data , width , height , page );

        if ( pixeldata != nullptr )
        {
            // Allocate bitmap
            result = _bitmap( width , height );

            // Get size of Data (in bytes)(every pixel consists of u8 red, u8 green, u8 blue, u8 alpha)
            _u32		size = width * height;
            _pixelArray	base = result.getBitmap();
            _u8*		source = pixeldata;

            do {
                _u8 r = *source++;
                _u8 g = *source++;
                _u8 b = *source++;
                bool a = *source++ > 127;
                *base++ = _color::fromRGB8(r,g,b,a);
            } while( --size > 0 );

            delete[] pixeldata;
        }

        if( !this->buffer )
            delete[] data;
        else
            this->bufferedData = data;
        return result;
    }
    else if( mimeType == _mime::image_gif )
    {
        gif_animation* gifAnim;
        gif_result statusCode = GIF_OK;

        // Allocate Decoder
        if( this->bufferedGif )
            gifAnim = this->bufferedGif;
        else
        {
            // Read file content to buffer
            _u32 size = this->getSize();
            _byte* data = new _byte[size];
            this->read( data , size );

            // Allocate Decoder
            gifAnim = new gif_animation;

            // Initialize Decoder
            gif_create( gifAnim );

            // Partly Decode the gif
            do {
                statusCode = gif_initialise( gifAnim , size , data );
                if (statusCode != GIF_OK && statusCode != GIF_WORKING) {
                    _imageFile::outputGifWarning( "gif_initialise" , statusCode);
                    break;
                }
            } while( statusCode != GIF_OK );
        }

        if( !this->bufferedGifBitmap )
            this->bufferedGifBitmap = new _bitmap( gifAnim->width , gifAnim->height , _color::transparent );

        // Limit Page Number
        if( gifAnim->frame_count <= page )
            page = gifAnim->frame_count -1;


        // Decode...
        statusCode = gif_decode_frame(gifAnim, page);

        // ... and Check if everything went ok
        if (statusCode != GIF_OK)
            _imageFile::outputGifWarning( "gif_decode_frame" , statusCode );

        // Get destination bitmap
        _pixelArray dest = this->bufferedGifBitmap->getBitmap();

        // Get Source bitmap
        _u8* source = (_u8*)gifAnim->frame_image;

        // Copy source bitmap to destination
        _length numPixels = gifAnim->height * gifAnim->width;
        do {
            *dest++ = _color::fromRGB8( source[0] , source[1] , source[2] , source[3] );
            source += 4;
        } while( --numPixels > 0 );

        // Clean temps
        if( this->buffer )
            this->bufferedGif = gifAnim;
        else
        {
            delete[] gifAnim->gif_data;
            delete gifAnim;
        }

        return *this->bufferedGifBitmap;
    }

    return _bitmap();
}
示例#6
0
int main(int argc, char *argv[])
{
    gif_bitmap_callback_vt bitmap_callbacks = {
        bitmap_create,
        bitmap_destroy,
        bitmap_get_buffer,
        bitmap_set_opaque,
        bitmap_test_opaque,
        bitmap_modified
    };
    gif_animation gif;
    size_t size;
    gif_result code;
    unsigned int i;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s image.gif\n", argv[0]);
        return 1;
    }

    /* create our gif animation */
    gif_create(&gif, &bitmap_callbacks);

    /* load file into memory */
    unsigned char *data = load_file(argv[1], &size);

    /* begin decoding */
    do {
        code = gif_initialise(&gif, size, data);
        if (code != GIF_OK && code != GIF_WORKING) {
            warning("gif_initialise", code);
            exit(1);
        }
    } while (code != GIF_OK);

    printf("P3\n");
    printf("# %s\n", argv[1]);
    printf("# width                %u \n", gif.width);
    printf("# height               %u \n", gif.height);
    printf("# frame_count          %u \n", gif.frame_count);
    printf("# frame_count_partial  %u \n", gif.frame_count_partial);
    printf("# loop_count           %u \n", gif.loop_count);
    printf("%u %u 256\n", gif.width, gif.height * gif.frame_count);

    /* decode the frames */
    for (i = 0; i != gif.frame_count; i++) {
        unsigned int row, col;
        unsigned char *image;

        code = gif_decode_frame(&gif, i);
        if (code != GIF_OK)
            warning("gif_decode_frame", code);

        printf("# frame %u:\n", i);
        image = (unsigned char *) gif.frame_image;
        for (row = 0; row != gif.height; row++) {
            for (col = 0; col != gif.width; col++) {
                size_t z = (row * gif.width + col) * 4;
                printf("%u %u %u ",
                    (unsigned char) image[z],
                    (unsigned char) image[z + 1],
                    (unsigned char) image[z + 2]);
            }
            printf("\n");
        }
    }

    /* clean up */
    gif_finalise(&gif);
    free(data);

    return 0;
}