`
hzy3774
  • 浏览: 985378 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类
最新评论

Android使用libnsgif类库解gif图片

阅读更多

下载地址:http://www.netsurf-browser.org/projects/libnsgif/

安卓Android项目地址:https://github.com/huzongyao/AndLibNsgif

这是netsurf浏览器的一个组件,可以单独使用,解析gif占用内存比较少,也比较简单。



 

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 \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);

	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\n",
				(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, "\n");
}

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]\n", 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;
}

 
 运行效果:



 

安卓平台通过jni调用:


 

安卓项目地址:https://github.com/huzongyao/AndLibNsgif
 其他参考附件。

 

  • 大小: 473.7 KB
  • 大小: 74.2 KB
  • 大小: 394.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics