实验二:tga格式图片转yuv格式

一、 文件格式

Tga常见的格式有非压缩RGB和压缩RGB两种格式,其他格式的我们在这里不做讲述。文件的第三个Byte位作为标记:2为非压缩RGB格式,10为压缩RGB格式。在此次实验中,分析未压缩的tga图片。

未压缩格式:

名称偏移长度说明
图像信息字段长度01本字段为1字节无符号整型,指出图像信息字段的长度,其取值范围为0~255,当它为0时,表示没有图像的信息字段
颜色表类型110表示没有颜色表,1表示颜色表存在
图像类型码21该字段总为2,表示无压缩图像
颜色表首址32颜色表首的入口索引,整型(低位-高位)
颜色表的长度52颜色表的表项总数,整型(低位-高位)
颜色表项位数71位数(bit),16代表16位TGA,24位代表24位TGA,32代表32位TGA
图像X坐标起始位置82图像左下角X坐标的整型值
图像Y坐标其实位置102图像左下角Y坐标的整型值
图像宽度122以像素为单位,图像宽度的整型
图像高度142以像素为单位,图像高度的整型
图像每像素存储占用位数162它的值为16,24或32等等,决定了该图像时TGA16,TGA24,TGA32等等
图像描述字节171bits 3-0 - 每像素对应的属性位的位数;对于TGA 16,该值为 0 或 1,对于 TGA24,该值为 0,对于 TGA 32,该值为 8。 bit 4 - 保留,必须为 0。bit 5 - 屏幕起始位置标志,0 = 原点在左下角,1 = 原点在左上角对于 truevision 图像必须为 0。bits 7-6 - 交叉数据存储标志:00 = 无交叉;01 = 两路奇/偶交叉;10 = 四路交叉;11 = 保留
图像信息字段18可变包含一个自由格式的,长度是图像由“图像信息字段”指定。它常常被忽略(即偏移 0 处值为 0 ),注意其最大可以含有 255 个字符。如果需要存储更多信息,可以放在图像数据之后
颜色表数据可变可变如果颜色类型为0,则该域不存在,否则越过该域直接读取图像颜色表规格中描述了每项的字节数,为2,3,4之一
图像数据可变可变RGB颜色数据,存放顺序为BGR,数据从图像左下角开始存储

参考:文件格式分析

二:代码部分

rgb2yuv.cpp

#include <stdio.h>
#include <iostream>
#include <malloc.h>
#include"TgaHeader.h"

int rgb2yuv(void* rgb_s, void* y_s, void* u_s, void* v_s, int W, int H)
{
	unsigned char *r = NULL, *g = NULL, *b = NULL, *rgb = NULL;
	unsigned char *y, *u, *v, *U, *V;

	rgb = (unsigned char *)rgb_s;
	y = (unsigned char *)y_s;
	u = (unsigned char *)u_s;
	v = (unsigned char *)v_s;
	
	r = (unsigned char *)malloc(sizeof(char)*(W*H));
	g = (unsigned char *)malloc(sizeof(char)*(W*H));
	b = (unsigned char *)malloc(sizeof(char)*(W*H));
	U = (unsigned char *)malloc(sizeof(char)*(W*H));
	V = (unsigned char *)malloc(sizeof(char)*(W*H));
	

	int j=0;
	for (int i = 0; i < W*H; i++)
	{
		b[i] = rgb[j];
		g[i] = rgb[j+1];
		r[i] = rgb[j+2];
		j += 3;
	}

	for (int i = 0; i < H*W; i++)
	{
		y[i] = r[i]*0.2990 + g[i]*0.5870 + b[i]*0.1140;
		U[i] = r[i]*(-0.1684) - g[i]*0.3316 + b[i]*0.5 + 128;
		V[i] = r[i]*0.5 - g[i]*0.4187 - b[i]*0.0813 + 128;
	}
	
	int k = 0;
	for (int i = 0; i < H; i = i + 2)
	{
		for (j = 0; j < W; j = j + 2)
		{
			u[k] = (U[W*i + j] + U[W*i + j + 1] + U[(i + 1)*W + j] + U[(i + 1)*W + j + 1]) / 4;
			v[k] = (V[W*i + j] + V[W*i + j + 1] + V[(i + 1)*W + j] + V[(i + 1)*W + j + 1]) / 4;
			k++;
		}
	}
	
	return 0;
}

main.cpp

#include <stdio.h>
#include <iostream>
#include <malloc.h>
#include"TgaHeader.h"

using namespace std;


struct TGA_HEADER
{
	unsigned short IDLength;
	unsigned short ImageType;
	unsigned short ColorMapLen;
	unsigned char ColorMapBits;
	unsigned int Width;
	unsigned int Height;
	unsigned char bitsPerPixel;
}TGAHEADER;


int main(int argc, char **argv)
{
	FILE *TgaFile = NULL;
	FILE *YuvFile = NULL;
	char *TgaFileName = NULL;
	char *YuvFileName = NULL;

	TgaFileName = argv[1];
	YuvFileName = argv[2];

	int Height, Width;
	int offset = 0;

	if (fopen_s(&TgaFile, TgaFileName, "rb") == 0)
		printf("The tgafile was opened: %s \n", TgaFileName);
	else printf("The tgafile cannot open: %s \n", TgaFileName);
	fopen_s(&YuvFile, YuvFileName, "wb");

	unsigned char typeHeader[18] = { 0 };
	fread(typeHeader, 1, 18, TgaFile);
	TGAHEADER.IDLength = typeHeader[0];
	TGAHEADER.ImageType = typeHeader[2];
	TGAHEADER.ColorMapLen = (typeHeader[6] << 8) + typeHeader[5];
	TGAHEADER.ColorMapBits = typeHeader[7];
	TGAHEADER.Width = (typeHeader[13] << 8) + typeHeader[12];
	TGAHEADER.Height = (typeHeader[15] << 8) + typeHeader[14];
	TGAHEADER.bitsPerPixel = (typeHeader[17] << 8) + typeHeader[16];

	unsigned short pixel = TGAHEADER.bitsPerPixel / 8;
	unsigned short ColorPixel = TGAHEADER.ColorMapBits / 8;
	Width = TGAHEADER.Width;
	Height = TGAHEADER.Height;

	printf("该tga图片的大小为: %d * %d \n", TGAHEADER.Width, TGAHEADER.Height);

	int i, j;

	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);
    tgaBuffer = (unsigned char *)malloc(Width*Height * 3);
	rgbBuffer = (unsigned char *)malloc(Width*Height * 3);

	offset = TGAHEADER.IDLength + 18;
	fseek(TgaFile, offset, SEEK_SET);
	
	switch (pixel)
	{
	case 3:
		fread(tgaBuffer, 1, Width*Height*pixel, TgaFile);
		break;
	case 4:
		unsigned char *tgaB = NULL;
		fread(tgaB, 1, Width*Height*pixel, TgaFile);

		int a = 0, b = 0;
		for (i = 0; i < Height; i++)
		{
			for (j = 0; j < Width; j++)
			{
				tgaBuffer[a] = tgaB[b];
				tgaBuffer[a + 1] = tgaB[b + 1];
				tgaBuffer[a + 2] = tgaB[b + 2];
				a += 3;
				b += 4;
			}
		}
		free(tgaB);
	}
	
	for(i=0;i<Height;i++)
		for (j = 0; j < Width * 3; j++)
		{
			rgbBuffer[Width * 3 * i + j] = tgaBuffer[Width * 3 * (Height - i - 1) + j];
		}
	
	
	if((rgb2yuv(rgbBuffer,yBuffer,uBuffer,vBuffer,Width,Height)==0))
		printf("yuvFile has finished\n");
	else
	{
		printf("error\n");
			exit(1);
	}

	fwrite(yBuffer, 1, Width*Height, YuvFile);
	fwrite(uBuffer, 1, Width*Height/4, YuvFile);
	fwrite(vBuffer, 1, Width*Height/4, YuvFile);

	free(yBuffer);
	free(uBuffer);
	free(vBuffer);
	free(tgaBuffer);
	free(rgbBuffer);
    fclose(TgaFile);
	fclose(YuvFile);
	return 0;
}

TgaHeader.h

#pragma once
int rgb2yuv(void* rgb_s, void* y_s, void* u_s, void* v_s, int W, int H);

三:实验结果

原图tga:
在这里插入图片描述转换结果yuv:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值