📄 ximawnd.cpp
字号:
// xImaWnd.cpp : Windows functions
/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
* CxImage version 6.0.0 02/Feb/2008
*/
#include "ximage.h"
#include "ximaiter.h"
#include "ximabmp.h"
////////////////////////////////////////////////////////////////////////////////
#if defined (_WIN32_WCE)
#ifndef DEFAULT_GUI_FONT
#define DEFAULT_GUI_FONT 17
#endif
#ifndef PROOF_QUALITY
#define PROOF_QUALITY 2
#endif
struct DIBINFO : public BITMAPINFO
{
RGBQUAD arColors[255]; // Color table info - adds an extra 255 entries to palette
operator LPBITMAPINFO() { return (LPBITMAPINFO) this; }
operator LPBITMAPINFOHEADER() { return &bmiHeader; }
RGBQUAD* ColorTable() { return bmiColors; }
};
int BytesPerLine(int nWidth, int nBitsPerPixel)
{
return ( (nWidth * nBitsPerPixel + 31) & (~31) ) / 8;
}
int NumColorEntries(int nBitsPerPixel, int nCompression, DWORD biClrUsed)
{
int nColors = 0;
switch (nBitsPerPixel)
{
case 1:
nColors = 2; break;
case 2:
nColors = 4; break; // winCE only
case 4:
nColors = 16; break;
case 8:
nColors =256; break;
case 24:
nColors = 0; break;
case 16:
case 32:
nColors = 3; break; // I've found that PocketPCs need this regardless of BI_RGB or BI_BITFIELDS
default:
ASSERT(FALSE);
}
// If biClrUsed is provided, and it is a legal value, use it
if (biClrUsed > 0 && biClrUsed <= (DWORD)nColors)
return biClrUsed;
return nColors;
}
int GetDIBits(
HDC hdc, // handle to DC
HBITMAP hbmp, // handle to bitmap
UINT uStartScan, // first scan line to set
UINT cScanLines, // number of scan lines to copy
LPVOID lpvBits, // array for bitmap bits
LPBITMAPINFO lpbi, // bitmap data buffer
UINT uUsage // RGB or palette index
)
{
UINT iColorTableSize = 0;
if (!hbmp)
return 0;
// Get dimensions of bitmap
BITMAP bm;
if (!::GetObject(hbmp, sizeof(bm),(LPVOID)&bm))
return 0;
//3. Creating new bitmap and receive pointer to it's bits.
HBITMAP hTargetBitmap;
void *pBuffer;
//3.1 Initilize DIBINFO structure
DIBINFO dibInfo;
dibInfo.bmiHeader.biBitCount = 24;
dibInfo.bmiHeader.biClrImportant = 0;
dibInfo.bmiHeader.biClrUsed = 0;
dibInfo.bmiHeader.biCompression = 0;
dibInfo.bmiHeader.biHeight = bm.bmHeight;
dibInfo.bmiHeader.biPlanes = 1;
dibInfo.bmiHeader.biSize = 40;
dibInfo.bmiHeader.biSizeImage = bm.bmHeight*BytesPerLine(bm.bmWidth,24);
dibInfo.bmiHeader.biWidth = bm.bmWidth;
dibInfo.bmiHeader.biXPelsPerMeter = 3780;
dibInfo.bmiHeader.biYPelsPerMeter = 3780;
dibInfo.bmiColors[0].rgbBlue = 0;
dibInfo.bmiColors[0].rgbGreen = 0;
dibInfo.bmiColors[0].rgbRed = 0;
dibInfo.bmiColors[0].rgbReserved = 0;
//3.2 Create bitmap and receive pointer to points into pBuffer
HDC hDC = ::GetDC(NULL);
ASSERT(hDC);
hTargetBitmap = CreateDIBSection(
hDC,
(const BITMAPINFO*)dibInfo,
DIB_RGB_COLORS,
(void**)&pBuffer,
NULL,
0);
::ReleaseDC(NULL, hDC);
//4. Copy source bitmap into the target bitmap.
//4.1 Create 2 device contexts
HDC memDc = CreateCompatibleDC(NULL);
if (!memDc) {
ASSERT(FALSE);
}
HDC targetDc = CreateCompatibleDC(NULL);
if (!targetDc) {
ASSERT(FALSE);
}
//4.2 Select source bitmap into one DC, target into another
HBITMAP hOldBitmap1 = (HBITMAP)::SelectObject(memDc, hbmp);
HBITMAP hOldBitmap2 = (HBITMAP)::SelectObject(targetDc, hTargetBitmap);
//4.3 Copy source bitmap into the target one
BitBlt(targetDc, 0, 0, bm.bmWidth, bm.bmHeight, memDc, 0, 0, SRCCOPY);
//4.4 Restore device contexts
::SelectObject(memDc, hOldBitmap1);
::SelectObject(targetDc, hOldBitmap2);
DeleteDC(memDc);
DeleteDC(targetDc);
//Here we can bitmap bits: pBuffer. Note:
// 1. pBuffer contains 3 bytes per point
// 2. Lines ane from the bottom to the top!
// 3. Points in the line are from the left to the right
// 4. Bytes in one point are BGR (blue, green, red) not RGB
// 5. Don't delete pBuffer, it will be automatically deleted
// when delete hTargetBitmap
lpvBits = pBuffer;
DeleteObject(hbmp);
//DeleteObject(hTargetBitmap);
return 1;
}
#endif
////////////////////////////////////////////////////////////////////////////////
#if CXIMAGE_SUPPORT_WINDOWS
////////////////////////////////////////////////////////////////////////////////
long CxImage::Blt(HDC pDC, long x, long y)
{
if((pDib==0)||(pDC==0)||(!info.bEnabled)) return 0;
HBRUSH brImage = CreateDIBPatternBrushPt(pDib, DIB_RGB_COLORS);
POINT pt;
SetBrushOrgEx(pDC,x,y,&pt); //<RT>
HBRUSH brOld = (HBRUSH) SelectObject(pDC, brImage);
PatBlt(pDC, x, y, head.biWidth, head.biHeight, PATCOPY);
SelectObject(pDC, brOld);
SetBrushOrgEx(pDC,pt.x,pt.y,NULL);
DeleteObject(brImage);
return 1;
}
////////////////////////////////////////////////////////////////////////////////
/**
* Transfer the image in a global bitmap handle (clipboard copy)
*/
HANDLE CxImage::CopyToHandle()
{
HANDLE hMem=NULL;
if (pDib){
hMem= GlobalAlloc(GHND, GetSize());
if (hMem){
BYTE* pDst=(BYTE*)GlobalLock(hMem);
if (pDst){
memcpy(pDst,pDib,GetSize());
}
GlobalUnlock(hMem);
}
}
return hMem;
}
////////////////////////////////////////////////////////////////////////////////
/**
* Global object (clipboard paste) constructor
* \param hMem: source bitmap object, the clipboard format must be CF_DIB
* \return true if everything is ok
*/
bool CxImage::CreateFromHANDLE(HANDLE hMem)
{
if (!Destroy())
return false;
DWORD dwSize = GlobalSize(hMem);
if (!dwSize) return false;
BYTE *lpVoid; //pointer to the bitmap
lpVoid = (BYTE *)GlobalLock(hMem);
BITMAPINFOHEADER *pHead; //pointer to the bitmap header
pHead = (BITMAPINFOHEADER *)lpVoid;
if (lpVoid){
//CxMemFile hFile(lpVoid,dwSize);
//copy the bitmap header
memcpy(&head,pHead,sizeof(BITMAPINFOHEADER));
//check if it's a top-down bitmap
bool bTopDownDib = head.biHeight<0;
if (bTopDownDib) head.biHeight=-head.biHeight;
//create the image
if(!Create(head.biWidth,head.biHeight,head.biBitCount)){
GlobalUnlock(lpVoid);
return false;
}
//preserve DPI
SetXDPI((long)floor(head.biXPelsPerMeter * 254.0 / 10000.0 + 0.5));
SetYDPI((long)floor(head.biYPelsPerMeter * 254.0 / 10000.0 + 0.5));
/*//copy the pixels (old way)
if((pHead->biCompression != BI_RGB) || (pHead->biBitCount == 32)){ //<J鰎gen Alfredsson>
// BITFIELD case
// set the internal header in the dib
memcpy(pDib,&head,sizeof(head));
// get the bitfield masks
DWORD bf[3];
memcpy(bf,lpVoid+pHead->biSize,12);
// transform into RGB
Bitfield2RGB(lpVoid+pHead->biSize+12,bf[0],bf[1],bf[2],(BYTE)pHead->biBitCount);
} else { //normal bitmap
memcpy(pDib,lpVoid,GetSize());
}*/
// <Michael Gandyra>
// fill in color map
bool bIsOldBmp = (head.biSize == sizeof(BITMAPCOREHEADER));
RGBQUAD *pRgb = GetPalette();
if (pRgb) {
// number of colors to fill in
int nColors = DibNumColors(pHead);
if (bIsOldBmp) {
/* get pointer to BITMAPCOREINFO (old style 1.x) */
LPBITMAPCOREINFO lpbmc = (LPBITMAPCOREINFO)lpVoid;
for (int i = nColors - 1; i >= 0; i--) {
pRgb[i].rgbRed = lpbmc->bmciColors[i].rgbtRed;
pRgb[i].rgbGreen = lpbmc->bmciColors[i].rgbtGreen;
pRgb[i].rgbBlue = lpbmc->bmciColors[i].rgbtBlue;
pRgb[i].rgbReserved = (BYTE)0;
}
} else {
/* get pointer to BITMAPINFO (new style 3.x) */
LPBITMAPINFO lpbmi = (LPBITMAPINFO)lpVoid;
for (int i = nColors - 1; i >= 0; i--) {
pRgb[i].rgbRed = lpbmi->bmiColors[i].rgbRed;
pRgb[i].rgbGreen = lpbmi->bmiColors[i].rgbGreen;
pRgb[i].rgbBlue = lpbmi->bmiColors[i].rgbBlue;
pRgb[i].rgbReserved = (BYTE)0;
}
}
}
// <Michael Gandyra>
DWORD dwCompression = pHead->biCompression;
// compressed bitmap ?
if(dwCompression!=BI_RGB || pHead->biBitCount==32 || pHead->biBitCount ==16) {
// get the bitmap bits
LPSTR lpDIBBits = (LPSTR)((BYTE*)pHead + *(DWORD*)pHead + (WORD)(GetNumColors() * sizeof(RGBQUAD)));
// decode and copy them to our image
switch (pHead->biBitCount) {
case 32 :
{
// BITFIELD case
if (dwCompression == BI_BITFIELDS || dwCompression == BI_RGB) {
// get the bitfield masks
DWORD bf[3];
memcpy(bf,lpVoid+pHead->biSize,12);
// transform into RGB
Bitfield2RGB(lpVoid+pHead->biSize+12,bf[0],bf[1],bf[2],(BYTE)pHead->biBitCount);
} else {
// "unknown compression";
GlobalUnlock(lpVoid);
return false;
}
}
break;
case 16 :
{
// get the bitfield masks
long offset=0;
DWORD bf[3];
if (dwCompression == BI_BITFIELDS) {
memcpy(bf,lpVoid+pHead->biSize,12);
offset= 12;
} else {
bf[0] = 0x7C00;
bf[1] = 0x3E0;
bf[2] = 0x1F; // RGB555
}
// copy the pixels
memcpy(info.pImage, lpDIBBits + offset, head.biHeight*((head.biWidth+1)/2)*4);
// transform into RGB
Bitfield2RGB(info.pImage, bf[0], bf[1], bf[2], 16);
}
break;
case 8 :
case 4 :
case 1 :
{
switch (dwCompression) {
case BI_RLE4:
{
BYTE status_byte = 0;
BYTE second_byte = 0;
int scanline = 0;
int bits = 0;
BOOL low_nibble = FALSE;
CImageIterator iter(this);
for (BOOL bContinue = TRUE; bContinue; ) {
status_byte = *(lpDIBBits++);
switch (status_byte) {
case RLE_COMMAND :
status_byte = *(lpDIBBits++);
switch (status_byte) {
case RLE_ENDOFLINE :
bits = 0;
scanline++;
low_nibble = FALSE;
break;
case RLE_ENDOFBITMAP :
bContinue = FALSE;
break;
case RLE_DELTA :
{
// read the delta values
BYTE delta_x;
BYTE delta_y;
delta_x = *(lpDIBBits++);
delta_y = *(lpDIBBits++);
// apply them
bits += delta_x / 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -