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

Heather ·
更新时间:2024-09-21
· 804 次阅读

一、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) <> 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) <> 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 #include #include #include #include #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 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 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 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 #include #include #include #include #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) <> 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) <> 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:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


作者:NTY518



yuv 数据压缩 压缩 数据

需要 登录 后方可回复, 如果你还没有账号请 注册新账号