draw.c

0000#include <stdio.h>
0001#include <stdlib.h>
0002#include <string.h>
0003#include <math.h>
0004#include "draw.h"
0005#include "gcs1.h"
0006
0007/**************** basic draw information ***********/
0008unsigned char* pD; // bitmap buffer
0009int depthD; // Mac standard 256 colors
0010int widthD; // picture size
0011int heightD;
0012int coloD; // current color for drawing
0013int xD; // current pen position
0014int yD;
0015int cliplD; // clip rect left
0016int cliprD;
0017int cliptD;
0018int clipbD;
0019
0020/**************** for polygon ***************/
0021unsigned char* poD; // bitmap buffer
0022int polyWidthD; // number of chars for one line of poD
0023int firstPtxD; // x value of first point. saved for closure
0024int firstPtyD;
0025int vertXD; // left-upper line crossings
0026int horiXD; // upper-left line crossings
0027int polyD; // 1 if polygon mode
0028int pxminD,pxmaxD,pyminD,pymaxD; // bounding rect
0029
0030/***************** for font ********************/
0031unsigned char* pfD; // font bitmap
0032int fontD; // font id (11,16,22)
0033int direcD; // direction of string 0:horiz 1:vert
0034int modeD; // current pen position is 0:left 1:right 2:center of string
0035int widthBytesD;
0036int fontBytesD;
0037int ascentD;
0038int descentD;
0039int fontWidthD;
0040int fontHeightD;
0041#include "font.c"
0042
0043/***************** for graph ********************/
0044int lgD,tgD,rgD,bgD;
0045double ldgD,tdgD,rdgD,bdgD;
0046int htD;
0047
0048int lzw;
0049unsigned char sizeOfCTD; // depthD-1
0050unsigned char outBufD[260];
0051int bitPtrD;
0052int bitsD;
0053FILE *fpD;
0054
0055/**************** for CRC ********************/
0056unsigned long crc_table[256];
0057int crc_table_computed=0;
0058
0059int MakeView(int width,int height)
0060{
0061 int i,j;
0062 widthD=width;
0063 heightD=height;
0064 pD=(unsigned char *)malloc(widthD*heightD*sizeof(char));
0065 j=widthD*heightD;
0066 for(i=0;i<j;i++) pD[i]=0;
0067 depthD=8;
0068 if(widthD%8==0) polyWidthD=widthD/8; // width for buffer
0069 else polyWidthD=width/8+1;
0070 poD=(unsigned char *)malloc(polyWidthD*heightD*sizeof(char));
0071 cliplD=0; // clip rect left
0072 cliprD=widthD;
0073 cliptD=0;
0074 clipbD=heightD;
0075 polyD=0; // not polygon mode initially
0076 lzw=0; // not compress
0077}
0078
0079int SetColor(int r1,int g1,int b1)
0080{
0081  int i;
0082  unsigned int r,g,b;
0083  
0084  r=r1*(0xffff/100);
0085  g=g1*(0xffff/100);
0086  b=b1*(0xffff/100);
0087
0088  if(r==0&&g==0&&b==0){
0089    coloD=255;
0090    return;
0091  }
0092  if(r==0xffff&&g==0xffff&&b==0xffff){
0093    coloD=0;
0094    return;
0095  }
0096  if(r==0&&g==0){
0097    i=(b+2185)/4369;
0098    if(i%3!=0){
0099      coloD=245-(i-i/3);
0100      return;
0101    }
0102  }
0103  if(g==0&&b==0){
0104    i=(r+2185)/4369;
0105    if(i%3!=0){
0106      coloD=225-(i-i/3);
0107      return;
0108    }
0109  }
0110  if(b==0&&r==0){
0111    i=(g+2185)/4369;
0112    if(i%3!=0){
0113      coloD=235-(i-i/3);
0114      return;
0115    }
0116  }
0117  if(b==g&&r==g){ // gray scale
0118    i=(g+2185)/4369;
0119    if(i!=0&&i%3!=0){
0120      coloD=255-(i-i/3);
0121      return;
0122    }
0123  }
0124  coloD=215-((r+6554)/13107)*36-((g+6554)/13107)*6-(b+6554)/13107;
0125  if(coloD==215) coloD=255;
0126}
0127
0128int MoveTo(int x,int y)
0129{
0130  if(polyD){
0131   firstPtxD=x;
0132   firstPtyD=y;
0133   if(x<pxminD) pxminD=x;
0134   if(x>pxmaxD) pxmaxD=x;
0135   if(y<pyminD) pyminD=y;
0136   if(y>pymaxD) pymaxD=y;
0137  }
0138  xD=x;
0139  yD=y;
0140}
0141
0142int LineTo(int x1,int y1)
0143{
0144  int a,dx,dy,b,two_a,two_b,xcrit,eps;
0145  unsigned char i;
0146  if(polyD){
0147   if(x1<pxminD) pxminD=x1;
0148   if(x1>pxmaxD) pxmaxD=x1;
0149   if(y1<pyminD) pyminD=y1;
0150   if(y1>pymaxD) pymaxD=y1;
0151   if(xD*x1<0){
0152    if((xD*y1-yD*x1)/(xD-x1)<0) vertXD++;
0153   }
0154   if(yD*y1<0){
0155    if((yD*x1-xD*y1)/(yD-y1)<0) horiXD++;
0156   }
0157  }
0158  dx=1;
0159  a=x1-xD;
0160  if(a<0){
0161   dx=-1;
0162   a=-a;
0163  }
0164
0165  dy=1;
0166  b=y1-yD;
0167  if(b<0){
0168   dy=-1;
0169   b=-b;
0170  }
0171  two_a = 2*a;
0172  two_b = 2*b;
0173  xcrit = -b+two_a;
0174  eps=0;
0175
0176  for(;;){
0177    if(cliplD<=xD && xD<cliprD && cliptD<=yD && yD<clipbD){
0178     if(polyD){
0179      i=1<<(xD%8);
0180      poD[yD*polyWidthD+xD/8]|=i;
0181     }
0182     else *(pD+yD*widthD+xD)=coloD;
0183    }
0184    if(xD==x1&&yD==y1) break;
0185    if(eps<=xcrit) xD += dx, eps+=two_b;
0186    if(eps>=a || a<=b) yD += dy, eps-=two_a;
0187  }
0188}
0189
0190int OpenPoly()
0191{
0192  int i,j;
0193  for(j=0;j<heightD;j++)
0194   for(i=0;i<polyWidthD;i++) poD[j*polyWidthD+i]=0;
0195  polyD=1; // polygon mode on
0196  vertXD=0; // left-upper line crossings
0197  horiXD=0;
0198  pxminD=10000;
0199  pxmaxD=-10000;
0200  pyminD=10000;
0201  pymaxD=-10000;
0202}
0203
0204int ClosePoly()
0205{
0206  int transitD[31][3]; // first black points and last black points
0207                       // for three lines
0208  int cornerBlack;
0209  int i,j,k,l,i1,i2,i3,i4,i5,i6,i7,i8;
0210  unsigned char m;
0211
0212  LineTo(firstPtxD,firstPtyD); // close polygon
0213  polyD=0; // polygon mode off
0214  if(pxminD>=widthD) return; // out of view
0215  if(pxmaxD<0) return;
0216  if(pyminD>=heightD) return;
0217  if(pymaxD<0) return;
0218
0219  pxmaxD++; // past-the-boundary value
0220  pymaxD++;
0221
0222  if(pxminD<0) pxminD=0; // crossing rect
0223  if(pxmaxD>widthD) pxmaxD=widthD;
0224  if(pyminD<0) pyminD=0;
0225  if(pymaxD>heightD) pymaxD=heightD;
0226
0227  if(pxminD==(pxmaxD-1)) return;
0228  if(pyminD==(pymaxD-1)) return;
0229  
0230  cornerBlack=0; // upper left corner is white
0231  if(pxminD==0&&pyminD==0){
0232   if(vertXD%2==1) cornerBlack=1;
0233  }
0234
0235  for(j=pyminD;j<pymaxD;j++){
0236   for(k=0;k<31;k++){
0237    transitD[k][0]=transitD[k][1];
0238    transitD[k][1]=transitD[k][2];
0239    transitD[k][2]=-1;
0240   }
0241   k=0; // point white
0242   for(i=pxminD;i<pxmaxD;i++){
0243    m=poD[j*polyWidthD+i/8];
0244    if(m&(1<<(i%8))){ // black
0245     if(k%3==0){
0246      transitD[k][2]=i; // first black
0247      k++;
0248     }
0249    }
0250    else{ // white
0251     if(k%3==1){
0252      transitD[k][2]=i-1; // last black
0253      k+=2;
0254     }
0255    }
0256   } /* for(i=pxminD;i<pxmaxD;i++) */
0257   if(k%3==1){
0258    transitD[k][2]=i-1; // last point is black
0259    k+=2;
0260   }
0261   transitD[30][2]=k/3; // number of islands
0262   if(j>pyminD){ // if line 1 and abobe , process line 0
0263    for(k=0;k<transitD[30][1];k++){
0264     i1=transitD[3*k][1];
0265     i2=transitD[3*k+1][1];
0266     i3=0;
0267     for(i4=0;i4<transitD[30][2];i4++){
0268      i5=transitD[3*i4][2];
0269      i6=transitD[3*i4+1][2];
0270      if(i6>=(i1-1)&&i5<=(i2+1)) i3++;
0271     }
0272     transitD[3*k+2][1]=i3;
0273    }
0274   } /* if(j>pyminD) */
0275   if(j>pyminD+1){ // re-evaluate 3-line data and fill first line
0276    i1=0;
0277    for(k=0;k<transitD[30][0];k++) i1+=transitD[3*k+2][0];
0278    i2=0;
0279    for(k=0;k<transitD[30][1];k++) i2+=transitD[3*k+2][1];
0280    if(i1==i2-1){ // change somewhere in transitD[3*k+2][0] to 2
0281     for(k=0;k<transitD[30][0];k++) transitD[3*k+2][0]=transitD[3*k+2][1];
0282    }
0283    else if(i2==i1-1){
0284     for(k=0;k<transitD[30][1];k++){
0285      i1=transitD[3*k][1];
0286      i2=transitD[3*k+1][1];
0287      i3=0;
0288      for(i4=0;i4<transitD[30][0];i4++){
0289       i5=transitD[3*i4][0];
0290       i6=transitD[3*i4+1][0];
0291       if(i6>=(i1-1)&&i5<=(i2+1)) i3++;
0292      }
0293      if(i3==2&&transitD[3*k+2][1]==1) transitD[3*k+2][1]=0;
0294     }
0295    } /* else if(i2==i1-1) */
0296    i8=cornerBlack; // starting color
0297    i7=pxminD;
0298    for(k=0;k<transitD[30][0];k++){
0299     i1=transitD[3*k][0];
0300     if(i8){ // if black, paint from i7 to i1
0301      for(l=i7;l<i1;l++)
0302      poD[(j-2)*polyWidthD+l/8]|=(1<<l%8);
0303     }
0304     if(transitD[3*k+2][0]==1){
0305      if(i8==1) i8=0;
0306      else i8=1;
0307     }
0308     i7=transitD[3*k+1][0]+1;
0309    }
0310    if(i8==1&&i7<pxmaxD){ // paint to the end of line
0311     for(l=i7;l<pxmaxD;l++)
0312      poD[(j-2)*polyWidthD+l/8]|=(1<<l%8);
0313    }
0314   } /* if(j>pymind+1) */      
0315  } /* for(j=pyminD;j<pymaxD,j++) */
0316/* now do for last two lines */
0317  for(k=0;k<transitD[30][2];k++){
0318   i1=transitD[3*k][2];
0319   i2=transitD[3*k+1][2];
0320   i3=0;
0321   for(i4=0;i4<transitD[30][1];i4++){
0322    i5=transitD[3*i4][1];
0323    i6=transitD[3*i4+1][1];
0324    if(i6>=(i1-1)&&i5<=(i2+1)) i3++;
0325   }
0326   transitD[3*k+2][2]=i3;
0327  }
0328  i1=0;
0329  for(k=0;k<transitD[30][1];k++) i1+=transitD[3*k+2][1];
0330  i2=0;
0331  for(k=0;k<transitD[30][2];k++) i2+=transitD[3*k+2][2];
0332  if(i1==i2-1){ // change somewhere in transitD[3*k+2][0] to 0
0333   for(k=0;k<transitD[30][2];k++) transitD[3*k+2][2]=transitD[3*k+2][1];
0334  }
0335  for(j=0;j<2;j++){
0336   i8=cornerBlack;
0337   i7=pxminD;
0338   for(k=0;k<transitD[30][j+1];k++){
0339    i1=transitD[3*k][j+1];
0340    if(i8){ // if black, paint from i7 to i1
0341     for(l=i7;l<i1;l++)
0342      poD[(pymaxD-2+j)*polyWidthD+l/8]|=(1<<l%8);
0343    }
0344    if(transitD[3*k+2][j+1]==1){
0345     if(i8==1) i8=0;
0346     else i8=1;
0347    }
0348    i7=transitD[3*k+1][j+1]+1;
0349   }
0350   if(i8==1&&i7<pxmaxD){ // paint to the end of line
0351    for(l=i7;l<pxmaxD;l++)
0352     poD[(pymaxD-2+j)*polyWidthD+l/8]|=(1<<l%8);
0353   }
0354  }
0355/* now poD has been painted, next we will paint pD in coloD */
0356  for(j=pyminD;j<pymaxD;j++){
0357   for(i=pxminD;i<pxmaxD;i++){
0358    m=poD[j*polyWidthD+i/8];
0359    if(m&(1<<(i%8)))
0360      *(pD+j*widthD+i)=coloD;
0361   }
0362  }
0363}
0364
0365int FontInfo(int font,int direc,int mode)
0366{
0367 fontD=font;
0368 switch(font){
0369  case 11: // 6x11
0370   pfD=fontdata_6x11;
0371   ascentD=8;
0372   descentD=3;
0373   fontWidthD=6;
0374   fontHeightD=11;
0375   widthBytesD=1;
0376   fontBytesD=11;
0377   break;
0378  case 16: // 8x16
0379   pfD=fontdata_8x16;
0380   ascentD=11;
0381   descentD=5;
0382   fontWidthD=8;
0383   fontHeightD=16;
0384   widthBytesD=1;
0385   fontBytesD=16;
0386   break;
0387  case 22: // 12x22
0388   pfD=fontdata_12x22;
0389   ascentD=16;
0390   descentD=6;
0391   fontWidthD=12;
0392   fontHeightD=22;
0393   widthBytesD=2;
0394   fontBytesD=44;
0395   break;
0396 }
0397 direcD=direc;
0398 modeD=mode;
0399}
0400
0401int DrawString(char *c)
0402{
0403  long int dots[1056]; // up to and including double size of 12x22
0404  int h,i,j,k,l,m,n,k0,x,y;
0405  unsigned char test,mask;
0406
0407  if(modeD==0);
0408  else{
0409   i=strlen(c);
0410   i=i*fontWidthD;
0411   if(modeD==2) i/=2; /* center */
0412   if(direcD==0) xD-=i;
0413   else yD+=i;
0414  }
0415  for(h=0;c[h]!='\0';h++){
0416   k0=fontBytesD*(int)c[h];
0417   n=0;
0418   for(i=0;i<fontHeightD;i++){
0419    k=k0+i*widthBytesD;
0420    m=0;
0421    for(j=0;j<widthBytesD;j++){
0422      test=pfD[k+j];
0423      mask=0x80;
0424      for(l=0;l<8;l++){
0425	if(test&mask){
0426         if(direcD==0){ // horizontal
0427          y=yD-ascentD+i;
0428          x=xD+j*8+l;
0429         }
0430         else{ // vertical
0431          x=xD-ascentD+i;
0432          y=yD-j*8-l;
0433         }
0434         if(x>=0&&x<widthD&&y>=0&&y<heightD)
0435          dots[n++]=y*widthD+x;
0436        }
0437	mask>>=1;
0438	m++;
0439	if(m==fontWidthD) break;
0440      }
0441    }
0442   } /* for(i=0;i<fontHeightD;i++) */
0443   for(j=0;j<n;j++) *(pD+dots[j])=coloD;
0444   if(direcD==0) xD+=fontWidthD;
0445   else yD-=fontWidthD;
0446  } /* for(h=0;c[h]!='\0';h++) */
0447}
0448
0449int DrawNum(int i)
0450{
0451 char c[15];
0452 sprintf(c,"%i",i);
0453 DrawString(c);
0454}
0455
0456int DrawFNum(char *f,double a)
0457{
0458 char c[30];
0459 sprintf(c,f,a);
0460 DrawString(c);
0461} 
0462
0463int MakeGraph(int left,int top,int right,int bottom)
0464{
0465 lgD=left;
0466 tgD=top;
0467 rgD=right;
0468 bgD=bottom;
0469 htD=0;
0470}
0471
0472int HorizTime()
0473{
0474 htD=1;
0475}
0476
0477int format(int col,double num,char* fig)
0478{
0479 int i,j,colst,inte1,ncha;
0480 double a,frac;
0481 double inte;
0482 char c[10]={'0','1','2','3','4','5','6','7','8','9'};
0483
0484 ncha=0;
0485 i=0;
0486 if(num<0.){
0487  i++;
0488  fig[ncha++]='-';
0489  num=fabs(num);
0490 }
0491
0492 if(num!=0.){
0493  a=log10(num);
0494  frac=modf(a,&inte);
0495  colst=inte+0.1;
0496  if(colst<0) colst=0;
0497 }
0498 else colst=0;
0499        
0500 num+=pow(10,colst-6);
0501        
0502 frac=num/pow(10,colst);
0503 if(frac<1.&&frac>0.9999) frac=1.;
0504 for(j=colst;j>=0;j--){
0505  if(frac<1.&&frac>0.9999) frac=1.;
0506  frac=modf(frac,&inte)*10.;
0507  inte1=inte;
0508  i++;
0509  fig[ncha++]=c[inte1];
0510 }
0511
0512 if(col!=0){
0513  i++;
0514  fig[ncha++]='.';
0515  for(j=col;j>0;j--){
0516   if(frac<1.&&frac>0.9999) frac=1.;
0517   frac=modf(frac,&inte)*10.;
0518   inte1=inte;
0519   i++;
0520   fig[ncha++]=c[inte1];
0521  }
0522 }
0523 fig[ncha]='\0';
0524 return i;
0525}
0526
0527
0528int HorizScale(char *c,double left,double right)
0529{
0530 int i,j,ix,colx;
0531 double stepc,stepf,delta,intef,frac,num;
0532 char ar[12];
0533 double mdy,hms,scl;
0534 char *month[]={"Jan","Feb","Mar","Apr","May","Jun",
0535  "Jul","Aug","Sep","Oct","Nov","Dec"};
0536
0537 ldgD=left;
0538 rdgD=right;
0539 delta=right-left;
0540 MoveTo(lgD,bgD);
0541 LineTo(rgD,bgD);
0542if(htD==0){
0543 frac=modf(log10(delta),&intef);
0544 stepc=pow(10.,intef-1);
0545 stepf=stepc;
0546 if(frac<0.2) stepf*=0.5;
0547 else if(frac<0.8) stepc*=5.;
0548 else{
0549  stepc*=10.;
0550  stepf*=5.;
0551 }
0552 frac=modf(log10(stepc),&intef);
0553// if(log10(stepc)<0.) colx=-intef+1.;
0554 if(log10(stepc)<0.) colx=-log10(stepc)+0.8;
0555 else colx=0;
0556 frac=modf(left/stepc,&intef);
0557 frac=intef;
0558 while(1){
0559  num=frac*stepc;                        // x value for grid
0560  if(num>rdgD) break;
0561  ix=(rgD-lgD)*((num-ldgD)/(rdgD-ldgD))+lgD;
0562  i=format(colx,num,ar);
0563  MoveTo(ix,tgD);
0564  LineTo(ix,bgD+2);
0565  FontInfo(11,0,0);
0566  for(i=0;ar[i]!='\0';i++);
0567  MoveTo(ix-i*3,bgD+12);
0568  DrawString(ar);
0569  frac++;
0570 }
0571}
0572else{ /* horiz is time */
0573  mdy=mdyday(left);
0574  hms=hmsday(left);
0575  scl=(rgD-lgD)/delta;  /* dots per day */
0576  if(delta>700.){ /* yr */   
0577   frac=fmod(mdy*1000000.,10000.);
0578   while(1){
0579    num=refday(1.01+frac/1000000.,0.);     // x value for grid
0580    if(num>rdgD) break;
0581    ix=scl*(num-ldgD)+lgD;
0582    i=format(0,frac,ar);
0583    MoveTo(ix,tgD);
0584    LineTo(ix,bgD+2);
0585    if(num+182.>rdgD) break;
0586    FontInfo(11,0,2); /* center */
0587    ix=scl*(num+182.-ldgD)+lgD;
0588    MoveTo(ix,bgD+12);
0589    if(scl>0.07) DrawString(ar);
0590    else DrawString(&ar[2]);
0591    frac++; /* add a year */
0592   }
0593  }
0594  else if(delta>70.){ /* mo */
0595   stepc=fmod(mdy*1000000.,10000.); 
0596   stepf=floor(mdy);
0597   while(1){
0598    num=refday(stepf+0.01+stepc/1000000.,0.);     // x value for grid
0599    if(num>rdgD) break;
0600    if(num>ldgD){
0601     ix=scl*(num-ldgD)+lgD;
0602     MoveTo(ix,tgD);
0603     LineTo(ix,bgD+2);
0604    }
0605    if(num+15.>rdgD) break;
0606    FontInfo(11,0,2); /* center */
0607    ix=scl*(num+15.-ldgD)+lgD;
0608    MoveTo(ix,bgD+12);
0609    i=stepf;
0610    DrawString(month[i-1]);
0611    stepf++;
0612    if(stepf>12.1){
0613     stepf=1.;
0614     stepc++;
0615    }
0616   }
0617  }
0618  else if(delta>2.){ /* day */
0619   num=refday(mdy,0.);
0620   while(1){
0621    if(num>rdgD) break;
0622    stepf=mdyday(num);
0623    stepc=floor(stepf*100.);
0624    stepf=fmod(stepc,100.);
0625    i=1;
0626    if(scl<12.){
0627     if(fmod(num+0.001,7.)>1.) i=0;
0628    }
0629    if(num>ldgD){
0630     ix=scl*(num-ldgD)+lgD;
0631     MoveTo(ix,tgD);
0632     LineTo(ix,bgD+2*i);
0633    }
0634    if(i==1){
0635     if(num+0.5>rdgD) break;
0636     FontInfo(11,0,2); /* center */
0637     ix=scl*(num+0.5-ldgD)+lgD;
0638     MoveTo(ix,bgD+12);
0639     format(0,stepf,ar);
0640     DrawString(ar);
0641    }
0642    num++;
0643   }
0644  }
0645  else{ /* hour */
0646   stepc=floor(hms);
0647   num=refday(mdy,stepc);
0648   while(1){
0649    if(num>rdgD) break;
0650    if(num>ldgD){
0651     ix=scl*(num-ldgD)+lgD;
0652     MoveTo(ix,tgD);
0653     LineTo(ix,bgD+2);
0654    }
0655    if(num>rdgD) break;
0656    FontInfo(11,0,2); /* center */
0657    ix=scl*(num-ldgD)+lgD;
0658    MoveTo(ix,bgD+12);
0659    i=format(0,stepc,ar);
0660    DrawString(ar);
0661    stepc++;
0662    if(stepc>23.5) stepc=0;
0663    num+=0.041666666;
0664   }
0665  }
0666 }
0667 for(i=0;c[i]!='\0';i++);
0668 MoveTo((lgD+rgD-i*8)/2,bgD+22);
0669 FontInfo(16,0,0);
0670 DrawString(c);
0671}
0672
0673int VertScale(char *c,double bottom,double top)
0674{
0675 int i,j,iy,coly;
0676 double stepc,stepf,delta,intef,frac,num;
0677 char ar[12];
0678
0679 bdgD=bottom;
0680 tdgD=top;
0681 delta=top-bottom;
0682 frac=modf(log10(delta),&intef);
0683 stepc=pow(10.,intef-1);
0684 stepf=stepc;
0685 if(frac<0.2) stepf*=0.5;
0686 else if(frac<0.8) stepc*=5.;
0687 else{
0688  stepc*=10.;
0689  stepf*=5.;
0690 }
0691 MoveTo(lgD,tgD);
0692 LineTo(lgD,bgD);
0693
0694 frac=modf(log10(stepc),&intef);
0695// if(log10(stepc)<0.) coly=-intef+1.;
0696 if(log10(stepc)<0.) coly=-log10(stepc)+0.8;
0697 else coly=0;
0698 frac=modf(bottom/stepc,&intef);
0699 frac=intef;
0700 j=0;
0701 while(1){
0702  num=frac*stepc;                        // y value for grid
0703  if(num>tdgD) break;
0704  iy=(tgD-bgD)*((num-bdgD)/(tdgD-bdgD))+bgD;
0705  i=format(coly,num,ar);
0706  if(i>j) j=i;
0707  MoveTo(lgD-2,iy);
0708  LineTo(rgD,iy);
0709  FontInfo(11,0,0);
0710  for(i=0;ar[i]!='\0';i++);
0711  MoveTo(lgD-i*6-3,iy+3);
0712  DrawString(ar);
0713  frac++;
0714 }
0715 for(i=0;c[i]!='\0';i++);
0716 MoveTo(lgD-j*6-8,(bgD+tgD+i*8)/2);
0717 FontInfo(16,1,0);
0718 DrawString(c);
0719}
0720
0721int MoveToG(double x,double y)
0722{
0723 int savel,saver,savet,saveb;
0724 int ix,iy;
0725 
0726 savel=cliplD;
0727 saver=cliprD;
0728 savet=cliptD;
0729 saveb=clipbD;
0730 cliplD=lgD;
0731 cliprD=rgD;
0732 cliptD=tgD;
0733 clipbD=bgD;
0734
0735 ix=(rgD-lgD)*((x-ldgD)/(rdgD-ldgD))+lgD;
0736 iy=(tgD-bgD)*((y-bdgD)/(tdgD-bdgD))+bgD;
0737 MoveTo(ix,iy);
0738
0739 cliplD=savel;
0740 cliprD=saver;
0741 cliptD=savet;
0742 clipbD=saveb;
0743}
0744
0745int LineToG(double x,double y)
0746{
0747 int savel,saver,savet,saveb;
0748 int ix,iy;
0749 
0750 savel=cliplD;
0751 saver=cliprD;
0752 savet=cliptD;
0753 saveb=clipbD;
0754 cliplD=lgD;
0755 cliprD=rgD;
0756 cliptD=tgD;
0757 clipbD=bgD;
0758
0759 
0760 ix=(rgD-lgD)*((x-ldgD)/(rdgD-ldgD))+lgD;
0761 iy=(tgD-bgD)*((y-bdgD)/(tdgD-bdgD))+bgD;
0762 LineTo(ix,iy);
0763
0764 cliplD=savel;
0765 cliprD=saver;
0766 cliptD=savet;
0767 clipbD=saveb;
0768}
0769
0770int PlotG(int mark,double x,double y)
0771{
0772 int ix,iy;
0773
0774 ix=(rgD-lgD)*((x-ldgD)/(rdgD-ldgD))+lgD;
0775 iy=(tgD-bgD)*((x-bdgD)/(tdgD-bdgD))+bgD;
0776 MoveTo(ix-1,iy-1);
0777 LineTo(ix-1,iy+1);
0778 LineTo(ix+1,iy+1);
0779 LineTo(ix-1,iy+1);
0780 LineTo(ix,iy+1);
0781 LineTo(ix,iy);
0782}
0783 
0784
0785 
0786int GifOut()
0787{
0788  int i,j,k;
0789  unsigned char m;
0790  unsigned int step,red,green,blue;
0791
0792  int ctSize=256;
0793  int *prec;
0794  unsigned char *color;
0795  unsigned char pc[2000];
0796  int ipc,nn,n,nnstart,nstart;
0797  int bitsmin;
0798  int kstart;
0799  int clrcode;
0800
0801#ifdef CGI
0802  printf("Content-type: image/gif\n\n");
0803#else
0804  fpD=fopen("test.gif","wb");
0805#endif
0806
0807  prec=(int *)malloc(4097*sizeof(int));	// code up to 12 bits
0808  color=(unsigned char*)malloc(4097*sizeof(unsigned char));
0809  for(i=0;i<4097;i++) prec[i]=-1;
0810
0811#ifdef CGI
0812  printf("GIF89a");
0813#else
0814  fprintf(fpD,"GIF89a");
0815#endif
0816  
0817#ifdef CGI
0818  fwrite((char *)&widthD,sizeof(char),2,stdout);
0819  fwrite((char *)&heightD,sizeof(char),2,stdout);
0820#else
0821  fwrite((char *)&widthD,sizeof(char),2,fpD);
0822  fwrite((char *)&heightD,sizeof(char),2,fpD);
0823#endif
0824  sizeOfCTD=7; // class variable
0825  m=0xF0|sizeOfCTD;
0826#ifdef CGI
0827  fwrite(&m,sizeof(char),1,stdout);
0828#else
0829  fwrite(&m,sizeof(char),1,fpD);
0830#endif
0831  m=0; // Background Color Index
0832#ifdef CGI
0833  fwrite(&m,sizeof(char),1,stdout);
0834#else
0835  fwrite(&m,sizeof(char),1,fpD);
0836#endif
0837  m=0; // Pixel Aspect Ratio
0838#ifdef CGI
0839  fwrite(&m,sizeof(char),1,stdout);
0840#else
0841  fwrite(&m,sizeof(char),1,fpD);
0842#endif
0843  step=0xFFFF/5;
0844  for(i=5;i>=0;i--){
0845    red=i*step;
0846    for(j=5;j>=0;j--){
0847      green=j*step;
0848      for(k=5;k>=0;k--){
0849	blue=k*step;
0850	if(i!=0||j!=0||k!=0){
0851#ifdef CGI
0852          fwrite(&red,sizeof(char),1,stdout);
0853          fwrite(&green,sizeof(char),1,stdout);
0854          fwrite(&blue,sizeof(char),1,stdout);
0855#else
0856          fwrite(&red,sizeof(char),1,fpD);
0857          fwrite(&green,sizeof(char),1,fpD);
0858          fwrite(&blue,sizeof(char),1,fpD);
0859#endif
0860	}
0861      }
0862    }
0863  }
0864  step=0xFFFF/15;
0865  green=0;
0866  blue=0;
0867  for(i=14;i>0;i--){
0868    if(i%3!=0){
0869      red=i*step;
0870#ifdef CGI
0871          fwrite(&red,sizeof(char),1,stdout);
0872          fwrite(&green,sizeof(char),1,stdout);
0873          fwrite(&blue,sizeof(char),1,stdout);
0874#else
0875          fwrite(&red,sizeof(char),1,fpD);
0876          fwrite(&green,sizeof(char),1,fpD);
0877          fwrite(&blue,sizeof(char),1,fpD);
0878#endif
0879    }
0880  }
0881  red=0;
0882  blue=0;
0883  for(i=14;i>0;i--){
0884    if(i%3!=0){
0885      green=i*step;
0886#ifdef CGI
0887          fwrite(&red,sizeof(char),1,stdout);
0888          fwrite(&green,sizeof(char),1,stdout);
0889          fwrite(&blue,sizeof(char),1,stdout);
0890#else
0891          fwrite(&red,sizeof(char),1,fpD);
0892          fwrite(&green,sizeof(char),1,fpD);
0893          fwrite(&blue,sizeof(char),1,fpD);
0894#endif
0895    }
0896  }
0897  red=0;
0898  green=0;
0899  for(i=14;i>0;i--){
0900    if(i%3!=0){
0901      blue=i*step;
0902#ifdef CGI
0903          fwrite(&red,sizeof(char),1,stdout);
0904          fwrite(&green,sizeof(char),1,stdout);
0905          fwrite(&blue,sizeof(char),1,stdout);
0906#else
0907          fwrite(&red,sizeof(char),1,fpD);
0908          fwrite(&green,sizeof(char),1,fpD);
0909          fwrite(&blue,sizeof(char),1,fpD);
0910#endif
0911    }
0912  }
0913  for(i=14;i>0;i--){
0914    if(i%3!=0){
0915      red=green=blue=i*step;
0916#ifdef CGI
0917          fwrite(&red,sizeof(char),1,stdout);
0918          fwrite(&green,sizeof(char),1,stdout);
0919          fwrite(&blue,sizeof(char),1,stdout);
0920#else
0921          fwrite(&red,sizeof(char),1,fpD);
0922          fwrite(&green,sizeof(char),1,fpD);
0923          fwrite(&blue,sizeof(char),1,fpD);
0924#endif
0925    }
0926  }
0927  red=0;
0928  green=0;
0929  blue=0;
0930#ifdef CGI
0931          fwrite(&red,sizeof(char),1,stdout);
0932          fwrite(&green,sizeof(char),1,stdout);
0933          fwrite(&blue,sizeof(char),1,stdout);
0934#else
0935          fwrite(&red,sizeof(char),1,fpD);
0936          fwrite(&green,sizeof(char),1,fpD);
0937          fwrite(&blue,sizeof(char),1,fpD);
0938#endif
0939
0940  m=0x2c; // image separator
0941#ifdef CGI
0942  fwrite(&m,sizeof(char),1,stdout);
0943#else
0944  fwrite(&m,sizeof(char),1,fpD);
0945#endif
0946  
0947  i=0; // image left position
0948#ifdef CGI
0949  fwrite((char *)&i,sizeof(char),2,stdout);
0950#else
0951  fwrite((char *)&i,sizeof(char),2,fpD);
0952#endif
0953  i=0; // image top position
0954#ifdef CGI
0955  fwrite((char *)&i,sizeof(char),2,stdout);
0956  fwrite((char *)&widthD,sizeof(char),2,stdout);
0957  fwrite((char *)&heightD,sizeof(char),2,stdout);
0958#else
0959  fwrite((char *)&i,sizeof(char),2,fpD);
0960  fwrite((char *)&widthD,sizeof(char),2,fpD);
0961  fwrite((char *)&heightD,sizeof(char),2,fpD);
0962#endif
0963  m=0x00|sizeOfCTD;
0964#ifdef CGI
0965  fwrite(&m,sizeof(char),1,stdout);
0966#else
0967  fwrite(&m,sizeof(char),1,fpD);
0968#endif
0969
0970  m++; // LZW minimum code size 8
0971  if(m==1) m=2;
0972#ifdef CGI
0973  fwrite(&m,sizeof(char),1,stdout);
0974#else
0975  fwrite(&m,sizeof(char),1,fpD);
0976#endif
0977  clrcode=1<<m; // clear code 0x100
0978  bitsD=m+1; // output number of bits 9
0979  bitsmin=bitsD; // initial number of bits
0980  for(i=0;i<ctSize;i++) color[i]=i; // the first 256 of 4097 colors
0981  for(i=0;i<260;i++) outBufD[i]=0;
0982  bitPtrD=0; // initialize output buffer
0983  emit(clrcode);
0984  ipc=0; // index for already-seen-color-sequence pc[]
0985  nnstart=0; // initial index value for nn used for pc[]
0986  nstart=clrcode+2; // n is index for preceeding code, prec
0987  for(j=0;j<heightD;j++){
0988    for(i=0;i<widthD;i++){
0989      m=pD[widthD*j+i]; // CHARACTER
0990      pc[ipc++]=m; // STRING add to already-seen-sequence
0991      nn=nnstart; // index for pc[] used at comparing
0992      if(nn==0){ // first time and immediately after emit
0993	// for(k=0;k<ctSize;k++) if(color[k]==pc[nn]) break;
0994	k=pc[nn]; // equivalent to the above expression
0995	nn++;
0996      }
0997      else k=kstart; // code to be compared
0998     if(lzw){ // compress
0999      for(n=nstart;prec[n]!=-1;n++){ // matched upto and including nn-1 and n-1
1000	if(nn==ipc) break; // same as previously-seen-color-sequence
1001	if(prec[n]==k){
1002	  if(color[n]==pc[nn]){
1003	    nn++;
1004	    k=n;
1005	  }
1006	}
1007      }
1008      if(nn==ipc-1){ // if there is no previously-seen-color-sequence
1009	emit(k); // output code for hether-to matching sequence
1010	prec[n]=k; // add the code to dictionary
1011	color[n]=pc[ipc-1]; // add next-to-code-color in dictionary
1012	if(n>>bitsD) bitsD++;
1013	if(n==0xFFF){
1014	  emit(clrcode);
1015	  bitsD=bitsmin;
1016	  for(n=0;n<4097;n++) prec[n]=-1;
1017	}
1018	pc[0]=m; // lastly-read color comes first in color array
1019	ipc=1;
1020	nnstart=0; //position of color array to be compared
1021	nstart=clrcode+2; // position of dictionary to be compared
1022      }
1023      else{ // when there is a previous instance
1024	nnstart=nn; // position of color array to be compared
1025	nstart=n; // position of dictionary to be compared
1026	kstart=k; // code to be compared
1027      }
1028     }
1029     else{ // not compress
1030	emit(m); // output code for hether-to matching sequence
1031	emit(clrcode);
1032	pc[0]=m; // lastly-read color comes first in color array
1033	ipc=1;
1034	nnstart=0; //position of color array to be compared
1035     }
1036    }
1037  }
1038  if(ipc==1){
1039    for(k=0;k<ctSize;k++) if(color[k]==pc[0]) break;
1040  }
1041  if(lzw) emit(k);
1042  n++;
1043  if(n>>bitsD) bitsD++;
1044
1045  emit(clrcode);
1046  bitsD=bitsmin;
1047
1048  emit(clrcode+1);
1049  i=bitPtrD/8;
1050  if((bitPtrD%8)!=0) i++;
1051#ifdef CGI
1052  fwrite((char *)&i,sizeof(char),1,stdout);
1053  fwrite((char *)outBufD,sizeof(char),i,stdout);
1054#else
1055  fwrite((char *)&i,sizeof(char),1,fpD);
1056  fwrite((char *)outBufD,sizeof(char),i,fpD);
1057#endif
1058  m=0;
1059#ifdef CGI
1060  fwrite((char *)&m,sizeof(char),1,stdout);
1061#else
1062  fwrite((char *)&m,sizeof(char),1,fpD);
1063#endif
1064  m=0x3b;
1065#ifdef CGI
1066  fwrite((char *)&m,sizeof(char),1,stdout);
1067#else
1068  fwrite((char *)&m,sizeof(char),1,fpD);
1069  fclose(fpD);
1070#endif
1071
1072//  delete[] prec;
1073//  delete[] color;
1074
1075
1076}
1077
1078
1079void emit(int k)
1080{
1081  int i,j,m,n;
1082
1083  for(i=0;i<bitsD;i++){ // do for current number of bits
1084    m=bitPtrD/8; // put in n-th bit of m-th byte
1085    n=bitPtrD%8;
1086    j=k;
1087    j>>=i;
1088    j&=1;
1089    j<<=n;
1090    outBufD[m]|=j; // outBuf is char , j is int
1091    bitPtrD++;
1092  }
1093
1094  if(m>254){
1095    i=0xFF;
1096#ifdef CGI
1097  fwrite((char *)&i,sizeof(char),1,stdout);
1098  fwrite((char *)outBufD,sizeof(char),255,stdout);
1099#else
1100  fwrite((char *)&i,sizeof(char),1,fpD);
1101  fwrite((char *)outBufD,sizeof(char),255,fpD);
1102#endif
1103    bitPtrD-=255*8;
1104    outBufD[0]=outBufD[255];
1105    outBufD[1]=outBufD[256];
1106    for(i=2;i<257;i++) outBufD[i]=0;
1107  }
1108}
1109
1110int PngOut()
1111{
1112  unsigned char signa[]={137,80,78,71,13,10,26,10};
1113  unsigned char *chunk;
1114
1115  int i,j,k,l,m,n;
1116  int i1,j1,k1,l1,m1,n1;
1117  int i2,j2,k2,l2,m2,n2;
1118  unsigned int step,red,green,blue;
1119  int lmatch,dmatch;
1120  int wdopen;
1121  unsigned long adler=1L;
1122  unsigned long s1,s2;
1123
1124
1125  chunk=(unsigned char *)malloc(100000*sizeof(char)); /* this size must be related to picture size */
1126  for(l=0;l<100000;l++) chunk[l]=0;
1127#ifdef CGI
1128  printf("Content-type: image/png\n\n");
1129  fwrite((char *)signa,sizeof(char),8,stdout);
1130#else
1131  fpD=fopen("test.png","wb");
1132  fwrite((char *)signa,sizeof(char),8,fpD);
1133#endif
1134  *(int *)&chunk[0]=13; // excluding length, type or crc
1135  revPng(&chunk[0]);
1136  chunk[4]='I';
1137  chunk[5]='H';
1138  chunk[6]='D';
1139  chunk[7]='R';
1140  *(int *)&chunk[8]=widthD;
1141  revPng(&chunk[8]);
1142  *(int *)&chunk[12]=heightD;
1143  revPng(&chunk[12]);
1144  chunk[16]=8; /* bit depth */
1145  chunk[17]=3; /* color type - palette index */
1146  chunk[18]=0; /* compression method - deflate */
1147  chunk[19]=0; /* filter method */
1148  chunk[20]=0; /* interlace method */
1149  crcPng(&chunk[4],17); // including chunk type and chunk data
1150#ifdef CGI
1151  fwrite((char *)chunk,sizeof(char),25,stdout);
1152#else
1153  fwrite((char *)chunk,sizeof(char),25,fpD);
1154#endif
1155  *(int *)&chunk[0]=768; // 256*3
1156  revPng(&chunk[0]);
1157  chunk[4]='P';
1158  chunk[5]='L';
1159  chunk[6]='T';
1160  chunk[7]='E';
1161  l=8;
1162  step=0xFFFF/5;
1163  for(i=5;i>=0;i--){
1164    red=i*step;
1165    for(j=5;j>=0;j--){
1166      green=j*step;
1167      for(k=5;k>=0;k--){
1168	blue=k*step;
1169	if(i!=0||j!=0||k!=0){
1170          chunk[l++]=red;
1171          chunk[l++]=green;
1172          chunk[l++]=blue;
1173	}
1174      }
1175    }
1176  }
1177  step=0xFFFF/15;
1178  green=0;
1179  blue=0;
1180  for(i=14;i>0;i--){
1181    if(i%3!=0){
1182      red=i*step;
1183      chunk[l++]=red;
1184      chunk[l++]=green;
1185      chunk[l++]=blue;
1186    }
1187  }
1188  red=0;
1189  blue=0;
1190  for(i=14;i>0;i--){
1191    if(i%3!=0){
1192      green=i*step;
1193      chunk[l++]=red;
1194      chunk[l++]=green;
1195      chunk[l++]=blue;
1196    }
1197  }
1198  red=0;
1199  green=0;
1200  for(i=14;i>0;i--){
1201    if(i%3!=0){
1202      blue=i*step;
1203      chunk[l++]=red;
1204      chunk[l++]=green;
1205      chunk[l++]=blue;
1206    }
1207  }
1208  for(i=14;i>0;i--){
1209    if(i%3!=0){
1210      red=green=blue=i*step;
1211      chunk[l++]=red;
1212      chunk[l++]=green;
1213      chunk[l++]=blue;
1214    }
1215  }
1216  red=0;
1217  green=0;
1218  blue=0;
1219  chunk[l++]=red;
1220  chunk[l++]=green;
1221  chunk[l++]=blue;
1222  crcPng(&chunk[4],768+4);
1223#ifdef CGI
1224  fwrite((char *)chunk,sizeof(char),780,stdout);
1225#else
1226  fwrite((char *)chunk,sizeof(char),780,fpD);
1227#endif
1228  for(l=0;l<780;l++) chunk[l]=0;
1229/** LZ77 conpression **/
1230  chunk[4]='I';
1231  chunk[5]='D';
1232  chunk[6]='A';
1233  chunk[7]='T';
1234  chunk[8]=0x78; /* compression methodflag code */
1235  chunk[9]=0x9c; /* additional flagscheck bits */
1236  i1=10; // initial code byte
1237  j1=0; // initial bit position
1238  setPng(chunk,i1,j1,3,3,&i1,&j1); // three header bit for the block
1239                                   // final & fixed Huffman code
1240  l=heightD*widthD; /* insert filter type byte */
1241  for(n=heightD-1;n>=0;n--){
1242   k=n*(widthD+1);
1243   for(m=widthD;m>0;m--) pD[k+m]=pD[--l];
1244   pD[k]=0;
1245  }
1246  wdopen=0;
1247  l=heightD*(widthD+1);
1248  for(n=0;n<l;n++){
1249   lmatch=0;
1250   if(n<32768) wdopen=0;
1251   else wdopen=n-32768;
1252   for(m=n-1;m>=wdopen;m--){
1253    j=n;
1254    k=m;
1255    i=0;
1256    while(pD[j++]==pD[k++]){
1257     i++;
1258     if(i==258) break;
1259     if(j>=l) break;
1260    }
1261    if(i>lmatch){
1262     lmatch=i; /* length */
1263     dmatch=n-m; /* distance */
1264    }
1265    if(lmatch==258||j>=l) break;
1266   }
1267   l1=0; // number of extra bits
1268   m1=0; // value of extra bits
1269   if(lmatch<3) k1=pD[n];  // raw data
1270   else{
1271    if(lmatch<11) k1=254+lmatch;
1272    else if(lmatch<19){
1273     l1=1;
1274     k1=(lmatch-11)/2+265;
1275     m1=(lmatch-11)%2;
1276    }
1277    else if(lmatch<35){
1278     l1=2;
1279     k1=(lmatch-19)/4+269;
1280     m1=(lmatch-19)%4;
1281    }
1282    else if(lmatch<67){
1283     l1=3;
1284     k1=(lmatch-35)/8+273;
1285     m1=(lmatch-35)%8;
1286    }
1287    else if(lmatch<131){
1288     l1=4;
1289     k1=(lmatch-67)/16+277;
1290     m1=(lmatch-67)%16;
1291    }
1292    else if(lmatch<258){
1293     l1=5;
1294     k1=(lmatch-131)/32+281;
1295     m1=(lmatch-131)%32;
1296    }
1297    else k1=285;
1298   } /* else */
1299/* convert alphabet k1 to Huffman code */
1300   if(k1<144){
1301    n1=0x30+k1; // Huffman code
1302    i2=0x80; // mask for output
1303   }
1304   else if(k1<256){
1305    n1=0x190+k1-144;
1306    i2=0x100;
1307   }
1308   else if(k1<280){
1309    n1=0x0+k1-256;
1310    i2=0x40;
1311   }
1312   else{
1313    n1=0xc0+k1-280;
1314    i2=0x80;
1315   }
1316   for(;i2>0;i2/=2){
1317    if(n1&i2) setPng(chunk,i1,j1,1,1,&i1,&j1);
1318    else setPng(chunk,i1,j1,0,1,&i1,&j1);
1319   }
1320   if(l1>0) setPng(chunk,i1,j1,m1,l1,&i1,&j1); /* extra bits for length */
1321   if(k1>256){ /* distance in dmatch */
1322    m2=1;
1323    for(l2=1;;l2++){
1324     m2*=2;
1325     if(m2>=dmatch) break;
1326    }
1327    k1=l2*2-1; // code 
1328               //     dmatch<= k1 l2 extra-bits
1329               //        2      1   1    0
1330               //        4      3   2    0
1331               //        8      5   3    1
1332               //       16      7   4    2
1333               //       32      9   5    3
1334    l1=l2-2;   // number of extra bits
1335    if(l1<0) l1=0;
1336               // m2       2   2   4   4   8   8   8   8  16  16  16
1337               // dmatch   1   2   3   4   5   6   7   8   9  10  11
1338               // l2       1   1   2   2   3   3   3   3   4   4   4
1339               // k1       1   1   3   3   5   5   5   5   7   7   7
1340               // l1       0   0   0   0   1   1   1   1   2   2   2 ->number of extra bits
1341               // n2       1   1   1   1   2   2   2   2   4   4   4
1342               // m2-n2    1   1   3   3   6   6   6   6  12  12  12
1343               // k1       0  (1)  2  (3)  4   4  (5) (5)  6   6   6 ->code
1344               // m2       1   2   3   4   6   6   8   8  12  12  12
1345               // m2-n2    0   1   2   3   4   4   6   6   8   8   8
1346               // m1       1   1   1   1   1   2   1   2   1   2   3
1347               // m1       0   0   0   0   0   1   0   1   0   1   2 ->extra bit value
1348    n2=pow(2,l1);
1349    if(dmatch<=m2-n2){
1350     k1--;
1351     m2=m2-n2;
1352    }
1353    m1=dmatch-(m2-n2);
1354    m1--;    // value of extra bits
1355
1356    i2=0x10; // 5 bits
1357    for(;i2>0;i2/=2){
1358     if(k1&i2) setPng(chunk,i1,j1,1,1,&i1,&j1);
1359     else setPng(chunk,i1,j1,0,1,&i1,&j1);
1360    }
1361    if(l1>0) setPng(chunk,i1,j1,m1,l1,&i1,&j1); /* extra bits for distance */
1362    n+=lmatch-1; /* advance main loop counter - 1 incremented later */
1363   } /* if(k1>256) */
1364  } /* for(n=0;n<l;n++){ */
1365  i2=0x40; // 7 bits - end of block mark
1366  for(;i2>0;i2/=2){ // huffman code for 256 is 0
1367   if(0&i2) setPng(chunk,i1,j1,1,1,&i1,&j1);
1368   else setPng(chunk,i1,j1,0,1,&i1,&j1);
1369  }
1370/* Adler-32 : a check sum value of the uncompressed data */
1371  s1=adler&0xffff;
1372  s2=(adler>>16)&0xffff;
1373  for(n=0;n<l;n++){
1374   s1=(s1+pD[n])%65521;
1375   s2=(s2+s1)%65521;
1376  }
1377  if(j1!=0) i1++;
1378  *(unsigned long *)&chunk[i1]=(s2<<16)+s1;
1379  revPng(&chunk[i1]);
1380  i1+=4;  /* pointer index to crc */
1381  *(int *)&chunk[0]=i1-8; /* data length */
1382  revPng(&chunk[0]);
1383  crcPng(&chunk[4],i1-4);
1384  i1+=4; /* number of bytes including crc */
1385#ifdef CGI
1386  fwrite((char *)chunk,sizeof(char),i1,stdout);
1387#else
1388  fwrite((char *)chunk,sizeof(char),i1,fpD);
1389#endif
1390  *(int *)&chunk[0]=0; /* data length */
1391  revPng(&chunk[0]);
1392  chunk[4]='I';
1393  chunk[5]='E';
1394  chunk[6]='N';
1395  chunk[7]='D';
1396  crcPng(&chunk[4],4);
1397
1398#ifdef CGI
1399  fwrite((char *)chunk,sizeof(char),12,stdout);
1400#else
1401  fwrite((char *)chunk,sizeof(char),12,fpD);
1402  fclose(fpD);
1403#endif
1404
1405}
1406
1407void revPng(unsigned char *c)
1408{
1409 unsigned char a;
1410 a=c[0];
1411 c[0]=c[3];
1412 c[3]=a;
1413 a=c[1];
1414 c[1]=c[2];
1415 c[2]=a;
1416}
1417
1418/*********************************************
1419  Pad data into chunk
1420  chunk : chunk array
1421  byte : index into chunk array
1422  bit : bit position (0(lsb)-7(msb))
1423  val : data to be set
1424  nbit : number of bits of val
1425  *nxtbyte : next index to be returned
1426  *nxtbit : next bit position to be returned
1427********************************************/
1428void setPng(unsigned char *chunk,int byte,int bit,
1429        int val,int nbit,int *nxtbyte,int *nxtbit)
1430{
1431 unsigned char c1,c2;
1432 unsigned char cin[4];
1433 unsigned char mask,mask1;
1434 int sourcebyte,destbyte,sourcebit,destbit;
1435 int i;
1436
1437 sourcebyte=0;
1438 sourcebit=0;
1439 destbyte=byte;
1440 destbit=bit;
1441 *(unsigned long*)cin=val;
1442 for(i=0;i<nbit;i++){
1443  mask=1;
1444  mask<<=sourcebit;
1445  c1=cin[sourcebyte];
1446  if(c1&mask){
1447   mask=1;
1448   mask<<=destbit;
1449   chunk[destbyte]|=mask;
1450  }
1451  sourcebit++;
1452  if(sourcebit==8){
1453   sourcebyte++;
1454   sourcebit=0;
1455  }
1456  destbit++;
1457  if(destbit==8){
1458   destbyte++;
1459   destbit=0;
1460  }
1461 }
1462 *nxtbyte=destbyte;
1463 *nxtbit=destbit;
1464}
1465
1466
1467/**********************************************
1468  CRC - ported from W3C specification
1469  Return the CRC of the bytes buf[0]..[len-1]
1470  in buf[len]..[len+3] 
1471**********************************************/
1472void crcPng(unsigned char *buf,int len)
1473{
1474 unsigned long c;
1475 int n,k;
1476
1477 if(!crc_table_computed){
1478  for(n=0;n<256;n++){
1479   c=(unsigned long)n;
1480   for(k=0;k<8;k++){
1481    if(c&1) c=0xedb88320L^(c>>1);
1482    else c=c>>1;
1483   }
1484   crc_table[n]=c;
1485  }
1486  crc_table_computed=1;
1487 }
1488 c=0xffffffffL;
1489 for(n=0;n<len;n++){
1490  c=crc_table[(c^buf[n])&0xff]^(c>>8);
1491 }
1492 *(int *)&buf[len]=c^0xffffffffL;
1493 revPng(&buf[len]);
1494}
1495