📄 bmpio.cpp
字号:
//--------------------------------------------------------------------------
// bmpio.cpp
//
// All copyrights reserved by ECNU
//--------------------------------------------------------------------------
// Abstract:
// BMP格式图像文件的I/O
//--------------------------------------------------------------------------
// Hostory:
// ver1.0.0
//--------------------------------------------------------------------------
// Contents:
// int CDIB::readFile(CString &filename)
// int CDIB::writeFile(CString &filename)
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "cdib.h"
#include <malloc.h>
#include <memory.h>
/*--------------------------------------------------------------------------
函数名 CDIB::readFileBMP
形式 int CDIB::_readFileBMP(CString &filename)
---------------------------------------------------------------------------*/
int CDIB::readFile(CString &filename)
{
CFile file;
BITMAPFILEHEADER bmf;
BITMAPINFOHEADER bmih;
BITMAPINFO *head;
UINT read_size;
int w, h, nbit, cmap_size, body_size;
BYTE *body;
//---------------------------------------------------------
// check参数
if (filename.IsEmpty()) {
return -1;
}
//---------------------------------------------------------
// 打开文件
if (file.Open(filename.GetBuffer(1),CFile::modeRead | CFile::shareDenyWrite)==FALSE) {
return -1;
}
//---------------------------------------------------------
// 读入BMP文件头
read_size=(UINT)sizeof(BITMAPFILEHEADER);
if (file.Read(&bmf, read_size)!=read_size) {
file.Close();
return -1;
}
//---------------------------------------------------------
// 读入BMP信息头
read_size=(UINT)sizeof(BITMAPINFOHEADER);
if (file.Read(&bmih, read_size)!=read_size) {
file.Close();
return -1;
}
if (bmih.biSize!=sizeof(BITMAPINFOHEADER)) {
file.Close();
return -1;
}
//---------------------------------------------------------
// 位图信息头的解析,以及调色板、图像数据的读入用领域的生成
// 图像大小和data bit数的取得
w=bmih.biWidth;
h=bmih.biHeight;
if (h<0) h=-h;
nbit=bmih.biBitCount;
if (nbit!=1 && nbit!=4 && nbit!=8 && nbit!=16 && nbit!=24 && nbit!=32) {
file.Close();
return -1;
}
// 图像数据大小的计算
if (bmih.biCompression==BI_RLE4 || bmih.biCompression==BI_RLE8) {
body_size=bmih.biSizeImage;
} else {
body_size=(int)((w*nbit+31)/32)*4*h;
}
if (body_size<=0) {
file.Close();
return -1;
}
// 调色板大小的计算
if (nbit==1 || nbit==4 || nbit==8) {
cmap_size=bmf.bfOffBits-sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER);
if (cmap_size%4!=0) {
file.Close();
return -1;
}
} else if (bmih.biCompression==BI_BITFIELDS) {
cmap_size=sizeof(DWORD)*3;
} else {
cmap_size=0;
}
// 调色板暂时读入领域的生成
if ((head=(BITMAPINFO*)malloc(sizeof(BITMAPINFOHEADER)+cmap_size))==NULL) {
file.Close();
return -1;
}
// 图像数据暂时读入领域的生成
if ((body=(BYTE*)malloc(body_size))==NULL) {
file.Close();
free(head);
return -1;
}
//---------------------------------------------------------
// BMP信息头拷贝到作用领域。
// 读入调色板。
// 像素bit数大于16时,即时是BI_RGB,跳过调色板部分。
memcpy(head, &bmih, sizeof(BITMAPINFOHEADER));
if (cmap_size>0) {
if (file.Read(head->bmiColors, cmap_size)!=(UINT)cmap_size) {
file.Close();
free(head);
free(body);
return -1;
}
} else if (nbit>=16 && bmih.biCompression==BI_RGB) {
int irregular_cmap_size;
irregular_cmap_size=bmf.bfOffBits-sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER);
if (irregular_cmap_size>0) {
file.Seek(irregular_cmap_size, CFile::current);
}
}
//---------------------------------------------------------
// 读入图像数据
if (file.Read(body, body_size)!=(UINT)body_size) {
file.Close();
free(head);
free(body);
return -1;
}
//---------------------------------------------------------
// 生成图像对象
if (nbit==4) {
if (create(w, h, 8)!=0) {
file.Close();
free(head);
free(body);
return -1;
}
} else if (nbit==16 || nbit==32) {
if (create(w, h, nbit, bmih.biCompression)!=0) {
file.Close();
free(head);
free(body);
return -1;
}
} else {
if (create(w, h, nbit)!=0) {
file.Close();
free(head);
free(body);
return -1;
}
}
//---------------------------------------------------------
// 把从图像文件读入的调色板拷贝到图像对象里
if (nbit<=8) {
memcpy(m_bmi->bmiColors, head->bmiColors, cmap_size);
if (::SetDIBColorTable(m_dc->GetSafeHdc(), 0, cmap_size/4,m_bmi->bmiColors)==0) {
file.Close();
free(head);
free(body);
return -1;
}
} else if (bmih.biCompression==BI_BITFIELDS) {
memcpy(m_bmi->bmiColors, head->bmiColors, cmap_size);
}
//---------------------------------------------------------
// 用::StretchDIBits把读入作用域里的信息头和调色板拷贝到
// 图像对象里。BMP像素bit数转化、topdown转化、RLE解压缩由
// ::StretchDIBits来完成。
if (::StretchDIBits(m_dc->GetSafeHdc(), 0, 0, w, h, 0, 0, w, h,
body, head, DIB_RGB_COLORS, SRCCOPY)==GDI_ERROR) {
file.Close();
free(head);
free(body);
return -1;
}
free(head);
free(body);
if (isGray()) m_color_type=IMG_GRAY;
else m_color_type=IMG_RGB;
return 0;
}
/*--------------------------------------------------------------------------
函数名 CDIB::writeFileBMP
形式 int CDIB::_writeFileBMP(CString &filename)
---------------------------------------------------------------------------*/
int CDIB::writeFile(CString &filename)
{
CFile file;
int colors;
BITMAPFILEHEADER bmf;
//---------------------------------------------------------
// check参数
if (filename.IsEmpty()) {
return -1;
}
if (m_img==NULL) {
return -1;
}
//---------------------------------------------------------
// 打开文件
if (file.Open(filename.GetBuffer(1),
CFile::modeCreate |
CFile::modeWrite | CFile::shareExclusive)==FALSE) {
return -1;
}
//---------------------------------------------------------
// 文件头的生成和保存
bmf.bfType=((WORD)('M'<<8)|'B');
bmf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
if (m_img->nbit==1 || m_img->nbit==8) {
colors=m_bmi->bmiHeader.biClrUsed;
if (colors==0) {
if (m_img->nbit==1) colors=2;
else colors=256;
}
bmf.bfSize+=sizeof(RGBQUAD)*colors;
} else if (m_bmi->bmiHeader.biCompression==BI_BITFIELDS) {
bmf.bfSize+=sizeof(DWORD)*3;
}
// } else {
// bmf.bfSize+=sizeof(RGBQUAD);
// }
bmf.bfOffBits=bmf.bfSize;
bmf.bfSize+=m_img->x_len*m_img->h;
bmf.bfReserved1=bmf.bfReserved2=0;
try {
file.Write(&bmf, sizeof(BITMAPFILEHEADER));
} catch (CFileException *e) {
e->Delete();
file.Close();
return -1;
}
//---------------------------------------------------------
//
BYTE *swapbuf;
int y, hh;
m_bmi->bmiHeader.biHeight= -m_bmi->bmiHeader.biHeight;
if ((swapbuf=(BYTE*)malloc(m_img->x_len))==NULL) {
file.Close();
return -1;
}
hh=m_img->h/2;
for (y=0 ; y<hh ; y++) {
memcpy(swapbuf, *(m_img->buff+y), m_img->x_len);
memcpy(*(m_img->buff+y), *(m_img->buff+(m_img->h-y-1)), m_img->x_len);
memcpy(*(m_img->buff+(m_img->h-y-1)), swapbuf, m_img->x_len);
}
//---------------------------------------------------------
// 信息头和调色板的保存
try {
if (m_img->nbit==1 || m_img->nbit==8) {
file.Write(m_bmi, sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*colors);
} else if (m_bmi->bmiHeader.biCompression==BI_BITFIELDS) {
file.Write(m_bmi, sizeof(BITMAPINFOHEADER)+sizeof(DWORD)*3);
} else {
file.Write(m_bmi, sizeof(BITMAPINFOHEADER));
}
} catch (CFileException *e) {
e->Delete();
free(swapbuf);
file.Close();
return -1;
}
//---------------------------------------------------------
// 图像data的保存
try {
file.Write(*(m_img->buff), m_img->x_len*m_img->h);
} catch (CFileException *e) {
e->Delete();
free(swapbuf);
file.Close();
return -1;
}
//---------------------------------------------------------
// 把BMP data转化成 topdown
m_bmi->bmiHeader.biHeight= -m_bmi->bmiHeader.biHeight;
hh=m_img->h/2;
for (y=0 ; y<hh ; y++) {
memcpy(swapbuf, *(m_img->buff+y), m_img->x_len);
memcpy(*(m_img->buff+y), *(m_img->buff+(m_img->h-y-1)), m_img->x_len);
memcpy(*(m_img->buff+(m_img->h-y-1)), swapbuf, m_img->x_len);
}
free(swapbuf);
file.Close();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -