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