⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bmpio.cpp

📁 数字图像处理的程序
💻 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 + -