位图的读写

对于计算机图形学来说,位图的读写是一个非常重要方面,位图是计算机图形和图像的桥梁

在计算机图形处理中,着色后形成的图形就转变为图像,可以用成熟的图像处理算法来处理.

是真实感图形绘制的基础

 

对位图的处理主要是了解位图的数据结构,有了对位图的数据结构的了解后,其它的一切就

是一般的读写文件的方向,下面提供一个读写的类

 

#if !defined(AFX_FG_DIB_H__873E62A0_D6E8_4151_9F0F_815768446735__INCLUDED_)
#define AFX_FG_DIB_H__873E62A0_D6E8_4151_9F0F_815768446735__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CFG_DIB : public CObject 
{
public:
 //默认构造函数
 CFG_DIB();
 //构造函数,根据图象宽和高,以及记录每个象素所需字节数来初始化
 CFG_DIB(int width, int height, int nBitCounts);
 virtual ~CFG_DIB();

public:
 HBITMAP m_hBitmap;
 LPBYTE m_lpDIBits;     //DIB位的起始位置
 LPBITMAPINFOHEADER m_lpBMPHdr;  //BITMAPINFOHEADER信息
 LPVOID m_lpvColorTable;    //颜色表信息
 HPALETTE m_hPalette;    //条调色板

private:
 DWORD m_dwImageSize;    //非BITMAPINFOHEADER或BITMAPFILEHEADER的位
 int m_nColorEntries;    //颜色表项的个数

//显示参数
public:
 CPoint m_Dest;      //目的矩形域的左上角坐标
 CSize m_DestSize;     //显示矩形的宽度和高度
 CPoint m_Src;      //原矩形左下角坐标
 CSize m_SrcSize;     //原矩形宽度和高度

public:
 void InitDestroy();       //初始化变量
 void ComputePaletteSize(int nBitCounts); //计算调色板大小
 void ComputeImage();      //计算图象大小

 //从BMP文件中读入DIB信息
 BOOL ReadFile(CFile* pFile);
 //从BMP文件中读入DIB信息,与ReadFile不同的是使用CreateSection创建位图位
 BOOL ReadSection(CFile* pFile, CDC* pDC = NULL);
 //将DIB写入文件,保存成BMP图片格式
 BOOL WriteFile(CFile* pFile);
 //创建新的位图文件,根据参数width,height,nBitCounts分配内存空间
 BOOL NewFile(int width, int height, int nBitCounts);
 //关闭位图文件
 BOOL CloseFile();

 //显示位图
 BOOL Display(CDC* pDC);

 HBITMAP CreateBitmap(CDC* pDC);    //用DIB创建DDB
 HBITMAP CreateSection(CDC* pDC = NULL);  //创建位图位数据,即象素数据
 //如果DIB没有颜色表,可以用逻辑调色板
 BOOL SetLogPalette(CDC* pDC);
 //如果DIB有颜色表,可以创建系统调色板
 BOOL SetWinPalette();
 //把DIB对象的逻辑调色板选进设备环境里,然后实现调色板
 UINT UseLogPalette(CDC* pDC);

 //得到BitmapInfoHeader的大小,包含颜色表数据
 int GetHeaderSize()
 {
  return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorEntries;
 }
 //得到图像的高度
 int GetHeight()
 {
  if(m_lpBMPHdr == NULL) return 0;
  return m_lpBMPHdr->biHeight;
 }
 //得到图像的宽度
 int GetWidth()
 {
  if(m_lpBMPHdr == NULL) return 0;
  return m_lpBMPHdr->biWidth;
 }
 //得到图像的大小
 int GetImageSize()
 {
  return m_dwImageSize;
 }
 long GetLineBit();  //得到一行的象素数
};

#endif // !defined(AFX_FG_DIB_H__873E62A0_D6E8_4151_9F0F_815768446735__INCLUDED_)

 

 

#include "stdafx.h"
#include "Dib.h"


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


CFG_DIB::CFG_DIB()
{
 m_hBitmap = NULL;
 m_hPalette = NULL;
 m_Dest.x = 0;
 m_Dest.y = 0;
 m_DestSize.cx = 0;
 m_DestSize.cy = 0;
 m_Src.x = 0;
 m_Src.y = 0;
 m_SrcSize.cx = 0;
 m_SrcSize.cy = 0;
 InitDestroy();
}

CFG_DIB::CFG_DIB(int width, int height, int nBitCounts)
{
 m_hBitmap = NULL;
 m_hPalette = NULL;
 m_Dest.x = 0;
 m_Dest.y = 0;
 m_DestSize.cx = 0;
 m_DestSize.cy = 0;
 m_Src.x = 0;
 m_Src.y = 0;
 m_SrcSize.cx = 0;
 m_SrcSize.cy = 0;
 InitDestroy();
 ComputePaletteSize(nBitCounts);     //为BITMAPINFOHEADER结构申请空间。
 m_lpBMPHdr = (LPBITMAPINFOHEADER)new
  char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorEntries];
 m_lpBMPHdr->biSize = sizeof(BITMAPINFOHEADER); //以下是为BITMAPINFOHEADER结构赋值
 m_lpBMPHdr->biWidth = width;
 m_lpBMPHdr->biHeight = height;
 m_lpBMPHdr->biPlanes = 1;
 m_lpBMPHdr->biBitCount = nBitCounts;
 m_lpBMPHdr->biCompression = BI_RGB;
 m_lpBMPHdr->biSizeImage = 0;
 m_lpBMPHdr->biXPelsPerMeter = 0;
 m_lpBMPHdr->biYPelsPerMeter = 0;
 m_lpBMPHdr->biClrUsed = m_nColorEntries;
 m_lpBMPHdr->biClrImportant = m_nColorEntries;
 ComputeImage();
 memset(m_lpvColorTable, 0, sizeof(RGBQUAD) * m_nColorEntries);
 m_lpDIBits = NULL; 
}

CFG_DIB::~CFG_DIB()
{
 InitDestroy();
}

void CFG_DIB::InitDestroy()
{
 m_Dest.x = 0;
 m_Dest.y = 0;
 m_DestSize.cx = 0;
 m_DestSize.cy = 0;
 m_Src.x = 0;
 m_Src.y = 0;
 m_SrcSize.cx = 0;
 m_SrcSize.cy = 0;
 if(m_hPalette != NULL) ::DeleteObject(m_hPalette);
 if(m_hBitmap != NULL) ::DeleteObject(m_hBitmap);
 m_lpBMPHdr = NULL;
 m_lpDIBits = NULL;
 m_lpvColorTable = NULL;
 m_nColorEntries = 0;
 m_dwImageSize = 0;
 m_hBitmap = NULL;
 m_hPalette = NULL;
}

void CFG_DIB::ComputePaletteSize(int nBitCounts)
{
 if((m_lpBMPHdr == NULL) || (m_lpBMPHdr->biClrUsed == 0)) {
  switch(nBitCounts) {
   case 1:
    m_nColorEntries = 2;
    break;
   case 4:
    m_nColorEntries = 16;
    break;
   case 8:
    m_nColorEntries = 256;
    break;
   case 16:
   case 24:
   case 32:
    m_nColorEntries = 0;
    break;
   default:
    ASSERT(FALSE);
  }
 }
 else {
  m_nColorEntries = m_lpBMPHdr->biClrUsed;
 }
 ASSERT((m_nColorEntries >= 0) && (m_nColorEntries <= 256));
}


void CFG_DIB::ComputeImage()
{
 if(m_lpBMPHdr->biSize != sizeof(BITMAPINFOHEADER)) {
  TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmap\n");
  throw new CException;
 }
 m_dwImageSize = m_lpBMPHdr->biSizeImage;
 if(m_dwImageSize == 0) {
  DWORD dwBytes = ((DWORD) m_lpBMPHdr->biWidth * m_lpBMPHdr->biBitCount) / 32;
  if(((DWORD) m_lpBMPHdr->biWidth * m_lpBMPHdr->biBitCount) % 32) {
   dwBytes++;
  }
  dwBytes *= 4;
  //没被压缩
  m_dwImageSize = dwBytes * m_lpBMPHdr->biHeight;
 }
 m_lpvColorTable = (LPBYTE) m_lpBMPHdr + sizeof(BITMAPINFOHEADER);
}

HBITMAP CFG_DIB::CreateBitmap(CDC* pDC)
{
 if (m_dwImageSize == 0) return NULL;
    HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(),
  m_lpBMPHdr, CBM_INIT, m_lpDIBits,
  (LPBITMAPINFO) m_lpBMPHdr, DIB_RGB_COLORS);
    ASSERT(hBitmap != NULL);
    return hBitmap;
}
HBITMAP CFG_DIB::CreateSection(CDC* pDC)
{
 if(m_lpBMPHdr == NULL) return NULL;
 if(m_lpDIBits != NULL) return NULL;     //图像不存在
 m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(),
  (LPBITMAPINFO)m_lpBMPHdr, DIB_RGB_COLORS,
  (LPVOID*)&m_lpDIBits, NULL, 0);
 ASSERT(m_lpDIBits != NULL);
 return m_hBitmap;
}

BOOL CFG_DIB::SetWinPalette()
{
 if(m_nColorEntries == 0) return FALSE;
 if(m_hPalette != NULL) ::DeleteObject(m_hPalette);
 TRACE("CDib::MakePalette -- m_nColorEntries = %d\n", m_nColorEntries);
 LPLOGPALETTE pLogPal =
  (LPLOGPALETTE) new char[2 * sizeof(WORD) +
  m_nColorEntries * sizeof(PALETTEENTRY)];
 pLogPal->palVersion = 0x300;
 pLogPal->palNumEntries = m_nColorEntries;
 LPRGBQUAD pDibRGBquad = (LPRGBQUAD) m_lpvColorTable;
 for(int i = 0; i < m_nColorEntries; i++) {
  pLogPal->palPalEntry[i].peRed =
    pDibRGBquad->rgbRed;
  pLogPal->palPalEntry[i].peGreen =
    pDibRGBquad->rgbGreen;
  pLogPal->palPalEntry[i].peBlue =
    pDibRGBquad->rgbBlue;
  pLogPal->palPalEntry[i].peFlags = 0;
  pDibRGBquad++;
 }
 m_hPalette = ::CreatePalette(pLogPal);
 delete pLogPal;
 return TRUE;
}

BOOL CFG_DIB::SetLogPalette(CDC* pDC)
{
 //如果DIB没有颜色表,可以用逻辑调色板
 if(m_nColorEntries != 0) return FALSE;
 m_hPalette = ::CreateHalftonePalette(pDC->GetSafeHdc());
 return TRUE;
}

UINT CFG_DIB::UseLogPalette(CDC* pDC)
{
 if(m_hPalette == NULL) return 0;
 HDC hdc = pDC->GetSafeHdc();
 ::SelectPalette(hdc, m_hPalette,FALSE);  //Windows作为前台调色板来实现该调色板
 return ::RealizePalette(hdc);
}

BOOL CFG_DIB::NewFile(int width, int height, int nBitCounts)
{
 if(m_hPalette != NULL) ::DeleteObject(m_hPalette);
 if(m_hBitmap != NULL) ::DeleteObject(m_hBitmap);
 m_hBitmap = NULL;
 m_hPalette = NULL;
 m_Dest.x = 0;
 m_Dest.y = 0;
 m_DestSize.cx = 0;
 m_DestSize.cy = 0;
 m_Src.x = 0;
 m_Src.y = 0;
 m_SrcSize.cx = 0;
 m_SrcSize.cy = 0;
 InitDestroy();
 ComputePaletteSize(nBitCounts);     //为BITMAPINFOHEADER结构申请空间。
 m_lpBMPHdr = (LPBITMAPINFOHEADER)new
  char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorEntries];
 m_lpBMPHdr->biSize = sizeof(BITMAPINFOHEADER); //以下是为BITMAPINFOHEADER结构赋值
 m_lpBMPHdr->biWidth = width;
 m_lpBMPHdr->biHeight = height;
 m_lpBMPHdr->biPlanes = 1;
 m_lpBMPHdr->biBitCount = nBitCounts;
 m_lpBMPHdr->biCompression = BI_RGB;
 m_lpBMPHdr->biSizeImage = 0;
 m_lpBMPHdr->biXPelsPerMeter = 0;
 m_lpBMPHdr->biYPelsPerMeter = 0;
 m_lpBMPHdr->biClrUsed = m_nColorEntries;
 m_lpBMPHdr->biClrImportant = m_nColorEntries;
 ComputeImage();
 memset(m_lpvColorTable, 0, sizeof(RGBQUAD) * m_nColorEntries);
 m_lpDIBits = (LPBYTE) new char[m_dwImageSize];

 memset(m_lpDIBits, 0, m_dwImageSize);

 return TRUE;
}

BOOL CFG_DIB::CloseFile()
{
 m_Dest.x = 0;
 m_Dest.y = 0;
 m_DestSize.cx = 0;
 m_DestSize.cy = 0;
 m_Src.x = 0;
 m_Src.y = 0;
 m_SrcSize.cx = 0;
 m_SrcSize.cy = 0;
 InitDestroy();
 return TRUE;
}

BOOL CFG_DIB::WriteFile(CFile* pFile)
{
 BITMAPFILEHEADER bmfh;
 bmfh.bfType = 0x4d42;  // 'BM'
 int sizeHdr = sizeof(BITMAPINFOHEADER) +
    sizeof(RGBQUAD) * m_nColorEntries;
 bmfh.bfSize = 0;
 bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
 bmfh.bfOffBits =
  sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
  sizeof(RGBQUAD) * m_nColorEntries; 
 try {
  pFile->Write((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
  pFile->Write((LPVOID) m_lpBMPHdr,  sizeHdr);
  pFile->Write((LPVOID) m_lpDIBits, m_dwImageSize);
 }
 catch(CException* pe) {
  pe->Delete();
  AfxMessageBox("write error");
  return FALSE;
 }
 return TRUE;
}

BOOL CFG_DIB::ReadFile(CFile* pFile)
{
 InitDestroy();
 int counts, size;
 BITMAPFILEHEADER bmfh;
 try {
  counts = pFile->Read((LPVOID) &bmfh,
     sizeof(BITMAPFILEHEADER));
  if(counts != sizeof(BITMAPFILEHEADER)) {
   throw new CException;
  }
  if(bmfh.bfType != 0x4d42) {
   throw new CException;
  }
  size = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
  m_lpBMPHdr = (LPBITMAPINFOHEADER) new char[size];
  // BITMAPINFOHEADER和颜色表
  counts = pFile->Read(m_lpBMPHdr, size);
  ComputeImage();
  ComputePaletteSize(m_lpBMPHdr->biBitCount);
  SetWinPalette();
  m_lpDIBits = (LPBYTE) new char[m_dwImageSize];
  counts = pFile->Read(m_lpDIBits, m_dwImageSize);
 }
 catch(CException* pe) {
  AfxMessageBox("Read error");
  pe->Delete();
  return FALSE;
 }
 return TRUE;
}

BOOL CFG_DIB::ReadSection(CFile* pFile, CDC* pDC)
{
 InitDestroy();
 int counts, size;
 BITMAPFILEHEADER bmfh;
 try {
  counts = pFile->Read((LPVOID) &bmfh,
     sizeof(BITMAPFILEHEADER));
  if(counts != sizeof(BITMAPFILEHEADER)) {
   throw new CException;
  }
  if(bmfh.bfType != 0x4d42) {
   throw new CException;
  }
  size = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
  m_lpBMPHdr = (LPBITMAPINFOHEADER) new char[size];
  //BITMAPINFOHEADER和颜色表
  counts = pFile->Read(m_lpBMPHdr, size);
  if(m_lpBMPHdr->biCompression != BI_RGB) {
   throw new CException;
  }
  ComputeImage();
  ComputePaletteSize(m_lpBMPHdr->biBitCount);
  SetWinPalette();
  UseLogPalette(pDC);
  m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(),
   (LPBITMAPINFO) m_lpBMPHdr, DIB_RGB_COLORS,
   (LPVOID*) &m_lpDIBits, NULL, 0);
  ASSERT(m_lpDIBits != NULL);
  counts = pFile->Read(m_lpDIBits, m_dwImageSize); // 图像
 }
 catch(CException* pe) {
  AfxMessageBox("ReadSection error");
  pe->Delete();
  return FALSE;
 }
 return TRUE;
}

BOOL CFG_DIB::Display(CDC* pDC)
{
 if(m_lpBMPHdr == NULL) return FALSE;
 if(m_hPalette != NULL) {
  ::SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE);
 }

 ::StretchDIBits(pDC->GetSafeHdc(), m_Dest.x, m_Dest.y,
        m_DestSize.cx, m_DestSize.cy,
        m_Src.x, m_Src.y,
        m_SrcSize.cx, m_SrcSize.cy,
        m_lpDIBits, (LPBITMAPINFO) m_lpBMPHdr,
        DIB_RGB_COLORS, SRCCOPY);
 return TRUE;
}

long CFG_DIB::GetLineBit()
{
 long dwBytes = ((long)m_lpBMPHdr->biWidth * m_lpBMPHdr->biBitCount) / 32;
 if(((long)m_lpBMPHdr->biWidth * m_lpBMPHdr->biBitCount) % 32)
 {
  dwBytes++;
 }
 dwBytes *= 4;

 return dwBytes;
}

 

 

使用如下,可以在OnView()函数内使用

 

CFile* pf;
pf = new CFile;
pf->Open("D://uuuu.bmp", CFile::modeRead);
m_fgdib.ReadFile(pf);
pf->Close();
delete pf;

//draw BMP
m_fgdib.m_Dest.x = 0;
m_fgdib.m_Dest.y = 0;
m_fgdib.m_DestSize.cx = m_fgdib.GetWidth();
m_fgdib.m_DestSize.cy = m_fgdib.GetHeight();
m_fgdib.m_Src.x = 0;
m_fgdib.m_Src.y = 0;
m_fgdib.m_SrcSize.cx = m_fgdib.GetWidth();
m_fgdib.m_SrcSize.cy = m_fgdib.GetHeight();
//CDC* pDC = GetDC();
m_fgdib.Display(pDC);

//close BMP
m_fgdib.CloseFile();


 

 

你可能感兴趣的:(读写)