不同的CDib类

Visual C++ MFC中没有提供一个专门的类来处理DIB位图,因此,为了方便地使用位图文件,我们有必要派生一个CDib类。类的源代码如下: 


  (1) CDib类的声明 


// DIB.h:类CDib声明头文件 
#ifndef __DIB_H__ 
#define __DIB_H__ 
#include <wingdi.h> 
class CDib 

 public: 
  CDib(); 
  ~CDib(); 


  BOOL Load( const char * ); 
  BOOL Save( const char * ); 
  BOOL Draw( CDC *, int nX = 0, int nY = 0, int nWidth = -1, int nHeight = -1, int mode = SRCCOPY); 
  BOOL SetPalette( CDC * ); 


 private: 
  CPalette m_Palette; 
  unsigned char *m_pDib, *m_pDibBits; 
  DWORD m_dwDibSize; 
  BITMAPINFOHEADER *m_pBIH; 
  RGBQUAD *m_pPalette; 
  int m_nPaletteEntries; 
}; 
#endif 




  (2) CDib类的实现 


// DIB.cpp:类CDib实现文件 
#include "stdafx.h" 
#include "DIB.h" 


CDib::CDib() 

 m_pDib = NULL; 



CDib::~CDib() 

 // 如果位图已经被加载,释放内存 
 if (m_pDib != NULL) 
  delete []m_pDib; 



  下面这个函数非常重要,其功能为加载位图,类似于CBitmap类的LoadBitmap函数: 


BOOL CDib::Load(const char *pszFilename) 

 CFile cf; 


 // 打开位图文件 
 if (!cf.Open(pszFilename, CFile::modeRead)) 
  return (FALSE); 


 // 获得位图文件大小,并减去BITMAPFILEHEADER的长度 
 DWORD dwDibSize; 
 dwDibSize = cf.GetLength() - sizeof(BITMAPFILEHEADER); 


 // 为DIB位图分配内存 
 unsigned char *pDib; 
 pDib = new unsigned char[dwDibSize]; 
 if (pDib == NULL) 
  return (FALSE); 


 BITMAPFILEHEADER BFH; 


 // 读取位图文件数据 
 try 
 { 
  // 文件格式是否正确有效 
  if ( cf.Read(&BFH, sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER) || 
     BFH.bfType != ’MB’ || cf.Read(pDib, dwDibSize) != dwDibSize) 
  { 
   delete []pDib; 
   return (FALSE); 
  } 
 } 
 catch (CFileException *e) 
 { 
  e->Delete(); 
  delete []pDib; 
  return (FALSE); 
 } 


 // delete先前加载的位图 
 if (m_pDib != NULL) 
  delete m_pDib; 


 // 将临时Dib数据指针和Dib大小变量赋给类成员变量 
 m_pDib = pDib; 
 m_dwDibSize = dwDibSize; 


 // 为相应类成员变量赋BITMAPINFOHEADER和调色板指针 
 m_pBIH = (BITMAPINFOHEADER*)m_pDib; 
 m_pPalette = (RGBQUAD*) &m_pDib[sizeof(BITMAPINFOHEADER)]; 


 // 计算调色板中实际颜色数量 
 m_nPaletteEntries = 1 << m_pBIH->biBitCount; 
 if (m_pBIH->biBitCount > 8) 
  m_nPaletteEntries = 0; 
 else if (m_pBIH->biClrUsed != 0) 
  m_nPaletteEntries = m_pBIH->biClrUsed; 


 // 为相应类成员变量赋image data指针 
 m_pDibBits = &m_pDib[sizeof(BITMAPINFOHEADER) + m_nPaletteEntries * sizeof (RGBQUAD)]; 


 // delete先前的调色板 
 if (m_Palette.GetSafeHandle() != NULL) 
  m_Palette.DeleteObject(); 


 // 如果位图中存在调色板,创建LOGPALETTE 及CPalette 
 if (m_nPaletteEntries != 0) 
 { 
  LOGPALETTE *pLogPal = (LOGPALETTE*)new char[sizeof(LOGPALETTE) + m_nPaletteEntries *sizeof(PALETTEENTRY)]; 


  if (pLogPal != NULL) 
  { 
   pLogPal->palVersion = 0x300; 
   pLogPal->palNumEntries = m_nPaletteEntries; 


   for (int i = 0; i < m_nPaletteEntries; i++) 
   { 
    pLogPal->palPalEntry[i].peRed = m_pPalette[i].rgbRed; 
    pLogPal->palPalEntry[i].peGreen = m_pPalette[i].rgbGreen; 
    pLogPal->palPalEntry[i].peBlue = m_pPalette[i].rgbBlue; 
   } 


   //创建CPalette并释放LOGPALETTE的内存 
   m_Palette.CreatePalette(pLogPal); 
   delete []pLogPal; 
  } 
 } 


 return (TRUE); 



//函数功能:保存位图入BMP文件 
BOOL CDib::Save(const char *pszFilename) 

 if (m_pDib == NULL) 
  return (FALSE); 


 CFile cf; 
 if (!cf.Open(pszFilename, CFile::modeCreate | CFile::modeWrite)) 
  return (FALSE); 


 try 
 { 
  BITMAPFILEHEADER BFH; 
  memset(&BFH, 0, sizeof(BITMAPFILEHEADER)); 
  BFH.bfType = ’MB’; 
  BFH.bfSize = sizeof(BITMAPFILEHEADER) + m_dwDibSize; 
  BFH.bfOffBits = sizeof(BITMAPFILEHEADER) + 
sizeof(BITMAPINFOHEADER) + m_nPaletteEntries *sizeof(RGBQUAD); 


  cf.Write(&BFH, sizeof(BITMAPFILEHEADER)); 
  cf.Write(m_pDib, m_dwDibSize); 
 } 
 catch (CFileException *e) 
 { 
  e->Delete(); 
  return (FALSE); 
 } 
 return (TRUE); 



  下面这个函数也非常重要,其功能为在pDC指向的CDC中绘制位图,起点坐标为(nX,nY),绘制宽度和高度为nWidth、nHeight,最后一个参数是光栅模式: 


BOOL CDib::Draw(CDC *pDC, int nX, int nY, int nWidth, int nHeight, int mode) 

 if (m_pDib == NULL) 
  return (FALSE); 


 // 获取位图宽度和高度赋值 
 if (nWidth == - 1) 
  nWidth = m_pBIH->biWidth; 
 if (nHeight == - 1) 
  nHeight = m_pBIH->biHeight; 


 // 绘制位图 
 StretchDIBits(pDC->m_hDC, nX, nY, nWidth, nHeight, 0, 0, m_pBIH->biWidth, m_pBIH->biHeight, m_pDibBits, (BITMAPINFO*)m_pBIH, BI_RGB, mode); 


 return (TRUE); 



//函数功能:设置调色板 
BOOL CDib::SetPalette(CDC *pDC) 

 if (m_pDib == NULL) 
  return (FALSE); 


 // 检查当前是否有一个调色板句柄,对于大于256色的位图,为NULL 
 if (m_Palette.GetSafeHandle() == NULL) 
  return (TRUE); 


 // 选择调色板,接着实施之,最后恢复老的调色板 
 CPalette *pOldPalette; 
 pOldPalette = pDC->SelectPalette(&m_Palette, FALSE); 
 pDC->RealizePalette(); 
 pDC->SelectPalette(pOldPalette, FALSE); 


 return (TRUE); 



  从整个CDib类的代码中我们可以看出,DIB位图的显示需遵循如下步骤: 


  (1)读取位图,本类中使用pDib = new unsigned char[dwDibSize]为位图中的信息分配内存,另一种方法是调用API函数CreateDIBSection,譬如: 


m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), 
(LPBITMAPINFO) m_lpBMPHdr, DIB_RGB_COLORS, 
(LPVOID*) &m_lpDIBits, NULL, 0); 


  m_hBitmap定义为: 


HBITMAP m_hBitmap; 


  (2)根据读取的位图信息,计算出调色板大小,然后创建调色板; 


  (3)调用CDib::SetPalette( CDC *pDC )设置调色板,需要用到CDC::SelectPalette及CDC::RealizePalette两个函数; 


  (4)调用CDib::Draw(CDC *pDC, int nX, int nY, int nWidth, int nHeight, int mode)函数绘制位图。在此函数中,真正发挥显示位图作用的是对StretchDIBits API函数的调用。StretchDIBits函数具有缩放功能,其最后一个参数也是光栅操作的模式。 


  下面给出DIB位图的打开及显示并在其中加入天极网logo的函数源代码。"DIB位图"父菜单下"打开"子菜单的单击事件消息处理函数为(其功能为打开位图并显示之): 


void CBitMapExampleDlg::OnOpendibpic() 

 // 弹出文件对话框,让用户选择位图文件 
 CFileDialog fileDialog(TRUE, "*.BMP", NULL, NULL,"位图文件(*.BMP)|*.bmp;*.BMP|"); 
 if (IDOK == fileDialog.DoModal()) 
 { 
  // 加载位图并显示之 
  CDib dib; 
  if (dib.Load(fileDialog.GetPathName())) 
  { 
   CClientDC dc(this); 
   dib.SetPalette(&dc); 
   dib.Draw(&dc); 
  } 
 } 



  "DIB位图"父菜单下"标记"子菜单的单击事件消息处理函数为(其功能为给位图加上天极网logo): 


void CBitMapExampleDlg::OnMarkDibpic() 

 // 弹出文件对话框,让用户选择标记logo 
 CFileDialog fileDialog(TRUE, "*.BMP", NULL, NULL, "标记位图文件(*.BMP)|*.bmp;*.BMP|"); 
 if (IDOK == fileDialog.DoModal()) 
 { 
  // 加载标记logo位图并与目标位图相与 
  CDib dib; 
  if (dib.Load(fileDialog.GetPathName())) 
  { 
   CClientDC dc(this); 
   dib.SetPalette(&dc); 
   dib.Draw(&dc, 0, 0, - 1, - 1, SRCAND); 
  } 

 } 


///


     我在网上没找到,所以在这里把它贴了出来,其实一句一句的敲,也很快的,一个月就敲完了,当然了,是一边玩一边敲的,注:源代码来自向世明著的《Visual C++ 数字图像与图形处理》

// dib.h: interface for the Cdib class.
//
//

#if !defined(AFX_DIB_H__98D8CBB1_E122_4397_890B_257BFA0AD5BF__INCLUDED_)
#define AFX_DIB_H__98D8CBB1_E122_4397_890B_257BFA0AD5BF__INCLUDED_
#define _CDIB_H
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class Cdib : public CObject
{
  DECLARE_DYNAMIC(Cdib)
public:
 Cdib();
 Cdib(const char *pszDibFileName);
 virtual ~Cdib();
 void ClearMemory();
 void Init();
 void LoadFile(const char*pszDibFileName);
 #ifdef _DEBUG
    virtual void Dump(CDumpContext &dc)const;
 virtual void AssertValid() const;
    #endif
    DWORD GetDdbData32(LPBYTE lpbyDdb32);
 DWORD GetDdbData24(LPBYTE lpbyDdb24);     //148或者24位的DIB图象数据转化为DDB格式的24位位图数据,并存放在lpbyDdb24所指示的内存区域中
    DWORD GetDibWidthBytes(int nWidth,BYTE byBitCount); //计算每行的扫描存储宽度字节数
 BYTE  GetBitCount() const;                 //获得颜色位数
 DWORD GetSize();                          //获得被压缩位图的字节数
    LONG  GetWidth() const;                       
 LONG  GetHeight() const;
 UINT  GetColorNumber() const;             //获得颜色总数      
 char  *GetFileName() const;
 BOOL  IsValid() const;
    RGBQUAD *GetRGBQuad() const;
 BYTE *GetDibData() const;                 //获得指向图象位疏忽局的指针
 BITMAPINFO *GetBmpInfo() const;
 INT  Draw(HDC hdc,int Xdest,int Ydest,int nDestWidth,int nDestHeight,
        int Xsrc,int Ysrc,int nSrcWidth,int nSrcHeight,UINT iUsage,DWORD dwRop);
protected:
 bool m_bValid;                //标志装载位图图象的操作过程是否成功
 RGBQUAD * m_pRGBQuad;             //颜色表项的指针
 BYTE    * m_pDibData;         //指向位数据的指针
 LONG    m_nWidth,m_nHeight;   //图象的宽度和高度,以象素为单位
 byte    m_nBitCount;          //颜色位数,可能取值为148或者24
 UINT    m_nTotalColors;       //颜色总数,可能取值为216256
 char    *m_pszFileName;       //文件名(包括路径)的指针 
 BITMAPFILEHEADER * m_pBitmapFileHeader;  //指向位图文件的文件头的指针
 BITMAPINFOHEADER * m_pBitmapInfoHeader;  //指向位图文件的信息头的指针
    BITMAPINFO       * m_pBitmapInfo;        //指向位图文件的信息头和颜色表项(总称BITMAPINFO)的指针
 HGLOBAL   m_hDIB;                        //内存管理句柄
 HPALETTE CreateBitmapPalette();           //简单的用颜色表项中的颜色来设置逻辑调色盘中的项,其中的逻辑调色盘是用CreatPalette函数来创建的
private:
};

#endif // !defined(AFX_DIB_H__98D8CBB1_E122_4397_890B_257BFA0AD5BF__INCLUDED_)

 

dib.cpp文件的全部代码及注释:

  // dib.cpp: implementation of the Cdib class.
//
//

#include "stdafx.h"
#include "ImageBasic.h"
#include "dib.h"

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


//
// Construction/Destruction
//
IMPLEMENT_DYNAMIC(Cdib,CObject)
Cdib::Cdib()
{
  Init();
}

Cdib::Cdib(const char *pszDibFileName)
{
  Init();
  LoadFile(pszDibFileName);
}

Cdib::~Cdib()
{
  ClearMemory();
}

void Cdib::ClearMemory()
{
 if(m_hDIB!=NULL)
  ::GlobalFree(m_hDIB);
 m_hDIB=0;
 m_pDibData=NULL;
 m_pszFileName=NULL;
 m_pBitmapFileHeader=NULL;
 m_pBitmapInfoHeader=NULL;
    m_pBitmapInfo=NULL;
 m_pRGBQuad=NULL;
 
}

void Cdib::Init()
{
   m_pRGBQuad=NULL;
   m_pDibData=NULL;
   m_nWidth=0;
   m_nHeight=0;
   m_nBitCount=0;
   m_nTotalColors=0;
   m_pBitmapFileHeader=NULL;
   m_pBitmapInfoHeader=NULL;
   m_pBitmapInfo=NULL;
   m_hDIB=0;
   m_pszFileName=NULL;
}

void Cdib::LoadFile(const char*pszDibFileName)
{
 ASSERT(pszDibFileName);
 if(m_pBitmapInfo) ::GlobalFree(m_hDIB);
 Init();
    m_pszFileName =(char*) pszDibFileName;
   
 BITMAPFILEHEADER bitmapFileHeader;
 CFile dibFile(pszDibFileName,CFile::modeRead);
 try
 {
  UINT nBFHsize=dibFile.Read((void*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER));
  if(nBFHsize!=sizeof(BITMAPFILEHEADER))    //如果打开文件出错,则弹出出现异常窗口
  {
   m_bValid=FALSE;
   return;
  }
 }
 catch(CFileException *e)
 {
  e->Delete();
 }
 if(bitmapFileHeader.bfType==0x4d42)
 {
  AfxGetApp()->BeginWaitCursor();
  DWORD dwFileLength=dibFile.GetLength();
  DWORD dwSize=dwFileLength-sizeof(BITMAPFILEHEADER);
  m_hDIB=(HGLOBAL)::GlobalAlloc(GMEM_MOVEABLE,dwSize);  //DIB信息和图像数据分配可移动的内存给句柄m_hDIB
  if(m_hDIB==0)
              m_bValid=FALSE;
  BYTE *pbyDib=(BYTE *)::GlobalLock(m_hDIB);   //定义指向BMP文件的指针,锁定内存并从文件中读取数据
        if(pbyDib==NULL)
             m_bValid=FALSE;
  try
  {
   DWORD dwReadSize=dibFile.Read((void*)pbyDib,dwSize);
   dibFile.Close();
   if(dwReadSize!=dwSize)
   {
               m_bValid=FALSE;
      ::GlobalUnlock(m_hDIB);
      ::GlobalFree(m_hDIB);
      Init();
      return;
   }
  }
  catch(CFileException *e)
  {
    e->Delete();
  }
         m_pBitmapInfo=(BITMAPINFO *)pbyDib;
   m_pBitmapInfoHeader=(BITMAPINFOHEADER *)pbyDib;
   m_nWidth=m_pBitmapInfoHeader->biWidth;
   m_nHeight=m_pBitmapInfoHeader->biHeight;
   m_nBitCount=(BYTE)m_pBitmapInfoHeader->biBitCount;    //获得位图的每个象素所占用的位数
   m_nTotalColors=GetColorNumber();
   if(m_pBitmapInfoHeader->biClrUsed==0)                   //如果位图实际使用的颜色数为0,说明位图为14或者8位位图
                m_pBitmapInfoHeader->biClrUsed= m_nTotalColors;  //此时,把位图实际使用的颜色数赋值给biClrUsed
   m_pRGBQuad=(RGBQUAD*)(pbyDib+m_pBitmapInfoHeader->biSize);
   DWORD dwColorTableSize=m_nTotalColors*sizeof(RGBQUAD);
   m_pDibData=pbyDib+m_pBitmapInfoHeader->biSize+dwColorTableSize;
   if(m_pRGBQuad==(RGBQUAD*)m_pDibData)
             m_pRGBQuad=NULL;
         m_pBitmapInfoHeader->biSizeImage=GetSize();
         ::GlobalUnlock(m_hDIB);
   AfxGetApp()->EndWaitCursor;
   m_bValid=true;
 }
 else
 {
  AfxMessageBox("This is not a bitmap file!");
        m_bValid=false;
 }
}


#ifdef _DEBUG
void Cdib::Dump(CDumpContext &dc)const
{
 CObject::Dump(dc);
}
 
void Cdib::AssertValid() const
{
 CObject::AssertValid();
 ASSERT(m_pszFileName!=NULL);
 ASSERT(m_hDIB!=0);
}
#endif

long Cdib::GetWidth()  const
{
 return m_nWidth;
}

LONG Cdib::GetHeight()  const
{
 return m_nHeight;
}

DWORD Cdib::GetSize()
{
 if(m_pBitmapInfoHeader->biSizeImage!=0)
  return (m_pBitmapInfoHeader->biSizeImage);
 else
  return (DWORD) GetDibWidthBytes(m_nWidth,24)*(DWORD)m_nHeight;
}

BYTE Cdib::GetBitCount() const
{
 return m_nBitCount;
}

UINT Cdib::GetColorNumber() const
{
 UINT nColors=0;
 if((m_pBitmapInfoHeader->biSizeImage==0) && (m_pBitmapInfoHeader->biSizeImage<9))
 {
  switch (m_pBitmapInfoHeader->biBitCount)
  {
     case 1: nColors=2;break;
   case 4: nColors=16;break;
    case 8: nColors=256;break;
  }
 }
 else
  nColors=(UINT)m_pBitmapInfoHeader->biClrUsed;
 return  nColors;
}


BYTE * Cdib::GetDibData() const
{
 return m_pDibData;
}

RGBQUAD *Cdib::GetRGBQuad() const
{
 return m_pRGBQuad;
}

BITMAPINFO *Cdib::GetBmpInfo() const
{
 return m_pBitmapInfo;
}

char *Cdib::GetFileName() const
{
 return m_pszFileName;
}

BOOL Cdib::IsValid() const
{
 return m_bValid;
}

DWORD Cdib::GetDibWidthBytes(int nWidth,BYTE byBitCount)
{
   DWORD dwWidthBytes=(DWORD)nWidth;  //如果位图的每个象素的位数是8,那么整个位图的字节数就等于象素数
  if(byBitCount==1)                   //如果位图的每个象素的位数是1,那么一个字节就包含了8个象素
       dwWidthBytes=(nWidth+7)/8;
  if(byBitCount==4)
       dwWidthBytes=(nWidth+1)/2;     //如果位图的每个象素的位数是4,那么一个字节就包含了2个象素
  if(byBitCount==24)
       dwWidthBytes=3*nWidth;         //如果位图的每个象素的位数是24,那么一个象素就需要3个字节来存储
  while((dwWidthBytes&3)!=0)
        dwWidthBytes++;
  return dwWidthBytes;
}

//148或者24位的DIB图象数据转换为DDB格式的24位位图,并存放在lpbyDdb24指示的内存区域中
DWORD Cdib::GetDdbData24(LPBYTE lpbyDdb24)
{
 ASSERT(lpbyDdb24);
 DWORD dwDibWidthBytes=GetDibWidthBytes(m_nWidth,m_nBitCount);
    DWORD dwDdbWidthBytes=((m_nWidth*24+15)/16)*2;  //????????
 
 if(m_nBitCount==1)
 {
  LONG nLineBytes=(m_nWidth+7)/8;
  BYTE abyBitMask[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
  DWORD dwDibBaseIndex=(m_nHeight-1)*dwDibWidthBytes;
        DWORD dwDdbBaseIndex=0;
        for(LONG i=0;i<m_nHeight;i++)
  {
   BYTE *pbyDibRaw=m_pDibData+dwDibBaseIndex;
            BYTE *pbyDdbRaw=lpbyDdb24+dwDdbBaseIndex;
   for(LONG j=0;j<nLineBytes;j++)
   {
    BYTE byBit8=*(pbyDibRaw++);
    for(int n=0;n<8;n++)
    {
     BYTE byBitSingle=(byBit8 & abyBitMask[n])>>(7-n);
     *(pbyDdbRaw++)=m_pRGBQuad[byBitSingle].rgbBlue;
                    *(pbyDdbRaw++)=m_pRGBQuad[byBitSingle].rgbGreen;
     *(pbyDdbRaw++)=m_pRGBQuad[byBitSingle].rgbRed;
    }
   } //end j
            dwDibBaseIndex-=dwDibWidthBytes;
   dwDdbBaseIndex+=dwDdbWidthBytes;
  } //end i
  return (dwDdbWidthBytes*m_nHeight);
 }   //end if(m_nBitCount==1)
 else
  if (m_nBitCount==4)
  {
   LONG nLineBytes=(m_nWidth+1)/2;
   DWORD dwDibBaseIndex=(m_nHeight-1)*dwDibWidthBytes;
   DWORD dwDdbBaseIndex=0;
            for(LONG i=0;i<m_nHeight;i++)
   {
       BYTE *pbyDibRaw=m_pDibData+dwDibBaseIndex;
             BYTE *pbyDdbRaw=lpbyDdb24+dwDdbBaseIndex;
      for(LONG j=0;j<nLineBytes;j++)
      {
     BYTE byBit8=*(pbyDibRaw++);          //对于4位位图,一个字节里面含有两个象素。前4位代表一个象素的颜色表项指针,后4位同样。
                 BYTE byBitHigh=(byBit8 & 0xF0)>>4;   //因此这里要右移4位,再与F0取与,先得到第一个象素
     BYTE byBitLow=(byBit8 & 0x0F);

     *(pbyDdbRaw++)=m_pRGBQuad[byBitHigh].rgbBlue;
                 *(pbyDdbRaw++)=m_pRGBQuad[byBitHigh].rgbGreen;
     *(pbyDdbRaw++)=m_pRGBQuad[byBitHigh].rgbRed;
                 *(pbyDdbRaw++)=m_pRGBQuad[byBitLow].rgbBlue;
                 *(pbyDdbRaw++)=m_pRGBQuad[byBitLow].rgbGreen;
     *(pbyDdbRaw++)=m_pRGBQuad[byBitLow].rgbRed;
      } //end j
   dwDibBaseIndex-=dwDibWidthBytes;
   dwDdbBaseIndex+=dwDdbWidthBytes;
  } //end i
  return (dwDdbWidthBytes*m_nHeight);
 }   //end if(m_nBitCount==4)
    else
  if (m_nBitCount==8)
  {
   DWORD dwDibBaseIndex=(m_nHeight-1)*dwDibWidthBytes;
   DWORD dwDdbBaseIndex=0;
            for(LONG i=0;i<m_nHeight;i++)
   {
       BYTE *pbyDibRaw=m_pDibData+dwDibBaseIndex;
             BYTE *pbyDdbRaw=lpbyDdb24+dwDdbBaseIndex;
      for(LONG j=0;j<m_nWidth;j++)
      {
     BYTE byIndex=*(pbyDibRaw++);

     *(pbyDdbRaw++)=m_pRGBQuad[byIndex].rgbBlue;
                 *(pbyDdbRaw++)=m_pRGBQuad[byIndex].rgbGreen;
     *(pbyDdbRaw++)=m_pRGBQuad[byIndex].rgbRed;
      }  // end j
   dwDibBaseIndex-=dwDibWidthBytes;
   dwDdbBaseIndex+=dwDdbWidthBytes;
  } //end i
  return (dwDdbWidthBytes*m_nHeight);
 }   //end if(m_nBitCount==8)              
     else
  if (m_nBitCount==24)
  {
   DWORD dwLength=m_nWidth*3;
   BYTE *pbyDibRaw=m_pDibData+(m_nHeight-1)*dwDibWidthBytes;
            BYTE *pbyDdbRaw=lpbyDdb24;
            for(LONG i=0;i<m_nHeight;i++)
   {
    ::CopyMemory(pbyDdbRaw,pbyDibRaw,dwLength);
                pbyDibRaw-=dwDibWidthBytes;          //from
                pbyDdbRaw-=dwDdbWidthBytes;          //to
   }  //end i
            return (dwDdbWidthBytes*m_nHeight);
  }   //end if(m_nBitCount==24)
  return (m_nWidth*m_nHeight);
}


//将所有格式的颜色数据转换为32位颜色,按字节顺序依次为绿色、蓝色、红色和8Alpha(说明256级透明性)
DWORD Cdib::GetDdbData32(LPBYTE lpbyDdb32)
{
    ASSERT(lpbyDdb32);
 DWORD dwDibWidthBytes=GetDibWidthBytes(m_nWidth,m_nBitCount);
    DWORD dwDdbWidthBytes=m_nWidth*4;
 if(m_nBitCount==1)
 {
  LONG nLineBytes=(m_nWidth+7)/8;
  BYTE abyBitMask[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
  DWORD dwDibBaseIndex=(m_nHeight-1)*dwDibWidthBytes;
        DWORD dwDdbBaseIndex=0;
        for(LONG i=0;i<m_nHeight;i++)
  {
   BYTE *pbyDibRaw=m_pDibData+dwDibBaseIndex;
            BYTE *pbyDdbRaw=lpbyDdb32+dwDdbBaseIndex;
   for(LONG j=0;j<nLineBytes;j++)
   {
    BYTE byBit8=*(pbyDibRaw++);
    for(int n=0;n<8;n++)
    {
     BYTE byBitSingle=(byBit8 & abyBitMask[n])>>(7-n);
     *(pbyDdbRaw++)=m_pRGBQuad[byBitSingle].rgbBlue;
                    *(pbyDdbRaw++)=m_pRGBQuad[byBitSingle].rgbGreen;
     *(pbyDdbRaw++)=m_pRGBQuad[byBitSingle].rgbRed;
     pbyDdbRaw++;
    }
   } //end j
            dwDibBaseIndex-=dwDibWidthBytes;
   dwDdbBaseIndex+=dwDdbWidthBytes;
  } //end i
  return (dwDdbWidthBytes*m_nHeight);
 }   //end if(m_nBitCount==1)
 else
  if (m_nBitCount==4)
  {
   LONG nLineBytes=(m_nWidth+1)/2;
   DWORD dwDibBaseIndex=(m_nHeight-1)*dwDibWidthBytes;
   DWORD dwDdbBaseIndex=0;
            for(LONG i=0;i<m_nHeight;i++)
   {
       BYTE *pbyDibRaw=m_pDibData+dwDibBaseIndex;
             BYTE *pbyDdbRaw=lpbyDdb32+dwDdbBaseIndex;
      for(LONG j=0;j<nLineBytes;j++)
      {
     BYTE byBit8=*(pbyDibRaw++);          //对于4位位图,一个字节里面含有两个象素。前4位代表一个象素的颜色表项指针,后4位同样。
                 BYTE byBitHigh=(byBit8 & 0xF0)>>4;   //因此这里要右移4位,再与F0取与,先得到第一个象素
     BYTE byBitLow=(byBit8 & 0x0F);

     *(pbyDdbRaw++)=m_pRGBQuad[byBitHigh].rgbBlue;
                 *(pbyDdbRaw++)=m_pRGBQuad[byBitHigh].rgbGreen;
     *(pbyDdbRaw++)=m_pRGBQuad[byBitHigh].rgbRed;
                 pbyDdbRaw++;

                 *(pbyDdbRaw++)=m_pRGBQuad[byBitLow].rgbBlue;
                 *(pbyDdbRaw++)=m_pRGBQuad[byBitLow].rgbGreen;
     *(pbyDdbRaw++)=m_pRGBQuad[byBitLow].rgbRed;
     pbyDdbRaw++;
      } //end j
   dwDibBaseIndex-=dwDibWidthBytes;
   dwDdbBaseIndex+=dwDdbWidthBytes;
  } //end i
  return (dwDdbWidthBytes*m_nHeight);
 }   //end if(m_nBitCount==4)
    else
  if (m_nBitCount==8)
  {
   DWORD dwDibBaseIndex=(m_nHeight-1)*dwDibWidthBytes;
   DWORD dwDdbBaseIndex=0;
            for(LONG i=0;i<m_nHeight;i++)
   {
       BYTE *pbyDibRaw=m_pDibData+dwDibBaseIndex;
             BYTE *pbyDdbRaw=lpbyDdb32+dwDdbBaseIndex;
      for(LONG j=0;j<m_nWidth;j++)
      {
     BYTE byIndex=*(pbyDibRaw++);

     *(pbyDdbRaw++)=m_pRGBQuad[byIndex].rgbBlue;
                 *(pbyDdbRaw++)=m_pRGBQuad[byIndex].rgbGreen;
     *(pbyDdbRaw++)=m_pRGBQuad[byIndex].rgbRed;
     pbyDdbRaw++;
      }  // end j
   dwDibBaseIndex-=dwDibWidthBytes;
   dwDdbBaseIndex+=dwDdbWidthBytes;
  } //end i
  return (dwDdbWidthBytes*m_nHeight);
 }   //end if(m_nBitCount==8)              
     else
  if (m_nBitCount==24)
  {
            DWORD dwDibBaseIndex=(m_nHeight-1)*dwDibWidthBytes;
   DWORD dwDdbBaseIndex=0;
            for(LONG i=0;i<m_nHeight;i++)
   {
       BYTE *pbyDibRaw=m_pDibData+dwDibBaseIndex;
             BYTE *pbyDdbRaw=lpbyDdb32+dwDdbBaseIndex;
      for(LONG j=0;j<m_nWidth;j++)
      {

     *(pbyDdbRaw++)=*(pbyDibRaw++);   //blue
                 *(pbyDdbRaw++)=*(pbyDibRaw++);   //qree
     *(pbyDdbRaw++)=*(pbyDibRaw++);   //red
     pbyDdbRaw++;
      }  // end j
   dwDibBaseIndex-=dwDibWidthBytes;
   dwDdbBaseIndex+=dwDdbWidthBytes;
  } //end i
            return (dwDdbWidthBytes*m_nHeight);
  }   //end if(m_nBitCount==24)
  return (m_nWidth*m_nHeight);
}


//用颜色表项中的颜色来设置逻辑调色板中的项,并通过CreatePalette函数来创建一个逻辑调色板
HPALETTE Cdib::CreateBitmapPalette()
{
 if((m_pRGBQuad==NULL)||!IsValid())  //如果不存在颜色表或者BMP文件不合法
   return NULL;
 struct
 {
  WORD palVersion;
  WORD palNumEntries;
  PALETTEENTRY palPalEntry[256];
 }palette={0x300,256};
 LPRGBQUAD pRGBTable=m_pRGBQuad;
 for(UINT i=0;i<m_nTotalColors;++i)
 {
  palette.palPalEntry[i].peRed=pRGBTable[i].rgbRed;
  palette.palPalEntry[i].peGreen=pRGBTable[i].rgbGreen;
  palette.palPalEntry[i].peBlue=pRGBTable[i].rgbBlue;
        palette.palPalEntry[i].peFlags=0;
 }
 HPALETTE hPalette=::CreatePalette((LPLOGPALETTE)&palette);
 return hPalette;
}


//通过调用系统的StretchDIBits()来绘制位图,它能够方便的确定位图输出的位置,并决定是否拉伸图象
int  Cdib::Draw(HDC hdc,int Xdest,int Ydest,int nDestWidth,int nDestHeight,
        int Xsrc,int Ysrc,int nSrcWidth,int nSrcHeight,UINT iUsage,DWORD dwRop)
{
 if(m_pRGBQuad)    //如果存在颜色表
 {
  HPALETTE hPalette=CreateBitmapPalette();
  HPALETTE hOldPalette=::SelectPalette(hdc,hPalette,FALSE);
  ::RealizePalette(hdc);
       
  int nScanLines=::StretchDIBits(hdc,Xdest,Ydest,nDestWidth,nDestHeight,
                                  Xsrc,Ysrc,nSrcWidth,nSrcHeight,
             m_pDibData,m_pBitmapInfo,iUsage,dwRop);
        ::SelectPalette(hdc,hOldPalette,FALSE);
  ::DeleteObject(hPalette);
  return nScanLines;
 }
 else
    return StretchDIBits(hdc,Xdest,Ydest,nDestWidth,nDestHeight,
                                  Xsrc,Ysrc,nSrcWidth,nSrcHeight,
             m_pDibData,m_pBitmapInfo,iUsage,dwRop);
}
#endif


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
用于图片处理,包括打开,存储,移动等,。 //====================================================================== // 文件: Dib.cpp // 内容: 设备无关位图-源文件 // 功能: (1)位图的加载与保存; // (2)位图信息的获取; // (3)位图数据的获取; // (3)位图的显示; // (4)位图的转换; // (5)位图相关判断; //====================================================================== #include "StdAfx.h" #include "Dib.h" //======================================================= // 函数功能: 构造函数,初始化数据成员 // 输入参数: 无 // 返回值: 无 //======================================================= CDib::CDib(void) { // 数据成员初始化 strcpy(m_fileName, ""); m_lpBmpFileHeader = NULL; m_lpDib = NULL; m_lpBmpInfo = NULL; m_lpBmpInfoHeader = NULL; m_lpRgbQuad = NULL; m_lpData = NULL; m_hPalette = NULL; m_bHasRgbQuad = FALSE; m_bValid = FALSE; m_rgbsum=0; } //======================================================= // 函数功能: 析构函数,释放内存空间 // 输入参数: 无 // 返回值: 无 //======================================================= CDib::~CDib(void) { // 清理空间 Empty(); } //======================================================= // 函数功能: 从文件加载位图 // 输入参数: LPCTSTR lpszPath-待加载位图文件路径 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::LoadFromFile(LPCTSTR lpszPath) { // 记录位图文件名 strcpy(m_fileName, lpszPath); // 以读模式打开位图文件 CFile dibFile; if(!dibFile.Open(m_fileName, CFile::modeRead | CFile::shareDenyWrite)) { return FALSE; } // 清理空间 Empty(FALSE); // 为位图文件头分配空间,并初始化为0 m_lpBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)]; memset(m_lpBmpFileHeader, 0, sizeof(BITMAPFILEHEADER)); // 读取位图文件头 int nCount = dibFile.Read((void *)m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER)); if(nCount != sizeof(BITMAPFILEHEADER)) { return FALSE; } // 判断此文件是不是位图文件(“0x4d42”代表“BM”) if(m_lpBmpFileHeader->bfType == 0x4d42) { // 是位图文件 //AfxMessageBox("m_lpBmpFileHeader->bfType == 0x4d42"); // 计算除位图文件头的空间大小,分配空间并初始化为0 DWORD dwDibSize = dibFile.GetLength() - sizeof(BITMAPFILEHEADER); m_lpDib = new BYTE[dwDibSize]; //(LPBYTE) new BYTE[lHeight*lineBytes24] //m_lpOldDib = new BYTE[dwDibSize]; memset(m_lpDib, 0, dwDibSize); //memset(m_lpOldDib, 0, dwDibSize); // 读取除位图文件头的所有数据 dibFile.Read(m_lpDib, dwDibSize); //dibFile.Read(m_lpOldDib, dwDibSize); // 关闭位图文件 dibFile.Close(); // 设置位图信息指针 m_lpBmpInfo = (LPBITMAPINFO)m_lpDib; // 设置位图信息头指针 m_lpBmpInfoHeader = (LPBITMAPINFOHEADER)m_lpDib; // 设置位图颜色表指针 m_lpRgbQuad = (LPRGBQUAD)(m_lpDib + m_lpBmpInfoHeader->biSize); // 如果位图没有设置位图使用的颜色数,设置它 if(m_lpBmpInfoHeader->biClrUsed == 0) { m_lpBmpInfoHeader->biClrUsed = GetNumOfColor(); //AfxMessageBox("24位"); //CString strColor; //strColor.Format("m_lpBmpInfoHeader->biClrUsed :%d",m_lpBmpInfoHeader->biClrUsed); //AfxMessageBox(strColor); } // 计算颜色表长度 DWORD dwRgbQuadLength = CalcRgbQuadLength(); //m_lpBmpInfoHeader->biPlanes = 1; //CString strColor; //strColor.Format("m_lpBmpInfoHeader->biCompression :%d", m_lpBmpInfoHeader->biPlanes); //AfxMessageBox(strColor); // 设置位图数据指针 //m_lpData = m_lpDib + m_lpBmpInfoHeader->biSize + dwRgbQuadLength; m_lpData = m_lpDib + m_lpBmpInfoHeader->biSize + dwRgbQuadLength; //m_lpOldData= m_lpOldDib + ((LPBITMAPINFOHEADER)m_lpOldDib)->biSize + dwRgbQuadLength; // 判断是否有颜色表 if(m_lpRgbQuad == (LPRGBQUAD)m_lpData) { m_lpRgbQuad = NULL; // 将位图颜色表指针置空 m_bHasRgbQuad = FALSE; // 无颜色表 //AfxMessageBox("无颜色表"); } else { m_bHasRgbQuad = TRUE; // 有颜色表 MakePalette(); // 根据颜色表生成调色板 //AfxMessageBox("加载生成调色板"); } // 设置位图大小(因为很多位图文件都不设置此项) m_lpBmpInfoHeader->biSizeImage = GetSize(); // 位图有效 m_bValid = TRUE; return TRUE; } else { // 不是位图文件 AfxMessageBox("该图不是位图!"); m_bValid = FALSE; return FALSE; } } //======================================================= // 函数功能: 将位图保存到文件 // 输入参数: LPCTSTR lpszPath-位图文件保存路径 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= /*BOOL CDib::SaveToFile(LPCTSTR lpszPath) { // 以写模式打开文件 HDC hdc,hdcMem; HBITMAP hBitMap = NULL; CBitmap *pBitMap = NULL; CDC *pMemDC = NULL; BYTE *pBits; hdc = CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL); hdcMem = CreateCompatibleDC(hdc); hBitMap = CreateDIBSection(hdcMem,m_lpBmpInfo,DIB_PAL_COLORS,(void **)&pBits,NULL,0); pBitMap = new CBitmap; pBitMap->Attach(hBitMap); pMemDC = new CDC; pMemDC->Attach(hdcMem); pMemDC->SelectObject(pBitMap); pMemDC->SetBkMode(TRANSPARENT); //pMemDC->SetBkMode(OPAQUE); //添加自绘图形 m_myview->DrawLine(pMemDC); CFile dibFile; if(!dibFile.Open(lpszPath, CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive)) { return FALSE; } // 记录位图文件名 strcpy(m_fileName, lpszPath); // 将文件头结构写进文件 dibFile.Write(m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER)); // 将文件信息头结构写进文件 dibFile.Write(m_lpBmpInfoHeader, sizeof(BITMAPINFOHEADER)); // 计算颜色表长度 DWORD dwRgbQuadlength = CalcRgbQuadLength(); // 如果有颜色表的话,将颜色表写进文件 if(dwRgbQuadlength != 0) { dibFile.Write(m_lpRgbQuad, dwRgbQuadlength); } // 将位图数据写进文件 DWORD dwDataSize = GetLineByte() * GetHeight(); dibFile.Write(m_lpData, dwDataSize); // 关闭文件 dibFile.Close(); return TRUE; } */ //======================================================= // 函数功能: 获取位图文件名 // 输入参数: 无 // 返回值: LPCTSTR-位图文件名 //======================================================= LPCTSTR CDib::GetFileName() { return m_fileName; } //======================================================= // 函数功能: 获取位图宽度 // 输入参数: 无 // 返回值: LONG-位图宽度 //======================================================= LONG CDib::GetWidth() { return m_lpBmpInfoHeader->biWidth; } //======================================================= // 函数功能: 获取位图高度 // 输入参数: 无 // 返回值: LONG-位图高度 //======================================================= LONG CDib::GetHeight() { return m_lpBmpInfoHeader->biHeight; } //======================================================= // 函数功能: 获取位图的宽度和高度 // 输入参数: 无 // 返回值: CSize-位图的宽度和高度 //======================================================= CSize CDib::GetDimension() { return CSize(GetWidth(), GetHeight()); } //======================================================= // 函数功能: 获取位图大小 // 输入参数: 无 // 返回值: DWORD-位图大小 //======================================================= DWORD CDib::GetSize() { if(m_lpBmpInfoHeader->biSizeImage != 0) { return m_lpBmpInfoHeader->biSizeImage; } else { return GetWidth() * GetHeight(); } } //======================================================= // 函数功能: 获取单个像素所占位数 // 输入参数: 无 // 返回值: WORD-单个像素所占位数 //======================================================= WORD CDib::GetBitCount() { return m_lpBmpInfoHeader->biBitCount; } //======================================================= // 函数功能: 获取每行像素所占字节数 // 输入参数: 无 // 返回值: UINT-每行像素所占字节数 //======================================================= UINT CDib::GetLineByte() { return (GetWidth() * GetBitCount() /8 + 3) / 4 * 4; } //======================================================= // 函数功能: 获取位图颜色数 // 输入参数: 无 // 返回值: DWORD-位图颜色数 //======================================================= DWORD CDib::GetNumOfColor() { UINT dwNumOfColor; if ((m_lpBmpInfoHeader->biClrUsed == 0) && (m_lpBmpInfoHeader->biBitCount < 9)) { switch (m_lpBmpInfoHeader->biBitCount) { case 1: dwNumOfColor = 2; break; case 4: dwNumOfColor = 16; break; case 8: dwNumOfColor = 256; } } else { dwNumOfColor = m_lpBmpInfoHeader->biClrUsed; //CString strColor; //strColor.Format("dwNumOfColor:%d",dwNumOfColor); //AfxMessageBox(strColor); } return dwNumOfColor; } //======================================================= // 函数功能: 计算位图颜色表长度 // 输入参数: 无 // 返回值: DWORD-位图颜色表长度 //======================================================= DWORD CDib::CalcRgbQuadLength() { DWORD dwNumOfColor = GetNumOfColor(); if(dwNumOfColor > 256) { dwNumOfColor = 0; } CString strColor; strColor.Format("dwNumOfColor:%d",dwNumOfColor); //AfxMessageBox(strColor); return dwNumOfColor * sizeof(RGBQUAD); } //======================================================= // 函数功能: 计算位图像素的起始位置 // 输入参数: 无 // 返回值: LPBYTE-位图像素的起始位置 //======================================================= LPBYTE CDib::GetBits() { return (m_lpDib+((LPBITMAPINFOHEADER)m_lpDib)->biSize+CalcRgbQuadLength()); } //======================================================= // 函数功能: 获取位图颜色表 // 输入参数: 无 // 返回值: LPRGBQUAD-位图颜色表指针 //======================================================= LPRGBQUAD CDib::GetRgbQuad() { return m_lpRgbQuad; } //======================================================= // 函数功能: 获取位图数据 // 输入参数: 无 // 返回值: LPBYTE-位图数据指针 //======================================================= LPBYTE CDib::GetData() { return m_lpData; } //======================================================= // 函数功能: 根据颜色表生成调色板 // 输入参数: 无 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::MakePalette() { // 计算颜色表长度 DWORD dwRgbQuadLength = CalcRgbQuadLength(); CString strColor; strColor.Format("dwRgbQuadLength:%d",dwRgbQuadLength); //AfxMessageBox(strColor); // 如果颜色表长度为0,则不生成逻辑调色板 if(dwRgbQuadLength == 0) { return FALSE; } //删除旧的调色板对象 if(m_hPalette != NULL) { DeleteObject(m_hPalette); m_hPalette = NULL; } // 申请缓冲区,初始化为0 DWORD dwNumOfColor = GetNumOfColor(); DWORD dwSize = 2 * sizeof(WORD) + dwNumOfColor * sizeof(PALETTEENTRY); LPLOGPALETTE lpLogPalette = (LPLOGPALETTE) new BYTE[dwSize]; memset(lpLogPalette, 0, dwSize); // 生成逻辑调色板 lpLogPalette->palVersion = 0x300; lpLogPalette->palNumEntries = dwNumOfColor; LPRGBQUAD lpRgbQuad = (LPRGBQUAD) m_lpRgbQuad; for(int i = 0; i < dwNumOfColor; i++) { lpLogPalette->palPalEntry[i].peRed = lpRgbQuad->rgbRed; lpLogPalette->palPalEntry[i].peGreen = lpRgbQuad->rgbGreen; lpLogPalette->palPalEntry[i].peBlue = lpRgbQuad->rgbBlue; lpLogPalette->palPalEntry[i].peFlags = 0; lpRgbQuad++; } // 创建逻辑调色板 m_hPalette = CreatePalette(lpLogPalette); // 释放缓冲区 delete [] lpLogPalette; return TRUE; } //======================================================= // 函数功能: 显示位图 // 输入参数: // CDC *pDC-设备环境指针 // CPoint origin-显示矩形区域的左上角 // CSize size-显示矩形区域的尺寸 // 返回值: // BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::Draw(CDC *pDC, CPoint origin, CSize size) { // 位图无效,无法绘制,返回错误 if(!IsValid()) { return FALSE; } // 旧的调色板句柄 HPALETTE hOldPalette = NULL; // 如果位图指针为空,则返回FALSE if(m_lpDib == NULL) { return FALSE; } // 如果位图有调色板,则选进设备环境中 if(m_hPalette != NULL) { hOldPalette = SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE); } // 设置位图伸缩模式 pDC->SetStretchBltMode(COLORONCOLOR); // 将位图在pDC所指向的设备上进行显示 StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy, 0, 0, GetWidth(), GetHeight(), m_lpData, m_lpBmpInfo, DIB_RGB_COLORS, SRCCOPY); // 恢复旧的调色板 if(hOldPalette != NULL) { SelectPalette(pDC->GetSafeHdc(), hOldPalette, TRUE); } return TRUE; } //======================================================= // 函数功能: 24位彩色位图转8位灰度位图 // 输入参数: 无 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::RgbToGrade() { // 位图无效,失败返回 if(!IsValid()) { AfxMessageBox("该位图无效!"); return FALSE; } // 是压缩位图,失败返回 if(m_lpBmpInfoHeader->biCompression != BI_RGB) { return FALSE; } // 如果不是灰度位图,才需要转换 if(!IsGrade()) { // 获取原位图信息 LONG lHeight = GetHeight(); LONG lWidth = GetWidth(); UINT uLineByte = GetLineByte(); // 计算灰度位图数据所需空间 UINT uGradeBmpLineByte = (lWidth * 8 / 8 + 3) / 4 * 4; DWORD dwGradeBmpDataSize = uGradeBmpLineByte * lHeight; // 计算灰度位图所需空间 DWORD dwGradeBmpSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256 + dwGradeBmpDataSize; // 设置灰度位图文件头 LPBITMAPFILEHEADER lpGradeBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)]; memset(lpGradeBmpFileHeader, 0, sizeof(BITMAPFILEHEADER)); lpGradeBmpFileHeader->bfType = 0x4d42; lpGradeBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + dwGradeBmpSize; lpGradeBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256; lpGradeBmpFileHeader->bfReserved1 = 0; lpGradeBmpFileHeader->bfReserved2 = 0; // 为灰度位图分配空间,并初始化为0 LPBYTE lpGradeBmp = (LPBYTE)new BYTE[dwGradeBmpSize]; memset(lpGradeBmp, 0, dwGradeBmpSize); // 设置灰度位图信息头 LPBITMAPINFOHEADER lpGradeBmpInfoHeader = (LPBITMAPINFOHEADER)(lpGradeBmp); lpGradeBmpInfoHeader->biBitCount = 8; lpGradeBmpInfoHeader->biClrImportant = 0; lpGradeBmpInfoHeader->biClrUsed = 256; lpGradeBmpInfoHeader->biCompression = BI_RGB; lpGradeBmpInfoHeader->biHeight = lHeight; lpGradeBmpInfoHeader->biPlanes = 1; lpGradeBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER); lpGradeBmpInfoHeader->biSizeImage = dwGradeBmpDataSize; lpGradeBmpInfoHeader->biWidth = lWidth; lpGradeBmpInfoHeader->biXPelsPerMeter = m_lpBmpInfoHeader->biXPelsPerMeter; lpGradeBmpInfoHeader->biYPelsPerMeter = m_lpBmpInfoHeader->biYPelsPerMeter; // 设置灰度位图颜色表 LPRGBQUAD lpGradeBmpRgbQuad = (LPRGBQUAD)(lpGradeBmp + sizeof(BITMAPINFOHEADER)); // 初始化8位灰度图的调色板信息 LPRGBQUAD lpRgbQuad; for(int k = 0; k < 256; k++) { lpRgbQuad = (LPRGBQUAD)(lpGradeBmpRgbQuad + k); lpRgbQuad->rgbBlue = k; lpRgbQuad->rgbGreen = k; lpRgbQuad->rgbRed = k; lpRgbQuad->rgbReserved = 0; } // 灰度位图数据处理 BYTE r, g, b; LPBYTE lpGradeBmpData = (LPBYTE)(lpGradeBmp + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256); // 进行颜色转换 for(int i = 0; i < lHeight; i++) { for(int j = 0; j < lWidth; j++) { b = m_lpData[i * uLineByte + 3 * j]; g = m_lpData[i * uLineByte + 3 * j + 1]; r = m_lpData[i * uLineByte + 3 * j + 2]; lpGradeBmpData[i * uGradeBmpLineByte + j] = (BYTE)(0.299 * r + 0.587 * g + 0.114 * b); } } // 释放原有位图空间 Empty(FALSE); // 重新设定原位图指针指向 m_lpBmpFileHeader = lpGradeBmpFileHeader; m_lpDib = lpGradeBmp; m_lpBmpInfo = (LPBITMAPINFO)(lpGradeBmp); m_lpBmpInfoHeader = lpGradeBmpInfoHeader; m_lpRgbQuad = lpGradeBmpRgbQuad; m_lpData = lpGradeBmpData; // 设置颜色表标志 m_bHasRgbQuad = TRUE; // 设置位图有效标志 m_bValid = TRUE; // 生成调色板 MakePalette(); } AfxMessageBox("转换成功,请保存8位灰度图!"); return TRUE; } //======================================================= // 函数功能: 8位彩色位图转24位彩色图 // 输入参数: 无 // 返回值: BOOL-TRUE 成功;FALSE 失败 //======================================================= BOOL CDib::GraphToRgb() { // 位图无效,失败返回 if(!IsValid()) { AfxMessageBox("该位图无效!"); return FALSE; } // 是压缩位图,失败返回 if(m_lpBmpInfoHeader->biCompression != BI_RGB) { return FALSE; } if(GetBitCount()==24) { AfxMessageBox("该位图已是24位,不用转换!"); return FALSE; } if(GetBitCount()!=8) { AfxMessageBox("该位图不是8位,不能转换,请用画图软件将其另存为成24位图!"); return FALSE; } // 如果不是24位图,才需要转换 // 获取原位图信息 LONG lHeight = GetHeight(); LONG lWidth = GetWidth(); UINT uLineByte = GetLineByte(); // 计算24位图数据所需空间 //return (GetWidth() * GetBitCount() /8 + 3) / 4 * 4; UINT uGradeBmpLineByte = (lWidth * 24/8 + 3) / 4 * 4; DWORD dwGradeBmpDataSize = uGradeBmpLineByte * lHeight; // 计算24位图所需空间 DWORD dwGradeBmpSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 0 + dwGradeBmpDataSize; // 设置24位图文件头 LPBITMAPFILEHEADER lpGradeBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)]; memset(lpGradeBmpFileHeader, 0, sizeof(BITMAPFILEHEADER)); lpGradeBmpFileHeader->bfType = 0x4d42; lpGradeBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + dwGradeBmpSize; lpGradeBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); lpGradeBmpFileHeader->bfReserved1 = 0; lpGradeBmpFileHeader->bfReserved2 = 0; // 为24位图分配空间,并初始化为0 LPBYTE lpGradeBmp = (LPBYTE)new BYTE[dwGradeBmpSize]; memset(lpGradeBmp, 0, dwGradeBmpSize); // 设置24位图信息头 LPBITMAPINFOHEADER lpGradeBmpInfoHeader = (LPBITMAPINFOHEADER)(lpGradeBmp); lpGradeBmpInfoHeader->biBitCount = 24; lpGradeBmpInfoHeader->biClrImportant = 0; lpGradeBmpInfoHeader->biClrUsed = 0; lpGradeBmpInfoHeader->biCompression = BI_RGB; lpGradeBmpInfoHeader->biHeight = lHeight; lpGradeBmpInfoHeader->biPlanes = 1; lpGradeBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER); lpGradeBmpInfoHeader->biSizeImage = dwGradeBmpDataSize; lpGradeBmpInfoHeader->biWidth = lWidth; lpGradeBmpInfoHeader->biXPelsPerMeter = 0; lpGradeBmpInfoHeader->biYPelsPerMeter = 0; // 设置24位图颜色表 //LPRGBQUAD lpGradeBmpRgbQuad = (LPRGBQUAD)(lpGradeBmp + sizeof(BITMAPINFOHEADER)); // 初始化8位灰度图的调色板信息 /*LPRGBQUAD lpRgbQuad; for(int k = 0; k < 256; k++) { lpRgbQuad = (LPRGBQUAD)(lpGradeBmpRgbQuad + k); lpRgbQuad->rgbBlue = k; lpRgbQuad->rgbGreen = k; lpRgbQuad->rgbRed = k; lpRgbQuad->rgbReserved = 0; }*/ // 24位图数据处理 //BYTE r, g, b; //LPBYTE lpGradeBmpData = (LPBYTE)(lpGradeBmp + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 0); // 进行颜色转换 LONG lineBytes24=(lWidth * 24 / 8 + 3) / 4 * 4; LONG lineBytes8=(lWidth * 8 / 8 + 3) / 4 * 4; //LONG lineBytes24=(lWidth * 24 + 31) / 32 * 4; //LONG lineBytes8=(lWidth * 8 + 31) / 32 * 4; //CString strColor; //strColor.Format("lineBytes24 :%d,lineBytes8 :%d", lineBytes24,lineBytes8); //AfxMessageBox(strColor); LPBYTE lpGradeBmpData =(LPBYTE) new BYTE[lHeight*lineBytes24]; for(int i = 0; i < lHeight; i++) { for(int j = 0,n=0; j < lineBytes8; j++,n++) { BYTE gray=*(m_lpData+lineBytes8*i+j); *(lpGradeBmpData+lineBytes24*i+n)=gray; n++; *(lpGradeBmpData+lineBytes24*i+n)=gray; n++; *(lpGradeBmpData+lineBytes24*i+n)=gray; /*lpGradeBmpData[lineBytes24*i+j ]= m_lpData[lineBytes8*i+j]; lpGradeBmpData[lineBytes24*i+j+1]= m_lpData[lineBytes8*i+j]; lpGradeBmpData[lineBytes24*i+j+2]= m_lpData[lineBytes8*i+j];*/ } } // 释放原有位图空间 //AfxMessageBox("转换成功"); Empty(FALSE); // 重新设定原位图指针指向 m_lpBmpFileHeader = lpGradeBmpFileHeader; m_lpDib = lpGradeBmp; m_lpBmpInfo = (LPBITMAPINFO)(lpGradeBmp); m_lpBmpInfoHeader = lpGradeBmpInfoHeader; //m_lpRgbQuad = lpGradeBmpRgbQuad; m_lpData = lpGradeBmpData; // 设置颜色表标志 //m_bHasRgbQuad = TRUE; // 设置位图有效标志 m_bValid = TRUE; // 生成调色板 //MakePalette(); AfxMessageBox("转换成功,请保存24位图!"); return TRUE; } //======================================================= // 函数功能: 判断是否含有颜色表 // 输入参数: 无 // 返回值: 判断结果:TRUE-含有颜色表;FALSE-不含颜色表 //======================================================= BOOL CDib::HasRgbQuad() { return m_bHasRgbQuad; } //======================================================= // 函数功能: 判断是否是灰度图 // 输入参数: 无 // 返回值: 判断结果:TRUE-是灰度图;FALSE-是彩色图 //======================================================= BOOL CDib::IsGrade() { return (GetBitCount() < 9 && GetBitCount() > 0); } //======================================================= // 函数功能: 判断位图是否有效 // 输入参数: 无 // 返回值: 判断结果:TRUE-位图有效;FALSE-位图无效 //======================================================= BOOL CDib::IsValid() { return m_bValid; } //======================================================= // 函数功能: 清理空间 // 输入参数: BOOL bFlag-TRUE 全部清空;FALSE 部分清空 // 返回值: 无 //======================================================= void CDib::Empty(BOOL bFlag) { // 文件名清空 if(bFlag) { strcpy(m_fileName, ""); } // 释放位图文件头指针空间 if(m_lpBmpFileHeader != NULL) { delete [] m_lpBmpFileHeader; m_lpBmpFileHeader = NULL; } // 释放位图指针空间 if(m_lpDib != NULL) { delete [] m_lpDib; m_lpDib = NULL; m_lpBmpInfo = NULL; m_lpBmpInfoHeader = NULL; m_lpRgbQuad = NULL; m_lpData = NULL; } // 释放调色板 if(m_hPalette != NULL) { DeleteObject(m_hPalette); m_hPalette = NULL; } // 设置不含颜色表 m_bHasRgbQuad = FALSE; // 设置位图无效 m_bValid = FALSE; } BOOL CDib::CountClr(int r,int g,int b,int fanwei) { m_rgbsum=0; // 位图无效,失败返回 if(!IsValid()) { AfxMessageBox("该位图无效!"); return FALSE; } if(GetBitCount()!=24) { CString str; str.Format("该位图是%d位,无法统计,请用画图软件将其另存为成24位图!",GetBitCount()); AfxMessageBox(str); return FALSE; } // 是压缩位图,失败返回 if(m_lpBmpInfoHeader->biCompression != BI_RGB) { return FALSE; } //LoadFromFile((LPCTSTR)m_fileName); // 获取原位图信息 LONG lHeight=GetHeight(); LONG lWidth=GetWidth(); UINT uLineByte=GetLineByte(); // 灰度位图数据处理 int R=0, G=0, B=0; //int R1=0, G1=0, B1=0; // 进行颜色转换 int clrfanwei; int clrjizhun=0.299 * r + 0.587 * g + 0.114 * b;//基准灰度 for(int i = 0; i < lHeight; i++) { for(int j = 0; j < lWidth; j++) { //(BYTE)(0.299 * r + 0.587 * g + 0.114 * b); B = *(m_lpData+i * uLineByte + 3 * j); G = *(m_lpData+i * uLineByte + 3 * j + 1); R = *(m_lpData+i * uLineByte + 3 * j + 2); int someonegray=0.299 * R + 0.587 * G + 0.114 * B; if(clrjizhun<128)//标定深色区域为缺陷 { clrfanwei=clrjizhun+fanwei; if(clrfanwei>255) clrfanwei=255; if(someonegray<=clrfanwei && someonegray>=clrjizhun) { if(r==255 && g==0 && b==0) { *(m_lpData+i * uLineByte + 3 * j)=255; *(m_lpData+i * uLineByte + 3 * j + 1)=0; *(m_lpData+i * uLineByte + 3 * j + 2)=0; } else { *(m_lpData+i * uLineByte + 3 * j)=0; *(m_lpData+i * uLineByte + 3 * j + 1)=0; *(m_lpData+i * uLineByte + 3 * j + 2)=255; } m_rgbsum++; } } else//标定浅色区域为缺陷 { clrfanwei=clrjizhun-fanwei; if(clrfanwei<0) clrfanwei=0; if(someonegray>=clrfanwei && someonegray<=clrjizhun) { if(r==255 && g==0 && b==0) { *(m_lpData+i * uLineByte + 3 * j)=255; *(m_lpData+i * uLineByte + 3 * j + 1)=0; *(m_lpData+i * uLineByte + 3 * j + 2)=0; } else { *(m_lpData+i * uLineByte + 3 * j)=0; *(m_lpData+i * uLineByte + 3 * j + 1)=0; *(m_lpData+i * uLineByte + 3 * j + 2)=255; } m_rgbsum++; } } } } return TRUE; } BOOL CDib::TranslationRight(long lXOffset,long lYOffset) { long i; long j; long lWidth,lHeight; lWidth=GetWidth(); lHeight=GetHeight(); //LPBYTE lpSrcDIBBits; long lLineBytes; lLineBytes=GetLineByte(); if (lXOffset<=0 || lYOffset<=0) { return FALSE; } for(i=0;i<lHeight;i+=(2*lYOffset)) { int index=0; do { for(j=0;j<GetWidth();j++) { if(index<lYOffset) { if((lWidth-j-lXOffset)>=0) { *(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j))=*(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j-lXOffset)); *(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j) + 1)=*(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j-lXOffset) + 1); *(m_lpData+(i+index) * lLineBytes + 3 * (lWidth-j) + 2)=*(m_lpData+(i+index)* lLineBytes + 3 * (lWidth-j-lXOffset) + 2); } else { break; } } else { if((i+index)<lHeight) { *(m_lpData+(i+index) * lLineBytes + 3 * j)=*(m_lpData+(i+index) * lLineBytes + 3 * j); *(m_lpData+(i+index) * lLineBytes + 3 * j + 1)=*(m_lpData+(i+index) * lLineBytes + 3 * j + 1); *(m_lpData+(i+index) * lLineBytes + 3 * j + 2)=*(m_lpData+(i+index) * lLineBytes + 3 * j + 2); } else { break; } } } index++; //AfxMessageBox("平移中!"); } while(index<2*lYOffset); } return TRUE; } BOOL CDib::TranslationLeft(long lXOffset,long lYOffset) { long i; long j; long lWidth,lHeight; lWidth=GetWidth(); lHeight=GetHeight(); //LPBYTE lpSrcDIBBits; long lLineBytes; lLineBytes=GetLineByte(); if (lXOffset<=0 || lYOffset<=0) { return FALSE; } for(i=0;i<lHeight;i+=(2*lYOffset)) { int index=0; do { for(j=0;j<GetWidth();j++) { if(index<lYOffset) { if((j+lXOffset)<=lWidth) { *(m_lpData+(i+index) * lLineBytes + 3 * j)=*(m_lpData+(i+index) * lLineBytes + 3 * (j+lXOffset)); *(m_lpData+(i+index) * lLineBytes + 3 * j + 1)=*(m_lpData+(i+index) * lLineBytes + 3 * (j+lXOffset) + 1); *(m_lpData+(i+index) * lLineBytes + 3 * j + 2)=*(m_lpData+(i+index)* lLineBytes + 3 * (j+lXOffset) + 2); } else { break; } } else { if((i+index)<lHeight) { *(m_lpData+(i+index) * lLineBytes + 3 * j)=*(m_lpData+(i+index) * lLineBytes + 3 * j); *(m_lpData+(i+index) * lLineBytes + 3 * j + 1)=*(m_lpData+(i+index) * lLineBytes + 3 * j + 1); *(m_lpData+(i+index) * lLineBytes + 3 * j + 2)=*(m_lpData+(i+index) * lLineBytes + 3 * j + 2); } else { break; } } } index++; //AfxMessageBox("平移中!"); } while(index<2*lYOffset); } return TRUE; }
///////////////////////图像处理函数////////////////////////////////////// void ChangeBrightness(CDib* pOrigDib, int nChange);//nChange是亮度的改变量 //改变图像亮度 pOrigDib 为原先的图像 void ChangeContrast(CDib* pOrigDib, int nChange);//nChange是对比度的改变量 //改变图像对比度 pOrigDib 为原先的图像 void Render(CDib* pOrigDib, BYTE byRed, BYTE byGreen, BYTE byBlue); //着色 void Scale(CDib* pOrigDib, int nWidth, int nHeight); //缩放图像,pOrigDib 为原先的图像,nWidth为缩放后的宽度, nHeight为缩放后的高度 void Rotate(CDib* pOrigDib, int nXCenter, int nYCenter, float fTheta); //旋转图像,pOrigDib为原图,(nXCenter,nYCenter)为旋转中心的坐标,fTheta为旋转角度 void MirrorX(CDib* pOrigDib, int x, int y, int nWidth, int nHeight); //垂直方向的镜像变换,(x,y)为起始点,nWidth,nHeight为镜像变换的区域 void MirrorY(CDib* pOirgDib, int x, int y, int nWidth, int nHeight); //水平方向的镜像变换,(x,y)为起始点,nWidth,nHeight为镜像变换的区域 void ConvolutionFilter(CDib* pOrigDib, int* pnKernel, int nRows, int nCols); //卷积滤波器,pnKernel为 nRows * nCols 的卷积核 void PercentileFilter(CDib* pOrigDib, int nPercentage, int nRows, int nCols); //百分比滤波器, nPercentage确定百分比, 模板为 nRows * nCols void ReverseColor(); //图像反色,原先x, 变为255 - x void DibCopy(CDib* pOrigDib); //重载 = 操作 void ClipRect(CDib* pDib, int x, int y, int nWidth, int nHeight); //剪切操作 //////////////////////////////////////////////////////////////////////////////// /////////////////文件存取函数/////////////////////////////////////////////////// void SaveToBMPFile(const char* pstFileName); //存为位图文件,按其自身的位数存储 void SaveToJPGFile(const char* pszJpgFileName,int nQuality); //存为JPG文件 void LoadFromJPGFile(const char* psrFileName); //从JPG文件中读取 void LoadFromBMPFile(const char* pszDibFileName); //从BMP文件中读取 void SaveAs256Bitmap(const char *pszDibFileName); //存为256色位图 void SaveAsBWBitmap(const char *pszDibFileName); //存为单色位图 void SaveAs256GrayBitmap(const char *pszDibFileName); //存为256级灰度位图 void SaveAs24BitBMPFile(const char* pstFileName); //存为24位位图 //////////////////////////////////////////////////////////////////////////////// ////////////////图像格式转换函数//////////////////////////////////////////////// bool GetHistValue(int nModulus, int nCoef, int* pRed, int* pGreen, int* pBlue, int* pGray); //取得直方图的统计数值 bool ChangeTo256Gray(CDib* pOrigDib = NULL); //将图像转换成256色灰度图,pOrigDib为待转换的图像,缺省则转换自身 void SetTo256Gray(); bool ChangeToBW(CDib* pOrigDib = NULL, int byCritical = 128); //二值化,BW: black & white, byCritical为阈值,缺省为128 void SetToBW(); void QuantizeColor(LPBYTE lpbyDibBits24, int nScanWidth, int nScanHeight, LPBYTE lpbyDibBits8, CPalette* pPalette); //对颜色进行量化, 结果被保存在逻辑调色盘pPalette中, 同时将24位数据量化为8位数据, 并存放于lpbyDdbBits8之中 //该算法保留系统默认的20种静态颜色 void SetTo24Bitmap(); //格式转换,置颜色深度为24位真彩色 void SetTo256Color(); //格式转换, 置颜色深度为256色(8位) ////////////////////////////////////////////////////////////////////////////////// #ifdef _DEBUG virtual void Dump(CDumpContext& dc) const; virtual void AssertValid() const; #endif private: void Sort(int *p, int length); //methods void Init(); int IncreaseContrast(int nOrigColor,int nChange); //OrigColor为原值,函数返回改变后的值 int DecreaseContrast(int nOrigColor,int nChange); BYTE* GetDib24Bit(DWORD nOrigSize, int nWidth, int nHeight); //将图像格式转换为24位 HPALETTE CreateBitmapPalette(); //attributes BYTE m_byUpper; //像素颜色的上阀值 BYTE m_byLower; //像素颜色的下阀值 }; #endif/*/////////////////////////////////////////////////////////////////////// // End of file 'Dib.h' // /////////////////////////////////////////////////////////////////////////////*/

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值