欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据压缩第六次作业:TGA文件转换为YUV文件

程序员文章站 2022-07-14 22:06:17
...

一、TGA文件格式基本介绍
TGA(Targa)格式是计算机上应用最广泛的图象格式。在兼顾了BMP的图象质量的同时又兼顾了JPEG的体积优势。并且还有自身的特点:通道效果、方向性。在CG领域常作为影视动画的序列输出格式,因为兼具体积小和效果清晰的特点。
TGA的结构比较简单,属于一种图形、图像数据的通用格式,在多媒体领域有很大影响,是计算机生成图像向电视转换的一种首选格式。TGA图像格式最大的特点是可以做出不规则形状的图形、图像文件,一般图形、图像文件都为四方形,若需要有圆形、菱形甚至是缕空的图像文件时,TGA就可以派上用场了。
TGA可以压缩也可以不压缩,文件格式较为简单。
二、实验内容
通过C++编写程序,实现TGA文件到YUV文件的转换
三、主要思路
1.利用photoshop将JPEG形式的图像转无压缩的TGA图像
2.读取TGA文件的文件头,获取文件信息
3.读取TGA的其他数据
4.将TGA中的数据转入存储RGB三种颜色的数组
5.从RGB转成YUV
四、TGA文件主体架构
PART1:文件信息头TGA FILE HEADER:
包含三部分:
(1)图像信息字段长度:1字节,规定了包含在字段6(Image ID字段)中的字节数,最大的字符数是255,它的值为0,则表示在这个文件中没有图像信息字段
(2)颜色表类型:1字节,其值为0表示没有颜色表,为1表示有颜色表
(3)图像类型:1字节,用于存储各种位深度的伪彩色,真彩色,调配色
此部分结构体定义如下:

typedef struct TGAFILEHEADER1{
	BYTE IDLENGTH;//图像信息字段长度,1个字节,值为0,则表示在这个文件中没有图像信息字段。
	BYTE COLORMAPTYPE;//颜色表类型,1个字节,0 表示没有颜色表,1 表示颜色表存在
	BYTE IMAGETYPE;//图像类型,1个字节
}TGAFILEHEADER1;

PART2: 颜色表规约COLOR MAP SPECIFICATION
包含三部分:
(1)颜色表首地址:2字节,第一个颜色表表项的索引,是装载颜色表的首地址。
(2)颜色表长度:2字节,颜色表表项的数量
(3)颜色表表项大小:1字节,每个表项占用的位数,典型的值有15,16,24,或者32位。
此部分结构体定义如下:

typedef struct TGAFILEHEADER2 {
	WORD FIRSTENTRYINDEX; //颜色表首地址,2字节
	WORD COLORMAPLENTH;//颜色表长度,2字节
	BYTE COLORMAPENTRYSIZE;//颜色表表项大小,1字节
	//每个表项占用的位数,典型的值有15,16,24,或者32位
}TGAFILEHEADER2;

PART3:图像规约IMAGE SPECIFICATION
(1)图像X的起始位置:2字节,图像左下角的水平坐标
(2)图像Y的起始位置:2字节,图像左下角的垂直坐标
(3)图像宽度:2字节
(4)图像高度:2字节
(5)像素深度:1字节,表示每个像素占用的位数,通常的值是8,16,24,32位。
(6)图像描述符:1字节
数据压缩第六次作业:TGA文件转换为YUV文件
0-3位,规定了每个像素属性位的数量;4-5位,这些位用于表示像素数据从文件发送到屏幕的顺序,位4表示从左到右,位5表示从上到下,如下图所示。
数据压缩第六次作业:TGA文件转换为YUV文件
此部分结构体定义如下:

typedef struct TGAFILEHEADER3 {
	WORD XORIGION; //2个字节,图像左下角的水平坐标
	WORD YORIGION;//2个字节,图像左下角的垂直坐标
	WORD IMAGEWIDTH;//2个字节,图像宽度
	WORD IMAGEHEIGHT;//2个字节,图像高度
	BYTE BITDEPTH;//1个字节,像素z深度
	BYTE IMAGEDESCRIPTOR;//1个字节,图像描述符
	//0-3位,规定了每个像素属性位的数量。看field 24(属性类型,Attributes Type)以获取更多信息
	//Targa 16, 该值为 0 或 1;Targa 24,该值为 0;Targa 32,该值为 8
	//4-5位,这些位用于表示像素数据从文件发送到屏幕的顺序
	//00:bottom left,01:bottom right,10:top left,11:top right
	//6-7位,必需为0。
}TGAFILEHEADER3;

五、实验具体流程及结果:
1.首先从photoshop中导入三张JPEG的图片,并将其分别转化为像素深度为16bit,24bit,32bit的三张TGA图片。获得的三张TGA图片分别为:
16.tga:1600✖️1600,16bit像素深度:
数据压缩第六次作业:TGA文件转换为YUV文件
24.tga:1600✖️1600,24bit像素深度
数据压缩第六次作业:TGA文件转换为YUV文件
32.tga:1200✖️1200,32bit像素深度
数据压缩第六次作业:TGA文件转换为YUV文件
2.写代码:
代码中重点部分:
part1:结构体定义:

typedef struct TGAFILEHEADER1{
	BYTE IDLENGTH;//图像信息字段长度,1个字节,值为0,则表示在这个文件中没有图像信息字段。
	BYTE COLORMAPTYPE;//颜色表类型,1个字节,0 表示没有颜色表,1 表示颜色表存在
	BYTE IMAGETYPE;//图像类型,1个字节
}TGAFILEHEADER1;

typedef struct TGAFILEHEADER2 {
	WORD FIRSTENTRYINDEX; //颜色表首地址,2字节
	WORD COLORMAPLENTH;//颜色表长度,2字节
	BYTE COLORMAPENTRYSIZE;//颜色表表项大小,1字节
	//每个表项占用的位数,典型的值有15,16,24,或者32位
}TGAFILEHEADER2;

typedef struct TGAFILEHEADER3 {
	WORD XORIGION; //2个字节,图像左下角的水平坐标
	WORD YORIGION;//2个字节,图像左下角的垂直坐标
	WORD IMAGEWIDTH;//2个字节,图像宽度
	WORD IMAGEHEIGHT;//2个字节,图像高度
	BYTE BITDEPTH;//1个字节,像素z深度
	BYTE IMAGEDESCRIPTOR;//1个字节,图像描述符
	//0-3位,规定了每个像素属性位的数量。看field 24(属性类型,Attributes Type)以获取更多信息
	//Targa 16, 该值为 0 或 1;Targa 24,该值为 0;Targa 32,该值为 8
	//4-5位,这些位用于表示像素数据从文件发送到屏幕的顺序
	//00:bottom left,01:bottom right,10:top left,11:top right
	//6-7位,必需为0。
}TGAFILEHEADER3;

PART2:无调色板的情况(COLORTYPE=0):

if (FILE_HEADER1.COLORMAPTYPE == 0)//no color chart
	{
		if (fread(DATA, sizeof(unsigned char), DataSize, TGA) == 0)
		{
			cout << "Failed to read the data into the buffer!" << endl;
		}
		else
		{
			cout << "Successfully read in the data into the buffer." << endl;
		}
		if (imagedescriptor == 1)//means Targa 16&bottom left
		{
			int j = DataSize / 2;
			for (int i = 0; i < DataSize;)
			{
				ALPHA[j] = DATA[i + 1] & 0b10000000;
				RED[j] = (DATA[i+1] & 0b01111100) << 1;
				GREEN[j] = ((DATA[i+1] & 0b00000011) << 6) | ((DATA[i] & 0b11100000) >> 2);
				BLUE[j] = (DATA[i] & 0b00011111) << 3;
				i += 2;
				j--;
			}
		}
		else if (imagedescriptor == 0)//means Targa 24&bottom left
		{
			int j = DataSize / 3;
			for (int i = 0; i < DataSize;)
			{
				RED[j] = DATA[i + 2];
				GREEN[j] = DATA[i + 1];
				BLUE[j] = DATA[i];
				i += 3;
				j--;
			}
		}
		else if (imagedescriptor == 8)//means Targa 32&bottom left
		{
			int j = DataSize / 4;
			for (int i = 0; i < DataSize;)
			{
				ALPHA[j] = DATA[i + 3];
				RED[j] = DATA[i + 2];
				GREEN[j] = DATA[i + 1];
				BLUE[j] = DATA[i];
				i += 4;
				j--;
			}
		}
		else
		{
			cout << "This picture is too special to analyse!" << endl;
		}
	}

PART3:有调色板的情况(COLORTYPE=1):

else if(FILE_HEADER1.COLORMAPTYPE == 1)//there is a color chart
	{
		int COLORMAPADDRESS = 0;
		int COLORMAPLENGTH = 0;
		int COLORMAPSIZE = 0;
		int bitsperpixel = 0;
		COLORMAPADDRESS = FILE_HEADER2.FIRSTENTRYINDEX;
		COLORMAPLENGTH = FILE_HEADER2.COLORMAPLENTH;
		COLORMAPSIZE = FILE_HEADER2.COLORMAPENTRYSIZE;
		bitsperpixel = FILE_HEADER3.BITDEPTH;
		unsigned char* COLORMAP = NULL;		
		COLORMAP = (unsigned char*)malloc(COLORMAPSIZE);
		fseek(TGA, COLORMAPADDRESS, SEEK_SET);
		if (fread(COLORMAP, sizeof(unsigned char), COLORMAPSIZE, TGA) == 0)
		{
			cout << "Read Color Map error!" << endl;
		}
		else
		{
			cout << "Successfully read Color Map!" << endl;
		}
		if (COLORMAPSIZE = 16)
		{
			unsigned char* COLORMAP_ALPHA = NULL;
			unsigned char* COLORMAP_RED = NULL;
			unsigned char* COLORMAP_GREEN = NULL;
			unsigned char* COLORMAP_BLUE = NULL;
			COLORMAP_ALPHA = (unsigned char*)malloc(COLORMAPSIZE / 2);
			COLORMAP_RED = (unsigned char*)malloc(COLORMAPSIZE / 2);
			COLORMAP_GREEN = (unsigned char*)malloc(COLORMAPSIZE / 2);
			COLORMAP_BLUE = (unsigned char*)malloc(COLORMAPSIZE / 2);
			int j = COLORMAPSIZE / 2;
			for (int i = 0; i < COLORMAPSIZE;)
			{
				COLORMAP_ALPHA[j] = COLORMAP[i + 1] & 0b10000000;
				COLORMAP_RED[j] = (COLORMAP[i + 1] & 0b01111100) << 1;
				COLORMAP_GREEN[j] = ((COLORMAP[i + 1] & 0b00000011) << 6) | ((COLORMAP[i] & 0b11100000) >> 2);
				COLORMAP_BLUE[j] = (COLORMAP[i] & 0b00011111) << 3;
				i += 2;
				j--;
			}
			if (fread(DATA, sizeof(unsigned char), DataSize, TGA) == 0)
			{
				cout << "Failed to read the data into the buffer!" << endl;
			}
			else
			{
				cout << "Successfully read in the data into the buffer." << endl;
			}
			int bytesperpixel = 0;
			bytesperpixel = bitsperpixel / 8;
			int k = DataSize / bytesperpixel;
			for (int i = 0; i < DataSize;)
			{
				if (bytesperpixel == 2)
				{
					for (int j = 0; j < COLORMAPSIZE; j++)
					{
						if (j == ((DATA[i] & 0b11111111 << 8) + DATA[i + 1]))
						{
							ALPHA[k - i / 2] = COLORMAP_ALPHA[j];
							RED[k - i / 2] = COLORMAP_RED[j];
							GREEN[k - i / 2] = COLORMAP_GREEN[j];
							BLUE[k - i / 2] = COLORMAP_BLUE[j];
							i += 2;
							k--;
						}
					}
				}
				if (bytesperpixel == 3)
				{
					for (int j = 0; j < COLORMAPSIZE; j++)
					{
						if (j == ((DATA[i] & 0b11111111 << 16) + (DATA[i + 1] & 0b11111111 << 8) + DATA[i + 2]))
						{
							ALPHA[k - i / 3] = COLORMAP_ALPHA[j];
							RED[k - i / 3] = COLORMAP_RED[j];
							GREEN[k - i / 3] = COLORMAP_GREEN[j];
							BLUE[k - i / 3] = COLORMAP_BLUE[j];
							i += 3;
							k--;
						}
					}
				}
				if (bytesperpixel == 4)
				{
					for (int j = 0; j < COLORMAPSIZE; j++)
					{
						if (j == ((DATA[i] & 0b11111111 << 24) + (DATA[i + 1] & 0b11111111 << 16) + (DATA[i + 2] & 0b11111111 << 8) + DATA[i + 3]))
						{
							ALPHA[k - i / 4] = COLORMAP_ALPHA[j];
							RED[k - i / 4] = COLORMAP_RED[j];
							GREEN[k - i / 4] = COLORMAP_GREEN[j];
							BLUE[k - i / 4] = COLORMAP_BLUE[j];
							i += 4;
							k--;
						}
					}
				}
			}
			free(COLORMAP_ALPHA);
			free(COLORMAP_RED);
			free(COLORMAP_GREEN);
			free(COLORMAP_BLUE);		
		}
		else if (COLORMAPSIZE = 24)
		{
			unsigned char* COLORMAP_RED = NULL;
			unsigned char* COLORMAP_GREEN = NULL;
			unsigned char* COLORMAP_BLUE = NULL;
			COLORMAP_RED = (unsigned char*)malloc(COLORMAPSIZE / 3);
			COLORMAP_GREEN = (unsigned char*)malloc(COLORMAPSIZE / 3);
			COLORMAP_BLUE = (unsigned char*)malloc(COLORMAPSIZE / 3);
			int j = COLORMAPSIZE / 3;
			for (int i = 0; i < COLORMAPSIZE;)
			{
				COLORMAP_RED[j] = COLORMAP[i + 2];
				COLORMAP_GREEN[j] = COLORMAP[i + 1];
				COLORMAP_BLUE[j] = COLORMAP[i];
				i += 3;
				j--;
			}
			if (fread(DATA, sizeof(unsigned char), DataSize, TGA) == 0)
			{
				cout << "Failed to read the data into the buffer!" << endl;
			}
			else
			{
				cout << "Successfully read in the data into the buffer." << endl;
			}
			int bytesperpixel = 0;
			bytesperpixel = bitsperpixel / 8;
			int k = DataSize / bytesperpixel;
			for (int i = 0; i < DataSize;)
			{
				if (bytesperpixel == 2)
				{
					for (int j = 0; j < COLORMAPSIZE; j++)
					{
						if (j == ((DATA[i] & 0b11111111 << 8) + DATA[i + 1]))
						{
							RED[k - i / 2] = COLORMAP_RED[j];
							GREEN[k - i / 2] = COLORMAP_GREEN[j];
							BLUE[k - i / 2] = COLORMAP_BLUE[j];
							i += 2;
							k--;
						}
					}
				}
				if (bytesperpixel == 3)
				{
					for (int j = 0; j < COLORMAPSIZE; j++)
					{
						if (j == ((DATA[i] & 0b11111111 << 16) + (DATA[i + 1] & 0b11111111 << 8) + DATA[i + 2]))
						{
							RED[k - i / 3] = COLORMAP_RED[j];
							GREEN[k - i / 3] = COLORMAP_GREEN[j];
							BLUE[k - i / 3] = COLORMAP_BLUE[j];
							i += 3;
							k--;
						}
					}
				}
				if (bytesperpixel == 4)
				{
					for (int j = 0; j < COLORMAPSIZE; j++)
					{
						if (j == ((DATA[i] & 0b11111111 << 24) + (DATA[i + 1] & 0b11111111 << 16) + (DATA[i + 2] & 0b11111111 << 8) + DATA[i + 3]))
						{
							RED[k - i / 4] = COLORMAP_RED[j];
							GREEN[k - i / 4] = COLORMAP_GREEN[j];
							BLUE[k - i / 4] = COLORMAP_BLUE[j];
							i += 4;
							k--;
						}
					}
				}
			}
			free(COLORMAP_RED);
			free(COLORMAP_GREEN);
			free(COLORMAP_BLUE);
		}
		else if (COLORMAPSIZE = 32)
		{
		    unsigned char* COLORMAP_ALPHA = NULL;
		    unsigned char* COLORMAP_RED = NULL;
		    unsigned char* COLORMAP_GREEN = NULL;
		    unsigned char* COLORMAP_BLUE = NULL;
		    COLORMAP_ALPHA = (unsigned char*)malloc(COLORMAPSIZE / 2);
		    COLORMAP_RED = (unsigned char*)malloc(COLORMAPSIZE / 2);
		    COLORMAP_GREEN = (unsigned char*)malloc(COLORMAPSIZE / 2);
		    COLORMAP_BLUE = (unsigned char*)malloc(COLORMAPSIZE / 2);
		    int j = COLORMAPSIZE / 4;
		    for (int i = 0; i < COLORMAPSIZE;)
		    {
			    COLORMAP_ALPHA[j] = COLORMAP[i + 3];
			    COLORMAP_RED[j] = COLORMAP[i + 2];
			    COLORMAP_GREEN[j] = COLORMAP[i + 1];
			    COLORMAP_BLUE[j] = COLORMAP[i];
			    i += 3;
			    j--;
		    }
		    if (fread(DATA, sizeof(unsigned char), DataSize, TGA) == 0)
		    {
			    cout << "Failed to read the data into the buffer!" << endl;
		    }
		    else
		    {
			    cout << "Successfully read in the data into the buffer." << endl;
		    } 
		    int bytesperpixel = 0;
		    bytesperpixel = bitsperpixel / 8;
		    int k = DataSize / bytesperpixel;
		    for (int i = 0; i < DataSize;)
		    {
			if (bytesperpixel == 2)
			{
				for (int j = 0; j < COLORMAPSIZE; j++)
				{
					if (j == ((DATA[i] & 0b11111111 << 8) + DATA[i + 1]))
					{
						ALPHA[k - i / 2] = COLORMAP_ALPHA[j];
						RED[k - i / 2] = COLORMAP_RED[j];
						GREEN[k - i / 2] = COLORMAP_GREEN[j];
						BLUE[k - i / 2] = COLORMAP_BLUE[j];
						i += 2;
						k--;
					}
				}
			}
			if (bytesperpixel == 3)
			{
				for (int j = 0; j < COLORMAPSIZE; j++)
				{
					if (j == ((DATA[i] & 0b11111111 << 16) + (DATA[i + 1] & 0b11111111 << 8) + DATA[i + 2]))
					{
						ALPHA[k - i / 3] = COLORMAP_ALPHA[j];
						RED[k - i / 3] = COLORMAP_RED[j];
						GREEN[k - i / 3] = COLORMAP_GREEN[j];
						BLUE[k - i / 3] = COLORMAP_BLUE[j];
						i += 3;
						k--;
					}
				}
			}
			if (bytesperpixel == 4)
			{
				for (int j = 0; j < COLORMAPSIZE; j++)
				{
					if (j == ((DATA[i] & 0b11111111 << 24) + (DATA[i + 1] & 0b11111111 << 16) + (DATA[i + 2] & 0b11111111 << 8) + DATA[i + 3]))
					{
						ALPHA[k - i / 4] = COLORMAP_ALPHA[j];
						RED[k - i / 4] = COLORMAP_RED[j];
						GREEN[k - i / 4] = COLORMAP_GREEN[j];
						BLUE[k - i / 4] = COLORMAP_BLUE[j];
						i += 4;
						k--;
					}
				}
			}
		}
		free(COLORMAP_ALPHA);
		free(COLORMAP_RED);
		free(COLORMAP_GREEN);
		free(COLORMAP_BLUE);
        }
		else
		{
			cout << "This colormap is too special.This program cannot analyse this picture!" << endl;
		}

	}
	else
	{
		cout << "this program cannot analyse this picture!" << endl;
	}

PART4:RGB转换为YUV(rgb2yuv.cpp):

#include<iostream>
#include<windows.h>
#include<math.h>
#include <cstring>
#include <cstdlib>
#include"header.h"
using namespace std;

void RGBtoYUV(int w,int h,int size,unsigned char*RED_BUFFER,unsigned char*GREEN_BUFFER,unsigned char*BLUE_BUFFER)
{
	FILE* YUV = NULL;
	if (fopen_s(&YUV, "C:\\32.yuv", "wb") != 0)
	{
		cout << "Failed to create the yuv file!" << endl;
	}
	else
	{
		cout << "Successfully created the yuv file!" << endl;
	}
	unsigned char* Y_BUFFER = NULL; 
	unsigned char* U_BUFFER = NULL; 
	unsigned char* V_BUFFER = NULL;
	Y_BUFFER = new unsigned char[size / 3];
	U_BUFFER = new unsigned char[size / 12];
    V_BUFFER = new unsigned char[size / 12];
	for (int i = 0; i < size/3; i++)//caculate Y
	{
		Y_BUFFER[i] = RED_BUFFER[i] * 0.2990 +
			GREEN_BUFFER[i] * 0.5870 +
			BLUE_BUFFER[i] * 0.1140;
		//Y=0.2990*Red+0.5870*Green+0.1440*Blue
		if (Y_BUFFER[i] > 235)
		{
			Y_BUFFER[i] = 235;
		}
		if (Y_BUFFER[i] < 16)
		{
			Y_BUFFER[i] = 16;
		}
		//In order to avoid the overload of the luminace, so we need to reserve some space
	}


	int u = 0;
	for (int i = 0; i < size/3;)//caculate u
	{
		U_BUFFER[u] = (RED_BUFFER[i] + RED_BUFFER[i + 1] + RED_BUFFER[i + w] + RED_BUFFER[i + w + 1]) / 4 * (-0.1684) +
			(GREEN_BUFFER[i] + GREEN_BUFFER[i + 1] + GREEN_BUFFER[i + w] + GREEN_BUFFER[i + w + 1]) / 4 * (-0.3316) +
			(BLUE_BUFFER[i] + BLUE_BUFFER[i + 1] + BLUE_BUFFER[i + w] + BLUE_BUFFER[i + w + 1]) / 4 * (0.500) + 128;
		if (U_BUFFER[u] > 235)
		{
			U_BUFFER[u] = 235;
		}
		if (U_BUFFER[u] < 16)
		{
			U_BUFFER[u] = 16;
		}
		if (i % w == (w-2))
		{
			i = i + w + 2;
		}
		else
		{
			i = i + 2;
		}
		u++;
	}
	int v = 0;
	for (int i = 0; i < size/3;)//caculate v
	{
		V_BUFFER[v] = (RED_BUFFER[i] + RED_BUFFER[i + 1] + RED_BUFFER[i + w] + RED_BUFFER[i + w + 1]) / 4 * (0.5) +
			(GREEN_BUFFER[i] + GREEN_BUFFER[i + 1] + GREEN_BUFFER[i + w] + GREEN_BUFFER[i + w + 1]) / 4 * (-0.4187) +
			(BLUE_BUFFER[i] + BLUE_BUFFER[i + 1] + BLUE_BUFFER[i + w] + BLUE_BUFFER[i + w + 1]) / 4 * (-0.0813) + 128;
		if (V_BUFFER[v] > 235)
		{
			V_BUFFER[v] = 235;
		}
		if (V_BUFFER[v] < 16)
		{
			V_BUFFER[v] = 16;
		}
		if (i % w == (w - 2))
		{
			i = i + w +2;
		}
		else
		{
			i = i + 2;
		}
		v++;
	}
	fwrite(Y_BUFFER, sizeof(unsigned char), size/3, YUV);
	fwrite(U_BUFFER, sizeof(unsigned char), size/12, YUV);
	fwrite(V_BUFFER, sizeof(unsigned char), size/12, YUV);

	
}

完整主函数(main.cpp):

#include<iostream>
#include<windows.h>
#include<math.h>
#include <cstring>
#include <cstdlib>
#include"header.h"
using namespace std;

typedef struct TGAFILEHEADER1{
	BYTE IDLENGTH;//图像信息字段长度,1个字节,值为0,则表示在这个文件中没有图像信息字段。
	BYTE COLORMAPTYPE;//颜色表类型,1个字节,0 表示没有颜色表,1 表示颜色表存在
	BYTE IMAGETYPE;//图像类型,1个字节
}TGAFILEHEADER1;

typedef struct TGAFILEHEADER2 {
	WORD FIRSTENTRYINDEX; //颜色表首地址,2字节
	WORD COLORMAPLENTH;//颜色表长度,2字节
	BYTE COLORMAPENTRYSIZE;//颜色表表项大小,1字节
	//每个表项占用的位数,典型的值有15,16,24,或者32位
}TGAFILEHEADER2;

typedef struct TGAFILEHEADER3 {
	WORD XORIGION; //2个字节,图像左下角的水平坐标
	WORD YORIGION;//2个字节,图像左下角的垂直坐标
	WORD IMAGEWIDTH;//2个字节,图像宽度
	WORD IMAGEHEIGHT;//2个字节,图像高度
	BYTE BITDEPTH;//1个字节,像素z深度
	BYTE IMAGEDESCRIPTOR;//1个字节,图像描述符
	//0-3位,规定了每个像素属性位的数量。看field 24(属性类型,Attributes Type)以获取更多信息
	//Targa 16, 该值为 0 或 1;Targa 24,该值为 0;Targa 32,该值为 8
	//4-5位,这些位用于表示像素数据从文件发送到屏幕的顺序
	//00:bottom left,01:bottom right,10:top left,11:top right
	//6-7位,必需为0。
}TGAFILEHEADER3;

int main()
{
	FILE* TGA = NULL;
	FILE* RGB = NULL;
	TGAFILEHEADER1 FILE_HEADER1;
	TGAFILEHEADER2 FILE_HEADER2;
	TGAFILEHEADER3 FILE_HEADER3;
	if (fopen_s(&TGA, "C:\\32.tga", "rb") != 0)
	{
        cout << "Failed to open the tga file!" << endl;
	}
	else
	{
	cout << "Successfully opened the tga file!" << endl;
	}
	if (fopen_s(&RGB, "C:\\32.rgb", "wb") != 0)
	{
		cout << "Failed to create the rgb file!" << endl;
	}
	else
	{
		cout << "Successfully created the rgb file!" << endl;
	}
	fseek(TGA, 0L, SEEK_END);
	int FileSize;
	FileSize = ftell(TGA);
	fseek(TGA, 0L, SEEK_SET);
	/*cout << sizeof(TGAFILEHEADER) << endl;*/
	if (fread(&FILE_HEADER1, 1, 3, TGA) == 0)
	{
		cout << "Read File Header1 error!" << endl;
	}
	else
	{
		cout << "Successfully read File Header!" << endl;
	}
	if (FILE_HEADER1.IDLENGTH == 0)
	{
		cout << "There's no Image information words in this picture." << endl;
	}
	else
	{
		cout << "This program cannot analyse this picture!" << endl;
	}
	if (FILE_HEADER1.COLORMAPTYPE == 0)
	{
		cout << "There is no PLTE in this picture." << endl;
	}
	else
	{
		cout << "This Image includes a PLTE!" << endl;
	}
	if (FILE_HEADER1.IMAGETYPE == 2)
	{
		cout << "This is a ture color image!" << endl;
	}
	else
	{
		cout << "This is a ture color image!" << endl;
	}
	if (fread(&FILE_HEADER2, 1, 5, TGA) == 0)
	{
		cout << "Read File Header2 error!" << endl;
	}
	else
	{
		cout << "Successfully read File Header!" << endl;
	}
	int colortype = FILE_HEADER2.COLORMAPENTRYSIZE;
	cout << "The fisrt entry of the index is " << FILE_HEADER2.FIRSTENTRYINDEX << "." << endl;
	cout << "The length of the color map is " << FILE_HEADER2.COLORMAPLENTH << "." << endl;
	cout << "The size of the color map entry is " << colortype << "." << endl;
	if (fread(&FILE_HEADER3, 1, 10, TGA) == 0)
	{
		cout << "Read File Header3 error!" << endl;
	}
	else
	{
		cout << "Successfully read File Header!" << endl;
	}
	int bitdepth = FILE_HEADER3.BITDEPTH;
	int imagedescriptor = FILE_HEADER3.IMAGEDESCRIPTOR;
	cout << "The X-origin of the image is " << FILE_HEADER3.XORIGION << "." << endl;
	cout << "The Y-origin of the image is " << FILE_HEADER3.YORIGION << "." << endl;
	cout << "The width of the image is " << FILE_HEADER3.IMAGEWIDTH << "." << endl;
	cout << "The height of the image is " << FILE_HEADER3.IMAGEHEIGHT << "." << endl;
	cout << "The bitdepth of the image is " << bitdepth << "." << endl;
	cout << "The imagedescripter of the image is " << imagedescriptor << "." << endl;

	int FILEHEADERSIZE = sizeof(FILE_HEADER1) + sizeof(FILE_HEADER1) + sizeof(FILE_HEADER1);
	int width = 0;
	int height = 0;
	width = FILE_HEADER3.IMAGEWIDTH;
	height = FILE_HEADER3.IMAGEHEIGHT;
	int DataSize = 0;
	DataSize = width * height * bitdepth / 8;
	cout << "The size of the data is " << DataSize << "bytes." << endl;

	unsigned char* DATA = NULL;
	unsigned char* RED = NULL;
	unsigned char* GREEN = NULL;
	unsigned char* BLUE = NULL;
	unsigned char* ALPHA = NULL;
	DATA = (unsigned char*)malloc(DataSize);
	RED = (unsigned char*)malloc(height * width);
	GREEN = (unsigned char*)malloc(height * width);
	BLUE = (unsigned char*)malloc(height * width);
	ALPHA = (unsigned char*)malloc(height * width);

	if (FILE_HEADER1.COLORMAPTYPE == 0)//no color chart
	{
		if (fread(DATA, sizeof(unsigned char), DataSize, TGA) == 0)
		{
			cout << "Failed to read the data into the buffer!" << endl;
		}
		else
		{
			cout << "Successfully read in the data into the buffer." << endl;
		}
		if (imagedescriptor == 1)//means Targa 16&bottom left
		{
			int j = DataSize / 2;
			for (int i = 0; i < DataSize;)
			{
				ALPHA[j] = DATA[i + 1] & 0b10000000;
				RED[j] = (DATA[i+1] & 0b01111100) << 1;
				GREEN[j] = ((DATA[i+1] & 0b00000011) << 6) | ((DATA[i] & 0b11100000) >> 2);
				BLUE[j] = (DATA[i] & 0b00011111) << 3;
				i += 2;
				j--;
			}
		}
		else if (imagedescriptor == 0)//means Targa 24&bottom left
		{
			int j = DataSize / 3;
			for (int i = 0; i < DataSize;)
			{
				RED[j] = DATA[i + 2];
				GREEN[j] = DATA[i + 1];
				BLUE[j] = DATA[i];
				i += 3;
				j--;
			}
		}
		else if (imagedescriptor == 8)//means Targa 32&bottom left
		{
			int j = DataSize / 4;
			for (int i = 0; i < DataSize;)
			{
				ALPHA[j] = DATA[i + 3];
				RED[j] = DATA[i + 2];
				GREEN[j] = DATA[i + 1];
				BLUE[j] = DATA[i];
				i += 4;
				j--;
			}
		}
		else
		{
			cout << "This picture is too special to analyse!" << endl;
		}
	}
	else if(FILE_HEADER1.COLORMAPTYPE == 1)//there is a color chart
	{
		int COLORMAPADDRESS = 0;
		int COLORMAPLENGTH = 0;
		int COLORMAPSIZE = 0;
		int bitsperpixel = 0;
		COLORMAPADDRESS = FILE_HEADER2.FIRSTENTRYINDEX;
		COLORMAPLENGTH = FILE_HEADER2.COLORMAPLENTH;
		COLORMAPSIZE = FILE_HEADER2.COLORMAPENTRYSIZE;
		bitsperpixel = FILE_HEADER3.BITDEPTH;
		unsigned char* COLORMAP = NULL;		
		COLORMAP = (unsigned char*)malloc(COLORMAPSIZE);
		fseek(TGA, COLORMAPADDRESS, SEEK_SET);
		if (fread(COLORMAP, sizeof(unsigned char), COLORMAPSIZE, TGA) == 0)
		{
			cout << "Read Color Map error!" << endl;
		}
		else
		{
			cout << "Successfully read Color Map!" << endl;
		}
		if (COLORMAPSIZE = 16)
		{
			unsigned char* COLORMAP_ALPHA = NULL;
			unsigned char* COLORMAP_RED = NULL;
			unsigned char* COLORMAP_GREEN = NULL;
			unsigned char* COLORMAP_BLUE = NULL;
			COLORMAP_ALPHA = (unsigned char*)malloc(COLORMAPSIZE / 2);
			COLORMAP_RED = (unsigned char*)malloc(COLORMAPSIZE / 2);
			COLORMAP_GREEN = (unsigned char*)malloc(COLORMAPSIZE / 2);
			COLORMAP_BLUE = (unsigned char*)malloc(COLORMAPSIZE / 2);
			int j = COLORMAPSIZE / 2;
			for (int i = 0; i < COLORMAPSIZE;)
			{
				COLORMAP_ALPHA[j] = COLORMAP[i + 1] & 0b10000000;
				COLORMAP_RED[j] = (COLORMAP[i + 1] & 0b01111100) << 1;
				COLORMAP_GREEN[j] = ((COLORMAP[i + 1] & 0b00000011) << 6) | ((COLORMAP[i] & 0b11100000) >> 2);
				COLORMAP_BLUE[j] = (COLORMAP[i] & 0b00011111) << 3;
				i += 2;
				j--;
			}
			if (fread(DATA, sizeof(unsigned char), DataSize, TGA) == 0)
			{
				cout << "Failed to read the data into the buffer!" << endl;
			}
			else
			{
				cout << "Successfully read in the data into the buffer." << endl;
			}
			int bytesperpixel = 0;
			bytesperpixel = bitsperpixel / 8;
			int k = DataSize / bytesperpixel;
			for (int i = 0; i < DataSize;)
			{
				if (bytesperpixel == 2)
				{
					for (int j = 0; j < COLORMAPSIZE; j++)
					{
						if (j == ((DATA[i] & 0b11111111 << 8) + DATA[i + 1]))
						{
							ALPHA[k - i / 2] = COLORMAP_ALPHA[j];
							RED[k - i / 2] = COLORMAP_RED[j];
							GREEN[k - i / 2] = COLORMAP_GREEN[j];
							BLUE[k - i / 2] = COLORMAP_BLUE[j];
							i += 2;
							k--;
						}
					}
				}
				if (bytesperpixel == 3)
				{
					for (int j = 0; j < COLORMAPSIZE; j++)
					{
						if (j == ((DATA[i] & 0b11111111 << 16) + (DATA[i + 1] & 0b11111111 << 8) + DATA[i + 2]))
						{
							ALPHA[k - i / 3] = COLORMAP_ALPHA[j];
							RED[k - i / 3] = COLORMAP_RED[j];
							GREEN[k - i / 3] = COLORMAP_GREEN[j];
							BLUE[k - i / 3] = COLORMAP_BLUE[j];
							i += 3;
							k--;
						}
					}
				}
				if (bytesperpixel == 4)
				{
					for (int j = 0; j < COLORMAPSIZE; j++)
					{
						if (j == ((DATA[i] & 0b11111111 << 24) + (DATA[i + 1] & 0b11111111 << 16) + (DATA[i + 2] & 0b11111111 << 8) + DATA[i + 3]))
						{
							ALPHA[k - i / 4] = COLORMAP_ALPHA[j];
							RED[k - i / 4] = COLORMAP_RED[j];
							GREEN[k - i / 4] = COLORMAP_GREEN[j];
							BLUE[k - i / 4] = COLORMAP_BLUE[j];
							i += 4;
							k--;
						}
					}
				}
			}
			free(COLORMAP_ALPHA);
			free(COLORMAP_RED);
			free(COLORMAP_GREEN);
			free(COLORMAP_BLUE);		
		}
		else if (COLORMAPSIZE = 24)
		{
			unsigned char* COLORMAP_RED = NULL;
			unsigned char* COLORMAP_GREEN = NULL;
			unsigned char* COLORMAP_BLUE = NULL;
			COLORMAP_RED = (unsigned char*)malloc(COLORMAPSIZE / 3);
			COLORMAP_GREEN = (unsigned char*)malloc(COLORMAPSIZE / 3);
			COLORMAP_BLUE = (unsigned char*)malloc(COLORMAPSIZE / 3);
			int j = COLORMAPSIZE / 3;
			for (int i = 0; i < COLORMAPSIZE;)
			{
				COLORMAP_RED[j] = COLORMAP[i + 2];
				COLORMAP_GREEN[j] = COLORMAP[i + 1];
				COLORMAP_BLUE[j] = COLORMAP[i];
				i += 3;
				j--;
			}
			if (fread(DATA, sizeof(unsigned char), DataSize, TGA) == 0)
			{
				cout << "Failed to read the data into the buffer!" << endl;
			}
			else
			{
				cout << "Successfully read in the data into the buffer." << endl;
			}
			int bytesperpixel = 0;
			bytesperpixel = bitsperpixel / 8;
			int k = DataSize / bytesperpixel;
			for (int i = 0; i < DataSize;)
			{
				if (bytesperpixel == 2)
				{
					for (int j = 0; j < COLORMAPSIZE; j++)
					{
						if (j == ((DATA[i] & 0b11111111 << 8) + DATA[i + 1]))
						{
							RED[k - i / 2] = COLORMAP_RED[j];
							GREEN[k - i / 2] = COLORMAP_GREEN[j];
							BLUE[k - i / 2] = COLORMAP_BLUE[j];
							i += 2;
							k--;
						}
					}
				}
				if (bytesperpixel == 3)
				{
					for (int j = 0; j < COLORMAPSIZE; j++)
					{
						if (j == ((DATA[i] & 0b11111111 << 16) + (DATA[i + 1] & 0b11111111 << 8) + DATA[i + 2]))
						{
							RED[k - i / 3] = COLORMAP_RED[j];
							GREEN[k - i / 3] = COLORMAP_GREEN[j];
							BLUE[k - i / 3] = COLORMAP_BLUE[j];
							i += 3;
							k--;
						}
					}
				}
				if (bytesperpixel == 4)
				{
					for (int j = 0; j < COLORMAPSIZE; j++)
					{
						if (j == ((DATA[i] & 0b11111111 << 24) + (DATA[i + 1] & 0b11111111 << 16) + (DATA[i + 2] & 0b11111111 << 8) + DATA[i + 3]))
						{
							RED[k - i / 4] = COLORMAP_RED[j];
							GREEN[k - i / 4] = COLORMAP_GREEN[j];
							BLUE[k - i / 4] = COLORMAP_BLUE[j];
							i += 4;
							k--;
						}
					}
				}
			}
			free(COLORMAP_RED);
			free(COLORMAP_GREEN);
			free(COLORMAP_BLUE);
		}
		else if (COLORMAPSIZE = 32)
		{
		    unsigned char* COLORMAP_ALPHA = NULL;
		    unsigned char* COLORMAP_RED = NULL;
		    unsigned char* COLORMAP_GREEN = NULL;
		    unsigned char* COLORMAP_BLUE = NULL;
		    COLORMAP_ALPHA = (unsigned char*)malloc(COLORMAPSIZE / 2);
		    COLORMAP_RED = (unsigned char*)malloc(COLORMAPSIZE / 2);
		    COLORMAP_GREEN = (unsigned char*)malloc(COLORMAPSIZE / 2);
		    COLORMAP_BLUE = (unsigned char*)malloc(COLORMAPSIZE / 2);
		    int j = COLORMAPSIZE / 4;
		    for (int i = 0; i < COLORMAPSIZE;)
		    {
			    COLORMAP_ALPHA[j] = COLORMAP[i + 3];
			    COLORMAP_RED[j] = COLORMAP[i + 2];
			    COLORMAP_GREEN[j] = COLORMAP[i + 1];
			    COLORMAP_BLUE[j] = COLORMAP[i];
			    i += 3;
			    j--;
		    }
		    if (fread(DATA, sizeof(unsigned char), DataSize, TGA) == 0)
		    {
			    cout << "Failed to read the data into the buffer!" << endl;
		    }
		    else
		    {
			    cout << "Successfully read in the data into the buffer." << endl;
		    } 
		    int bytesperpixel = 0;
		    bytesperpixel = bitsperpixel / 8;
		    int k = DataSize / bytesperpixel;
		    for (int i = 0; i < DataSize;)
		    {
			if (bytesperpixel == 2)
			{
				for (int j = 0; j < COLORMAPSIZE; j++)
				{
					if (j == ((DATA[i] & 0b11111111 << 8) + DATA[i + 1]))
					{
						ALPHA[k - i / 2] = COLORMAP_ALPHA[j];
						RED[k - i / 2] = COLORMAP_RED[j];
						GREEN[k - i / 2] = COLORMAP_GREEN[j];
						BLUE[k - i / 2] = COLORMAP_BLUE[j];
						i += 2;
						k--;
					}
				}
			}
			if (bytesperpixel == 3)
			{
				for (int j = 0; j < COLORMAPSIZE; j++)
				{
					if (j == ((DATA[i] & 0b11111111 << 16) + (DATA[i + 1] & 0b11111111 << 8) + DATA[i + 2]))
					{
						ALPHA[k - i / 3] = COLORMAP_ALPHA[j];
						RED[k - i / 3] = COLORMAP_RED[j];
						GREEN[k - i / 3] = COLORMAP_GREEN[j];
						BLUE[k - i / 3] = COLORMAP_BLUE[j];
						i += 3;
						k--;
					}
				}
			}
			if (bytesperpixel == 4)
			{
				for (int j = 0; j < COLORMAPSIZE; j++)
				{
					if (j == ((DATA[i] & 0b11111111 << 24) + (DATA[i + 1] & 0b11111111 << 16) + (DATA[i + 2] & 0b11111111 << 8) + DATA[i + 3]))
					{
						ALPHA[k - i / 4] = COLORMAP_ALPHA[j];
						RED[k - i / 4] = COLORMAP_RED[j];
						GREEN[k - i / 4] = COLORMAP_GREEN[j];
						BLUE[k - i / 4] = COLORMAP_BLUE[j];
						i += 4;
						k--;
					}
				}
			}
		}
		free(COLORMAP_ALPHA);
		free(COLORMAP_RED);
		free(COLORMAP_GREEN);
		free(COLORMAP_BLUE);
        }
		else
		{
			cout << "This colormap is too special.This program cannot analyse this picture!" << endl;
		}

	}
	else
	{
		cout << "this program cannot analyse this picture!" << endl;
	}

	fwrite(BLUE, sizeof(unsigned char),width*height, RGB);
	fwrite(GREEN, sizeof(unsigned char), width* height, RGB);
	fwrite(RED, sizeof(unsigned char), width* height, RGB);
	RGBtoYUV(width, height, width* height * 3, RED, GREEN, BLUE);
	/*free(DATA);
	free(RED);
	free(ALPHA);
	free(GREEN);
	free(BLUE);*/
}

六、实验结果:
(1)像素深度为16:
数据压缩第六次作业:TGA文件转换为YUV文件
数据压缩第六次作业:TGA文件转换为YUV文件
数据压缩第六次作业:TGA文件转换为YUV文件
(2)像素深度为24:
数据压缩第六次作业:TGA文件转换为YUV文件
数据压缩第六次作业:TGA文件转换为YUV文件
数据压缩第六次作业:TGA文件转换为YUV文件
(3)像素深度为32:
数据压缩第六次作业:TGA文件转换为YUV文件
数据压缩第六次作业:TGA文件转换为YUV文件
数据压缩第六次作业:TGA文件转换为YUV文件