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

📄 ddb.cpp

📁 使用大恒采集卡的图像显示
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	{
		(pCQBox + i)->byFlag = 1; // not discard
		pdwFrequency[i] = (pCQBox + i)->dwPixelCount; 
	}

	//找出出现频率最少的16种颜色, 并标记为0
	for(i = 0;  i < 16;  i++)
	{
		//最小值
		DWORD dwMin = pdwFrequency[0]; 
		int nIndexMin = 0; 
		for(j = 1;  j < 252; j++)
		{
			if( pdwFrequency[j] < dwMin)
			{
				dwMin = pdwFrequency[j]; 
				nIndexMin = j; 
			}
		}
		pdwFrequency[nIndexMin] = 100000000L; 
		(pCQBox + nIndexMin)->byFlag = 0;  //discard
	}
	delete[] pdwFrequency; 
	
	//第三步, 为LOGOALETTE分配内存, 并对其进行填充:
	HDC hDC = ::GetDC(NULL); //If this value is NULL,  GetDC retrieves the device context for the entire screen. 
		
	BYTE* pbyLogPalette = new BYTE[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)]; 
	if(pbyLogPalette == NULL)return; 
	memset(pbyLogPalette,  0 ,  (sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY))); 
	LOGPALETTE* pLogPalette = (LOGPALETTE*)pbyLogPalette; 

	pLogPalette->palVersion = 0x300; 
	pLogPalette->palNumEntries = 256; 
	//获取系统调色盘的信息.//
	::GetSystemPaletteEntries(hDC, 0, 256, pLogPalette->palPalEntry); 
	::ReleaseDC(NULL, hDC); 

	//第四步, 采用颜色量化结果改写位于中间的236项, 并建立映射表
	
	//将填入236项的顺序号
	int nIndexMid = 10; 

	//记录被抛弃的顺序
	int nIndexThrow = 0; 

	//保存被抛弃的项
	BYTE abyDiscard[16]; 

	//映射表
	int anMap[252]; 

	
	//从252种入选颜色中顺序填入236种颜色:
	for(i = 0; i < 252; i++)
	{
		if((pCQBox + i)->byFlag != 0)
		{
			DWORD dwNum = (pCQBox + i)->dwPixelCount; 
			if(dwNum == 0)dwNum = 1; 

			(pLogPalette->palPalEntry + nIndexMid)->peBlue = (BYTE)(((pCQBox + i)->dwBlueSum) / dwNum); 		
			(pLogPalette->palPalEntry + nIndexMid)->peGreen = (BYTE)(((pCQBox + i)->dwGreenSum) / dwNum); 
			(pLogPalette->palPalEntry + nIndexMid)->peRed = (BYTE)(((pCQBox + i)->dwRedSum) / dwNum); 
			(pLogPalette->palPalEntry + nIndexMid)->peFlags = PC_NOCOLLAPSE; 
			anMap[i] = nIndexMid; 
			nIndexMid++; 
		}
		else
		{
			abyDiscard[nIndexThrow] = i; 
			nIndexThrow++; 
		}
	}

	//第五步, 创建逻辑调色盘, 对于16种被抛弃的颜色向邻近颜色映射
	pPalette->CreatePalette(pLogPalette); 
	for(i = 0; i < 16; i++)
	{
		DWORD dwNum = (pCQBox + i)->dwPixelCount; 
		if(dwNum == 0)dwNum = 1; 

		BYTE byRed = (BYTE)(((pCQBox + abyDiscard[i])->dwRedSum) / dwNum); 
		BYTE byGreen = (BYTE)(((pCQBox + abyDiscard[i])->dwGreenSum) / dwNum); 
		BYTE byBlue = (BYTE)(((pCQBox + abyDiscard[i])->dwBlueSum) / dwNum); 
		
		anMap[abyDiscard[i]] = (BYTE)pPalette->GetNearestPaletteIndex(RGB(byRed, byGreen, byBlue)); 
	}

	//第六步, 对8位数据重新进行映射

	DWORD dwSize = dwWidthBytes8 * nScanHeight; 
	BYTE* pbyBits8 = lpbyDdbBits8; 
	while(dwSize--)
	{
		*pbyBits8 = anMap[*pbyBits8]; 
		pbyBits8++; 
	}

	delete[] pbyColorBox; 
	delete[] pbyLogPalette; 
}

void CDdb::Save(const char *pszDibFileName, int x, int y, int nWidth, int nHeight)
{
	ASSERT(pszDibFileName); 
	//首先进行参数合法性检测
	if((x > m_nWidth - 1) || (y > nHeight - 1))
	{
		AfxMessageBox("Cross the border!"); 
		return; 
	}
	
	AfxGetApp()->BeginWaitCursor(); 

	//被保存的最后有效宽度和高度:w , h.
	LONG w = (LONG)min(nWidth, m_nWidth - x); 
	LONG h = (LONG)min(nHeight, m_nHeight - y); 


	//被保存位图每行的字节数
	DWORD dwSaveWidthBytes = CalcDibWidthBytes(w, m_nBitCount); 
	
	//DIB位图数据大小, 以字节为单位
	DWORD dwDibBitsSize = dwSaveWidthBytes * m_nHeight; 
	
	//计算整个Dib文件的大小dwFileSize
	DWORD dwFileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwDibBitsSize; 
	if(m_nBitCount == 8) dwFileSize += (256 * sizeof(RGBQUAD)); 

	//计算位图信息到位图数据间的偏移量(字节)
	DWORD dwOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 
	if(m_nBitCount == 8) dwOffBits += (256 * sizeof(RGBQUAD)); 


	//位图文件头结构和位图信息结构
	BITMAPFILEHEADER bmFileHeader; 
	BITMAPINFOHEADER bmInfo; 

	//填充BITMAPFILEHEADER结构
	bmFileHeader.bfType=0x4d42; 
	bmFileHeader.bfSize = dwFileSize; 
	bmFileHeader.bfReserved1 = 0; 
	bmFileHeader.bfReserved2 = 0;  
    bmFileHeader.bfOffBits = dwOffBits; 

	//填充BITMAPINFOHEADER结构:8位仍然保存为8位, 其它均被保存为24位.最低显示模式为8位.
	WORD wBitsPixel = (WORD)m_nBitCount; 
	if(m_nBitCount != 8)wBitsPixel = 24; 
	bmInfo.biSize = sizeof(BITMAPINFOHEADER);    
	bmInfo.biWidth = w;     
	bmInfo.biHeight = h;     
	bmInfo.biPlanes = 1;  
	bmInfo.biBitCount = wBitsPixel;     
	bmInfo.biCompression = 0;     
	bmInfo.biSizeImage = 0;  
	bmInfo.biXPelsPerMeter = 0;     
	bmInfo.biYPelsPerMeter = 0;     
	bmInfo.biClrUsed = 0;  
	bmInfo.biClrImportant = 0; 	

	try
	{
		//	请创建自己的目录或获取当前目录:
		CFile file((LPCTSTR )pszDibFileName, CFile::modeCreate |
			CFile::modeReadWrite | CFile::shareExclusive); 

		//写入文件头和位图信息
		file.Write((LPSTR)&bmFileHeader, sizeof(BITMAPFILEHEADER)); 
		file.Write((LPSTR)&bmInfo, sizeof(BITMAPINFOHEADER)); 

		//如果是8位显示模式, 还需要写入调色盘表项
		if(m_nBitCount == 8)
		{
			//为8位显示模式准备调色盘
			RGBQUAD* pRGBQuad = new RGBQUAD[256]; 
			if(pRGBQuad == NULL)return; 
			
			//初始化为0
			memset(pRGBQuad, 0, 256 * sizeof(RGBQUAD)); 
			
			//创建表项:可能丢失颜色
			GetSystemPaletteEntries(pRGBQuad); 
			
			//写入数据
			file.Write((LPSTR)pRGBQuad, 256 * sizeof(RGBQUAD)); 
			
			delete[] pRGBQuad; 
		}

		switch(m_nBitCount)
		{
		case 8:
		case 24:
			{
				//每行需要补0的个数
				DWORD dwLength = (m_nBitCount == 8) ? w : (3 * w); 
				UINT nZero =  dwSaveWidthBytes - dwLength; 
				BYTE abyZero[] =  {0, 0, 0}; 

				//数据索引基数, 从下往上读
				DWORD dwBaseIndex = (y + h - 1) * m_nDdbWidthBytes + ((m_nBitCount == 8) ? x : (3 * x)); 
				for(LONG i = 0; i < h ; i++)
				{
					
					LPSTR lpsRaw = (LPSTR)(m_pDdbData + dwBaseIndex); 

					//写入子数据, 注意数据量小于64k, 位图宽度可达22767个像素单位或更高
					file.Write(lpsRaw, dwLength); //
					
					//结尾补0
					if(nZero > 0) file.Write((LPSTR)abyZero, nZero); 
					dwBaseIndex -= m_nDdbWidthBytes; 
			
				}
			}
			break; 

		case 16:
		case 32:
			{	
				//对于16位和32位位图, 由于数据需要重组, 所以需要重新分配内存

				//指向Dib实际像素数据的指针, 
				BYTE* pbyDibBits = new BYTE[dwDibBitsSize]; 
				if (pbyDibBits == NULL)	return; 
				
				//数据索引基数
				DWORD dwBaseIndex = y * m_nDdbWidthBytes + ((m_nBitCount == 16) ? (x + x) : (4 * x)); 
				DWORD dwIndexDib = (h - 1) * dwSaveWidthBytes; 
				//离析像素数据, 并将其写入内存, 从上往下读
				for(LONG i = 0;  i < h; i++)
				{
				
					//指向Ddb内存数据的指针(行)
					BYTE* pbyDdbData = m_pDdbData + dwBaseIndex; 

					//指向Dib内存数据的指针(行)
					BYTE* pbyDibData = pbyDibBits + dwIndexDib; 

					for(LONG j = 0; j < w; j++)
					{
						
						//处理16位
						if(m_nBitCount == 16)
						{
							//记录一个像素点的24位颜色值(16位和32位模式均被转化为24位)
							BYTE* pbyRGB = new BYTE[3]; 
							WORD* pwDdbData_16 = (WORD*)(pbyDdbData++); 
							GetRGB16(pbyRGB, pwDdbData_16); 
							pbyDdbData++; 
							*pbyDibData++ =  pbyRGB[0]; 	//b
							*pbyDibData++ =  pbyRGB[1];  //g
							*pbyDibData++ =  pbyRGB[2]; 	//r
							delete[] pbyRGB; 
						}

						//处理32位
						if(m_nBitCount == 32)
						{
							*pbyDibData++ = *pbyDdbData++; 	//蓝色
							*pbyDibData++ = *pbyDdbData++; 	//绿色
							*pbyDibData++ = *pbyDdbData++; 	//红色
							pbyDdbData++; 
						}
			
					}//end j
					dwBaseIndex += m_nDdbWidthBytes; 
					dwIndexDib -= dwSaveWidthBytes; 
				}//end  i

				//将内存数据写入文件
				file.WriteHuge((LPSTR)pbyDibBits, dwDibBitsSize); 
				
				delete[] pbyDibBits; 
			}
			break; 
		
		}

		file.Close(); 	
	}//end try
	catch(CFileException* e)
	{
		e->Delete(); 
	}

	AfxGetApp()->EndWaitCursor(); 
}

void CDdb::Save256(const char *pszDibFileName, int x, int y, int nWidth, int nHeight)
{
	ASSERT(pszDibFileName); 
	if(m_nBitCount <= 8) 
	{
		Save(pszDibFileName, x, y, nWidth, nHeight); 
		return; 
	}

	//首先进行参数合法性检测
	if((x > m_nWidth - 1) || (y > nHeight - 1))
	{
		AfxMessageBox("Cross the border!"); 
		return; 
	}
	AfxGetApp()->BeginWaitCursor(); 

	//被保存的最后有效宽度和高度:w , h.
	LONG w = (LONG)min(nWidth, m_nWidth - x); 
	LONG h = (LONG)min(nHeight, m_nHeight - y); 


	//////////////////////////////////////////////////////
	//第一步:将数据转化为24位DDB数据
	//原DDB数据转换成24位后, 每行的大小和总的数据量
	DWORD dwWidthBytes24 =  ((w * 24 + 15) / 16) * 2; 
	DWORD dwBitsSize24 = dwWidthBytes24 * h; 

	//分配全局内存, 以存放经格式转换后的像素数据

	//指向24位数据的指针
	BYTE* pbyDdbBits24 = new BYTE[dwBitsSize24]; 
	if(pbyDdbBits24 == NULL) return; 
	memset(pbyDdbBits24,  0,  dwBitsSize24); 

	//指向24位像素数据的指针, 这些数据是由16, 24, 32位模式转化而来的.
	GetDdbDataTo24(x,  y,  w,  h,  pbyDdbBits24); 

	
	//////////////////////////////////////////////////////
	//第二步, 获取量化后的数据
	//分配存储8位数据的内存
	DWORD dwWidthBytes8 =  ((w * 8 + 15) / 16) * 2; 
	DWORD dwBitsSize8 = dwWidthBytes8 * h; 

	//指向8位数据的指针
	BYTE* pbyDdbBits8 =  new BYTE[dwBitsSize8]; 
	if (pbyDdbBits8 == NULL)return ; 
	memset(pbyDdbBits8,  0 ,  dwBitsSize8);  

	//////////////////////////////////////////////////////
	//获取量化数据
	CPalette* pPalette = new CPalette(); 
	QuantizeColor(pbyDdbBits24,  w,  h,  pbyDdbBits8,  pPalette); 

	
	//////////////////////////////////////////////////////
	//获取调色数据
	RGBQUAD* pRGBQuad = new RGBQUAD[256]; 
	if(pRGBQuad == NULL)return; 
	//初始化为0
	memset(pRGBQuad, 0, 256 * sizeof(RGBQUAD)); 
	
	PALETTEENTRY* pPE = new PALETTEENTRY[256]; 
	if(pPE == NULL)return; 
	pPalette->GetPaletteEntries(0, 256, pPE); 
	
	for(int j = 0; j < 256; j++)
	{
		pRGBQuad[j].rgbRed = pPE[j].peRed; 
		pRGBQuad[j].rgbGreen = pPE[j].peGreen; 
		pRGBQuad[j].rgbBlue = pPE[j].peBlue; 
	}

	delete[] pPE; 
	delete pPalette; 

	//////////////////////////////////////////////////////
	//第三步, 填充与位图相关的结构

	//宽度字节数
	DWORD dwDibWidthBytes = ((w * 8 + 31) / 32) * 4; 
	//位图数据大小
	DWORD dwDibBitsSize = dwDibWidthBytes * h; 

	//计算整个Dib文件的大小dwFileSize
	DWORD dwFileSize = sizeof(BITMAPFILEHEADER) 
						 + sizeof(BITMAPINFOHEADER) 
						 + 256 * sizeof(RGBQUAD)
						 + dwDibBitsSize; 

	//计算位图信息到位图数据间的偏移量(字节)
	DWORD dwOffBits = sizeof(BITMAPFILEHEADER) 
						+ sizeof(BITMAPINFOHEADER) 
						+ 256 * sizeof(RGBQUAD); 

	//位图文件头结构和位图信息结构
	BITMAPFILEHEADER bmFileHeader; 
	BITMAPINFOHEADER bmInfo; 

	//填充BITMAPFILEHEADER结构
	bmFileHeader.bfType=0x4d42; 
	bmFileHeader.bfSize = dwFileSize; 
	bmFileHeader.bfReserved1 = 0; 
	bmFileHeader.bfReserved2 = 0;  
    bmFileHeader.bfOffBits = dwOffBits; 

	//填充BITMAPINFOHEADER结构

	bmInfo.biSize = sizeof(BITMAPINFOHEADER);     
	bmInfo.biWidth = w;     
	bmInfo.biHeight = h;     
	bmInfo.biPlanes = 1;  
	bmInfo.biBitCount = 8;     
	bmInfo.biCompression = 0;     
	bmInfo.biSizeImage = 0;  
	bmInfo.biXPelsPerMeter = 0;     
	bmInfo.biYPelsPerMeter = 0;     
	bmInfo.biClrUsed = 0;  
	bmInfo.biClrImportant = 0; 	

	//第四步, 写数据
	//////////////////////////////////////////////////////
	try
	{
		//	请创建自己的目录或获取当前目录:
		CFile file((LPCTSTR )pszDibFileName, CFile::modeCreate |
			CFile::modeReadWrite | CFile::shareExclusive); 

		//写入文件头和位图信息
		file.Write((LPSTR)&bmFileHeader, sizeof(BITMAPFILEHEADER)); 
		file.Write((LPSTR)&bmInfo, sizeof(BITMAPINFOHEADER)); 

		//写入数据
		file.Write((LPSTR)pRGBQuad, 256 * sizeof(RGBQUAD)); 
		
		delete[] pRGBQuad; 
		pRGBQuad = NULL; 

		//数据索引(行头)
		DWORD dwBaseIndex = (DWORD)(h - 1) * dwWidthBytes8; 

		UINT nZero =  dwDibWidthBytes - dwWidthBytes8; 
		BYTE abyZero[] =  {0, 0}; 
		
		for(int i = 0; i < h ; i++)
		{
			BYTE* pDibBits8 = pbyDdbBits8 + dwBaseIndex; 
			file.Write((LPSTR)pDibBits8,  dwWidthBytes8); 
			if(nZero > 0)file.Write((LPSTR)abyZero, 2); 
			dwBaseIndex -= dwWidthBytes8; 
		}//end i

		file.Close(); 
	}//end try
	catch(CFileException* e)
	{
		e->Delete(); 
	}

	if(pRGBQuad)delete[] pRGBQuad; 

	delete[] pbyDdbBits24; 
	delete[] pbyDdbBits8; 

	AfxGetApp()->EndWaitCursor(); 
}

BOOL CDdb::Draw(CDC *pDstDC, int x, int y, int nWidth, int nHeight, int xSrc, 
				int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop)
{
	CDC memoryDC; 
	memoryDC.CreateCompatibleDC(pDstDC); 
	CBitmap* pOldBitmap = memoryDC.SelectObject(m_pDdb); 

	BOOL bDraw = (pDstDC->StretchBlt(x, y, nWidth, nHeight, &memoryDC, xSrc, ySrc, nSrcWidth, nSrcHeight, dwRop )); 
	memoryDC.SelectObject(pOldBitmap); 
	return (bDraw); 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -