实验内容:将TGA图像文件转化为YUV文件
建立TGA文件头的结构体
TGA文件头有5个字段,共18个字节
typedef struct
{
unsigned char IDLength;
unsigned char ColorMapType;
unsigned char ImageType;
unsigned short FirstEntryIndex;//颜色首地址
unsigned short ColorMapLength;//颜色表长度
unsigned char ColorMapEntrySize;//颜色表表项大小
unsigned short x_origin;
unsigned short y_origin;
unsigned short width;
unsigned short height;
unsigned char PixelDepth;//像素深度
unsigned char ImageDescriptor;
}TGAFileHeader;
读取TGA文件头信息
TGAFileHeader tgaHeader;
tga_file.read((char*)&tgaHeader, sizeof(TGAFileHeader));
根据文件头信息,计算偏移量
int PixelCount = tgaHeader.width * tgaHeader.height;
int bitdepth = 24;
int colortable = 0;//没有颜色表
unsigned char* r = new unsigned char[PixelCount];
unsigned char* g = new unsigned char[PixelCount];
unsigned char* b = new unsigned char[PixelCount];
unsigned char* buffer = new unsigned char[];
unsigned char* buffer = new unsigned char[PixelCount * 3];
rgb_buffer = new unsigned char[PixelCount * 3];
//rgb_buffer = (unsigned char*)malloc(PixelCount * 3 * sizeof(unsigned char*));
int offset = 0;
if (tgaHeader.IDLength == 0)//没有图像信息字段
{
offset = 18;
}
if (tgaHeader.IDLength != 0)
{
offset = 18 + tgaHeader.IDLength;
}
if (tgaHeader.ColorMapType != 0)//有颜色表
{
offset = offset + tgaHeader.ColorMapLength;
bitdepth = tgaHeader.ColorMapEntrySize;
colortable = 1;
}
从文件中提取图像数据并转换为rgb数据
//没有颜色表
tga_file.read((char*)buffer, size + offset);
rgb = buffer + offset;
if (colortable == 0)
{
b = rgb;
for (int i = 0; i < PixelCount; i++)
{
g = rgb + 1;
r = rgb + 2;
b += 3;
}
}
//有颜色表
if (colortable == 1)
{
tga_file.read((char*)buffer_t, size_t + tgaHeader.ColorMapEntrySize);
table = buffer_t + tgaHeader.FirstEntryIndex;
for (int i = 0; i < PixelCount*3; i++)
{
if (i % 3 == 0) { b[i/3] = table[rgb[i]]; }
if (i % 3 == 1) { g[i/3] = table[rgb[i + 1]]; }
if (i % 3 == 2) { r[i/3] = table[rgb[i] + 2]; }
}
}
int height = tgaHeader.height;
for (int i = 0; i < tgaHeader.height; i++)
{
for (int j = 0; j < tgaHeader.width; j++)
{
r_r[i * 256 + j] = r[(height * 1 * i) * 256 + j];
g_r[i * 256 + j] = g[(height * 1 * i) * 256 + j];
b_r[i * 256 + j] = b[(height * 1 * i) * 256 + j];
}
}
for (int i = 0; i < PixelCount; i++)
{
int j = 0;
rgb_buffer[j] = b[i];
rgb_buffer[j + 1] = g[i];
rgb_buffer[j + 2] = r[i];
j += 3;
}
imagesize = PixelCount;
return rgb_buffer;
最后将rgb数据转换成yuv
(这一步在上一个实验中已实现过)
rgb2yuv.cpp
#include "stdlib.h"
#include"rgb2yuv.h"
static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
static float RGBYUV01684[256], RGBYUV03316[256];
static float RGBYUV04187[256], RGBYUV00813[256];
void RGB2YUV(int size, unsigned char* rgb, unsigned char* yuv)
{
static int init_done;
int usize = size;
int vsize = size * 2;
unsigned char* r, * g, * b;
int y, u, v;
if (init_done == 0)
{
InitLookupTable();
init_done = 1;
}
b = rgb;
for (int i = 0; i < size; i++)
{
g = b + 1;
r = b + 2;
y = (unsigned char)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
u = (unsigned char)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);
v = (unsigned char)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
*(yuv + i) = y;
*(yuv + i + usize) = u;
*(yuv + i + vsize) = v;
b += 3;
}
}
void InitLookupTable()
{
int i;
for (i = 0; i < 256; i++) RGBYUV02990[i] = (float)0.2990 * i;
for (i = 0; i < 256; i++) RGBYUV05870[i] = (float)0.5870 * i;
for (i = 0; i < 256; i++) RGBYUV01140[i] = (float)0.1140 * i;
for (i = 0; i < 256; i++) RGBYUV01684[i] = (float)0.1684 * i;
for (i = 0; i < 256; i++) RGBYUV03316[i] = (float)0.3316 * i;
for (i = 0; i < 256; i++) RGBYUV04187[i] = (float)0.4187 * i;
for (i = 0; i < 256; i++) RGBYUV00813[i] = (float)0.0813 * i;
}
main.cpp
#include <iostream>
#include <cstdio>
#include <fstream>
#include "rgb2yuv.h"
using namespace std;
int main()
{
unsigned char* tgaheader = new unsigned char[18];
unsigned char* rgb_buffer = NULL;
unsigned char* yuv_buffer = NULL;
int rgbsize = 0;
long imagesize = 0;
ifstream tga_file("1.png", ios::binary);
if (!tga_file)
{
cout << "Cannot open tga file!" << endl;
abort();
}
ofstream yuv_file("1.yuv", ios::binary);
if (!yuv_file)
{
cout << "Cannot open yuv file!" << endl;
abort();
}
rgb_buffer = TGA2BGR(tga_file, rgb_buffer, imagesize);
RGB2YUV(rgbsize, rgb_buffer, yuv_buffer);
yuv_file.write((char*)yuv_buffer, imagesize * 3);
free(rgb_buffer);
free(yuv_buffer);
yuv_file.close;
tga_file.close;
}
参考文献:TGA文件格式解析