急,如何在程序中把一个真彩色位图,变成256色的呢 我在Linux下见过这方面的源码。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 给你一份源程序吧。这可是我自己想出来的方法,使用时感觉还不错。BOOL CovtRGBToPal(HANDLE& hDib); //这儿的 hDib 存放的数据结构和bmp文件的结构一样,只是没有bmp文件的头结构BITMAPFILEINFO。我这儿用的是API的代码(因为我是用C++Builder的)。#ifdef NUM#undef NUM#endif#define NUM 0x2000struct RGBNum{ int Num; long RGB;};static int SortN(const void* p1, const void* p2){ int i,j,Y[2]; RGBNum* pr[2]; WORD C[3]={299,587,114}; pr[0] = (RGBNum*)p1; pr[1] = (RGBNum*)p2; if (pr[0]->Num == pr[1]->Num) { if (pr[0]->RGB==pr[1]->RGB) return 0; for(i=0; i<2; i++) { for(j=0,Y[i]=0;j<24;j+=8) Y[i] += C[j/8]*((BYTE) (pr[i]->RGB>>j)); } return Y[1] - Y[0]; } else return pr[1]->Num - pr[0]->Num;}static void MaskRGB(RGBNum* Data, DWORD Mask){ int n; int Size; RGBNum *pr; RGBNum *pr1; Mask = RGB(Mask, Mask, Mask); for(n=0,pr=Data; n<NUM; n++) { pr->RGB &= Mask; pr++; } pr = Data + (NUM-1); Size = sizeof(RGBNum); for(n=NUM-1; n>0; n--,pr--) { if (pr->Num==0) continue; DWORD nRGB = pr->RGB; for(pr1=pr-1; true; ) { if (pr1->RGB!=nRGB) { if (pr1 == Data) break; pr1--; continue; } pr1->Num += pr->Num; memset(pr, 0, Size); break; } } qsort(Data, NUM, sizeof( RGBNum), SortN);}BOOL CovtRGBToPal(HANDLE& hDib){ int i,j; int k,n; int nClr; BYTE Sht; BYTE *pb; BYTE *pb1; BYTE Mask; BYTE Pad0; BYTE Pad1; DWORD nRGB; DWORD Size; HANDLE hMem; RGBNum *pr; HPALETTE hPal; RGBNum Count[NUM]; PALETTEENTRY *ppe; LOGPALETTE* pLogPal; BITMAPINFOHEADER* pbih; if (!hDib) return FALSE; pbih = (BITMAPINFOHEADER*) GlobalLock(hDib); if (!pbih) return FALSE; if (pbih->biBitCount!=24) { i = pbih->biBitCount; GlobalUnlock(hDib); return i<=8 ? 1 : 0; } Sht = 0; Mask = 0xFF; memset(Count, 0, sizeof (Count)); pb = (BYTE*)pbih + 40; Pad0 = (pbih->biWidth*3)%4; if (Pad0!=0) Pad0 = 4 - Pad0; for(i=pbih->biHeight; i>0; i--, pb+=Pad0) { for(j=pbih->biWidth; j>0; j--, pb+=3) { nRGB = RGB(pb[2]&Mask, pb[ 1]&Mask, pb[0]&Mask); pr = (RGBNum*)Count; for(n=0; n<NUM; n++,pr++) { if (pr->Num == 0) pr->RGB = nRGB; else if(pr->RGB!=nRGB) continue; pr->Num++; break; } if (n==NUM && Sht<3) { while(Sht < 3) { Sht++; Mask <<= 1; MaskRGB(Count,Mask); if (Count[NUM-1]. Num == 0) { j++; pb -= 3; break; } } } } } qsort(Count, NUM, sizeof(RGBNum), SortN); while(1) { for(nClr=NUM; nClr>0; nClr--) if (Count[nClr-1].Num!=0) break; if (Sht==3 || nClr<=256) { nClr = min(nClr, 256); break; } for(i=1,n=0; i<256; i++) n += Count[i].Num; for(i=256,k=0; i<nClr; ) k += Count[i++].Num; if (k*10 < k+n) { nClr = 256; break; } Sht++; Mask <<= 1; MaskRGB(Count, Mask); } Size = ((pbih->biWidth+3)/4)*4 *pbih->biHeight+40+4*nClr; if (Size > GlobalSize(hDib)) { //hDib is small picture GlobalUnlock(hDib); hMem = GlobalReAlloc(hDib, Size, GMEM_MOVEABLE); if (hMem==NULL) return 0; hDib = hMem; pbih = (BITMAPINFOHEADER*) GlobalLock(hDib); if (pbih==NULL) return 0; } pLogPal = (LOGPALETTE*)(Count + nClr); pLogPal->palNumEntries = nClr; pLogPal->palVersion = 0x300; ppe = pLogPal->palPalEntry; for(i=0; i<nClr; i++,ppe++) { nRGB = Count[i].RGB; ppe->peRed = GetRValue(nRGB); ppe->peGreen = GetGValue(nRGB); ppe->peBlue = GetBValue(nRGB); ppe->peFlags = 0; } hPal = CreatePalette(pLogPal); if (hPal == NULL) { GlobalUnlock(hDib); return 0; } Pad1 = pbih->biWidth % 4; if (Pad1!=0) Pad1 = 4-Pad1; pb1 = pb = (BYTE*)pbih + 40; for(i=0; i<pbih->biHeight; i++) { for(j=0; j<pbih->biWidth; j++) { *pb1 = GetNearestPaletteIndex (hPal, RGB(pb[2]&Mask,pb[ 1]&Mask,pb[0]&Mask)); pb += 3; pb1++; } pb += Pad0; pb1 += Pad1; } pbih->biBitCount = 8; pbih->biClrUsed = nClr; i = Size - (40+4*nClr); pbih->biSizeImage = i; pb = (BYTE*)pbih + 40; memmove(pb+4*nClr, pb, i); ppe = pLogPal->palPalEntry; for(i=0; i<nClr; i++,ppe++) { *pb++ = ppe->peBlue; *pb++ = ppe->peGreen; *pb++ = ppe->peRed; pb++; } GlobalUnlock(hDib); if (GlobalSize(hDib)>Size) { hMem = GlobalReAlloc(hDib, Size, GMEM_MOVEABLE); if (hMem) hDib = hMem; } return TRUE;} 怎么实现一个像桌面上的任务栏那样的窗体 vc中怎么屏蔽组合键? 关于CMonthCalCtrl控件的style问题 消息响应函数无法返回 VC编辑框控件变量和String类型的变量有什么不同? 有什么好办法把一个类里的数据成员一次性写得文件当中? 如何在VC中,管理和播放视频文件?? 且听风吟 "进来拿分! 怎样将"03:15:08"这样的字符串时间转化成秒? 太怪了。关于WM_SIZE.求解 关于自画光标,我想一定是个经典的简单问题 应用combo box时的文件读取?各位大侠多多帮忙
BOOL CovtRGBToPal(HANDLE& hDib); //这儿的 hDib 存放的数据结构和
bmp文件的结构一样,只是没有bmp文件的头结构BITMAPFILEINFO。我这儿
用的是API的代码(因为我是用C++Builder的)。#ifdef NUM
#undef NUM
#endif
#define NUM 0x2000struct RGBNum
{
int Num;
long RGB;
};static int SortN(const void* p1, const void* p2)
{
int i,j,Y[2];
RGBNum* pr[2];
WORD C[3]={299,587,114}; pr[0] = (RGBNum*)p1;
pr[1] = (RGBNum*)p2;
if (pr[0]->Num == pr[1]->Num) {
if (pr[0]->RGB==pr[1]->RGB)
return 0;
for(i=0; i<2; i++) {
for(j=0,Y[i]=0;j<24;j+=8)
Y[i] += C[j/8]*((BYTE)
(pr[i]->RGB>>j));
}
return Y[1] - Y[0];
}
else
return pr[1]->Num - pr[0]->Num;
}static void MaskRGB(RGBNum* Data, DWORD Mask)
{
int n;
int Size;
RGBNum *pr;
RGBNum *pr1; Mask = RGB(Mask, Mask, Mask);
for(n=0,pr=Data; n<NUM; n++) {
pr->RGB &= Mask; pr++;
} pr = Data + (NUM-1);
Size = sizeof(RGBNum);
for(n=NUM-1; n>0; n--,pr--) {
if (pr->Num==0) continue; DWORD nRGB = pr->RGB;
for(pr1=pr-1; true; ) {
if (pr1->RGB!=nRGB) {
if (pr1 == Data)
break;
pr1--; continue;
}
pr1->Num += pr->Num;
memset(pr, 0, Size);
break;
}
}
qsort(Data, NUM, sizeof(
RGBNum), SortN);
}BOOL CovtRGBToPal(HANDLE& hDib)
{
int i,j;
int k,n;
int nClr;
BYTE Sht;
BYTE *pb;
BYTE *pb1;
BYTE Mask;
BYTE Pad0;
BYTE Pad1;
DWORD nRGB;
DWORD Size;
HANDLE hMem;
RGBNum *pr;
HPALETTE hPal;
RGBNum Count[NUM];
PALETTEENTRY *ppe;
LOGPALETTE* pLogPal;
BITMAPINFOHEADER* pbih; if (!hDib) return FALSE;
pbih = (BITMAPINFOHEADER*)
GlobalLock(hDib);
if (!pbih) return FALSE;
if (pbih->biBitCount!=24) {
i = pbih->biBitCount;
GlobalUnlock(hDib);
return i<=8 ? 1 : 0;
} Sht = 0; Mask = 0xFF;
memset(Count, 0, sizeof
(Count));
pb = (BYTE*)pbih + 40;
Pad0 = (pbih->biWidth*3)%4;
if (Pad0!=0) Pad0 = 4 - Pad0;
for(i=pbih->biHeight; i>0; i--,
pb+=Pad0) {
for(j=pbih->biWidth; j>0; j--,
pb+=3) {
nRGB = RGB(pb[2]&Mask, pb[
1]&Mask, pb[0]&Mask);
pr = (RGBNum*)Count;
for(n=0; n<NUM; n++,pr++) {
if (pr->Num == 0)
pr->RGB = nRGB;
else if(pr->RGB!=nRGB)
continue;
pr->Num++; break;
}
if (n==NUM && Sht<3) {
while(Sht < 3) {
Sht++; Mask <<= 1;
MaskRGB(Count,Mask);
if (Count[NUM-1].
Num == 0) {
j++; pb -= 3;
break;
}
}
}
}
}
qsort(Count, NUM, sizeof(RGBNum),
SortN);
while(1) {
for(nClr=NUM; nClr>0; nClr--)
if (Count[nClr-1].Num!=0)
break;
if (Sht==3 || nClr<=256) {
nClr = min(nClr, 256);
break;
}
for(i=1,n=0; i<256; i++)
n += Count[i].Num;
for(i=256,k=0; i<nClr; )
k += Count[i++].Num;
if (k*10 < k+n) {
nClr = 256; break;
} Sht++; Mask <<= 1;
MaskRGB(Count, Mask);
}
Size = ((pbih->biWidth+3)/4)*4
*pbih->biHeight+40+4*nClr;
if (Size > GlobalSize(hDib)) {
//hDib is small picture
GlobalUnlock(hDib);
hMem = GlobalReAlloc(hDib,
Size, GMEM_MOVEABLE);
if (hMem==NULL) return 0; hDib = hMem;
pbih = (BITMAPINFOHEADER*)
GlobalLock(hDib);
if (pbih==NULL) return 0;
}
pLogPal = (LOGPALETTE*)(Count
+ nClr);
pLogPal->palNumEntries = nClr;
pLogPal->palVersion = 0x300;
ppe = pLogPal->palPalEntry;
for(i=0; i<nClr; i++,ppe++) {
nRGB = Count[i].RGB;
ppe->peRed = GetRValue(nRGB);
ppe->peGreen = GetGValue(nRGB);
ppe->peBlue = GetBValue(nRGB);
ppe->peFlags = 0;
}
hPal = CreatePalette(pLogPal);
if (hPal == NULL) {
GlobalUnlock(hDib); return 0;
}
Pad1 = pbih->biWidth % 4;
if (Pad1!=0) Pad1 = 4-Pad1;
pb1 = pb = (BYTE*)pbih + 40;
for(i=0; i<pbih->biHeight; i++) {
for(j=0; j<pbih->biWidth; j++) {
*pb1 = GetNearestPaletteIndex
(hPal, RGB(pb[2]&Mask,pb[
1]&Mask,pb[0]&Mask));
pb += 3; pb1++;
}
pb += Pad0; pb1 += Pad1;
}
pbih->biBitCount = 8;
pbih->biClrUsed = nClr;
i = Size - (40+4*nClr);
pbih->biSizeImage = i;
pb = (BYTE*)pbih + 40;
memmove(pb+4*nClr, pb, i);
ppe = pLogPal->palPalEntry;
for(i=0; i<nClr; i++,ppe++) {
*pb++ = ppe->peBlue;
*pb++ = ppe->peGreen;
*pb++ = ppe->peRed; pb++;
}
GlobalUnlock(hDib);
if (GlobalSize(hDib)>Size) {
hMem = GlobalReAlloc(hDib,
Size, GMEM_MOVEABLE);
if (hMem) hDib = hMem;
}
return TRUE;
}