📄 dibapi.cpp
字号:
/*************************************************************************************************
//
// DIBAPI.CPP
//
// Source file for Device-Independent Bitmap (DIB) API.
//
*************************************************************************************************/
#include "stdafx.h"
#include "dibapi.h"
#include <io.h>
#include <errno.h>
#include <math.h>
#include <direct.h>
#include <assert.h>
///////////////////////////////////////////////////////////////////////////////////////////////
//Local Functions
int PalEntriesOnDevice (HDC hDC);
HDIB CreateDither8BppDIB(HDIB hDIB);
HGLOBAL DitherImage(LPSTR lpImageData, WORD Width, WORD Height);
void DitherLine(WORD Width, LPSTR pLine1, LPSTR pLine2);
///////////////////////////////////////////////////////////////////////////////////////////////
//Constructions definitions
typedef struct
{
BYTE Red;
BYTE Green;
BYTE Blue;
} RGBCOLOR;
RGBCOLOR DitherPalette[256] =
{
{0, 0, 0}, {0, 0, 85}, {0, 0, 170}, {0, 0, 255},
{0, 36, 0}, {0, 36, 85}, {0, 36, 170}, {0, 36, 255},
{0, 73, 0}, {0, 73, 85}, {0, 73, 170}, {0, 73, 255},
{0, 109, 0}, {0, 109, 85}, {0, 109, 170}, {0, 109, 255},
{0, 146, 0}, {0, 146, 85}, {0, 146, 170}, {0, 146, 255},
{0, 182, 0}, {0, 182, 85}, {0, 182, 170}, {0, 182, 255},
{0, 219, 0}, {0, 219, 85}, {0, 219, 170}, {0, 219, 255},
{0, 255, 0}, {0, 255, 85}, {0, 255, 170}, {0, 255, 255},
{36, 0, 0}, {36, 0, 85}, {36, 0, 170}, {36, 0, 255},
{36, 36, 0}, {36, 36, 85}, {36, 36, 170}, {36, 36, 255},
{36, 73, 0}, {36, 73, 85}, {36, 73, 170}, {36, 73, 255},
{36, 109, 0}, {36, 109, 85}, {36, 109, 170}, {36, 109, 255},
{36, 146, 0}, {36, 146, 85}, {36, 146, 170}, {36, 146, 255},
{36, 182, 0}, {36, 182, 85}, {36, 182, 170}, {36, 182, 255},
{36, 219, 0}, {36, 219, 85}, {36, 219, 170}, {36, 219, 255},
{36, 255, 0}, {36, 255, 85}, {36, 255, 170}, {36, 255, 255},
{73, 0, 0}, {73, 0, 85}, {73, 0, 170}, {73, 0, 255},
{73, 36, 0}, {73, 36, 85}, {73, 36, 170}, {73, 36, 255},
{73, 73, 0}, {73, 73, 85}, {73, 73, 170}, {73, 73, 255},
{73, 109, 0}, {73, 109, 85}, {73, 109, 170}, {73, 109, 255},
{73, 146, 0}, {73, 146, 85}, {73, 146, 170}, {73, 146, 255},
{73, 182, 0}, {73, 182, 85}, {73, 182, 170}, {73, 182, 255},
{73, 219, 0}, {73, 219, 85}, {73, 219, 170}, {73, 219, 255},
{73, 255, 0}, {73, 255, 85}, {73, 255, 170}, {73, 255, 255},
{109, 0, 0}, {109, 0, 85}, {109, 0, 170}, {109, 0, 255},
{109, 36, 0}, {109, 36, 85}, {109, 36, 170}, {109, 36, 255},
{109, 73, 0}, {109, 73, 85}, {109, 73, 170}, {109, 73, 255},
{109, 109, 0}, {109, 109, 85}, {109, 109, 170}, {109, 109, 255},
{109, 146, 0}, {109, 146, 85}, {109, 146, 170}, {109, 146, 255},
{109, 182, 0}, {109, 182, 85}, {109, 182, 170}, {109, 182, 255},
{109, 219, 0}, {109, 219, 85}, {109, 219, 170}, {109, 219, 255},
{109, 255, 0}, {109, 255, 85}, {109, 255, 170}, {109, 255, 255},
{146, 0, 0}, {146, 0, 85}, {146, 0, 170}, {146, 0, 255},
{146, 36, 0}, {146, 36, 85}, {146, 36, 170}, {146, 36, 255},
{146, 73, 0}, {146, 73, 85}, {146, 73, 170}, {146, 73, 255},
{146, 109, 0}, {146, 109, 85}, {146, 109, 170}, {146, 109, 255},
{146, 146, 0}, {146, 146, 85}, {146, 146, 170}, {146, 146, 255},
{146, 182, 0}, {146, 182, 85}, {146, 182, 170}, {146, 182, 255},
{146, 219, 0}, {146, 219, 85}, {146, 219, 170}, {146, 219, 255},
{146, 255, 0}, {146, 255, 85}, {146, 255, 170}, {146, 255, 255},
{182, 0, 0}, {182, 0, 85}, {182, 0, 170}, {182, 0, 255},
{182, 36, 0}, {182, 36, 85}, {182, 36, 170}, {182, 36, 255},
{182, 73, 0}, {182, 73, 85}, {182, 73, 170}, {182, 73, 255},
{182, 109, 0}, {182, 109, 85}, {182, 109, 170}, {182, 109, 255},
{182, 146, 0}, {182, 146, 85}, {182, 146, 170}, {182, 146, 255},
{182, 182, 0}, {182, 182, 85}, {182, 182, 170}, {182, 182, 255},
{182, 219, 0}, {182, 219, 85}, {182, 219, 170}, {182, 219, 255},
{182, 255, 0}, {182, 255, 85}, {182, 255, 170}, {182, 255, 255},
{219, 0, 0}, {219, 0, 85}, {219, 0, 170}, {219, 0, 255},
{219, 36, 0}, {219, 36, 85}, {219, 36, 170}, {219, 36, 255},
{219, 73, 0}, {219, 73, 85}, {219, 73, 170}, {219, 73, 255},
{219, 109, 0}, {219, 109, 85}, {219, 109, 170}, {219, 109, 255},
{219, 146, 0}, {219, 146, 85}, {219, 146, 170}, {219, 146, 255},
{219, 182, 0}, {219, 182, 85}, {219, 182, 170}, {219, 182, 255},
{219, 219, 0}, {219, 219, 85}, {219, 219, 170}, {219, 219, 255},
{219, 255, 0}, {219, 255, 85}, {219, 255, 170}, {219, 255, 255},
{255, 0, 0}, {255, 0, 85}, {255, 0, 170}, {255, 0, 255},
{255, 36, 0}, {255, 36, 85}, {255, 36, 170}, {255, 36, 255},
{255, 73, 0}, {255, 73, 85}, {255, 73, 170}, {255, 73, 255},
{255, 109, 0}, {255, 109, 85}, {255, 109, 170}, {255, 109, 255},
{255, 146, 0}, {255, 146, 85}, {255, 146, 170}, {255, 146, 255},
{255, 182, 0}, {255, 182, 85}, {255, 182, 170}, {255, 182, 255},
{255, 219, 0}, {255, 219, 85}, {255, 219, 170}, {255, 219, 255},
{255, 255, 0}, {255, 255, 85}, {255, 255, 170}, {255, 255, 255}
};
// Macros used to facilitate RGB pixel access for dithering
#define GetRGBPixel(Addr, Red, Green, Blue) \
Blue = (int) *(Addr); \
Green = (int) *(Addr+1); \
Red = (int) *(Addr+2);
#define PutRGBPixel(Addr, Red, Green, Blue) \
Red = (Red<0) ? 0 : Red; \
Red = (Red>255) ? 255 : Red; \
Green = (Green<0) ? 0 : Green; \
Green = (Green>255) ? 255 : Green;\
Blue = (Blue<0) ? 0 : Blue; \
Blue = (Blue>255) ? 255 : Blue; \
*(Addr) = (BYTE)Blue; \
*(Addr+1) = (BYTE)Green; \
*(Addr+2) = (BYTE)Red;
///////////////////////////////////////////////////////////////////////////////////////////////
/*****************************************************************************************
*
* CreateDIB()
*
* Parameters:
*
* DWORD dwWidth - Width for new bitmap, in pixels
* DWORD dwHeight - Height for new bitmap
* WORD wBitCount - Bit Count for new DIB (1, 4, 8, or 24)
*
* Return Value:
*
* HDIB - Handle to new DIB
*
* Description:
*
* This function allocates memory for and initializes a new DIB by
* filling in the BITMAPINFOHEADER, allocating memory for the color
* table, and allocating memory for the bitmap bits. As with all
* HDIBs, the header, colortable and bits are all in one contiguous
* memory block. This function is similar to the CreateBitmap()
* Windows API.
*
* The colortable and bitmap bits are left uninitialized (zeroed) in the
* returned HDIB.
*
*
****************************************************************************************/
HDIB CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount)
{
BITMAPINFOHEADER bi; // bitmap header
LPBITMAPINFOHEADER lpbi; // pointer to BITMAPINFOHEADER
DWORD dwLen; // size of memory block
HDIB hDIB;
DWORD dwBytesPerLine; // Number of bytes per scanline
// Make sure bits per pixel is valid
if (wBitCount <= 1)
wBitCount = 1;
else if (wBitCount <= 4)
wBitCount = 4;
else if (wBitCount <= 8)
wBitCount = 8;
else if (wBitCount <= 24)
wBitCount = 24;
else
wBitCount = 4; // set default value to 4 if parameter is bogus
// initialize BITMAPINFOHEADER
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = dwWidth; // fill in width from parameter
bi.biHeight = dwHeight; // fill in height from parameter
bi.biPlanes = 1; // must be 1
bi.biBitCount = wBitCount; // from parameter
bi.biCompression = BI_RGB;
bi.biSizeImage = 0; // 0's here mean "default"
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
// calculate size of memory block required to store the DIB. This
// block should be big enough to hold the BITMAPINFOHEADER, the color
// table, and the bits
dwBytesPerLine = WIDTHBYTES(wBitCount * dwWidth);
dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + (dwBytesPerLine * dwHeight);
// alloc memory block to store our bitmap
hDIB = GlobalAlloc(GHND, dwLen);
// major bummer if we couldn't get memory block
if (!hDIB)
return NULL;
// lock memory and get pointer to it
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
// use our bitmap info structure to fill in first part of
// our DIB with the BITMAPINFOHEADER
*lpbi = bi;
// Since we don't know what the colortable and bits should contain,
// just leave these blank. Unlock the DIB and return the HDIB.
GlobalUnlock(hDIB);
//return handle to the DIB
return hDIB;
}
/*************************************************************************************************
*
* CreateDefaultDIB()
*
* Parameters:
*
* DWORD dwWidth - Width for new bitmap, in pixels
* DWORD dwHeight - Height for new bitmap
*
* Return Value:
*
* HDIB - Handle to new DIB
*
* Description:
*
* This function allocates memory for and initializes a new DIB by
* filling in the BITMAPINFOHEADER, allocating memory for the color
* table, and allocating memory for the bitmap bits. As with all
* HDIBs, the header, colortable and bits are all in one contiguous
* memory block. This function is similar to the CreateBitmap()
* Windows API.
*
* The colortable is initialized with system palette, but bitmap bits
* are left uninitialized (zeroed) in the returned HDIB.
*
*
***********************************************************************************************/
HDIB CreateDefaultDIB(DWORD dwWidth, DWORD dwHeight)
{
// Get DC
HDC hDC = GetDC(NULL);
if (!hDC)
return NULL;
// DC bts/pixel
int nDeviceBitsPixel = GetDeviceCaps(hDC, BITSPIXEL);
// create DIB according to DC
HDIB hDIB = CreateDIB(dwWidth, dwHeight, nDeviceBitsPixel);
// DIB buffer
LPBITMAPINFO lpbmi = (LPBITMAPINFO)GlobalLock(hDIB);
LPSTR lpDIBBits = FindDIBBits((LPSTR)lpbmi);
DWORD dwBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader));
// set DIB color to White
for (DWORD l=0; l<dwBitsSize; ++l)
lpDIBBits[l] = (unsigned char)0xff;
// if no palette, return DIB handle
if (nDeviceBitsPixel > 8)
{
GlobalUnlock(hDIB);
ReleaseDC(NULL, hDC);
return hDIB;
}
// if there is palette, set system palette to DIB
// colors in system palette
int nColors = PalEntriesOnDevice(hDC); // Number of palette entries
// Copy the current system palette into our logical palette
PALETTEENTRY pe[256];
GetSystemPaletteEntries(hDC, 0, nColors, pe);
// set color table
for (int i=0; i<nColors; ++i)
{
lpbmi->bmiColors[i].rgbRed = pe[i].peRed;
lpbmi->bmiColors[i].rgbGreen = pe[i].peGreen;
lpbmi->bmiColors[i].rgbBlue = pe[i].peBlue;
lpbmi->bmiColors[i].rgbReserved = 0;
}
// clean up
GlobalUnlock(hDIB);
ReleaseDC(NULL, hDC);
return hDIB;
}
/*************************************************************************
*
* PalEntriesOnDevice()
*
* Parameter:
*
* HDC hDC - device context
*
* Return Value:
*
* int - number of palette entries on device
*
* Description:
*
* This function gets the number of palette entries on the specified device
*
************************************************************************/
int PalEntriesOnDevice(HDC hDC)
{
int nColors; // number of colors
// Find out the number of colors on this device.
nColors = (1 << (GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES)));
assert(nColors);
return nColors;
}
/*********************************************************************************************
*
* DestroyDIB ()
*
* Purpose: Frees memory associated with a DIB
*
* Returns: none
*
*********************************************************************************************/
void DestroyDIB(HDIB hDib)
{
GlobalFree(hDib);
}
/**********************************************************************************************
*
* LoadDIB()
*
* Loads the specified DIB from a file, allocates memory for it,
* and reads the disk file into the memory.
*
*
* Parameters:
*
* LPCTSTR lpFileName - specifies the file to load a DIB from
*
* Returns: A handle to a DIB, or NULL if unsuccessful.
*
* NOTE: The DIB API were not written to handle OS/2 DIBs; This
* function will reject any file that is not a Windows DIB.
*
**********************************************************************************************/
HDIB LoadDIB(LPCTSTR lpFileName)
{
HDIB hDIB;
HANDLE hFile;
// Set the cursor to a hourglass, in case the loading operation
// takes more than a sec, the user will know what's going on.
SetCursor(LoadCursor(NULL, IDC_WAIT));
if ((hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL)) != INVALID_HANDLE_VALUE)
{
hDIB = ReadDIBFile(hFile);
CloseHandle(hFile);
SetCursor(LoadCursor(NULL, IDC_ARROW));
return hDIB;
}
else
{
SetCursor(LoadCursor(NULL, IDC_ARROW));
return NULL;
}
}
/*************************************************************************
*
* 函数名称:
* SaveDIB()
*
* 参数:
* HDIB hDib - 要保存的DIB
* CFile& file - 保存文件CFile
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE或者CFileException
*
* 说明:
* 该函数将指定的DIB对象保存到指定的CFile中。该CFile由调用程序打开和关闭。
*
*************************************************************************/
BOOL SaveDIB(HDIB hDib, CFile& file)
{
// Bitmap文件头
BITMAPFILEHEADER bmfHdr;
// 指向BITMAPINFOHEADER的指针
LPBITMAPINFOHEADER lpBI;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -