// ■C言語で画像処理 #include "myWin.h" #include "math.h" #define BT_1 1001 #define BT_2 1002 #define BT_3 1003 #define BT_4 1004 #define BT_5 1005 #define BT_6 1006 #define BT_7 1007 #define BT_8 1008 #define BT_9 1009 #define BT_13 1013 #define XST 310 #define YST 70 #define RED(X) (X & 0xFF) #define GREEN(X) ((X>> 8) & 0xFF) #define BLUE(X) ((X>>16) & 0xFF) #define swap(type, X, Y) do{type T; T=X; X=Y; Y=T;} while(0) static HDC hBuff[2]; //ビットマップ描画用 static HBITMAP hBM[2];//ビットマップ描画用 static BITMAP bM[2];//ビットマップ描画用 static HCURSOR hc; int Xstart=310, DX=-1; int filter[3][3]={{1,1,1},{1,1,1},{1,1,1}}; void drawEdge(HWND hw){ COLORREF C1, C2, C3, R1, R2, G1, G2, B1, B2; for(int i=0;i<300;i++)for(int j=0;j<300;j++){ int i1= (i==299)?298: i, j1=(j==299)? 298: j, i2=i1+1, j2=j1+1; C1=GetPixel(hBuff[1],i1, j1); C2=GetPixel(hBuff[1],i2, j1); C3=GetPixel(hBuff[1],i1, j2); R1=abs((int)(RED (C1)-RED (C2))); G1=abs((int)(GREEN(C1)-GREEN(C2))); B1=abs((int)(BLUE (C1)-BLUE (C2))); R2=abs((int)(RED (C1)-RED (C3))); G2=abs((int)(GREEN(C1)-GREEN(C3))); B2=abs((int)(BLUE (C1)-BLUE (C3))); SetPixel(hBuff[0],i,j,RGB((R1+R2)/2,(G1+G2)/2,(G1+G2)/2)); } InvalidateRect(hw,NULL,TRUE); } int mixColor(int C1, int C2, double Alfa){ return (int)((double)C1*(1-Alfa)+(double)C2*Alfa); } void drawDistinct(HWND hw){ int C0, C1, C2, C3,C4, R1, R2, G1, G2, B1, B2, R,G,B; double AR, AG, AB, Alfa=0.5;//Alfa:鮮明化の度合い。0〜1 for(int i=1;i<299;i++)for(int j=0;j<300;j++){ int i1=i+1, j1=j+1,i2=i-1, j2=j-1; C0=GetPixel(hBuff[1], i , j );//該当ピクセルの色と C1=GetPixel(hBuff[1], i1, j );//周辺ピクセルの色 C2=GetPixel(hBuff[1], i , j1); C3=GetPixel(hBuff[1], i2, j ); C4=GetPixel(hBuff[1], i , j2); R=RED(C0); G=GREEN(C0); B=BLUE(C0);//周辺の明るさとの差 R1= R*4 - RED (C1)- RED (C2)- RED (C3) - RED (C4); G1= G*4 - GREEN(C1)- GREEN(C2)- GREEN(C3) - GREEN(C4); B1= B*4 - BLUE (C1)- BLUE (C2)- BLUE (C3) - BLUE (C4); AR=abs((double)R1/255)*Alfa;//強調度合い AG=abs((double)G1/255)*Alfa; AB=abs((double)B1/255)*Alfa; R2=0xFF;if(R1<0) R2=0; //周辺が暗い場合は明るく G2=0xFF;if(G1<0) G2=0; //周辺が明るい場合は暗く B2=0xFF;if(B1<0) B2=0; //周辺色との差で明暗強調 R1=mixColor(R, R2, AR);if(R1>255) R1=255; G1=mixColor(G, G2, AG);if(G1>255) G1=255; B1=mixColor(B, B2, AB);if(B1>255) B1=255; SetPixel(hBuff[0],i,j,RGB(R1,G1,B1)); } InvalidateRect(hw,NULL,TRUE); } double setValue(double X,double tCurve[]){//カラートーンによる明るさ double A=0; for(int i=4;i>=0;i--)A = A*X+tCurve[i]; if(A<0) A=0; if(A>255)A=255; return A; } void drawContrast(HWND hw){ double tCurve[5]={ 0.0, 4.0, -0.003, 0.0001, 0.0}; int C0, C1, C2, C3,C4, R1, R2, G1, G2, B1, B2, R,G,B; double AR, AG, AB, Alfa=0.5;//Alfa:鮮明化の度合い。0〜1 for(int i=1;i<299;i++)for(int j=0;j<300;j++){ int i1=i+1, j1=j+1,i2=i-1, j2=j-1; C0=GetPixel(hBuff[1], i , j );//該当ピクセルの色と R=RED(C0); G=GREEN(C0); B=BLUE(C0);//周辺の明るさとの差 double Z=setValue(((double)R+(double)G+(double)B)/3,tCurve)/255; R1= (int)(Z*R); G1= (int)(Z*G); B1= (int)(Z*B); SetPixel(hBuff[0],i,j,RGB(R1,G1,B1)); } InvalidateRect(hw,NULL,TRUE); } void procFilter(int filter[3][3]){//フィルタ処理 for(int i=1;i<299;i++)for(int j=0;j<300;j++){ COLORREF C; int R=0,G=0,B=0, T=0; for(int k1=0;k1<=2; k1++)for(int k2=0;k2<=2; k2++){ C=GetPixel(hBuff[1],i+k1-1,j+k2-1); T+= filter[k1][k2]; R+=RED(C)*filter[k1][k2]; G+=GREEN(C)*filter[k1][k2]; B+=BLUE(C)*filter[k1][k2]; } R/=T; G/=T; B/=T; if(R>255)R=255; if(G>255)G=255; if(B>255)B=255; SetPixel(hBuff[0],i,j,RGB(R,G,B)); } } void drawShade(HWND hw){//平滑化フィルタ int filter[3][3]={{1,1,1},{1,1,1},{1,1,1}}; procFilter(filter); InvalidateRect(hw,NULL,TRUE); } void drawAverage(HWND hw){//加重平均フィルタ int filter[3][3]={{1,2,1},{2,4,2},{1,2,1}}; procFilter(filter); InvalidateRect(hw,NULL,TRUE); } void drawMedian(HWND hw){//メディアンフィルタ for(int i=1;i<299;i++)for(int j=0;j<300;j++){ int R=0,G=0,B=0, T=0, filter[9], k=0; for(int k1=0;k1<=2; k1++)for(int k2=0;k2<=2; k2++,k++) filter[k]=GetPixel(hBuff[1], i+k1-1, j+k2-1); for(int k1=0;k1<8;k1++)for(int k2=8;k2>k1; k2--) if(filter[k2-1]>filter[k2]) swap(int,filter[k2-1],filter[k2]); SetPixel(hBuff[0],i,j,filter[4]); } InvalidateRect(hw,NULL,TRUE); } void drawGamma(HWND hw){//ガンマ補正 トーンカーブは、 double DP=0.8; //255*pow(色/255,DP)の式で近似。DP<1のとき強調。 for(int i=1;i<299;i++)for(int j=0;j<300;j++){ COLORREF C=GetPixel(hBuff[1], i, j); double R=255*pow((double)RED (C)/255, DP); double G=255*pow((double)GREEN(C)/255, DP); double B=255*pow((double)BLUE (C)/255, DP); SetPixel(hBuff[0],i,j,RGB((int)R,(int)G,(int)B)); } InvalidateRect(hw,NULL,TRUE); } void drawMosaic(HWND hw){//モザイク処理(位置は固定)、 BitBlt(hBuff[0],0,0,bM[1].bmWidth,bM[1].bmHeight,hBuff[1],0,0,SRCCOPY); for(int i=60;i<140; i+=8)for(int j=40;j<120;j+=8){ int N=0, R=0, G=0, B=0, C=0; for(int k1=0;k1<8; k1++)for(int k2=0;k2<8; k2++){ N++; COLORREF C=GetPixel(hBuff[1], i+k1, j+k2); R+=RED(C); G+=GREEN(C); B+=BLUE(C); } C=RGB(R/N, G/N, B/N); for(int k1=0;k1<8; k1++)for(int k2=0;k2<8; k2++){ SetPixel(hBuff[0],i+k1,j+k2,C); } } InvalidateRect(hw,NULL,TRUE); } void drawMono(HWND hw){//モノクロ画像化 COLORREF C; for(int i=0;i<300;i++)for(int j=0;j<300;j++){ C=GetPixel(hBuff[1],i,j); C=(RED(C)+GREEN(C)+BLUE(C))/3; SetPixel(hBuff[0],i,j,RGB(C,C,C)); } InvalidateRect(hw,NULL,TRUE); } void drawMove(HWND hw){//結果反映 BitBlt(hBuff[1],0,0,bM[1].bmWidth,bM[1].bmHeight,hBuff[0],0,0,SRCCOPY); InvalidateRect(hw,NULL,TRUE); } void createButton(HWND hw, TCHAR name[], int X,int Y, int w, int h, int No){ CreateWindow(TEXT("BUTTON"),name,WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, X,Y,w,h, hw, (HMENU)No,hInstance,NULL); } void procCreate(HWND hw, WPARAM wp, LPARAM lp){ MoveWindow(hw, 0,0,640, 420,TRUE); SetWindowText(hw,TEXT("C言語で画像処理")); createButton(hw,TEXT("白黒化" ), 10, 2,90,30,BT_1); createButton(hw,TEXT("エッジ抽出" ),100, 2,90,30,BT_2); createButton(hw,TEXT("ぼかし" ),190, 2,90,30,BT_3); createButton(hw,TEXT("荷重平均" ),280, 2,90,30,BT_4); createButton(hw,TEXT("メディアン" ),370, 2,90,30,BT_5); createButton(hw,TEXT("ガンマ補正" ),460, 2,90,30,BT_6); createButton(hw,TEXT("モザイク" ), 10,32,90,30,BT_7); createButton(hw,TEXT("鮮明化" ),100,32,90,30,BT_8); createButton(hw,TEXT("明暗強調" ),190,32,90,30,BT_9); createButton(hw,TEXT("結果反映" ),460,32,90,30,BT_13); HDC hdc=GetDC(hw); hBM[0]=CreateCompatibleBitmap(hdc,300,300); hBM[1]=LoadBitmap(hInstance,TEXT("pict1")); for(int i=0;i<2;i++){ hBuff[i]=CreateCompatibleDC(hdc);SelectObject(hBuff[i],hBM[i]); } SelectObject(hBuff[0], GetStockObject(NULL_PEN)); PatBlt(hBuff[0], 0,0,300,300,WHITENESS); for(int i=0;i<2;i++)GetObject(hBM[i],sizeof(BITMAP),&bM[i]); BitBlt(hBuff[0],0,0,bM[1].bmWidth,bM[1].bmHeight,hBuff[1],0,0,SRCCOPY); ReleaseDC(hw, hdc); hc=LoadCursor(NULL, IDC_ARROW);SetCursor(hc); InvalidateRect(hw,NULL,TRUE); } void procLButtonDown(HWND hw, WPARAM wp, LPARAM lp){ int X=LOWORD(lp)-XST, Y=HIWORD(lp)-YST; if(X>0 && X0 && Y0 && X0 && Y