第16章 调色板管理器_16.4 一个DIB位图库的实现(2)
//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 ( == (iNum = DibNumColors(hdib)))
return NULL;
plp = malloc(sizeof(LOGPALETTE) + (iNum - )*sizeof(PALETTEENTRY));
plp->palVersion = 0x0300;
plp->palNumEntries = iNum;
for (i = ; 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 = ;
}
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) + * sizeof(PALETTEENTRY));
plp->palVersion = 0x0300;
plp->palNumEntries = ; //下面的循环会计算31种灰度色阶,但其中3种会匹配20种系统保留颜色
for (i = , G = , incr = ; 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 = ;
incr = ((incr == ) ? : );
}
//下面的循环负责创建216种颜色,但其中8种会匹配20种系统保留颜色,另外的4种会匹配
//上面产生的灰度色阶
for (R = ; R <= 0xFF; R += 0x33)
for (G = ; G <= 0xFF; G += 0x33)
for (B = ; 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 = ;
i++;
}
hPalette = CreatePalette(plp);
free(plp);
return hPalette;
}
/*-------------------------------------------------------------------
DibPalUniformGrays:创建具有相同间隔的灰度色阶(将256分成相同的iNum份)
-------------------------------------------------------------------*/
HPALETTE DibPalUniformGrays(int iNum)
{
HPALETTE hPalette;
LOGPALETTE* plp;
int i;
if (iNum <= )
return NULL;
plp = malloc(sizeof(LOGPALETTE) + (iNum - )*sizeof(PALETTEENTRY));
plp->palVersion = 0x0300;
plp->palNumEntries = iNum;
for (i = ; i < iNum; i++)
{
plp->palPalEntry[i].peRed = //peRed =peGreen =peBlue =(i*255/(iNum-1))
plp->palPalEntry[i].peGreen =
plp->palPalEntry[i].peBlue = (BYTE)(i * / (iNum - ));
plp->palPalEntry[i].peFlags = ;
}
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) <= )
return NULL;
plp = malloc(sizeof(LOGPALETTE) + (iNum - )*sizeof(PALETTEENTRY));
plp->palVersion = 0x0300;
plp->palNumEntries = iNum; i = ;
for (R = ; R < iNumR; R++)
for (G = ; G < iNumG; G++)
for (B = ; B < iNumB; B++)
{
plp->palPalEntry[i].peRed = (BYTE)((R * / iNumR - ));
plp->palPalEntry[i].peGreen = (BYTE)((G * / iNumG - ));
plp->palPalEntry[i].peBlue = (BYTE)((B * / iNumB - ));
plp->palPalEntry[i].peFlags = ;
i++;
}
hPalette = CreatePalette(plp);
free(plp);
return hPalette;
}
/*-------------------------------------------------------------------
DibPalVga:创建一个基于标准显示器的16色调色板
-------------------------------------------------------------------*/
HPALETTE DibPalVga(void)
{
static RGBQUAD rgb[] = { 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) + ( - )*sizeof(PALETTEENTRY));
plp->palVersion = 0x0300;
plp->palNumEntries = ;
for (i = ; i < ; 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 = ;
}
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 = ; y < cy; y++)
for (x = ; x < cx; x++)
{
DibGetPixelColor(hdib, x, y, &rgb);
rgb.rgbRed >>= ( - iRes);
rgb.rgbGreen >>= ( - iRes);
rgb.rgbBlue >>= ( - 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) < )
return NULL;
if (iRes< || iRes > )
return NULL;
//分配颜色使用次数的数组2^(3*iRes)
iArraySize = << ( * iRes); // iRes为分辨率,表示通道颜色使用的位数
iMask = ( << iRes) - ;//如iRes=6时,掩码为00 11 1111
if (NULL == (piCount = calloc(iArraySize, sizeof(int))))
return NULL;
//获取每种颜色的使用次数
AccumColorCounts(hdib, piCount, iRes);
//设置调色板,最多236种
plp = malloc(sizeof(LOGPALETTE) + * sizeof(PALETTEENTRY));
plp->palVersion = 0x0300; for (iEntry = ; iEntry < ; iEntry++)
{
//piCount数组中的最大值,为防止多次被找到,使用完后,该值被置0
for (i = , iCount = ; i < iArraySize; i++)
if (piCount[i]>iCount)
{
iCount = piCount[i];
iIndex = i;
}
if (iCount == )
break;
R = (iMask& iIndex) << ( - iRes);
G = (iMask& (iIndex >> iRes)) << ( - iRes);
B = (iMask& (iIndex >> (iRes + iRes))) << ( - iRes);
plp->palPalEntry[iEntry].peRed = (BYTE)R;
plp->palPalEntry[iEntry].peGreen = (BYTE)G;
plp->palPalEntry[iEntry].peBlue = (BYTE)B;
plp->palPalEntry[iEntry].peFlags = ;
piCount[iIndex] = ; //将本轮找到的最大值置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 = ;
//遍历盒子中所有的颜色
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) << ( - iRes));
prgb->rgbGreen = (BYTE)((iG / iTotal) << ( - iRes));
prgb->rgbBlue = (BYTE)((iB / iTotal) << ( - 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 == ) //iBoxCount存放盒子里像素点的数量
return;
//如果嵌套层次等于8或盒里子只剩一个像素,则准备计算出该盒子的平均颜色
//并将该盒子里的像素点的数量存储起来
if (iLevel == || (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 = ;
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 / )
break;
//如果下一个蓝色将达到最大值,也退出(蓝色边长的查找)
if (B == mm.Bmax - )
break;;
}
//这时己经按蓝色边长等分为两个具有相同数量的像素集合
//分割盒子:第2个参数为新盒子的像素数量,第3个参数为新的蓝边的最大值和最小值
mmNew = mm;
mmNew.Bmin = mm.Bmin;
mmNew.Bmax = B; //以B为界来分割
CutBox(piCount, iCount, mmNew, iRes, iLevel + , pboxes, piEntry);
mmNew = mm;
mmNew.Bmin = B + ;
mmNew.Bmax = mm.Bmax; //以B为界来分割
CutBox(piCount, iBoxCount - iCount, mmNew, iRes, iLevel + , pboxes, piEntry);
}
//否则,如果盒子中,红色边长较长,则按该边来分成颜色数量相等的两个盒子
else if ((mm.Rmax - mm.Rmin) > (mm.Gmax - mm.Gmin))
{
//初始化计数变量iCount,并遍历红色边
iCount = ;
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 / )
break;
//如果下一个红色将达到最大值,也退出(红色边长的查找)
if (R == mm.Rmax - )
break;;
}
//这时己经按红色边长等分为两个具有相同数量的像素集合
//分割盒子:第2个参数为新盒子的像素数量,第3个参数为新的蓝边的最大值和最小值
mmNew = mm;
mmNew.Rmin = mm.Rmin;
mmNew.Rmax = R; //以R为界来分割
CutBox(piCount, iCount, mmNew, iRes, iLevel + , pboxes, piEntry);
mmNew = mm;
mmNew.Rmin = R + ;
mmNew.Rmax = mm.Rmax; //以R为界来分割
CutBox(piCount, iBoxCount - iCount, mmNew, iRes, iLevel + , pboxes, piEntry);
}
//否则,如果盒子中,绿色边长较长,则按该边来分成颜色数量相等的两个盒子
else
{
//初始化计数变量iCount,并遍历绿色边
iCount = ;
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 / )
break;
//如果下一个绿色将达到最大值,也退出(绿色边长的查找)
if (G == mm.Gmax - )
break;;
}
//这时己经按绿色边长等分为两个具有相同数量的像素集合
//分割盒子:第2个参数为新盒子的像素数量,第3个参数为新的蓝边的最大值和最小值
mmNew = mm;
mmNew.Gmin = mm.Gmin;
mmNew.Gmax = G; //以G为界来分割
CutBox(piCount, iCount, mmNew, iRes, iLevel + , pboxes, piEntry);
mmNew = mm;
mmNew.Gmin = G + ;
mmNew.Gmax = mm.Gmax; //以G为界来分割
CutBox(piCount, iBoxCount - iCount, mmNew, iRes, iLevel + , 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[];
MINMAX mm;
int* piCount;
int i, iArraySize, iDim, R, G, B, iCount, iTotal, iEntry = ;
//有效性验证
if (DibBitCount(hdib) < )
return NULL;
if (iRes< || iRes >)
return NULL;
//统计每种颜色被使用的次数
iArraySize = << ( * iRes);
if (NULL == (piCount = calloc(iArraySize, sizeof(int))))
return NULL;
AccumColorCounts(hdib, piCount, iRes);
//计算大盒子的总尺寸
iDim = << iRes; //如每像素6位,则盒子每边的长度为2^6个像素
mm.Rmax = mm.Gmax = mm.Bmax = ;
mm.Rmin = mm.Gmin = mm.Bmin = iDim - ;
iTotal = ;
//找出盒子长、宽、高(分别R、G、B)的边界范围
for (R = ; R < iDim; R++)
for (G = ; G < iDim; G++)
for (B = ; B < iDim; B++)
{
iCount = piCount[PACK_RGB(R, G, B, iRes)];
if (iCount>) //如果颜色使用次数>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, , boxes, &iEntry);
free(piCount);
//按RGB颜色被使用的次数,降序排序boxes数组
qsort(boxes, iEntry, sizeof(BOXES), Compare);
plp = malloc(sizeof(LOGPALETTE) + (iEntry - )*sizeof(PALETTEENTRY));
plp->palVersion = 0x0300;
plp->palNumEntries = iEntry;
for (i = ; 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 = ;
}
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位以下的带有颜色表
{
cColors = DibNumColors(hdibSrc);
hdibDst = DibCreate(cx, cy, iBitCountDst, cColors);
//设置颜色表
for (i = ; i < cColors; i++)
{
DibGetColor(hdibSrc, i, &rgb);
DibSetColor(hdibDst, i, &rgb);
}
//设置像素颜色
for (x = ; x < cx; x++)
for (y = ; y < cy; y++)
{
DibSetPixel(hdibDst, x, y, DibGetPixel(hdibSrc, x, y));
}
}
//目标没有颜色表(如16、24、32位)
else if (iBitCountDst >= )
{
hdibDst = DibCreate(cx, cy, iBitCountDst, );
//设置像素颜色
for (x = ; x < cx; x++)
for (y = ; y < cy; y++)
{
DibGetPixelColor(hdibSrc, x, y, &rgb);
DibSetPixelColor(hdibDst, x, y, &rgb);
}
}
//源没有颜色表的DIB(如16、24,32),而目标有颜色表
else if (iBitCountSrc >= && iBitCountDst == ) //目标是8位的
{
hPalette = DibPalMedianCut(hdibSrc, );
GetObject(hPalette, sizeof(WORD), &wNumEntries);
hdibDst = DibCreate(cx, cy, , (int)wNumEntries);
//设置颜色表
for (i = ; i < (int)wNumEntries; i++)
{
GetPaletteEntries(hPalette, i, , &pe);
rgb.rgbRed = pe.peRed;
rgb.rgbGreen = pe.peGreen;
rgb.rgbBlue = pe.peBlue;
rgb.rgbReserved = ;
DibSetColor(hdibDst, i, &rgb);
}
//设置像素数据
for (x = ; x < cx; x++)
for (y = ; 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 == )
{
hdibDst = DibCreate(cx, cy, , );
hPalette = DibPalUniformGrays();
//颜色表
for (i = ; i < ; i++)
{
GetPaletteEntries(hPalette, i, , &pe);
rgb.rgbRed = pe.peRed;
rgb.rgbGreen = pe.peGreen;
rgb.rgbBlue = pe.peBlue;
rgb.rgbReserved = ;
DibSetColor(hdibDst, i, &rgb);
}
//设置像素数据
for (x = ; x < cx; x++)
for (y = ; 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 >= && iBitCountDst == )
{
hdibDst = DibCreate(cx, cy, , );
hPalette = DibPalVga();
//颜色表
for (i = ; i < ; i++)
{
GetPaletteEntries(hPalette, i, , &pe);
rgb.rgbRed = pe.peRed;
rgb.rgbGreen = pe.peGreen;
rgb.rgbBlue = pe.peBlue;
rgb.rgbReserved = ;
DibSetColor(hdibDst, i, &rgb);
}
//设置像素数据
for (x = ; x < cx; x++)
for (y = ; 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;
}
第16章 调色板管理器_16.4 一个DIB位图库的实现(2)的更多相关文章
- 第16章 调色板管理器_16.4 一个DIB位图库的实现(1)
16.4.1自定义的 DIBSTRUCT结构体 字段 含义 PBYTE *ppRow ①指向位图视觉上最上面的一行像素.(不管是自下而上,还是自上而下) ②放在第一个字段,为的是后面定义宏时可方便访问 ...
- 第15章 上下文管理器和else块
#<流流畅的Python>第15章 上下文管理器和else块 #15.1 先做这个,再做那个:if语句之外的else块 #else子句不仅能在if语句中使用,还能在for.while和tr ...
- 【Ubuntu 16】显示管理器lightdm
lightdm是一个全新的轻量级的显示管理器,在Ubuntu16.04上面已经使用. 从图形界面进入到命令行界面 systemctl disable lightdm.service 从命令行进入到图形 ...
- 流畅的python第十五章上下文管理器和else块学习记录
with 语句和上下文管理器for.while 和 try 语句的 else 子句 with 语句会设置一个临时的上下文,交给上下文管理器对象控制,并且负责清理上下文.这么做能避免错误并减少样板代码, ...
- 第4章 URL管理器和实现方法
URL管理器:管理待抓取URL集合和已抓取URL集合 -- 防止重复抓取.防止循环抓取 URL需要支持哪些功能: 添加新URL到待爬取集合中.判断待添加URL是否在容器中,判断是否还有待爬取URL,获 ...
- 转:OGRE场景管理器介绍
一个场景代表在虚拟世界中显示的物品.场景可以包括静态几何体(比如地形或者室内),模型(比如树.椅子等),光和摄像机.场景有下面种类.室内场景:可能由走廊.有家具的屋子和挂着装饰品的墙组成.室外场景:可 ...
- 【java】浅析java组件中的布局管理器
这篇博文笔者介绍一下java组件中,常用的布局管理器.java组件中的布局方式有好几十种,所有的这些布局管理器都实现了java.awt.LayoutManager接口.接下来笔者介绍一下常用的5种布局 ...
- yum 软件管理器
yum软件管理器 yum是一个强大的软件包管理器,能够自动解决安装时rpm包之间的依赖关系. 一.使用yum管理软件包 1.使用命令 yum help 查看使用方法 [root@majinhai ~] ...
- [Qt Creator 快速入门] 第4章 布局管理
第3章讲述了一些窗口部件,当时往界面上拖放部件时都是随意放置的,这对于学习部件的使用没有太大的影响,但是,对于一个完善的软件,布局管理却是必不可少的. 无论是想要界面中部件有一个很整齐的排列,还是想要 ...
随机推荐
- 【web前端面试题整理04】阿里一行之大神面对面
前言 这段时间我在河南一家公司当了一段时间的前端主管,最后可耻的匿了,原因各种各样,最主要的就是不想呆在郑州了. 其实这里的同事还是很不错的,面对老总最后的挽留我不是没有动心,而是这个地方确实不太好, ...
- CSS选择符详解
一.类型选择符 什么是类型选择符?指以网页中已有的标签类型作为名称的行径符.body是网页中的一个标签类型,div,p,span都是. 如下: body {} div {} p {} span {} ...
- URL 路径长度限制(错误:指定的文件或文件夹名称太长)
本节讨论 URL 的构成.SharePoint 2010 构建 URL 的方式.URL 的编码和加长以及作为其他 URL 中的参数传递的方式. SharePoint URL 的构成 SharePoin ...
- 为什么relativelayout.layoutParams的width为-1
源码里看下就知道了.. -1不代表宽度,代表MATCH_PARENT常量的值public static final int FILL_PARENT = -1; public static final ...
- 拓展:使用终端创建、编译、链接OC…
本文介绍一下如何使用Mac OS X自带终端快速创建.编译.链接OC程序. 1.打开终端 顺序:打开Finder——应用程序——实用工具——终端 2.打开需要存放 .m 文件的路径(比如我需要放到桌面 ...
- ios 颜色转图片
- (UIImage *)imageWithColor:(UIColor*) color{ CGRect rect=CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); ...
- 深入.net(继承)
继承.多态,学习目标: 1.能够熟记定义和概念 2.能够理解其内部意义 3.能够运用到自己的编码实现中 如何进行代码的复用: ----- 自己写好了一段代码,理想状态(永远都不要再写了,直接用) -- ...
- iOS学习19之OC类的扩展
为一个类扩展功能:1.子类化:2.修改源代码:3.定义协议:4.Category:类目 1.Category 1> Category的作用 Category:也叫分类,类目,是为没有源代码的类扩 ...
- 单例模式-用GCD实现
用GCD实现单例模式的步骤: 步骤1. 创建头文件 XZSingleton.h,里面代码如下: // .h文件 #define XZSingletonH(name) + (instancetype)s ...
- 深入理解Objective-C Runtime
一.简介 主要特点: 在OC语言中,函数的调用是属于动态调用的,编译阶段并不确定要调用的函数,在真正的运行时才会根据函数名查找要调用哪个函数. 而在C语言中,函数的调用是在编译阶段就已经确定要调用哪个 ...