tiff转bmp的实现

tiff文件格式内容见之前的文章
本次实验,自己用ps做了一个160*90的未压缩图像,预览图如下
tiff转bmp的实现_第1张图片
由于rgb本身就是倒着存的,希望得到一个倒过来的图像
黑底白字便于对着二进制文件找错,实现如下:

header.h

该文件里声明了转换为bmp所要用的文件头和信息头

#ifndef HEADER_H
#define HEADER_H
#include"stdafx.h"
#include
#include
#include

#pragma pack(2)
class bmpHeader {
public:
	short type=0 ;
	unsigned int size=0 ;
	unsigned int reserved=0 ;
	unsigned int offbit=0 ;
};//文件头
class bmpInfo {
public:
	unsigned int size=40 ;
	unsigned int width=160 ;
	unsigned int height=90;
	short planes=1 ;
	unsigned int bitcount=24 ;
	unsigned int compression=0;
	unsigned int sizeimage=0;
	unsigned int XP=0 ;
	unsigned int YP=0 ;
	unsigned int clr=0 ;
	unsigned int clrsig=0 ;
};//信息头
int rgb2bmp(bmpHeader*, bmpInfo*);

#endif // !HEADER_H

#pragma pack(2)用来防止结构体自动对齐,之前没注意这回事让我的bmp文件头出错,图片无法打开
另外这里偷懒,没有从tiff对应的目录项里读取长宽和色彩格式,在声明时就定义了,读取的实现和下文中读取图像数据过程相似

处理前的准备

#include"header.h"
using namespace std;
const char*pathin = "pic.tif";
const char*pathout = "pic.rgb";
unsigned char*buffer = new unsigned char[12];
int main()
{
	int off_img=0;//图像数据偏移量
	ifstream in(pathin, ios::binary);
	ofstream out(pathout, ios::binary);
	bmpHeader head;
	bmpInfo info;
	in.read((char*)buffer, 8);
	if (!in.is_open()) { cout << "open failed" << endl; }
	int offset = 0;//文件目录的偏移量
	offset = (buffer[7] << 24) + (buffer[6] << 16) + (buffer[5] << 8) + buffer[4];
	in.seekg(offset);
	in.read((char*)buffer, 2);
	unsigned int package_num = buffer[0] + (buffer[1] << 8);
	class package
	{
	public:
		unsigned char tag_ID[2];
		unsigned char type[2];
		unsigned char num[4];
		unsigned int data[4];
	};//定义了目录项
	
	package*a= new package[package_num];
	head.type = 0x4d42;
	head.size = 160 * 90 * 3 + 54;
	head.offbit = 54;
	info.size = 40;

手动定义了bmp文件头里的数据,对目录项的类定义也完成,接下来可以开始处理数据了

数据处理

for (int i = 0; i < package_num; i++)
	{
		in.read((char*)buffer, 12);
		for (int j = 0; j < 2; j++) { a[i].tag_ID[j] = buffer[j]; }
		for (int j = 0; j < 2; j++) { a[i].type [j]= buffer[j + 2]; }
		for (int j = 0; j < 4; j++) { a[i].data[j] = buffer[j + 8];  }
		if (a[i].tag_ID[0]== 17&&a[i].tag_ID[1]==01) {
			 off_img = (a[i].data[3] << 24) + (a[i].data[2] << 16) + (a[i].data[1] << 8) + a[i].data[0];
			cout << off_img << endl;
		}
		if (a[i].tag_ID[0] ==23&&a[i].tag_ID[1]==01) 
		{
			for (int j = 0; j < 4; j++) { cout << a[i].data[j] << endl; }
			unsigned int length = (a[i].data[3] << 24) + (a[i].data[2] << 16) + (a[i].data[1] << 8) + a[i].data[0];
			unsigned char*data = new unsigned char[length];
			in.seekg(off_img);
			in.read((char*)data, length);
			for (int i = 0; i < length; i = i + 3)
			{
				for (int j = 0; j < 3; j++)
				{
					data[i + j] = data[i + 2 - j];
				}
			}
			out.write((char*)data, length);
			out.close();
			in.seekg((i+1)*12+2+offset, ios::beg);
		}
	}
	in.close();
	rgb2bmp(&head, &info);
	system("pause");
    return 0;

把数据从buffer里读出来以后进行判断,这里没有读取所有的目录项,只读取了需要的0111和0117项,这里为16进制,代码中为10进制,上面只是把tiff的图像数据读了出来,目前文件还是rgb的状态,预览如下
tiff转bmp的实现_第2张图片
可见,图像刚好是原图倒过来,与预期的一样
接下来转换成bmp

rgb2bmp

#include"stdafx.h"
#include"header.h"
using namespace std;

const char*pathrgb = "pic.rgb";
const char*pathbmp = "pic.bmp";
unsigned char*bufferrgb = new unsigned char[160 * 90 * 3 ];
int rgb2bmp(bmpHeader*A,bmpInfo*B)
{
	
	ifstream rgb(pathrgb, ios::binary);
	ofstream bmp(pathbmp, ios::binary);
	rgb.read((char*)bufferrgb, 160 * 90 * 3);
	bmp.write((char*)A, 14);
	bmp.write((char*)B, 40);
	bmp.write((char*)bufferrgb, 160 * 90 * 3);
	bmp.close();
	rgb.close();
	system("pause");
	return 0;
}

这里由于本次使用的图像的真彩色图像所以没有调色板信息
再来看看bmp图像
tiff转bmp的实现_第3张图片
与预期一样

你可能感兴趣的:(tiff转bmp的实现)