数据压缩实验 | TGA文件转YUV文件

实验内容:将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文件格式解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值