zoukankan      html  css  js  c++  java
  • 位图的读写

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

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

    是真实感图形绘制的基础

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

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

    #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();


     

  • 相关阅读:
    迭代器、可迭代对象、生成器
    提问的智慧
    爬虫【自动登陆github和抽屉】
    爬虫【爬取汽车之家新闻】
    Python多线程-守护线程
    Python的多线程
    一个简单的Python多线程
    Python实现SSH传输文件(sftp)
    Python实现SSH连接远程服务器
    实验吧CTF题库-WEB题(部分)
  • 原文地址:https://www.cnblogs.com/lizhengjin/p/1269420.html
Copyright © 2011-2022 走看看