第8章 カラー・ディザリング 【リスト8-1】 8色を表示するプログラム #include "myWin.h" #include "math.h" #define XST 420 #define YST 10 #define GWIDTH 400 #define GHIGHT 400 #define RED(X) (X & 0xFF) #define GREEN(X) ((X>>8) & 0xFF) #define BLUE(X) ((X>>16) & 0xFF) static HBITMAP hBM[2];static HDC hBuff[2]; static BITMAP bM[2]; void clearBitmap(int i){//ビットマップのクリア SelectObject(hBuff[i], GetStockObject(NULL_PEN)); PatBlt(hBuff[i], 0,0,GWIDTH,GHIGHT,WHITENESS);//黒塗り } void createBitmap(HWND hw){//ビットマップの設定 HDC hdc=GetDC(hw); for(int i=0;i<2;i++){ hBM[i]=CreateCompatibleBitmap(hdc,GWIDTH,GHIGHT); hBuff[i]=CreateCompatibleDC(hdc); SelectObject(hBuff[i], hBM[i]); clearBitmap(i); } } int pixel(int i, int j){//画像1からピクセルを取り出す return GetPixel(hBuff[1], i,j); } void setPixel(int i, int j, COLORREF C){//画像0にピクセルを設定する SetPixel(hBuff[0], i,j, C); } void drawColor1(){ int ist=0, size=40; for(int r=0;r<=1;r++)for(int g=0;g<=1;g++)for(int b=0;b<=1;b++){ int C=RGB(r*255, g*255, b*255); for(int i=0;i=DM[x][y])? 0xFF: 0; } void drawColor2D(int yst){ double DM[NDITHX][NDITHY]; int M[NDITHX][NDITHY]={{0,3},{2,1}}; setDitherMat(M, DM, 255); int ist=0,jst=0, size=24; for(int r=0;r<4;r++){ for(int g=0;g<4;g++) for(int b=0;b<4;b++){ int R=BPP(r,4), G=BPP(g, 4), B=BPP(b,4); int RR, GG, BB; for(int i=0;i=DM[x][y])? 0xFF: 0; } void drawColor256(int yst){ int ist=0,jst=0, size=12; for(int r=0;r<8;r++){ for(int g=0;g<8;g++) for(int b=0;b<4;b++){ int C=RGB(BPP(r,8),BPP(g,8),BPP(b,4)); for(int i=0;i=DM[x][y])? MAX: MIN; } 【リスト8-7】 8色による64色ディザリング(2×2ディザ行列) #define NDITHX 2 #define NDITHY 2 void setDitherMat(int M[][NDITHY], double DM[][NDITHY], int CMAX){ double NM=1.0+(double)(NDITHX*NDITHY), DV = CMAX; for(int i=0;i=DM[x][y])? MAX: MIN; } void color64D(){ double DM[NDITHX][NDITHY]; int M[NDITHX][NDITHY]={{0,3},{2,1}}; setDitherMat(M, DM, 255); int C, R, G, B, RR, GG, BB, D=256/4,DX=255/3; for(int j=0;j=0 && ii=0 && jj255)?255:((R<0)?0:R); G=(green[i][j]/DG)*XG; G=(G>255)?255:((G<0)?0:G); B=(blue [i][j]/DB)*XB; B=(B>255)?255:((B<0)?0:B); setPixel(i,j,RGB(R,G,B)); defusionError(i,j, red[i][j]-R, green[i][j]-G, blue[i][j]-B, Mat, TT); } } 【リスト8-11】 Floyd-Steinberg dithering void Floyd_Steinberg(){ int Mat[][5]={ // C言語での表記法で {0, 0, 0, 7, 0}, // 分かりやすくするため {0, 3, 5, 1, 0}, // XYの添え字を逆転 {0, 0, 0, 0, 0} // しているので注意 }; defusionProc(Mat); } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ Floyd_Steinberg(); InvalidateRect(hw,NULL,TRUE); } 【リスト8-12】 Floyd-Steinberg dithering以外の手法 void False_Floyd_Steinberg(){//いわゆる False Floyd-Steinberg dithering int Mat[][5]={ {0, 0, 0, 3, 0}, {0, 0, 3, 2, 0}, {0, 0, 0, 0, 0} }; defusionProc(Mat); } void JJN_Algolism(){// Jarvis, Judice, and Ninke dithering int Mat[][5]={ {0, 0, 0, 7, 5}, {3, 5, 7, 5, 3}, {1, 3, 5, 3, 1} }; defusionProc(Mat); } void Stucki(){ int Mat[][5]={ {0, 0, 0, 8, 4}, {2, 4, 8, 4, 2}, {1, 2, 4, 2, 1} }; defusionProc(Mat); } void Bukes(){ int Mat[][5]={ {0, 0, 0, 8, 4}, {2, 4, 8, 4, 2}, {0, 0, 0, 0, 0} }; defusionProc(Mat); } void Atkinson(){ int Mat[][5]={ {0, 0, 0, 1, 1}, {0, 1, 1, 1, 0}, {0, 0, 1, 0, 0} }; defusionProc(Mat); } void Sierra(){ int Mat[][5]={ {0, 0, 0, 5, 3}, {2, 4, 5, 4, 2}, {0, 2, 3, 2, 0} }; defusionProc(Mat); } void Two_Row_Sierra(){// Two Row Sierra dithering int Mat[][5]={ {0, 0, 0, 4, 3}, {1, 2, 3, 2, 1}, {0, 0, 0, 0, 0} }; defusionProc(Mat); } void Sierra_Lite(){// Sierra Lite dithering int Mat[][5]={ {0, 0, 0, 2, 0}, {0, 1, 1, 0, 0}, {0, 0, 0, 0, 0} }; defusionProc(Mat); } 【リスト8-13】 カラー無作為ディザリング #define NRED 2 // REDの階調数 #define NGREEN 2 // GREENの階調数 #define NBLUE 2 // BLUEの階調数 int RDTCL(int X,int MAX, int MIN, int DM){ return (255*(X-MIN)/(MAX-MIN)>=DM)? MAX:MIN; } void colorRandom(){ int C, R, G, B, RR, GG, BB,R1,R2, G1,G2, B1,B2,DM; int DR=256/NRED, DG=256/NGREEN, DB=256/NBLUE; int XR=255/(NRED-1), XG=255/(NGREEN-1), XB=255/(NBLUE-1); int RD=255-20, ST=10;srand(1); for(int j=0;j=R1) R2 += XR; else R1 -= XR; G1=G2=(G/DG)*XG; if(G>=G1) G2 += XG; else G1 -= XG; B1=B2=(B/DB)*XB; if(B>=B1) B2 += XB; else B1 -= XB; R=RDTCL(RR, R2, R1, DM); G=RDTCL(GG, G2, G1, DM); B=RDTCL(BB, B2, B1, DM); setPixel(i, j, RGB(R, G,B)); } }