一、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: