Androidはlibnsgifクラスライブラリを使用してgif画像を解く


ダウンロードアドレス:http://www.netsurf-browser.org/projects/libnsgif/
Android Androidプロジェクト住所:https://github.com/hzy3774/AndroidNSGif
これはnetsurfブラウザのコンポーネントで、単独で使用でき、gifを解析するのにメモリが少なく、簡単です.
Android使用libnsgif类库解gif图片_第1张图片  
Windowsの下でopenglでレンダリングし、MinGWでコンパイルした、コード:
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <GL/freeglut.h>
#include "nsgif/libnsgif.h"

unsigned char *load_file(const char *path, size_t *data_size);
void warning(const char *context, int code);
void *bitmap_create(int width, int height);
void bitmap_set_opaque(void *bitmap, bool opaque);
bool bitmap_test_opaque(void *bitmap);
unsigned char *bitmap_get_buffer(void *bitmap);
void bitmap_destroy(void *bitmap);
void bitmap_modified(void *bitmap);

gif_animation gif;
unsigned char *data;
int index = 0;

void close(){
	/* clean up */
	gif_finalise(&gif);
	free(data);
}

int decodeGif(const char* fname)
{
	gif_bitmap_callback_vt bitmap_callbacks = {
		bitmap_create,
		bitmap_destroy,
		bitmap_get_buffer,
		bitmap_set_opaque,
		bitmap_test_opaque,
		bitmap_modified
	};
	size_t size;
	gif_result code;
	/* create our gif animation */
	gif_create(&gif, &bitmap_callbacks);

	/* load file into memory */
	data = load_file(fname, &size);
	/* begin decoding */
	do {
		code = gif_initialise(&gif, size, data);
		if (code != GIF_OK && code != GIF_WORKING) {
			warning("gif_initialise", code);
			return -1;
		}
	} while (code != GIF_OK);

	printf("# width                %u 
", gif.width); printf("# height %u
", gif.height); printf("# frame_count %u
", gif.frame_count); printf("# frame_count_partial %u
", gif.frame_count_partial); printf("# loop_count %u
", gif.loop_count); printf("%u %u 256
", gif.width, gif.height * gif.frame_count); return 0; } unsigned char* getFrame(int i){ unsigned char *image; gif_result code; code = gif_decode_frame(&gif, i); if (code != GIF_OK) warning("gif_decode_frame", code); image = (unsigned char *) gif.frame_image; return image; } unsigned char *load_file(const char *path, size_t *data_size) { FILE *fd; struct stat sb; unsigned char *buffer; size_t size; size_t n; fd = fopen(path, "rb"); if (!fd) { perror(path); exit(EXIT_FAILURE); } if (stat(path, &sb)) { perror(path); exit(EXIT_FAILURE); } size = sb.st_size; buffer = malloc(size); if (!buffer) { fprintf(stderr, "Unable to allocate %lld bytes
", (long long) size); exit(EXIT_FAILURE); } n = fread(buffer, 1, size, fd); if (n != size) { perror(path); exit(EXIT_FAILURE); } fclose(fd); *data_size = size; return buffer; } void warning(const char *context, gif_result code) { fprintf(stderr, "%s failed: ", context); switch (code) { case GIF_INSUFFICIENT_FRAME_DATA: fprintf(stderr, "GIF_INSUFFICIENT_FRAME_DATA"); break; case GIF_FRAME_DATA_ERROR: fprintf(stderr, "GIF_FRAME_DATA_ERROR"); break; case GIF_INSUFFICIENT_DATA: fprintf(stderr, "GIF_INSUFFICIENT_DATA"); break; case GIF_DATA_ERROR: fprintf(stderr, "GIF_DATA_ERROR"); break; case GIF_INSUFFICIENT_MEMORY: fprintf(stderr, "GIF_INSUFFICIENT_MEMORY"); break; default: fprintf(stderr, "unknown code %i", code); break; } fprintf(stderr, "
"); } void *bitmap_create(int width, int height) { return calloc(width * height, 4); } void bitmap_set_opaque(void *bitmap, bool opaque) { (void) opaque; /* unused */ assert(bitmap); } bool bitmap_test_opaque(void *bitmap) { assert(bitmap); return false; } unsigned char *bitmap_get_buffer(void *bitmap) { assert(bitmap); return bitmap; } void bitmap_destroy(void *bitmap) { assert(bitmap); free(bitmap); } void bitmap_modified(void *bitmap) { assert(bitmap); return; } void myDisplay(void) { // glClear(GL_COLOR_BUFFER_BIT); glDrawPixels(gif.width, gif.height, GL_RGBA, GL_UNSIGNED_BYTE, gif.frame_image); glutSwapBuffers(); } void myTimer(int i){ int delay; index++; if(index == gif.frame_count){ index = 0; } delay = gif.frames[index].frame_delay * 10; getFrame(index); glutPostRedisplay(); printf("Frame index[%d], delay[%d]
", index, delay); glutTimerFunc(delay, myTimer, 1); } int main(int argc, char *argv[]) { decodeGif("test.gif"); glutInit(&argc, argv) ; glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutInitWindowPosition(300, 200); glutInitWindowSize(gif.width, gif.height); glutCreateWindow("Gif Show"); getFrame(index); glutTimerFunc(gif.frames[index].frame_delay * 10, &myTimer, 1); glRasterPos2f(-1, 1); // glPixelZoom(1, -1); //y glutDisplayFunc(&myDisplay); glutMainLoop(); return 0; }

実行効果:
Android使用libnsgif类库解gif图片_第2张图片  
アンドロイドプラットフォームはjniによって呼び出されます.
Android使用libnsgif类库解gif图片_第3张图片
 
Androidプロジェクトの住所:https://github.com/hzy3774/AndroidNSGifその他の参考添付ファイル.