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

一、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字节
在这里插入图片描述
0-3位,规定了每个像素属性位的数量;4-5位,这些位用于表示像素数据从文件发送到屏幕的顺序,位4表示从左到右,位5表示从上到下,如下图所示。
在这里插入图片描述
此部分结构体定义如下:

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像素深度:
在这里插入图片描述
24.tga:1600✖️1600,24bit像素深度
在这里插入图片描述
32.tga:1200✖️1200,32bit像素深度
在这里插入图片描述
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:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(2)像素深度为24:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(3)像素深度为32:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值