📄 dib.cpp
字号:
}
else
{
GlobalUnlock(hDib);
return hDib;
}
}
BOOL DIB:: SaveDIB(HANDLE hDib, CFile& file)
{
// Bitmap文件头
BITMAPFILEHEADER bmfHdr;
// 指向BITMAPINFOHEADER的指针
LPBITMAPINFOHEADER lpBI;
// DIB大小
DWORD dwDIBSize =0;
if (hDib == NULL)
{
// 如果DIB为空,返回FALSE
return FALSE;
}
// 读取BITMAPINFO结构,并锁定
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
if (lpBI == NULL)
{
// 为空,返回FALSE
return FALSE;
}
// 判断是否是WIN3.0 DIB
// if (!IS_WIN30_DIB(lpBI))
// {
// 不支持其它类型的DIB保存
// 解除锁定
// ::GlobalUnlock((HGLOBAL) hDib);
// 返回FALSE
// return FALSE;
// }
// 填充文件头
// 文件类型"BM"
bmfHdr.bfType = 0x4d42; //DIB_HEADER_MARKER;
// 计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并
// 不是DIB真正的大小,它总是多几个字节。这样就需要计算一下DIB的真实大小。
// 文件头大小+颜色表大小
// (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个DWORD都是该结构的大小)
// dwDIBSize = *(LPDWORD)lpBI; //+ ::PaletteSize((LPSTR)lpBI);
dwDIBSize = sizeof(BITMAPINFOHEADER);//+lpBI->biSizeImage;
// 计算图像大小
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
{
// 对于RLE位图,没法计算大小,只能信任biSizeImage内的值
dwDIBSize += lpBI->biSizeImage;
}
else
{
// 象素的大小
DWORD dwBmBitsSize;
// 大小为Width * Height
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*24) * lpBI->biHeight;
// 计算出DIB真正的大小
dwDIBSize += dwBmBitsSize;
// 更新biSizeImage(很多BMP文件头中biSizeImage的值是错误的)
lpBI->biSizeImage = dwBmBitsSize;
}
// 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
// 两个保留字
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
// 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize;
// + PaletteSize((LPSTR)lpBI);
// 尝试写文件
// TRY
{
// 写文件头
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
// 写DIB头和象素
file.WriteHuge(lpBI, dwDIBSize);
}
// CATCH (CFileException, e)
// {
// 解除锁定
// ::GlobalUnlock((HGLOBAL) hDib);
// 抛出异常
/// THROW_LAST();
// }
// END_CATCH
// 解除锁定
::GlobalUnlock((HGLOBAL) hDib);
// 返回TRUE
return TRUE;
}
void DIB::ReduceColor(HANDLE hDib, int numcolor)
{
LPBITMAPINFOHEADER lpbi;
int width,height;
long lOffset;
WORD wBytesPerLine;
wBytesPerLine = this->BytePerLine(hDib);
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
width = lpbi->biWidth;
height = lpbi->biHeight;
LPBYTE lpData;
lpData = this->FindDIBBits(hDib);
int cal[256];
for(int i =0;i<256;i++)
cal[i] = 0;
for(i = 0;i<height;i++)
for(int j=0;j<width;j++)
{
lOffset = this->PixelOffset(i,j,wBytesPerLine);
int blue = *(lpData+lOffset++);
int green = *(lpData+lOffset++);
int red = *(lOffset+lpData);
int colorIndex = (39*red+50*green+blue*11)/100;
cal[colorIndex]++;
}
const int steplen = 5;
for(i =0;i<4;i++)
{
cal[4+i] += cal[i]/steplen;
cal[4+steplen+i] += cal[i]/steplen;
cal[4+2*steplen+i] +=cal[i]/steplen;
cal[4+3*steplen+i] +=cal[i]/steplen;
}
for(i=252;i<256;i++)
{
cal[i-4] += cal[i]/steplen;
cal[i-4-steplen] +=cal[i]/steplen;
cal[i-4-steplen*2] +=cal[i]/steplen;
cal[i-4-steplen*3] +=cal[i]/steplen;
}
int cal2[256];
for(i =0;i<256;i++)
cal2[i] =0;
for(i =3;i<253;i++)
{
int sum=0;
for(int len =-2;len<=2;len++)
sum +=cal[i+len];
sum /=5;
cal2[i] = sum;
}
for(i =0;i<256;i++)
cal[i] = cal2[i];
int k[10][2];
int colnum = this->FindK(cal,k,numcolor);
for(i =0;i<height;i++)
for(int j =0;j<width;j++)
{
lOffset = this->PixelOffset(i,j,wBytesPerLine);
int blue = *(lpData+lOffset++);
int green = *(lpData+lOffset++);
int red = *(lOffset+lpData);
int colorIndex = (39*red+50*green+blue*11)/100;
for(int kk=0;kk<colnum;kk++)
{
if(colorIndex>=k[kk][0] && colorIndex<=k[kk][1])
{
lOffset -=2;
if(kk==0){
*(lpData+lOffset++) = 0;
*(lpData+lOffset++) = 0;
*(lpData+lOffset) = 255;
break;
}
else if(kk == 1)
{ *(lpData+lOffset++) = 0;
*(lpData+lOffset++) = 255;
*(lpData+lOffset) = 0;
break;
}
else if(kk == 2)
{
*(lpData+lOffset++) = 255;
*(lpData+lOffset++) = 0;
*(lpData+lOffset) = 0;
break;
}
else if(kk == 3)
{
*(lpData+lOffset++) = 0;
*(lpData+lOffset++) = 255;
*(lpData+lOffset) = 255;
break;
}
else
{
*(lpData+lOffset++) = 255;
*(lpData+lOffset++) = 255;
*(lpData+lOffset) = 255;
break;
}
}
}
}
GlobalUnlock(hDib);
}
bool DIB::IsValley(int hisdata[], int point)
{
int sum =0;
for(int i =-4;i<=4;i++)
{
if(hisdata[point]<hisdata[point+i])
sum++;
}
if(sum>=5)
return true;
else
return false;
}
void DIB::JudgeDomain(int hisdata[], int ipoint,int *imin,int *imax)
{
int ilen=0,sum =0,add;
for(int i=0;i<2;i++)
{
add=hisdata[ipoint-ilen];
sum+=add;
ilen ++;
}
L:
add = hisdata[ipoint-ilen];
sum +=add;
ilen++;
if((float)add/sum <1.0/60.0 || (this->IsValley(hisdata,ipoint+ilen)))
{
*imin =ipoint- ilen;
goto LL;
}
else
goto L;
LL:
ilen = 0;
for(i=0;i<2;i++)
{
add = hisdata[ipoint+ilen];
sum+=add;
ilen ++;
}
LLL: add = hisdata[ipoint+ilen];
sum+=add;
ilen ++;
if((float)add/sum <1.0/60.0 || this->IsValley(hisdata,ipoint+ilen))
{
*imax =ipoint+ ilen;
goto LLLL;
}
else
goto LLL;
LLLL: ;
}
bool DIB::Kjudge(int source[], int point,int lenth,int threshold)
{
long sum =0;
for(int i = -lenth/2;i<=lenth/2;i++)
{
sum +=source[point+i];
if(source[i+point]>source[point])
return false;
}
if(sum >threshold)
return true;
else
return false;
}
int DIB::FindK(int hisdata[], int k[10][2],int numcolor)
{
int num =0;
int threshold = 0;
int current,first =1;
for(int i=0;i<256;i++)
threshold +=hisdata[i];
threshold = threshold/100;
for( i=4;i<252;i++)
{
if(Kjudge(hisdata,i,8,threshold))
{
if(first ==1)
{
k[num++][0] = i;
first = 0;
current = i;
}
else
{
if(i-current>=10)
{
k[num++][0] = i;
current = i;
}
}
}
}
if(num<=numcolor)
{
for(int i =0;i<num;i++)
{
int imin,imax;
this->JudgeDomain(hisdata,k[i][0],&imin,&imax);
k[i][1] = imax;
k[i][0] = imin;
}
int k2[10][2];
for( i = 0;i<num;i++)
{
if(i==0 && num >1)
{
k2[i][0] =0;
k2[i][1] = (k[i+1][0]+k[i][1])/2;
}
else if(i == 0 && num == 1 )
{
k2[i][0] = 0;
k2[i][1] = 255;
}
else if( i == num-1 && num >1 && num !=1)
{
k2[i][0] = (k[i-1][1]+k[i][0])/2;
k2[i][1] = 255;
}
else if (i == num-1 && num ==1)
{
;
}
else
{
k2[i][0] = (k[i-1][1] + k[i][0])/2;
k2[i][1] = (k[i][1] + k[i+1][0])/2;
}
}
for(i=0;i<num;i++)
{
k[i][0] = k2[i][0];
k[i][1] = k2[i][1];
}
return num;
}
else
{
for(int i =0;i<num;i++)
{
int imin,imax;
this->JudgeDomain(hisdata,k[i][0],&imin,&imax);
k[i][1] = imax;
k[i][0] = imin;
}
int sourcecenter[10];
L: int temp = 1000;
int position;
for( i = 0;i<num;i++)
sourcecenter[i] = (k[i][0]+k[i][1])/2;
for(i =0;i<num-1;i++)
{
if(sourcecenter[i+1] - sourcecenter[i]<temp)
{
temp = sourcecenter[i+1] - sourcecenter[i];
position = i;
}
}
k[position+1][0] = k[position][0];
for(i = position;i<num-1;i++)
{
k[i][0] = k[i+1][0];
k[i][1] = k[i+1][1];
}
num--;
if(num>numcolor)
goto L;
int k2[10][2];
for( i = 0;i<num;i++)
{
if(i==0 && num >1)
{
k2[i][0] =0;
k2[i][1] = (k[i+1][0]+k[i][1])/2;
}
else if(i == 0 && num == 1 )
{
k2[i][0] = 0;
k2[i][1] = 255;
}
else if( i == num-1 && num >1 && num !=1)
{
k2[i][0] = (k[i-1][1]+k[i][0])/2;
k2[i][1] = 255;
}
else if (i == num-1 && num ==1)
{
;
}
else
{
k2[i][0] = (k[i-1][1] + k[i][0])/2-1;
k2[i][1] = (k[i][1] + k[i+1][0])/2;
}
}
for(i=0;i<num;i++)
{
k[i][0] = k2[i][0];
k[i][1] = k2[i][1];
}
return num;
}
}
HANDLE DIB::ScaleDIB(HANDLE hDIB, float scal_x, float scal_y)
{
if(scal_x<0 || scal_y <0)
return NULL;
LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER) GlobalLock(hDIB);
int w = lpbi->biWidth;
int h = lpbi->biHeight;
BYTE tempmess[40];
LPBYTE Src = this->FindDIBBits(hDIB);
memcpy(tempmess,(LPBYTE)lpbi,40);
int wid = ((int)(w*scal_x+0.5f)*24+31)/32*4;
int imgsize =(int) (wid*(int)(h*scal_y+0.5f));
HDIB hDIB2 = GlobalAlloc(GMEM_MOVEABLE,(DWORD)(sizeof(BITMAPINFOHEADER)+imgsize));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB2);
memcpy((LPBYTE)lpbi,tempmess,40);
lpbi->biWidth =(int)(w*scal_x+0.5f);
lpbi->biHeight = (int)(h*scal_y+0.5f);
lpbi->biSizeImage = imgsize;
LPBYTE lpData = this->FindDIBBits(hDIB2);
int srcWidth = w;
int srcHeight = h;
int dstWidth = (int)(w*scal_x+0.5f);
int dstHeight = (int)(h*scal_y+0.5f);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -