001: #include <stdio.h>
002: #include <stdlib.h>
003: #include <time.h>
004: #include <math.h>
005: #include <windows.h>
006: #include "wingui.h"
007: #include "ipcommon.h"
008: //-----------------------------------------------------------------
009: // 乱数発生 [0..n-1 までの乱数]
010: //-----------------------------------------------------------------
011: void init_random() // 乱数の初期化
012: {
013:     int seed = time(NULL);
014:     if(seed<1) seed=1;
015:     srand(seed);
016: }
017: int random_int(int n)
018: {
019:     return rint((double)rand()/((double)RAND_MAX+1.0)*n);
020: }
021: //-----------------------------------------------------------------
022: // 色の交換
023: //-----------------------------------------------------------------
024: void swapcol(BYTE c1,BYTE c2)
025: {
026:     BYTE c = c1; c1 = c2; c2 = c;
027: }
028: //-----------------------------------------------------------------
029: // RGB から 濃淡値の計算
030: //-----------------------------------------------------------------
031: BYTE rgb2gray(BYTE r,BYTE g,BYTE b)
032: {
033:     int gray=rint(r*0.299+g*0.587+b*0.144);
034:     if(gray>iWHITE) gray=iWHITE;
035:     return gray;
036: }
037: //-----------------------------------------------------------------
038: // 点の交換
039: //-----------------------------------------------------------------
040: void swap_point(POINT p1,POINT p2)
041: {
042:     POINT p;
043:     p.x  = p1.x; p.x  = p1.y;
044:     p1.x = p2.x; p1.y = p2.y;
045:     p2.x = p.x;  p2.y = p.y;
046: }
047: //-----------------------------------------------------------------
048: // 色の比較
049: //-----------------------------------------------------------------
050: int colcmp(LPBYTE inb,CPIXEL c)
051: {
052:     if(*(inb+2)==c.r && *(inb+1)==c.g && *(inb+0)==c.b)
053:         return 1;
054:     return 0;
055: }
056: //-----------------------------------------------------------------
057: // 色の設定
058: //-----------------------------------------------------------------
059: void setcol(LPBYTE inb,CPIXEL c)
060: {
061:     *(inb+2) = c.r;
062:     *(inb+1) = c.g;
063:     *(inb+0) = c.b;
064: }
065: //-----------------------------------------------------------------
066: // 距離の計算
067: //-----------------------------------------------------------------
068: double calc_distance(POINT p1,POINT p2)
069: {
070:     return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
071: }
072: double calc_distance(int x1,int y1,int x2,int y2)
073: {
074:     return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
075: }
076: //-----------------------------------------------------------------
077: // 描画関数
078: //-----------------------------------------------------------------
079: // 中心:p(x,y),半径:r の円を描く
080: void draw_circle(LPBYTE oBuf,POINT cp,int radius)
081: {
082:     int xp,yp,th,th_max;
083:     double cirstep;
084:     // 1ピクセル毎の計算となるように
085:     th_max  = rint(2*M_PI*radius);
086:     cirstep = 360./th_max;
087:     for(th=0;th<th_max;th++){
088:         xp = rint(cp.x + radius * cos(deg2rad(cirstep*th)));
089:         yp = rint(cp.y + radius * sin(deg2rad(cirstep*th)));
090:         if(xp>=0 && xp<iWidth && yp>=0 && yp<iHeight)
091:             oBuf[xp+yp*iWidth] = iWHITE;
092:     }
093: }
094: //-----------------------------------------------------------------
095: // p1:(x1,y1), p2:(x2,y2) 間の直線を描く
096: //-----------------------------------------------------------------
097: void draw_line(LPBYTE oBuf,POINT p1,POINT p2)
098: {
099:     draw_line(oBuf,p1.x,p1.y,p2.x,p2.y);
100: }
101: void draw_line(LPBYTE oBuf,int x1,int y1,int x2,int y2)
102: {
103:     int xp,yp;
104:     double distance,step,t;
105:     int dx1,dx2,dy1,dy2;
106:     dx1 = x1; dx2 = x2; dy1 = y1; dy2 = y2;
107:     // 描画位置のクリッピング処理
108:     if(scrossln(&dx1,&y1,&x2,&y2)==0) return;
109:     // 描画開始
110:     t = 0.0;
111:     distance = calc_distance(dx1,dy1,dx2,dy2);
112:     step = 1.0/(1.5*distance);
113:     while(t<1.0){
114:         xp = rint(t*dx2 + (1.0-t)*dx1);
115:         yp = rint(t*dy2 + (1.0-t)*dy1);
116:         if(xp>=0 && xp<iWidth && yp>=0 && yp<iHeight)
117:             oBuf[xp+yp*iWidth] = iWHITE;
118:         t = t + step;
119:     }
120: }
121: //-----------------------------------------------------------------
122: // 直線と(x=xc)の直線との交点のy座標を求める
123: //-----------------------------------------------------------------
124: int croslnxc(int x1,int y1,int x2,int y2,int xc,int *yc)
125: {
126:     double wk;
127:     if(y1 == y2){ *yc = y1; return  1; }
128:     if(x1 == x2){ *yc = 0;  return -1; }
129:     if(x1 != x2){
130:         wk  = (y2-y1)/(x2-x1);
131:         *yc = rint(wk*(xc-x1)+y1);
132:         return 1;
133:     }
134:     return 0;
135: }
136: //-----------------------------------------------------------------
137: // 直線と(y=yc)の直線との交点のx座標を求める
138: //-----------------------------------------------------------------
139: int croslnyc(int x1,int y1,int x2,int y2,int yc,int *xc)
140: {
141:     double wk;
142:     if(x1 == x2){ *xc = x1; return  1; }
143:     if(y1 == y2){ *xc = 0;  return -1; }
144:     if(x1 != x2){
145:         wk  = (y2-y1)/(x2-x1);
146:         *xc = rint(x1+(yc-y1)/wk);
147:         return 1;
148:     }
149:     return 0;
150: }
151: //-----------------------------------------------------------------
152: // 直線描画領域の2次元クリッピング処理:
153: //        直線の両端点の座標から実際に描く線分の端点を求める
154: //-----------------------------------------------------------------
155: int scrossln(int* x1,int* y1,int* x2,int* y2)
156: {
157:     int dx1,dx2,dy1,dy2;
158:     int i,is,ip,mkp1,mkp2;
159:     int wk,xc,yc,xw1,xw2,yw1,yw2;
160:     int xx[2],yy[2],ds1[2],ds2[2];
161:     int gr_wnx[2],gr_wny[2];
162:     //--------------------------------------------------
163:     // 初期化
164:     //--------------------------------------------------
165:     dx1 = *x1; dx2 = *x2; dy1 = *y1; dy2 = *y2;
166:     for(i=0;i<2;i++){
167:         xx[i] =0; yy[i] =0; ds1[i]=0; ds2[i]=0;
168:     }
169:     xw1=gr_wnx[0]=0; xw2=gr_wnx[1]=iWidth;
170:     yw1=gr_wny[0]=0; yw2=gr_wny[1]=iHeight;
171:     mkp1=mkp2=0;
172:     //--------------------------------------------------
173:     // 直線の端点がウィンドウの枠の内部かどうか
174:     //--------------------------------------------------
175:     if(dx1>=xw1 && dx1<=xw2 && dy1>=yw1 && dy1<=yw2){
176:         *x1  = dx1; *y1 = dy1;
177:         mkp1 = 1;
178:     }
179:     if(dx2>=xw1 && dx2<=xw2 && dy2>=yw1 && dy2<=yw2){
180:         *x2  = dx2; *y2 = dy2;
181:         mkp2 = 1;
182:     }
183:     //--------------------------------------------------
184:     // ウィンドウ内であれば終了
185:     //--------------------------------------------------
186:     if(mkp1 == 1 && mkp2 == 1) return 1;
187:     ip = 0;
188:     //--------------------------------------------------
189:     // 直線とウィンドウの上下の枠と交差する点を求める
190:     //--------------------------------------------------
191:     for(i=0;i<2;i++){
192:         wk=gr_wnx[i];
193:         is=croslnxc(dx1,dy1,dx2,dy2,wk,&yc); 
194:         if(is == 1 && yc>=yw1 && yc<=yw2){
195:             xx[ip] = wk; yy[ip] = yc;
196:             ip++;
197:         }
198:     }
199:     //--------------------------------------------------
200:     // 直線とウィンドウの左右の枠と交差する点を求める
201:     //--------------------------------------------------
202:     if(ip<2){
203:         for(i=0;i<2;i++){
204:             wk=gr_wny[i];
205:             is=croslnyc(dx1,dy1,dx2,dy2,wk,&xc); 
206:             if(is == 1 && xc>=xw1 && xc<=xw2){
207:                 xx[ip] = xc; yy[ip] = wk;
208:                 ip++;
209:             }
210:         }    
211:     }
212:     //--------------------------------------------------
213:     // 描く直線が枠と交差しない場合は直線の全てが
214:     // 枠の外側にあるので、描く必要がないことをしめす
215:     //--------------------------------------------------
216:     if(ip==0) return 0;
217:     //--------------------------------------------------
218:     // 枠と交差する点を描く直線の対応する端点として代入
219:     //--------------------------------------------------
220:     for(i=0;i<2;i++){
221:         ds1[i] = ((xx[i]-dx1)*(xx[i]-dx1)+(yy[i]-dy1)*(yy[i]-dy1));
222:         ds2[i] = ((xx[i]-dx2)*(xx[i]-dx2)+(yy[i]-dy2)*(yy[i]-dy2));
223:     }
224:     if(mkp1 == 0){
225:         if(ds1[0]<ds1[1]){
226:             *x1 = xx[0]; *y1 = yy[0];
227:         }
228:         if(ds1[0]>ds1[1]){
229:             *x1 = xx[1]; *y1 = yy[1];
230:         }
231:     }
232:     if(mkp2 == 0){
233:         if(ds2[0]<ds2[1]){
234:             *x2 = xx[0]; *y2 = yy[0];
235:         }
236:         if(ds2[0]>ds2[1]){
237:             *x2 = xx[1]; *y2 = yy[1];
238:         }
239:     }
240:     return 1;
241: }
242: //-----------------------------------------------------------------
243: // 画像処理関数
244: //-----------------------------------------------------------------
245: // 表示用
246: void GrayToColor(LPBYTE iGray,LPBYTE iColor)
247: {
248:     int i,x,y;
249:     int iadd = iLength-iWidth*3;
250:     // カラー画像へ
251:     for(y=0;y<iHeight;y++){
252:         for(x=0;x<iWidth;x++) {
253:             FillMemory(iColor+x*3+y*iLength,sizeof(BYTE)*3,iGray[x+y*iWidth]);
254:         }
255:         for(i=0;i<iadd;i++)
256:             iColor[x*3+y*iLength + i] = 0;
257:     }
258: }
259: //-----------------------------------------------------------------
260: // 濃淡化
261: //-----------------------------------------------------------------
262: void toGray()
263: {
264:     int i,j; BYTE r,g,b,gray;
265:     FillMemory(iGHist,sizeof(UINT)*512,0);
266:     // 濃淡化
267:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
268:         b=lpOrgBMP[j*3+i*iLength+0];
269:         g=lpOrgBMP[j*3+i*iLength+1];
270:         r=lpOrgBMP[j*3+i*iLength+2];
271:         gray=rgb2gray(r,g,b);
272:         iGHist[gray]++;
273:         FillMemory(lpBMP+j*3+i*iLength,sizeof(BYTE)*3,gray);
274:     }
275: }
276: //-----------------------------------------------------------------
277: // 濃淡[R,G,B]画像の取得
278: //-----------------------------------------------------------------
279: LPBYTE GetGray()
280: {
281:     int i,j; BYTE r,g,b,gray;
282:     LPBYTE iGray=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iSize);
283:     FillMemory(iGHist,sizeof(UINT)*512,0);
284:     // 濃淡化
285:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
286:         b=lpOrgBMP[j*3+i*iLength+0];
287:         g=lpOrgBMP[j*3+i*iLength+1];
288:         r=lpOrgBMP[j*3+i*iLength+2];
289:         gray=rgb2gray(r,g,b);
290:         if(gray>iWHITE) gray=iWHITE;
291:         iGHist[gray]++;
292:         iGray[j+i*iWidth] = gray;
293:     }
294:     return iGray;
295: }
296: LPBYTE GetColor(int csel)
297: {
298:     int i,j; BYTE c;
299:     LPBYTE iColor=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iSize);
300:     FillMemory(iGHist,sizeof(UINT)*512,0);
301:     // RGB成分
302:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
303:         c = lpOrgBMP[j*3+i*iLength + csel];
304:         iColor[j+i*iWidth] = c;
305:         iGHist[c]++;
306:     }
307:     return iColor;
308: }
309: //-----------------------------------------------------------------
310: // OR 処理
311: //-----------------------------------------------------------------
312: void IPfunc_OR(LPBYTE iDst,LPBYTE iAdd)
313: {
314:     int x,y;
315:     for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++) {
316:         iDst[x+y*iWidth] = (iDst[x+y*iWidth] | iAdd[x+y*iWidth])?
317:             iWHITE: iBLACK;
318:     }
319: }
320: //-----------------------------------------------------------------
321: // メディアンフィルタ
322: //-----------------------------------------------------------------
323: void IPfunc_median(LPBYTE inBuf)
324: {
325:     int i,x,y,px,py;
326:     BYTE c[9];
327:     LPBYTE tempBuf=(LPBYTE)GlobalAlloc(GPTR,iSize);
328:     CopyMemory(tempBuf,inBuf,iSize);
329:     // フィルタリング開始
330:     for(y=1;y<iHeight-1;y++) for(x=1;x<iWidth-1;x++){
331:         for(i=0;i<8;i++){
332:             px = x+offset8[i].x;
333:             py = y+offset8[i].y;
334:             c[i] = tempBuf[px+py*iWidth];
335:         }
336:         inBuf[x+y*iWidth] = median(c);
337:     }
338:     GlobalFree(tempBuf);
339: }
340: BYTE median(BYTE c[9])
341: {
342:     int i,j;
343:     for(j=0;j<8;j++) for(i=0;i<8;i++){
344:         if(c[i+1]<c[i]) swapcol(c[i],c[i+1]);
345:     }
346:     return c[4];
347: }
348: //-----------------------------------------------------------------
349: // 組織的ディザ法によるディザ画像の作成
350: //-----------------------------------------------------------------
351: void toDither(LPBYTE inBuf)
352: {
353:     static int DITHER_BSZ = 4;  // ブロックの画素数
354:     static int DITHER_NL  = 16; // 擬似階調数(=4^2)
355:     double width;               // 16段階画像の階調値の単位幅
356:     BYTE new_gray;              // 新しい階調(16階調での値)
357:     int x_block,y_block;        // 横・縦のブロック数
358:     int x,y,i,j,m,n,px,py;
359:     static int dither_matrix[4][4]={ // Bayer 型ディザ行列
360:         { 0, 8, 2,10},
361:         {12, 4,14, 6},
362:         { 3,11, 1, 9},
363:         {15, 7,13, 5}
364:     };
365:     //--------------------------------------------------
366:     // 16階調の画像の作成
367:     //--------------------------------------------------
368:     width = iWHITE/(double)DITHER_NL;
369:     for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++){
370:         new_gray=rint(inBuf[x+y*iWidth]/width);
371:         if(new_gray > DITHER_NL-1)
372:             new_gray = DITHER_NL-1;
373:         inBuf[x+y*iWidth] = new_gray;
374:     }
375:     //--------------------------------------------------
376:     // ディザ画像の作成
377:     //--------------------------------------------------
378:     x_block=iWidth  / DITHER_BSZ;  // 横のブロック数
379:     y_block=iHeight / DITHER_BSZ;  // 縦のブロック数
380:     if(iWidth  % DITHER_BSZ) x_block++;
381:     if(iHeight % DITHER_BSZ) y_block++;
382:     for(i=0;i<y_block;i++) for(j=0;j<x_block;j++){
383:         x=j*DITHER_BSZ;
384:         y=i*DITHER_BSZ;
385:         for(m=0;m<DITHER_BSZ;m++) for(n=0;n<DITHER_BSZ;n++){
386:             px=x+n; py=y+m;
387:             if(px>=0 && px<iWidth && py>=0 && py<iHeight){
388:                 if(inBuf[px+py*iWidth] <= dither_matrix[m][n])
389:                     inBuf[px+py*iWidth]=0;
390:                 else inBuf[px+py*iWidth]=iWHITE;
391:             }
392:         }
393:     }
394: }
395: //-----------------------------------------------------------------
396: // 画素の階調分布に対して線形変換
397: //-----------------------------------------------------------------
398: void linear_transform(LPBYTE inBuf)
399: {
400:     int x,y;
401:     int minv,maxv; // 階調値の最小値,最大値
402:     // 階調値の最小値,最大値を求める
403:     minv = 10000;  maxv = 0;
404:     for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++){
405:         if(inBuf[x+y*iWidth]<minv) minv=inBuf[x+y*iWidth];
406:         if(inBuf[x+y*iWidth]>maxv) maxv=inBuf[x+y*iWidth];
407:     }
408:     // 階調を線形変換して image2[y][x] に代入
409:     for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++)
410:         inBuf[x+y*iWidth] = (BYTE)rint((inBuf[x+y*iWidth]-minv)*
411:                                        iWHITE/(double)(maxv-minv));    
412: }
413: 
414: //-----------------------------------------------------------------
415: // 表現階調数の変更
416: //    GetGray(),GetColor(): 等で計算したヒストグラムを使用
417: //-----------------------------------------------------------------
418: void change_graylevel(LPBYTE inBuf,int iLevel)
419: {
420:     int trhist[512],trans_table[512];
421:     int i,x,y,gray;
422:     int target_value; // 変換後の頻度の目標値
423:     double gray_step; // 表現階調間隔
424:     // ヒストグラム変換表の作成
425:     target_value = rint(iSize/(double)iLevel);
426:     FillMemory(trhist,512,0);
427:     FillMemory(trans_table,512,0);
428:     gray = 0;
429:     for(i=0;i<iMAX_GRAY;i++){
430:         if(abs(target_value-trhist[gray]) <
431:            abs(target_value-(trhist[gray] + iGHist[i]))){
432:             gray ++;
433:             if(gray>=iLevel) gray=iLevel-1;
434:         }
435:         trans_table[i] = gray;
436:         trhist[gray]  += iGHist[i];
437:     }
438:     // 平滑化した画像の作成
439:     gray_step = (double)(iWHITE+1) / iLevel;
440:     for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++)
441:         inBuf[x+y*iWidth] = (BYTE)rint(
442:             trans_table[inBuf[x+y*iWidth]] * gray_step);
443: }
444: //-----------------------------------------------------------------
445: // 画像の空間フィルタリングを行う
446: //-----------------------------------------------------------------
447: void spacial_filtering(LPBYTE inBuf,int iFlt[9],double iMag)
448: {
449:     LPBYTE tempBuf=(LPBYTE)GlobalAlloc(GPTR,iSize);
450:     int i,x,y,px,py;
451:     double new_value,minv,maxv;
452:     // 画像の複製
453:     CopyMemory(tempBuf,inBuf,iSize);
454:     // 最小・最大値の計算[線形変換用]
455:     minv = 10000.; maxv = 0.;
456:     for(y=1;y<iHeight-1;y++) for(x=1;x<iWidth-1;x++){
457:         new_value = 0.0;
458:         for(i=0;i<9;i++){
459:             px = x+offset9[i].x;
460:             py = y+offset9[i].y;
461:             new_value += iFlt[i] * tempBuf[px+py*iWidth];
462:         }
463:         new_value = new_value / iMag;
464:         if(new_value < minv) minv = new_value;
465:         if(new_value > maxv) maxv = new_value;
466:     }
467:     // フィルタリングを行う
468:     for(y=1;y<iHeight-1;y++) for(x=1;x<iWidth-1;x++){
469:         new_value = 0.0;
470:         for(i=0;i<9;i++){
471:             px = x+offset9[i].x;
472:             py = y+offset9[i].y;
473:             new_value += iFlt[i] * tempBuf[px+py*iWidth];
474:         }
475:         new_value = new_value / iMag;
476:         new_value = iWHITE / (maxv-minv) * (new_value-minv);
477:         inBuf[x+y*iWidth] = (BYTE)rint(new_value);
478:     }
479:     GlobalFree(tempBuf);
480: }
inserted by FC2 system