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