//DibPal.h
/*----------------------------------------------------------------- DIBPAL.H header file for DIBPAL.C -----------------------------------------------------------------*/ #pragma once; #include <windows.h> #include "DibHelp.h" HPALETTE DibPalDibTable(HDIB hdib); HPALETTE DibPalAllPurpose(void); HPALETTE DibPalUniformGrays(int iNum); HPALETTE DibPalUniformColors(int iNumR, int iNumG, int iNumB); HPALETTE DibPalVga(void); HPALETTE DibPalPopularity(HDIB hdib, int iRes); HPALETTE DibPalMedianCut(HDIB hdib, int iRes);
//DibPal.c
#include "DibPal.h" /*------------------------------------------------------------------- DibPalDibTable:根据DIB颜色表创建一个调色板 -------------------------------------------------------------------*/ HPALETTE DibPalDibTable(HDIB hdib) { HPALETTE hPalette; LOGPALETTE* plp; RGBQUAD rgb; int i, iNum; if (0 == (iNum = DibNumColors(hdib))) return NULL; plp = malloc(sizeof(LOGPALETTE) + (iNum - 1)*sizeof(PALETTEENTRY)); plp->palVersion = 0x0300; plp->palNumEntries = iNum; for (i = 0; i < iNum; i++) { DibGetColor(hdib, i, &rgb); plp->palPalEntry[i].peRed = rgb.rgbRed; plp->palPalEntry[i].peGreen = rgb.rgbGreen; plp->palPalEntry[i].peBlue = rgb.rgbBlue; plp->palPalEntry[i].peFlags = 0; } hPalette = CreatePalette(plp); free(plp); return hPalette; } /*------------------------------------------------------------------- DibPalAllPurpose:创建一个通用的调色板,共有247种颜色,但15种是从20种 系统保留颜色中复制或匹配出来的。 -------------------------------------------------------------------*/ HPALETTE DibPalAllPurpose(void) { HPALETTE hPalette; LOGPALETTE* plp; int i, incr, R, G, B; plp = malloc(sizeof(LOGPALETTE) + 246 * sizeof(PALETTEENTRY)); plp->palVersion = 0x0300; plp->palNumEntries = 247; //下面的循环会计算31种灰度色阶,但其中3种会匹配20种系统保留颜色 for (i = 0, G = 0, incr = 8; G <= 0xFF; i++, G += incr) { plp->palPalEntry[i].peRed = (BYTE)G; plp->palPalEntry[i].peGreen = (BYTE)G; plp->palPalEntry[i].peBlue = (BYTE)G; plp->palPalEntry[i].peFlags = 0; incr = ((incr == 9) ? 8 : 9); } //下面的循环负责创建216种颜色,但其中8种会匹配20种系统保留颜色,另外的4种会匹配 //上面产生的灰度色阶 for (R = 0; R <= 0xFF; R += 0x33) for (G = 0; G <= 0xFF; G += 0x33) for (B = 0; B <= 0xFF; B += 0x33) { plp->palPalEntry[i].peRed = (BYTE)R; //i从31开始 plp->palPalEntry[i].peGreen = (BYTE)G; plp->palPalEntry[i].peBlue = (BYTE)B; plp->palPalEntry[i].peFlags = 0; i++; } hPalette = CreatePalette(plp); free(plp); return hPalette; } /*------------------------------------------------------------------- DibPalUniformGrays:创建具有相同间隔的灰度色阶(将256分成相同的iNum份) -------------------------------------------------------------------*/ HPALETTE DibPalUniformGrays(int iNum) { HPALETTE hPalette; LOGPALETTE* plp; int i; if (iNum <= 0) return NULL; plp = malloc(sizeof(LOGPALETTE) + (iNum - 1)*sizeof(PALETTEENTRY)); plp->palVersion = 0x0300; plp->palNumEntries = iNum; for (i = 0; i < iNum; i++) { plp->palPalEntry[i].peRed = //peRed =peGreen =peBlue =(i*255/(iNum-1)) plp->palPalEntry[i].peGreen = plp->palPalEntry[i].peBlue = (BYTE)(i * 255 / (iNum - 1)); plp->palPalEntry[i].peFlags = 0; } hPalette = CreatePalette(plp); free(plp); return hPalette; } /*------------------------------------------------------------------- DibPalUniformColors:创建iNumR*iNumG*iNumB调色板 -------------------------------------------------------------------*/ HPALETTE DibPalUniformColors(int iNumR, int iNumG, int iNumB) { HPALETTE hPalette; LOGPALETTE* plp; int i, iNum, R, G, B; if ((iNum = iNumR*iNumG*iNumB) <= 0) return NULL; plp = malloc(sizeof(LOGPALETTE) + (iNum - 1)*sizeof(PALETTEENTRY)); plp->palVersion = 0x0300; plp->palNumEntries = iNum; i = 0; for (R = 0; R < iNumR; R++) for (G = 0; G < iNumG; G++) for (B = 0; B < iNumB; B++) { plp->palPalEntry[i].peRed = (BYTE)((R * 255 / iNumR - 1)); plp->palPalEntry[i].peGreen = (BYTE)((G * 255 / iNumG - 1)); plp->palPalEntry[i].peBlue = (BYTE)((B * 255 / iNumB - 1)); plp->palPalEntry[i].peFlags = 0; i++; } hPalette = CreatePalette(plp); free(plp); return hPalette; } /*------------------------------------------------------------------- DibPalVga:创建一个基于标准显示器的16色调色板 -------------------------------------------------------------------*/ HPALETTE DibPalVga(void) { static RGBQUAD rgb[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00 }; HPALETTE hPalette; LOGPALETTE* plp; int i; plp = malloc(sizeof(LOGPALETTE) + (16 - 1)*sizeof(PALETTEENTRY)); plp->palVersion = 0x0300; plp->palNumEntries = 16; for (i = 0; i < 16; i++) { plp->palPalEntry[i].peRed = rgb[i].rgbRed; plp->palPalEntry[i].peGreen = rgb[i].rgbGreen; plp->palPalEntry[i].peBlue = rgb[i].rgbBlue; plp->palPalEntry[i].peFlags = 0; } hPalette = CreatePalette(plp); free(plp); return hPalette; } /*------------------------------------------------------------------- 优化调色板使用到的宏 -------------------------------------------------------------------*/ #define PACK_RGB(R,G,B,iRes) ((int)(R) | ((int)(G)<<(iRes)) | ((int)(B) <<((iRes)+(iRes)))) /*------------------------------------------------------------------- AccumColorCounts:填充piCount参数,该参数是一个数组,里面存放每种 颜色被使用的次数 -------------------------------------------------------------------*/ static void AccumColorCounts(HDIB hdib, int* piCount, int iRes) { int x, y, cx, cy, tmp; RGBQUAD rgb; cx = DibWidth(hdib); cy = DibHeight(hdib); for (y = 0; y < cy; y++) for (x = 0; x < cx; x++) { DibGetPixelColor(hdib, x, y, &rgb); rgb.rgbRed >>= (8 - iRes); rgb.rgbGreen >>= (8 - iRes); rgb.rgbBlue >>= (8 - iRes); //每种颜色的使用次数存放在以颜色值为下标的数组元素中 tmp = PACK_RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, iRes); ++piCount[PACK_RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, iRes)]; } } /*------------------------------------------------------------------- DibPalPopularity:流行度算法 1、选取最多256种RGB色值构成调色板 2、使用RGB色值权重最高的几位,如8位或24位,这里选择6位(很多显示设备 的解析度只有6,这样可以大大减少内存消耗。 -------------------------------------------------------------------*/ HPALETTE DibPalPopularity(HDIB hdib, int iRes) { HPALETTE hPalette; int i, iArraySize, iMask, iEntry, iCount, iIndex, R, G, B; int *piCount; //数组,存放每种颜色使用的次数 LOGPALETTE* plp; //有效性检查 if (DibBitCount(hdib) < 16) return NULL; if (iRes<3 || iRes > 8) return NULL; //分配颜色使用次数的数组2^(3*iRes) iArraySize = 1 << (3 * iRes); // iRes为分辨率,表示通道颜色使用的位数 iMask = (1 << iRes) - 1;//如iRes=6时,掩码为00 11 1111 if (NULL == (piCount = calloc(iArraySize, sizeof(int)))) return NULL; //获取每种颜色的使用次数 AccumColorCounts(hdib, piCount, iRes); //设置调色板,最多236种 plp = malloc(sizeof(LOGPALETTE) + 235 * sizeof(PALETTEENTRY)); plp->palVersion = 0x0300; for (iEntry = 0; iEntry < 236; iEntry++) { //piCount数组中的最大值,为防止多次被找到,使用完后,该值被置0 for (i = 0, iCount = 0; i < iArraySize; i++) if (piCount[i]>iCount) { iCount = piCount[i]; iIndex = i; } if (iCount == 0) break; R = (iMask& iIndex) << (8 - iRes); G = (iMask& (iIndex >> iRes)) << (8 - iRes); B = (iMask& (iIndex >> (iRes + iRes))) << (8 - iRes); plp->palPalEntry[iEntry].peRed = (BYTE)R; plp->palPalEntry[iEntry].peGreen = (BYTE)G; plp->palPalEntry[iEntry].peBlue = (BYTE)B; plp->palPalEntry[iEntry].peFlags = 0; piCount[iIndex] = 0; //将本轮找到的最大值置0,防止多次被找到 } //当结束循环后iEntry保存的是实际被存储的颜色的数量、 plp->palNumEntries = iEntry; //创建调色板,返回调色板句柄,并清除内存 hPalette = CreatePalette(plp); free(plp); free(piCount); return hPalette; } /*------------------------------------------------------------------- 中分算法用到的数据结构 -------------------------------------------------------------------*/ typedef struct //定义一个盒子的尺寸 { int Rmin, Rmax, Gmin, Gmax, Bmin, Bmax; }MINMAX; typedef struct //为快速排序使用的 { int iBoxCount; //盒子里面的点的数量 RGBQUAD rgbBoxAv; //盒子内的平均颜色 }BOXES; /*------------------------------------------------------------------- FindAverageColor:找到一个盒子里的平均颜色,返回值为盒子里所有点被使 用的次数总和,即盒子里像素点的总数量 -------------------------------------------------------------------*/ static int FindAverageColor(int *piCount, MINMAX mm, int iRes, RGBQUAD* prgb) { int R, G, B, iCount, iR, iG, iB, iTotal; iTotal = iR = iG = iB = 0; //遍历盒子中所有的颜色 for (R = mm.Rmin; R <= mm.Rmax; R++) for (G = mm.Gmin; G <= mm.Gmax; G++) for (B = mm.Bmin; B <= mm.Bmax; B++) { //获取某一颜色被使用的次数 iCount = piCount[PACK_RGB(R, G, B, iRes)]; //根据颜色值,算出各分量的加权和 iR += iCount*R; iG += iCount*G; iB += iCount*B; iTotal += iCount; } //计算出平均颜色 prgb->rgbRed = (BYTE)((iR / iTotal) << (8 - iRes)); prgb->rgbGreen = (BYTE)((iG / iTotal) << (8 - iRes)); prgb->rgbBlue = (BYTE)((iB / iTotal) << (8 - iRes)); //返回盒子里像素点的数量 return iTotal; } /*------------------------------------------------------------------- CutBox:将一个盒子分隔成两个 1、piCount:为所有像素点的被使用次数,是个数组。是个指针会被所有递归共用 2、mm为当前盒子的边界 3、iRes为颜色分辩率,会被所有递归共用 4、iLevel为嵌套层次 5、pBoxes为盒子的总数量(如256个),会被所有递归共用 6、piEntry为当前要分割的盒子索引,会被所有递归共用 -------------------------------------------------------------------*/ static void CutBox(int* piCount, int iBoxCount, MINMAX mm, int iRes, int iLevel, BOXES* pboxes, int * piEntry) { int iCount, R, G, B; MINMAX mmNew; //如果盒子里的没有像素点,则无需分隔,直接退出 if (iBoxCount == 0) //iBoxCount存放盒子里像素点的数量 return; //如果嵌套层次等于8或盒里子只剩一个像素,则准备计算出该盒子的平均颜色 //并将该盒子里的像素点的数量存储起来 if (iLevel == 8 || (mm.Rmin == mm.Rmax && mm.Gmin == mm.Gmax && mm.Bmin == mm.Bmax)) { pboxes[*piEntry].iBoxCount = FindAverageColor(piCount, mm, iRes, &pboxes[*piEntry].rgbBoxAv); (*piEntry)++; } //否则,如果盒子中,蓝色边长较长,则按该边来分成颜色数量相等的两个盒子 else if ((mm.Bmax - mm.Bmin) > (mm.Rmax - mm.Rmin) && (mm.Bmax - mm.Bmin) >(mm.Gmax - mm.Gmin)) { //初始化计数变量iCount,并遍历蓝色边 iCount = 0; for (B = mm.Bmin; B < mm.Bmax; B++) //注意这里不取到最大值 { for (R = mm.Rmin; R <= mm.Rmax; R++) for (G = mm.Gmin; G <= mm.Gmax; G++) iCount += piCount[PACK_RGB(R, G, B, iRes)]; //将使用次数相加(即己经找到的像素数量) //如果己经找到的像素数量超过一半,则退出蓝色边长的查找 if (iCount >= iBoxCount / 2) break; //如果下一个蓝色将达到最大值,也退出(蓝色边长的查找) if (B == mm.Bmax - 1) break;; } //这时己经按蓝色边长等分为两个具有相同数量的像素集合 //分割盒子:第2个参数为新盒子的像素数量,第3个参数为新的蓝边的最大值和最小值 mmNew = mm; mmNew.Bmin = mm.Bmin; mmNew.Bmax = B; //以B为界来分割 CutBox(piCount, iCount, mmNew, iRes, iLevel + 1, pboxes, piEntry); mmNew = mm; mmNew.Bmin = B + 1; mmNew.Bmax = mm.Bmax; //以B为界来分割 CutBox(piCount, iBoxCount - iCount, mmNew, iRes, iLevel + 1, pboxes, piEntry); } //否则,如果盒子中,红色边长较长,则按该边来分成颜色数量相等的两个盒子 else if ((mm.Rmax - mm.Rmin) > (mm.Gmax - mm.Gmin)) { //初始化计数变量iCount,并遍历红色边 iCount = 0; for (R = mm.Rmin; R < mm.Rmax; R++) { for (G = mm.Gmin; G <= mm.Gmax; G++) for (B = mm.Bmin; B <= mm.Bmax; B++) iCount += piCount[PACK_RGB(R, G, B, iRes)]; //将使用次数相加(即己经找到的像素数量) //如果己经找到的像素数量超过一半,则退出红色边长的查找 if (iCount >= iBoxCount / 2) break; //如果下一个红色将达到最大值,也退出(红色边长的查找) if (R == mm.Rmax - 1) break;; } //这时己经按红色边长等分为两个具有相同数量的像素集合 //分割盒子:第2个参数为新盒子的像素数量,第3个参数为新的蓝边的最大值和最小值 mmNew = mm; mmNew.Rmin = mm.Rmin; mmNew.Rmax = R; //以R为界来分割 CutBox(piCount, iCount, mmNew, iRes, iLevel + 1, pboxes, piEntry); mmNew = mm; mmNew.Rmin = R + 1; mmNew.Rmax = mm.Rmax; //以R为界来分割 CutBox(piCount, iBoxCount - iCount, mmNew, iRes, iLevel + 1, pboxes, piEntry); } //否则,如果盒子中,绿色边长较长,则按该边来分成颜色数量相等的两个盒子 else { //初始化计数变量iCount,并遍历绿色边 iCount = 0; for (G = mm.Gmin; G < mm.Gmax; G++) { for (R = mm.Rmin; R <= mm.Rmax; R++) for (B = mm.Bmin; B <= mm.Bmax; B++) iCount += piCount[PACK_RGB(R, G, B, iRes)]; //将使用次数相加(即己经找到的像素数量) //如果己经找到的像素数量超过一半,则退出绿色边长的查找 if (iCount >= iBoxCount / 2) break; //如果下一个绿色将达到最大值,也退出(绿色边长的查找) if (G == mm.Gmax - 1) break;; } //这时己经按绿色边长等分为两个具有相同数量的像素集合 //分割盒子:第2个参数为新盒子的像素数量,第3个参数为新的蓝边的最大值和最小值 mmNew = mm; mmNew.Gmin = mm.Gmin; mmNew.Gmax = G; //以G为界来分割 CutBox(piCount, iCount, mmNew, iRes, iLevel + 1, pboxes, piEntry); mmNew = mm; mmNew.Gmin = G + 1; mmNew.Gmax = mm.Gmax; //以G为界来分割 CutBox(piCount, iBoxCount - iCount, mmNew, iRes, iLevel + 1, pboxes, piEntry); } } /*------------------------------------------------------------------- Compare:提供给快速排序作比较函数 -------------------------------------------------------------------*/ static int Compare(const BOXES* pbox1, const BOXES* pbox2) { return pbox1->iBoxCount > pbox2->iBoxCount; } /*------------------------------------------------------------------- DibPalMedianCut:基于中分算法创建一个调色板 -------------------------------------------------------------------*/ HPALETTE DibPalMedianCut(HDIB hdib, int iRes) { HPALETTE hPalette; LOGPALETTE* plp; BOXES boxes[256]; MINMAX mm; int* piCount; int i, iArraySize, iDim, R, G, B, iCount, iTotal, iEntry = 0; //有效性验证 if (DibBitCount(hdib) < 16) return NULL; if (iRes<3 || iRes >8) return NULL; //统计每种颜色被使用的次数 iArraySize = 1 << (3 * iRes); if (NULL == (piCount = calloc(iArraySize, sizeof(int)))) return NULL; AccumColorCounts(hdib, piCount, iRes); //计算大盒子的总尺寸 iDim = 1 << iRes; //如每像素6位,则盒子每边的长度为2^6个像素 mm.Rmax = mm.Gmax = mm.Bmax = 0; mm.Rmin = mm.Gmin = mm.Bmin = iDim - 1; iTotal = 0; //找出盒子长、宽、高(分别R、G、B)的边界范围 for (R = 0; R < iDim; R++) for (G = 0; G < iDim; G++) for (B = 0; B < iDim; B++) { iCount = piCount[PACK_RGB(R, G, B, iRes)]; if (iCount>0) //如果颜色使用次数>0,表示该颜色是要用到的,否则是不用的颜色 { iTotal += iCount; //找到各分量的最小值 if (R < mm.Rmin) mm.Rmin = R; if (G < mm.Gmin) mm.Gmin = G; if (B < mm.Bmin) mm.Bmin = B; //找到各分量的最大值 if (R > mm.Rmax) mm.Rmax = R; if (G > mm.Gmax) mm.Gmax = G; if (B > mm.Bmax) mm.Bmax = B; } } //分割第一个盒子(递归函数)。当返回时boxes结构将有256种RGB值,每个盒子一种。 //像素数量被记录在每个盒子的iBoxCount字段中,平均颜色存在rgbBoxAv中。 //iEntry表示所有非空盒子的数量 CutBox(piCount, iTotal, mm, iRes, 0, boxes, &iEntry); free(piCount); //按RGB颜色被使用的次数,降序排序boxes数组 qsort(boxes, iEntry, sizeof(BOXES), Compare); plp = malloc(sizeof(LOGPALETTE) + (iEntry - 1)*sizeof(PALETTEENTRY)); plp->palVersion = 0x0300; plp->palNumEntries = iEntry; for (i = 0; i < iEntry; i++) { plp->palPalEntry[i].peRed = boxes[i].rgbBoxAv.rgbRed; plp->palPalEntry[i].peGreen = boxes[i].rgbBoxAv.rgbGreen; plp->palPalEntry[i].peBlue = boxes[i].rgbBoxAv.rgbBlue; plp->palPalEntry[i].peFlags = 0; } hPalette = CreatePalette(plp); free(plp); return hPalette; }
//DibConv.h
/*------------------------------------- DIBCONV.H header file for DIBCONV.C -------------------------------------*/ #pragma once #include "DibHelp.h" HDIB DibConvert(HDIB hdibSrc, int iBitCountDst);
//DibConv.c
/*-------------------------------------------------------------- DIBCONV.C -- Converts DIBs from one format to another (c) Charles Petzold,1998 --------------------------------------------------------------*/ #include <windows.h> #include "DibConv.h" #include "DibPal.h" HDIB DibConvert(HDIB hdibSrc, int iBitCountDst) { HDIB hdibDst = NULL; int i, x, y, cx, cy, iBitCountSrc, cColors; RGBQUAD rgb; HPALETTE hPalette; PALETTEENTRY pe; WORD wNumEntries; cx = DibWidth(hdibSrc); cy = DibHeight(hdibSrc); iBitCountSrc = DibBitCount(hdibSrc); if (iBitCountSrc == iBitCountDst) return NULL; //带有颜色表的DIB转换为更大颜色表的DIB //如1位DIB转为4位或8位DIB,或4位DIB转为8位DIB,需要复制像素点阵和颜色表 if ((iBitCountSrc < iBitCountDst) && (iBitCountDst <= 8)) //8位以下的带有颜色表 { cColors = DibNumColors(hdibSrc); hdibDst = DibCreate(cx, cy, iBitCountDst, cColors); //设置颜色表 for (i = 0; i < cColors; i++) { DibGetColor(hdibSrc, i, &rgb); DibSetColor(hdibDst, i, &rgb); } //设置像素颜色 for (x = 0; x < cx; x++) for (y = 0; y < cy; y++) { DibSetPixel(hdibDst, x, y, DibGetPixel(hdibSrc, x, y)); } } //目标没有颜色表(如16、24、32位) else if (iBitCountDst >= 16) { hdibDst = DibCreate(cx, cy, iBitCountDst, 0); //设置像素颜色 for (x = 0; x < cx; x++) for (y = 0; y < cy; y++) { DibGetPixelColor(hdibSrc, x, y, &rgb); DibSetPixelColor(hdibDst, x, y, &rgb); } } //源没有颜色表的DIB(如16、24,32),而目标有颜色表 else if (iBitCountSrc >= 16 && iBitCountDst == 8) //目标是8位的 { hPalette = DibPalMedianCut(hdibSrc, 6); GetObject(hPalette, sizeof(WORD), &wNumEntries); hdibDst = DibCreate(cx, cy, 8, (int)wNumEntries); //设置颜色表 for (i = 0; i < (int)wNumEntries; i++) { GetPaletteEntries(hPalette, i, 1, &pe); rgb.rgbRed = pe.peRed; rgb.rgbGreen = pe.peGreen; rgb.rgbBlue = pe.peBlue; rgb.rgbReserved = 0; DibSetColor(hdibDst, i, &rgb); } //设置像素数据 for (x = 0; x < cx; x++) for (y = 0; y < cy; y++) { DibGetPixelColor(hdibSrc, x, y, &rgb); DibSetPixel(hdibDst, x, y, GetNearestPaletteIndex(hPalette, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue))); } DeleteObject(hPalette); } //目标是单色的DIB else if (iBitCountDst == 1) { hdibDst = DibCreate(cx, cy, 1, 0); hPalette = DibPalUniformGrays(2); //颜色表 for (i = 0; i < 2; i++) { GetPaletteEntries(hPalette, i, 1, &pe); rgb.rgbRed = pe.peRed; rgb.rgbGreen = pe.peGreen; rgb.rgbBlue = pe.peBlue; rgb.rgbReserved = 0; DibSetColor(hdibDst, i, &rgb); } //设置像素数据 for (x = 0; x < cx; x++) for (y = 0; y < cy; y++) { DibGetPixelColor(hdibSrc, x, y, &rgb); DibSetPixel(hdibDst, x, y, GetNearestPaletteIndex(hPalette, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue))); } DeleteObject(hPalette); } //从8位或更高位的DIB,转为4位DIB else if (iBitCountSrc >= 8 && iBitCountDst == 4) { hdibDst = DibCreate(cx, cy, 4, 0); hPalette = DibPalVga(); //颜色表 for (i = 0; i < 16; i++) { GetPaletteEntries(hPalette, i, 1, &pe); rgb.rgbRed = pe.peRed; rgb.rgbGreen = pe.peGreen; rgb.rgbBlue = pe.peBlue; rgb.rgbReserved = 0; DibSetColor(hdibDst, i, &rgb); } //设置像素数据 for (x = 0; x < cx; x++) for (y = 0; y < cy; y++) { DibGetPixelColor(hdibSrc, x, y, &rgb); DibSetPixel(hdibDst, x, y, GetNearestPaletteIndex(hPalette, RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue))); } DeleteObject(hPalette); } else hdibDst = NULL; return hdibDst; }