读取 定义DIB类 BMP文件中依次为文件头、位图信息头、调色板
DIB.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 #pragma once #include "framework.h" #pragma pack(2) struct BMPFileHeader { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; }; #pragma pack(2) struct BMPInfoHeader { DWORD biSize; DWORD biWidth; DWORD biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; DWORD biXPelsPerMeter; DWORD biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; }; #pragma pack(1) struct RGBQuad { BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved; }; class DIB { public : BMPFileHeader m_BMPfileheader; BMPInfoHeader m_BMPinfoheader; unsigned char * m_BMPdata; RGBQuad* m_palette; int m_width; int m_height; int m_colornb; public : DIB(); virtual ~DIB(); void Read (const CString& fileName) ; void Write (const CString& fileName) ; void Clear () ; void Grayscale () ; };
DIB.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 #include "pch.h" #include "DIB.h" DIB::DIB() { m_BMPdata = NULL ; m_palette = NULL ; } DIB::~DIB() { Clear(); } void DIB::Clear () { if (m_BMPdata) { delete [] m_BMPdata; m_BMPdata = NULL ; } if (m_palette) { delete [] m_palette; m_palette = 0 ; } } void DIB::Read (const CString& fileName) { Clear(); CFile file; VERIFY(file.Open(fileName, CFile::modeRead)); file.Read(&m_BMPfileheader, sizeof (BMPFileHeader)); if (m_BMPfileheader.bfType == 0x4D42 ) { file.Read(&m_BMPinfoheader, sizeof (BMPInfoHeader)); m_width = m_BMPinfoheader.biWidth; m_height = m_BMPinfoheader.biHeight; int bit = m_BMPinfoheader.biBitCount; if (bit <= 16 ) { AfxMessageBox(_T("Used palette" )); m_colornb = 0 ; if (m_BMPinfoheader.biClrUsed == 0 ) m_colornb = (1 << bit); else m_colornb = m_BMPinfoheader.biClrUsed; m_palette = new RGBQuad[m_colornb]; file.Read(m_palette, sizeof (RGBQuad) * m_colornb); } file.Seek(m_BMPfileheader.bfOffBits, CFile::begin); m_BMPdata = new unsigned char [m_BMPinfoheader.biSizeImage]; file.Read(m_BMPdata, m_BMPinfoheader.biSizeImage); file.Close(); } else { file.Close(); AfxMessageBox(_T("Not a bmp image!" )); return ; } } void DIB::Write (const CString& fileName) { CFile BMPFile; VERIFY(BMPFile.Open(fileName, CFile::modeCreate | CFile::modeWrite)); try { BMPFile.Write(&m_BMPfileheader, sizeof (BMPFileHeader)); BMPFile.Write(&m_BMPinfoheader, sizeof (BMPInfoHeader)); if (m_palette != NULL ) BMPFile.Write(m_palette, sizeof (RGBQuad) * m_colornb); BMPFile.Write(m_BMPdata, m_BMPinfoheader.biSizeImage); } catch (CException * pe) { pe->Delete(); AfxMessageBox(_T("write error" )); BMPFile.Close(); return ; } BMPFile.Close(); } void DIB::Grayscale () { for (int j = 0 ; j < m_height; j++) { for (int i = 0 ; i < m_width; i++) { int index = j * m_width + i; unsigned char r = m_BMPdata[3 * index]; unsigned char g = m_BMPdata[3 * index + 1 ]; unsigned char b = m_BMPdata[3 * index + 2 ]; unsigned gray = (r * 0.299 + g * 0.587 + b * 0.114 ); m_BMPdata[3 * index] = gray; m_BMPdata[3 * index + 1 ] = gray; m_BMPdata[3 * index + 2 ] = gray; } } }
在{项目名}View.h
中添加类成员DIB* m_dib
,并using uchar = unsigned char
在{项目名}View.cpp
中修改OnFileOpen
,添加读取代码
1 2 3 4 5 6 CFileDialog dlg (TRUE) ; if (dlg.DoModal() == IDOK) { bitmapPath = dlg.GetPathName(); m_dib = new DIB; m_dib->Read(bitmapPath); }
显示 在{项目名}View.cpp
中修改OnDraw
,添加绘制代码
逐像素绘制 这里只考虑24位真彩色位图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 uchar* image = m_dib->m_BMPdata; int height = m_dib->m_height;int width = m_dib->m_width;int width3 = width * 3 ;for (int i = 0 ; i < height; i++) { for (int j = 0 ; j < width; j++) { uchar* pos = image + width3 * i + j * 3 ; uchar b = *pos; pos++; uchar g = *pos; pos++; uchar r = *pos; pDC->SetPixelV(10 + j, 10 + height - i, RGB(r, g, b)); } }
调用MFC接口显示 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 HBITMAP m_hBitmap; m_hBitmap = (HBITMAP)LoadImage(NULL , bitMapPath, IMAGE_BITMAP, 0 , 0 , LR_LOADFROMFILE | LR_DEFAULTSIZE | LR_CREATEDIBSECTION); if (m_bitmap.m_hObject) { m_bitmap.Detach(); } m_bitmap.Attach(m_hBitmap); CRect rect; GetClientRect(&rect); int m_showX = 0 ;int m_showY = 0 ;int m_nWindowWidth = rect.right - rect.left; int m_nWindowHeight = rect.bottom - rect.top; CDC dcBmp; if (!dcBmp.CreateCompatibleDC(pDC)) return ; BITMAP m_bmp; m_bitmap.GetBitmap(&m_bmp); CBitmap* pbmpOld = NULL ; dcBmp.SelectObject(&m_bitmap); pDC->StretchBlt(0 , 0 , m_bmp.bmWidth, m_bmp.bmHeight, &dcBmp, 0 , 0 , m_bmp.bmWidth, m_bmp.bmHeight, SRCCOPY); dcBmp.SelectObject(pbmpOld); DeleteObject(&m_bitmap); dcBmp.DeleteDC();