/* * Convert BJC-printjobs to xbm files, one for each color channel * * Copyright 2001 Andy Thaller * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include char *efnlc= 0,*efnlm= 0,*efnc= 0,*efnm= 0,*efny= 0,*efnk= 0; int lc_cnt= 0,lm_cnt= 0,ly_cnt= 0,c_cnt= 0,m_cnt= 0,y_cnt= 0,k_cnt= 0; FILE *outfilelc= 0; FILE *outfilelm= 0; FILE *outfilely= 0; FILE *outfilec= 0; FILE *outfilem= 0; FILE *outfiley= 0; FILE *outfilek= 0; int xsize,ysize,pixcnt; typedef struct scanline_t_ { int size; int osize; unsigned char *buf; int xmin; int xmax; int width; int y; struct scanline_t_ *next; } scanline_t; typedef struct bitimage_t_ { unsigned char *buf; int y0; int width; int height; int xmin; int xmax; } bitimage_t; typedef struct level_t_ { /* Max number of bits per ink so far known is 8 Thus max number of levels is 256 (including value 0) */ int levelvals[256]; /* number of occurrences of each level */ int numlevels; /* number of actual levels used */ int maxlevel; /* maximum value */ int numbits; /* deduced number bits used for numlevels */ } level_t; bitimage_t *bitimage_new (void); int last_bit (unsigned char i); int first_bit (unsigned char i); void rle_info (const unsigned char *inbuf, int n, int *first, int *last, int *width, int *length); int rle_decode (unsigned char *inbuf, int n, unsigned char *outbuf, int max, level_t *levels); scanline_t* scanline_new (void); level_t* level_new (void); int calc_bits(int numlevels); scanline_t *scanline_store (scanline_t *line, int y, unsigned char *buf, int size); bitimage_t *scanlines2bitimage (scanline_t *slimg, level_t *levels); char conv (char i); void save2xbm (const char *filename,char col, bitimage_t *img, int xmin, int ymin, int xmax, int ymax); int nextcmd (FILE *infile, unsigned char *inbuff, int *cnt); int process(FILE *infile, scanline_t *sf[7], int *xmin_, int *xmax_, int *ymin_, int *ymax_, level_t *lv[7]); bitimage_t *bitimage_new(void) { bitimage_t *tmp= (bitimage_t*) stp_malloc (sizeof(bitimage_t)); tmp->buf= 0; tmp->y0= 0; tmp->width= 0; tmp->height= 0; tmp->xmin= 0; tmp->xmax= 0; return tmp; } int last_bit(unsigned char i) { if (i & 0x1) return 0; if (i & 0x2) return 1; if (i & 0x4) return 2; if (i & 0x8) return 3; if (i & 0x10) return 4; if (i & 0x20) return 5; if (i & 0x40) return 6; if (i & 0x80) return 7; return 0; } int first_bit(unsigned char i) { if (i & 0x80) return 7; if (i & 0x40) return 6; if (i & 0x20) return 5; if (i & 0x10) return 4; if (i & 0x8) return 3; if (i & 0x4) return 2; if (i & 0x2) return 1; if (i & 0x1) return 0; return 0; } void rle_info(const unsigned char *inbuf, int n, int *first, int *last, int *width, int *length) { const char *ib= (const char *)inbuf; char cnt; int o= 0; int i=0,j,num,f=-1,l=0; *first= 0; *last= 0; *width= 0; if (n<=0) return; while (ilevelvals[outbuf[o+j]] += 1; if ( outbuf[o+j] > levels->maxlevel ) levels->maxlevel = outbuf[o+j]; } o+= num; i+= 2; } else { num= cnt+1; /* for (j=0; jlevelvals[outbuf[o+j]] += 1; if ( outbuf[o+j] > levels->maxlevel ) levels->maxlevel = outbuf[o+j]; } o+= num; i+= num+1; } } /*fprintf(stderr,"\n");*/ return o; } scanline_t* scanline_new(void) { scanline_t* tmp= (scanline_t*) stp_malloc (sizeof(scanline_t)); tmp->size= 0; tmp->osize= 0; tmp->buf= 0; tmp->xmin= 0; tmp->xmax= 0; tmp->width= 0; tmp->y= 0; tmp->next= 0; return tmp; } level_t *level_new(void) { int i; level_t* tmp = (level_t*) stp_malloc (sizeof(level_t)); tmp->numlevels=0; tmp->maxlevel=0; tmp->numbits=0; for (i=0; i<256; i++) tmp->levelvals[i]=0; return tmp; } int calc_bits(int numlevels) { if (numlevels > 128) return 8; else if (numlevels > 64) return 7; else if (numlevels > 32) return 6; else if (numlevels > 16) return 5; else if (numlevels > 8) return 4; else if (numlevels > 4) return 3; else if (numlevels > 2) return 2; else if (numlevels > 1) return 1; else return 0; } scanline_t *scanline_store(scanline_t *line, int y, unsigned char *buf, int size) { if (!line && !(line= scanline_new())) return 0; line->size= size; /* from cnt in nextcmd function */ line->buf= (unsigned char *) stp_malloc (size); memcpy(line->buf,buf,size); rle_info(buf,size,&line->xmin,&line->xmax,&line->width,&line->osize); /*fprintf(stderr,"Scanline size %d, xmin %d, xmax %d, width %d\n",size,line->xmin,line->xmax,line->width);*/ line->y= y; return line; } bitimage_t *scanlines2bitimage(scanline_t *slimg, level_t *level) { bitimage_t *img= 0; scanline_t *sl; int w= 0; int y0= -1; int y= 0; int h,i; for (sl=slimg; sl!=0; sl=sl->next) { if (sl->width) { if (wosize) w= sl->osize; if (y0<0) y0= sl->y; y= sl->y; } } h= y-y0+1; if ((!w) || (!h)) return 0; img= bitimage_new(); img->buf= (unsigned char*) stp_malloc(h*w); memset(img->buf,0,h*w); img->width= w; img->height= h; img->y0= y0; for (sl=slimg; sl!=0; sl=sl->next) { y= sl->y- y0; if ((y>=0) && (ybuf,sl->size,img->buf+y*w,w,level); } } /* print out stats of levels */ for (i=0;i<256;i++) { fprintf(stderr,"level %d: %d\n",i,level->levelvals[i]); if (level->levelvals[i] > 0) level->numlevels += 1; } fprintf(stderr,"numlevels: %d\n",level->numlevels); fprintf(stderr,"maxlevel: %d\n",level->maxlevel); level->numbits = calc_bits(level->maxlevel); fprintf(stderr,"numbits: %d\n",level->numbits); return img; } char conv(char i) { char o= 0; if (i & 0x80) o|=0x01; if (i & 0x40) o|=0x02; if (i & 0x20) o|=0x04; if (i & 0x10) o|=0x08; if (i & 0x08) o|=0x10; if (i & 0x04) o|=0x20; if (i & 0x02) o|=0x40; if (i & 0x01) o|=0x80; return o; } void save2xbm(const char *filename,char col, bitimage_t *img, int xmin, int ymin, int xmax, int ymax) { char *outfilename= (char*) stp_malloc(strlen(filename)+16); FILE *o; int i,j,k,i0,i1,j0,j1,w,h; if (!img) return; if (col) sprintf(outfilename,"%s_%c.xbm",filename,col); else sprintf(outfilename,"%s.xbm",filename); if (!(o= fopen(outfilename,"w"))) { stp_free(outfilename); return; } i0= (ymin>0) ? ymin-img->y0 : 0; i1= (ymax>0) ? ymax-img->y0 : img->height; j0= (xmin>0 && xminwidth*8) ? xmin/8 : 0; j1= (xmax>0 && xmaxwidth*8) ? xmax/8 : img->width-1; w= j1-j0+1; h= i1-i0; if (col) fprintf(o,"#define %s_%c_width %d\n#define %s_%c_height %d\nstatic char %s_%c_bits[] = {", outfilename,col,w*8, outfilename,col,h, outfilename,col); else fprintf(o,"#define %s_width %d\n#define %s_height %d\nstatic char %s_bits[] = {", outfilename,w*8, outfilename,h, outfilename); fprintf(stderr,"%d %d %d %d\n",i0,h,j0,w); for (i=i0,k=0; i=0 && iheight)? conv(img->buf[i*img->width+j])&0xff : 0); k++; } } fprintf(o," 0x00 };\n"); fclose(o); } int nextcmd(FILE *infile,unsigned char *inbuff,int *cnt) { unsigned char c1=0,c2=0; int c; int cmd; while (!feof(infile) && c1!=0x1b && (c2!=0x28 && c2!=0x5b)) { c1=c2; c2=fgetc(infile); } if (feof(infile)) return 0; cmd=fgetc(infile); if (feof(infile)) return 0; c1= fgetc(infile); if (feof(infile)) return 0; c2= fgetc(infile); if (feof(infile)) return 0; /* 2 bytes: seems to be the size+1 of one scanline in cases where command is a scanline */ *cnt= c1+256*c2; if ((c=fread(inbuff,1,*cnt,infile) != *cnt)) { fprintf(stderr,"read error for 0x%02x - not enough data (%d/%d)!\n",cmd, c,*cnt); return 0; } return cmd; } int process(FILE *infile,scanline_t *sf[7],int *xmin_,int *xmax_,int *ymin_,int *ymax_,level_t *lv[7]) { unsigned char inbuff[65540]; scanline_t *sl[7], *nsl; int xres,yres; int xmin=1000000,xmax=0,ymin=-1,ymax=0,width=0; int col=0; int line=0; int i; int cnt; int cmd; for (i=0; i<7; i++) sf[i]= sl[i]= 0; for (i=0; i<7; i++) lv[i] = level_new(); if (!infile) return 0; fseek(infile,0,SEEK_SET); while ((cmd= nextcmd(infile,inbuff,&cnt))) { switch(cmd) { case 0x64: yres=inbuff[0]*256+inbuff[1]; xres=inbuff[2]*256+inbuff[3]; fprintf(stderr,"res=%dx%ddpi\n",xres,yres); break; case 0x65: line+=(inbuff[0]*256+inbuff[1]); break; case 0x41: switch(inbuff[0]) { case 0x4b: col= 0; break; /* black */ case 0x59: col= 1; break; /* yellow */ case 0x4d: col= 2; break; /* magenta */ case 0x43: col= 3; break; /* cyan */ case 0x79: col= 4; break; /* lightyellow */ case 0x6d: col= 5; break; /* lightmagenta */ case 0x63: col= 6; break; /* lightcyan */ default: fprintf(stderr,"unknown color component 0x%02x\n",inbuff[0]); exit(-1); } nsl= scanline_store(0,line,inbuff+1,cnt-1); if (nsl) { if (nsl->width) { if (ymin<0) ymin=line; ymax=line; if (nsl->xminxmin; if (nsl->xmax>xmax) xmax=nsl->xmax; if (nsl->width>width) width=nsl->width; if (!sf[col]) sf[col]=nsl; else sl[col]->next= nsl; sl[col]= nsl; } else { stp_free (nsl); nsl= 0; } if (fgetc(infile)!=0x0d) { fprintf(stderr,"COLOR LINE NOT TERMINATED BY 0x0d @ %lx!!\n", ftell(infile)); } } break; case 0x62: break; default: ; } } fprintf(stderr,"size=%d..%d:%d..%d = %dx%d\n",xmin,xmax,ymin,ymax,width,ymax-ymin+1); *xmin_= xmin; *xmax_= xmax; *ymin_= ymin; *ymax_= ymax; return 1; } /* const char *fbin(char b) { static char bf[9]; bf[0]= (b & 0x80) ? '1' : '0'; bf[1]= (b & 0x40) ? '1' : '0'; bf[2]= (b & 0x20) ? '1' : '0'; bf[3]= (b & 0x10) ? '1' : '0'; bf[4]= (b & 0x08) ? '1' : '0'; bf[5]= (b & 0x04) ? '1' : '0'; bf[6]= (b & 0x02) ? '1' : '0'; bf[7]= (b & 0x01) ? '1' : '0'; bf[8]=0; return bf; } */ int main(int argc, char **argv) { char *infilename= 0, *outfilename=0; FILE *infile= 0; scanline_t *scanlines[7]; char colname[7] = { 'K', 'Y', 'M', 'C', 'y', 'm', 'c' }; level_t *levels[7]; int xmin,xmax; int ymin,ymax; if (argc>1) { if (argc>2) outfilename= argv[2]; else outfilename= argv[1]; infilename= argv[1]; infile= fopen(infilename,"r"); xsize=ysize=0; process(infile,scanlines,&xmin,&xmax,&ymin,&ymax,levels); fprintf(stderr,"Color %c\n",colname[0]); save2xbm(outfilename,colname[0],scanlines2bitimage(scanlines[0],levels[0]),xmin,ymin,xmax,ymax); fprintf(stderr,"Color %c\n",colname[1]); save2xbm(outfilename,colname[1],scanlines2bitimage(scanlines[1],levels[1]),xmin,ymin,xmax,ymax); fprintf(stderr,"Color %c\n",colname[2]); save2xbm(outfilename,colname[2],scanlines2bitimage(scanlines[2],levels[2]),xmin,ymin,xmax,ymax); fprintf(stderr,"Color %c\n",colname[3]); save2xbm(outfilename,colname[3],scanlines2bitimage(scanlines[3],levels[3]),xmin,ymin,xmax,ymax); fprintf(stderr,"Color %c\n",colname[4]); save2xbm(outfilename,colname[4],scanlines2bitimage(scanlines[4],levels[4]),xmin,ymin,xmax,ymax); fprintf(stderr,"Color %c\n",colname[5]); save2xbm(outfilename,colname[5],scanlines2bitimage(scanlines[5],levels[5]),xmin,ymin,xmax,ymax); fprintf(stderr,"Color %c\n",colname[6]); save2xbm(outfilename,colname[6],scanlines2bitimage(scanlines[6],levels[6]),xmin,ymin,xmax,ymax); } else { fprintf(stderr,"\nusage: bjc-unprint INFILE [OUTFILE]\n\n"); } return 0; }