位图的颜色转换 24位转成256色和16色,怎么转? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 24bit to 16bitred = (truecolor>>8)&0xf800;green = (truecolor>>5)&0x7e0;blue = (truecolor>>3)&0x1f;hicolor=red|green|blue; HBITMAP LoadBitmap( HINSTANCE hInstance, // handle to application instance LPCTSTR lpBitmapName // address of bitmap resource name);BITMAPINFO * BitmapToDIB(HPALETTE hPal, // palette for color conversion HBITMAP hBmp, // DDB for convert int nBitCount, int nCompression) // format wanted{ typedef struct { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[256+3]; } DIBINFO; BITMAP ddbinfo; DIBINFO dibinfo; // retrieve DDB information if ( GetObject(hBmp, sizeof(BITMAP), & ddbinfo)==0 ) return NULL; // fill out BITMAPINFOHEADER based on size and required format memset(&dibinfo, 0, sizeof(dibinfo)); dibinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); dibinfo.bmiHeader.biWidth = ddbinfo.bmWidth; dibinfo.bmiHeader.biHeight = ddbinfo.bmHeight; dibinfo.bmiHeader.biPlanes = 1; dibinfo.bmiHeader.biBitCount = nBitCount; dibinfo.bmiHeader.biCompression = nCompression; HDC hDC = GetDC(NULL); // screen DC HGDIOBJ hpalOld; if ( hPal ) hpalOld = SelectPalette(hDC, hPal, FALSE); else hpalOld = NULL; // query GDI for image size GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, NULL, (BITMAPINFO *) & dibinfo, DIB_RGB_COLORS); int nInfoSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * GetDIBColorCount(dibinfo.bmiHeader); int nTotalSize = nInfoSize + GetDIBPixelSize(dibinfo.bmiHeader); BYTE * pDIB = new BYTE[nTotalSize]; if ( pDIB ) { memcpy(pDIB, & dibinfo, nInfoSize); if ( ddbinfo.bmHeight != GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, pDIB + nInfoSize, (BITMAPINFO *) pDIB, DIB_RGB_COLORS) ) { delete [] pDIB; pDIB = NULL; } } if ( hpalOld ) SelectObject(hDC, hpalOld); ReleaseDC(NULL, hDC); return (BITMAPINFO *) pDIB;}BOOL SaveDIBToBmp(const char* pFileName, const BITMAPINFO *pBMI, const BYTE *pBits){ if(pFileName==NULL){ return FALSE; } HANDLE handle = CreateFile(pFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(handle == INVALID_HANDLE_VALUE){ return FALSE; } BITMAPFILEHEADER bmFH; int nHeadSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * GetDIBColorCount(pBMI->bmiHeader); bmFH.bfType = 0x4D42; bmFH.bfSize = nHeadSize + GetDIBPixelSize(pBMI->bmiHeader); bmFH.bfReserved1 = 0; bmFH.bfReserved2 = 0; bmFH.bfOffBits = nHeadSize + sizeof(BITMAPFILEHEADER); DWORD dwRead = 0; WriteFile(handle, & bmFH, sizeof(bmFH), & dwRead, NULL); if(pBits==NULL) // packed DIB pBits = (BYTE *) pBMI + nHeadSize; WriteFile(handle, pBMI, nHeadSize, & dwRead, NULL); WriteFile(handle, pBits, GetDIBPixelSize(pBMI->bmiHeader), & dwRead, NULL); CloseHandle(handle); return TRUE;}给下面函数nBitCount 传递8表示保存为256色位图BITMAPINFO * BitmapToDIB(HPALETTE hPal, // palette for color conversion HBITMAP hBmp, // DDB for convert int nBitCount, int nCompression) // format wanted 有没有直接对象素的RGB进行转换的算法? hehe ,我做过这样的东东,256色的8个bit 中(RGB332),一个语句就搞定了:return (P[tag].red/32*32+(P[tag].green/32)*4+P[tag].blue/64); 有没有直接对象素的RGB进行转换的算法?-------------------------------------------------肯定没有16色、256色都是调色版格式必须考虑色彩量化处理我以前用VB写的通过有序抖动保存各种格式的BMP(先进行相应抖动运算,再保存)的程序:http://zyl910vb.51.net/vb/map/ddsfDIB.htm右击连接,目标另存为注意把下载后的*.zip.jpg改名成*.zip这个程序是以前写的刚学计算机图形学不太懂效率较低 如果用了gammergr的方法觉得效果不好请联系我,不过是付费的! CCh1_1Doc* pDoc = GetDocument();// 获取文档 HDIB hDIB=pDoc->GetHDIB(); m_UnDo=CopyHandle(hDIB); LPSTR lpDIB; // 指向DIB的指针 lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());// 锁定DIB if (lpDIB==NULL)return; int NumColors; NumColors=((LPBITMAPINFOHEADER)lpDIB)->biBitCount; if(NumColors!=24) { MessageBox("不是24位真彩位图,不能操作。"); return; } BeginWaitCursor(); // 更改光标形状 LPSTR lpDIBBits;// 指向DIB图像开始处象素指针 LPSTR lpNewDIBBits;// 指向DIB灰度图图像开始处象素的指针 unsigned char * ired; unsigned char * igreen; unsigned char * iblack; long i,j;// 循环变量 long lWidth,lHeight;// 图像宽度,图像高度 lWidth = ::DIBWidth(lpDIB); // 获取图像宽度 lHeight = ::DIBHeight(lpDIB);// 获取图像高度 lWidth =WIDTHBYTES(lWidth * 8); lpDIBBits=::FindDIBBits(lpDIB);// 找到DIB图像象素起始位置&lpDIB[sizeof(BITMAPINFOHEADER)]; unsigned char * lpdest; lpdest=(unsigned char *)::malloc(lHeight*lWidth); int n=0; for(j = 0; j <3*lWidth*lHeight; n++,j=j+3)//读取图像数据并转化成灰度 { ired= (unsigned char*)lpDIBBits + j+2; igreen = (unsigned char*)lpDIBBits+j+1; iblack = (unsigned char*)lpDIBBits +j; lpdest[n] =(unsigned char)(0.299*(*ired)+0.587*(*igreen)+0.114*(*iblack)); } LPBITMAPINFOHEADER lpBI;//位图信息头 // 读取BITMAPINFO结构,初始化指针 lpBI = (LPBITMAPINFOHEADER)lpDIB;//[sizeof(BITMAPFILEHEADER)]; lpBI->biBitCount=8; //设置256色灰度调色板 RGBQUAD *lpRGBquad; lpRGBquad=(RGBQUAD *)&lpDIB[sizeof(BITMAPINFOHEADER)];//位图信息头后面为调色板 for (i = 0; i < 256; i++) { lpRGBquad[i].rgbRed =(unsigned char)i;// 读取红色分量 lpRGBquad[i].rgbGreen =(unsigned char)i;// 读取绿色分量 lpRGBquad[i].rgbBlue = (unsigned char)i;// 读取红色分量 lpRGBquad[i].rgbReserved = 0;// 保留位 } lpNewDIBBits= ::FindDIBBits(lpDIB);// 找到DIB图像象素起始位置 unsigned char * lpSrc; for (i=0;i<lHeight*lWidth;i++)//写灰度图像数据 { lpSrc=(unsigned char*)lpNewDIBBits+i; *lpSrc=lpdest[i]; } ::free((void *)lpdest); pDoc->UpdateAllViews(NULL);//更新视图 ::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());// 解除锁定 EndWaitCursor();// 恢复光标 期望高手可以推荐网络编程的入门资料 VC2008用MFC开发时查询oracle,中文乱码问题 Scoket通信的简单问题! 图像放缩算法改进疑问 怎样在进程间传输带有指针变量的结构数据? 两个多边形相交,如何把相交的部分构造一个闭合区域??? 如何做两个计时器? 高手帮帮我 WIN2K下屏蔽ALT+F4的问题 如何导出计算过程? jennyvenus, oldworm来拿分,顺便继续讨论软件加密问题。 能解决这个问题的肯定为vc老手,你有没没兴趣挑战一下
green = (truecolor>>5)&0x7e0;
blue = (truecolor>>3)&0x1f;
hicolor=red|green|blue;
HINSTANCE hInstance, // handle to application instance
LPCTSTR lpBitmapName // address of bitmap resource name
);BITMAPINFO * BitmapToDIB(HPALETTE hPal, // palette for color conversion
HBITMAP hBmp, // DDB for convert
int nBitCount, int nCompression) // format wanted
{
typedef struct
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256+3];
} DIBINFO; BITMAP ddbinfo;
DIBINFO dibinfo; // retrieve DDB information
if ( GetObject(hBmp, sizeof(BITMAP), & ddbinfo)==0 )
return NULL; // fill out BITMAPINFOHEADER based on size and required format
memset(&dibinfo, 0, sizeof(dibinfo)); dibinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
dibinfo.bmiHeader.biWidth = ddbinfo.bmWidth;
dibinfo.bmiHeader.biHeight = ddbinfo.bmHeight;
dibinfo.bmiHeader.biPlanes = 1;
dibinfo.bmiHeader.biBitCount = nBitCount;
dibinfo.bmiHeader.biCompression = nCompression; HDC hDC = GetDC(NULL); // screen DC
HGDIOBJ hpalOld;
if ( hPal )
hpalOld = SelectPalette(hDC, hPal, FALSE);
else
hpalOld = NULL; // query GDI for image size
GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, NULL, (BITMAPINFO *) & dibinfo, DIB_RGB_COLORS); int nInfoSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * GetDIBColorCount(dibinfo.bmiHeader);
int nTotalSize = nInfoSize + GetDIBPixelSize(dibinfo.bmiHeader); BYTE * pDIB = new BYTE[nTotalSize]; if ( pDIB )
{
memcpy(pDIB, & dibinfo, nInfoSize);
if ( ddbinfo.bmHeight != GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, pDIB + nInfoSize, (BITMAPINFO *) pDIB, DIB_RGB_COLORS) )
{
delete [] pDIB;
pDIB = NULL;
}
} if ( hpalOld )
SelectObject(hDC, hpalOld); ReleaseDC(NULL, hDC); return (BITMAPINFO *) pDIB;
}BOOL SaveDIBToBmp(const char* pFileName, const BITMAPINFO *pBMI, const BYTE *pBits)
{
if(pFileName==NULL){
return FALSE;
} HANDLE handle = CreateFile(pFileName, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE){
return FALSE;
} BITMAPFILEHEADER bmFH; int nHeadSize = sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * GetDIBColorCount(pBMI->bmiHeader); bmFH.bfType = 0x4D42;
bmFH.bfSize = nHeadSize + GetDIBPixelSize(pBMI->bmiHeader);
bmFH.bfReserved1 = 0;
bmFH.bfReserved2 = 0;
bmFH.bfOffBits = nHeadSize + sizeof(BITMAPFILEHEADER); DWORD dwRead = 0;
WriteFile(handle, & bmFH, sizeof(bmFH), & dwRead, NULL); if(pBits==NULL) // packed DIB
pBits = (BYTE *) pBMI + nHeadSize;
WriteFile(handle, pBMI, nHeadSize, & dwRead, NULL);
WriteFile(handle, pBits, GetDIBPixelSize(pBMI->bmiHeader), & dwRead, NULL); CloseHandle(handle); return TRUE;
}给下面函数nBitCount 传递8表示保存为256色位图
BITMAPINFO * BitmapToDIB(HPALETTE hPal, // palette for color conversion
HBITMAP hBmp, // DDB for convert
int nBitCount, int nCompression) // format wanted
一个语句就搞定了:
return (P[tag].red/32*32+(P[tag].green/32)*4+P[tag].blue/64);
-------------------------------------------------
肯定没有
16色、256色都是调色版格式
必须考虑色彩量化处理
我以前用VB写的通过有序抖动保存各种格式的BMP(先进行相应抖动运算,再保存)的程序:
http://zyl910vb.51.net/vb/map/ddsfDIB.htm
右击连接,目标另存为
注意把下载后的*.zip.jpg改名成*.zip
这个程序是以前写的
刚学计算机图形学
不太懂
效率较低
请联系我,不过是付费的!
HDIB hDIB=pDoc->GetHDIB();
m_UnDo=CopyHandle(hDIB);
LPSTR lpDIB; // 指向DIB的指针
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());// 锁定DIB
if (lpDIB==NULL)return;
int NumColors;
NumColors=((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
if(NumColors!=24)
{
MessageBox("不是24位真彩位图,不能操作。");
return;
}
BeginWaitCursor(); // 更改光标形状
LPSTR lpDIBBits;// 指向DIB图像开始处象素指针
LPSTR lpNewDIBBits;// 指向DIB灰度图图像开始处象素的指针
unsigned char * ired;
unsigned char * igreen;
unsigned char * iblack;
long i,j;// 循环变量
long lWidth,lHeight;// 图像宽度,图像高度
lWidth = ::DIBWidth(lpDIB); // 获取图像宽度
lHeight = ::DIBHeight(lpDIB);// 获取图像高度
lWidth =WIDTHBYTES(lWidth * 8);
lpDIBBits=::FindDIBBits(lpDIB);// 找到DIB图像象素起始位置&lpDIB[sizeof(BITMAPINFOHEADER)];
unsigned char * lpdest;
lpdest=(unsigned char *)::malloc(lHeight*lWidth);
int n=0;
for(j = 0; j <3*lWidth*lHeight; n++,j=j+3)//读取图像数据并转化成灰度
{
ired= (unsigned char*)lpDIBBits + j+2;
igreen = (unsigned char*)lpDIBBits+j+1;
iblack = (unsigned char*)lpDIBBits +j;
lpdest[n] =(unsigned char)(0.299*(*ired)+0.587*(*igreen)+0.114*(*iblack));
}
LPBITMAPINFOHEADER lpBI;//位图信息头
// 读取BITMAPINFO结构,初始化指针
lpBI = (LPBITMAPINFOHEADER)lpDIB;//[sizeof(BITMAPFILEHEADER)];
lpBI->biBitCount=8;
//设置256色灰度调色板
RGBQUAD *lpRGBquad;
lpRGBquad=(RGBQUAD *)&lpDIB[sizeof(BITMAPINFOHEADER)];//位图信息头后面为调色板
for (i = 0; i < 256; i++)
{
lpRGBquad[i].rgbRed =(unsigned char)i;// 读取红色分量
lpRGBquad[i].rgbGreen =(unsigned char)i;// 读取绿色分量
lpRGBquad[i].rgbBlue = (unsigned char)i;// 读取红色分量
lpRGBquad[i].rgbReserved = 0;// 保留位
}
lpNewDIBBits= ::FindDIBBits(lpDIB);// 找到DIB图像象素起始位置
unsigned char * lpSrc;
for (i=0;i<lHeight*lWidth;i++)//写灰度图像数据
{
lpSrc=(unsigned char*)lpNewDIBBits+i;
*lpSrc=lpdest[i];
}
::free((void *)lpdest);
pDoc->UpdateAllViews(NULL);//更新视图
::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());// 解除锁定
EndWaitCursor();// 恢复光标