tiff文件格式内容见之前的文章
本次实验,自己用ps做了一个160*90的未压缩图像,预览图如下
由于rgb本身就是倒着存的,希望得到一个倒过来的图像
黑底白字便于对着二进制文件找错,实现如下:
该文件里声明了转换为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的状态,预览如下
可见,图像刚好是原图倒过来,与预期的一样
接下来转换成bmp
#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;
}