BMP文件序列转YUV文件再转成GIF文件上传

BMP文件序列转YUV文件

bmp文件

由四个部分组成:
1.位图文件头
在这里插入图片描述
2. 位图信息头
在这里插入图片描述3. 调色板
在这里插入图片描述4.实际的位图数据
也就是我们需要处理的bgr数据

实验思路

之前一直在用c++写这次实验,但是wingdi.h的库导入老是报错,索性还是用c语言写了,在前面加个windows.h就可以用wingdi.h库了。
由于我们使用的是24位真彩色图像,所以无调色板。在将bgr数据转为yuv数据之前,我们需要先读取文件头和信息头,并且可以从信息头中获取图片的宽高等数据,再用第一周实验的rgb转yuv程序实现批量地转换。
每两幅图之间写了个渐变转场。

代码
#include<stdio.h>
#include<stdbool.h>
#include<windows.h>
#include<wingdi.h>
#define u_int8_t unsigned __int8
void main(){
	int i, j, k;
	char path[] = ".bmp";
	char in_path[20];
	const char out_path[20] = "yuv_video.yuv";
	FILE* fc;
	FILE* fp;
	u_int8_t* rgbBuf = NULL;
	u_int8_t* yBuf = NULL;
	u_int8_t* uBuf = NULL;
	u_int8_t* vBuf = NULL;
	BITMAPFILEHEADER fileheader;
	BITMAPINFOHEADER infoheader;
	RGBQUAD rgbq;// 由于用的是24位真彩色图片,所以没有调色板
	int w = 512;
	int h = 512;
	int frame = 42;// 42帧
	rgbBuf = (u_int8_t*)malloc(w * h * 3);
	yBuf = (u_int8_t*)malloc(w * h);
	uBuf = (u_int8_t*)malloc((w * h) / 4);
	vBuf = (u_int8_t*)malloc((w * h) / 4);
	bool flip = true;
	fopen_s(&fc, out_path, "wb"); // 写入二进制
	// 先读取第一帧,初始化brgbBuf,用于后续转场
	fopen_s(&fp, "0.bmp", "rb"); // 读取二进制
	printf("0.bmp");
	fread(&fileheader, sizeof(BITMAPFILEHEADER), 1, fp);// 读取文件头
	fread(&infoheader, sizeof(BITMAPINFOHEADER), 1, fp);// 信息头
	// printf(infoheader.biWeight)
	// printf(infoheader.biHeight)
	fread(rgbBuf, w * h * 3, 1, fp);
	RGB2YUV(w, h, rgbBuf, yBuf, uBuf, vBuf, flip);
	for (i = 0; i < w * h; i++)
	{
		if (yBuf[i] < 16) yBuf[i] = 16;
		if (yBuf[i] > 235) yBuf[i] = 235;
	}

	for (i = 0; i < w * h / 4; i++)
	{
		if (uBuf[i] < 16) uBuf[i] = 16;
		if (uBuf[i] > 240) uBuf[i] = 240;

		if (vBuf[i] < 16) vBuf[i] = 16;
		if (vBuf[i] > 240) vBuf[i] = 240;
	}
	fwrite(yBuf, 1, w * h, fc);
	fwrite(uBuf, 1, (w * h) / 4, fc);
	fwrite(vBuf, 1, (w * h) / 4, fc);

	u_int8_t* brgbBuf;// 用于存储前一帧的值
	brgbBuf = (u_int8_t*)malloc(w * h * 3);
	u_int8_t* trgbBuf;// 用于转场输出的每一帧
	trgbBuf = (u_int8_t*)malloc(w * h * 3);
	for (i = 0; i < w * h * 3; i++)
	{
		brgbBuf[i] = rgbBuf[i];
	}
	fclose(fp);

	// 一共有6幅图像
	for (j = 1; j < 6; j++)
	{
		sprintf(in_path,"%d.bmp",j); // 依次打开1.bmp文件,2.bmp文件,3.bmp文件
		printf(in_path);
		fopen_s(&fp, in_path, "rb"); // 读取二进制
		fread(&fileheader, sizeof(BITMAPFILEHEADER), 1, fp);
		fread(&infoheader, sizeof(BITMAPINFOHEADER), 1, fp);
		fread(rgbBuf, w * h * 3, 1, fp);

		// 每两幅图片之间写一个转场
		for (k = 0; k < frame; k++)
		{
			for (i = 0; i < w * h * 3; i++)
			{
				trgbBuf[i] = brgbBuf[i]+k*(rgbBuf[i]-brgbBuf[i])/frame;// 渐变转场
			}
			RGB2YUV(w, h, trgbBuf, yBuf, uBuf, vBuf, flip);
			for (i = 0; i < w * h; i++)
			{
				if (yBuf[i] < 16) yBuf[i] = 16;
				if (yBuf[i] > 235) yBuf[i] = 235;
			}

			for (i = 0; i < w * h / 4; i++)
			{
				if (uBuf[i] < 16) uBuf[i] = 16;
				if (uBuf[i] > 240) uBuf[i] = 240;

				if (vBuf[i] < 16) vBuf[i] = 16;
				if (vBuf[i] > 240) vBuf[i] = 240;
			}
			fwrite(yBuf, 1, w * h, fc);
			fwrite(uBuf, 1, (w * h) / 4, fc);
			fwrite(vBuf, 1, (w * h) / 4, fc);
		}
		// 将当前图像作为上一幅图像
		for (i = 0; i < w * h * 3; i++)
		{
			brgbBuf[i] = rgbBuf[i];
		}
	
		fclose(fp);
	}
	free(rgbBuf);
	free(yBuf);
	free(uBuf);
	free(vBuf);
	free(trgbBuf);
	free(brgbBuf);
	fclose(fc);
}

RGB2YUV程序使用的是老师给的范例程序,参数分别是图像宽高,rgb的数据,y、u、v的数据,是否执行。

实验结果

bmp文件:用PS加了文字,改了大小为512x512,文件名统一为0.bmp,1.bmp,2.bmp等等
在这里插入图片描述yuv文件在博客上播放不了
所以我们用一句话把它转成gif图片播放
ffmpeg -s 512x512 -i yuv_video.yuv output.gif

得到如图gif
在这里插入图片描述用PS压缩了大小和颜色板总算上传成功了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值