📄 dibapi.cpp
字号:
//**********************************************************************
//
// AIBAPI.CPP
//
// Source file for Device-Independent Bitmap (DIB) API.
//
//**********************************************************************
#define STRICT // enable strict type checking
#include "stdafx.h"
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <io.h>
#include <direct.h>
#include <stdlib.h>
#include <assert.h>
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include "dibapi.h"
////////////////////////////////////////////////////////////////////////////////////
// Local use only function prototypes
////////////////////////////////////////////////////////////////////////////////////
BOOL CopyColorTable(LPBITMAPINFO lpTarget, LPBITMAPINFO lpSource, HPALETTE hPalSrc);
void DecreaseContrast(BYTE *pByte, const int Level, const float Grad);
void IncreaseContrast(BYTE *pByte, const int Low, const int High, const float Grad);
double Value(double n1, double n2, double hue);
HGLOBAL DitherImage(LPBYTE lpImageData, WORD Width, WORD Height);
void DitherLine(WORD Width, LPBYTE pLine1, LPBYTE pLine2);
////////////////////////////////////////////////////////////////////////////////////
/*************************************************************************
*
* 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((LPBYTE)&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);
LPBYTE lpDIBBits = FindDIBBits((LPBYTE)lpbmi);
DWORD dwBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader));
// set DIB color to White
for (DWORD l=0; l<dwBitsSize; ++l)
lpDIBBits[l] = 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;
}
//释放内存
void DestroyDIB(HDIB hDib)
{
GlobalFree(hDib);
}
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;
}
}
//保存DIB图象
BOOL SaveDIB(HDIB hDib, LPCTSTR lpFileName)
{
HANDLE fh; // file handle for opened file
if (!hDib)
return FALSE;
fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh == INVALID_HANDLE_VALUE)
return FALSE;
BOOL bSuccess = WriteDIBFile(hDib, fh);
CloseHandle(fh);
return bSuccess;
}
//读取DIB文件
HANDLE ReadDIBFile(HANDLE hFile)
{
BITMAPFILEHEADER bmfHeader;
DWORD dwBitsSize;
UINT nNumColors; // Number of colors in table
HANDLE hDIB;
HANDLE hDIBtmp; // Used for GlobalRealloc() //MPB
LPBITMAPINFOHEADER lpbi;
DWORD offBits;
DWORD dwRead;
// get length of DIB in bytes for use when reading
dwBitsSize = GetFileSize(hFile, NULL);
// Allocate memory for header & color table. We'll enlarge this
// memory as needed.
hDIB = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(sizeof(BITMAPINFOHEADER) +
256 * sizeof(RGBQUAD)));
if (!hDIB)
return NULL;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
if (!lpbi)
{
GlobalFree(hDIB);
return NULL;
}
// read the BITMAPFILEHEADER from our file
if (!ReadFile(hFile, (LPBYTE)&bmfHeader, sizeof (BITMAPFILEHEADER),
&dwRead, NULL))
goto ErrExit;
if (sizeof (BITMAPFILEHEADER) != dwRead)
goto ErrExit;
if (bmfHeader.bfType != 0x4d42) // 'BM'
goto ErrExit;
// read the BITMAPINFOHEADER
if (!ReadFile(hFile, (LPBYTE)lpbi, sizeof(BITMAPINFOHEADER), &dwRead,
NULL))
goto ErrExit;
if (sizeof(BITMAPINFOHEADER) != dwRead)
goto ErrExit;
// Check to see that it's a Windows DIB -- an OS/2 DIB would cause
// strange problems with the rest of the DIB API since the fields
// in the header are different and the color table entries are
// smaller.
//
// If it's not a Windows DIB (e.g. if biSize is wrong), return NULL.
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
goto ErrExit;
// Now determine the size of the color table and read it. Since the
// bitmap bits are offset in the file by bfOffBits, we need to do some
// special processing here to make sure the bits directly follow
// the color table (because that's the format we are susposed to pass
// back)
if (!(nNumColors = (UINT)lpbi->biClrUsed))
{
// no color table for 24-bit, default size otherwise
if (lpbi->biBitCount > 8) //(lpbi->biBitCount != 24)
nNumColors = 1 << lpbi->biBitCount; // standard size table
}
// fill in some default values if they are zero
if (lpbi->biClrUsed == 0)
lpbi->biClrUsed = nNumColors;
if (lpbi->biSizeImage == 0)
{
lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) +
31) & ~31) >> 3) * lpbi->biHeight;
}
// get a proper-sized buffer for header, color table and bits
GlobalUnlock(hDIB);
hDIBtmp = GlobalReAlloc(hDIB, lpbi->biSize + nNumColors *
sizeof(RGBQUAD) + lpbi->biSizeImage, 0);
if (!hDIBtmp) // can't resize buffer for loading
goto ErrExitNoUnlock; //MPB
else
hDIB = hDIBtmp;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
// read the color table
ReadFile (hFile, (LPBYTE)(lpbi) + lpbi->biSize,
nNumColors * sizeof(RGBQUAD), &dwRead, NULL);
// offset to the bits from start of DIB header
offBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD);
// If the bfOffBits field is non-zero, then the bits might *not* be
// directly following the color table in the file. Use the value in
// bfOffBits to seek the bits.
if (bmfHeader.bfOffBits != 0L)
SetFilePointer(hFile, bmfHeader.bfOffBits, NULL, FILE_BEGIN);
if (ReadFile(hFile, (LPBYTE)lpbi + offBits, lpbi->biSizeImage, &dwRead,
NULL))
goto OKExit;
ErrExit:
GlobalUnlock(hDIB);
ErrExitNoUnlock:
GlobalFree(hDIB);
return NULL;
OKExit:
GlobalUnlock(hDIB);
return hDIB;
}
//写入DIB文件
BOOL WriteDIBFile(HDIB hDib, HANDLE fh)
{
BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure
DWORD dwDIBSize;
DWORD dwWritten;
if (!hDib)
return FALSE;
// Get a pointer to the DIB memory, the first of which contains
// a BITMAPINFO structure
lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);
if (!lpBI)
{
CloseHandle(fh);
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -