本文受了https://blog.csdn.net/m0_46340275/article/details/105476139 的启发。
bmp的格式是RGBRGB.....排列下来的,每个像素的三个分量靠在一起,描述完一个像素,接着描述下一个像素。
tif的格式更多样。通常的格式也是BGRBGR.....(次序与bmp相反)排列下来的,但偶尔有一些tif文件采用RRRRRR.......GGGGG.........BBBBB.....的安排。还有的tif文件内容是压缩过的。。。。这里我们只考虑三个颜色分量靠在一起的情况。
下面的例子是一个tif文件,宽896,高608,三个分量。这里先把其内容取出,并交换RB的位置,然后保存为.rgb文件。再给这个rgb文件加上头,形成bmp。
#include<iostream>
#include<fstream>
#include<cmath>
const int cnst_iWidth = 896;//图宽
const int cnst_iHeight = 608;
const int cnst_iChan = 3;//RGB三通道
#pragma pack(2)
struct bmpHeader {
short type;
unsigned int size;
unsigned int reserved ;
unsigned int offbit;
public:
bmpHeader()
{
type=0 ;
size=0 ;
reserved=0 ;
offbit=0 ;
}
};//文件头
struct bmpInfo {
unsigned int size ;
unsigned int width ;
unsigned int height;
short planes;
unsigned int bitcount;
unsigned int compression;
unsigned int sizeimage;
unsigned int XP;
unsigned int YP;
unsigned int clr ;
unsigned int clrsig ;
public:
bmpInfo()
{
size=40 ;
width=cnst_iWidth ;
height= cnst_iHeight;
planes=1 ;
bitcount=24 ;
compression=0;
sizeimage=0;
XP=0 ;
YP=0 ;
clr=0 ;
clrsig=0 ;
}
};//信息头
int rgb2bmp(bmpHeader*, bmpInfo*);
using namespace std;
const char*pathin = "earthRGBRGB.tif";
const char*pathout = "earth.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 = cnst_iWidth * cnst_iHeight * cnst_iChan + 54;
head.offbit = 54;
info.size = 40;
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)
{
unsigned char ucTmp = data[i];
data[i] = data[i + 2];
data[i + 2] = ucTmp;
}
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;
}
const char*pathbmp = "earthRGBRGB.bmp";
unsigned char*bufferrgb = new unsigned char[cnst_iWidth * cnst_iHeight * cnst_iChan ];
int rgb2bmp(bmpHeader*A,bmpInfo*B)
{
ifstream rgb(pathout, ios::binary);
ofstream bmp(pathbmp, ios::binary);
rgb.read((char*)bufferrgb, cnst_iWidth * cnst_iHeight * cnst_iChan);
bmp.write((char*)A, 14);
bmp.write((char*)B, 40);
bmp.write((char*)bufferrgb, cnst_iWidth * cnst_iHeight * cnst_iChan);
bmp.close();
rgb.close();
system("pause");
return 0;
}
原tif文件
新的bmp文件:
两图上下翻转,这是因为bmp把图片最底部一行的像素放在文件的前面,而图片最顶部的一行放在文件后面。