数据压缩实验报告2 TGA转YUV

写在前面:
由于大二上学习C++时没有进行充分的练习,这次的实验先是自己想了很久但是无果,最后只能参考同学的代码。看不懂的地方和同学讨论并逐渐理解。感觉自己的情况就是知道大概的思路方法,但是不知道如何用代码实现。在没有参考的前提下没法自己写出完整的代码,还是需要多思考多练习。

代码:
pga_struct.h(用来创建pga文件的结构体)

#pragma once
#include <windows.h>
#include <iostream>
#include <fstream>
using namespace std;

//TGA文件结构体
typedef struct TgaHeader 
{
    BYTE IDLength;        
    BYTE ColorMapType;    
    BYTE ImageTypeCode;     
} TGAHEAD;

typedef struct TgaHeader_Color 
{
    WORD ColorMapStart;      
    WORD ColorMapLength;     
    BYTE ColorMapDepth;      
}TGAHEAD_Color;

typedef struct TgaHeader_Info
{
    WORD XStart;        
    WORD YStart;        
    WORD w2;           
    WORD h2;         
    BYTE PixelDepth;      
    BYTE ImageDescriptor; 
}TgaHeader_Info;

void Read_rgb(ifstream& file, unsigned char* R_buffer, unsigned char* G_buffer, unsigned char* B_buffer, int h1, int w1);
void Read_rgb_ColorMap(ifstream& file, TGAHEAD_Color& color, unsigned char* R_buffer, unsigned char* G_buffer, unsigned char* B_buffer, int h1, int w1);

rgb2yuv.h(定义rgb2yuv.cpp中所需要的函数)

#pragma once
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <malloc.h>
using namespace std;

extern float RGB2YUV02990[256], RGB2YUV05870[256], RGB2YUV01140[256], RGB2YUV01684[256],
RGB2YUV03316[256], RGB2YUV05000[256], RGB2YUV04187[256], RGB2YUV00813[256];

void table();
void process(int h1, int w1, unsigned char* R, unsigned char* G, unsigned char* B, unsigned char* Y, unsigned char* U, unsigned char* V);
void subsample(int h2, int w2, unsigned char* U, unsigned char* V, unsigned char* U2, unsigned char* V2);
void write(int h2, int w2, unsigned char* Y, unsigned char* U, unsigned char* V);

tga.cpp(主要包含读取rgb数据和颜色表的函数)

#include "tga_struct.h"

void Read_rgb(ifstream& file, unsigned char* R_buffer, unsigned char* G_buffer, unsigned char* B_buffer, int h1, int w1) 
{
	for (int i = h1 - 1; i >= 0; i--)
	{
		for (int j = 0; j < w1; j++)
		{
			file.read((char*)(B_buffer + (i * w1 + j)), 1);
			file.read((char*)(G_buffer + (i * w1 + j)), 1);
			file.read((char*)(R_buffer + (i * w1 + j)), 1);
		}
	}
}

void Read_rgb_ColorMap(ifstream& file, TGAHEAD_Color& color, unsigned char* R_buffer, unsigned char* G_buffer, unsigned char* B_buffer, int h1, int w1)
{
	unsigned char* Table_R = new unsigned char[color.ColorMapLength];
	unsigned char* Table_G = new unsigned char[color.ColorMapLength];
	unsigned char* Table_B = new unsigned char[color.ColorMapLength];
	unsigned char* k = new unsigned char[h1 * w1];

	// 读入颜色表
	for (int i = 0; i < color.ColorMapLength; i++)
	{
		file.read((char*)(Table_B + i), 1);
		file.read((char*)(Table_G + i), 1);
		file.read((char*)(Table_R + i), 1);
	}
	for (int i = h1 - 1; i >= 0; i--) 
	{
		for (int j = 0; j < w1; j++) {
			file.read((char*)(k + (i * w1 + j)), 1);
			*(B_buffer + (i * w1 + j)) = *(Table_B + (*(k + (i * w1 + j))));
			*(G_buffer + (i * w1 + j)) = *(Table_G + (*(k + (i * w1 + j))));
			*(R_buffer + (i * w1 + j)) = *(Table_R + (*(k + (i * w1 + j))));
		}
	}
	if (Table_R != NULL)
		delete Table_R; 
	if (Table_G != NULL) 
		delete Table_G; 
	if (Table_B != NULL) 
		delete Table_B; 
	if (k != NULL)
		delete k;
}

rgb2yuv.cpp(将rgb分量转换为yuv分量、下采样、写文件的函数)

#include "rgb2yuv.h"

void table() 
{
	for (int i = 0; i < 256; i++) {
		RGB2YUV02990[i] = (float)0.2990 * i;
		RGB2YUV05870[i] = (float)0.5870 * i;
		RGB2YUV01140[i] = (float)0.1140 * i;
		RGB2YUV01684[i] = (float)0.1684 * i;
		RGB2YUV03316[i] = (float)0.3316 * i;
		RGB2YUV05000[i] = (float)0.5000 * i;
		RGB2YUV04187[i] = (float)0.4187 * i;
		RGB2YUV00813[i] = (float)0.0813 * i;
	}
}
// 计算yuv分量的值
void process(int h1, int w1, unsigned char* R, unsigned char* G, unsigned char* B, unsigned char* Y, unsigned char* U, unsigned char* V) 
{
	float k;
	for (int i = 0; i < h1 * w1; i++) 
	{
		// 计算y分量
		k = RGB2YUV02990[*(R + i)] + RGB2YUV05870[*(G + i)] + RGB2YUV01140[*(B + i)];
		if (k > 236)
			k = 236;
		else if (k < 16)
			k = 16;
		*(Y + i) = (unsigned char)k;
		// 计算u分量
		k = -RGB2YUV01684[*(R + i)] - RGB2YUV03316[*(G + i)] + RGB2YUV05000[*(B + i)] + 128;
		if (k > 236)
			k = 236;
		else if (k < 16)
			k = 16;
		*(U + i) = (unsigned char)k;
		// 计算v分量
		k = RGB2YUV05000[*(R + i)] - RGB2YUV04187[*(G + i)] - RGB2YUV00813[*(B + i)] + 128;
		if (k > 236)
			k = 236;
		else if (k < 16)
			k = 16;
		*(V + i) = (unsigned char)k;
	}
}

//写yuv文件
void write(int h2, int w2, unsigned char* Y, unsigned char* U, unsigned char* V)
{
	ofstream Output_file;
	Output_file.open("new.yuv", ios::binary, ios::trunc);
	if (!Output_file) 
		cout << "Failed to open file" << endl;
	else {
		Output_file.write((char*)Y, h2 * w2);
		Output_file.write((char*)U, h2 * w2 / 4);
		Output_file.write((char*)V, h2 * w2 / 4);
		Output_file.close();
	}
}

// uv分量下采样
void subsample(int h2, int w2, unsigned char* U, unsigned char* V, unsigned char* U2, unsigned char* V2) 
{
	int k = 0;
	float uuu, vvv;
	for (int i = 0; i < h2 * w2 / 4; i++) {
		uuu = (float)(*(U + k) + *(U + k + 1) + *(U + k + w2) + *(U + k + 1 + w2)) / 4;
		vvv = (float)(*(V + k) + *(V + k + 1) + *(V + k + w2) + *(V + k + 1 + w2)) / 4;
		*(U2 + i) = (unsigned char)uuu;
		*(V2 + i) = (unsigned char)vvv;

		if ((i + 1) % (w2 / 2) == 0) 
			k = k + 2 + w2;
		else 
			k = k + 2;
	}
}

task2.cpp(主函数)

#include "rgb2yuv.h"
#include "tga_struct.h"

float RGB2YUV02990[256], RGB2YUV05870[256], RGB2YUV01140[256], RGB2YUV01684[256],RGB2YUV03316[256], RGB2YUV05000[256], RGB2YUV04187[256], RGB2YUV00813[256];

int main(int argc, char* argv[])
{
    unsigned char* buffer_Y = NULL, * buffer_U = NULL, * buffer_V = NULL;
    unsigned char* buffer_R = NULL, * buffer_G = NULL, * buffer_B = NULL;
    unsigned char* U2 = NULL, * V2 = NULL;

    table();
    //判断是否打开文件
    ifstream input_file;
    input_file.open(argv[1], ios::in | ios::binary);
    if (!input_file.is_open()) 
        cout << "input file not opened." << endl;

    // 定义文件头
    TGAHEAD FILE_header;
    TGAHEAD_Color FILE_header_CMap;
    TgaHeader_Info FILE_header_Info;
    // 读文件头
    input_file.read((char*)(&FILE_header), 3);
    input_file.read((char*)(&FILE_header_CMap), 5);
    input_file.read((char*)(&FILE_header_Info), 10);

    int w1 = FILE_header_Info.w2;
    int h1 = FILE_header_Info.h2;

    //建立缓冲区
    buffer_R = new unsigned char[w1 * h1];
    buffer_G = new unsigned char[w1 * h1];
    buffer_B = new unsigned char[w1 * h1];
    buffer_Y = new unsigned char[w1 * h1];
    buffer_U = new unsigned char[w1 * h1];
    buffer_V = new unsigned char[w1 * h1];
    //读rgb文件的内容
    Read_rgb(input_file, buffer_R, buffer_G, buffer_B, h1, w1);
    //计算yuv分量的值
    process(h1, w1, buffer_R, buffer_G, buffer_B, buffer_Y, buffer_U, buffer_V);
    U2 = new unsigned char[int(w1 * h1 / 4)];
    V2 = new unsigned char[int(w1 * h1 / 4)];
    //下采样
    subsample(h1, w1, buffer_U, buffer_V, U2, V2);
    write(h1, w1, buffer_Y, U2, V2);
    //关闭文件,释放缓冲区
    input_file.close();
    if (buffer_Y != NULL) 
        delete buffer_Y; 
    if (buffer_U != NULL) 
        delete buffer_U; 
    if (buffer_V != NULL)
        delete buffer_V; 
    if (U2 != NULL)
        delete U2; 
    if (V2 != NULL) 
        delete V2; 
    if (buffer_R != NULL) 
        delete buffer_R; 
    if (buffer_G != NULL) 
        delete buffer_G; 
    if (buffer_B != NULL)  
        delete buffer_B; 
}

运行结果:在这里插入图片描述原本的TGA图像文件

在这里插入图片描述左上角的墙与原图有色差,眼睛部分明显有被锐化的感觉

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值