音视频入门-20-BMP、PNG、JPG、GIF静态图生成GIF动态图

* 音视频入门文章目录 *

静态图 -> 动态图

前面 【18-手动生成一张GIF图片】 和 【19-使用giflib处理GIF图片】 生成的 GIF 每一帧都是一个颜色,平时用到的 GIF 每一帧都是图片,下面就做一张每一帧都是图片的 GIF。

准备了 4 张静态图 .bmp 、 .png 、 .jpg 、 .gif(静态的GIF):

BMP PNG JPG GIF

Android.bmp

 

Huawei.png

 

Fuchsia.jpg

 

iOS.gif

 
Android.bmp   Huawei.png   Fuchsia.jpg   iOS.gif  

每张图片显示 1 秒,生成 GIF:

image-to-gif-loop.gif

image to RGB

GIF 中使用 RGB 颜色索引来表示图像,每一帧图像最多 256 个颜色。所以第一步,要将静态图片转成 RGB。

BMP to RGB

根据 【05-RGB-TO-BMP使用开源库】 ,使用 libbmp 库来完成 .bmp to RGB。

int decodeBMP(char *filename, unsigned char **bmpRGB) { bmp_img img; bmp_img_read(&img, filename); int width = img.img_header.biWidth; int height = img.img_header.biHeight; printf("Size: [%d, %d]\n", width, height); printf("BitCount: %d\n", img.img_header.biBitCount); printf("Compression: %d\n", img.img_header.biCompression); printf("SizeImage: %d\n", img.img_header.biSizeImage); *bmpRGB = malloc(width * height * 3); int x, y; unsigned char *BufferP; for (x = 0 ; x < height ; x++) { bmp_pixel *row = img.img_pixels[x]; for (y = 0, BufferP = *bmpRGB+width*3*x; y < width; y++) { /* Get pixel's RGB values */ bmp_pixel pixel = row[y]; *BufferP++ = pixel.red; *BufferP++ = pixel.green; *BufferP++ = pixel.blue; } } return 0; } PNG to RGB

根据 【13-使用开源库生成PNG图片】 ,使用 libpng 库来完成 .png to RGB。

int decodePNG(char *filename, unsigned char **pngRGB) { FILE *fp = fopen(filename, "rb"); png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png) { fclose(fp); return -1; } png_infop info = png_create_info_struct(png); if(!info) { fclose(fp); return -1; } if(setjmp(png_jmpbuf(png))) { fclose(fp); return -1; } png_init_io(png, fp); png_read_info(png, info); int width, height; png_byte color_type; png_byte bit_depth; png_bytep *row_pointers = NULL; width = png_get_image_width(png, info); height = png_get_image_height(png, info); color_type = png_get_color_type(png, info); bit_depth = png_get_bit_depth(png, info); printf("PNG 图片尺寸:【%d, %d】\n", width, height); printf("颜色类型:%d, 位深:%d\n", color_type, bit_depth); // Read any color_type into 8bit depth, RGBA format. // See if(bit_depth == 16) png_set_strip_16(png); if(color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); // PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth. if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png); if(png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); // These color_type don't have an alpha channel then fill it with 0xff. if(color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE) png_set_filler(png, 0xFF, PNG_FILLER_AFTER); if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); png_read_update_info(png, info); int rowByteCount = png_get_rowbytes(png,info); printf("rowByteCount: %d\n", rowByteCount); row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height); for(int y = 0; y < height; y++) { row_pointers[y] = (png_byte*)malloc(rowByteCount); } png_read_image(png, row_pointers); *pngRGB = malloc(width*height*3); int counter = 0; for(int i = 0; i < height; i++) { if(color_type == 6) { // 带有透明 RGBA for(int j = 0; j < rowByteCount; j+=4) { memcpy(*pngRGB+counter, row_pointers[i]+j, 3); counter+=3; } } else { memcpy(*pngRGB+rowByteCount, row_pointers[i], rowByteCount); } } fclose(fp); png_destroy_read_struct(&png, &info, NULL); return 0; } JPG to RGB

根据 【16-使用libjpeg-trubo处理JPEG图片】 ,使用 libjpeg-turbo 库来完成 .jpg to RGB。

int decodeJPG(char *filename, unsigned char **jpgRGB) { FILE *fp = fopen(filename, "rb"); struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, fp); jpeg_read_header(&cinfo, TRUE); printf("image_width = %d\n", cinfo.image_width); printf("image_height = %d\n", cinfo.image_height); printf("num_components = %d\n", cinfo.num_components); printf("enter scale M/N:\n"); // cinfo.out_color_space = JCS_YCbCr; printf("scale to : %d/%d\n", cinfo.scale_num, cinfo.scale_denom); jpeg_start_decompress(&cinfo); //输出的图象的信息 printf("output_width = %d\n", cinfo.output_width); printf("output_height = %d\n", cinfo.output_height); printf("output_components = %d\n", cinfo.output_components); int row_stride = cinfo.output_width * cinfo.output_components; /* Make a one-row-high sample array that will go away when done with image */ JSAMPARRAY buffer = (JSAMPARRAY)malloc(sizeof(JSAMPROW)); buffer[0] = (JSAMPROW)malloc(sizeof(JSAMPLE) * row_stride); *jpgRGB = malloc(row_stride*cinfo.image_height); long counter = 0; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, buffer, 1); memcpy(*jpgRGB + counter, buffer[0], row_stride); counter += row_stride; } printf("total size: %ld\n", counter); jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(fp); return 0; } GIF to RGB

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssfsj.html