draw1.c

0000#include <stdio.h>
0001#include <stdlib.h>
0002#include <string.h>
0003#include <math.h>
0004#include "draw1.h"
0005#include "draw7.h"
0006#include "gcs1.h"
0007
0008int outbyte(int num,char *buf);
0009int flush();
0010
0011/**************** basic draw information ***********/
0012unsigned char* pD; // bitmap buffer
0013int depthD; // Mac standard 256 colors
0014int widthD; // picture size
0015int heightD;
0016int coloD; // current color for drawing
0017int xD; // current pen position
0018int yD;
0019int cliplD; // clip rect left
0020int cliprD;
0021int cliptD;
0022int clipbD;
0023
0024/**************** for polygon ***************/
0025unsigned char* poD; // bitmap buffer
0026int polyWidthD; // number of chars for one line of poD
0027int firstPtxD; // x value of first point. saved for closure
0028int firstPtyD;
0029int vertXD; // left-upper line crossings
0030int horiXD; // upper-left line crossings
0031int polyD; // 1 if polygon mode
0032int pxminD,pxmaxD,pyminD,pymaxD; // bounding rect
0033
0034/***************** for font ********************/
0035unsigned char* pfD; // font bitmap
0036int fontD; // font id (11,16,22)
0037int direcD; // direction of string 0:horiz 1:vert
0038int modeD; // current pen position is 0:left 1:right 2:center of string
0039int widthBytesD;
0040int fontBytesD;
0041int ascentD;
0042int descentD;
0043int fontWidthD;
0044int fontHeightD;
0045#include "font.c"
0046
0047/***************** for graph ********************/
0048int lgD,tgD,rgD,bgD;
0049double ldgD,tdgD,rdgD,bdgD;
0050int htD,hlD,vlD;
0051
0052/**************** output ***********************/
0053int widMin,widMax,heiMin,heiMax;
0054int lzw=1; // compress
0055unsigned char sizeOfCTD; // depthD-1
0056unsigned char outBufD[260];
0057int bitPtrD;
0058int bitsD;
0059FILE *fpD;
0060int gsize=1; // gif scale
0061
0062/**************** for CRC ********************/
0063unsigned long crc_table[256];
0064int crc_table_computed=0;
0065
0066/************* color table ******************/
0067int std256[256][4]={
00680,65535,65535,65535,
00691,65535,65535,52428,
00702,65535,65535,39321,
00713,65535,65535,26214,
00724,65535,65535,13107,
00735,65535,65535,    0,
00746,65535,52428,65535,
00757,65535,52428,52428,
00768,65535,52428,39321,
00779,65535,52428,26214,
007810,65535,52428,13107,
007911,65535,52428,    0,
008012,65535,39321,65535,
008113,65535,39321,52428,
008214,65535,39321,39321,
008315,65535,39321,26214,
008416,65535,39321,13107,
008517,65535,39321,    0,
008618,65535,26214,65535,
008719,65535,26214,52428,
008820,65535,26214,39321,
008921,65535,26214,26214,
009022,65535,26214,13107,
009123,65535,26214,    0,
009224,65535,13107,65535,
009325,65535,13107,52428,
009426,65535,13107,39321,
009527,65535,13107,26214,
009628,65535,13107,13107,
009729,65535,13107,    0,
009830,65535,    0,65535,
009931,65535,    0,52428,
010032,65535,    0,39321,
010133,65535,    0,26214,
010234,65535,    0,13107,
010335,65535,    0,    0,
010436,52428,65535,65535,
010537,52428,65535,52428,
010638,52428,65535,39321,
010739,52428,65535,26214,
010840,52428,65535,13107,
010941,52428,65535,    0,
011042,52428,52428,65535,
011143,52428,52428,52428,
011244,52428,52428,39321,
011345,52428,52428,26214,
011446,52428,52428,13107,
011547,52428,52428,    0,
011648,52428,39321,65535,
011749,52428,39321,52428,
011850,52428,39321,39321,
011951,52428,39321,26214,
012052,52428,39321,13107,
012153,52428,39321,    0,
012254,52428,26214,65535,
012355,52428,26214,52428,
012456,52428,26214,39321,
012557,52428,26214,26214,
012658,52428,26214,13107,
012759,52428,26214,    0,
012860,52428,13107,65535,
012961,52428,13107,52428,
013062,52428,13107,39321,
013163,52428,13107,26214,
013264,52428,13107,13107,
013365,52428,13107,    0,
013466,52428,    0,65535,
013567,52428,    0,52428,
013668,52428,    0,39321,
013769,52428,    0,26214,
013870,52428,    0,13107,
013971,52428,    0,    0,
014072,39321,65535,65535,
014173,39321,65535,52428,
014274,39321,65535,39321,
014375,39321,65535,26214,
014476,39321,65535,13107,
014577,39321,65535,    0,
014678,39321,52428,65535,
014779,39321,52428,52428,
014880,39321,52428,39321,
014981,39321,52428,26214,
015082,39321,52428,13107,
015183,39321,52428,    0,
015284,39321,39321,65535,
015385,39321,39321,52428,
015486,39321,39321,39321,
015587,39321,39321,26214,
015688,39321,39321,13107,
015789,39321,39321,    0,
015890,39321,26214,65535,
015991,39321,26214,52428,
016092,39321,26214,39321,
016193,39321,26214,26214,
016294,39321,26214,13107,
016395,39321,26214,    0,
016496,39321,13107,65535,
016597,39321,13107,52428,
016698,39321,13107,39321,
016799,39321,13107,26214,
0168100,39321,13107,13107,
0169101,39321,13107,    0,
0170102,39321,    0,65535,
0171103,39321,    0,52428,
0172104,39321,    0,39321,
0173105,39321,    0,26214,
0174106,39321,    0,13107,
0175107,39321,    0,    0,
0176108,26214,65535,65535,
0177109,26214,65535,52428,
0178110,26214,65535,39321,
0179111,26214,65535,26214,
0180112,26214,65535,13107,
0181113,26214,65535,    0,
0182114,26214,52428,65535,
0183115,26214,52428,52428,
0184116,26214,52428,39321,
0185117,26214,52428,26214,
0186118,26214,52428,13107,
0187119,26214,52428,    0,
0188120,26214,39321,65535,
0189121,26214,39321,52428,
0190122,26214,39321,39321,
0191123,26214,39321,26214,
0192124,26214,39321,13107,
0193125,26214,39321,    0,
0194126,26214,26214,65535,
0195127,26214,26214,52428,
0196128,26214,26214,39321,
0197129,26214,26214,26214,
0198130,26214,26214,13107,
0199131,26214,26214,    0,
0200132,26214,13107,65535,
0201133,26214,13107,52428,
0202134,26214,13107,39321,
0203135,26214,13107,26214,
0204136,26214,13107,13107,
0205137,26214,13107,    0,
0206138,26214,    0,65535,
0207139,26214,    0,52428,
0208140,26214,    0,39321,
0209141,26214,    0,26214,
0210142,26214,    0,13107,
0211143,26214,    0,    0,
0212144,13107,65535,65535,
0213145,13107,65535,52428,
0214146,13107,65535,39321,
0215147,13107,65535,26214,
0216148,13107,65535,13107,
0217149,13107,65535,    0,
0218150,13107,52428,65535,
0219151,13107,52428,52428,
0220152,13107,52428,39321,
0221153,13107,52428,26214,
0222154,13107,52428,13107,
0223155,13107,52428,    0,
0224156,13107,39321,65535,
0225157,13107,39321,52428,
0226158,13107,39321,39321,
0227159,13107,39321,26214,
0228160,13107,39321,13107,
0229161,13107,39321,    0,
0230162,13107,26214,65535,
0231163,13107,26214,52428,
0232164,13107,26214,39321,
0233165,13107,26214,26214,
0234166,13107,26214,13107,
0235167,13107,26214,    0,
0236168,13107,13107,65535,
0237169,13107,13107,52428,
0238170,13107,13107,39321,
0239171,13107,13107,26214,
0240172,13107,13107,13107,
0241173,13107,13107,    0,
0242174,13107,    0,65535,
0243175,13107,    0,52428,
0244176,13107,    0,39321,
0245177,13107,    0,26214,
0246178,13107,    0,13107,
0247179,13107,    0,    0,
0248180,    0,65535,65535,
0249181,    0,65535,52428,
0250182,    0,65535,39321,
0251183,    0,65535,26214,
0252184,    0,65535,13107,
0253185,    0,65535,    0,
0254186,    0,52428,65535,
0255187,    0,52428,52428,
0256188,    0,52428,39321,
0257189,    0,52428,26214,
0258190,    0,52428,13107,
0259191,    0,52428,    0,
0260192,    0,39321,65535,
0261193,    0,39321,52428,
0262194,    0,39321,39321,
0263195,    0,39321,26214,
0264196,    0,39321,13107,
0265197,    0,39321,    0,
0266198,    0,26214,65535,
0267199,    0,26214,52428,
0268200,    0,26214,39321,
0269201,    0,26214,26214,
0270202,    0,26214,13107,
0271203,    0,26214,    0,
0272204,    0,13107,65535,
0273205,    0,13107,52428,
0274206,    0,13107,39321,
0275207,    0,13107,26214,
0276208,    0,13107,13107,
0277209,    0,13107,    0,
0278210,    0,    0,65535,
0279211,    0,    0,52428,
0280212,    0,    0,39321,
0281213,    0,    0,26214,
0282214,    0,    0,13107,
0283215,61166,    0,    0,
0284216,56797,    0,    0,
0285217,48059,    0,    0,
0286218,43690,    0,    0,
0287219,34952,    0,    0,
0288220,30583,    0,    0,
0289221,21845,    0,    0,
0290222,17476,    0,    0,
0291223, 8738,    0,    0,
0292224, 4369,    0,    0,
0293225,    0,61166,    0,
0294226,    0,56797,    0,
0295227,    0,48059,    0,
0296228,    0,43690,    0,
0297229,    0,34952,    0,
0298230,    0,30583,    0,
0299231,    0,21845,    0,
0300232,    0,17476,    0,
0301233,    0, 8738,    0,
0302234,    0, 4369,    0,
0303235,    0,    0,61166,
0304236,    0,    0,56797,
0305237,    0,    0,48059,
0306238,    0,    0,43690,
0307239,    0,    0,34952,
0308240,    0,    0,30583,
0309241,    0,    0,21845,
0310242,    0,    0,17476,
0311243,    0,    0, 8738,
0312244,    0,    0, 4369,
0313245,61166,61166,61166,
0314246,56797,56797,56797,
0315247,48059,48059,48059,
0316248,43690,43690,43690,
0317249,34952,34952,34952,
0318250,30583,30583,30583,
0319251,21845,21845,21845,
0320252,17476,17476,17476,
0321253, 8738, 8738, 8738,
0322254, 4369, 4369, 4369,
0323255,    0,    0,    0};
0324/****************** for MakeView1 *******************/
0325/**************** basic draw information ***********/
0326/* unsigned char* pD; // bitmap buffer */
0327PixMap* pD1=NULL;
0328/* int depthD; // Mac standard 256 colors */
0329/* int widthD; // picture size */
0330/* int heightD; */
0331/* int coloD; // current color for drawing */
0332unsigned char rD1,gD1,bD1;
0333/* int xD; // current pen position */
0334/* int yD; */
0335/* int cliplD; // clip rect left */
0336/* int cliprD; */
0337/* int cliptD; */
0338/* int clipbD; */
0339PixMap* pD2=NULL;
0340PixMap* pD3=NULL; /* for thumbnail */
0341/************** saving gif in directory pc ********************/
0342int saveG=0;
0343char saveGfn[30];
0344FILE *gfp;
0345/************************** for base64 encode ********************************/
0346int k64=0,l64=0;
0347unsigned char in64[4],out64[5];
0348char b64digits[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
0349
0350int MakeView(int width,int height)
0351{
0352 int i,j;
0353 widthD=width;
0354 heightD=height;
0355 pD=(unsigned char *)malloc((widthD+1)*heightD*sizeof(char));
0356 j=widthD*heightD;
0357 for(i=0;i<j;i++) pD[i]=0;
0358 depthD=8;
0359 if(widthD%8==0) polyWidthD=widthD/8; // width for buffer
0360 else polyWidthD=width/8+1;
0361 poD=(unsigned char *)malloc(polyWidthD*heightD*sizeof(char));
0362 cliplD=0; // clip rect left
0363 cliprD=widthD;
0364 cliptD=0;
0365 clipbD=heightD;
0366 polyD=0; // not polygon mode initially
0367 widMin=0;
0368 widMax=widthD;
0369 heiMin=0;
0370 heiMax=heightD;
0371}
0372
0373int SetColor(int r1,int g1,int b1)
0374{
0375  int i;
0376  int r,g,b;
0377  
0378  r=r1*(0xffff/100);
0379  g=g1*(0xffff/100);
0380  b=b1*(0xffff/100);
0381  return SetColor1(r,g,b);
0382}
0383
0384int SetColor1(int r,int g,int b)
0385{
0386 int i;
0387  if(r==0&&g==0&&b==0){
0388    coloD=255;
0389    return;
0390  }
0391  if(r==0xffff&&g==0xffff&&b==0xffff){
0392    coloD=0;
0393    return;
0394  }
0395  if(r==0&&g==0){
0396    i=(b+2185)/4369;
0397    if(i%3!=0){
0398      coloD=245-(i-i/3);
0399      return;
0400    }
0401  }
0402  if(g==0&&b==0){
0403    i=(r+2185)/4369;
0404    if(i%3!=0){
0405      coloD=225-(i-i/3);
0406      return;
0407    }
0408  }
0409  if(b==0&&r==0){
0410    i=(g+2185)/4369;
0411    if(i%3!=0){
0412      coloD=235-(i-i/3);
0413      return;
0414    }
0415  }
0416  if(b==g&&r==g){ // gray scale
0417    i=(g+2185)/4369;
0418    if(i!=0&&i%3!=0){
0419      coloD=255-(i-i/3);
0420      return;
0421    }
0422  }
0423  coloD=215-((r+6554)/13107)*36-((g+6554)/13107)*6-(b+6554)/13107;
0424  if(coloD==215) coloD=255;
0425}
0426
0427int MoveTo(int x,int y)
0428{
0429  if(polyD){
0430   firstPtxD=x;
0431   firstPtyD=y;
0432   if(x<pxminD) pxminD=x;
0433   if(x>pxmaxD) pxmaxD=x;
0434   if(y<pyminD) pyminD=y;
0435   if(y>pymaxD) pymaxD=y;
0436  }
0437  xD=x;
0438  yD=y;
0439}
0440
0441int LineTo(int x1,int y1)
0442{
0443  int a,dx,dy,b,two_a,two_b,xcrit,eps;
0444  unsigned char i;
0445  if(polyD){
0446   if(x1<pxminD) pxminD=x1;
0447   if(x1>pxmaxD) pxmaxD=x1;
0448   if(y1<pyminD) pyminD=y1;
0449   if(y1>pymaxD) pymaxD=y1;
0450   if(xD*x1<0){
0451    if((xD*y1-yD*x1)/(xD-x1)<0) vertXD++;
0452   }
0453   if(yD*y1<0){
0454    if((yD*x1-xD*y1)/(yD-y1)<0) horiXD++;
0455   }
0456  }
0457  dx=1;
0458  a=x1-xD;
0459  if(a<0){
0460   dx=-1;
0461   a=-a;
0462  }
0463
0464  dy=1;
0465  b=y1-yD;
0466  if(b<0){
0467   dy=-1;
0468   b=-b;
0469  }
0470  two_a = 2*a;
0471  two_b = 2*b;
0472  xcrit = -b+two_a;
0473  eps=0;
0474
0475  for(;;){
0476    if(cliplD<=xD && xD<cliprD && cliptD<=yD && yD<clipbD){
0477     if(polyD){
0478      i=1<<(xD%8);
0479      poD[yD*polyWidthD+xD/8]|=i;
0480     }
0481     else *(pD+yD*widthD+xD)=coloD;
0482    }
0483    if(xD==x1&&yD==y1) break;
0484    if(eps<=xcrit) xD += dx, eps+=two_b;
0485    if(eps>=a || a<=b) yD += dy, eps-=two_a;
0486  }
0487}
0488
0489void drawGrid()
0490{
0491 int i;
0492 SetColor(100,70,60);
0493 for(i=0;i<heightD;i+=10){
0494  MoveTo(0,i);
0495  LineTo(widthD,i);
0496 }
0497 for(i=0;i<widthD;i+=10){
0498  MoveTo(i,0);
0499  LineTo(i,heightD);
0500 }
0501 SetColor(80,40,20);
0502 for(i=0;i<heightD;i+=50){
0503  MoveTo(0,i);
0504  LineTo(widthD,i);
0505 }
0506 for(i=0;i<widthD;i+=50){
0507  MoveTo(i,0);
0508  LineTo(i,heightD);
0509 }
0510 SetColor(40,20,10);
0511 for(i=0;i<heightD;i+=100){
0512  MoveTo(0,i);
0513  LineTo(widthD,i);
0514 }
0515 for(i=0;i<widthD;i+=100){
0516  MoveTo(i,0);
0517  LineTo(i,heightD);
0518 }
0519}
0520
0521int OpenPoly()
0522{
0523  int i,j;
0524  for(j=0;j<heightD;j++)
0525   for(i=0;i<polyWidthD;i++) poD[j*polyWidthD+i]=0;
0526  polyD=1; // polygon mode on
0527  vertXD=0; // left-upper line crossings
0528  horiXD=0;
0529  pxminD=10000;
0530  pxmaxD=-10000;
0531  pyminD=10000;
0532  pymaxD=-10000;
0533}
0534
0535int ClosePoly()
0536{
0537/* [item][island][line]
0538  item 0 first column
0539  item 1 last column
0540  item 2 first upper continuous island (if -1 no upper island)
0541  item 3 second upper continuous island
0542  item 4 first lower continuous island (if -1 no lower island)
0543  item 5 second lower continuous island
0544  item 6 degenerative island (if 1)
0545  item 7 left corner (if 1)
0546  item 8 right corner (if 1)
0547*/
0548  int isl[3]; // number od islands
0549  int transitD[9][10][3]; // first black points and last black points
0550                       // for three lines
0551  int cornerBlack;
0552  int i,j,k,l,n,i1,i2,i3,i4,i5,i6,i7,i8;
0553  int topin; // top is inside
0554  unsigned char m;
0555
0556  LineTo(firstPtxD,firstPtyD); // close polygon
0557  polyD=0; // polygon mode off
0558  if(pxminD>=widthD) return; // out of view
0559  if(pxmaxD<0) return;
0560  if(pyminD>=heightD) return;
0561  if(pymaxD<0) return;
0562
0563  pxmaxD++; // past-the-boundary value
0564  pymaxD++;
0565
0566  if(pxminD<0) pxminD=0; // crossing rect
0567  if(pxmaxD>widthD) pxmaxD=widthD;
0568  if(pyminD<0) pyminD=0;
0569  if(pymaxD>heightD) pymaxD=heightD;
0570
0571  if(pxminD==(pxmaxD-1)) return;
0572  if(pyminD==(pymaxD-1)) return;
0573
0574  if(pyminD>0) topin=1; // top is in the view
0575  else topin=0;
0576  
0577  cornerBlack=0; // upper left corner is white
0578  if(pxminD==0&&pyminD==0){
0579   if(vertXD%2==1) cornerBlack=1;
0580  }
0581
0582  for(j=pyminD;j<pymaxD;j++){
0583   for(k=0;k<10;k++)
0584    for(n=0;n<9;n++){
0585     transitD[n][k][0]=transitD[n][k][1];
0586     transitD[n][k][1]=transitD[n][k][2];
0587     transitD[n][k][2]=-1;
0588    }
0589   isl[0]=isl[1];
0590   isl[1]=isl[2];
0591   k=0; // point white
0592   isl[2]=0;
0593   for(i=pxminD;i<pxmaxD;i++){
0594    m=poD[j*polyWidthD+i/8];
0595    if(m&(1<<(i%8))){ // black
0596     if(k==0){
0597      transitD[0][isl[2]][2]=i; // first black
0598      k=1;
0599      if(i==pxminD) transitD[7][isl[2]][2]=1;
0600      if(i==pxmaxD-1) transitD[8][isl[2]][2]=1;
0601     }
0602    }
0603    else{ // white
0604     if(k==1){
0605      transitD[1][isl[2]][2]=i-1; // last black
0606      k=0;
0607      isl[2]++;
0608     }
0609    }
0610   } /* for(i=pxminD;i<pxmaxD;i++) */
0611   if(k==1){
0612    transitD[1][isl[2]][2]=i-1; // last point is black
0613    transitD[8][isl[2]][2]=1;
0614    isl[2]++;
0615   }
0616   if(j>pyminD){ // if line 1 and above , process line 0
0617    for(k=0;k<isl[1];k++){
0618     i1=transitD[0][k][1];
0619     i2=transitD[1][k][1];
0620     i3=0;
0621     for(i4=0;i4<isl[2];i4++){
0622      i5=transitD[0][i4][2];
0623      i6=transitD[1][i4][2];
0624      if(i6>=(i1-1)&&i5<=(i2+1)){
0625       if(i3<2) transitD[4+i3][k][1]=i4; // lower
0626       i3++;
0627      }
0628     }
0629    } /* for(k=0;k<isl[1];k++){ */
0630    for(k=0;k<isl[2];k++){
0631     i1=transitD[0][k][2];
0632     i2=transitD[1][k][2];
0633     i3=0;
0634     for(i4=0;i4<isl[1];i4++){
0635      i5=transitD[0][i4][1];
0636      i6=transitD[1][i4][1];
0637      if(i6>=(i1-1)&&i5<=(i2+1)){
0638       if(i3<2) transitD[2+i3][k][2]=i4; // upper
0639       i3++;
0640      }
0641     }
0642    } /* for(k=0;k<isl[2];k++){ */
0643    if(j==pyminD+1){ // for the second line
0644     if(topin){
0645      for(k=0;k<isl[1];k++){
0646       if(transitD[5][k][1]!=-1) transitD[6][k][1]=1; // two lowers - degenerative
0647       else if(transitD[8][k][1]!=1){ // one lower and not right corner
0648        transitD[6][k][1]=1; // one lower - consecutive degenerative
0649        if(transitD[4][k][1]!=-1)  transitD[6][ transitD[4][k][1] ][2]=1; // make the lower degenerative
0650       }
0651      }
0652      for(k=0;k<isl[2];k++){
0653       if(transitD[2][k][2]==-1){
0654        if(transitD[8][k][2]!=1) transitD[6][k][2]=1; // no uppers and not right edge
0655       }
0656      }
0657     } /* if(topin){ */
0658    } /* if(j==pyminD+1){ */
0659   } /* if(j>pyminD) */
0660   if(j>pyminD+1){ // re-evaluate 3-line data and fill first line
0661    for(k=0;k<isl[2];k++){
0662     if(transitD[2][k][2]==-1){
0663      if(transitD[8][k][2]!=1) transitD[6][k][2]=1; // no uppers and not right edge
0664     }
0665     else if(transitD[3][k][2]==-1&&transitD[6][ transitD[2][k][2] ][1]==1){ // one upper and it's degenerative
0666      if(transitD[5][ transitD[2][k][2] ][1]==-1) transitD[6][k][2]=1; // the upper has one lower
0667     }
0668    }
0669    for(k=0;k<isl[2];k++){
0670     if(transitD[3][k][2]!=-1)  transitD[6][k][2]=1; // second-upper exists. join
0671    }
0672    for(k=0;k<isl[1];k++){
0673     if(transitD[5][k][1]!=-1){ // second-lower exists. cancel lowers' degene
0674      transitD[6][ transitD[4][k][1] ][2]=-1;
0675      transitD[6][ transitD[5][k][1] ][2]=-1;
0676     }
0677    }    
0678    i8=cornerBlack; // starting color
0679    i7=pxminD;
0680    for(k=0;k<isl[0];k++){
0681     i1=transitD[0][k][0];
0682     if(i8){ // if black, paint from i7 to i1
0683      for(l=i7;l<i1;l++)
0684      poD[(j-2)*polyWidthD+l/8]|=(1<<l%8);
0685     }
0686     if(transitD[6][k][0]!=1){
0687      if(i8==1) i8=0;
0688      else i8=1;
0689     }
0690     i7=transitD[1][k][0]+1;
0691    }
0692    if(i8==1&&i7<pxmaxD){ // paint to the end of line
0693     for(l=i7;l<pxmaxD;l++)
0694      poD[(j-2)*polyWidthD+l/8]|=(1<<l%8);
0695    }
0696   } /* if(j>pymind+1) */      
0697  } /* for(j=pyminD;j<pymaxD,j++) */
0698/* now do for last two lines */
0699  for(j=1;j<3;j++){
0700   i8=cornerBlack;
0701   i7=pxminD;
0702   for(k=0;k<isl[j];k++){
0703    i1=transitD[0][k][j];
0704    if(i8){ // if black, paint from i7 to i1
0705     for(l=i7;l<i1;l++)
0706      poD[(pymaxD-3+j)*polyWidthD+l/8]|=(1<<l%8);
0707    }
0708    if(transitD[6][k][j]!=1){
0709     if(i8==1) i8=0;
0710     else i8=1;
0711    }
0712    i7=transitD[1][k][j]+1;
0713   }
0714   if(i8==1&&i7<pxmaxD){ // paint to the end of line
0715    for(l=i7;l<pxmaxD;l++)
0716     poD[(pymaxD-3+j)*polyWidthD+l/8]|=(1<<l%8);
0717   }
0718  }
0719/* now poD has been painted, next we will paint pD in coloD */
0720  for(j=pyminD;j<pymaxD;j++){
0721   for(i=pxminD;i<pxmaxD;i++){
0722    m=poD[j*polyWidthD+i/8];
0723    if(m&(1<<(i%8)))
0724      *(pD+j*widthD+i)=coloD;
0725   }
0726  }
0727}
0728
0729int FontInfo(int font,int direc,int mode)
0730{
0731 fontD=font;
0732 switch(font){
0733  case 11: // 6x11
0734   pfD=fontdata_6x11;
0735   ascentD=8;
0736   descentD=3;
0737   fontWidthD=6;
0738   fontHeightD=11;
0739   widthBytesD=1;
0740   fontBytesD=11;
0741   break;
0742  case 16: // 8x16
0743   pfD=fontdata_8x16;
0744   ascentD=11;
0745   descentD=5;
0746   fontWidthD=8;
0747   fontHeightD=16;
0748   widthBytesD=1;
0749   fontBytesD=16;
0750   break;
0751  case 22: // 12x22
0752   pfD=fontdata_12x22;
0753   ascentD=16;
0754   descentD=6;
0755   fontWidthD=12;
0756   fontHeightD=22;
0757   widthBytesD=2;
0758   fontBytesD=44;
0759   break;
0760 }
0761 direcD=direc;
0762 modeD=mode;
0763}
0764
0765int DrawString(char *c)
0766{
0767  long int dots[1056]; // up to and including double size of 12x22
0768  int h,i,j,k,l,m,n,k0,x,y;
0769  unsigned char test,mask;
0770
0771  if(modeD==0);
0772  else{
0773   i=strlen(c);
0774   i=i*fontWidthD;
0775   if(modeD==2) i/=2; /* center */
0776   if(direcD==0) xD-=i;
0777   else yD+=i;
0778  }
0779  for(h=0;c[h]!='\0';h++){
0780   k0=fontBytesD*(int)c[h];
0781   n=0;
0782   for(i=0;i<fontHeightD;i++){
0783    k=k0+i*widthBytesD;
0784    m=0;
0785    for(j=0;j<widthBytesD;j++){
0786      test=pfD[k+j];
0787      mask=0x80;
0788      for(l=0;l<8;l++){
0789        if(test&mask){
0790         if(direcD==0){ // horizontal
0791          y=yD-ascentD+i;
0792          x=xD+j*8+l;
0793         }
0794         else{ // vertical
0795          x=xD-ascentD+i;
0796          y=yD-j*8-l;
0797         }
0798         if(x>=0&&x<widthD&&y>=0&&y<heightD)
0799          dots[n++]=y*widthD+x;
0800        }
0801        mask>>=1;
0802        m++;
0803        if(m==fontWidthD) break;
0804      }
0805    }
0806   } /* for(i=0;i<fontHeightD;i++) */
0807   for(j=0;j<n;j++) *(pD+dots[j])=coloD;
0808   if(direcD==0) xD+=fontWidthD;
0809   else yD-=fontWidthD;
0810  } /* for(h=0;c[h]!='\0';h++) */
0811}
0812
0813int DrawNum(int i)
0814{
0815 char c[15];
0816 sprintf(c,"%i",i);
0817 DrawString(c);
0818}
0819
0820int DrawFNum(char *f,double a)
0821{
0822 char c[30];
0823 sprintf(c,f,a);
0824 DrawString(c);
0825} 
0826
0827int MakeGraph(int left,int top,int right,int bottom)
0828{
0829 lgD=left;
0830 tgD=top;
0831 rgD=right;
0832 bgD=bottom;
0833 htD=0;
0834 hlD=0;
0835 vlD=0;
0836}
0837
0838int HorizTime()
0839{
0840 htD=1;
0841}
0842
0843int HorizLog()
0844{
0845 hlD=1;
0846}
0847
0848int VertLog()
0849{
0850 vlD=1;
0851}
0852
0853int format(int col,double num,char* fig)
0854{
0855 int i,j,colst,inte1,ncha;
0856 double a,frac;
0857 double inte;
0858 char c[10]={'0','1','2','3','4','5','6','7','8','9'};
0859
0860 ncha=0;
0861 i=0;
0862 if(num<0.){
0863  i++;
0864  fig[ncha++]='-';
0865  num=fabs(num);
0866 }
0867
0868 if(num!=0.){
0869  a=log10(num);
0870  frac=modf(a,&inte);
0871  colst=inte+0.1;
0872  if(colst<0) colst=0;
0873 }
0874 else colst=0;
0875        
0876 num+=pow(10,colst-6);
0877        
0878 frac=num/pow(10,colst);
0879 if(frac<1.&&frac>0.9999) frac=1.;
0880 for(j=colst;j>=0;j--){
0881  if(frac<1.&&frac>0.9999) frac=1.;
0882  frac=modf(frac,&inte)*10.;
0883  inte1=inte;
0884  i++;
0885  fig[ncha++]=c[inte1];
0886 }
0887
0888 if(col!=0){
0889  i++;
0890  fig[ncha++]='.';
0891  for(j=col;j>0;j--){
0892   if(frac<1.&&frac>0.9999) frac=1.;
0893   frac=modf(frac,&inte)*10.;
0894   inte1=inte;
0895   i++;
0896   fig[ncha++]=c[inte1];
0897  }
0898 }
0899 fig[ncha]='\0';
0900 return i;
0901}
0902
0903
0904int HorizScale(char *c,double left,double right)
0905{
0906 int i,j,ix,colx;
0907 double stepc,stepf,delta,intef,frac,num;
0908 char ar[12];
0909 double mdy,hms,scl;
0910 char *month[]={"Jan","Feb","Mar","Apr","May","Jun",
0911  "Jul","Aug","Sep","Oct","Nov","Dec"};
0912
0913 ldgD=left;
0914 rdgD=right;
0915 delta=right-left;
0916 MoveTo(lgD,bgD);
0917 LineTo(rgD,bgD);
0918if(htD==0){
0919 frac=modf(log10(delta),&intef);
0920 stepc=pow(10.,intef-1);
0921 stepf=stepc;
0922 if(frac<0.2) stepf*=0.5;
0923 else if(frac<0.8) stepc*=5.;
0924 else{
0925  stepc*=10.;
0926  stepf*=5.;
0927 }
0928 frac=modf(log10(stepc),&intef);
0929// if(log10(stepc)<0.) colx=-intef+1.;
0930 if(log10(stepc)<0.) colx=-log10(stepc)+0.8;
0931 else colx=0;
0932 frac=modf(left/stepc,&intef);
0933 frac=intef;
0934 if(hlD){
0935  stepc=1.;
0936  colx=0;
0937 }
0938 while(1){
0939  num=frac*stepc;                        // x value for grid
0940  if(num>rdgD) break;
0941  ix=(rgD-lgD)*((num-ldgD)/(rdgD-ldgD))+lgD;
0942  i=format(colx,num,ar);
0943  MoveTo(ix,tgD);
0944  LineTo(ix,bgD+2);
0945  FontInfo(11,0,0);
0946  for(i=0;ar[i]!='\0';i++);
0947  if(hlD){
0948   MoveTo(ix-i*3+4,bgD+12);
0949   DrawString(ar);
0950   MoveTo(ix-i*3-6,bgD+20);
0951   DrawString("10");
0952  }
0953  else{
0954   MoveTo(ix-i*3,bgD+12);
0955   DrawString(ar);
0956  }
0957  frac++;
0958 }
0959}
0960else{ /* horiz is time */
0961  mdy=mdyday(left);
0962  hms=hmsday(left);
0963  scl=(rgD-lgD)/delta;  /* dots per day */
0964  if(delta>700.){ /* yr */   
0965   frac=fmod(mdy*1000000.,10000.);
0966   while(1){
0967    num=refday(1.01+frac/1000000.,0.);     // x value for grid
0968    if(num>rdgD) break;
0969    ix=scl*(num-ldgD)+lgD;
0970    i=format(0,frac,ar);
0971    MoveTo(ix,tgD);
0972    LineTo(ix,bgD+2);
0973    if(num+182.>rdgD) break;
0974    FontInfo(11,0,2); /* center */
0975    ix=scl*(num+182.-ldgD)+lgD;
0976    MoveTo(ix,bgD+12);
0977    if(scl>0.07) DrawString(ar);
0978    else DrawString(&ar[2]);
0979    frac++; /* add a year */
0980   }
0981  }
0982  else if(delta>70.){ /* mo */
0983   stepc=fmod(mdy*1000000.,10000.); 
0984   stepf=floor(mdy);
0985   while(1){
0986    num=refday(stepf+0.01+stepc/1000000.,0.);     // x value for grid
0987    if(num>rdgD) break;
0988    if(num>ldgD){
0989     ix=scl*(num-ldgD)+lgD;
0990     MoveTo(ix,tgD);
0991     LineTo(ix,bgD+2);
0992    }
0993    if(num+15.>rdgD) break;
0994    FontInfo(11,0,2); /* center */
0995    ix=scl*(num+15.-ldgD)+lgD;
0996    MoveTo(ix,bgD+12);
0997    i=stepf;
0998    DrawString(month[i-1]);
0999    stepf++;
1000    if(stepf>12.1){
1001     stepf=1.;
1002     stepc++;
1003    }
1004   }
1005  }
1006  else if(delta>2.){ /* day */
1007   num=refday(mdy,0.);
1008   while(1){
1009    if(num>rdgD) break;
1010    stepf=mdyday(num);
1011    stepc=floor(stepf*100.);
1012    stepf=fmod(stepc,100.);
1013    i=1;
1014    if(scl<12.){
1015     if(fmod(num+0.001,7.)>1.) i=0;
1016    }
1017    if(num>ldgD){
1018     ix=scl*(num-ldgD)+lgD;
1019     MoveTo(ix,tgD);
1020     LineTo(ix,bgD+2*i);
1021    }
1022    if(i==1){
1023     if(num+0.5>rdgD) break;
1024     FontInfo(11,0,2); /* center */
1025     ix=scl*(num+0.5-ldgD)+lgD;
1026     MoveTo(ix,bgD+12);
1027     format(0,stepf,ar);
1028     DrawString(ar);
1029    }
1030    num++;
1031   }
1032  }
1033  else{ /* hour */
1034   stepc=floor(hms);
1035   num=refday(mdy,stepc);
1036   while(1){
1037    if(num>rdgD) break;
1038    if(num>ldgD){
1039     ix=scl*(num-ldgD)+lgD;
1040     MoveTo(ix,tgD);
1041     LineTo(ix,bgD+2);
1042    }
1043    if(num>rdgD) break;
1044    FontInfo(11,0,2); /* center */
1045    ix=scl*(num-ldgD)+lgD;
1046    MoveTo(ix,bgD+12);
1047    i=format(0,stepc,ar);
1048    DrawString(ar);
1049    stepc++;
1050    if(stepc>23.5) stepc=0;
1051    num+=0.041666666;
1052   }
1053  }
1054 }
1055 for(i=0;c[i]!='\0';i++);
1056 if(hlD) MoveTo((lgD+rgD-i*8)/2,bgD+33);
1057 else MoveTo((lgD+rgD-i*8)/2,bgD+22);
1058 FontInfo(16,0,0);
1059 DrawString(c);
1060}
1061
1062int VertScale(char *c,double bottom,double top)
1063{
1064 int i,j,iy,coly;
1065 double stepc,stepf,delta,intef,frac,num;
1066 char ar[12];
1067
1068 bdgD=bottom;
1069 tdgD=top;
1070 delta=top-bottom;
1071 frac=modf(log10(delta),&intef);
1072 stepc=pow(10.,intef-1);
1073 stepf=stepc;
1074 if(frac<0.2) stepf*=0.5;
1075 else if(frac<0.8) stepc*=5.;
1076 else{
1077  stepc*=10.;
1078  stepf*=5.;
1079 }
1080 MoveTo(lgD,tgD);
1081 LineTo(lgD,bgD);
1082
1083 frac=modf(log10(stepc),&intef);
1084// if(log10(stepc)<0.) coly=-intef+1.;
1085 if(log10(stepc)<0.) coly=-log10(stepc)+0.8;
1086 else coly=0;
1087 frac=modf(bottom/stepc,&intef);
1088 frac=intef;
1089 if(vlD){
1090  stepc=1.;
1091  coly=0;
1092 }
1093 j=0;
1094 while(1){
1095  num=frac*stepc;                        // y value for grid
1096  if(num>tdgD) break;
1097  iy=(tgD-bgD)*((num-bdgD)/(tdgD-bdgD))+bgD;
1098  i=format(coly,num,ar);
1099  if(i>j) j=i;
1100  MoveTo(lgD-2,iy);
1101  LineTo(rgD,iy);
1102  FontInfo(11,0,0);
1103  for(i=0;ar[i]!='\0';i++);
1104  if(vlD){
1105   MoveTo(lgD-i*6-3,iy-1);
1106   DrawString(ar);
1107   MoveTo(lgD-i*6-12,iy+6);
1108   DrawString("10");
1109  }
1110  else{
1111   MoveTo(lgD-i*6-3,iy+3);
1112   DrawString(ar);
1113  }
1114  frac++;
1115 }
1116 for(i=0;c[i]!='\0';i++);
1117 if(vlD) MoveTo(lgD-j*6-16,(bgD+tgD+i*8)/2);
1118 else MoveTo(lgD-j*6-8,(bgD+tgD+i*8)/2);
1119 FontInfo(16,1,0);
1120 DrawString(c);
1121}
1122
1123int MoveToG(double x,double y)
1124{
1125 int savel,saver,savet,saveb;
1126 int ix,iy;
1127 
1128 savel=cliplD;
1129 saver=cliprD;
1130 savet=cliptD;
1131 saveb=clipbD;
1132 cliplD=lgD;
1133 cliprD=rgD;
1134 cliptD=tgD;
1135 clipbD=bgD;
1136
1137 ix=(rgD-lgD)*((x-ldgD)/(rdgD-ldgD))+lgD;
1138 iy=(tgD-bgD)*((y-bdgD)/(tdgD-bdgD))+bgD;
1139 MoveTo(ix,iy);
1140
1141 cliplD=savel;
1142 cliprD=saver;
1143 cliptD=savet;
1144 clipbD=saveb;
1145}
1146
1147int LineToG(double x,double y)
1148{
1149 int savel,saver,savet,saveb;
1150 int ix,iy;
1151 
1152 savel=cliplD;
1153 saver=cliprD;
1154 savet=cliptD;
1155 saveb=clipbD;
1156 cliplD=lgD;
1157 cliprD=rgD;
1158 cliptD=tgD;
1159 clipbD=bgD;
1160
1161 
1162 ix=(rgD-lgD)*((x-ldgD)/(rdgD-ldgD))+lgD;
1163 iy=(tgD-bgD)*((y-bdgD)/(tdgD-bdgD))+bgD;
1164 LineTo(ix,iy);
1165
1166 cliplD=savel;
1167 cliprD=saver;
1168 cliptD=savet;
1169 clipbD=saveb;
1170}
1171
1172int PlotG(int mark,double x,double y)
1173{
1174 int ix,iy;
1175
1176 ix=(rgD-lgD)*((x-ldgD)/(rdgD-ldgD))+lgD;
1177 iy=(tgD-bgD)*((x-bdgD)/(tdgD-bdgD))+bgD;
1178 MoveTo(ix-1,iy-1);
1179 LineTo(ix-1,iy+1);
1180 LineTo(ix+1,iy+1);
1181 LineTo(ix-1,iy+1);
1182 LineTo(ix,iy+1);
1183 LineTo(ix,iy);
1184}
1185 
1186
1187int GifOutMin()
1188{
1189  int i,j,k;
1190  heiMin=10000;
1191  heiMax=-10000;
1192  widMin=10000;
1193  widMax=-10000;
1194  for(j=0;j<heightD;j++){
1195   for(i=0;i<widthD;i++){
1196    k=pD[widthD*j+i]; // CHARACTER
1197    if(k>0){
1198     if(i<widMin) widMin=i;
1199     if(i>widMax) widMax=i;
1200     if(j<heiMin) heiMin=j;
1201     if(j>heiMax) heiMax=j;
1202    }
1203   }
1204  }
1205  heiMax++;
1206  widMax++;
1207  i=GifOut();
1208  return i;
1209}
1210 
1211int GifSaveMin(int n)
1212{
1213  int i,j,k;
1214  heiMin=10000;
1215  heiMax=-10000;
1216  widMin=10000;
1217  widMax=-10000;
1218  for(j=0;j<heightD;j++){
1219    for(i=0;i<widthD;i++){
1220      k=pD[widthD*j+i]; // CHARACTER
1221      if(k>0){
1222        if(i<widMin) widMin=i;
1223        if(i>widMax) widMax=i;
1224        if(j<heiMin) heiMin=j;
1225        if(j>heiMax) heiMax=j;
1226      }
1227    }
1228  }
1229  heiMax++;
1230  widMax++;
1231  GifSave(n);
1232  return 0;
1233}
1234
1235void outbyte1(int num,char *s)
1236{
1237  int i;
1238  unsigned char c;
1239  if(num<0){
1240    if(k64>0){
1241      out64[0]=b64digits[in64[0] >> 2];
1242      c=(in64[0] << 4) & 0x30;
1243      if (k64 > 1) c |= in64[1] >> 4;
1244      out64[1]=b64digits[c];
1245      out64[2] = (k64 < 2) ? '=' : b64digits[(in64[1] << 2) & 0x3c];
1246      out64[3] = '=';
1247      outbyte(4,out64);
1248    }
1249  }
1250  else{
1251    if(saveG==1||saveG==2) fwrite(s,sizeof(char),num,gfp);
1252    if(saveG==0||saveG==1) outbyte(num,s);
1253    if(saveG==3){
1254      for(i=0;i<num;i++){
1255        in64[k64]=s[i];
1256        k64++;
1257        if(k64==3){
1258          out64[0]=b64digits[in64[0] >> 2];
1259          out64[1]=b64digits[((in64[0] << 4) & 0x30) | (in64[1] >> 4)];
1260          out64[2]=b64digits[((in64[1] << 2) & 0x3c) | (in64[2] >> 6)];
1261          out64[3]=b64digits[in64[2] & 0x3f];
1262          outbyte(4,out64);
1263          k64=0;
1264          l64++;
1265          if(l64%18==0) outbyte(1,"\n");
1266        }
1267      }
1268    }
1269  }
1270
1271  return 0;
1272}
1273
1274int gifsize(int size)
1275{
1276  gsize=size;
1277  return 0;
1278}
1279
1280int GifOutMode(int mode)
1281{
1282  saveG=3;
1283  return 0;
1284}
1285
1286/**********************************************************************************
1287 GifOut
1288  saveG : 0 - out, 1 - out and save, 2 - save, 3 - base64
1289  pD1 : NULL - standard color table. pD[widthD*j+i];
1290        non-NULL - addaptive color table. (unsigned char)pD2->pixdata[widthD*j+i];
1291**********************************************************************************/
1292int GifOut()
1293{
1294  int i,j,k,l,o;
1295  unsigned char m;
1296  unsigned int step,red,green,blue;
1297
1298  int ctSize=256; /* may be overriden */
1299  int *prec;
1300  unsigned char *color;
1301  unsigned char pc[2000];
1302  int ipc,nn,n,nnstart,nstart;
1303  int bitsmin;
1304  int kstart;
1305  int clrcode;
1306  int wid,hei;
1307  int wid1,hei1;
1308  double ratio;
1309  int *nent;
1310  int r,g,b,r1,g1,b1;
1311
1312  if(pD1==NULL&&gsize!=1){ /* scaled output can be made only in the standard 256 colors */
1313    ratio=1./gsize;
1314    wid1=widMax-widMin;
1315    hei1=heiMax-heiMin;
1316    wid=wid1*ratio;
1317    hei=hei1*ratio;
1318    pD3=pcreate(4,wid,hei);
1319    k=wid*hei;
1320    nent=(int *)calloc(k,sizeof(int));
1321    for(j=0;j<hei1;j++){
1322      o=ratio*j;
1323      for(i=0;i<wid1;i++){
1324        l=ratio*i;
1325        k=pD[wid1*j+i];
1326        r=std256[k][1]/256;
1327        g=std256[k][2]/256;
1328        b=std256[k][3]/256;
1329        getpix(pD3,l,o,&r1,&g1,&b1);
1330        n=nent[o*wid+l];
1331        r=(r1*n+r)/(n+1);
1332        g=(g1*n+g)/(n+1);
1333        b=(b1*n+b)/(n+1);
1334        putpix(pD3,l,o,r,g,b);
1335        nent[o*wid+l]++;
1336      }
1337    }
1338    k=0;
1339    for(j=0;j<hei;j++){
1340      for(i=0;i<wid;i++){
1341        getpix(pD3,i,j,&r,&g,&b);
1342        pD[k++]=StdColorx(r*256,g*256,b*256);
1343      }
1344    }
1345    widMax=ratio*widMax;
1346    widMin=ratio*widMin;
1347    heiMax=ratio*heiMax;
1348    heiMin=ratio*heiMin;
1349    widthD=widMax-widMin;
1350  }
1351  wid=widMax-widMin;
1352  hei=heiMax-heiMin;
1353
1354  prec=(int *)malloc(4097*sizeof(int)); // code up to 12 bits
1355  color=(unsigned char*)malloc(4097*sizeof(unsigned char));
1356  for(i=0;i<4097;i++) prec[i]=-1;
1357
1358  outbyte1(6,"GIF89a");
1359  outbyte1(2,(char *)&wid);
1360  outbyte1(2,(char *)&hei);
1361
1362  if(pD1){
1363    switch(pD1->type){
1364    case 0:
1365      sizeOfCTD=0;
1366      ctSize=2;
1367      break;
1368    case 6:
1369      sizeOfCTD=1;
1370      ctSize=4;
1371      break;
1372    case 1:
1373    case 7:
1374      sizeOfCTD=3;
1375      ctSize=16;
1376      break;
1377    case 9:
1378    case 4:
1379      sizeOfCTD=7;
1380      ctSize=256;
1381      break;
1382    }
1383  }
1384  else sizeOfCTD=7;
1385  m=0xF0|sizeOfCTD;
1386  outbyte1(1,&m);
1387  m=0; // Background Color Index
1388  outbyte1(1,&m);
1389  m=0; // Pixel Aspect Ratio
1390  outbyte1(1,&m);
1391  if(pD1){
1392    if(pD1->type==4){
1393      pD2=pcreate(8,pD1->wid,pD1->hei); /* 8-bit non-standard index */
1394      cnvtype(pD1,pD2,2); /* reduce sparse */
1395      //  cnvtype(pD1,pD2,0); /* reduce dark */
1396      outbyte1(768,pD2->data);
1397    }
1398    else outbyte1(pD1->idxlen,pD1->data);
1399  }
1400  else{
1401    step=0xFFFF/5;
1402    for(i=5;i>=0;i--){
1403      red=i*step;
1404      for(j=5;j>=0;j--){
1405        green=j*step;
1406        for(k=5;k>=0;k--){
1407          blue=k*step;
1408          if(i!=0||j!=0||k!=0){
1409            outbyte1(1,(char *)&red);
1410            outbyte1(1,(char *)&green);
1411            outbyte1(1,(char *)&blue);
1412          }
1413        }
1414      }
1415    }
1416    step=0xFFFF/15;
1417    green=0;
1418    blue=0;
1419    for(i=14;i>0;i--){
1420      if(i%3!=0){
1421        red=i*step;
1422        outbyte1(1,(char *)&red);
1423        outbyte1(1,(char *)&green);
1424        outbyte1(1,(char *)&blue);
1425      }
1426    }
1427    red=0;
1428    blue=0;
1429    for(i=14;i>0;i--){
1430      if(i%3!=0){
1431        green=i*step;
1432        outbyte1(1,(char *)&red);
1433        outbyte1(1,(char *)&green);
1434        outbyte1(1,(char *)&blue);
1435      }
1436    }
1437    red=0;
1438    green=0;
1439    for(i=14;i>0;i--){
1440      if(i%3!=0){
1441        blue=i*step;
1442        outbyte1(1,(char *)&red);
1443        outbyte1(1,(char *)&green);
1444        outbyte1(1,(char *)&blue);
1445      }
1446    }
1447    for(i=14;i>0;i--){
1448      if(i%3!=0){
1449        red=green=blue=i*step;
1450        outbyte1(1,(char *)&red);
1451        outbyte1(1,(char *)&green);
1452        outbyte1(1,(char *)&blue);
1453      }
1454    }
1455    red=0;
1456    green=0;
1457    blue=0;
1458    outbyte1(1,(char *)&red);
1459    outbyte1(1,(char *)&green);
1460    outbyte1(1,(char *)&blue);
1461  }
1462  m=0x2c; // image separator
1463  outbyte1(1,&m);
1464  
1465  i=0; // image left position
1466  outbyte1(2,(char *)&i);
1467  i=0; // image top position
1468  outbyte1(2,(char *)&i);
1469  outbyte1(2,(char *)&wid);
1470  outbyte1(2,(char *)&hei);
1471  m=0x00|sizeOfCTD;
1472  outbyte1(1,&m);
1473
1474  m++; // LZW minimum code size 8
1475  if(m==1) m=2;
1476  outbyte1(1,&m);
1477  clrcode=1<<m; // clear code 0x100
1478  bitsD=m+1; // output number of bits
1479  bitsmin=bitsD; // initial number of bits
1480  for(i=0;i<ctSize;i++) color[i]=i; // the first 256 of 4097 colors
1481  for(i=0;i<260;i++) outBufD[i]=0;
1482  bitPtrD=0; // initialize output buffer
1483  emit(clrcode);
1484  ipc=0; // index for already-seen-color-sequence pc[]
1485  nnstart=0; // initial index value for nn used for pc[]
1486  nstart=clrcode+2; // n is index for preceeding code, prec
1487  for(j=heiMin;j<heiMax;j++){
1488    for(i=widMin;i<widMax;i++){
1489      if(pD1){
1490        switch(pD1->type){
1491        case 4:
1492          m=(unsigned char)pD2->pixdata[widthD*j+i];
1493          break;
1494        default:
1495          m=getpixid(pD1,i,j);
1496          break;
1497        }
1498      }
1499      else m=pD[widthD*j+i]; // CHARACTER
1500      pc[ipc++]=m; // STRING add to already-seen-sequence
1501      nn=nnstart; // index for pc[] used at comparing
1502      if(nn==0){ // first time and immediately after emit
1503        // for(k=0;k<ctSize;k++) if(color[k]==pc[nn]) break;
1504        k=pc[nn]; // equivalent to the above expression
1505        nn++;
1506      }
1507      else k=kstart; // code to be compared
1508      if(lzw){ // compress
1509        for(n=nstart;prec[n]!=-1;n++){ // matched upto and including nn-1 and n-1
1510          if(nn==ipc) break; // same as previously-seen-color-sequence
1511          if(prec[n]==k){
1512            if(color[n]==pc[nn]){
1513              nn++;
1514              k=n;
1515            }
1516          }
1517        }
1518        if(nn==ipc-1){ // if there is no previously-seen-color-sequence
1519          emit(k); // output code for hether-to matching sequence
1520          prec[n]=k; // add the code to dictionary
1521          color[n]=pc[ipc-1]; // add next-to-code-color in dictionary
1522          if(n>>bitsD) bitsD++;
1523          if(n==0xFFF){
1524            emit(clrcode);
1525            bitsD=bitsmin;
1526            for(n=0;n<4097;n++) prec[n]=-1;
1527          }
1528          pc[0]=m; // lastly-read color comes first in color array
1529          ipc=1;
1530          nnstart=0; //position of color array to be compared
1531          nstart=clrcode+2; // position of dictionary to be compared
1532        }
1533        else{ // when there is a previous instance
1534          nnstart=nn; // position of color array to be compared
1535          nstart=n; // position of dictionary to be compared
1536          kstart=k; // code to be compared
1537        }
1538      }
1539      else{ // not compress
1540        emit(m); // output code for hether-to matching sequence
1541        emit(clrcode);
1542        pc[0]=m; // lastly-read color comes first in color array
1543        ipc=1;
1544        nnstart=0; //position of color array to be compared
1545      }
1546    }
1547  }
1548  if(ipc==1){
1549    for(k=0;k<ctSize;k++) if(color[k]==pc[0]) break;
1550  }
1551  if(lzw) emit(k);
1552  n++;
1553  if(n>>bitsD) bitsD++;
1554
1555  emit(clrcode);
1556  bitsD=bitsmin;
1557
1558  emit(clrcode+1);
1559  i=bitPtrD/8;
1560  if((bitPtrD%8)!=0) i++;
1561  outbyte1(1,(char *)&i);
1562  outbyte1(i,(char *)outBufD);
1563  m=0;
1564  outbyte1(1,(char *)&m);
1565  m=0x3b;
1566  outbyte1(1,(char *)&m);
1567  outbyte1(-1,(char *)&m); /* for base64 encode */
1568  flush();
1569
1570  //  delete[] prec;
1571  //  delete[] color;
1572
1573  return 0;
1574}
1575
1576
1577void emit(int k)
1578{
1579  int i,j,m,n;
1580
1581  for(i=0;i<bitsD;i++){ // do for current number of bits
1582    m=bitPtrD/8; // put in n-th bit of m-th byte
1583    n=bitPtrD%8;
1584    j=k;
1585    j>>=i;
1586    j&=1;
1587    j<<=n;
1588    outBufD[m]|=j; // outBuf is char , j is int
1589    bitPtrD++;
1590  }
1591
1592  if(m>254){
1593    i=0xFF;
1594    outbyte1(1,(char *)&i);
1595    outbyte1(255,(char *)outBufD);
1596
1597    bitPtrD-=255*8;
1598    outBufD[0]=outBufD[255];
1599    outBufD[1]=outBufD[256];
1600    for(i=2;i<257;i++) outBufD[i]=0;
1601  }
1602}
1603
1604int PngOut()
1605{
1606  unsigned char signa[]={137,80,78,71,13,10,26,10};
1607  unsigned char *chunk;
1608
1609  int i,j,k,l,m,n;
1610  int i1,j1,k1,l1,m1,n1;
1611  int i2,j2,k2,l2,m2,n2;
1612  unsigned int step,red,green,blue;
1613  int lmatch,dmatch;
1614  int wdopen;
1615  unsigned long adler=1L;
1616  unsigned long s1,s2;
1617
1618  i=widthD*heightD/10;
1619  chunk=(unsigned char *)calloc(i*sizeof(char),sizeof(char)); /* this size must be related to picture size */
1620  
1621
1622  outbyte(8,(char *)signa);
1623
1624  *(int *)&chunk[0]=13; // excluding length, type or crc
1625  revPng(&chunk[0]);
1626  chunk[4]='I';
1627  chunk[5]='H';
1628  chunk[6]='D';
1629  chunk[7]='R';
1630  *(int *)&chunk[8]=widthD;
1631  revPng(&chunk[8]);
1632  *(int *)&chunk[12]=heightD;
1633  revPng(&chunk[12]);
1634  chunk[16]=8; /* bit depth */
1635  chunk[17]=3; /* color type - palette index */
1636  chunk[18]=0; /* compression method - deflate */
1637  chunk[19]=0; /* filter method */
1638  chunk[20]=0; /* interlace method */
1639  crcPng(&chunk[4],17); // including chunk type and chunk data
1640  outbyte(25,(char *)chunk);
1641  *(int *)&chunk[0]=768; // 256*3
1642  revPng(&chunk[0]);
1643  chunk[4]='P';
1644  chunk[5]='L';
1645  chunk[6]='T';
1646  chunk[7]='E';
1647  l=8;
1648  step=0xFFFF/5;
1649  for(i=5;i>=0;i--){
1650    red=i*step;
1651    for(j=5;j>=0;j--){
1652      green=j*step;
1653      for(k=5;k>=0;k--){
1654        blue=k*step;
1655        if(i!=0||j!=0||k!=0){
1656          chunk[l++]=red;
1657          chunk[l++]=green;
1658          chunk[l++]=blue;
1659        }
1660      }
1661    }
1662  }
1663  step=0xFFFF/15;
1664  green=0;
1665  blue=0;
1666  for(i=14;i>0;i--){
1667    if(i%3!=0){
1668      red=i*step;
1669      chunk[l++]=red;
1670      chunk[l++]=green;
1671      chunk[l++]=blue;
1672    }
1673  }
1674  red=0;
1675  blue=0;
1676  for(i=14;i>0;i--){
1677    if(i%3!=0){
1678      green=i*step;
1679      chunk[l++]=red;
1680      chunk[l++]=green;
1681      chunk[l++]=blue;
1682    }
1683  }
1684  red=0;
1685  green=0;
1686  for(i=14;i>0;i--){
1687    if(i%3!=0){
1688      blue=i*step;
1689      chunk[l++]=red;
1690      chunk[l++]=green;
1691      chunk[l++]=blue;
1692    }
1693  }
1694  for(i=14;i>0;i--){
1695    if(i%3!=0){
1696      red=green=blue=i*step;
1697      chunk[l++]=red;
1698      chunk[l++]=green;
1699      chunk[l++]=blue;
1700    }
1701  }
1702  red=0;
1703  green=0;
1704  blue=0;
1705  chunk[l++]=red;
1706  chunk[l++]=green;
1707  chunk[l++]=blue;
1708  crcPng(&chunk[4],768+4);
1709  outbyte(780,(char *)chunk);
1710  for(l=0;l<780;l++) chunk[l]=0;
1711/** LZ77 conpression **/
1712  chunk[4]='I';
1713  chunk[5]='D';
1714  chunk[6]='A';
1715  chunk[7]='T';
1716  chunk[8]=0x78; /* compression method/flag code */
1717  chunk[9]=0x9c; /* additional flags/check bits */
1718  i1=10; // initial code byte
1719  j1=0; // initial bit position
1720  setPng(chunk,i1,j1,3,3,&i1,&j1); // three header bit for the block
1721                                   // final & fixed Huffman code
1722  l=heightD*widthD; /* insert filter type byte */
1723  for(n=heightD-1;n>=0;n--){
1724   k=n*(widthD+1);
1725   for(m=widthD;m>0;m--) pD[k+m]=pD[--l];
1726   pD[k]=0;
1727  }
1728  wdopen=0;
1729  l=heightD*(widthD+1);
1730  for(n=0;n<l;n++){
1731   lmatch=0;
1732   if(n<32768) wdopen=0;
1733   else wdopen=n-32768;
1734   for(m=n-1;m>=wdopen;m--){
1735    j=n;
1736    k=m;
1737    i=0;
1738    while(pD[j++]==pD[k++]){
1739     i++;
1740     if(i==258) break;
1741     if(j>=l) break;
1742    }
1743    if(i>lmatch){
1744     lmatch=i; /* length */
1745     dmatch=n-m; /* distance */
1746    }
1747    if(lmatch==258||j>=l) break;
1748   }
1749   l1=0; // number of extra bits
1750   m1=0; // value of extra bits
1751   if(lmatch<3) k1=pD[n];  // raw data
1752   else{
1753    if(lmatch<11) k1=254+lmatch;
1754    else if(lmatch<19){
1755     l1=1;
1756     k1=(lmatch-11)/2+265;
1757     m1=(lmatch-11)%2;
1758    }
1759    else if(lmatch<35){
1760     l1=2;
1761     k1=(lmatch-19)/4+269;
1762     m1=(lmatch-19)%4;
1763    }
1764    else if(lmatch<67){
1765     l1=3;
1766     k1=(lmatch-35)/8+273;
1767     m1=(lmatch-35)%8;
1768    }
1769    else if(lmatch<131){
1770     l1=4;
1771     k1=(lmatch-67)/16+277;
1772     m1=(lmatch-67)%16;
1773    }
1774    else if(lmatch<258){
1775     l1=5;
1776     k1=(lmatch-131)/32+281;
1777     m1=(lmatch-131)%32;
1778    }
1779    else k1=285;
1780   } /* else */
1781/* convert alphabet k1 to Huffman code */
1782   if(k1<144){
1783    n1=0x30+k1; // Huffman code
1784    i2=0x80; // mask for output
1785   }
1786   else if(k1<256){
1787    n1=0x190+k1-144;
1788    i2=0x100;
1789   }
1790   else if(k1<280){
1791    n1=0x0+k1-256;
1792    i2=0x40;
1793   }
1794   else{
1795    n1=0xc0+k1-280;
1796    i2=0x80;
1797   }
1798   for(;i2>0;i2/=2){
1799    if(n1&i2) setPng(chunk,i1,j1,1,1,&i1,&j1);
1800    else setPng(chunk,i1,j1,0,1,&i1,&j1);
1801   }
1802   if(l1>0) setPng(chunk,i1,j1,m1,l1,&i1,&j1); /* extra bits for length */
1803   if(k1>256){ /* distance in dmatch */
1804    m2=1;
1805    for(l2=1;;l2++){
1806     m2*=2;
1807     if(m2>=dmatch) break;
1808    }
1809    k1=l2*2-1; // code 
1810               //     dmatch<= k1 l2 extra-bits
1811               //        2      1   1    0
1812               //        4      3   2    0
1813               //        8      5   3    1
1814               //       16      7   4    2
1815               //       32      9   5    3
1816    l1=l2-2;   // number of extra bits
1817    if(l1<0) l1=0;
1818               // m2       2   2   4   4   8   8   8   8  16  16  16
1819               // dmatch   1   2   3   4   5   6   7   8   9  10  11
1820               // l2       1   1   2   2   3   3   3   3   4   4   4
1821               // k1       1   1   3   3   5   5   5   5   7   7   7
1822               // l1       0   0   0   0   1   1   1   1   2   2   2 ->number of extra bits
1823               // n2       1   1   1   1   2   2   2   2   4   4   4
1824               // m2-n2    1   1   3   3   6   6   6   6  12  12  12
1825               // k1       0  (1)  2  (3)  4   4  (5) (5)  6   6   6 ->code
1826               // m2       1   2   3   4   6   6   8   8  12  12  12
1827               // m2-n2    0   1   2   3   4   4   6   6   8   8   8
1828               // m1       1   1   1   1   1   2   1   2   1   2   3
1829               // m1       0   0   0   0   0   1   0   1   0   1   2 ->extra bit value
1830    n2=pow(2,l1);
1831    if(dmatch<=m2-n2){
1832     k1--;
1833     m2=m2-n2;
1834    }
1835    m1=dmatch-(m2-n2);
1836    m1--;    // value of extra bits
1837
1838    i2=0x10; // 5 bits
1839    for(;i2>0;i2/=2){
1840     if(k1&i2) setPng(chunk,i1,j1,1,1,&i1,&j1);
1841     else setPng(chunk,i1,j1,0,1,&i1,&j1);
1842    }
1843    if(l1>0) setPng(chunk,i1,j1,m1,l1,&i1,&j1); /* extra bits for distance */
1844    n+=lmatch-1; /* advance main loop counter - 1 incremented later */
1845   } /* if(k1>256) */
1846  } /* for(n=0;n<l;n++){ */
1847  i2=0x40; // 7 bits - end of block mark
1848  for(;i2>0;i2/=2){ // huffman code for 256 is 0
1849   if(0&i2) setPng(chunk,i1,j1,1,1,&i1,&j1);
1850   else setPng(chunk,i1,j1,0,1,&i1,&j1);
1851  }
1852/* Adler-32 : a check sum value of the uncompressed data */
1853  s1=adler&0xffff;
1854  s2=(adler>>16)&0xffff;
1855  for(n=0;n<l;n++){
1856   s1=(s1+pD[n])%65521;
1857   s2=(s2+s1)%65521;
1858  }
1859  if(j1!=0) i1++;
1860  *(unsigned long *)&chunk[i1]=(s2<<16)+s1;
1861  revPng(&chunk[i1]);
1862  i1+=4;  /* pointer index to crc */
1863  *(int *)&chunk[0]=i1-8; /* data length */
1864  revPng(&chunk[0]);
1865  crcPng(&chunk[4],i1-4);
1866  i1+=4; /* number of bytes including crc */
1867  outbyte(i1,(char *)chunk);
1868  *(int *)&chunk[0]=0; /* data length */
1869  revPng(&chunk[0]);
1870  chunk[4]='I';
1871  chunk[5]='E';
1872  chunk[6]='N';
1873  chunk[7]='D';
1874  crcPng(&chunk[4],4);
1875  outbyte(12,(char *)chunk);
1876  flush();
1877
1878}
1879
1880void revPng(unsigned char *c)
1881{
1882 unsigned char a;
1883 a=c[0];
1884 c[0]=c[3];
1885 c[3]=a;
1886 a=c[1];
1887 c[1]=c[2];
1888 c[2]=a;
1889}
1890
1891/*********************************************
1892  Pad data into chunk
1893  chunk : chunk array
1894  byte : index into chunk array
1895  bit : bit position (0(lsb)-7(msb))
1896  val : data to be set
1897  nbit : number of bits of val
1898  *nxtbyte : next index to be returned
1899  *nxtbit : next bit position to be returned
1900********************************************/
1901void setPng(unsigned char *chunk,int byte,int bit,
1902        int val,int nbit,int *nxtbyte,int *nxtbit)
1903{
1904 unsigned char c1,c2;
1905 unsigned char cin[4];
1906 unsigned char mask,mask1;
1907 int sourcebyte,destbyte,sourcebit,destbit;
1908 int i;
1909
1910 sourcebyte=0;
1911 sourcebit=0;
1912 destbyte=byte;
1913 destbit=bit;
1914 *(unsigned long*)cin=val;
1915 for(i=0;i<nbit;i++){
1916  mask=1;
1917  mask<<=sourcebit;
1918  c1=cin[sourcebyte];
1919  if(c1&mask){
1920   mask=1;
1921   mask<<=destbit;
1922   chunk[destbyte]|=mask;
1923  }
1924  sourcebit++;
1925  if(sourcebit==8){
1926   sourcebyte++;
1927   sourcebit=0;
1928  }
1929  destbit++;
1930  if(destbit==8){
1931   destbyte++;
1932   destbit=0;
1933  }
1934 }
1935 *nxtbyte=destbyte;
1936 *nxtbit=destbit;
1937}
1938
1939
1940/**********************************************
1941  CRC - ported from W3C specification
1942  Return the CRC of the bytes buf[0]..[len-1]
1943  in buf[len]..[len+3] 
1944**********************************************/
1945void crcPng(unsigned char *buf,int len)
1946{
1947 unsigned long c;
1948 int n,k;
1949
1950 if(!crc_table_computed){
1951  for(n=0;n<256;n++){
1952   c=(unsigned long)n;
1953   for(k=0;k<8;k++){
1954    if(c&1) c=0xedb88320L^(c>>1);
1955    else c=c>>1;
1956   }
1957   crc_table[n]=c;
1958  }
1959  crc_table_computed=1;
1960 }
1961 c=0xffffffffL;
1962 for(n=0;n<len;n++){
1963  c=crc_table[(c^buf[n])&0xff]^(c>>8);
1964 }
1965 *(int *)&buf[len]=c^0xffffffffL;
1966 revPng(&buf[len]);
1967}
1968
1969/**************************************************
1970 r,g,b - 0-100
1971**************************************************/
1972int WritePixel(int x,int y,int r,int g, int b)
1973{
1974 int i;
1975 if(x<cliplD) return; // clip rect left
1976 if(x>=cliprD) return;
1977 if(y<cliptD) return;
1978 if(y>=clipbD) return;
1979 i=StdColor(r,g,b);
1980 *(pD+y*widthD+x)=i;
1981}
1982
1983int WritePixel1(int xoff,int yoff)
1984{
1985 int x,y;
1986 x=xD+xoff;
1987 y=yD+yoff;
1988 if(x<cliplD) return; // clip rect left
1989 if(x>=cliprD) return;
1990 if(y<cliptD) return;
1991 if(y>=clipbD) return;
1992 *(pD+y*widthD+x)=coloD;
1993}
1994
1995/***************************************************
1996 frac - 0-255
1997***************************************************/
1998int WritePixel2(int xoff,int yoff,int frac)
1999{
2000 int x,y,r,g,b,r1,g1,b1,r2,g2,b2,co1,col1;
2001 x=xD+xoff;
2002 y=yD+yoff;
2003 if(x<cliplD) return; // clip rect left
2004 if(x>=cliprD) return;
2005 if(y<cliptD) return;
2006 if(y>=clipbD) return;
2007 col1=*(pD+y*widthD+x);
2008 r1=std256[col1][1];
2009 g1=std256[col1][2];
2010 b1=std256[col1][3];
2011 r2=std256[coloD][1];
2012 g2=std256[coloD][2];
2013 b2=std256[coloD][3];
2014 r=(r1*(255-frac)+r2*frac)/255;
2015 g=(g1*(255-frac)+g2*frac)/255;
2016 b=(b1*(255-frac)+b2*frac)/255;
2017 *(pD+y*widthD+x)=StdColorx(r,g,b);
2018}
2019
2020/***************************************************
2021 standard color index
2022 r1,g1,b1 - 0-100
2023***************************************************/
2024int StdColor(int r1,int g1,int b1)
2025{
2026  int i;
2027  int r,g,b;
2028  
2029  r=r1*(0xffff/100);
2030  g=g1*(0xffff/100);
2031  b=b1*(0xffff/100);
2032  return StdColorx(r,g,b);
2033}
2034
2035int StdColorx(int r,int g,int b)
2036{
2037 int i;
2038
2039  if(r==0&&g==0&&b==0){
2040    return 255;
2041  }
2042  if(r==0xffff&&g==0xffff&&b==0xffff){
2043    return 0;
2044  }
2045  if(r==0&&g==0){
2046    i=(b+2185)/4369;
2047    if(i%3!=0){
2048      return 245-(i-i/3);
2049    }
2050  }
2051  if(g==0&&b==0){
2052    i=(r+2185)/4369;
2053    if(i%3!=0){
2054      return 225-(i-i/3);
2055    }
2056  }
2057  if(b==0&&r==0){
2058    i=(g+2185)/4369;
2059    if(i%3!=0){
2060      return 235-(i-i/3);
2061    }
2062  }
2063  if(b==g&&r==g){ // gray scale
2064    i=(g+2185)/4369;
2065    if(i!=0&&i%3!=0){
2066      return 255-(i-i/3);
2067    }
2068  }
2069  i=215-((r+6554)/13107)*36-((g+6554)/13107)*6-(b+6554)/13107;
2070  if(i==215) i=255;
2071  return i;
2072}
2073
2074void GifPatent() /* no more used */
2075{
2076 lzw=1;
2077}
2078
2079void ChangeSize(int deno)
2080{
2081 int i,j,k,l,m,n;
2082 int r,g,b;
2083
2084 widMin=0;
2085 widMax=widthD/2;
2086 heiMin=0;
2087 heiMax=heightD/2;
2088 for(j=0;j<heiMax;j++){
2089  for(i=0;i<widMax;i++){
2090   k=pD[widthD*j*2+i*2];
2091   l=pD[widthD*j*2+i*2+1];
2092   m=pD[widthD*(j*2+1)+i*2];
2093   n=pD[widthD*(j*2+1)+i*2+1];
2094   if(k==l&&l==m&&m==n){
2095    pD[widthD*j+i]=k;
2096   }
2097   else{
2098    r=(std256[k][1]+std256[l][1]+std256[m][1]+std256[n][1])/4;
2099    g=(std256[k][2]+std256[l][2]+std256[m][2]+std256[n][2])/4;
2100    b=(std256[k][3]+std256[l][3]+std256[m][3]+std256[n][3])/4;
2101    pD[widthD*j+i]=StdColorx(r,g,b);
2102   }
2103  }
2104 }
2105 i=GifOut();
2106}
2107
2108void GifSave(int num)
2109{
2110  double ratio;
2111  FILE *fp;
2112  int i,j,k,l,m,n;
2113  int *nent;
2114  int r,g,b,r1,g1,b1;
2115  int wid,hei;
2116  int wid1,hei1;
2117
2118  saveG=1; /* output and save */
2119  saveG=2;
2120  strcpy(saveGfn,"pc/o"); /* original */
2121  sprintf(&saveGfn[4],"%04i",num);
2122  strcat(saveGfn,".gif");
2123  gfp=fopen(saveGfn,"wb");
2124  GifOut();
2125  fclose(gfp);
2126  saveG=2; /* save */
2127  saveG=1;
2128  if(widthD*heightD<3000){ /* the original is smaller than thumbnail */
2129    gfp=fopen(saveGfn,"rb");
2130    saveGfn[3]='t';
2131    fp=fopen(saveGfn,"wb");
2132    while((i=fgetc(gfp))!=EOF) fputc(i,fp);
2133    fclose(fp);
2134    fclose(gfp);
2135    outbyte(16,"thumbnail saved\n");
2136    flush();
2137    return;
2138  }
2139  ratio=3000./(widthD*heightD);
2140  ratio=sqrt(ratio);
2141  wid=ratio*widthD;
2142  hei=ratio*heightD;
2143  widMin=0;
2144  widMax=wid;
2145  heiMin=0;
2146  heiMax=hei;
2147  wid1=widthD;
2148  hei1=heightD;
2149  widthD=wid;
2150  heightD=hei;
2151
2152  pD3=pcreate(4,wid,hei);
2153  k=wid*hei;
2154  nent=(int *)calloc(k,sizeof(int));
2155  if(pD1){
2156    for(j=0;j<hei1;j++){
2157      m=ratio*j;
2158      if(m==hei) m--;
2159      for(i=0;i<wid1;i++){
2160        l=ratio*i;
2161        if(l==wid) l--;
2162        getpix(pD1,i,j,&r,&g,&b);
2163        getpix(pD3,l,m,&r1,&g1,&b1);
2164        n=nent[m*wid+l];
2165        r=(r1*n+r)/(n+1);
2166        g=(g1*n+g)/(n+1);
2167        b=(b1*n+b)/(n+1);
2168        putpix(pD3,l,m,r,g,b);
2169        nent[m*wid+l]++;
2170      }
2171    }
2172  }
2173  else{
2174    for(j=0;j<hei1;j++){
2175      m=ratio*j;
2176      if(m==hei) m--;
2177      for(i=0;i<wid1;i++){
2178        l=ratio*i;
2179        if(l==wid) l--;
2180        k=pD[wid1*j+i];
2181        r=std256[k][1]/256;
2182        g=std256[k][2]/256;
2183        b=std256[k][3]/256;
2184        getpix(pD3,l,m,&r1,&g1,&b1);
2185        n=nent[m*wid+l];
2186        r=(r1*n+r)/(n+1);
2187        g=(g1*n+g)/(n+1);
2188        b=(b1*n+b)/(n+1);
2189        putpix(pD3,l,m,r,g,b);
2190        nent[m*wid+l]++;
2191      }
2192    }
2193  }  
2194  if(pD1){
2195    free(pD1);
2196    free(pD2);
2197  }
2198  pD1=pD3;
2199
2200  strcpy(saveGfn,"pc/t"); /* thumbnail */
2201  sprintf(&saveGfn[4],"%04i",num);
2202  strcat(saveGfn,".gif");
2203  gfp=fopen(saveGfn,"wb");
2204  GifOut();
2205  fclose(gfp);
2206}
2207