#include "myWin.h" #include "math.h" #include "stdio.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) #define DMAX 64 static HBITMAP hBM[2];static HDC hBuff[2]; static BITMAP bM[2]; #define frand()((double) rand()/(RAND_MAX+1)) #define ED_RED 4000 #define ED_GREEN 4001 #define ED_BLUE 4002 #define ED_NUM 4003 #define CM_METHOD 5001 #define CM_COLOR 5002 #define BT_1 6001 #define BT_2 6002 #define BT_3 6003 #define BT_4 6004 #define BT_5 6005 #define BT_6 6006 #define BT_7 6007 #define BT_8 6008 #define BT_9 6009 #define BT_10 6010 #define BT_11 6011 #define BT_12 6012 #define BT_13 6013 #define BT_14 6014 #define BT_15 6015 #define BT_16 6016 #define BT_17 6017 #define RD_1 7001 #define RD_2 7002 static HWND bt1, bt2, bt3, bt4, bt5,bt6, bt7, bt8, bt9; static HWND bt10,bt11, bt12, bt13, bt14, bt15,bt16,bt17; static HWND rd1, rd2; static HWND edCol[3], edNum,cmMethod,cmColor; static HWND edMAT[3][5]; 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); } int NRED= 2 ; // REDの階調数 int NGREEN= 2; // GREENの階調数 int NBLUE= 2; // BLUEの階調数 int monoChro=false; void setDitherMat(int M[][DMAX], int DM[][DMAX], int NX, int NY,int CMAX){ double NM=1.0+(double)(NX*NY), DV = CMAX; for(int i=0;i=TCHAR('0') && lstr[i]<=TCHAR('9')){ str[i]=(char)lstr[i]; iflag=false; } if(iflag) return 0; str[i]=0; sscanf(str,"%d", &i); return i; } int DTCL(int R, int MAX, int MIN, int DM[][DMAX], int x, int y){ return ((255*(R-MIN)/(MAX-MIN))>=DM[x][y])? MAX: MIN; } int DM[DMAX][DMAX]; int M[DMAX][DMAX]; int M2[2][2]={{0, 3},{2,1}}; int Mtmp[2][DMAX][DMAX]; int M3[3][3]={{0,3,5},{8,6,2},{4,1,7}}; int M6[6][6]={ { 0,12,20, 3,15,23}, {32,24, 8,35,27,11}, {16, 4,28,19, 7,31}, { 2,14,22, 1,13,21}, {34,26,10,33,25, 9}, {18, 6,30,17, 5,29}}; void setM(int M[][DMAX], int N){ if(N==3){ for(int i=0;iDMAX) N=DMAX; int k1=0,k2=1; for(int i=0;i<2;i++)for(int j=0;j<2;j++) Mtmp[k2][i][j]=M2[i][j]; for(int k=4;k<=N; k*=2){ k2=k1;k1=1-k2;int kk=k/2; for(int i=0;i=kk){ if(j>=kk) add=1; else add=2; } else if(j>=kk) add=3; Mtmp[k2][i][j]=Mtmp[k1][ii][jj]*4 + add; } } for(int i=0;iR1) 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+=XR;else B1-=XB; R=DTCL(RR, R2, R1, DM, x, y); G=DTCL(GG, G2, G1, DM, x, y); B=DTCL(BB, B2, B1, DM, x, y); setPixel(i + x, j + y, RGB(R, G,B)); } } } } void colorMatDithering(){ TCHAR str[32];GetWindowText(edNum,str,31); NX=getInt(str); if(NX!=3 && NX!=6){ int k=2; while(kDMAX)NX=DMAX; } NY=NX;setM(M,NX);setDitherMat(M,DM,NX,NY, 255); colorMat(); } void cluster4(HWND hw){ int CM[][4]={{12,5,6,13},{4,0,1,7},{11,3,2,8},{15,10,9,14}}; NX=NY=4; for(int i=0;iR1) 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+=XR;else B1-=XB; R=DTCL(RR, R2, R1, DM[id], x, y); G=DTCL(GG, G2, G1, DM[id], x, y); B=DTCL(BB, B2, B1, DM[id], x, y); setPixel(i + x, j + y, RGB(R, G,B)); } } } } void randomSelect(HWND hw){ static int RM[6][DMAX][DMAX]={ {{1,4,7},{6,0,2},{3,8,5}}, {{4,6,3},{8,1,5},{0,3,7}}, {{5,0,3},{2,8,6},{7,4,1}}, {{8,2,5},{6,4,0},{1,7,3}}, {{2,5,8},{0,7,3},{4,1,6}}, {{7,4,1},{3,6,8},{2,0,5}}}; randomSelect(RM, 3,6); InvalidateRect(hw,NULL,TRUE); } void randomSelect2(HWND hw){ static int RM[4][DMAX][DMAX]={ {{0,3},{2,1}},{{2,1},{0,3}}, {{3,0},{1,2}},{{1,2},{3,0}}}; randomSelect(RM, 2,4); InvalidateRect(hw,NULL,TRUE); } int RDTCL(int R, int MAX, int MIN, int DM){ return ((255*(R-MIN)/(MAX-MIN))>=DM)? MAX: MIN; } void completeRandom(HWND hw){ getStateColor(); 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(7); for(int j=0;jR1) 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+=XR;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)); } InvalidateRect(hw,NULL,TRUE); } void dithering(HWND hw){ TCHAR str[32]; GetWindowText(edNum,str,31); NX=NY=getInt(str); colorMatDithering(); InvalidateRect(hw,NULL,TRUE); } void ditheringMono(HWND hw){ MonoExt=SendMessage(rd2,BM_GETCHECK,0,0L); MonoFlag=true; dithering(hw); MonoFlag=false; } // ■以下は白井独自の方法です。 // // 簡略形 M[i,j] = ( i + (N - 3)×j) Mod Nとし, // 色値とd[i,j] = (1 + M[i,j])/(1 + N)との大小比較で判定します。 // // 結果的には,以下のディザタイルを用意したことと同じになります。 // // (N = 5 のとき) (N = 8 のとき) // // 3       2 3      // 4 0 1 6 7 0 1 // 2 4 5 // // なおプログラムでは,d[i,j] = (1 + M[i,j])/(1 + N)の // 計算を容易にするために,M[i,j] + 1 の値を // 変数値 ij としています。 // void ditheringTile(HWND hw, int N){ int NX=N-3, MAX=N+1, ii=1; getStateColor(); 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-10,ST=10; for(int j=0;jN) ij=1; DM=ij*255/MAX; C=pixel(i,j),R=RR=RED(C), G=GG=GREEN(C), B=BB=BLUE(C); R1=R2=R/DR*XR; if(R>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+=XR;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)); } ii+=NX;while(ii>N) ii-=N; } InvalidateRect(hw,NULL,TRUE); } int getAddChk(int i,int j){ int addTab[][5]={ {1,1,3,2,0},{1,0,2,2,2},{0,0,0,2,1}, {2,0,3,1,1},{1,3,3,3,1}}; int ii=i % 20, k = 0; if (ii>=16) { k=3; ii -= 16;} else if(ii>=12) { k=1; ii -= 12;} else if(ii>= 8) { k=4; ii -= 8;} else if(ii>= 4) { k=2; ii -= 4;} return addTab[(j+k) % 5][ii]; } void supercellDithering(HWND hw){ int N=5; int NX=N-3, MAX=4*N+1, ii=0; getStateColor(); 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; for(int j=0;j=N) ij=0; DM=(1+ij*4+getAddChk(i,j))*255/MAX; C=pixel(i,j),R=RR=RED(C), G=GG=GREEN(C), B=BB=BLUE(C); R1=R2=R/DR*XR; if(R>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+=XR;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)); } ii+=NX;while(ii>N) ii-=N; } InvalidateRect(hw,NULL,TRUE); } static LPCTSTR colorName[]={TEXT("8色(3bits)"), TEXT("64色(6bits)"), TEXT("256色(83bits)"), TEXT("4,096色(12bits)"), TEXT("32,768色(15bits)")}; int colTab[5][3]={{2,2,2}, {4,4,4},{8,8,4},{16,16,16},{32,32,32}}; void selectColor(HWND hw){ TCHAR str[20]; int r=SendMessage(cmColor, CB_GETCURSEL,0,0L); for(int i=0;i<3;i++){ wsprintf(str, TEXT("%d"),colTab[r][i]); SetWindowText(edCol[i],str); } } void draw24bits(HWND hw){//元画像 BitBlt(hBuff[0],0,0,GWIDTH, GHIGHT, hBuff[1], 0,0,SRCCOPY); InvalidateRect(hw,NULL,TRUE); } void changeColor(HWND hw, WPARAM wp){//元画像 if(HIWORD(wp)==CBN_SELCHANGE) selectColor(hw); setM(M,NX); } void monoChroPro(HWND hw){ for(int j=0;j=0 && ii<=GWIDTH){ for(int y=-1;y<2;y++){ int jj=j+y; if(jj>=0 && jj<=GHIGHT){ int C=pixel(i,j),R=RED(C), G=GREEN(C), B=BLUE(C); N++; TT+=(double)(R+G+B)/3.0; } } } } return (int)(TT/N+0.5); } int Rmap[GWIDTH][GHIGHT]; void modifiedRandom(HWND hw){ getStateColor(); 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(7); for(int j=0;jRD)Rmap[i][j]=RD; int RR=(int)((128-Rmap[i][j])*(1.0/(KM+1))); Rmap[i+1][j]+=(RR*3/4); Rmap[i][j+1]+=(RR*2/4); Rmap[i+1][j+1]+=(RR*1/4); } } double Gamma=0.05, K=65; for(int j=0;jR1) 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+=XR;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)); } InvalidateRect(hw,NULL,TRUE); } HWND createLabel(HWND hw, TCHAR text[], int x, int y, int width, int height, int id){ return CreateWindow(TEXT("STATIC"),text, WS_CHILD | WS_VISIBLE | SS_LEFT, x, y, width,height, hw, (HMENU)id, hInstance, NULL); } HWND createEdit(HWND hw,TCHAR str[], int x, int y, int width, int height, int id){ return CreateWindow(TEXT("EDIT"),str, WS_CHILD | WS_VISIBLE | WS_BORDER |ES_CENTER | ES_OEMCONVERT | ES_WANTRETURN, x,y, width,height, hw, (HMENU)id, hInstance, NULL); } HWND createRadio(HWND hw,TCHAR str[], int x, int y, int width, int height, int id, int start){ if(start) return CreateWindow(TEXT("BUTTON"),str, WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON|WS_GROUP, x,y, width,height, hw, (HMENU)id, hInstance, NULL); return CreateWindow(TEXT("BUTTON"),str, WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, x,y, width,height, hw, (HMENU)id, hInstance, NULL); } HWND createCombo(HWND hw,LPCTSTR text[10],int N, int x, int y, int width, int height, int id){ HWND combo1= CreateWindow(TEXT("COMBOBOX") ,NULL, WS_CHILD|WS_VISIBLE|CBS_SIMPLE|CBS_DROPDOWN|LBS_NOTIFY, x,y,width,height,hw,(HMENU)id, hInstance, NULL); for(int i=0;i=N) ij=0; if(dspArea[j][i]) { int DT=ij*4+getAddChk(i,j); wsprintf(str,TEXT("%4d"),DT); } else lstrcpy(str, TEXT(" ")); lstrcat(msg,str); } ii+=NX; while(ii>N) ii-=N; } SetWindowText(hEdit,msg); } BOOL CALLBACK DialogProc2(HWND hw,UINT msg, WPARAM wp,LPARAM lp){ switch(msg){ case WM_CLOSE : EndDialog(hw, IDOK) ;return TRUE; case WM_INITDIALOG: initDialog2(hw,wp,lp) ;return TRUE; } return FALSE; } void procDSP(HWND hw){ DSPFlag=false; DialogBox(hInstance,TEXT("TEXTMSG"),hw,DialogProc); } void procDSP2(HWND hw){ DSPFlag=true; DialogBox(hInstance,TEXT("TEXTMSG"),hw,DialogProc); } void procDSP3(HWND hw){ DSPFlag=true; DialogBox(hInstance,TEXT("TEXTMSG"),hw,DialogProc2); } void procRButtonDown(HWND hw, WPARAM wp,LPARAM lp){ clearBitmap(0);//画像0をクリア InvalidateRect(hw,NULL,TRUE); } void procCreate(HWND hw, WPARAM wp,LPARAM lp){//初期処理 createLabel(hw,TEXT(" RED"), 500, 5, 50,20, 2001); createLabel(hw,TEXT("GREEN"),550, 5, 50,20, 2002); createLabel(hw,TEXT(" BRUE"), 600, 5, 50,20, 2003); createLabel(hw,TEXT("階調"), 420, 30, 50,20, 2004); edCol[0] =createEdit(hw, TEXT("2") , 500, 30, 50, 20, ED_RED); edCol[1] =createEdit(hw, TEXT("2"), 550, 30, 50, 20, ED_GREEN); edCol[2] =createEdit(hw, TEXT("2") , 600, 30, 50, 20, ED_BLUE); createLabel(hw,TEXT("正方行列サイズ(3,6または2のべき乗 2〜32)"), 420, 90, 340,20, 2004); edNum =createEdit(hw, TEXT("2") , 760,90, 50, 20, ED_NUM); rd1=createRadio(hw,TEXT("白黒変換平均"), 420, 120, 120,20, RD_1,true); rd2=createRadio(hw,TEXT("白黒変換緑強調"), 560, 120, 140,20, RD_2,false); CheckDlgButton(hw, RD_2,1); bt1 =createButton(hw, TEXT("ディザリング") , 420, 150, 180, 30, BT_1); bt2 =createButton(hw, TEXT("単色ディザリング") , 600, 150, 180, 30, BT_2); bt4 =createButton(hw, TEXT("4×4 cluster dot") , 420, 180, 180, 30, BT_4); bt5 =createButton(hw, TEXT("8×8 cluster dot") , 600, 180, 180, 30, BT_5); bt6 =createButton(hw, TEXT("Ordered") , 510, 210, 90, 30, BT_6); bt7 =createButton(hw, TEXT("Select 3×3"), 600, 210, 90, 30, BT_7); bt8 =createButton(hw, TEXT("無作為") , 420, 210, 90, 30, BT_8); bt12 =createButton(hw, TEXT("Select 2×2"), 690, 210, 90, 30, BT_12); bt13 =createButton(hw, TEXT("Dither Tile size=5"), 420, 240, 180, 30, BT_13); bt14 =createButton(hw, TEXT("Dither Tile size=8"), 600, 240, 180, 30, BT_14); bt15 =createButton(hw, TEXT("Supercell dithering"), 420, 270, 180, 30, BT_15); bt17 =createButton(hw, TEXT("Modified Random"), 600, 270, 180, 30, BT_17); bt9 =createButton(hw, TEXT("行列確認") , 420, 300, 140, 30, BT_9); bt10 =createButton(hw, TEXT("白黒画像変換") , 560, 300, 140, 30, BT_10); bt3 =createButton(hw, TEXT("元画像表示") , 700, 300, 100, 30, BT_3); bt11 =createButton(hw, TEXT("簡略形行列確認") , 420, 330, 140, 30, BT_11); bt16 =createButton(hw, TEXT("Supercell確認") , 560, 330, 140, 30, BT_16); TCHAR MSG1[]=TEXT("単色のとき階調が異なると色が付いてしまいます。"); TCHAR MSG2[]=TEXT("ディザリング後,行列確認ができます。\n") TEXT("無作為〜Dither Tileでは行列確認できません。"); createLabel(hw,MSG1, 420, 60, 400,20, 2004); createLabel(hw,MSG2, 420, 370, 400,60, 2004); cmColor =createCombo(hw,colorName, 5, 700,27, 120,250,CM_COLOR); SendMessage(cmColor, CB_SETCURSEL,0,0L); createBitmap(hw);MoveWindow(hw,0,0,850,460,TRUE); hBM[1]=LoadBitmap(hInstance, TEXT("kodomo"));//画像1に表示 GetObject(hBM[1],sizeof(BITMAP), &bM[1]); selectColor(hw); SetWindowText(hw,TEXT("Ordered Dithering")); InvalidateRect(hw,NULL,TRUE); } void procPaint(HWND hw, WPARAM wp,LPARAM lp){//画面表示 PAINTSTRUCT ps; HDC hdc = BeginPaint(hw,&ps); SelectObject(hBuff[0],hBM[0]);SelectObject(hBuff[1],hBM[1]); BitBlt(hdc,10,YST,GWIDTH, GHIGHT, hBuff[0], 0,0,SRCCOPY); //BitBlt(hdc,XST,YST,GWIDTH, GHIGHT, hBuff[1], 0,0,SRCCOPY); EndPaint(hw,&ps); } void procCommand(HWND hw, WPARAM wp,LPARAM lp){ switch(LOWORD(wp)){ case BT_1: dithering(hw); return; case BT_2: ditheringMono(hw); return; case BT_3: draw24bits(hw); return; case BT_4: cluster4(hw);return; case BT_5: cluster8(hw);return; case BT_6: randomDithering(hw);return; case BT_7: randomSelect(hw);return; case BT_8: completeRandom(hw);return; case BT_9: procDSP(hw);return; case BT_10: monoChroPro(hw);return; case BT_11: procDSP2(hw);return; case BT_12: randomSelect2(hw);return; case BT_13: ditheringTile(hw,5);return; case BT_14: ditheringTile(hw,8);return; case BT_15: supercellDithering(hw);return; case BT_16: procDSP3(hw);return; case BT_17: modifiedRandom(hw);return; case CM_COLOR: changeColor(hw, wp); return; } } LRESULT CALLBACK WndProc(HWND hw, UINT msg, WPARAM wp,LPARAM lp){ switch(msg){ case WM_DESTROY : PostQuitMessage(0) ; return 0; case WM_CREATE : procCreate(hw,wp,lp); return 0; case WM_COMMAND : procCommand(hw,wp,lp); return 0; case WM_RBUTTONDOWN : procRButtonDown(hw,wp,lp); return 0; case WM_PAINT : procPaint (hw,wp,lp); return 0; } return DefWindowProc(hw,msg,wp,lp); }