TGA文件转YUV文件

文件头

#include "pch.h"
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

TGA结构体

typedef struct _TgaHeader
{
 BYTE IDLength;       
 BYTE ColorMapType;    
BYTE ImageType;      
 }TGAHEAD;

typedef struct _TgaHeaderCMap
{
WORD CMapStart;       
WORD CMapLength;      
BYTE CMapDepth;      
}TGAHEADCMAP;

typedef struct _TgaHeaderImage
{
WORD XOffset;        
WORD YOffset;         
WORD Width;           
WORD Height;          
BYTE PixelDepth;     
BYTE ImageDescriptor; 
}TGAHEADIMG;

打开文件

int main()
{
FILE *TgaFile = NULL, *YuvFile = NULL, *RgbFile = NULL;
if ((TgaFile = fopen("D:\\数据压缩\\16.tga", "rb")) == NULL)
{
printf("tga file open failed!");
exit(0);
}
if ((YuvFile = fopen("D:\\数据压缩\\16.yuv", "wb")) == NULL)
{
printf("yuv file  open failed!");
exit(0);
}
TGAHEAD tga_header;
TGAHEADCMAP tga_header_cmap;
TGAHEADIMG tga_header_img;
fread(&tga_header, 3, 1, TgaFile);
fread(&tga_header_cmap, 5, 1, TgaFile);
fread(&tga_header_img, 10, 1, TgaFile);
unsigned char* ImageData = NULL;
unsigned char* b = NULL;
unsigned char* g = NULL;
unsigned char* r = NULL;
unsigned char* R = NULL;
unsigned char* G = NULL;
unsigned char* B = NULL;
unsigned char* Y = NULL;
unsigned char* U = NULL;
unsigned char* V = NULL;
unsigned char* u = NULL;
unsigned char* v = NULL;
unsigned char* RGB = NULL;
unsigned char* YUV = NULL;

颜色表部分

if (tga_header.ColorMapType == 0)//不带颜色表
{
	if (tga_header.ImageType == 0)
		exit(0);
	else if (tga_header.ImageType == 2)//未压缩的真彩色图像
	{
		int depth = tga_header_img.PixelDepth;
		int width = tga_header_img.Width;
		int height = tga_header_img.Height;
		int size = width * height * depth / 8;//整个图像块的大小
		cout << "该文件是未压缩的真彩色图像" << endl;
		cout << "图像分辨率为" << width << "×" << height << endl;
		cout << "像素深度为" << depth << "bit" << endl;
		ImageData = new unsigned char[size];
		fread(ImageData, 1, size, TgaFile);
		b = (unsigned char *)malloc(sizeof(char)*(width * height));
		g = (unsigned char *)malloc(sizeof(char)*(width * height));
		r = (unsigned char *)malloc(sizeof(char)*(width * height));
		R = (unsigned char *)malloc(sizeof(char)*(width * height));
		G = (unsigned char *)malloc(sizeof(char)*(width * height));
		B = (unsigned char *)malloc(sizeof(char)*(width * height));
		Y = (unsigned char *)malloc(sizeof(char)*(width * height));
		U = (unsigned char *)malloc(sizeof(char)*(width * height));
		V = (unsigned char *)malloc(sizeof(char)*(width * height));
		u = (unsigned char *)malloc(sizeof(char)*(width * height / 4));
		v = (unsigned char *)malloc(sizeof(char)*(width * height / 4));
		RGB = new unsigned char[width * height * 3];

打开16位的TGA

 if (tga_header_img.PixelDepth == 16)*/
	{
		for (int j = 0, i = 0; i < width * height; i++)
		{
			{
				b[i] = (ImageData[j] & 0x1F) << 3;
				g[i] = ((ImageData[j + 1] & 0x03) << 6) + ((ImageData[j] & 0xE0) >> 2);
				r[i] = ((ImageData[j + 1] & 0x7C)) << 1;
				j = j + 2;
			}
		}
	}


	for (int k = 0, i = height - 1; i >= 0; i--)
	{
		for (int j = 0; j < width; j++)
		{
			RGB[k] = b[j + i * width];
			RGB[k + 1] = g[j + i * width];
			RGB[k + 2] = r[j + i * width];
			k = k + 3;
		}
	}
	for (int i = 0, j = 0; i < width*height * 3; i = i + 3, j++)
	{
		R[j] = RGB[i + 2];
		G[j] = RGB[i + 1];
		B[j] = RGB[i];
	}

计算YUV分量

	for (int i = 0, j = 0; i < width*height; i++, j++)
	{
		Y[j] = 0.2990*R[i] + 0.5870*G[i] + 0.1140*B[i];
		U[j] = -0.1684*R[i] - 0.3316*G[i] + 0.5*B[i] + 128;
		V[j] = 0.5*R[i] - 0.4187*G[i] - 0.0813*B[i] + 128;
	}

对UV下采样

	for (int k = 0, i = 0; i < height; i = i + 2)
	{
		for (int j = 0; j < width; j = j + 2)
		{
			u[k] = (U[width*i + j] + U[width*i + j + 1] + U[(i + 1)*width + j] + U[(i + 1)*width + j + 1]) / 4;
			v[k] = (V[width*i + j] + V[width*i + j + 1] + V[(i + 1)*width + j] + V[(i + 1)*width + j + 1]) / 4;

			k++;
		}
	}

YUV量化后码电平分配

	for (int k = 0; k < width*height; k++)
	{
		if (Y[k] > 235)
			Y[k] = 235;
		if (Y[k] < 16)
			Y[k] = 16;
	}
	for (int k = 0; k < width*height / 4; k++)
	{
		if (u[k] > 240)
			u[k] = 240;
		if (u[k] < 16)
			u[k] = 16;
		if (v[k] > 240)
			v[k] = 240;
		if (v[k] < 16)
			v[k] = 16;
	}

	fwrite(Y, 1, width*height, YuvFile);
	fwrite(u, 1, width*height / 4, YuvFile);
	fwrite(v, 1, width*height / 4, YuvFile);
}

}
else
exit(0);

最后得到
TGA文件转YUV文件_第1张图片

原TGA图

目测没有原图清楚

你可能感兴趣的:(TGA文件转YUV文件)