TGA格式文件转化为YUV文件

因为之前分析的PNG格式文件数据有压缩,不太好提取数据,所以这一次尝试将TGA格式的文件转化为YUV格式的文件。
TGA文件的文件头中包括图片类型、图片的宽高数据、每像素占用的bit位数等数据,本次的转化程序只支持图片类型为2也就是无压缩无调色板数据的TGA文件,并且每像素占用的bit位数为24位。
程序的设计思路是:
1、先建立一个TGA文件的头文件结构体,用于读取头文件数据。
2、从头文件中获得图片长宽数据,因为只支持类型为2的文件,在无调色板无图像信息的情况下,数据的偏移量固定为18。
3、定好偏移量后,因为TGA文件的数据是从左下角读入,也就是图片的上下是颠倒的,读取RGB数据时需要将图片正向读入。
4、之前写过RGB2YUV的程序,因此在读入RGB数据后,可以直接调用转化为YUV图像。
程序如下:
头文件结构体函数:

#ifndef HEAD_DEFINE_H_INCLUDED
#define HEAD_DEFINE_H_INCLUDED
typedef struct{
    char IDlength = 0;
    char Colormaptype = 0;
    char Imagetypecode = 0;
    short Colormapoffset = 0;
    short Colormaplength = 0;
    char Colormapdepth = 0;
    short Xorigin = 0;
    short Yorigin = 0;
    short Width = 0;
    short Height = 0;
    char Bitsperpixel = 0;
    char Imagedescriptor = 0;
}Headfile;
void initialHeadfile(unsigned char* buffer, Headfile* H){
    H->IDlength = buffer[0];
    H->Colormaptype = buffer[1];
    H->Imagetypecode = buffer[2];
    H->Colormapoffset = (buffer[3]<<4) + buffer[4];
    H->Colormaplength = (buffer[5]<<4) + buffer[6];
    H->Colormapdepth = buffer[7];
    H->Xorigin = (buffer[8]<<4) + buffer[9];
    H->Yorigin = (buffer[10]<<4) + buffer[11];
    H->Width = (buffer[13]*256) + buffer[12];
    H->Height = (buffer[15]*256) + buffer[14];
    H->Bitsperpixel = buffer[16];
    H->Imagedescriptor = buffer[17];
}
#endif // HEAD_DEFINE_H_INCLUDED

RGB2YUV文件如下:

#ifndef RGB2YUV_H_INCLUDED
#define RGB2YUV_H_INCLUDED
#include"iostream"
#include"math.h"
#include"stdio.h"
#include"malloc.h"
using namespace std;
void transf(unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* rgb, FILE* out, int W, int H){
    unsigned char* ybuffer = new unsigned char[W*H];
    unsigned char* ubuffer = new unsigned char[W*H/4];
    unsigned char* vbuffer = new unsigned char[W*H/4];
    unsigned char* u444buffer = new unsigned char[W*H];
    unsigned char* v444buffer = new unsigned char[W*H];
    int i;
    int j;
    int coun=0;
    for(i = 0; i < W*H; i++){
        b[i] = rgb[3*i];
        g[i] = rgb[3*i+1];
        r[i] = rgb[3*i+2];
    }
    for(i = 0; i < W*H; i++){
        ybuffer[i] = ((66*r[i] + 129*g[i] + 25*b[i]) >> 8) + 16;
        u444buffer[i] = ((-38*r[i] - 74*g[i] + 112*b[i]) >> 8) + 128;
        v444buffer[i] = ((112*r[i] - 94*g[i] - 18*b[i]) >> 8) + 128;
    }
    for (int i = 0; i < H; i += 2)
 {
  for (int j = 0; j < W; j += 2)
  {
   ubuffer[i/2*W/2 + j/2] = u444buffer[i * W + j];
   vbuffer[i/2*W/2 + j/2] = v444buffer[i * W + j];
  }
 }
    //for(i = 0; i < H; i++){
    //    for(j = 0; j < W; j++){
    //        ybuffer[i*W+j] = ((66*r[i*W+j] + 129*g[i*W+j] + 25*b[i*W+j]) >> 8) + 16;
    //        if((!(i%2))&&(!(j%2))){
    //            ubuffer[coun] = ((-38*r[coun] - 74*g[coun] + 112*b[coun]) >> 8) + 128;
    //            vbuffer[coun] = ((112*r[coun] - 94*g[coun] - 18*b[coun]) >> 8) + 128;
    //            coun++;
    //            cout<<i<<" "<<j<<endl;
    //        }
    //    }
    //}
    fwrite(ybuffer, sizeof(unsigned char), W*H, out);
 fwrite(ubuffer, sizeof(unsigned char), W*H/4, out);
 fwrite(vbuffer, sizeof(unsigned char), W*H/4, out);
 cout<<"yuv file settled down"<<endl;
 delete ybuffer;
 delete ubuffer;
 delete vbuffer;
}
#endif // RGB2YUV_H_INCLUDED

这里有一个小疑问,被注释掉的代码是我之前的思路,但输出的图像的U和V数据似乎有问题,但并没有看出来哪里错了。
main函数如下:

#include"iostream"
#include"math.h"
#include"stdio.h"
#include"malloc.h"
#include"head_define.h"
#include"rgb2yuv.h"
using namespace std;
int main(int argc, char* argv[]){
    char* imgaddr = argv[1];
    char* outaddr = argv[2];
    FILE* TGAfile = fopen(imgaddr,"rb");
    FILE* YUVfile = fopen(outaddr,"w");
    int TGAfileSize;
    fseek(TGAfile, 0L, SEEK_END);
 TGAfileSize = ftell(TGAfile);
 rewind(TGAfile);
 cout<<"The tga space is "<<TGAfileSize<< endl;  //输出tga文件大小
 int offset = 18;
 unsigned char* headbuffer = new unsigned char[offset];
 fread(headbuffer, sizeof(unsigned char), offset, TGAfile);
 Headfile Header;
 initialHeadfile(headbuffer, &Header);  //初始化头文件
 if((Header.IDlength)!=0 ||(Header.Colormaptype)!=0 ||(Header.Imagetypecode)!=2 ||(Header.Bitsperpixel)!=24){
        cout<<"It is out of my ability"<<endl;
        return -1;
 }
 cout<<"The width of the image is "<<int(Header.Width)<<endl;
 cout<<"The Height of the image is "<<int(Header.Height)<<endl;
 int W = int(Header.Width);
 int H = int(Header.Height);
 unsigned char* rgbbuffer = new unsigned char[W*H*3];
 unsigned char* bbuffer = new unsigned char[W*H];
 unsigned char* gbuffer = new unsigned char[W*H];
 unsigned char* rbuffer = new unsigned char[W*H];
 unsigned char* tgabuffer = new unsigned char[TGAfileSize];
 fread(tgabuffer, sizeof(unsigned char), TGAfileSize, TGAfile);
 int i;
 int j;
 int a = 0;
 for(i = H-1; i >= 0; i--){
        for(j = 0; j < 3*W; j++){
           rgbbuffer[a] = tgabuffer[3*i*W + j];
           a++;
        }
 }
 //FILE* rgb = fopen("E:\\数据压缩奇怪的作业们\\作业3\\作业3\\2.rgb","w" );
 //fwrite(rgbbuffer, sizeof(unsigned char), 3*W*H, rgb);
 transf(rbuffer, gbuffer, bbuffer, rgbbuffer, YUVfile, W, H);  //转化为yuv文件并输出
 delete tgabuffer;
 delete rgbbuffer;
 delete rbuffer;
 delete gbuffer;
 delete bbuffer;
}

原图是这样的:
在这里插入图片描述
最终输出出来的YUV文件为:
在这里插入图片描述
程序运行后结果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值