/* (c) 2000 Karel Kulhavy, Clocksoft * clock@atrey.karlin.mff.cuni.cz * This program is a stdin filter that performs these operations: * 1) Downconverts 17x15 oversampled binary image data (black-or-white * pixels, 1 bit per pixel, pbmraw format) to 256-level grayscale * pgmraw format and saves it to basename_%d.png. * 2) At the end, generates necessary html's * 3) The input pages must be concatenated * 4) Recommended source of the pbm: Aladdin Ghostscript * If there is an input argument (one number as first arg), it's treated * as number of first page that comes at fd #0. Default value is 0. * Parameters: * [first page number] * Little benchmarks: Normal (gs+pbm2png) 1:32 Without pbm2png 0:28 Without libpng 0:51 Without grayscaling 0:32 */ #include #include #include #include #include #include #include #include #include unsigned char *basename_; /* basename: pbm2png.c:32: `basename' redeclared as different kind of symbol /usr/include/string.h:245: previous declaration of `basename' */ unsigned char *titlestring; unsigned char *bottom; int pageoffset=-13; unsigned long t1[256]; /* Conversion from 1-bit to 2-bit expansion */ unsigned long t2[256]; /* Conversion from 2-bit to 4-bit expansion */ unsigned char *l1; /* Input data, output data. lw<<1 bytes long */ unsigned long *l2; /* 2-bit expansion lw unsigned long's long*/ unsigned long long *l4; /* 4-bit expansion lw unsigned long long's long */ int ox,oy; int lw; /* Width of the input in 16-pixel units. */ int lb; /* Width of the input in 8-pixel units */ FILE *of; int filenumber; int x,y; png_structp png_ptr; png_infop info_ptr; unsigned long ppm; float dpi; unsigned char string[8192]; unsigned char *filename; int ifd; void gentables(void) { int a,d; unsigned long b; unsigned char c; for (a=0;a<256;a++){ b=0; c=a; for (d=7;d>=0;d--){ b<<=2; b|=(c>>d)&1; } t1[a]=b; b=0; c=a; for (d=4;d;d--){ b<<=4; b|=c&3; c>>=2; } t2[a]=b; } } void make_index(void) { FILE *f; f=fopen("index.html","w"); fprintf(f,"%s\n",titlestring); fprintf(f,"
" "Download in PDF format
" "

%s

Page index

",basename_,titlestring); { int n; unsigned char *t; FILE *g; fprintf(f,"\n"); for (n=0;n\n"); } fprintf(f,"\n",basename_,n,n+pageoffset); } fprintf(f,"
%d

"); g=fopen("index.dir","rb"); if (g) { t=malloc(65536); fprintf(f,"Contents Index

"); while(fgets(t,65536,g)){ int val=0; int len=strlen(t); unsigned char *u=t; if (len&&t[len-1]=='\n') t[len-1]=0; if (*t>'9'||*t<'0') continue; while(*u>='0'&&*u<='9'){ val*=10; val+=*u-'0'; u++; } val--; u++; /* The char behind the number is ignored */ fprintf(f,"\n",val+pageoffset ,basename_,val,u); } fprintf(f,"
%d %s
"); fclose(g); free(t); } fprintf(f,""); fclose(f); } } void make_page(int index) { FILE *f; sprintf(string,"%s%d.html",basename_,index); f=fopen(string,"w"); fprintf(f,"%s\n",titlestring); fprintf(f,"

%s, Page %d

\n",titlestring,index+pageoffset); fprintf(f,"

"); fprintf(f,"\n
"); fprintf(f,"
"); if (index) { fprintf(f,"\n",basename_,index-1); } else { fprintf(f,"\n"); } fprintf(f,""); if (index \n",basename_,index+1); } else { fprintf(f,"\n"); } fprintf(f,"
"); fprintf(f,"
",basename_,index); fprintf(f,""); fclose(f); } /* Returns 0 is OK, exit(1) on error, returns 1 on broken pipe */ int sure_read(unsigned char *dest, size_t len) { ssize_t rd; if (!len) return 0; again: rd=read(ifd,dest,len); if (rd==len) return 0; if (!rd) return 1; if (rd<0&&(errno==EINTR||errno==EAGAIN||errno==EWOULDBLOCK)) goto again; if (rd>0&&rd=0;index--){ bit2=l2[index]; bit4=t2[bit2&255]; bit4<<=16; bit2>>=8; bit4|=t2[bit2&255]; bit4<<=16; bit2>>=8; bit4|=t2[bit2&255]; bit4<<=16; bit2>>=8; bit4|=t2[bit2&255]; l4[index]=bit4; } } /* Adds the same pixels that are in l2 to l4. */ void add_2_to_4(void) { unsigned long long bit4; unsigned long bit2; int index; for (index=lw-1;index>=0;index--){ bit2=l2[index]; bit4=t2[bit2&255]; bit4<<=16; bit2>>=8; bit4|=t2[bit2&255]; bit4<<=16; bit2>>=8; bit4|=t2[bit2&255]; bit4<<=16; bit2>>=8; bit4|=t2[bit2&255]; l4[index]+=bit4; } } /* Moves pixels from l1 to l2 with format change */ void move_1_to_2(void) { int index; for (index=lw-1;index>=0;index--) l2[index]=(t1[l1[index<<1]]<<16)|t1[l1[(index<<1)+1]]; } /* Adds pixels from l1 to l2 with format change */ void add_1_to_2(void) { int index; for (index=lw-1;index>=0;index--) l2[index]+=(t1[l1[index<<1]]<<16)|t1[l1[(index<<1)+1]]; } /* Loads 1 line into l1 */ void load(void) { sure_read(l1,lb); } /* Loads 3 lines into l2 */ void load_to_2(void) { load(); move_1_to_2(); load(); add_1_to_2(); load(); add_1_to_2(); } /* Loads 15 lines into l4 */ void load_to_4(void) { load_to_2(); move_2_to_4(); load_to_2(); add_2_to_4(); load_to_2(); add_2_to_4(); load_to_2(); add_2_to_4(); load_to_2(); add_2_to_4(); } /* Converts the data from l4 to l1 including suming up 17 adjacent pixels */ void export_from_4(void) { int a,b,reg_hold; unsigned char sum; unsigned long long *loader=l4; unsigned long long reg=0; reg_hold=0; for (a=0;a>=4; reg_hold--; } l1[a]=sum; } png_write_row(png_ptr,l1); } /* * Parameters: * [first page number] */ int main(int argc, char **argv) { int a,z; if (argc<7){ fprintf(stderr,"Usage: pbm2png [starting_filenumber]\n"); return 0; } dpi=atof(argv[1])/10; ppm=dpi*1000/25.4; basename_=argv[2]; titlestring=argv[3]; bottom=argv[4]; pageoffset=atol(argv[5]); filename=argv[6]; again0: ifd=open(filename,O_RDONLY); if (ifd<0){ if (errno==EAGAIN||errno==EINTR||errno==EWOULDBLOCK) goto again0; else { perror(""); exit(1); } } fprintf(stderr,"filename %s, %d\n",filename,ifd); if (argc>=8){ filenumber=atol(argv[7]); } gentables(); again: fprintf(stderr,"\nFile %i\n",filenumber); if (read_header()){ for (a=0;a>4; lb=(x+7)>>3; ox=x/17; oy=y/15; fprintf(stderr,"Input: %i*%i pixels, %f*%f dpi, %.1fMB.\n",x,y,dpi*17,dpi*15,(float)lb*y/1048576); fprintf(stderr,"Ouput: %i*%i pixels, %f*%f dpi, %.1fKB raw data.\n",ox,oy,dpi,dpi,(float)ox*oy/1024); l1=(unsigned char*)malloc(lw*2); l2=(unsigned long*)malloc(lw*sizeof(unsigned long)); l4=(unsigned long long*)malloc(lw*sizeof(unsigned long long)); sprintf(string,"%s%d.png",basename_,filenumber); filenumber++; of=fopen(string,"w"); open_png(); for (z=oy;z;z--){ if (!(z&15)){ fprintf(stderr,"."); fflush(stderr); } load_to_4(); export_from_4(); } close_png(); fprintf(stderr,"\nWritten %lu bytes of data, ratio %.1f%%\n",ftell(of),(float)ftell(of)*100/ox/oy); fclose(of); for (a=y%15;a;a--) load(); free(l1); free(l2); free(l4); goto again; }