GDI和DIB的一些笔记

来源:互联网 发布:淘宝上好多商品搜不到 编辑:程序博客网 时间:2024/05/09 17:01

 该文章是自己在看有关GDI DIB方面知识的时候做的一些笔记,整理的不好,仅仅适合个人看看。。。。若于你的学习
 有助,吾乃幸也!
 
 1.
 bmp文件有位图文件头、位图信息头、颜色信息以及数据组成
 文件头主要包含文件的大小、文件类型、图像数据偏离文件头的长度等信息;
 位图信息头包含图象的尺寸信息、图像用几个比特数值来表示一个像素、图像是否压缩、图像所用的颜色数等信息。
 颜色信息包含图像所用到的颜色表,显示图像时需用到这个颜色表来生成调色板,但如果图像为真彩色,
 既图像的每个像素用24个比特来表示,文件中就没有这一块信息,也就不需要操作调色板。
 文件中的数据块表示图像的相应的像素值
 注意的是:
 文件有文件头和数据组成
 文件头分三个部分:
   BITMAPfileHEADER位图信息,
   BITMAPINFOHEADER位图信息头,40个字节
   RGBQUAD颜色表,在真彩色的时候,文件头里面不包含此项
   typedef struct tagBITMAPFILEHEADER { // bmfh
    WORD    bfType;
    DWORD   bfSize;
    WORD    bfReserved1;
    WORD    bfReserved2;
    DWORD   bfOffBits;
} BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER{ // bmih
    DWORD  biSize;
    LONG   biWidth;
    LONG   biHeight;
    WORD   biPlanes;
   WORD   biBitCount //调色板的大小
    DWORD  biCompression;
    DWORD  biSizeImage;
    LONG   biXPelsPerMeter;
    LONG   biYPelsPerMeter;
    DWORD  biClrUsed; //实际上使用的颜色数目
    DWORD  biClrImportant;
} BITMAPINFOHEADER;


typedef struct tagBITMAPINFO { // bmi
    BITMAPINFOHEADER bmiHeader;
    RGBQUAD          bmiColors[1];
}BITMAPINFO;    
   数据:记录位图的每一个像素值或者在调色板中的索引值
   1.图像的像素值在文件中的存放顺序为从左到右,从下到上,也就是说,在BMP文件中首先存放的是图像的
     最后一行像素,最后才存储图像的第一行像素,但对与同一行的像素,则是按照先左边后右边的的顺序存储的
   2.文件存储图像的每一行像素值时,如果存储该行像素值所占的字节数为4的倍数,则正常存储,
     否则,需要在后端补0,凑足4的倍数。
     以字节为单位的每行长度始终是4的倍数。行的长度可以计算为:
     RowLength = 4 * ((bmch.bcWidth * bmch.bcBitCount + 31) / 32) ;        
     如果需要,可通过在右边补充行(通常是用零)来完成长度。图素数据的总字节数等于RowLength和
     bmch.bcHeight的乘积。
   24位图素不需要调色板
/////////////////////////////////////////////////////////////////////////////////////////////////
显示
要呼叫SetDIBitsToDevice来显示整个DIB图像,您需要下列信息:
hdc目的表面的设备内容句柄
xDst和yDst图像左上角的目的坐标
cxDib和cyDibDIB的图素宽度和高度,在这里,cyDib是BITMAPINFOHEADER结构内biHeight字段的绝对值。
pInfo和pBits指向位图信息部分和图素位的指针        
*************************************************   
下面这个函数可以返回DC
DC BeginPaint(
  HWND hwnd,  // handle to window
  LPPAINTSTRUCT lpPaint
              // pointer to structure for paint information
);

也可以用GETDC()
InvalidateRect函数定义更新的区域,该函数发出WM_PAINT消息
The InvalidateRect function adds a rectangle to the specified window's update region.
The update region represents the portion of the window's client area that must be redrawn.
BOOL InvalidateRect(
  HWND hWnd,  // handle of window with changed update region
  CONST RECT *lpRect,
              // address of rectangle coordinates
  BOOL bErase // erase-background flag
);
////////////////////////////////////////////////////////////////////////////////////////////
文件的读写
API:在API中首先要创建一个文件,创建成功以后,得到文件的指针,然后再去读或者写这个文件。最后记得
释放文件的指针

在MFC中特可以使用类似的结构
BOOL ReadFile(
  HANDLE hFile,                // handle of file to read
  LPVOID lpBuffer,             // pointer to buffer that receives data
  DWORD nNumberOfBytesToRead,  // number of bytes to read
  LPDWORD lpNumberOfBytesRead, // pointer to number of bytes read
  LPOVERLAPPED lpOverlapped    // pointer to structure for data
);

BOOL WriteFile(
  HANDLE hFile,                    // handle to file to write to
  LPCVOID lpBuffer,                // pointer to data to write to file
  DWORD nNumberOfBytesToWrite,     // number of bytes to write
  LPDWORD lpNumberOfBytesWritten,  // pointer to number of bytes written
  LPOVERLAPPED lpOverlapped        // pointer to structure for overlapped I/O
);

HANDLE CreateFile(
  LPCTSTR lpFileName,          // pointer to name of the file
  DWORD dwDesiredAccess,       // access (read-write) mode
  DWORD dwShareMode,           // share mode
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
                               // pointer to security attributes
  DWORD dwCreationDisposition,  // how to create
  DWORD dwFlagsAndAttributes,  // file attributes
  HANDLE hTemplateFile         // handle to file with attributes to
                               // copy
)

对于海量数据的显示
使用setbit分行来显示,节约内存空间,但是这样做的处理的速度会慢
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
DIB到DDB的转换
hBitmap = CreateDIBitmap (
        
                    hdc,               // device context handle
                    pInfoHdr,              // pointer to DIB information header
                    fInit,      // 0 or CBM_INIT
                    pBits,      // pointer to DIB pixel bits
                    pInfo,      // pointer to DIB information
                    fClrUse) ;  // color use flag        

该函数返回一个DDB位图的结构
如果仅需显示DIB一次,并担心SetDIBitsToDevice显示太慢,则呼叫CreateDIBitmap并使用BitBlt或StretchBlt
来显示DDB就没有什么意义。因为SetDIBitsToDevice和CreateDIBitmap都执行颜色转换,这两个工作会占用同样
长的时间。只有在多次显示DIB时(例如在处理WM_PAINT消息时)进行这种转换才有意义。
DDB到DIB
int WINAPI GetDIBits(      
                  hdc,          // device context handle
                  hBitmap,      // bitmap handle       
                  yScan,        // first scan line to convert
                  cyScans,      // number of scan lines to convert        
                  pBits,        // pointer to pixel bits (out)
                  pInfo,        // pointer to DIB information (out)       
                  fClrUse) ;    // color use flag
     
内存检测
CreateDIBSection检查BITMAPINFOHEADER结构并配置足够的内存块来加载DIB图素位。
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
API中的DIB函数

SetDIBitsToDevice
直接显示或打印,不进行缩放
图像过大,占用的内存较多的时候可以使用这个函数分段显示图片
The SetDIBitsToDevice function sets the pixels in the specified rectangle on the device that
is associated with the destination device context using color data from a device-independent
bitmap (DIB).

Windows 98 and Windows NT 5.0: SetDIBitsToDevice has been extended to allow a JPEG image to
be passed as the source image.

int SetDIBitsToDevice(
  HDC hdc,              // handle to device context
  int XDest,            // x-coordinate of upper-left corner of
                        // dest. rect.
  int YDest,            // y-coordinate of upper-left corner of
                        // dest. rect.
  DWORD dwWidth,        // source rectangle width
  DWORD dwHeight,       // source rectangle height
  int XSrc,             // x-coordinate of lower-left corner of
                        // source rect.
  int YSrc,             // y-coordinate of lower-left corner of
                        // source rect.
  UINT uStartScan,      // first scan line in array
  UINT cScanLines,      // number of scan lines
  CONST VOID *lpvBits,  // address of array with DIB bits
  CONST BITMAPINFO *lpbmi,  // address of structure with bitmap info.
  UINT fuColorUse       // RGB or palette indexes
);
*******************************************************
StretchDIBits

可以根据目标区域的大小进行放大、缩小
The StretchDIBits function copies the color data for a rectangle of pixels in a
-independent bitmap (DIB) to the specified destination rectangle. If the destination
rectangle is larger than the source rectangle, this function stretches the rows and
columns of color data to fit the destination rectangle. If the destination rectangle
is smaller than the source rectangle, this function compresses the rows and columns
by using the specified raster operation.

int StretchDIBits(
  HDC hdc,                // handle to device context
  int XDest,              // x-coordinate of upper-left corner of dest. rectangle
  int YDest,              // y-coordinate of upper-left corner of dest. rectangle
  int nDestWidth,         // width of destination rectangle
  int nDestHeight,        // height of destination rectangle
  int XSrc,               // x-coordinate of upper-left corner of source rectangle
  int YSrc,               // y-coordinate of upper-left corner of source rectangle
  int nSrcWidth,          // width of source rectangle
  int nSrcHeight,         // height of source rectangle
  CONST VOID *lpBits,            // address of bitmap bits
  CONST BITMAPINFO *lpBitsInfo,  // address of bitmap data
  UINT iUsage,                   // usage flags
  DWORD dwRop                    // raster operation code
);
 
********************************************************
CDC::GetSafeHdc  
HDC GetSafeHdc( ) const;
Return Value
A device context handle.
Remarks
Call this member function to get m_hDC, the output device context. This member function also
 works with null pointers.
///////////////////////////////////////////////////////////////////////////////////////////////////////
位图传输
BitBlt
The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle
of pixels from the specified source device context into a destination device context.

BOOL BitBlt(
  HDC hdcDest, // handle to destination device context
  int nXDest,  // x-coordinate of destination rectangle's upper-left
               // corner
  int nYDest,  // y-coordinate of destination rectangle's upper-left
               // corner
  int nWidth,  // width of destination rectangle
  int nHeight, // height of destination rectangle
  HDC hdcSrc,  // handle to source device context
  int nXSrc,   // x-coordinate of source rectangle's upper-left
               // corner
  int nYSrc,   // y-coordinate of source rectangle's upper-left
               // corner
  DWORD dwRop  // raster operation code
);
位图拉伸
BOOL StretchBlt(
  HDC hdcDest,      // handle to destination device context
  int nXOriginDest, // x-coordinate of upper-left corner of dest. rectangle
  int nYOriginDest, // y-coordinate of upper-left corner of dest. rectangle
  int nWidthDest,   // width of destination rectangle
  int nHeightDest,  // height of destination rectangle
  HDC hdcSrc,       // handle to source device context
  int nXOriginSrc,  // x-coordinate of upper-left corner of source rectangle
  int nYOriginSrc,  // y-coordinate of upper-left corner of source rectangle
  int nWidthSrc,    // width of source rectangle
  int nHeightSrc,   // height of source rectangle
  DWORD dwRop       // raster operation code
);
填充矩形区域
PatBlt (hdc, x, y, cx, cy, BLACKNESS) ;
*******************************************************
这个也可以
int FillRect(
  HDC hDC,           // handle to device context
  CONST RECT *lprc,  // pointer to structure with rectangle
  HBRUSH hbr         // handle to brush
);
反正视图颜
BOOL InvertRect(
  HDC hDC,           // handle to device context
  CONST RECT *lprc   // pointer to structure with rectangle
);
BitBlt、PatBlt和StretchBlt是最合适的GDI画图函数,它们根据从一个角测得的逻辑宽度和高度来指定逻辑直角坐标。
矩形边框用到的其它所有GDI画图函数都要求根据左上角和右下角的坐标来指定坐标。对于MM_TEXT映像模式,
上面讲述的PatBlt参数就是正确的。然而对于公制的映像模式来说,就不正确。如果您使用负的cx和cy值,
那么点(x,y)将是矩形的左下角。如果希望点(x,y)是矩形的左上角,那么cy参数必须设为矩形的负高度。

***********************************************
上面是GDI的三种位块传输的三种基本方法
关于设备DC的获取

GetWindowDC is intended for special painting effects within a window's nonclient area.
Painting in nonclient areas of any window is not recommended.
可以使用非客户区
TheGetSystemMetrics function can be used to retrieve the dimensions of various parts
of the nonclient area, such as the title bar, menu, and scroll bars.
得到窗口上图标的大小
The GetDC function can be used to retrieve a device context for the entire screen.
得到客户区整个屏幕的DC
After painting is complete, the ReleaseDC function must be called to release the device
context. Not releasing the window device context has serious effects on painting requested
by applications.
注意释放DC
GetWindowDC
返回整个窗口的设备DC
HDC GetWindowDC(
  HWND hWnd   // handle of window
);
int GetSystemMetrics(
  int nIndex   // system metric or configuration setting to retrieve
);
HDC GetDC(
  HWND hWnd   // handle to a window
);
 *******************************************************
GDI
GDI.EXE这些动态链接库呼叫您安装的视讯显示器和任何打印机呼叫驱动程序中的例程。
因为PC兼容机种上可以连接许多种不同的视讯设备,所以,GDI的主要目的之一是支持与设备无关的图形
Windows程序应该能够毫无困难地在Windows支持的任意一种图形输出设备上执行,GDI通过将您的程序和不同输出
设备的特性隔离开来的方法来达到这一目的。
Windows GDI允许您使用两种坐标系统之一(甚至依据实际度量衡的坐标系)。您可以使用虚拟坐标系以便让程序
独立于硬件之外,或者也可以使用设备坐标系而完全迎合硬设备提供的环境。

hBitmap = LoadBitmap (hInstance, szBitmapName) ;//创建位图
hdcMem = CreateCompatibleDC (hdc) ;//得到DC
SelectObject (hdcMem, hBitmap) ;//将位图和DC联系在一起

××××××××××××××××××××××××××

在windows里面注意一些内存 句柄 指针 一类的建立、释放


由LoadBitmap加载的所有位图最终应用DeleteObject清除
应用程序建立的任何内存设备内容最终都通过呼叫DeleteDC来清除。
××××××××××××××××××××××××××

SelectObject呼叫以后,DDB就是内存设备内容的显示平面。处理实际设备内容的每项操作,您几乎都可以用于内
存设备内容。例如,如果用GDI画图函数在内存设备内容中画图,那么图像将画在位图上。这是非常有用的。还可
以将内存设备内容作为来源,把视讯设备内容作为目的来呼叫BitBlt。这就是在显示器上绘制位图的方法。如果
把视讯设备内容作为来源,把内存设备内容作为目的,那么呼叫BitBlt可将屏幕上的一些内容复制给位图。
××××××××××××××××××××××××××××××××××××××××××××××
将数据和位图来联系在一起的方法
有数据建立二值位图:
0 1 0 1 0 0 0 1 0 1 1 1 0 1 1 1 0 0 0 1 = 51 77 10 00
        
0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 0 1 = 57 77 50 00
        
0 0 0 1 0 0 1 1 0 1 1 1 0 1 1 1 0 1 0 1 = 13 77 50 00
        
0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 0 1 = 57 77 50 00
        
0 1 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 = 51 11 10 00

static BYTE  bits []       = {    0x51, 0x77, 0x10, 0x00,
        
                                  0x57, 0x77, 0x50, 0x00,
        
                                         0x13, 0x77, 0x50, 0x00,
        
                             0x57, 0x77, 0x50, 0x00,
        
                               0x51, 0x11, 0x10, 0x00 } ;

(1)static BITMAP bitmap               = { 0, 20, 5, 4, 1, 1 } ;
(2)bitmap.bmBits = (PSTR) bits ;
     hBitmap = CreateBitmapIndirect (&bitmap) ;
(3)hBitmap = CreateBitmapIndirect (&bitmap) ;
     SetBitmapBits (hBitmap, sizeof bits, bits) ;
(4)hBitmap = CreateBitmap (20, 5, 1, 1, bits) ;
××××××××××××××××××××××××××××××××××××××××××
在窗口中使用画刷,使用下面的方式可以建立画刷来初始化WNDCLASS 从而使界面充满位图
hBitmap = LoadBitmap (hInstance, TEXT ("Bricks")) ;
hBrush = CreatePatternBrush (hBitmap) ;
DeleteObject (hBitmap) ;
如果您依据位图建立画刷,那么在用画刷画图时,Windows将复制位图位到画刷所绘制的区域内。
呼叫CreatePatternBrush(或者CreateBrushIndirect)之后,您可以立即删除位图而不会影响到画笔。
类似地,您也可以删除画刷而不会影响到您选进的原始位图。注意,BRICKS3在建立画刷后删除了位图,
并在程序终止前删除了画刷。
×××××××××××××××××××××××××××××××
下面的内容还涉及:位图与菜单  非矩形位图  和简单的动画