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,hlD,vlD;
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+1)*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 hlD=0;
0471 vlD=0;
0472}
0473
0474int HorizTime()
0475{
0476 htD=1;
0477}
0478
0479int HorizLog()
0480{
0481 hlD=1;
0482}
0483
0484int VertLog()
0485{
0486 vlD=1;
0487}
0488
0489int format(int col,double num,char* fig)
0490{
0491 int i,j,colst,inte1,ncha;
0492 double a,frac;
0493 double inte;
0494 char c[10]={'0','1','2','3','4','5','6','7','8','9'};
0495
0496 ncha=0;
0497 i=0;
0498 if(num<0.){
0499 i++;
0500 fig[ncha++]='-';
0501 num=fabs(num);
0502 }
0503
0504 if(num!=0.){
0505 a=log10(num);
0506 frac=modf(a,&inte);
0507 colst=inte+0.1;
0508 if(colst<0) colst=0;
0509 }
0510 else colst=0;
0511
0512 num+=pow(10,colst-6);
0513
0514 frac=num/pow(10,colst);
0515 if(frac<1.&&frac>0.9999) frac=1.;
0516 for(j=colst;j>=0;j--){
0517 if(frac<1.&&frac>0.9999) frac=1.;
0518 frac=modf(frac,&inte)*10.;
0519 inte1=inte;
0520 i++;
0521 fig[ncha++]=c[inte1];
0522 }
0523
0524 if(col!=0){
0525 i++;
0526 fig[ncha++]='.';
0527 for(j=col;j>0;j--){
0528 if(frac<1.&&frac>0.9999) frac=1.;
0529 frac=modf(frac,&inte)*10.;
0530 inte1=inte;
0531 i++;
0532 fig[ncha++]=c[inte1];
0533 }
0534 }
0535 fig[ncha]='\0';
0536 return i;
0537}
0538
0539
0540int HorizScale(char *c,double left,double right)
0541{
0542 int i,j,ix,colx;
0543 double stepc,stepf,delta,intef,frac,num;
0544 char ar[12];
0545 double mdy,hms,scl;
0546 char *month[]={"Jan","Feb","Mar","Apr","May","Jun",
0547 "Jul","Aug","Sep","Oct","Nov","Dec"};
0548
0549 ldgD=left;
0550 rdgD=right;
0551 delta=right-left;
0552 MoveTo(lgD,bgD);
0553 LineTo(rgD,bgD);
0554if(htD==0){
0555 frac=modf(log10(delta),&intef);
0556 stepc=pow(10.,intef-1);
0557 stepf=stepc;
0558 if(frac<0.2) stepf*=0.5;
0559 else if(frac<0.8) stepc*=5.;
0560 else{
0561 stepc*=10.;
0562 stepf*=5.;
0563 }
0564 frac=modf(log10(stepc),&intef);
0565// if(log10(stepc)<0.) colx=-intef+1.;
0566 if(log10(stepc)<0.) colx=-log10(stepc)+0.8;
0567 else colx=0;
0568 frac=modf(left/stepc,&intef);
0569 frac=intef;
0570 if(hlD){
0571 stepc=1.;
0572 colx=0;
0573 }
0574 while(1){
0575 num=frac*stepc; // x value for grid
0576 if(num>rdgD) break;
0577 ix=(rgD-lgD)*((num-ldgD)/(rdgD-ldgD))+lgD;
0578 i=format(colx,num,ar);
0579 MoveTo(ix,tgD);
0580 LineTo(ix,bgD+2);
0581 FontInfo(11,0,0);
0582 for(i=0;ar[i]!='\0';i++);
0583 if(hlD){
0584 MoveTo(ix-i*3+4,bgD+12);
0585 DrawString(ar);
0586 MoveTo(ix-i*3-6,bgD+20);
0587 DrawString("10");
0588 }
0589 else{
0590 MoveTo(ix-i*3,bgD+12);
0591 DrawString(ar);
0592 }
0593 frac++;
0594 }
0595}
0596else{ /* horiz is time */
0597 mdy=mdyday(left);
0598 hms=hmsday(left);
0599 scl=(rgD-lgD)/delta; /* dots per day */
0600 if(delta>700.){ /* yr */
0601 frac=fmod(mdy*1000000.,10000.);
0602 while(1){
0603 num=refday(1.01+frac/1000000.,0.); // x value for grid
0604 if(num>rdgD) break;
0605 ix=scl*(num-ldgD)+lgD;
0606 i=format(0,frac,ar);
0607 MoveTo(ix,tgD);
0608 LineTo(ix,bgD+2);
0609 if(num+182.>rdgD) break;
0610 FontInfo(11,0,2); /* center */
0611 ix=scl*(num+182.-ldgD)+lgD;
0612 MoveTo(ix,bgD+12);
0613 if(scl>0.07) DrawString(ar);
0614 else DrawString(&ar[2]);
0615 frac++; /* add a year */
0616 }
0617 }
0618 else if(delta>70.){ /* mo */
0619 stepc=fmod(mdy*1000000.,10000.);
0620 stepf=floor(mdy);
0621 while(1){
0622 num=refday(stepf+0.01+stepc/1000000.,0.); // x value for grid
0623 if(num>rdgD) break;
0624 if(num>ldgD){
0625 ix=scl*(num-ldgD)+lgD;
0626 MoveTo(ix,tgD);
0627 LineTo(ix,bgD+2);
0628 }
0629 if(num+15.>rdgD) break;
0630 FontInfo(11,0,2); /* center */
0631 ix=scl*(num+15.-ldgD)+lgD;
0632 MoveTo(ix,bgD+12);
0633 i=stepf;
0634 DrawString(month[i-1]);
0635 stepf++;
0636 if(stepf>12.1){
0637 stepf=1.;
0638 stepc++;
0639 }
0640 }
0641 }
0642 else if(delta>2.){ /* day */
0643 num=refday(mdy,0.);
0644 while(1){
0645 if(num>rdgD) break;
0646 stepf=mdyday(num);
0647 stepc=floor(stepf*100.);
0648 stepf=fmod(stepc,100.);
0649 i=1;
0650 if(scl<12.){
0651 if(fmod(num+0.001,7.)>1.) i=0;
0652 }
0653 if(num>ldgD){
0654 ix=scl*(num-ldgD)+lgD;
0655 MoveTo(ix,tgD);
0656 LineTo(ix,bgD+2*i);
0657 }
0658 if(i==1){
0659 if(num+0.5>rdgD) break;
0660 FontInfo(11,0,2); /* center */
0661 ix=scl*(num+0.5-ldgD)+lgD;
0662 MoveTo(ix,bgD+12);
0663 format(0,stepf,ar);
0664 DrawString(ar);
0665 }
0666 num++;
0667 }
0668 }
0669 else{ /* hour */
0670 stepc=floor(hms);
0671 num=refday(mdy,stepc);
0672 while(1){
0673 if(num>rdgD) break;
0674 if(num>ldgD){
0675 ix=scl*(num-ldgD)+lgD;
0676 MoveTo(ix,tgD);
0677 LineTo(ix,bgD+2);
0678 }
0679 if(num>rdgD) break;
0680 FontInfo(11,0,2); /* center */
0681 ix=scl*(num-ldgD)+lgD;
0682 MoveTo(ix,bgD+12);
0683 i=format(0,stepc,ar);
0684 DrawString(ar);
0685 stepc++;
0686 if(stepc>23.5) stepc=0;
0687 num+=0.041666666;
0688 }
0689 }
0690 }
0691 for(i=0;c[i]!='\0';i++);
0692 if(hlD) MoveTo((lgD+rgD-i*8)/2,bgD+33);
0693 else MoveTo((lgD+rgD-i*8)/2,bgD+22);
0694 FontInfo(16,0,0);
0695 DrawString(c);
0696}
0697
0698int VertScale(char *c,double bottom,double top)
0699{
0700 int i,j,iy,coly;
0701 double stepc,stepf,delta,intef,frac,num;
0702 char ar[12];
0703
0704 bdgD=bottom;
0705 tdgD=top;
0706 delta=top-bottom;
0707 frac=modf(log10(delta),&intef);
0708 stepc=pow(10.,intef-1);
0709 stepf=stepc;
0710 if(frac<0.2) stepf*=0.5;
0711 else if(frac<0.8) stepc*=5.;
0712 else{
0713 stepc*=10.;
0714 stepf*=5.;
0715 }
0716 MoveTo(lgD,tgD);
0717 LineTo(lgD,bgD);
0718
0719 frac=modf(log10(stepc),&intef);
0720// if(log10(stepc)<0.) coly=-intef+1.;
0721 if(log10(stepc)<0.) coly=-log10(stepc)+0.8;
0722 else coly=0;
0723 frac=modf(bottom/stepc,&intef);
0724 frac=intef;
0725 if(vlD){
0726 stepc=1.;
0727 coly=0;
0728 }
0729 j=0;
0730 while(1){
0731 num=frac*stepc; // y value for grid
0732 if(num>tdgD) break;
0733 iy=(tgD-bgD)*((num-bdgD)/(tdgD-bdgD))+bgD;
0734 i=format(coly,num,ar);
0735 if(i>j) j=i;
0736 MoveTo(lgD-2,iy);
0737 LineTo(rgD,iy);
0738 FontInfo(11,0,0);
0739 for(i=0;ar[i]!='\0';i++);
0740 if(vlD){
0741 MoveTo(lgD-i*6-3,iy-1);
0742 DrawString(ar);
0743 MoveTo(lgD-i*6-12,iy+6);
0744 DrawString("10");
0745 }
0746 else{
0747 MoveTo(lgD-i*6-3,iy+3);
0748 DrawString(ar);
0749 }
0750 frac++;
0751 }
0752 for(i=0;c[i]!='\0';i++);
0753 if(vlD) MoveTo(lgD-j*6-16,(bgD+tgD+i*8)/2);
0754 else MoveTo(lgD-j*6-8,(bgD+tgD+i*8)/2);
0755 FontInfo(16,1,0);
0756 DrawString(c);
0757}
0758
0759int MoveToG(double x,double y)
0760{
0761 int savel,saver,savet,saveb;
0762 int ix,iy;
0763
0764 savel=cliplD;
0765 saver=cliprD;
0766 savet=cliptD;
0767 saveb=clipbD;
0768 cliplD=lgD;
0769 cliprD=rgD;
0770 cliptD=tgD;
0771 clipbD=bgD;
0772
0773 ix=(rgD-lgD)*((x-ldgD)/(rdgD-ldgD))+lgD;
0774 iy=(tgD-bgD)*((y-bdgD)/(tdgD-bdgD))+bgD;
0775 MoveTo(ix,iy);
0776
0777 cliplD=savel;
0778 cliprD=saver;
0779 cliptD=savet;
0780 clipbD=saveb;
0781}
0782
0783int LineToG(double x,double y)
0784{
0785 int savel,saver,savet,saveb;
0786 int ix,iy;
0787
0788 savel=cliplD;
0789 saver=cliprD;
0790 savet=cliptD;
0791 saveb=clipbD;
0792 cliplD=lgD;
0793 cliprD=rgD;
0794 cliptD=tgD;
0795 clipbD=bgD;
0796
0797
0798 ix=(rgD-lgD)*((x-ldgD)/(rdgD-ldgD))+lgD;
0799 iy=(tgD-bgD)*((y-bdgD)/(tdgD-bdgD))+bgD;
0800 LineTo(ix,iy);
0801
0802 cliplD=savel;
0803 cliprD=saver;
0804 cliptD=savet;
0805 clipbD=saveb;
0806}
0807
0808int PlotG(int mark,double x,double y)
0809{
0810 int ix,iy;
0811
0812 ix=(rgD-lgD)*((x-ldgD)/(rdgD-ldgD))+lgD;
0813 iy=(tgD-bgD)*((x-bdgD)/(tdgD-bdgD))+bgD;
0814 MoveTo(ix-1,iy-1);
0815 LineTo(ix-1,iy+1);
0816 LineTo(ix+1,iy+1);
0817 LineTo(ix-1,iy+1);
0818 LineTo(ix,iy+1);
0819 LineTo(ix,iy);
0820}
0821
0822
0823
0824int GifOut()
0825{
0826 int i,j,k;
0827 unsigned char m;
0828 unsigned int step,red,green,blue;
0829
0830 int ctSize=256;
0831 int *prec;
0832 unsigned char *color;
0833 unsigned char pc[2000];
0834 int ipc,nn,n,nnstart,nstart;
0835 int bitsmin;
0836 int kstart;
0837 int clrcode;
0838
0839#ifdef CGI
0840 printf("Content-type: image/gif\n\n");
0841#else
0842 fpD=fopen("test.gif","wb");
0843#endif
0844
0845 prec=(int *)malloc(4097*sizeof(int)); // code up to 12 bits
0846 color=(unsigned char*)malloc(4097*sizeof(unsigned char));
0847 for(i=0;i<4097;i++) prec[i]=-1;
0848
0849#ifdef CGI
0850 printf("GIF89a");
0851#else
0852 fprintf(fpD,"GIF89a");
0853#endif
0854
0855#ifdef CGI
0856 fwrite((char *)&widthD,sizeof(char),2,stdout);
0857 fwrite((char *)&heightD,sizeof(char),2,stdout);
0858#else
0859 fwrite((char *)&widthD,sizeof(char),2,fpD);
0860 fwrite((char *)&heightD,sizeof(char),2,fpD);
0861#endif
0862 sizeOfCTD=7; // class variable
0863 m=0xF0|sizeOfCTD;
0864#ifdef CGI
0865 fwrite(&m,sizeof(char),1,stdout);
0866#else
0867 fwrite(&m,sizeof(char),1,fpD);
0868#endif
0869 m=0; // Background Color Index
0870#ifdef CGI
0871 fwrite(&m,sizeof(char),1,stdout);
0872#else
0873 fwrite(&m,sizeof(char),1,fpD);
0874#endif
0875 m=0; // Pixel Aspect Ratio
0876#ifdef CGI
0877 fwrite(&m,sizeof(char),1,stdout);
0878#else
0879 fwrite(&m,sizeof(char),1,fpD);
0880#endif
0881 step=0xFFFF/5;
0882 for(i=5;i>=0;i--){
0883 red=i*step;
0884 for(j=5;j>=0;j--){
0885 green=j*step;
0886 for(k=5;k>=0;k--){
0887 blue=k*step;
0888 if(i!=0||j!=0||k!=0){
0889#ifdef CGI
0890 fwrite(&red,sizeof(char),1,stdout);
0891 fwrite(&green,sizeof(char),1,stdout);
0892 fwrite(&blue,sizeof(char),1,stdout);
0893#else
0894 fwrite(&red,sizeof(char),1,fpD);
0895 fwrite(&green,sizeof(char),1,fpD);
0896 fwrite(&blue,sizeof(char),1,fpD);
0897#endif
0898 }
0899 }
0900 }
0901 }
0902 step=0xFFFF/15;
0903 green=0;
0904 blue=0;
0905 for(i=14;i>0;i--){
0906 if(i%3!=0){
0907 red=i*step;
0908#ifdef CGI
0909 fwrite(&red,sizeof(char),1,stdout);
0910 fwrite(&green,sizeof(char),1,stdout);
0911 fwrite(&blue,sizeof(char),1,stdout);
0912#else
0913 fwrite(&red,sizeof(char),1,fpD);
0914 fwrite(&green,sizeof(char),1,fpD);
0915 fwrite(&blue,sizeof(char),1,fpD);
0916#endif
0917 }
0918 }
0919 red=0;
0920 blue=0;
0921 for(i=14;i>0;i--){
0922 if(i%3!=0){
0923 green=i*step;
0924#ifdef CGI
0925 fwrite(&red,sizeof(char),1,stdout);
0926 fwrite(&green,sizeof(char),1,stdout);
0927 fwrite(&blue,sizeof(char),1,stdout);
0928#else
0929 fwrite(&red,sizeof(char),1,fpD);
0930 fwrite(&green,sizeof(char),1,fpD);
0931 fwrite(&blue,sizeof(char),1,fpD);
0932#endif
0933 }
0934 }
0935 red=0;
0936 green=0;
0937 for(i=14;i>0;i--){
0938 if(i%3!=0){
0939 blue=i*step;
0940#ifdef CGI
0941 fwrite(&red,sizeof(char),1,stdout);
0942 fwrite(&green,sizeof(char),1,stdout);
0943 fwrite(&blue,sizeof(char),1,stdout);
0944#else
0945 fwrite(&red,sizeof(char),1,fpD);
0946 fwrite(&green,sizeof(char),1,fpD);
0947 fwrite(&blue,sizeof(char),1,fpD);
0948#endif
0949 }
0950 }
0951 for(i=14;i>0;i--){
0952 if(i%3!=0){
0953 red=green=blue=i*step;
0954#ifdef CGI
0955 fwrite(&red,sizeof(char),1,stdout);
0956 fwrite(&green,sizeof(char),1,stdout);
0957 fwrite(&blue,sizeof(char),1,stdout);
0958#else
0959 fwrite(&red,sizeof(char),1,fpD);
0960 fwrite(&green,sizeof(char),1,fpD);
0961 fwrite(&blue,sizeof(char),1,fpD);
0962#endif
0963 }
0964 }
0965 red=0;
0966 green=0;
0967 blue=0;
0968#ifdef CGI
0969 fwrite(&red,sizeof(char),1,stdout);
0970 fwrite(&green,sizeof(char),1,stdout);
0971 fwrite(&blue,sizeof(char),1,stdout);
0972#else
0973 fwrite(&red,sizeof(char),1,fpD);
0974 fwrite(&green,sizeof(char),1,fpD);
0975 fwrite(&blue,sizeof(char),1,fpD);
0976#endif
0977
0978 m=0x2c; // image separator
0979#ifdef CGI
0980 fwrite(&m,sizeof(char),1,stdout);
0981#else
0982 fwrite(&m,sizeof(char),1,fpD);
0983#endif
0984
0985 i=0; // image left position
0986#ifdef CGI
0987 fwrite((char *)&i,sizeof(char),2,stdout);
0988#else
0989 fwrite((char *)&i,sizeof(char),2,fpD);
0990#endif
0991 i=0; // image top position
0992#ifdef CGI
0993 fwrite((char *)&i,sizeof(char),2,stdout);
0994 fwrite((char *)&widthD,sizeof(char),2,stdout);
0995 fwrite((char *)&heightD,sizeof(char),2,stdout);
0996#else
0997 fwrite((char *)&i,sizeof(char),2,fpD);
0998 fwrite((char *)&widthD,sizeof(char),2,fpD);
0999 fwrite((char *)&heightD,sizeof(char),2,fpD);
1000#endif
1001 m=0x00|sizeOfCTD;
1002#ifdef CGI
1003 fwrite(&m,sizeof(char),1,stdout);
1004#else
1005 fwrite(&m,sizeof(char),1,fpD);
1006#endif
1007
1008 m++; // LZW minimum code size 8
1009 if(m==1) m=2;
1010#ifdef CGI
1011 fwrite(&m,sizeof(char),1,stdout);
1012#else
1013 fwrite(&m,sizeof(char),1,fpD);
1014#endif
1015 clrcode=1<<m; // clear code 0x100
1016 bitsD=m+1; // output number of bits 9
1017 bitsmin=bitsD; // initial number of bits
1018 for(i=0;i<ctSize;i++) color[i]=i; // the first 256 of 4097 colors
1019 for(i=0;i<260;i++) outBufD[i]=0;
1020 bitPtrD=0; // initialize output buffer
1021 emit(clrcode);
1022 ipc=0; // index for already-seen-color-sequence pc[]
1023 nnstart=0; // initial index value for nn used for pc[]
1024 nstart=clrcode+2; // n is index for preceeding code, prec
1025 for(j=0;j<heightD;j++){
1026 for(i=0;i<widthD;i++){
1027 m=pD[widthD*j+i]; // CHARACTER
1028 pc[ipc++]=m; // STRING add to already-seen-sequence
1029 nn=nnstart; // index for pc[] used at comparing
1030 if(nn==0){ // first time and immediately after emit
1031 // for(k=0;k<ctSize;k++) if(color[k]==pc[nn]) break;
1032 k=pc[nn]; // equivalent to the above expression
1033 nn++;
1034 }
1035 else k=kstart; // code to be compared
1036 if(lzw){ // compress
1037 for(n=nstart;prec[n]!=-1;n++){ // matched upto and including nn-1 and n-1
1038 if(nn==ipc) break; // same as previously-seen-color-sequence
1039 if(prec[n]==k){
1040 if(color[n]==pc[nn]){
1041 nn++;
1042 k=n;
1043 }
1044 }
1045 }
1046 if(nn==ipc-1){ // if there is no previously-seen-color-sequence
1047 emit(k); // output code for hether-to matching sequence
1048 prec[n]=k; // add the code to dictionary
1049 color[n]=pc[ipc-1]; // add next-to-code-color in dictionary
1050 if(n>>bitsD) bitsD++;
1051 if(n==0xFFF){
1052 emit(clrcode);
1053 bitsD=bitsmin;
1054 for(n=0;n<4097;n++) prec[n]=-1;
1055 }
1056 pc[0]=m; // lastly-read color comes first in color array
1057 ipc=1;
1058 nnstart=0; //position of color array to be compared
1059 nstart=clrcode+2; // position of dictionary to be compared
1060 }
1061 else{ // when there is a previous instance
1062 nnstart=nn; // position of color array to be compared
1063 nstart=n; // position of dictionary to be compared
1064 kstart=k; // code to be compared
1065 }
1066 }
1067 else{ // not compress
1068 emit(m); // output code for hether-to matching sequence
1069 emit(clrcode);
1070 pc[0]=m; // lastly-read color comes first in color array
1071 ipc=1;
1072 nnstart=0; //position of color array to be compared
1073 }
1074 }
1075 }
1076 if(ipc==1){
1077 for(k=0;k<ctSize;k++) if(color[k]==pc[0]) break;
1078 }
1079 if(lzw) emit(k);
1080 n++;
1081 if(n>>bitsD) bitsD++;
1082
1083 emit(clrcode);
1084 bitsD=bitsmin;
1085
1086 emit(clrcode+1);
1087 i=bitPtrD/8;
1088 if((bitPtrD%8)!=0) i++;
1089#ifdef CGI
1090 fwrite((char *)&i,sizeof(char),1,stdout);
1091 fwrite((char *)outBufD,sizeof(char),i,stdout);
1092#else
1093 fwrite((char *)&i,sizeof(char),1,fpD);
1094 fwrite((char *)outBufD,sizeof(char),i,fpD);
1095#endif
1096 m=0;
1097#ifdef CGI
1098 fwrite((char *)&m,sizeof(char),1,stdout);
1099#else
1100 fwrite((char *)&m,sizeof(char),1,fpD);
1101#endif
1102 m=0x3b;
1103#ifdef CGI
1104 fwrite((char *)&m,sizeof(char),1,stdout);
1105#else
1106 fwrite((char *)&m,sizeof(char),1,fpD);
1107 fclose(fpD);
1108#endif
1109
1110// delete[] prec;
1111// delete[] color;
1112
1113
1114}
1115
1116
1117void emit(int k)
1118{
1119 int i,j,m,n;
1120
1121 for(i=0;i<bitsD;i++){ // do for current number of bits
1122 m=bitPtrD/8; // put in n-th bit of m-th byte
1123 n=bitPtrD%8;
1124 j=k;
1125 j>>=i;
1126 j&=1;
1127 j<<=n;
1128 outBufD[m]|=j; // outBuf is char , j is int
1129 bitPtrD++;
1130 }
1131
1132 if(m>254){
1133 i=0xFF;
1134#ifdef CGI
1135 fwrite((char *)&i,sizeof(char),1,stdout);
1136 fwrite((char *)outBufD,sizeof(char),255,stdout);
1137#else
1138 fwrite((char *)&i,sizeof(char),1,fpD);
1139 fwrite((char *)outBufD,sizeof(char),255,fpD);
1140#endif
1141 bitPtrD-=255*8;
1142 outBufD[0]=outBufD[255];
1143 outBufD[1]=outBufD[256];
1144 for(i=2;i<257;i++) outBufD[i]=0;
1145 }
1146}
1147
1148int PngOut()
1149{
1150 unsigned char signa[]={137,80,78,71,13,10,26,10};
1151 unsigned char *chunk;
1152
1153 int i,j,k,l,m,n;
1154 int i1,j1,k1,l1,m1,n1;
1155 int i2,j2,k2,l2,m2,n2;
1156 unsigned int step,red,green,blue;
1157 int lmatch,dmatch;
1158 int wdopen;
1159 unsigned long adler=1L;
1160 unsigned long s1,s2;
1161
1162 i=widthD*heightD/10;
1163 chunk=(unsigned char *)calloc(i*sizeof(char),sizeof(char)); /* this size must be related to picture size */
1164#ifdef CGI
1165 printf("Content-type: image/png\n\n");
1166 fwrite((char *)signa,sizeof(char),8,stdout);
1167#else
1168 fpD=fopen("test.png","wb");
1169 fwrite((char *)signa,sizeof(char),8,fpD);
1170#endif
1171 *(int *)&chunk[0]=13; // excluding length, type or crc
1172 revPng(&chunk[0]);
1173 chunk[4]='I';
1174 chunk[5]='H';
1175 chunk[6]='D';
1176 chunk[7]='R';
1177 *(int *)&chunk[8]=widthD;
1178 revPng(&chunk[8]);
1179 *(int *)&chunk[12]=heightD;
1180 revPng(&chunk[12]);
1181 chunk[16]=8; /* bit depth */
1182 chunk[17]=3; /* color type - palette index */
1183 chunk[18]=0; /* compression method - deflate */
1184 chunk[19]=0; /* filter method */
1185 chunk[20]=0; /* interlace method */
1186 crcPng(&chunk[4],17); // including chunk type and chunk data
1187#ifdef CGI
1188 fwrite((char *)chunk,sizeof(char),25,stdout);
1189#else
1190 fwrite((char *)chunk,sizeof(char),25,fpD);
1191#endif
1192 *(int *)&chunk[0]=768; // 256*3
1193 revPng(&chunk[0]);
1194 chunk[4]='P';
1195 chunk[5]='L';
1196 chunk[6]='T';
1197 chunk[7]='E';
1198 l=8;
1199 step=0xFFFF/5;
1200 for(i=5;i>=0;i--){
1201 red=i*step;
1202 for(j=5;j>=0;j--){
1203 green=j*step;
1204 for(k=5;k>=0;k--){
1205 blue=k*step;
1206 if(i!=0||j!=0||k!=0){
1207 chunk[l++]=red;
1208 chunk[l++]=green;
1209 chunk[l++]=blue;
1210 }
1211 }
1212 }
1213 }
1214 step=0xFFFF/15;
1215 green=0;
1216 blue=0;
1217 for(i=14;i>0;i--){
1218 if(i%3!=0){
1219 red=i*step;
1220 chunk[l++]=red;
1221 chunk[l++]=green;
1222 chunk[l++]=blue;
1223 }
1224 }
1225 red=0;
1226 blue=0;
1227 for(i=14;i>0;i--){
1228 if(i%3!=0){
1229 green=i*step;
1230 chunk[l++]=red;
1231 chunk[l++]=green;
1232 chunk[l++]=blue;
1233 }
1234 }
1235 red=0;
1236 green=0;
1237 for(i=14;i>0;i--){
1238 if(i%3!=0){
1239 blue=i*step;
1240 chunk[l++]=red;
1241 chunk[l++]=green;
1242 chunk[l++]=blue;
1243 }
1244 }
1245 for(i=14;i>0;i--){
1246 if(i%3!=0){
1247 red=green=blue=i*step;
1248 chunk[l++]=red;
1249 chunk[l++]=green;
1250 chunk[l++]=blue;
1251 }
1252 }
1253 red=0;
1254 green=0;
1255 blue=0;
1256 chunk[l++]=red;
1257 chunk[l++]=green;
1258 chunk[l++]=blue;
1259 crcPng(&chunk[4],768+4);
1260#ifdef CGI
1261 fwrite((char *)chunk,sizeof(char),780,stdout);
1262#else
1263 fwrite((char *)chunk,sizeof(char),780,fpD);
1264#endif
1265 for(l=0;l<780;l++) chunk[l]=0;
1266/** LZ77 conpression **/
1267 chunk[4]='I';
1268 chunk[5]='D';
1269 chunk[6]='A';
1270 chunk[7]='T';
1271 chunk[8]=0x78; /* compression methodflag code */
1272 chunk[9]=0x9c; /* additional flagscheck bits */
1273 i1=10; // initial code byte
1274 j1=0; // initial bit position
1275 setPng(chunk,i1,j1,3,3,&i1,&j1); // three header bit for the block
1276 // final & fixed Huffman code
1277 l=heightD*widthD; /* insert filter type byte */
1278 for(n=heightD-1;n>=0;n--){
1279 k=n*(widthD+1);
1280 for(m=widthD;m>0;m--) pD[k+m]=pD[--l];
1281 pD[k]=0;
1282 }
1283 wdopen=0;
1284 l=heightD*(widthD+1);
1285 for(n=0;n<l;n++){
1286 lmatch=0;
1287 if(n<32768) wdopen=0;
1288 else wdopen=n-32768;
1289 for(m=n-1;m>=wdopen;m--){
1290 j=n;
1291 k=m;
1292 i=0;
1293 while(pD[j++]==pD[k++]){
1294 i++;
1295 if(i==258) break;
1296 if(j>=l) break;
1297 }
1298 if(i>lmatch){
1299 lmatch=i; /* length */
1300 dmatch=n-m; /* distance */
1301 }
1302 if(lmatch==258||j>=l) break;
1303 }
1304 l1=0; // number of extra bits
1305 m1=0; // value of extra bits
1306 if(lmatch<3) k1=pD[n]; // raw data
1307 else{
1308 if(lmatch<11) k1=254+lmatch;
1309 else if(lmatch<19){
1310 l1=1;
1311 k1=(lmatch-11)/2+265;
1312 m1=(lmatch-11)%2;
1313 }
1314 else if(lmatch<35){
1315 l1=2;
1316 k1=(lmatch-19)/4+269;
1317 m1=(lmatch-19)%4;
1318 }
1319 else if(lmatch<67){
1320 l1=3;
1321 k1=(lmatch-35)/8+273;
1322 m1=(lmatch-35)%8;
1323 }
1324 else if(lmatch<131){
1325 l1=4;
1326 k1=(lmatch-67)/16+277;
1327 m1=(lmatch-67)%16;
1328 }
1329 else if(lmatch<258){
1330 l1=5;
1331 k1=(lmatch-131)/32+281;
1332 m1=(lmatch-131)%32;
1333 }
1334 else k1=285;
1335 } /* else */
1336/* convert alphabet k1 to Huffman code */
1337 if(k1<144){
1338 n1=0x30+k1; // Huffman code
1339 i2=0x80; // mask for output
1340 }
1341 else if(k1<256){
1342 n1=0x190+k1-144;
1343 i2=0x100;
1344 }
1345 else if(k1<280){
1346 n1=0x0+k1-256;
1347 i2=0x40;
1348 }
1349 else{
1350 n1=0xc0+k1-280;
1351 i2=0x80;
1352 }
1353 for(;i2>0;i2/=2){
1354 if(n1&i2) setPng(chunk,i1,j1,1,1,&i1,&j1);
1355 else setPng(chunk,i1,j1,0,1,&i1,&j1);
1356 }
1357 if(l1>0) setPng(chunk,i1,j1,m1,l1,&i1,&j1); /* extra bits for length */
1358 if(k1>256){ /* distance in dmatch */
1359 m2=1;
1360 for(l2=1;;l2++){
1361 m2*=2;
1362 if(m2>=dmatch) break;
1363 }
1364 k1=l2*2-1; // code
1365 // dmatch<= k1 l2 extra-bits
1366 // 2 1 1 0
1367 // 4 3 2 0
1368 // 8 5 3 1
1369 // 16 7 4 2
1370 // 32 9 5 3
1371 l1=l2-2; // number of extra bits
1372 if(l1<0) l1=0;
1373 // m2 2 2 4 4 8 8 8 8 16 16 16
1374 // dmatch 1 2 3 4 5 6 7 8 9 10 11
1375 // l2 1 1 2 2 3 3 3 3 4 4 4
1376 // k1 1 1 3 3 5 5 5 5 7 7 7
1377 // l1 0 0 0 0 1 1 1 1 2 2 2 ->number of extra bits
1378 // n2 1 1 1 1 2 2 2 2 4 4 4
1379 // m2-n2 1 1 3 3 6 6 6 6 12 12 12
1380 // k1 0 (1) 2 (3) 4 4 (5) (5) 6 6 6 ->code
1381 // m2 1 2 3 4 6 6 8 8 12 12 12
1382 // m2-n2 0 1 2 3 4 4 6 6 8 8 8
1383 // m1 1 1 1 1 1 2 1 2 1 2 3
1384 // m1 0 0 0 0 0 1 0 1 0 1 2 ->extra bit value
1385 n2=pow(2,l1);
1386 if(dmatch<=m2-n2){
1387 k1--;
1388 m2=m2-n2;
1389 }
1390 m1=dmatch-(m2-n2);
1391 m1--; // value of extra bits
1392
1393 i2=0x10; // 5 bits
1394 for(;i2>0;i2/=2){
1395 if(k1&i2) setPng(chunk,i1,j1,1,1,&i1,&j1);
1396 else setPng(chunk,i1,j1,0,1,&i1,&j1);
1397 }
1398 if(l1>0) setPng(chunk,i1,j1,m1,l1,&i1,&j1); /* extra bits for distance */
1399 n+=lmatch-1; /* advance main loop counter - 1 incremented later */
1400 } /* if(k1>256) */
1401 } /* for(n=0;n<l;n++){ */
1402 i2=0x40; // 7 bits - end of block mark
1403 for(;i2>0;i2/=2){ // huffman code for 256 is 0
1404 if(0&i2) setPng(chunk,i1,j1,1,1,&i1,&j1);
1405 else setPng(chunk,i1,j1,0,1,&i1,&j1);
1406 }
1407/* Adler-32 : a check sum value of the uncompressed data */
1408 s1=adler&0xffff;
1409 s2=(adler>>16)&0xffff;
1410 for(n=0;n<l;n++){
1411 s1=(s1+pD[n])%65521;
1412 s2=(s2+s1)%65521;
1413 }
1414 if(j1!=0) i1++;
1415 *(unsigned long *)&chunk[i1]=(s2<<16)+s1;
1416 revPng(&chunk[i1]);
1417 i1+=4; /* pointer index to crc */
1418 *(int *)&chunk[0]=i1-8; /* data length */
1419 revPng(&chunk[0]);
1420 crcPng(&chunk[4],i1-4);
1421 i1+=4; /* number of bytes including crc */
1422#ifdef CGI
1423 fwrite((char *)chunk,sizeof(char),i1,stdout);
1424#else
1425 fwrite((char *)chunk,sizeof(char),i1,fpD);
1426#endif
1427 *(int *)&chunk[0]=0; /* data length */
1428 revPng(&chunk[0]);
1429 chunk[4]='I';
1430 chunk[5]='E';
1431 chunk[6]='N';
1432 chunk[7]='D';
1433 crcPng(&chunk[4],4);
1434
1435#ifdef CGI
1436 fwrite((char *)chunk,sizeof(char),12,stdout);
1437#else
1438 fwrite((char *)chunk,sizeof(char),12,fpD);
1439 fclose(fpD);
1440#endif
1441
1442}
1443
1444void revPng(unsigned char *c)
1445{
1446 unsigned char a;
1447 a=c[0];
1448 c[0]=c[3];
1449 c[3]=a;
1450 a=c[1];
1451 c[1]=c[2];
1452 c[2]=a;
1453}
1454
1455/*********************************************
1456 Pad data into chunk
1457 chunk : chunk array
1458 byte : index into chunk array
1459 bit : bit position (0(lsb)-7(msb))
1460 val : data to be set
1461 nbit : number of bits of val
1462 *nxtbyte : next index to be returned
1463 *nxtbit : next bit position to be returned
1464********************************************/
1465void setPng(unsigned char *chunk,int byte,int bit,
1466 int val,int nbit,int *nxtbyte,int *nxtbit)
1467{
1468 unsigned char c1,c2;
1469 unsigned char cin[4];
1470 unsigned char mask,mask1;
1471 int sourcebyte,destbyte,sourcebit,destbit;
1472 int i;
1473
1474 sourcebyte=0;
1475 sourcebit=0;
1476 destbyte=byte;
1477 destbit=bit;
1478 *(unsigned long*)cin=val;
1479 for(i=0;i<nbit;i++){
1480 mask=1;
1481 mask<<=sourcebit;
1482 c1=cin[sourcebyte];
1483 if(c1&mask){
1484 mask=1;
1485 mask<<=destbit;
1486 chunk[destbyte]|=mask;
1487 }
1488 sourcebit++;
1489 if(sourcebit==8){
1490 sourcebyte++;
1491 sourcebit=0;
1492 }
1493 destbit++;
1494 if(destbit==8){
1495 destbyte++;
1496 destbit=0;
1497 }
1498 }
1499 *nxtbyte=destbyte;
1500 *nxtbit=destbit;
1501}
1502
1503
1504/**********************************************
1505 CRC - ported from W3C specification
1506 Return the CRC of the bytes buf[0]..[len-1]
1507 in buf[len]..[len+3]
1508**********************************************/
1509void crcPng(unsigned char *buf,int len)
1510{
1511 unsigned long c;
1512 int n,k;
1513
1514 if(!crc_table_computed){
1515 for(n=0;n<256;n++){
1516 c=(unsigned long)n;
1517 for(k=0;k<8;k++){
1518 if(c&1) c=0xedb88320L^(c>>1);
1519 else c=c>>1;
1520 }
1521 crc_table[n]=c;
1522 }
1523 crc_table_computed=1;
1524 }
1525 c=0xffffffffL;
1526 for(n=0;n<len;n++){
1527 c=crc_table[(c^buf[n])&0xff]^(c>>8);
1528 }
1529 *(int *)&buf[len]=c^0xffffffffL;
1530 revPng(&buf[len]);
1531}
1532