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


     

  • 相关阅读:
    faster with MyISAM tables than with InnoDB or NDB tables
    w-BIG TABLE 1-toSMALLtable @-toMEMORY
    Indexing and Hashing
    MEMORY Storage Engine MEMORY Tables TEMPORARY TABLE max_heap_table_size
    controlling the variance of request response times and not just worrying about maximizing queries per second
    Variance
    Population Mean
    12.162s 1805.867s
    situations where MyISAM will be faster than InnoDB
    1920.154s 0.309s 30817
  • 原文地址:https://www.cnblogs.com/lizhengjin/p/1269420.html
Copyright © 2011-2022 走看看