⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dib.cpp

📁 《数字图象工程案例》原码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
					}
			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 + -