TGA文件转YUV文件(C++实现)

算法

1、读取TGA文件文件头,查看颜色表、图像属性。
2、根据颜色表和文件属性,开辟存储空间,动态分配内存
3、根据颜色表和文件属性,判断颜色表是否存在,找到图像数据首地址,颜色表偏移量等。
4、若有颜色表,读取颜色表数据
5、根据图像数据和颜色表、图像属性,从图像数据中读取RGB分量
6、RGB分量向YUV转换
7、输出

一、文件头读取

unsigned char fileheader[18];
 fread(fileheader, sizeof(unsigned char), 18, fpi);
 int width = fileheader[12] + fileheader[13] * 256;
 int height = fileheader[14] + fileheader[15] * 256;
 int offset=0;
 int bitdepth = 24;//描述一个像素在图像中占的比特数
 bool colortable = 0;
 if (fileheader[0] == 0)
 {
  offset = 18;
 }
 if (fileheader[0] != 0 )
 {
  offset = 18+fileheader[0];
 }
 if(fileheader[1] != 0)
 {
  offset = offset + fileheader[5] + fileheader[6] * 256;
  bitdepth = fileheader[7];
  colortable = 1;
 }

二、空间开辟

fseek(fpi,offset,0);
 unsigned char *R = (unsigned char*)malloc(width*height);
 unsigned char *G = (unsigned char*)malloc(width*height);
 unsigned char *B = (unsigned char*)malloc(width*height);
 unsigned char *RGB = (unsigned char*)malloc(width*height * bitdepth/8);
 unsigned char *YUV = (unsigned char*)malloc(width*height * 3 / 2);
 unsigned char *Y = (unsigned char*)malloc(width*height);
 unsigned char *U = (unsigned char*)malloc(width*height / 4);
 unsigned char *V = (unsigned char*)malloc(width*height / 4);
 unsigned char *Rr = (unsigned char*)malloc(width*height);
 unsigned char *Gr = (unsigned char*)malloc(width*height);
 unsigned char *Br = (unsigned char*)malloc(width*height);
 unsigned char *TABLE = (unsigned char*)malloc((fileheader[5] + fileheader[6] * 256)*fileheader[7]/8);
 fread(RGB, sizeof(unsigned char), height*width *  bitdepth / 8, fpi);

三&四&五

写代码的时候才发现这三步是写在一起的

if (colortable ==0)
 {
  for (int i = 0; i < height*width * 3; i++)
  {
   if (i % 3 == 0) { B[i / 3] = RGB[i]; }
   if (i % 3 == 1) { G[i / 3] = RGB[i]; }
   if (i % 3 == 2) { R[i / 3] = RGB[i]; }
  }
 }
 if (colortable == 1)
 {
  fseek(fpi, fileheader[3], 0);
  fread(TABLE, fileheader[7] / 8, fileheader[5] + fileheader[6] * 256, fpi);
  for (int i = 0; i < height*width * 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]; }
  }
 }
 fclose(fpi);
 //翻转像素矩阵
 for (int i = 0; i < height; i++)
 {
  for (int j = 0; j < width; j++)
  {
   Rr[i * 256 + j] = R[(height-1- i) * 256 + j];
   Gr[i * 256 + j] = G[(height-1- i) * 256 + j];
   Br[i * 256 + j] = B[(height-1- i) * 256 + j];
  }
 }

六、RGB2YUV

在我之前的文章中也有写

 //2YUV
 for (int i = 0; i < height*width; i++)
 {
  YUV[i] = (unsigned char)(0.299*Rr[i] + 0.587*Gr[i] + 0.114*Br[i]);
  Y[i] = YUV[i];
 }
 int a = 0;
 for (int i = 0; i < height*width / 4; i++)
 {
  if (a % (height*2) >= height)
  {
   a = a + height;
  }
  YUV[height*width + i] = (unsigned char)(-0.1684*Rr[a] - 0.3316*Gr[a] + 0.5*Br[a]) + 128;
  U[i] = YUV[height*width + i] - 128;
  a = a + 2;
 }
 a = 0;
 for (int i = 0; i < height*width / 4; i++)
 {
  if (a % (height * 2)>= height)
  {
   a = a + height;
  }
  YUV[height*width * 5 / 4 + i] = (unsigned char)(0.5*Rr[a] - 0.4187*Gr[a] - 0.0813*Br[a]) + 128;
  V[i] = YUV[height*width * 5 / 4 + i] - 128;
  a = a + 2;
 }
 fwrite(YUV, sizeof(unsigned char), height*width * 3 / 2, fpo);
 fclose(fpo);

其实在最后写完程序开始写博客的时候才能发现很多写代码的时候思维不清晰的地方,转yuv也没有写成函数的形式。

你可能感兴趣的:(TGA文件转YUV文件(C++实现))