直接在24位位图中访问得到像素.docx
- 文档编号:28828060
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:24
- 大小:20.03KB
直接在24位位图中访问得到像素.docx
《直接在24位位图中访问得到像素.docx》由会员分享,可在线阅读,更多相关《直接在24位位图中访问得到像素.docx(24页珍藏版)》请在冰豆网上搜索。
直接在24位位图中访问得到像素
Directly Accessing Pixels in a 24-bit Bitmap
Environment:
VC5/6, Win9x
This article describes how to display 24-bit (TrueColor) bitmaps which are created during run-time by directly accessing the bitmap's bit image.
The code in this article uses the CDib class, developed by David J. Kruglinski in his book Inside Visual C++, 4th edition. The CDib class is copyrighted by Microsoft, and can be used in your programs as long as you mention their name. The CDib class is included at the end of this document.
1. Create a CDib object, and allocate memory.
This will typically be done in CView:
:
OnInitialUpdate, or some such. It's done in the following way:
// Create a compatible DC
CDC* pDC = GetDC();
ASSERT(pDC);
CDC dcCompat;
dcCompat.CreateCompatibleDC(pDC);
ReleaseDC(pDC);
// Allocate memory for the bitmap
m_pDib = new CDib(CSize(XSIZE,YSIZE), // size of the bitmap
24); // bits per pixel
VERIFY(m_pDib->CreateSection(&dcCompat)); // allocate memory for bitmap
2. Fill the bitmap data.
You now have a memory region, allocated by Windows, in which you can write the output information. This memory region is accessed from m_pDib->m_lpImage, and contains a series of three-byte (R,G,B) pixels. As an example, you can get a nice rainbow-color image using the following code:
int x,y;
BYTE* dibits = m_pDib->m_lpImage;
for(x=0; x
*(dibits++) = doc(doc.XSize()-x-1,y); // green
*(dibits++) = doc(x,doc.YSize()-y-1); // blue
}
Where we used the function doc, defined as follows (intended for bitmaps of size 512x512 pixels, more or less):
BYTE doc(int x,int y) {
return (BYTE)(sqrt(x*x+y*y)/4);
}
3. Display the bitmap.
From within CView:
:
OnDraw, use the following to display the bitmap:
m_pDib->Draw(pDC,m_rectDraw.TopLeft(),m_rectDraw.Size());
where m_rectDraw is a logical-coordinate rectangle defining the position in which we want to place the bitmap. The bitmap is shrunk or expanded using the StretchDIBits function so that it will fit into this rectangle.
4. Delete the DIB.
Don't forget to deallocate the CDib object when you're done. The constructor deallocates all memory associate with the DIB, including the memory of the actual image.
delete m_pDib;
File:
CDib.h -- CDib class header file
// cdib.h declaration for Inside Visual C++ CDib class
#ifndef _INSIDE_VISUAL_CPP_CDIB
#define _INSIDE_VISUAL_CPP_CDIB
class CDib :
public CObject
{
enum Alloc {noAlloc, crtAlloc, heapAlloc};
DECLARE_SERIAL(CDib)
public:
LPVOID m_lpvColorTable;
HBITMAP m_hBitmap;
LPBYTE m_lpImage; // starting address of DIB bits
LPBITMAPINFOHEADER m_lpBMIH; // buffer containing the BITMAPINFOHEADER
private:
HGLOBAL m_hGlobal; // For external windows we need to free;
// could be allocated by this class or allocated externally
Alloc m_nBmihAlloc;
Alloc m_nImageAlloc;
DWORD m_dwSizeImage; // of bits -- not BITMAPINFOHEADER or BITMAPFILEHEADER
int m_nColorTableEntries;
HANDLE m_hFile;
HANDLE m_hMap;
LPVOID m_lpvFile;
HPALETTE m_hPalette;
public:
CDib();
CDib(CSize size, int nBitCount);// builds BITMAPINFOHEADER
~CDib();
int GetSizeImage() {return m_dwSizeImage;}
int GetSizeHeader()
{return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pBMIH->biClrImportant = m_nColorTableEntries;
ComputeMetrics();
memset(m_lpvColorTable, 0, sizeof(RGBQUAD) * m_nColorTableEntries);
m_lpImage = NULL; // no data yet
}
#endif // _INSIDE_VISUAL_CPP_CDIB
File CDib.cpp -- CDib class definition file
// cdib.cpp
// new version for WIN32
#include "stdafx.h"
#include "cdib.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_SERIAL(CDib, CObject, 0);
CDib:
:
CDib()
{
m_hFile = NULL;
m_hBitmap = NULL;
m_hPalette = NULL;
m_nBmihAlloc = m_nImageAlloc = noAlloc;
Empty();
}
CDib:
:
CDib(CSize size, int nBitCount)
{
m_hFile = NULL;
m_hBitmap = NULL;
m_hPalette = NULL;
m_nBmihAlloc = m_nImageAlloc = noAlloc;
Empty();
ComputePaletteSize(nBitCount);
m_lpBMIH = (LPBITMAPINFOHEADER) new
char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries];
m_nBmihAlloc = crtAlloc;
m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER);
m_lpBMIH->biWidth = size.cx;
m_lpBMIH->biHeight = size.cy;
m_lpBMIH->biPlanes = 1;
m_lpBMIH->biBitCount = nBitCount;
m_lpBMIH->biCompression = BI_RGB;
m_lpBMIH->biSizeImage = 0;
m_lpBMIH->biXPelsPerMeter = 0;
m_lpBMIH->biYPelsPerMeter = 0;
m_lpBMIH->biClrUsed = m_nColorTableEntries;
m_lpBMIH->biClrImportant = m_nColorTableEntries;
ComputeMetrics();
memset(m_lpvColorTable, 0, sizeof(RGBQUAD) * m_nColorTableEntries);
m_lpImage = NULL; // no data yet
}
CDib:
:
~CDib()
{
Empty();
}
CSize CDib:
:
GetDimensions()
{
if(m_lpBMIH == NULL) return CSize(0, 0);
return CSize((int) m_lpBMIH->biWidth, (int) m_lpBMIH->biHeight);
}
BOOL CDib:
:
AttachMapFile(const char* strPathname, BOOL bShare) // for reading
{
// if we open the same file twice, Windows treats it as 2 separate files
// doesn't work with rare BMP files where # palette entries > biClrUsed
HANDLE hFile = :
:
CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ,
bShare ?
FILE_SHARE_READ :
0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ASSERT(hFile !
= INVALID_HANDLE_VALUE);
DWORD dwFileSize = :
:
GetFileSize(hFile, NULL);
HANDLE hMap = :
:
CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
DWORD dwErr = :
:
GetLastError();
if(hMap == NULL) {
AfxMessageBox("Empty bitmap file");
return FALSE;
}
LPVOID lpvFile = :
:
MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); // map whole file
ASSERT(lpvFile !
= NULL);
if(((LPBITMAPFILEHEADER) lpvFile)->bfType !
= 0x4d42) {
AfxMessageBox("Invalid bitmap file");
DetachMapFile();
return FALSE;
}
AttachMemory((LPBYTE) lpvFile + sizeof(BITMAPFILEHEADER));
m_lpvFile = lpvFile;
m_hFile = hFile;
m_hMap = hMap;
return TRUE;
}
BOOL CDib:
:
CopyToMapFile(const char* strPathname)
{
// copies DIB to a new file, releases prior pointers
// if you previously used CreateSection, the HBITMAP will be NULL (and unusable)
BITMAPFILEHEADER bmfh;
bmfh.bfType = 0x4d42; // 'BM'
bmfh.bfSize = m_dwSizeImage + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * m_nColorTableEntries + sizeof(BITMAPFILEHEADER);
// meaning of bfSize open to interpretation
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * m_nColorTableEntries;
HANDLE hFile = :
:
CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
ASSERT(hFile !
= INVALID_HANDLE_VALUE);
int nSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * m_nColorTableEntries + m_dwSizeImage;
HANDLE hMap = :
:
CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, nSize, NULL);
DWORD dwErr = :
:
GetLastError();
ASSERT(hMap !
= NULL);
LPVOID lpvFile = :
:
MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); // map whole file
ASSERT(lpvFile !
= NULL);
LPBYTE lpbCurrent = (LPBYTE) lpvFile;
memcpy(lpbCurrent, &bmfh, sizeof(BITMAPFILEHEADER)); // file header
lpbCurrent += sizeof(BITMAPFILEHEADER);
LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) lpbCurrent;
memcpy(lpbCurrent, m_lpBMIH,
sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries); // info
lpbCurrent += sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
memcpy(lpbCurrent, m_lpImage, m_dwSizeImage); // bit image
DWORD dwSizeImage = m_dwSizeImage;
Empty();
m_dwSizeImage = dwSizeImage;
m_nBmihAlloc = m_nImageAlloc = noAlloc;
m_lpBMIH = lpBMIH;
m_lpImage = lpbCurrent;
m_hFile = hFile;
m_hMap = hMap;
m_lpvFile = lpvFile;
ComputePaletteSize(m_lpBMIH->biBitCount);
ComputeMetrics();
MakePalette();
return TRUE;
}
BOOL CDib:
:
AttachMemory(LPVOID lpvMem, BOOL bMustDelete, HGLOBAL hGlobal)
{
// assumes contiguous BITMAPINFOHEADER, color table, image
// color table could be zero length
Empty();
m_hGlobal = hGlobal;
if(bMustDelete == FALSE) {
m_nBmihAlloc = noAlloc;
}
else {
m_nBmihAlloc = ((hGlobal == NULL) ?
crtAlloc :
heapAlloc);
}
try {
m_lpBMIH = (LPBITMAPINFOHEADER) lpvMem;
ComputeMetrics();
ComputePaletteSize(m_lpBMIH->biBitCount);
m_lpImage = (LPBYTE) m_lpvColorTable + sizeof(RGBQUAD) * m_nColorTableEntries;
MakePalette();
}
catch(CException* pe) {
AfxMessageBox("AttachMemory error");
pe->Delete();
return FALSE;
}
return TRUE;
}
UINT CDib:
:
UsePalette(CDC* pDC, BOOL bBackground /* = FALSE */)
{
if(m_hPalette == NULL) return 0;
HDC hdc = pDC->GetSafeHdc();
:
:
SelectPalette(hdc, m_hPalette, bBackground);
return :
:
RealizePalette(hdc);
}
BOOL CDib:
:
Draw(CDC* pDC, CPoint origin, CSize size)
{
if(m_lpBMIH == NULL) return FALSE;
if(m_hPalette !
= NULL) {
:
:
SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE);
}
pDC->SetStretchBltMode(COLORONCOLOR);
:
:
StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy,
0, 0, m_lpBMIH->biWidth, m_lpBMIH->biHeight,
m_lpImage, (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS, SRCCOPY);
return TRUE;
}
HBITMAP CDib:
:
CreateSection(CDC* pDC /* = NULL */)
{
if(m_lpBMIH == NULL) return NULL;
if(m_lpImage !
= NULL) return NULL; // can only do this if image doesn't exist
m_hBitmap = :
:
CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_lpBMIH,
DIB_RGB_COLORS,(LPVOID*) &m_lpImage, NULL, 0);
ASSERT(m_lpImage !
= NULL);
return m_hBitmap;
}
BOOL CDib:
:
MakePalette()
{
// makes a logical palette (m_hPalette) from the DIB's color table
// this palette will be selected and realized prior to drawing the DIB
if(m_nColorTableEntries == 0) return FALSE;
if(m_hPalette !
= NULL) :
:
DeleteObjec
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 直接 24 位图 访问 得到 像素