📄 dibapi.cpp
字号:
ptr = (unsigned char *)array;
while (length--) {
b1 = *ptr++;
b2 = *ptr++;
*array++ = (unsigned short)((b1 << 8) | (b2));
}
}
void WINAPI ConvertLong(unsigned long *array, long length)
{
unsigned long b1, b2, b3, b4;
unsigned char *ptr;
ptr = (unsigned char *)array;
while (length--) {
b1 = *ptr++;
b2 = *ptr++;
b3 = *ptr++;
b4 = *ptr++;
*array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
}
}
/*************************************************************************
*
* SaveDIB()
*
* Saves the specified DIB into the specified CFile. The CFile
* is opened and closed by the caller.
*
* Parameters:
*
* HDIB hDib - Handle to the dib to save
*
* CFile& file - open CFile used to save DIB
*
* Return value: TRUE if successful, else FALSE or CFileException
*
*************************************************************************/
BOOL WINAPI SaveDIB(HDIB hDib, CFile& file)
{
BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure
DWORD dwDIBSize;
if (hDib == NULL)
return FALSE;
/*
* Get a pointer to the DIB memory, the first of which contains
* a BITMAPINFO structure
*/
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
if (lpBI == NULL)
return FALSE;
if (!IS_WIN30_DIB(lpBI))
{
::GlobalUnlock((HGLOBAL) hDib);
return FALSE; // It's an other-style DIB (save not supported)
}
/*
* Fill in the fields of the file header
*/
/* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"
// Calculating the size of the DIB is a bit tricky (if we want to
// do it right). The easiest way to do this is to call GlobalSize()
// on our global handle, but since the size of our global memory may have
// been padded a few bytes, we may end up writing out a few too
// many bytes to the file (which may cause problems with some apps).
//
// So, instead let's calculate the size manually (if we can)
//
// First, find size of header plus size of color table. Since the
// first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
// the size of the structure, let's use this.
dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI); // Partial Calculation
// Now calculate the size of the image
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
{
// It's an RLE bitmap, we can't calculate size, so trust the
// biSizeImage field
dwDIBSize += lpBI->biSizeImage;
}
else
{
DWORD dwBmBitsSize; // Size of Bitmap Bits only
// It's not RLE, so size is Width (DWORD aligned) * Height
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
dwDIBSize += dwBmBitsSize;
// Now, since we have calculated the correct size, why don't we
// fill in the biSizeImage field (this will fix any .BMP files which
// have this field incorrect).
lpBI->biSizeImage = dwBmBitsSize;
}
// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
/*
* Now, calculate the offset the actual bitmap bits will be in
* the file -- It's the Bitmap file header plus the DIB header,
* plus the size of the color table.
*/
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize
+ PaletteSize((LPSTR)lpBI);
#ifdef _MAC
ByteSwapHeader(&bmfHdr);
// First swap the size field
*((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
// Now swap the rest of the structure (we don't save < Win30 files)
ByteSwapInfo((LPSTR)lpBI, TRUE);
#endif
TRY
{
// Write the file header
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
//
// Write the DIB header and the bits
//
file.WriteHuge(lpBI, dwDIBSize);
}
CATCH (CFileException, e)
{
#ifdef _MAC
// Swap everything back
*((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
ByteSwapInfo((LPSTR)lpBI, TRUE);
#endif
::GlobalUnlock((HGLOBAL) hDib);
THROW_LAST();
}
END_CATCH
#ifdef _MAC
// Swap everything back
*((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
ByteSwapInfo((LPSTR)lpBI, TRUE);
#endif
::GlobalUnlock((HGLOBAL) hDib);
return TRUE;
}
/*************************************************************************
Function: ReadDIBFile (CFile&)
Purpose: Reads in the specified DIB file into a global chunk of
memory.
Returns: A handle to a dib (hDIB) if successful.
NULL if an error occurs.
Comments: BITMAPFILEHEADER is stripped off of the DIB. Everything
from the end of the BITMAPFILEHEADER structure on is
returned in the global memory handle.
*************************************************************************/
HDIB WINAPI ReadDIBFile(CFile& file)
{
BITMAPFILEHEADER bmfHeader;
DWORD dwBitsSize;
HDIB hDIB;
LPSTR pDIB;
/*
* get length of DIB in bytes for use when reading
*/
dwBitsSize = file.GetLength();
/*
* Go read the DIB file header and check if it's valid.
*/
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
return NULL;
#ifdef _MAC
ByteSwapHeader(&bmfHeader);
#endif
if (bmfHeader.bfType != DIB_HEADER_MARKER)
return NULL;
/*
* Allocate memory for DIB
*/
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
if (hDIB == 0)
{
return NULL;
}
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
/*
* Go read the bits.
*/
if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
dwBitsSize - sizeof(BITMAPFILEHEADER) )
{
::GlobalUnlock((HGLOBAL) hDIB);
::GlobalFree((HGLOBAL) hDIB);
return NULL;
}
#ifdef _MAC
// First swap the size field
*((LPDWORD)pDIB) = SWAPLONG(*((LPDWORD)pDIB));
// Now swap the rest of the structure
ByteSwapInfo(pDIB, IS_WIN30_DIB(pDIB));
#endif
::GlobalUnlock((HGLOBAL) hDIB);
return hDIB;
}
//
HDIB WINAPI NewDIB(long width, long height,unsigned short biBitCount)
{
long dwindth = (width*biBitCount/8+3)/4*4; // align 4 bytes
WORD color_num;
switch(biBitCount)
{
case 1:
color_num=2;
break;
case 4:
color_num=16;
break;
case 8:
color_num=256;
break;
default:
color_num=0;
break;
}
long dwBitsSize = dwindth *height + 40 + color_num*4;// 40 LPBIMHEAD
LPSTR pDIB;
HDIB hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
if (hDIB == 0)
{
return NULL;
}
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
::memset(pDIB,-1,dwBitsSize);//
LPBITMAPINFO lpmf = (LPBITMAPINFO)pDIB;
lpmf->bmiHeader.biSize = 40;//40
lpmf->bmiHeader.biWidth = width; //i_info.width;
lpmf->bmiHeader.biHeight = height;
lpmf->bmiHeader.biPlanes = 1;
lpmf->bmiHeader.biBitCount = biBitCount;// 24
lpmf->bmiHeader.biCompression = 0;
lpmf->bmiHeader.biSizeImage = dwindth *height;
lpmf->bmiHeader.biXPelsPerMeter = 2925;
lpmf->bmiHeader.biYPelsPerMeter = 2925;
lpmf->bmiHeader.biClrUsed = 0;
lpmf->bmiHeader.biClrImportant= 0;
if(color_num!=0)
{
for(int i=0;i<color_num;i++)
{
lpmf->bmiColors[i].rgbRed =(BYTE)i;
lpmf->bmiColors[i].rgbGreen =(BYTE)i;
lpmf->bmiColors[i].rgbBlue =(BYTE)i;
}
}
::GlobalUnlock((HGLOBAL) hDIB);
return hDIB;
}
#ifdef _MAC
void ByteSwapHeader(BITMAPFILEHEADER* bmfHeader)
{
bmfHeader->bfType = SWAPWORD(bmfHeader->bfType);
bmfHeader->bfSize = SWAPLONG(bmfHeader->bfSize);
bmfHeader->bfOffBits = SWAPLONG(bmfHeader->bfOffBits);
}
void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header)
{
// Note this doesn't swap the bcSize/biSize field. It assumes that the
// size field was swapped during read or while setting the fWin30Header
// flag.
if (fWin30Header)
{
LPBITMAPINFOHEADER lpBMIH = &(LPBITMAPINFO(lpHeader)->bmiHeader);
//lpBMIH->biSize = SWAPLONG(lpBMIH->biSize);
lpBMIH->biWidth = SWAPLONG(lpBMIH->biWidth);
lpBMIH->biHeight = SWAPLONG(lpBMIH->biHeight);
lpBMIH->biPlanes = SWAPWORD(lpBMIH->biPlanes);
lpBMIH->biBitCount = SWAPWORD(lpBMIH->biBitCount);
lpBMIH->biCompression = SWAPLONG(lpBMIH->biCompression);
lpBMIH->biSizeImage = SWAPLONG(lpBMIH->biSizeImage);
lpBMIH->biXPelsPerMeter = SWAPLONG(lpBMIH->biXPelsPerMeter);
lpBMIH->biYPelsPerMeter = SWAPLONG(lpBMIH->biYPelsPerMeter);
lpBMIH->biClrUsed = SWAPLONG(lpBMIH->biClrUsed);
lpBMIH->biClrImportant = SWAPLONG(lpBMIH->biClrImportant);
}
else
{
LPBITMAPCOREHEADER lpBMCH = &(LPBITMAPCOREINFO(lpHeader)->bmciHeader);
lpBMCH->bcWidth = SWAPWORD(lpBMCH->bcWidth);
lpBMCH->bcHeight = SWAPWORD(lpBMCH->bcHeight);
lpBMCH->bcPlanes = SWAPWORD(lpBMCH->bcPlanes);
lpBMCH->bcBitCount = SWAPWORD(lpBMCH->bcBitCount);
}
}
void rectcoding(HDIB hDIB,int wRect,int hRect)
{
// 指向源图像象素的指针
unsigned char * lpSrc;
// 指向DIB的指针
LPSTR lpDIB;
// 指向DIB象素指针
LPSTR lpDIBBits;
//锁定并获得位图句柄的地址
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
// 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的模糊操作,其它的可以类推)
if (::DIBNumColors(lpDIB) != 256)
{
// 提示用户
::AfxMessageBox ("目前只支持256色位图的运算!");
// 返回
return;
}
// 找到DIB图像象素起始位置
lpDIBBits = ::FindDIBBits(lpDIB);
//图像处理操作
//方块编码
//获得图像的宽度和高度
LONG lWidth=::DIBWidth ((char*)lpDIB);
LONG lHeight=::DIBHeight ((char*)lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 8);
if(lWidth!=lHeight)
{
// 提示用户
::AfxMessageBox("只能对宽度和高度相等的图像进行方块编码!");
// 返回
return;
}
//编码过程
//循环变量
LONG i,j,k;
int ii,jj;
double* Xt=new double [lWidth*lHeight/(hRect*wRect)];
int Xi;
int* a0=new int [lWidth*lHeight/(hRect*wRect)];
int* a1=new int [lWidth*lHeight/(hRect*wRect)];
int* N0=new int [lWidth*lHeight/(hRect*wRect)];
int* N1=new int [lWidth*lHeight/(hRect*wRect)];
//计算阈值
k=0;
for (i = 0; i < lHeight; i =i+hRect)
{
for (j = 0; j < lWidth; j =j+wRect)
{
Xt[k]=0;
//计算Xt
for(ii=0;ii<hRect;ii++)
for(jj=0;jj<wRect;jj++)
{ // 指向图像指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * (i+ii) + (j+jj);
Xi=*lpSrc;
Xt[k]+=Xi;
}
Xt[k]/=hRect*wRect;
k++;
}
}
//计算N0、N1
k=0;
for (i = 0; i < lHeight; i =i+hRect)
{
for (j = 0; j < lWidth; j =j+wRect)
{
N0[k]=0;
N1[k]=0;
//计算N0、N1
for(ii=0;ii<hRect;ii++)
for(jj=0;jj<wRect;jj++)
{ // 指向图像指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * (i+ii) + (j+jj);
Xi=*lpSrc;
if(Xi<Xt[k]) N0[k]++;
else N1[k]++;
}
k++;
}
}
//计算a0、a1
k=0;
for (i = 0; i < lHeight; i =i+hRect)
{
for (j = 0; j < lWidth; j =j+wRect)
{
a0[k]=0;
a1[k]=0;
//计算N0、N1
for(ii=0;ii<hRect;ii++)
for(jj=0;jj<wRect;jj++)
{ // 指向图像指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * (i+ii) + (j+jj);
Xi=*lpSrc;
if(Xi<Xt[k]) a0[k]+=Xi;
else a1[k]+=Xi;
}
if(N0[k]!=0&&N1[k]!=0)
{ a0[k]/=N0[k];
a1[k]/=N1[k];
}
k++;
}
}
//二值化编码过程
k=0;
for (i = 0; i < lHeight; i =i+hRect)
{
for (j = 0; j < lWidth; j =j+wRect)
{
for(ii=0;ii<hRect;ii++)
for(jj=0;jj<wRect;jj++)
{ // 指向图像指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * (i+ii) + (j+jj);
Xi=*lpSrc;
if(Xi<Xt[k]) Xi=a0[k];
else Xi=a1[k];
//赋新的像素值给像素
*lpSrc=Xi;
}
k++;
}
}
::GlobalUnlock((HGLOBAL) hDIB);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -