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

📄 formatddbdata.cpp

📁 visual c++数字图像与图形处理中的光盘内容
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	pLogPalette->palPalEntry[253].peRed = 0xFF;
	pLogPalette->palPalEntry[253].peGreen = 0x00;
	pLogPalette->palPalEntry[253].peBlue = 0xFF;
	pLogPalette->palPalEntry[254].peRed = 0x00;
	pLogPalette->palPalEntry[254].peGreen = 0xFF;
	pLogPalette->palPalEntry[254].peBlue = 0xFF;
	pLogPalette->palPalEntry[255].peRed = 0xFF;
	pLogPalette->palPalEntry[255].peGreen = 0xFF;
	pLogPalette->palPalEntry[255].peBlue = 0xFF;
	
	//第三步, 以正常方式对待调色盘中的颜色.
	for(i = 0; i < 256; i++)
		pLogPalette->palPalEntry[i].peFlags = 0;

	delete[] pbyColorBox;
}

//创建等同调色盘.等同调色盘是与当前系统主调色盘完全匹配的一个逻辑调色盘.
//事实上, 它是主调色盘的一个副本.
//pLogPalRsc--应用程序希望的逻辑调色盘;
//pPalette, 等于同调色盘, 它是一个CPalette
BOOL CFormatDdbData::CreateIdentityPalette(LOGPALETTE *pLogPalRsc,  CPalette *pPalette)
{
	ASSERT(pLogPalRsc);

	//第一步, 检测是否为调色设备
	CDC dc;

	//如果不是一个需调色设备, 就简单地返回
	if (!dc.CreateDC ("DISPLAY",  NULL,  NULL,  NULL))
	{
		AfxMessageBox("Can't create a DC");
		return FALSE;
	}
	else if ((~dc.GetDeviceCaps (RASTERCAPS) & RC_PALETTE)) 
	{
		dc.DeleteDC ();
		AfxMessageBox("The DC is not a palette device");
		return FALSE;
	} 
	//我们只处理8位256色显示模式, 对于16色显示模式, 我们不处理.
	if(dc.GetDeviceCaps(BITSPIXEL) != 8) 
	{
		AfxMessageBox("The display mode is not 256-color mode"); 
		return FALSE;
	}

	//在256色显示模式中检查颜色模式:
	
	//nStaticColors表示静态颜色数目, 在8位颜色模式下, 该值应该等于20
	int nStaticColors = dc.GetDeviceCaps (NUMCOLORS);
	if (nStaticColors != 20) 
	{
		dc.DeleteDC ();
		AfxMessageBox("The number of static color is not equal to 20"); 
		return FALSE;
	}
 
	//Number of entries in the system palette. This index is valid only if the device driver sets the RC_PALETTE bit in the RASTERCAPS index and is available only if the driver is compatible with 16-bit Windows.
	//nPaletteEntries表示调色盘颜色表项的数目
	int nPaletteEntries = dc.GetDeviceCaps (SIZEPALETTE);

	//第二, 迫使系统包含静态颜色
	//迫使系统调色盘包含两项静态颜色, 黑色和白色, 其索引号分别为0和255.
	//同时, 系统调色盘将重设主颜色表, 让它必须包含静态颜色, 这些颜色将不会因为选入新的逻辑调色盘后而得到改变.
	//并且, 可方便下一个将要实现的调色盘将其颜色插入主调色盘.
	SetSystemPaletteUse (dc.GetSafeHdc(),  SYSPAL_NOSTATIC);
	SetSystemPaletteUse (dc.GetSafeHdc(),  SYSPAL_STATIC);

	//第三, 对希望的逻辑调色盘进行映射
	//利用源调色盘信息pLogPalRsc构造一个逻辑调色盘, 
	pPalette->CreatePalette(pLogPalRsc);
	if (!pPalette) 
	{
		dc.DeleteDC ();
		return FALSE;
	}
	
	//强制性地重新设置主调色盘, 将其完全映射到逻辑调色盘.
	//选取并实现指定的逻辑调色盘.
	CPalette* pOldPal = dc.SelectPalette (pPalette,  FALSE);
	dc.RealizePalette ();
	dc.SelectPalette (pOldPal,  FALSE);

	//第四, 创建一个等同调色盘
	//获取当前主调色盘的一个副本, 同时, 这个副本应使颜色使用PC_NOCOLLAPSE标志.
	//从而当再次实现该逻辑调色盘时, 这些颜色不必重新映射.

	PALETTEENTRY pe[256];
	GetSystemPaletteEntries (dc.GetSafeHdc(),  0,  nPaletteEntries,  pe);

	
	//设置调色盘的前10项, 中间236项, 后10项.
	//系统静态颜色分别位于前10项和后10项.
	int i = 0;
	for (i = 0; i < nStaticColors / 2; i++) 
		pe[i].peFlags = 0;
	for (; i < nPaletteEntries - nStaticColors / 2; i++)
		pe[i].peFlags = PC_NOCOLLAPSE;
	for (; i < nPaletteEntries; i++) 
		pe[i].peFlags = 0;

	//重新设置调色盘的大小, 使之与系统匹配
	pPalette->ResizePalette (nPaletteEntries);
	
	//将系统主调色盘的一个副本 pe 拷贝到pPalette之中, 从而创建了一个等同调色盘.
	pPalette->SetPaletteEntries (0,  nPaletteEntries,  pe);

	dc.DeleteDC();
	return TRUE;
}

//

void CFormatDdbData::Remap(DWORD dwCount, LPBYTE lpbyDstBits8,  LOGPALETTE* pLogPalRsc,  CPalette *pIdentityPal)
{
	ASSERT(lpbyDstBits8);
	ASSERT(pLogPalRsc);
	ASSERT(pIdentityPal);

	//创建一个新的索引映射表
	BYTE abyMap[256];
	for(int i = 0; i < 256; i++)
		abyMap[i] = (BYTE) pIdentityPal->GetNearestPaletteIndex(
						RGB(pLogPalRsc->palPalEntry[i].peRed,  
						pLogPalRsc->palPalEntry[i].peGreen,  
						pLogPalRsc->palPalEntry[i].peBlue));

	//完成映射
	DWORD dwMapNum = dwCount;
	BYTE* pbyScanMap = lpbyDstBits8;

	//扫描行尾的0(如果有)必然被映射映射为0.
	while(dwMapNum--)
	{
		//单点映射
		*pbyScanMap = abyMap[*pbyScanMap]; 
		pbyScanMap++;
	}

}

void CFormatDdbData::Format32To16(LPBYTE lpbySrcBits32,  int nScanWidth,  int nScanHeight,  LPBYTE lpbyDstBits16)
{
	ASSERT(lpbySrcBits32);
	ASSERT(lpbyDstBits16);
	//对于16, 32位DDB数据, 其扫描字节宽度必然为其宽度的2倍

	//指向32位和16每行数据的指针	
	BYTE* pbyBits32 = lpbySrcBits32;
	WORD* pwBits16 = (WORD*)lpbyDstBits16;
	for(int i = 0; i < nScanHeight; i++)
	{
		for(int j = 0; j < nScanWidth; j++)
		{
			
			BYTE byBlue = *(pbyBits32++);	
			BYTE byGreen = *(pbyBits32++);
			BYTE byRed = *(pbyBits32++);
			pbyBits32++;
			*(pwBits16++) = PutRGB16(byRed, byGreen, byBlue);
		}
	}
}

void CFormatDdbData::Format32To24(LPBYTE lpbySrcBits32,  int nScanWidth,  int nScanHeight,  LPBYTE lpbyDstBits24)
{
	ASSERT(lpbySrcBits32);
	ASSERT(lpbyDstBits24);
	//24位DDB数据
	DWORD dwWidthBytes24 = GetDdbWidthBytes(nScanWidth, 24);
	//对于32位DDB数据, 其扫描字节宽度必然为其宽度的2倍

	//指向32每行数据的指针	
	DWORD dwBaseIndex24 = 0;
	BYTE* pbyBits32 = lpbySrcBits32;
	for(int i = 0; i < nScanHeight; i++)
	{
		BYTE* pbyBits24 = lpbyDstBits24 + dwBaseIndex24;
		for(int j = 0; j < nScanWidth; j++)
		{
			
			*(pbyBits24++) = *(pbyBits32++);	//蓝色	
			*(pbyBits24++) = *(pbyBits32++);	//绿色
			*(pbyBits24++) = *(pbyBits32++);	//红色
			pbyBits32++;
		}
		dwBaseIndex24 += dwWidthBytes24;
	}
}

//将32位数据转化为8位数据
void CFormatDdbData::Format32To8(LPBYTE lpbySrcBits32,  int nScanWidth,  int nScanHeight,  LPBYTE lpbyDstBits8, CPalette *pPalette)
{
	ASSERT(lpbySrcBits32);
	ASSERT(lpbyDstBits8);
	//先转化为24位数据, 再转换为8位数据
	//总的数据量:字节数
	DWORD dwCount24 = GetDdbWidthBytes(nScanWidth, 24) * nScanHeight;

	//指向位数据的指针, 在运算的过程中不改变
	BYTE* pbyDdb24 =  new BYTE[dwCount24];
	if(pbyDdb24 == NULL) return;
	memset(pbyDdb24, 0, dwCount24);


	Format32To24(lpbySrcBits32, nScanWidth, nScanHeight, pbyDdb24);
	Format24To8(pbyDdb24, nScanWidth, nScanHeight, lpbyDstBits8, pPalette);

	delete[] pbyDdb24;
}

//找出给定颜色的最邻近颜色索引, 采用欧拉空间距离法
int CFormatDdbData::GetNearestColorIndex(BYTE byRed,  BYTE byGreen,  BYTE byBlue,  PALETTEENTRY *pPalEntry)
{
	ASSERT(pPalEntry);
	int nNearestIndex = 0;
	DWORD dwMin = 300000L;
	for(int i = 0;i < 256;i++)
	{
		DWORD dwDeltaRed, dwDeltaGreen, dwDeltaBlue, dwMag;
		if(byRed > pPalEntry[i].peRed)
			dwDeltaRed = (DWORD)(byRed - pPalEntry[i].peRed);
		else
			dwDeltaRed = (DWORD)(pPalEntry[i].peRed - byRed);
	
		if(byGreen > pPalEntry[i].peGreen)
			dwDeltaGreen = (DWORD)(byGreen - pPalEntry[i].peGreen);
		else
			dwDeltaGreen = (DWORD)(pPalEntry[i].peGreen - byGreen);
		
		if(byBlue > pPalEntry[i].peBlue)
			dwDeltaBlue = (DWORD)(byBlue - pPalEntry[i].peBlue);
		else
			dwDeltaBlue = (DWORD)(pPalEntry[i].peBlue - byBlue);
		dwMag = (dwDeltaRed * dwDeltaRed + dwDeltaGreen * dwDeltaGreen + dwDeltaBlue * dwDeltaBlue);

		if(dwMag < dwMin)
		{
			if(dwMag <= 1) return (i);
			dwMin = dwMag;
			nNearestIndex = i;
		}
	}
	return (nNearestIndex);
}


⌨️ 快捷键说明

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