[Experimento 2] El lenguaje C realiza una secuencia de imágenes bmp para generar un video yuv

1. Requisitos experimentales

1. Analice archivos en formato BMP para obtener información de la imagen
2. Convierta imágenes BMP en imágenes en formato YUV
3. Convierta múltiples imágenes BMP en videos YUV.

2. Contenido experimental

1. Obtener fotografías

Obtenga imágenes bmp (540 * 720):
Inserte la descripción de la imagen aquí

2.conceptos básicos del formato bmp

El experimento utiliza archivos bmp de color verdadero de 24 bits. El documento se divide en tres partes:

  • FileHeader
  • InfoHeader
  • Información RGB de la imagen

El uso #include<windows.h>puede leer fácilmente la información del encabezado del archivo en la estructura

3. Realización de la programación

El programa se modifica del código de rgb a yuv en [Experimento 1] .

Función principal

La función principal implementa el siguiente proceso:

  • Lea el archivo bmp en los parámetros para obtener la información de ancho, alto y color
  • rgb a yuv
  • Empiece a escribir la transición a partir de la segunda imagen.
  • Escribe una imagen estática
  • Guarde la imagen actual en temp y guárdela para la próxima transición

el código se muestra a continuación

int main(int argc, char** argv)
{
    
    
	u_int8_t* y_temp;
	u_int8_t* u_temp;
	u_int8_t* v_temp;
	int transFrames = 30;//转场帧数
	int photoFrames = 30;//静止图片帧数
	for (int pic = 2; pic < argc; pic++) //从第二个参数到最后一个是图片
	{
    
    

		//1.读bmp文件头,获取宽高
		BITMAPFILEHEADER File_header;
		BITMAPINFOHEADER Info_header;
		FILE* bmpFile;
		bmpFile = fopen(argv[pic], "rb");
		fread(&File_header, sizeof(BITMAPFILEHEADER), 1, bmpFile);
		fread(&Info_header, sizeof(BITMAPINFOHEADER), 1, bmpFile);
		u_int frameWidth;			
		u_int frameHeight;		   
		frameWidth = Info_header.biWidth;
		frameHeight = Info_header.biHeight;

		//2.色彩信息读入rgb_buffer
		u_int8_t* rgbBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3);
		fread(rgbBuf, 1, frameWidth * frameHeight * 3, bmpFile);
		fclose(bmpFile);
		
		//3.追加模式打开yuv文件
		FILE* yuvFile = fopen(argv[1], "ab+");

		//4.rgb转yuv
		u_int8_t*  yBuf = (u_int8_t*)malloc(frameWidth * frameHeight);
		u_int8_t*  uBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);
		u_int8_t*  vBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);

		if (RGB2YUV(frameWidth, frameHeight, rgbBuf, yBuf, uBuf, vBuf, FALSE))
		{
    
    
			printf("error");
			return 0;
		}

		for (int i = 0; i < frameWidth * frameHeight; i++)
		{
    
    
			if (yBuf[i] < 16) yBuf[i] = 16;
			if (yBuf[i] > 235) yBuf[i] = 235;
		}

		for (int i = 0; i < frameWidth * frameHeight / 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;
		}
		
		//5.从第二张图片开始加入转场
		if (pic > 2) {
    
    
			for (int frame = 0; frame < transFrames; frame++) {
    
    
				u_int8_t* y_mix = getInsertFrames(y_temp, yBuf, transFrames, frame, frameWidth, frameHeight);
				u_int8_t* u_mix = getInsertFrames(u_temp, uBuf, transFrames, frame, frameWidth / 2, frameHeight / 2);
				u_int8_t* v_mix = getInsertFrames(v_temp, vBuf, transFrames, frame, frameWidth / 2, frameHeight / 2);
				fwrite(y_mix, 1, frameWidth * frameHeight, yuvFile);
				fwrite(u_mix, 1, (frameWidth * frameHeight) / 4, yuvFile);
				fwrite(v_mix, 1, (frameWidth * frameHeight) / 4, yuvFile);
			}
		}
		
		//6.写静态图片
		for (int frame = 0; frame < photoFrames; frame++) {
    
    
			fwrite(yBuf, 1, frameWidth * frameHeight, yuvFile);
			fwrite(uBuf, 1, (frameWidth * frameHeight) / 4, yuvFile);
			fwrite(vBuf, 1, (frameWidth * frameHeight) / 4, yuvFile);
		}
			
		printf("\n%u %ux%u video frames written\n",
			pic, frameWidth, frameHeight);
		fclose(yuvFile);

		
		//7.将当前图片存入temp中,留给下一张转场用
		y_temp = (u_int8_t*)malloc(frameWidth * frameHeight);
		u_temp = (u_int8_t*)malloc(frameWidth * frameHeight*0.5);
		v_temp = (u_int8_t*)malloc(frameWidth * frameHeight*0.5);
		for (int i = 0; i < frameWidth * frameHeight; i++)
		{
    
    
			*(y_temp + i) = *(yBuf + i);
		}
		for (int i = 0; i < frameWidth * frameHeight/4; i++)
		{
    
    
			*(u_temp + i) = *(uBuf + i);
			*(v_temp + i) = *(vBuf + i);
		}

	}
	return(0);
}

Entre ellos, la RGB2YUV()función es el código dado por el profesor en el [Experimento 1], por lo que no se publica.

Parámetros de depuración

Ingrese el nombre del archivo yuv y el nombre del archivo bmp que se generarán como parámetros:
Inserte la descripción de la imagen aquí

Función de transición getInsertFrames ()

getInsertFrames()La función se utiliza para obtener un fotograma mixto de dos imágenes, y se escriben dos métodos de transición: superposición y barrido.

Cubrir:

u_int8_t* getInsertFrames_mix(u_int8_t* buf1, u_int8_t* buf2, int frame,int currentFrame, u_int frameWidth,u_int frameHeight) {
    
    
	//获取两帧混合(插值)
	//frame:总转场帧数
	//currentFrame:当前帧
	u_int8_t * mix = (u_int8_t*)malloc(frameWidth * frameHeight);
	for (int j = 0; j < frameHeight * frameWidth; j++) {
    
    
		*(mix + j) = int((*(buf2 + j)* currentFrame + *(buf1 + j)*(frame- currentFrame)) / frame);
	}
	return mix;
}

Pasar un trapo

u_int8_t* getInsertFrames_sweap(u_int8_t* buf1, u_int8_t* buf2, int frame, int currentFrame, u_int frameWidth, u_int frameHeight) {
    
    
	//获取两帧混合(扫下来)
	//frame:总转场帧数
	//currentFrame:当前帧
	u_int8_t * mix = (u_int8_t*)malloc(frameWidth * frameHeight);
	for (int h = 0; h < frameHeight; h++) {
    
    
			for (int w = 0; w < frameWidth; w++) {
    
    
				if (currentFrame * frameHeight / frame > h) {
    
    
					*(mix + h * frameWidth + w) = *(buf2 + h * frameWidth + w);
				}
				else {
    
    
					*(mix + h * frameWidth + w) = *(buf1 + h * frameWidth + w);
				}
			}
		}
	return mix;
}

3. Resultados experimentales

Los resultados experimentales utilizan LICEcapsoftware para grabar imágenes GIF, csdn solo puede admitir imágenes de no más de 5 M, por lo que solo se graba un cambio de imagen.

(1) Superposición

(2) Limpiar

4. Resumen del experimento:

  • La estructura del lenguaje C es muy conveniente para leer rápidamente varias partes de la información del archivo.
  • Para el video yuv, no hay compresión y ocupa espacio y la redundancia es muy alta.

Supongo que te gusta

Origin blog.csdn.net/hdkks/article/details/115217174
Recomendado
Clasificación