[PR]子育てママさんへ:3年毎に15万円うけとれる医療保険?

0001: //-----------------------------------------------------------------
0002: // ipcommon.cpp:
0003: //     画像処理一般
0004: //                 Last Update: <2004/12/13 18:10:29 A.Murakami>
0005: //-----------------------------------------------------------------
0006: #include <stdlib.h>
0007: #include <time.h>
0008: #include <math.h>
0009: #include <windows.h>
0010: #include "wingui.h"
0011: #include "ipcommon.h"
0012: //-----------------------------------------------------------------
0013: // ユークリッドの互除法による最小公倍数
0014: //-----------------------------------------------------------------
0015: // ユークリッドの互除法による最小公倍数
0016: int lcm(int a,int b)
0017: {
0018:     int x=a,y=b,c;
0019:     if(a<=0||b<=0) return 1;
0020:     if(a<b) swapv(a,b);
0021:     if(a<b){ c=a; a=b; b=c; }
0022:     while(b!=0){ c=a%b; a=b; b=c; }
0023:     return (x*y/a);
0024: }
0025: //-----------------------------------------------------------------
0026: // 乱数発生 [0..n-1 までの乱数]
0027: //-----------------------------------------------------------------
0028: void init_random() // 乱数の初期化
0029: {
0030:     int seed = time(NULL);
0031:     if(seed<1) seed=1;
0032:     srand(seed);
0033: }
0034: int random_int(int n)
0035: {
0036:     return rint((double)rand()/((double)RAND_MAX+1.0)*n);
0037: }
0038: //-----------------------------------------------------------------
0039: // データの入れ替え
0040: //-----------------------------------------------------------------
0041: void swapv(int c1,int c2)
0042: {
0043:     int c=c1; c1=c2; c2=c;
0044: }
0045: // 点の交換
0046: void swap_point(POINT p1,POINT p2)
0047: {
0048:     POINT p={0,0};
0049:     p.x  = p1.x; p.x  = p1.y;
0050:     p1.x = p2.x; p1.y = p2.y;
0051:     p2.x = p.x;  p2.y = p.y;
0052: }
0053: //-----------------------------------------------------------------
0054: // 色の比較
0055: //-----------------------------------------------------------------
0056: int colcmp(LPBYTE inb,CPIXEL c)
0057: {
0058:     if(*(inb+2)==c.r && *(inb+1)==c.g && *(inb+0)==c.b)
0059:         return 1;
0060:     return 0;
0061: }
0062: //-----------------------------------------------------------------
0063: // 色の設定
0064: //-----------------------------------------------------------------
0065: void setcol(LPBYTE inb,CPIXEL c)
0066: {
0067:     *(inb+2) = c.r;
0068:     *(inb+1) = c.g;
0069:     *(inb+0) = c.b;
0070: }
0071: //-----------------------------------------------------------------
0072: // 距離の計算
0073: //-----------------------------------------------------------------
0074: double calc_distance(POINT p1,POINT p2)
0075: {
0076:     return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
0077: }
0078: double calc_distance(int x1,int y1,int x2,int y2)
0079: {
0080:     return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
0081: }
0082: //-----------------------------------------------------------------
0083: //  平均値 (mean)
0084: //-----------------------------------------------------------------
0085: double calc_mean(int n,double* a)
0086: {
0087:     int i; double mean=0;
0088:     for(i=0;i<n;i++) mean += a[i];
0089:     return mean/n;
0090: }
0091: //-----------------------------------------------------------------
0092: // 標準偏差 (standard deviation)
0093: //-----------------------------------------------------------------
0094: double calc_sd(int n,double* a)
0095: {
0096:     int i;
0097:     double sd=0,mean=calc_mean(n,a);
0098:     for(i=0;i<n;i++) sd+=(a[i]*a[i]);
0099:     sd -= n*mean*mean;
0100:     sd /= (double)n;
0101:     return sqrt(sd);
0102: }
0103: //-----------------------------------------------------------------
0104: // 標準化[平均,標準偏差=0]
0105: //-----------------------------------------------------------------
0106: void standalize_data(int n,double* a)
0107: {
0108:     int i;
0109:     double mv=calc_mean(n,a);
0110:     double sd=calc_sd(n,a);
0111:     for(i=0;i<n;i++)
0112:         a[i] = (a[i]-mv)/sd;
0113: }
0114: //-----------------------------------------------------------------
0115: // 正規化[0..1]
0116: //-----------------------------------------------------------------
0117: void normalize_data(int n,double* a)
0118: {
0119:     int i; double maxv,minv;
0120:     maxv = -10000.; minv = 10000.;
0121:     for(i=0;i<n;i++){
0122:         if(a[i]-maxv > 0) maxv = a[i];
0123:         if(a[i]-minv < 0) minv = a[i];
0124:     }
0125:     // 正規化
0126:     for(i=0;i<n;i++)
0127:         a[i] = maxv*(a[i]-minv) / fabs(maxv-minv);
0128: }
0129: //-----------------------------------------------------------------
0130: // 表色系の変換
0131: //-----------------------------------------------------------------
0132: // RGB から 濃淡値の計算
0133: BYTE rgb2gray(BYTE r,BYTE g,BYTE b)
0134: {
0135:     int gray=rint(r*0.299+g*0.587+b*0.144);
0136:     if(gray>iWHITE) gray=iWHITE;
0137:     return gray;
0138: }
0139: //-----------------------------------------------------------------
0140: // RGB から YUV 色調への計算
0141: //-----------------------------------------------------------------
0142: void rgb2yuv(BYTE r,BYTE g,BYTE b,BYTE &y,BYTE &u,BYTE &v)
0143: {
0144:     double yv,uv,vv;
0145:     yv = (0.2989 *(r+175.45)+0.5871*(g-132.40)+0.1140*(b+221.74));
0146:     uv = (0.5115 *(r+175.45)-0.4283*(g-132.40)-0.0832*(b+221.74));
0147:     vv = (-0.1726*(r+175.45)-0.3389*(g-132.40)+0.5114*(b+221.74));
0148:     if(yv>iWHITE) yv=iWHITE; if(yv<0) yv=0;
0149:     if(uv>iWHITE) uv=iWHITE; if(uv<0) uv=0;
0150:     if(vv>iWHITE) vv=iWHITE; if(vv<0) vv=0;
0151:     y = (BYTE)yv; u = (BYTE)uv; v = (BYTE)vv;
0152: }
0153: BYTE rgb2y(BYTE r,BYTE g,BYTE b)
0154: {
0155:     double yv;
0156:     yv = (0.2989 *(r+175.45)+0.5871*(g-132.40)+0.1140*(b+221.74));
0157:     if(yv>iWHITE) yv=iWHITE; if(yv<0) yv=0;
0158:     return (BYTE)yv;
0159: }
0160: BYTE rgb2u(BYTE r,BYTE g,BYTE b)
0161: {
0162:     double uv;
0163:     uv = (0.5115 *(r+175.45)-0.4283*(g-132.40)-0.0832*(b+221.74));
0164:     if(uv>iWHITE) uv=iWHITE; if(uv<0) uv=0;
0165:     return (BYTE)uv;
0166: }
0167: BYTE rgb2v(BYTE r,BYTE g,BYTE b)
0168: {
0169:     double vv;
0170:     vv = (-0.1726*(r+175.45)-0.3389*(g-132.40)+0.5114*(b+221.74));
0171:     if(vv>iWHITE) vv=iWHITE; if(vv<0) vv=0;
0172:     return (BYTE)vv;
0173: }
0174: //-----------------------------------------------------------------
0175: // RGB から ρ/θ の計算
0176: //-----------------------------------------------------------------
0177: void rgb2rth(BYTE r,BYTE g,BYTE b,BYTE &rho,BYTE &th)
0178: {
0179:     // YUV 色調への変換
0180:     BYTE y,u,v;
0181:     rgb2yuv(r,g,b,y,u,v);
0182:     // 色彩距離(ρ),色相(θ) の計算
0183:     double tmp1,tmp2,rhov,thv;
0184:     tmp1=u-128.; tmp2=v-128.;
0185:     rhov = sqrt(tmp1*tmp1+tmp2*tmp2);
0186:     thv  = rad2deg(atan2(tmp1,tmp2));
0187:     if(rhov<0) rhov=0;   if(rhov>180) rhov=180;
0188:     if(thv<0)  thv+=360; if(thv>360)  thv-=360;
0189:     rhov = (double)iWHITE*(rhov)/(180.);
0190:     thv  = (double)iWHITE*(thv) /(360.);
0191:     rho = (BYTE)rhov;
0192:     th  = (BYTE)thv;
0193: }
0194: BYTE rgb2rho(BYTE r,BYTE g,BYTE b)
0195: {
0196:     // YUV 色調への変換
0197:     BYTE y,u,v;
0198:     rgb2yuv(r,g,b,y,u,v);
0199:     // 色彩距離(ρ)の計算
0200:     double tmp1,tmp2,rhov;
0201:     tmp1=u-128.; tmp2=v-128.;
0202:     rhov  = sqrt(tmp1*tmp1+tmp2*tmp2);
0203:     if(rhov<0) rhov=0;   if(rhov>180) rhov=180;
0204:     rhov = (double)iWHITE*(rhov)/(180.);
0205:     return (BYTE)rhov;
0206: }
0207: BYTE rgb2theta(BYTE r,BYTE g,BYTE b)
0208: {
0209:     // YUV 色調への変換
0210:     BYTE y,u,v;
0211:     rgb2yuv(r,g,b,y,u,v);
0212:     // 色相(θ) の計算
0213:     double tmp1,tmp2,thv;
0214:     tmp1=u-128.; tmp2=v-128.;
0215:     thv = rad2deg(atan2(tmp1,tmp2));
0216:     if(thv<0)  thv+=360; if(thv>360)  thv-=360;
0217:     thv  = (double)iWHITE*(thv) /(360.);
0218:     return (BYTE)thv;
0219: }
0220: //-----------------------------------------------------------------
0221: // 描画関数
0222: //-----------------------------------------------------------------
0223: // 中心:p(x,y),半径:r の円を描く
0224: void draw_circle(LPBYTE oBuf,POINT cp,int radius)
0225: {
0226:     int xs,ys,th,th_max;
0227:     double cirstep;
0228:     // 1ピクセル毎の計算となるように
0229:     th_max  = rint(2*M_PI*radius);
0230:     cirstep = 360./th_max;
0231:     for(th=0;th<th_max/2.;th++){
0232:         xs = rint(cp.x + radius * cos(deg2rad(cirstep*th)));
0233:         ys = rint(cp.y + radius * sin(deg2rad(cirstep*th)));
0234:         if(ip_safe(xs,ys,iWidth,iHeight))
0235:             oBuf[XY2PI(xs,ys,iWidth)] = iWHITE;
0236:         xs = rint(cp.x + radius * cos(deg2rad(360-cirstep*th)));
0237:         ys = rint(cp.y + radius * sin(deg2rad(360-cirstep*th)));
0238:         if(ip_safe(xs,ys,iWidth,iHeight))
0239:             oBuf[XY2PI(xs,ys,iWidth)] = iWHITE;
0240:     }
0241: }
0242: //-----------------------------------------------------------------
0243: // p1:(x1,y1), p2:(x2,y2) 間の直線を描く
0244: //-----------------------------------------------------------------
0245: void draw_line(LPBYTE oBuf,POINT p1,POINT p2,int col)
0246: {
0247:     draw_line(oBuf,p1.x,p1.y,p2.x,p2.y,col);
0248: }
0249: void draw_line(LPBYTE oBuf,int x1,int y1,int x2,int y2,int col)
0250: {
0251:     int xp,yp;
0252:     double distance,step,t;
0253:     int dx1,dx2,dy1,dy2;
0254:     dx1 = x1; dx2 = x2; dy1 = y1; dy2 = y2;
0255:     // 描画位置のクリッピング処理
0256:     if(scrossln(&dx1,&y1,&x2,&y2)==0) return;
0257:     // 描画開始
0258:     t = 0.0;
0259:     distance = calc_distance(dx1,dy1,dx2,dy2);
0260:     step = 1.0/(1.5*distance);
0261:     while(t<0.5){
0262:         xp = rint(t*dx2 + (1.0-t)*dx1);
0263:         yp = rint(t*dy2 + (1.0-t)*dy1);
0264:         if(ip_safe(xp,yp,iWidth,iHeight))
0265:             oBuf[XY2PI(xp,yp,iWidth)] = col;
0266:         xp = rint((1.0-t)*dx2 + t*dx1);
0267:         yp = rint((1.0-t)*dy2 + t*dy1);
0268:         if(ip_safe(xp,yp,iWidth,iHeight))
0269:             oBuf[XY2PI(xp,yp,iWidth)] = col;
0270:         t = t + step;
0271:     }
0272: }
0273: //-----------------------------------------------------------------
0274: // 直線と(x=xc)の直線との交点のy座標を求める
0275: //-----------------------------------------------------------------
0276: int croslnxc(int x1,int y1,int x2,int y2,int xc,int *yc)
0277: {
0278:     double wk;
0279:     if(y1 == y2){ *yc = y1; return  1; }
0280:     if(x1 == x2){ *yc = 0;  return -1; }
0281:     if(x1 != x2){
0282:         wk  = (y2-y1)/(x2-x1);
0283:         *yc = rint(wk*(xc-x1)+y1);
0284:         return 1;
0285:     }
0286:     return 0;
0287: }
0288: //-----------------------------------------------------------------
0289: // 直線と(y=yc)の直線との交点のx座標を求める
0290: //-----------------------------------------------------------------
0291: int croslnyc(int x1,int y1,int x2,int y2,int yc,int *xc)
0292: {
0293:     double wk;
0294:     if(x1 == x2){ *xc = x1; return  1; }
0295:     if(y1 == y2){ *xc = 0;  return -1; }
0296:     if(x1 != x2){
0297:         wk  = (y2-y1)/(x2-x1);
0298:         *xc = rint(x1+(yc-y1)/wk);
0299:         return 1;
0300:     }
0301:     return 0;
0302: }
0303: //-----------------------------------------------------------------
0304: // 直線描画領域の2次元クリッピング処理:
0305: //        直線の両端点の座標から実際に描く線分の端点を求める
0306: //-----------------------------------------------------------------
0307: int scrossln(int* x1,int* y1,int* x2,int* y2)
0308: {
0309:     int dx1,dx2,dy1,dy2;
0310:     int i,is,ip,mkp1,mkp2;
0311:     int wk,xc,yc,xw1,xw2,yw1,yw2;
0312:     int xx[2],yy[2],ds1[2],ds2[2];
0313:     int gr_wnx[2],gr_wny[2];
0314:     //--------------------------------------------------
0315:     // 初期化
0316:     //--------------------------------------------------
0317:     dx1 = *x1; dx2 = *x2; dy1 = *y1; dy2 = *y2;
0318:     for(i=0;i<2;i++){
0319:         xx[i] =0; yy[i] =0; ds1[i]=0; ds2[i]=0;
0320:     }
0321:     xw1=gr_wnx[0]=0; xw2=gr_wnx[1]=iWidth;
0322:     yw1=gr_wny[0]=0; yw2=gr_wny[1]=iHeight;
0323:     mkp1=mkp2=0;
0324:     //--------------------------------------------------
0325:     // 直線の端点がウィンドウの枠の内部かどうか
0326:     //--------------------------------------------------
0327:     if(dx1>=xw1 && dx1<=xw2 && dy1>=yw1 && dy1<=yw2){
0328:         *x1  = dx1; *y1 = dy1;
0329:         mkp1 = 1;
0330:     }
0331:     if(dx2>=xw1 && dx2<=xw2 && dy2>=yw1 && dy2<=yw2){
0332:         *x2  = dx2; *y2 = dy2;
0333:         mkp2 = 1;
0334:     }
0335:     //--------------------------------------------------
0336:     // ウィンドウ内であれば終了
0337:     //--------------------------------------------------
0338:     if(mkp1 == 1 && mkp2 == 1) return 1;
0339:     ip = 0;
0340:     //--------------------------------------------------
0341:     // 直線とウィンドウの上下の枠と交差する点を求める
0342:     //--------------------------------------------------
0343:     for(i=0;i<2;i++){
0344:         wk=gr_wnx[i];
0345:         is=croslnxc(dx1,dy1,dx2,dy2,wk,&yc); 
0346:         if(is == 1 && yc>=yw1 && yc<=yw2){
0347:             xx[ip] = wk; yy[ip] = yc;
0348:             ip++;
0349:         }
0350:     }
0351:     //--------------------------------------------------
0352:     // 直線とウィンドウの左右の枠と交差する点を求める
0353:     //--------------------------------------------------
0354:     if(ip<2){
0355:         for(i=0;i<2;i++){
0356:             wk=gr_wny[i];
0357:             is=croslnyc(dx1,dy1,dx2,dy2,wk,&xc); 
0358:             if(is == 1 && xc>=xw1 && xc<=xw2){
0359:                 xx[ip] = xc; yy[ip] = wk;
0360:                 ip++;
0361:             }
0362:         }    
0363:     }
0364:     //--------------------------------------------------
0365:     // 描く直線が枠と交差しない場合は直線の全てが
0366:     // 枠の外側にあるので、描く必要がないことをしめす
0367:     //--------------------------------------------------
0368:     if(ip==0) return 0;
0369:     //--------------------------------------------------
0370:     // 枠と交差する点を描く直線の対応する端点として代入
0371:     //--------------------------------------------------
0372:     for(i=0;i<2;i++){
0373:         ds1[i] = ((xx[i]-dx1)*(xx[i]-dx1)+(yy[i]-dy1)*(yy[i]-dy1));
0374:         ds2[i] = ((xx[i]-dx2)*(xx[i]-dx2)+(yy[i]-dy2)*(yy[i]-dy2));
0375:     }
0376:     if(mkp1 == 0){
0377:         if(ds1[0]<ds1[1]){
0378:             *x1 = xx[0]; *y1 = yy[0];
0379:         }
0380:         if(ds1[0]>ds1[1]){
0381:             *x1 = xx[1]; *y1 = yy[1];
0382:         }
0383:     }
0384:     if(mkp2 == 0){
0385:         if(ds2[0]<ds2[1]){
0386:             *x2 = xx[0]; *y2 = yy[0];
0387:         }
0388:         if(ds2[0]>ds2[1]){
0389:             *x2 = xx[1]; *y2 = yy[1];
0390:         }
0391:     }
0392:     return 1;
0393: }
0394: //-----------------------------------------------------------------
0395: // テンプレート位置の描画[網掛け]
0396: //-----------------------------------------------------------------
0397: void mark_template_area(LPBYTE inBuf,POINT tp,int txsize,int tysize)
0398: {
0399:     int x,y,xstep=5,ystep=5;
0400:     for(y=tp.y;y<tp.y+tysize;y++) for(x=tp.x;x<tp.x+txsize;x++){
0401:         if(ip_safe(x,y,iWidth,iHeight))
0402:             inBuf[XY2PI(x,y,iWidth)] = iWHITE-inBuf[XY2PI(x,y,iWidth)];
0403:     }
0404:     // 網掛け
0405:     for(y=tp.y;y<tp.y+tysize;y+=ystep){
0406:         draw_line(inBuf,tp.x,y,tp.x+txsize,y,175);
0407:     }
0408:     for(x=tp.x;x<tp.x+txsize;x+=xstep){
0409:         draw_line(inBuf,x,tp.y,x,tp.y+tysize,175);
0410:     }
0411: #if 0
0412:     // 囲む
0413:     for(y=tp.y;y<=tp.y+tysize;y+=tysize){
0414:         draw_line(inBuf,tp.x,y,tp.x+txsize,y,0);
0415:     }
0416:     for(x=tp.x;x<=tp.x+txsize;x+=txsize){
0417:         draw_line(inBuf,x,tp.y,x,tp.y+tysize,0);
0418:     }
0419: #endif
0420: }
0421: //-----------------------------------------------------------------
0422: // 画像処理関数
0423: //-----------------------------------------------------------------
0424: //-----------------------------------------------------------------
0425: // 画像のヒストグラムの作成-->iGHistへ
0426: //-----------------------------------------------------------------
0427: void make_histogram(LPBYTE inBuf)
0428: {
0429:     int x,y;
0430:     FillMemory(iGHist,sizeof(UINT)*iMAX_GRAY,0);
0431:     for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++)
0432:         iGHist[inBuf[XY2PI(x,y,iWidth)]]++;
0433: }
0434: //-----------------------------------------------------------------
0435: // 表示用
0436: //-----------------------------------------------------------------
0437: void GrayToColor(LPBYTE iGray,LPBYTE iColor)
0438: {
0439:     int i,x,y;
0440:     int iadd=(4-(iWidth*3)%4);
0441:     // カラー画像へ
0442:     for(y=0;y<iHeight;y++){
0443:         for(x=0;x<iWidth;x++) {
0444:             FillMemory(iColor+x*3+y*iLength,
0445:                        sizeof(BYTE)*3,iGray[XY2PI(x,y,iWidth)]);
0446:         }
0447:         for(i=0;i<iadd;i++)
0448:             iColor[x*3+y*iLength+i] = 0;
0449:     }
0450: }
0451: //-----------------------------------------------------------------
0452: // 濃淡化
0453: //-----------------------------------------------------------------
0454: void toGray(LPBYTE inBuf)
0455: {
0456:     int i,j; BYTE r,g,b,gray;
0457:     FillMemory(iGHist,sizeof(UINT)*512,0);
0458:     // 濃淡化
0459:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
0460:         b=inBuf[XY2PI(j*3,i,iLength)+0];
0461:         g=inBuf[XY2PI(j*3,i,iLength)+1];
0462:         r=inBuf[XY2PI(j*3,i,iLength)+2];
0463:         gray=rgb2gray(r,g,b);
0464:         iGHist[gray]++;
0465:         inBuf[XY2PI(j,i,iWidth)] = gray;
0466:     }
0467:     FillMemory(inBuf+iSize,sizeof(BYTE)*(biSize-iSize),0);
0468: }
0469: void toCGray(LPBYTE inBuf,int csel)
0470: {
0471:     int i,j; BYTE gray,r,g,b;
0472:     FillMemory(iGHist,sizeof(UINT)*512,0);
0473:     // 濃淡化
0474:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
0475:         gray=inBuf[XY2PI(j*3,i,iLength)+csel];
0476:         // RGB成分
0477:         if(csel <= COLOR_B){
0478:             switch(csel){
0479:             case COLOR_R: gray = lpOrgBMP[XY2PI(j*3,i,iLength) + 2]; break;
0480:             case COLOR_G: gray = lpOrgBMP[XY2PI(j*3,i,iLength) + 1]; break;
0481:             case COLOR_B: gray = lpOrgBMP[XY2PI(j*3,i,iLength) + 0]; break;
0482:             }
0483:         } else {
0484:             r = lpOrgBMP[XY2PI(j*3,i,iLength) + 2];
0485:             g = lpOrgBMP[XY2PI(j*3,i,iLength) + 1];
0486:             b = lpOrgBMP[XY2PI(j*3,i,iLength) + 0];
0487:             switch(csel){
0488:             case COLOR_Y:     gray = rgb2y(r,g,b);     break;
0489:             case COLOR_U:     gray = rgb2u(r,g,b);     break;
0490:             case COLOR_V:     gray = rgb2v(r,g,b);     break;
0491:             case COLOR_RHO:   gray = rgb2rho(r,g,b);   break;
0492:             case COLOR_THETA: gray = rgb2theta(r,g,b); break;
0493:             }
0494:         }
0495:         iGHist[gray]++;
0496:         inBuf[j+i*iWidth] = gray;
0497:     }
0498:     FillMemory(inBuf+iSize,sizeof(BYTE)*(biSize-iSize),0);
0499: }
0500: //-----------------------------------------------------------------
0501: // 濃淡化
0502: //-----------------------------------------------------------------
0503: void toGray()
0504: {
0505:     int i,j; BYTE r,g,b,gray;
0506:     FillMemory(iGHist,sizeof(UINT)*512,0);
0507:     // 濃淡化
0508:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
0509:         b=lpOrgBMP[XY2PI(j*3,i,iLength)+0];
0510:         g=lpOrgBMP[XY2PI(j*3,i,iLength)+1];
0511:         r=lpOrgBMP[XY2PI(j*3,i,iLength)+2];
0512:         gray=rgb2gray(r,g,b);
0513:         iGHist[gray]++;
0514:         FillMemory(lpBMP+XY2PI(j*3,i,iLength),sizeof(BYTE)*3,gray);
0515:     }
0516: }
0517: //-----------------------------------------------------------------
0518: // 濃淡[R,G,B]画像の取得
0519: //-----------------------------------------------------------------
0520: LPBYTE GetGray()
0521: {
0522:     int i,j; BYTE r,g,b,gray;
0523:     LPBYTE iGray=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iSize);
0524:     FillMemory(iGHist,sizeof(UINT)*512,0);
0525:     // 濃淡化
0526:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
0527:         b=lpOrgBMP[XY2PI(j*3,i,iLength)+0];
0528:         g=lpOrgBMP[XY2PI(j*3,i,iLength)+1];
0529:         r=lpOrgBMP[XY2PI(j*3,i,iLength)+2];
0530:         gray=rgb2gray(r,g,b);
0531:         if(gray>iWHITE) gray=iWHITE;
0532:         iGHist[gray]++;
0533:         iGray[j+i*iWidth] = gray;
0534:     }
0535:     return iGray;
0536: }
0537: LPBYTE GetColor(int csel)
0538: {
0539:     int i,j; BYTE r,g,b,gray;
0540:     LPBYTE iColor=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iSize);
0541:     FillMemory(iGHist,sizeof(UINT)*512,0);
0542:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++) {
0543:         // RGB成分
0544:         if(csel <= COLOR_B){
0545:             switch(csel){
0546:             case COLOR_R: gray = lpOrgBMP[XY2PI(j*3,i,iLength) + 2]; break;
0547:             case COLOR_G: gray = lpOrgBMP[XY2PI(j*3,i,iLength) + 1]; break;
0548:             case COLOR_B: gray = lpOrgBMP[XY2PI(j*3,i,iLength) + 0]; break;
0549:             }
0550:         } else {
0551:             r = lpOrgBMP[XY2PI(j*3,i,iLength) + 2];
0552:             g = lpOrgBMP[XY2PI(j*3,i,iLength) + 1];
0553:             b = lpOrgBMP[XY2PI(j*3,i,iLength) + 0];
0554:             switch(csel){
0555:             case COLOR_Y:     gray = rgb2y(r,g,b);     break;
0556:             case COLOR_U:     gray = rgb2u(r,g,b);     break;
0557:             case COLOR_V:     gray = rgb2v(r,g,b);     break;
0558:             case COLOR_RHO:   gray = rgb2rho(r,g,b);   break;
0559:             case COLOR_THETA: gray = rgb2theta(r,g,b); break;
0560:             }
0561:         }
0562:         iColor[j+i*iWidth] = gray;
0563:         iGHist[gray]++;
0564:     }
0565:     return iColor;
0566: }
0567: //-----------------------------------------------------------------
0568: // 線形補間法による画像サイズの縮小・拡大
0569: //-----------------------------------------------------------------
0570: void affine_transform(LPBYTE inBuf,int intp_opt,
0571:                       double zx,double zy,
0572:                       double deg,double px,double py)
0573: // zx,zy: 倍率x,y
0574: // deg  : 回転角(degree)
0575: // px,py: 移動量x,y
0576: {
0577:     int i,j,xc=iWidth/2,yc=iHeight/2;
0578:     double x,y,u,v,r,c,s;
0579:     LPBYTE ib;
0580:     // 画像確保
0581:     ib=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iSize);
0582:     CopyMemory(ib,inBuf,sizeof(BYTE)*iSize);
0583:     FillMemory(inBuf,sizeof(BYTE)*iSize,0);
0584:     // パラメータ計算
0585:     r = deg2rad(deg); c = cos(r); s = sin(r);
0586:     // アフィン変換
0587:     for(i=-yc;i<yc;i++) for(j=-xc;j<xc;j++){
0588:         v = i-py;         u = j-px;
0589:         y = (u*s+v*c)/zy; x = (u*c-v*s)/zx;
0590:         // 補間形式の選択
0591:         inBuf[XY2PI(j+xc,i+yc,iWidth)] =
0592:             image_interpolation(ib,intp_opt,x,y,xc,yc);
0593:     }
0594:     GlobalFree(ib);
0595: }
0596: void c_affine_transform(LPBYTE inCBuf,int intp_opt,
0597:                         double zx,double zy,
0598:                         double deg,double px,double py)
0599: // zx,zy: 倍率x,y
0600: // deg  : 回転角(degree)
0601: // px,py: 移動量x,y
0602: {
0603:     int i,j,xc=iWidth/2,yc=iHeight/2;
0604:     double x,y,u,v,r,c,s;
0605:     CPIXEL rgb;
0606:     LPBYTE icb;
0607:     // 画像確保
0608:     icb=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*biSize);
0609:     CopyMemory(icb,inCBuf,sizeof(BYTE)*biSize);
0610:     FillMemory(inCBuf,sizeof(BYTE)*biSize,0);
0611:     // パラメータ計算
0612:     r = deg2rad(deg); c = cos(r); s = sin(r);
0613:     // アフィン変換
0614:     for(i=-yc;i<yc;i++) for(j=-xc;j<xc;j++){
0615:         v = i-py;         u = j-px;
0616:         y = (u*s+v*c)/zy; x = (u*c-v*s)/zx;
0617:         // 補間形式の選択
0618:         rgb = c_image_interpolation(icb,intp_opt,x,y,xc,yc);
0619:         inCBuf[XY2PI((j+xc)*3,i+yc,iLength) + 0] = rgb.b;
0620:         inCBuf[XY2PI((j+xc)*3,i+yc,iLength) + 1] = rgb.g;
0621:         inCBuf[XY2PI((j+xc)*3,i+yc,iLength) + 2] = rgb.r;
0622:     }
0623:     GlobalFree(icb);
0624: }
0625: //-----------------------------------------------------------------
0626: // 画像の補間
0627: //-----------------------------------------------------------------
0628: BYTE image_interpolation(LPBYTE ib,int intp_opt,
0629:                          double x,double y,int xc,int yc)
0630: {
0631:     int i,m,n,gray;
0632:     // for linear
0633:     BYTE p1,p2,p3,p4; double p,q;
0634:     // for bicubic
0635:     double c[8],sum;
0636:     // point of interpolation
0637:     if(intp_opt>INTP_NN){
0638:         if(y>0) m=(int)y; else m=(int)(y-1);
0639:         if(x>0) n=(int)x; else n=(int)(x-1);
0640:     } else {
0641:         m = rint(y); n = rint(x);
0642:     }
0643:     // out of area
0644:     if(!ip_safe(n+xc,m+yc,iWidth,iHeight))
0645:         return 0;
0646:     // interpolation
0647:     switch(intp_opt){
0648:     case INTP_NN: // nearest neighbour
0649:         gray = ib[XY2PI(n+xc,m+yc,iWidth)];
0650:         break;
0651:     case INTP_LN: // linear
0652:         if(!ip_safe(n+xc+1,m+yc+1,iWidth,iHeight))
0653:             return 0;
0654:         // 線形補間
0655:         q = y-m; p = x-n;
0656:         p1 = ib[XY2PI(n+xc  ,m+yc  ,iWidth)];
0657:         p2 = ib[XY2PI(n+xc+1,m+yc  ,iWidth)];
0658:         p3 = ib[XY2PI(n+xc  ,m+yc+1,iWidth)];
0659:         p4 = ib[XY2PI(n+xc+1,m+yc+1,iWidth)];
0660:         gray = rint((1.0-q)*((1.0-p)*p1+p*p2) + q*((1.0-p)*p3+p*p4));
0661:         break;
0662:     case INTP_BCC: // bicubic
0663:         if(!ip_safe(n+xc+2,m+yc+2,iWidth,iHeight) ||
0664:            !ip_safe(n+xc-1,m+yc-1,iWidth,iHeight))
0665:             return 0;
0666:         // 16個の格子点を用いた補間(3次補間)
0667:         c[0]=(m-1)-y; c[1]=m-y;
0668:         c[2]=(m+1)-y; c[3]=(m+2)-y;
0669:         c[4]=(n-1)-x; c[5]=n-x;
0670:         c[6]=(n+1)-x; c[7]=(n+2)-x;
0671:         // 補間関数
0672:         for(i=0;i<8;i++){
0673:             if(c[i]<0) c[i]=-c[i];
0674:             if(0<=c[i] && c[i]<1)
0675:                 c[i]=1-2*c[i]*c[i]+c[i]*c[i]*c[i];
0676:             else if(1<=c[i] && c[i]<2)
0677:                 c[i]=4-8*c[i]+5*c[i]*c[i]-c[i]*c[i]*c[i];
0678:             else if(2<=c[i]) c[i]=0;
0679:         }
0680:         // 補間濃度
0681:         sum = 0;
0682:         sum += c[0]*c[4]*ib[XY2PI(n+xc-1,m+yc-1,iWidth)];
0683:         sum += c[0]*c[5]*ib[XY2PI(n+xc  ,m+yc-1,iWidth)];
0684:         sum += c[0]*c[6]*ib[XY2PI(n+xc+1,m+yc-1,iWidth)];
0685:         sum += c[0]*c[7]*ib[XY2PI(n+xc+2,m+yc-1,iWidth)];
0686:         sum += c[1]*c[4]*ib[XY2PI(n+xc-1,m+yc  ,iWidth)];
0687:         sum += c[1]*c[5]*ib[XY2PI(n+xc  ,m+yc  ,iWidth)];
0688:         sum += c[1]*c[6]*ib[XY2PI(n+xc+1,m+yc  ,iWidth)];
0689:         sum += c[1]*c[7]*ib[XY2PI(n+xc+2,m+yc  ,iWidth)];
0690:         sum += c[2]*c[4]*ib[XY2PI(n+xc-1,m+yc+1,iWidth)];
0691:         sum += c[2]*c[5]*ib[XY2PI(n+xc  ,m+yc+1,iWidth)];
0692:         sum += c[2]*c[6]*ib[XY2PI(n+xc+1,m+yc+1,iWidth)];
0693:         sum += c[2]*c[7]*ib[XY2PI(n+xc+2,m+yc+1,iWidth)];
0694:         sum += c[3]*c[4]*ib[XY2PI(n+xc-1,m+yc+2,iWidth)];
0695:         sum += c[3]*c[5]*ib[XY2PI(n+xc  ,m+yc+2,iWidth)];
0696:         sum += c[3]*c[6]*ib[XY2PI(n+xc+1,m+yc+2,iWidth)];
0697:         sum += c[3]*c[7]*ib[XY2PI(n+xc+2,m+yc+2,iWidth)];
0698:         if(sum<0) sum = 0; if(sum>iWHITE) sum = iWHITE;
0699:         gray = rint(sum);
0700:         break;
0701:     }
0702:     if(gray<0) gray=0; if(gray>iWHITE) gray=iWHITE;
0703:     return (BYTE)gray;
0704: }
0705: CPIXEL c_image_interpolation(LPBYTE icb,int intp_opt,
0706:                            double x,double y,int xc,int yc)
0707: {
0708:     CPIXEL rgb={0,0,0};
0709:     int i,m,n,gray,r,g,b;
0710:     // for linear
0711:     BYTE p1,p2,p3,p4; double p,q;
0712:     // for bicubic
0713:     double c[8],sum;
0714:     // point of interpolation
0715:     if(intp_opt>INTP_NN){
0716:         if(y>0) m=(int)y; else m=(int)(y-1);
0717:         if(x>0) n=(int)x; else n=(int)(x-1);
0718:     } else {
0719:         m = rint(y); n = rint(x);
0720:     }
0721:     // out of area
0722:     if(!ip_safe(n+xc,m+yc,iWidth,iHeight))
0723:         return rgb;
0724:     // interpolation
0725:     switch(intp_opt){
0726:     case INTP_NN: // nearest neighbour
0727:         r = icb[XY2PI((n+xc)*3,m+yc,iLength)+2];
0728:         g = icb[XY2PI((n+xc)*3,m+yc,iLength)+1];
0729:         b = icb[XY2PI((n+xc)*3,m+yc,iLength)+0];
0730:         break;
0731:     case INTP_LN: // linear
0732:         if(!ip_safe(n+xc+1,m+yc+1,iWidth,iHeight))
0733:             return rgb;
0734:         // 線形補間
0735:         for(i=0;i<3;i++){
0736:             q = y-m; p = x-n;
0737:             p1 = icb[XY2PI((n+xc  )*3,m+yc  ,iLength)+i];
0738:             p2 = icb[XY2PI((n+xc+1)*3,m+yc  ,iLength)+i];
0739:             p3 = icb[XY2PI((n+xc  )*3,m+yc+1,iLength)+i];
0740:             p4 = icb[XY2PI((n+xc+1)*3,m+yc+1,iLength)+i];
0741:             gray = rint((1.0-q)*((1.0-p)*p1+p*p2) + q*((1.0-p)*p3+p*p4));
0742:             switch(i){
0743:             case 0: b = gray; break;
0744:             case 1: g = gray; break;
0745:             case 2: r = gray; break;
0746:             }
0747:         }
0748:         break;
0749:     case INTP_BCC: // bicubic
0750:         if(!ip_safe(n+xc+2,m+yc+2,iWidth,iHeight) ||
0751:            !ip_safe(n+xc-1,m+yc-1,iWidth,iHeight))
0752:             return rgb;
0753:         // 16個の格子点を用いた補間(3次補間)
0754:         c[0]=(m-1)-y; c[1]=m-y;
0755:         c[2]=(m+1)-y; c[3]=(m+2)-y;
0756:         c[4]=(n-1)-x; c[5]=n-x;
0757:         c[6]=(n+1)-x; c[7]=(n+2)-x;
0758:         // 補間関数
0759:         for(i=0;i<8;i++){
0760:             if(c[i]<0) c[i]=-c[i];
0761:             if(0<=c[i] && c[i]<1)
0762:                 c[i]=1-2*c[i]*c[i]+c[i]*c[i]*c[i];
0763:             else if(1<=c[i] && c[i]<2)
0764:                 c[i]=4-8*c[i]+5*c[i]*c[i]-c[i]*c[i]*c[i];
0765:             else if(2<=c[i]) c[i]=0;
0766:         }
0767:         // 補間濃度
0768:         for(i=0;i<3;i++){
0769:             sum = 0;
0770:             sum += c[0]*c[4]*icb[XY2PI((n+xc-1)*3,m+yc-1,iLength)+i];
0771:             sum += c[0]*c[5]*icb[XY2PI((n+xc  )*3,m+yc-1,iLength)+i];
0772:             sum += c[0]*c[6]*icb[XY2PI((n+xc+1)*3,m+yc-1,iLength)+i];
0773:             sum += c[0]*c[7]*icb[XY2PI((n+xc+2)*3,m+yc-1,iLength)+i];
0774:             sum += c[1]*c[4]*icb[XY2PI((n+xc-1)*3,m+yc  ,iLength)+i];
0775:             sum += c[1]*c[5]*icb[XY2PI((n+xc  )*3,m+yc  ,iLength)+i];
0776:             sum += c[1]*c[6]*icb[XY2PI((n+xc+1)*3,m+yc  ,iLength)+i];
0777:             sum += c[1]*c[7]*icb[XY2PI((n+xc+2)*3,m+yc  ,iLength)+i];
0778:             sum += c[2]*c[4]*icb[XY2PI((n+xc-1)*3,m+yc+1,iLength)+i];
0779:             sum += c[2]*c[5]*icb[XY2PI((n+xc  )*3,m+yc+1,iLength)+i];
0780:             sum += c[2]*c[6]*icb[XY2PI((n+xc+1)*3,m+yc+1,iLength)+i];
0781:             sum += c[2]*c[7]*icb[XY2PI((n+xc+2)*3,m+yc+1,iLength)+i];
0782:             sum += c[3]*c[4]*icb[XY2PI((n+xc-1)*3,m+yc+2,iLength)+i];
0783:             sum += c[3]*c[5]*icb[XY2PI((n+xc  )*3,m+yc+2,iLength)+i];
0784:             sum += c[3]*c[6]*icb[XY2PI((n+xc+1)*3,m+yc+2,iLength)+i];
0785:             sum += c[3]*c[7]*icb[XY2PI((n+xc+2)*3,m+yc+2,iLength)+i];
0786:             if(sum<0) sum = 0; if(sum>iWHITE) sum = iWHITE;
0787:             gray = rint(sum);
0788:             switch(i){
0789:             case 0: b = gray; break;
0790:             case 1: g = gray; break;
0791:             case 2: r = gray; break;
0792:             }
0793:         }
0794:         break;
0795:     }
0796:     if(r<0) r=0; if(r>iWHITE) r=iWHITE;
0797:     if(g<0) g=0; if(g>iWHITE) g=iWHITE;
0798:     if(b<0) b=0; if(b>iWHITE) b=iWHITE;
0799:     rgb.r = r; rgb.g = g; rgb.b = b;
0800:     return rgb;
0801: }
0802: //-----------------------------------------------------------------
0803: // 最近傍法による画像サイズの縮小・拡大[nearest neighbour]
0804: //-----------------------------------------------------------------
0805: void nn_scale(LPBYTE inBuf,double zx,double zy)
0806: {
0807:     int i,j,m,n;
0808:     int xsize=(zx>1.0)?iWidth : rint(iWidth*zx);
0809:     LPBYTE ib;
0810:     // 画像確保
0811:     ib=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iSize);
0812:     CopyMemory(ib,inBuf,sizeof(BYTE)*iSize);
0813:     FillMemory(inBuf,sizeof(BYTE)*iSize,0);
0814:     // 変換
0815:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++){
0816:         m = rint(i/zy); n = rint(j/zx);
0817:         if(ip_safe(n,m,iWidth,iHeight))
0818:             inBuf[XY2PI(j,i,xsize)] = ib[XY2PI(n,m,iWidth)];
0819:         else
0820:             inBuf[XY2PI(j,i,xsize)] = 0;
0821:     }
0822:     GlobalFree(ib);
0823: }
0824: //-----------------------------------------------------------------
0825: // 線形補間法による画像サイズの縮小・拡大
0826: //-----------------------------------------------------------------
0827: void linear_scale(LPBYTE inBuf,double zx,double zy)
0828: {
0829:     int i,j,m,n;
0830:     int p1,p2,p3,p4,d;
0831:     int xsize=(zx>1.0)?iWidth:rint(iWidth*zx);
0832:     double x,y,p,q;
0833:     LPBYTE ib;
0834:     // 画像確保
0835:     ib=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iSize);
0836:     CopyMemory(ib,inBuf,sizeof(BYTE)*iSize);
0837:     FillMemory(inBuf,sizeof(BYTE)*iSize,0);
0838:     // 変換
0839:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++){
0840:         y = i/zy;     x = j/zx;
0841:         m = (int)(y);  n = (int)(x);
0842:         q = y-m;      p = x-n;
0843:         if(ip_safe(n,m,iWidth,iHeight) && 
0844:             ip_safe(n+1,m+1,iWidth,iHeight)){
0845:             p1 = ib[XY2PI(n  ,m  ,iWidth)];
0846:             p2 = ib[XY2PI(n+1,m  ,iWidth)];
0847:             p3 = ib[XY2PI(n  ,m+1,iWidth)];
0848:             p4 = ib[XY2PI(n+1,m+1,iWidth)];
0849:             d = rint((1.0-q)*((1.0-p)*p1+p*p2) + q*((1.0-p)*p3+p*p4));
0850:             if(d<0) d=0; if(d>iWHITE) d=iWHITE;
0851:         } else d = 0;
0852:         inBuf[XY2PI(j,i,xsize)] = d;
0853:     }
0854:     GlobalFree(ib);
0855: }
0856: //-----------------------------------------------------------------
0857: // バイキュービック[3次補間]法による画像の拡大・縮小
0858: //-----------------------------------------------------------------
0859: void bcc_scale(LPBYTE inBuf,double zx,double zy)
0860: {
0861:     int i,j,k,m,n,d;
0862:     int xsize=(zx>1.0)?iWidth : rint(iWidth*zx);
0863:     double x,y,c[8],sum;
0864:     LPBYTE ib;
0865:     // 画像確保
0866:     ib=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iSize);
0867:     CopyMemory(ib,inBuf,sizeof(BYTE)*iSize);
0868:     FillMemory(inBuf,sizeof(BYTE)*iSize,0);
0869:     // 変換
0870:     for(i=0;i<iHeight;i++) for(j=0;j<iWidth;j++){
0871:         y = i/zy;     x = j/zx;
0872:         m = (int)(y); n = (int)(x);
0873:         if(ip_safe(n-1,m-1,iWidth,iHeight) && 
0874:             ip_safe(n+2,m+2,iWidth,iHeight)){
0875:             // 16個の格子点を用いた補間(3次補間)
0876:             c[0]=(m-1)-y; c[1]=m-y;
0877:             c[2]=(m+1)-y; c[3]=(m+2)-y;
0878:             c[4]=(n-1)-x; c[5]=n-x;
0879:             c[6]=(n+1)-x; c[7]=(n+2)-x;
0880:             // 補間関数
0881:             for(k=0;k<8;k++){
0882:                 if(c[k]<0) c[k]=-c[k];
0883:                 if(0<=c[k] && c[k]<1)
0884:                     c[k]=1-2*c[k]*c[k]+c[k]*c[k]*c[k];
0885:                 else if(1<=c[k] && c[k]<2)
0886:                     c[k]=4-8*c[k]+5*c[k]*c[k]-c[k]*c[k]*c[k];
0887:                 else if(2<=c[k]) c[k]=0;
0888:             }
0889:             // 補間濃度
0890:             sum = 0;
0891:             sum += c[0]*c[4]*ib[XY2PI(n-1,m-1,iWidth)];
0892:             sum += c[0]*c[5]*ib[XY2PI(n  ,m-1,iWidth)];
0893:             sum += c[0]*c[6]*ib[XY2PI(n+1,m-1,iWidth)];
0894:             sum += c[0]*c[7]*ib[XY2PI(n+2,m-1,iWidth)];
0895:             sum += c[1]*c[4]*ib[XY2PI(n-1,m  ,iWidth)];
0896:             sum += c[1]*c[5]*ib[XY2PI(n  ,m  ,iWidth)];
0897:             sum += c[1]*c[6]*ib[XY2PI(n+1,m  ,iWidth)];
0898:             sum += c[1]*c[7]*ib[XY2PI(n+2,m  ,iWidth)];
0899:             sum += c[2]*c[4]*ib[XY2PI(n-1,m+1,iWidth)];
0900:             sum += c[2]*c[5]*ib[XY2PI(n  ,m+1,iWidth)];
0901:             sum += c[2]*c[6]*ib[XY2PI(n+1,m+1,iWidth)];
0902:             sum += c[2]*c[7]*ib[XY2PI(n+2,m+1,iWidth)];
0903:             sum += c[3]*c[4]*ib[XY2PI(n-1,m+2,iWidth)];
0904:             sum += c[3]*c[5]*ib[XY2PI(n  ,m+2,iWidth)];
0905:             sum += c[3]*c[6]*ib[XY2PI(n+1,m+2,iWidth)];
0906:             sum += c[3]*c[7]*ib[XY2PI(n+2,m+2,iWidth)];
0907:             if(sum<0) sum = 0; if(sum>iWHITE) sum = iWHITE;
0908:             d = rint(sum);
0909:         } else d=0;
0910:         inBuf[XY2PI(j,i,xsize)] = d;
0911:     }
0912: }
0913: //-----------------------------------------------------------------
0914: // 平均画素法による画像サイズの縮小
0915: // [兼ローパスフィルタ]
0916: //-----------------------------------------------------------------
0917: void sqm_scale(LPBYTE inBuf,double zx,double zy)
0918: {
0919:     int i,x,y,x1,x2,y1,y2;
0920:     int lcm_x,lcm_y,p_count,meanp;
0921:     int xsize,ysize,oxsize,oysize;
0922:     LPBYTE oneline;
0923:     // 画像サイズ[偶数に調節]
0924:     xsize = oxsize = rint(iWidth*zx);
0925:     ysize = oysize = rint(iHeight*zy);
0926:     if(xsize%2) xsize--; if(ysize%2) ysize--;
0927:     // 最小公倍数の計算
0928:     lcm_x = lcm(iWidth ,xsize);
0929:     lcm_y = lcm(iHeight,ysize);
0930:     x1 = lcm_x / iWidth; y1 = lcm_y / iHeight;
0931:     x2 = lcm_x / xsize;  y2 = lcm_y / ysize;
0932:     // 描画サイズは元のまま
0933:     if(xsize>iWidth ) xsize = oxsize = iWidth;
0934:     if(ysize>iHeight) ysize = oysize = iHeight;
0935:     //--------------------------------------------------
0936:     // x 方向
0937:     //--------------------------------------------------
0938:     oneline=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iWidth*x1);
0939:     for(y=0;y<iHeight;y++){
0940:         for(x=0;x<iWidth;x++)
0941:             for(i=0;i<x1;i++)
0942:                 oneline[x*x1+i] = inBuf[XY2PI(x,y,iWidth)];
0943:         for(x=0;x<xsize;x++) {
0944:             meanp = p_count = 0;
0945:             for(i=0;i<x2;i++){
0946:                 if(x*x2+i < x1*iWidth){
0947:                     p_count ++;
0948:                     meanp += oneline[x*x2+i];
0949:                 }
0950:             }
0951:             if(p_count) meanp /= p_count;
0952:             inBuf[XY2PI(x,y,oxsize)] = meanp;
0953:         }
0954:         for(x=xsize;x<iWidth;x++)
0955:             inBuf[XY2PI(x,y,oxsize)] = 0;
0956:     }
0957:     GlobalFree(oneline);
0958:     //--------------------------------------------------
0959:     // y 方向
0960:     //--------------------------------------------------
0961:     oneline=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iHeight*y1);
0962:     for(x=0;x<xsize;x++){
0963:         for(y=0;y<iHeight;y++)
0964:             for(i=0;i<y1;i++)
0965:                 oneline[y*y1+i] = inBuf[XY2PI(x,y,oxsize)];
0966:         for(y=0;y<ysize;y++) {
0967:             meanp = p_count = 0;
0968:             for(i=0;i<y2;i++){
0969:                 if(y*y2+i < y1*iHeight){
0970:                     p_count ++;
0971:                     meanp += oneline[y*y2+i];
0972:                 }
0973:             }
0974:             if(p_count) meanp /= p_count;
0975:             inBuf[XY2PI(x,y,oxsize)] = meanp;
0976:         }
0977:         for(y=ysize;y<iHeight;y++)
0978:             inBuf[XY2PI(x,y,oxsize)] = 0;
0979:     }
0980:     GlobalFree(oneline);
0981: }
0982: void c_sqm_scale(LPBYTE inBuf,double zx,double zy)
0983: {
0984:     int i,x,y,x1,x2,y1,y2;
0985:     int lcm_x,lcm_y,p_count,meanp[3];
0986:     int bxsize,xsize,ysize,oxsize,oysize;
0987:     LPBYTE oneline;
0988:     // 画像サイズ[偶数に調節]
0989:     xsize = oxsize = rint(iWidth*zx);
0990:     ysize = oysize = rint(iHeight*zy);
0991:     if(xsize%2) xsize--; if(ysize%2) ysize--;
0992:     // 最小公倍数の計算
0993:     lcm_x = lcm(iWidth ,xsize);
0994:     lcm_y = lcm(iHeight,ysize);
0995:     x1 = lcm_x / iWidth; y1 = lcm_y / iHeight;
0996:     x2 = lcm_x / xsize;  y2 = lcm_y / ysize;
0997:     // 描画サイズは元のまま
0998:     if(xsize>iWidth ) xsize = oxsize = iWidth;
0999:     if(ysize>iHeight) ysize = oysize = iHeight;
1000:     // ビットマップ用サイズ
1001:     if((oxsize*3)%4==0) bxsize = oxsize*3;
1002:     else bxsize = oxsize*3+(4-(oxsize*3)%4);
1003:     //--------------------------------------------------
1004:     // x 方向
1005:     //--------------------------------------------------
1006:     oneline=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iLength*x1);
1007:     for(y=0;y<iHeight;y++){
1008:         for(x=0;x<iWidth;x++)
1009:             for(i=0;i<x1;i++){
1010:                 oneline[(x*x1+i)*3+0] = inBuf[XY2PI(x*3,y,iLength)+0];
1011:                 oneline[(x*x1+i)*3+1] = inBuf[XY2PI(x*3,y,iLength)+1];
1012:                 oneline[(x*x1+i)*3+2] = inBuf[XY2PI(x*3,y,iLength)+2];
1013:             }
1014:         for(x=0;x<xsize;x++) {
1015:             p_count = 0;
1016:             for(i=0;i<3;i++) meanp[i] = 0;
1017:             for(i=0;i<x2;i++){
1018:                 if((x*x2+i)*3 < x1*iLength){
1019:                     p_count ++;
1020:                     meanp[0] += oneline[(x*x2+i)*3+0];
1021:                     meanp[1] += oneline[(x*x2+i)*3+1];
1022:                     meanp[2] += oneline[(x*x2+i)*3+2];
1023:                 }
1024:             }
1025:             if(p_count) {
1026:                 meanp[0] /= p_count;
1027:                 meanp[1] /= p_count;
1028:                 meanp[2] /= p_count;
1029:             }
1030:             inBuf[XY2PI(x*3,y,bxsize)+0] = meanp[0];
1031:             inBuf[XY2PI(x*3,y,bxsize)+1] = meanp[1];
1032:             inBuf[XY2PI(x*3,y,bxsize)+2] = meanp[2];
1033:         }
1034:         for(x=xsize*3;x<bxsize;x++)
1035:             inBuf[XY2PI(x,y,bxsize)] = 0;
1036:     }
1037:     GlobalFree(oneline);
1038:     //--------------------------------------------------
1039:     // y 方向
1040:     //--------------------------------------------------
1041:     oneline=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iHeight*y1*3);
1042:     for(x=0;x<xsize;x++){
1043:         for(y=0;y<iHeight;y++)
1044:             for(i=0;i<y1;i++){
1045:                 oneline[(y*y1+i)*3+0] = inBuf[XY2PI(x*3,y,bxsize)+0];
1046:                 oneline[(y*y1+i)*3+1] = inBuf[XY2PI(x*3,y,bxsize)+1];
1047:                 oneline[(y*y1+i)*3+2] = inBuf[XY2PI(x*3,y,bxsize)+2];
1048:             }
1049:         for(y=0;y<ysize;y++) {
1050:             for(i=0;i<3;i++) meanp[i] = 0;
1051:             p_count = 0;
1052:             for(i=0;i<y2;i++){
1053:                 if((y*y2+i)*3 < y1*iHeight*3){
1054:                     p_count ++;
1055:                     meanp[0] += oneline[(y*y2+i)*3+0];
1056:                     meanp[1] += oneline[(y*y2+i)*3+1];
1057:                     meanp[2] += oneline[(y*y2+i)*3+2];
1058:                 }
1059:             }
1060:             if(p_count){
1061:                 meanp[0] /= p_count;
1062:                 meanp[1] /= p_count;
1063:                 meanp[2] /= p_count;
1064:             }
1065:             inBuf[XY2PI(x*3,y,bxsize)+0] = meanp[0];
1066:             inBuf[XY2PI(x*3,y,bxsize)+1] = meanp[1];
1067:             inBuf[XY2PI(x*3,y,bxsize)+2] = meanp[2];
1068:         }
1069:         for(y=ysize;y<iHeight;y++) {
1070:             inBuf[XY2PI(x*3,y,bxsize)+0] = 0;
1071:             inBuf[XY2PI(x*3,y,bxsize)+1] = 0;
1072:             inBuf[XY2PI(x*3,y,bxsize)+2] = 0;
1073:         }
1074:     }
1075:     GlobalFree(oneline);
1076: }
1077: //-----------------------------------------------------------------
1078: // OR 処理
1079: //-----------------------------------------------------------------
1080: void IPfunc_OR(LPBYTE iDst,LPBYTE iAdd)
1081: {
1082:     int x,y;
1083:     for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++) {
1084:         iDst[XY2PI(x,y,iWidth)] = (iDst[XY2PI(x,y,iWidth)]  |
1085:                                    iAdd[XY2PI(x,y,iWidth)]) ? iWHITE:iBLACK;
1086:     }
1087: }
1088: //-----------------------------------------------------------------
1089: // メディアンフィルタ
1090: //-----------------------------------------------------------------
1091: void IPfunc_median(LPBYTE inBuf)
1092: {
1093:     int i,x,y,px,py;
1094:     BYTE c[9];
1095:     LPBYTE ib=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iSize);
1096:     CopyMemory(ib,inBuf,sizeof(BYTE)*iSize);
1097:     // フィルタリング開始
1098:     for(y=1;y<iHeight-1;y++) for(x=1;x<iWidth-1;x++){
1099:         for(i=0;i<8;i++){
1100:             px = x+offset8[i].x;
1101:             py = y+offset8[i].y;
1102:             c[i] = ib[XY2PI(px,py,iWidth)];
1103:         }
1104:         inBuf[XY2PI(x,y,iWidth)] = median(c);
1105:     }
1106:     GlobalFree(ib);
1107: }
1108: BYTE median(BYTE c[9])
1109: {
1110:     int i,j;
1111:     for(j=0;j<8;j++) for(i=0;i<8;i++){
1112:         if(c[i+1]<c[i]) swapv(c[i],c[i+1]);
1113:     }
1114:     return c[4];
1115: }
1116: //-----------------------------------------------------------------
1117: // 組織的ディザ法によるディザ画像の作成
1118: //-----------------------------------------------------------------
1119: void toDither(LPBYTE inBuf)
1120: {
1121:     static int DITHER_BSZ = 4;  // ブロックの画素数
1122:     static int DITHER_NL  = 16; // 擬似階調数(=4^2)
1123:     double width;               // 16段階画像の階調値の単位幅
1124:     BYTE new_gray;              // 新しい階調(16階調での値)
1125:     int x_block,y_block;        // 横・縦のブロック数
1126:     int x,y,i,j,m,n,px,py;
1127:     static int dither_matrix[4][4]={ // Bayer 型ディザ行列
1128:         { 0, 8, 2,10},
1129:         {12, 4,14, 6},
1130:         { 3,11, 1, 9},
1131:         {15, 7,13, 5}
1132:     };
1133:     //--------------------------------------------------
1134:     // 16階調の画像の作成
1135:     //--------------------------------------------------
1136:     width = iWHITE/(double)DITHER_NL;
1137:     for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++){
1138:         new_gray=rint(inBuf[XY2PI(x,y,iWidth)]/width);
1139:         if(new_gray > DITHER_NL-1)
1140:             new_gray = DITHER_NL-1;
1141:         inBuf[XY2PI(x,y,iWidth)] = new_gray;
1142:     }
1143:     //--------------------------------------------------
1144:     // ディザ画像の作成
1145:     //--------------------------------------------------
1146:     x_block=iWidth  / DITHER_BSZ;  // 横のブロック数
1147:     y_block=iHeight / DITHER_BSZ;  // 縦のブロック数
1148:     if(iWidth  % DITHER_BSZ) x_block++;
1149:     if(iHeight % DITHER_BSZ) y_block++;
1150:     for(i=0;i<y_block;i++) for(j=0;j<x_block;j++){
1151:         x=j*DITHER_BSZ;
1152:         y=i*DITHER_BSZ;
1153:         for(m=0;m<DITHER_BSZ;m++) for(n=0;n<DITHER_BSZ;n++){
1154:             px=x+n; py=y+m;
1155:             if(ip_safe(px,py,iWidth,iHeight)){
1156:                 if(inBuf[XY2PI(px,py,iWidth)] <= dither_matrix[m][n])
1157:                     inBuf[XY2PI(px,py,iWidth)]=0;
1158:                 else inBuf[XY2PI(px,py,iWidth)]=iWHITE;
1159:             }
1160:         }
1161:     }
1162: }
1163: //-----------------------------------------------------------------
1164: // 画素の階調分布に対して線形変換
1165: //-----------------------------------------------------------------
1166: void linear_transform(LPBYTE inBuf)
1167: {
1168:     int x,y,minv,maxv; BYTE gray;
1169:     // 階調値の最小値,最大値を求める
1170:     minv = 10000;  maxv = 0;
1171:     for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++){
1172:         if(inBuf[XY2PI(x,y,iWidth)]<minv) minv=inBuf[XY2PI(x,y,iWidth)];
1173:         if(inBuf[XY2PI(x,y,iWidth)]>maxv) maxv=inBuf[XY2PI(x,y,iWidth)];
1174:     }
1175:     // 階調を線形変換して image2[y][x] に代入
1176:     for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++){
1177:         gray = rint(iWHITE*(inBuf[XY2PI(x,y,iWidth)]-minv)/
1178:                     (double)(maxv-minv));
1179:         inBuf[XY2PI(x,y,iWidth)] = gray;
1180:     }
1181: }
1182: //-----------------------------------------------------------------
1183: // 表現階調数の変更
1184: //    GetGray(),GetColor(): 等で計算したヒストグラムを使用
1185: //-----------------------------------------------------------------
1186: void change_graylevel(LPBYTE inBuf,int iLevel)
1187: {
1188:     int trhist[512],trans_table[512];
1189:     int i,x,y,gray;
1190:     int target_value; // 変換後の頻度の目標値
1191:     double gray_step; // 表現階調間隔
1192:     // ヒストグラム変換表の作成
1193:     target_value = rint(iSize/(double)iLevel);
1194:     FillMemory(trhist,sizeof(int)*512,0);
1195:     FillMemory(trans_table,sizeof(int)*512,0);
1196:     gray = 0;
1197:     for(i=0;i<iMAX_GRAY;i++){
1198:         if(abs(target_value-trhist[gray]) <
1199:            abs(target_value-(trhist[gray] + iGHist[i]))){
1200:             gray ++;
1201:             if(gray>=iLevel) gray=iLevel-1;
1202:         }
1203:         trans_table[i] = gray;
1204:         trhist[gray]  += iGHist[i];
1205:     }
1206:     // 平滑化した画像の作成
1207:     gray_step = (double)(iWHITE+1) / iLevel;
1208:     for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++)
1209:         inBuf[XY2PI(x,y,iWidth)] = (BYTE)rint(
1210:             trans_table[inBuf[XY2PI(x,y,iWidth)]] * gray_step);
1211: }
1212: //-----------------------------------------------------------------
1213: // 画像の空間フィルタリングを行う
1214: //-----------------------------------------------------------------
1215: void spacial_filtering(LPBYTE inBuf,int iFlt[9],double iMag)
1216: {
1217:     LPBYTE ib=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iSize);
1218:     int i,x,y,px,py;
1219:     double new_value,minv,maxv;
1220:     // 画像の複製
1221:     CopyMemory(ib,inBuf,sizeof(BYTE)*iSize);
1222:     // 最小・最大値の計算[線形変換用]
1223:     minv = 10000.; maxv = 0.;
1224:     for(y=1;y<iHeight-1;y++) for(x=1;x<iWidth-1;x++){
1225:         new_value = 0.0;
1226:         for(i=0;i<9;i++){
1227:             px = x+offset9[i].x;
1228:             py = y+offset9[i].y;
1229:             new_value += iFlt[i] * ib[XY2PI(px,py,iWidth)];
1230:         }
1231:         new_value = new_value / iMag;
1232:         if(new_value < minv) minv = new_value;
1233:         if(new_value > maxv) maxv = new_value;
1234:     }
1235:     // フィルタリングを行う
1236:     for(y=1;y<iHeight-1;y++) for(x=1;x<iWidth-1;x++){
1237:         new_value = 0.0;
1238:         for(i=0;i<9;i++){
1239:             px = x+offset9[i].x;
1240:             py = y+offset9[i].y;
1241:             new_value += iFlt[i]*ib[XY2PI(px,py,iWidth)];
1242:         }
1243:         new_value = new_value / iMag;
1244:         new_value = iWHITE / (maxv-minv) * (new_value-minv);
1245:         inBuf[XY2PI(x,y,iWidth)] = (BYTE)rint(new_value);
1246:     }
1247:     GlobalFree(ib);
1248: }
1249: //-----------------------------------------------------------------
1250: // 誤差拡散画像の作成
1251: // 誤差分散 |  *  | 3/8 |    * : 注目点,
1252: //          | 3/8 | 2/8 |    注)最右列, 最下行は誤差拡散しない
1253: //-----------------------------------------------------------------
1254: void make_error_difusion_image(LPBYTE inBuf)
1255: {
1256:     int x, y;
1257:     double err1,err2,err3; // 階調誤差
1258:     double* buf=(double*)GlobalAlloc(GPTR,sizeof(double)*iWidth*2);
1259:     double modified_gray;
1260:     // 2ライン分のバッファのクリア
1261:     FillMemory(buf,sizeof(double)*iWidth*2,0);
1262:     // 誤差拡散画像の作成
1263:     for(y=0;y<iHeight;y++){
1264:         for(x=0;x<iWidth;x++){
1265:             // 近傍が外に出るときは単純2値化する
1266:             if(x==iWidth-1 || y==iHeight-1){
1267:                 if(inBuf[XY2PI(x,y,iWidth)] <= iMAX_GRAY/2) 
1268:                     inBuf[XY2PI(x,y,iWidth)]=iBLACK;
1269:                 else
1270:                     inBuf[XY2PI(x,y,iWidth)]=iWHITE;
1271:             } else {
1272:                 modified_gray=inBuf[XY2PI(x,y,iWidth)]+buf[x];
1273:                 err1=modified_gray - 0.0;
1274:                 err2=modified_gray - iWHITE;
1275:                 if(err1 * err1<err2 * err2){
1276:                     inBuf[XY2PI(x,y,iWidth)]=0;   
1277:                     err3=err1;
1278:                 } else {
1279:                     inBuf[XY2PI(x,y,iWidth)]=iWHITE; 
1280:                     err3=err2;
1281:                 }
1282:                 // 近傍に応じて次の式を変える
1283:                 buf[x+1]       =buf[x+1]       + err3 * 3.0 / 8.0;
1284:                 buf[x+1+iWidth]=buf[x+1+iWidth]+ err3 * 2.0 / 8.0;
1285:                 buf[x  +iWidth]=buf[x  +iWidth]+ err3 * 3.0 / 8.0;
1286:             }
1287:         }
1288:         for(x=0;x<iWidth;x++){
1289:             buf[x]=buf[x+iWidth];
1290:             buf[x+iWidth]=0.0;
1291:         }
1292:     }
1293:     GlobalFree(buf);
1294: }
1295: //-----------------------------------------------------------------
1296: // 画像のヒストグラムを作り画像として表示
1297: //-----------------------------------------------------------------
1298: void make_histogram_image(LPBYTE inBuf)
1299: {
1300:     int i,j,data,max_frequency;
1301:     // ヒストグラムの作成
1302:     make_histogram(inBuf);
1303:     // 頻度の最大値を求める
1304:     max_frequency=0;
1305:     for(i=0;i<iMAX_GRAY;i++)
1306:         if(iGHist[i] > max_frequency) 
1307:             max_frequency = iGHist[i];
1308:     // ヒストグラム画像の作成
1309:     FillMemory(inBuf,sizeof(BYTE)*iSize,0);
1310:     for(i=0;i<iMAX_GRAY;i++){
1311:         // グラフ長さ
1312:         data=rint(iWHITE*(double)iGHist[i]/(double)max_frequency);
1313:         for(j=0;j<data;j++)
1314:             inBuf[XY2PI(i,j,iWidth)] = iWHITE;
1315:     }
1316: }
1317: //-----------------------------------------------------------------
1318: // 画像を簡易3次元表示
1319: //   plot_step:  線の描画間隔 [画素] 2〜10 程度
1320: //   plot_ratio: 階調方向の倍率 0.0〜1.0(=255画素)
1321: //-----------------------------------------------------------------
1322: void draw_3D_graph(LPBYTE inBuf,int plot_step,double plot_ratio)
1323: {
1324:     int x,y,lx1,lx2,ly1,ly2;
1325:     int x_size,y_size;
1326:     int plot_height; // 階調方向の高さ=256.0 * plot_ratio
1327:     double xmag,ymag;
1328:     LPBYTE ib=(LPBYTE)GlobalAlloc(GPTR,sizeof(BYTE)*iSize);
1329:     CopyMemory(ib,inBuf,sizeof(BYTE)*iSize);
1330:     //-------------------------------------------------------
1331:     // 描画パラメータ(plot_step,plot_ratio)の指定
1332:     //-------------------------------------------------------
1333:     x_size=iWidth  + iHeight / 2;  // グラフの想定横幅(画素)
1334:     plot_height=rint(iMAX_GRAY*plot_ratio);
1335:     y_size=iHeight + plot_height;  // グラフの想定縦幅(画素)
1336:     xmag = (double)iWidth /(double)x_size;
1337:     ymag = (double)iHeight/(double)y_size;
1338:     //-------------------------------------------------------
1339:     // 描画エリアの初期化
1340:     //-------------------------------------------------------
1341:     FillMemory(inBuf,sizeof(BYTE)*iSize,0);
1342:     //-------------------------------------------------------
1343:     // グラフの表示
1344:     //-------------------------------------------------------
1345:     for(y=0;y<iHeight;y++){
1346:         if(y%plot_step == 0){
1347:             // y が plot_step で割り切れるときだけ描く
1348:             // 始めに曲線部分を黒で描いて隠面消去する
1349:             for(x=0;x<iWidth;x++){
1350:                 lx1 = rint(xmag*(x+y/2));
1351:                 ly1 = rint(ymag*((y_size-1)-(plot_height+y)));
1352:                 lx2 = rint(xmag*(x+y/2));
1353:                 ly2 = rint(ymag*((y_size-1)-
1354:                                  (plot_height+y-
1355:                                   (ib[XY2PI(x,y,iWidth)]*plot_ratio))));
1356:                 draw_line(inBuf,lx1,ly1,lx2,ly2,0);
1357:             }
1358:             // 曲線部分を白で描く
1359:             for(x=0;x<iWidth-1;x++){
1360:                 lx1 = rint(xmag*(x+y/2));
1361:                 ly1 = rint(ymag*((y_size-1)-
1362:                                  (plot_height+y-
1363:                                   (ib[XY2PI(x,y,iWidth)]*plot_ratio))));
1364:                 lx2 = rint(xmag*(x+y/2+1));
1365:                 ly2 = rint(ymag*((y_size-1)-
1366:                                  (plot_height+y-
1367:                                   (ib[XY2PI(x+1,y,iWidth)]*plot_ratio))));
1368:                 draw_line(inBuf,lx1,ly1,lx2,ly2,iWHITE);
1369:             }
1370:         }
1371:     }
1372:     GlobalFree(ib);
1373: }

[PR]看護師の好条件な求人情報満載:今人気の転職サイト♪6分に1人が登録中