TGA转YUV

本文介绍了如何将TGA文件转换为YUV格式。首先通过在线工具将GIF转为TGA,然后详细阐述转换过程,包括读取文件、处理颜色表、图像数据上下颠倒以及调用RGB2YUV函数。最后,将YUV数据写入文件并展示转换前后图像对比。
摘要由CSDN通过智能技术生成

TGA转YUV
【前期准备】得到TGA文件
通过https://convertio.co/zh/tga-converter/将GIF文件转换为TGA文件,选取其中一幅
【程序思路】
1.打开文件
2.建立结构体-头文件信息,并初始化
3.判断颜色表是否存在
a存在,则
建立结构体-颜色表,并初始化
计算offset,恢复bgr值
b不存在,则
计算offset,读取bgr值
4.图像数据上下颠倒
5.调用RGB2YUV函数完成转换
6.y,u,v写入yuv文件
7.判断并释放内存
8.关闭文件

【代码】
tga2yuv.cpp

#include "stdafx.h"
#include <stdio.h>
#include <malloc.h>
#include <iostream>
using namespace std;
#include "tga2yuv.h"

struct TGA_HEADER
{
 unsigned short IDlength;//图像信息字段长度
 unsigned short ImageType;//图像类型
 unsigned short ColorMapLength;//颜色表长度
 unsigned char ColorMapBits;//颜色表项位数
 unsigned short Width;
 unsigned short Height;
 unsigned char bitsPerPixel;//像素位数
}HEADER;

struct COLOR_MAP
{
 unsigned char R,G,B;
};

void STRUCTTGA(FILE *Tfile)
{
 unsigned char typeHeader[18] = { 0 };
 fread(typeHeader, sizeof(unsigned char), 18, Tfile);
 HEADER.IDlength = typeHeader[0];
 HEADER.ImageType = typeHeader[2];
 HEADER.ColorMapLength = (typeHeader[6] << 8) + typeHeader[5];
 HEADER.ColorMapBits = typeHeader[7];
 HEADER.Width = (typeHeader[13] << 8) + typeHeader[12];
 HEADER.Height = (typeHeader[15] << 8) + typeHeader[14];
 HEADER.bitsPerPixel = (typeHeader[17] << 8) + typeHeader[16];
}

//颜色表数据
void COLORMAPDATA(unsigned char *ColorMapBuffer, struct COLOR_MAP *COLORMAP,int offset,int Len)
{
 int j = 0;
 for (int i = 0; i <Len; i++)
 {
  COLORMAP[i].B=ColorMapBuffer[j];
  COLORMAP[i].G = ColorMapBuffer[j+1];
  COLORMAP[i].R = ColorMapBuffer[j+2];
  j += 3;
 }
}

int main(int argc, char *argv[])
{
 FILE *tgaFile = NULL, *yuvFile = NULL;
 char *tgaFileName = argv[1];
 char *yuvFileName = argv[2];
 unsigned short width = 0, height = 0, pixel = 0,ColorPixel=0;
 int offset = 0;
 int W = 0;
 errno_t err;
 err = fopen_s(&tgaFile, tgaFileName, "rb");
 if (err == 0)//打开tga文件
  printf("The file\t%s\t open sucess \n", tgaFileName);
 else
  printf("The file\t%s\t open fail\n", tgaFileName);
 err = fopen_s(&yuvFile, yuvFileName, "wb");
 if (err == 0)//打开yuv文件
  printf("The file\t%s\t open sucess \n", yuvFileName);
 else
  printf("The file\t%s\t open fail\n", yuvFileName);
  //数组初始化
 STRUCTTGA(tgaFile); 
 pixel = HEADER.bitsPerPixel / 8;
 ColorPixel = HEADER.ColorMapBits / 8;
 int Type = HEADER.ImageType;
 int Length = HEADER.ColorMapLength;
 if ((HEADER.Width % 2) == 0)
  width = HEADER.Width;
 else
  width = HEADER.Width; +1;
 if ((HEADER.Height % 2) == 0)
  height = HEADER.Height;
 else
  height = HEADER.Height + 1;
 printf("W=%d\n", width);
 printf("H=%d\n",height);
 //四个动态内存区指针
 unsigned char* tgaBuffer = NULL;
 unsigned char* rgbBuffer = NULL;
 unsigned char* yBuffer = NULL;
 unsigned char* uBuffer = NULL;
 unsigned char* vBuffer = NULL;
 unsigned char* ColorBuffer = NULL;
 unsigned char *ColorMapBuffer = NULL;
//分配动态内存
 yBuffer = (unsigned char *)malloc(width*height);
 uBuffer = (unsigned char *)malloc(width*height / 4);
 vBuffer = (unsigned char *)malloc(width*height / 4);
 int i, j, b = 0, g = 1, r = 2;
 if (Type == 1)//有颜色表
 {
 tgaBuffer = (unsigned char *)malloc(width*height*ColorPixel);
  rgbBuffer = (unsigned char *)malloc(width*height*ColorPixel);
  
  struct COLOR_MAP *COLORMAP = (struct COLOR_MAP*)malloc(Length*sizeof(struct COLOR_MAP));
  ColorMapBuffer = (unsigned char *)malloc(3*Length);
  fseek(tgaFile,18, SEEK_SET);
  fread(ColorMapBuffer, sizeof(unsigned char), 3*Length,tgaFile);
  COLORMAPDATA(ColorMapBuffer, COLORMAP, offset, Length);//调色盘数据初始化
  ColorBuffer = (unsigned char *)malloc(width*height*pixel);
  offset = 18 + HEADER.IDlength + HEADER.ColorMapLength * 3;
  fseek(tgaFile, offset, SEEK_SET);
  fread(ColorBuffer, sizeof(unsigned char), width*height*pixel, tgaFile);
  for (i = 0; i < width*height; i++)
  {
   tgaBuffer[b] = COLORMAP[ColorBuffer[i]].B;
   tgaBuffer[g] = COLORMAP[ColorBuffer[i]].G;
   tgaBuffer[r] = COLORMAP[ColorBuffer[i]].R;
   b += 3;
   g += 3;
   r += 3;
  }
  free(COLORMAP);
  W = width * ColorPixel;
  for (i = 0; i < height; i++)//图像上下颠倒
   for (j = 0; j < W; j++)
   {
    rgbBuffer[W*i + j] = tgaBuffer[W*(height - 1 - i) + j];
   }
 }
if(Type==2)//无颜色表
 {
  rgbBuffer = (unsigned char *)malloc(width*height*3);
  tgaBuffer = (unsigned char *)malloc(width*height*3);
  offset = 18 + HEADER.IDlength;
  fseek(tgaFile,offset, SEEK_SET);
  switch (pixel)
  {
  case 3: //3字节
   fread(tgaBuffer, sizeof(unsigned char), width*height*pixel, tgaFile);
   break;
  case 4: //4字节
   unsigned char* tgaBuffer1 = NULL;
   tgaBuffer1 = (unsigned char *)malloc(width*height*pixel);
   fread(tgaBuffer1, sizeof(unsigned char), width*height*pixel, tgaFile);
   int b0 = 0, b1 = 0;
   for(i=0;i<height;i++)
    for (j = 0; j < width; j++)
    {
     tgaBuffer[b0] = tgaBuffer1[b1];
     tgaBuffer[b0+1] = tgaBuffer1[b1+1];
     tgaBuffer[b0+2] = tgaBuffer1[b1+2];
     b0 += 3;
     b1 += 4;
    }
   free(tgaBuffer1);   
  }
  for (i = 0; i < height; i++)
   for (j = 0; j <width*3; j++)
   {
    rgbBuffer[width*3*i+j] = tgaBuffer[width*3*(height-1-i)+j];
   }
 }
 //调用RGB2YUV函数实现转换
 if ((RGB2YUV(rgbBuffer, yBuffer, uBuffer, vBuffer, width, height)) == 0)
  printf("changed successfully");
 else
 {
  printf("fail");
  exit(1);
 }
 //动态内存写入yuv
 fwrite(yBuffer, sizeof(unsigned char), width*height, yuvFile);
 fwrite(uBuffer, sizeof(unsigned char), width*height / 4, yuvFile);
 fwrite(vBuffer, sizeof(unsigned char), width*height / 4, yuvFile);
 //释放内存,关闭文件
 free(yBuffer);
 free(uBuffer);
 free(vBuffer);
 if(tgaBuffer)
  free(tgaBuffer);
 if (ColorBuffer)
  free(ColorBuffer);
 if(rgbBuffer)
  free(rgbBuffer);
 if (ColorMapBuffer)
  free(ColorMapBuffer);
 fclose(tgaFile);
 fclose(yuvFile);
 system("pause");
 return 0;
}

rgb2yuv.cpp

#include <iostream>
#include "tga2yuv.h"
#include "stdafx.h"
static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
static float RGBYUV01684[256], RGBYUV03316[256];
static float RGBYUV04187[256], RGBYUV00813[256];
int RGB2YUV(void* rgb, void* y_out, void* u_out, void* v_out, int W, int H)
{
 unsigned char *b = NULL, *g = NULL, *r = NULL;
 unsigned char *y, *u, *v;
 b = (unsigned char *)rgb;
 y = (unsigned char *)y_out;
 u = (unsigned char *)u_out;
 v = (unsigned char *)v_out;
 
 InitLookupTable();//调用数据表
 int i, j;
 //亮度信号转换
 for (i = 0; i < W*H; i++)
 {
  g = b + 1;
  r = b + 2;
  *y = (unsigned char)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
  b += 3;
  y++;
 }
 //色差信号转换
 b = (unsigned char *)rgb;
 for (j = 0; j < H; j++)
 {
 for (i = 0; i < W; i++)
  {
   g = b + 1;
   r = b + 2;
   if (i % 2 == 0 && j % 2 == 0)
   {
   *u = (unsigned char)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);
    *v = (unsigned char)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
    u++;
    v++;
   }
   b += 3;
  }
 }
 return  0;
}
 void InitLookupTable()
{
 int i;
 for (i = 0; i < 256; i++) 
 {
 RGBYUV02990[i] = (float)0.2990 * i;
  RGBYUV05870[i] = (float)0.5870 * i;
  RGBYUV01140[i] = (float)0.1140 * i;
  RGBYUV01684[i] = (float)0.1684 * i;
  RGBYUV03316[i] = (float)0.3316 * i;
  RGBYUV04187[i] = (float)0.4187 * i;
  RGBYUV00813[i] = (float)0.0813 * i;
 }
}

tga2yuv.h

int RGB2YUV(void* rgb, void* y_out, void* u_out, void* v_out, int W, int H);
void InitLookupTable();

【实验结果】
实验结果
图像对比,都是截图所得,图像实际没有大小差异
yuv图像
yuv文件
原gif图像的截图(没有合适的图用于转换)
gif的截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值