/********************************************************************/ /** bbox -- calculates Bounding Box of a pbmraw/ppmraw-picture **/ /** Created: Nov. 1997, revised Feb. 1998, Dec. 1999 **/ /** Author: Roland Bless **/ /** Copyright (C) 1998-2000 Roland Bless **/ /** To compile simply use: **/ /** "cc bbox.c -o bbox" or "make bbox" **/ /********************************************************************/ /* * $Id: bbox.c,v 1.13 2004/01/25 10:15:48 bless Exp $ * * $Log: bbox.c,v $ * Revision 1.13 2004/01/25 10:15:48 bless * - added %%HiResBoundingBox: output (now compatible with bbox device output of ghostscript) * * Revision 1.12 2003/11/09 18:16:53 bless * - print help, license and version to stdout instead of stderr (incorporated patch from Rafael Laboissiere ) * * Revision 1.11 2003/07/08 11:14:12 bless * - added include for strcmp() * - removed unused argument in fprintf() call * * Revision 1.10 2000/08/04 08:46:47 bless * Incorporated bugfix by Dan Blake : read * unsigned int into unsigned char variable via sscanf caused crash * under HP-UX. Thanks, Dan! * * */ #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include /* needed for _setmode() */ #include #endif /********************** * global variables * **********************/ const char *const version= "$Revision: 1.13 $ $Date: 2004/01/25 10:15:48 $"; const char *const prgname= "bbox"; unsigned char bitval[8]= { 1 << 7, 1 << 6, 1 << 5, 1 << 4, 1 << 3, 1 << 2, 1 << 1, 1 }; unsigned int minus_one(const unsigned x) { return (x == 0) ? x : x-1; } unsigned int plus_one(const unsigned x) { return (x == (unsigned int) ~0U) ? x : x+1; } /***************************** readppm_and_calcbb *********************** * input: name, resolution, tight * * output: - (stdout) * * * * Reads a RAWPPM or RAWPBM picture file (name or STDIN) and * * calculates its Bounding Box on-the-fly (line-by-line). * * * * Parameters: * * name: name of the PBMRAW file or NULL (input from stdin) * * resolution: Pixel per Inch (DPI) * * tight: boolean value, if false 1 Postscript Point is added to * each Bounding Box parameter, otherwise the BB is tight * * The Bounding Box is given in Postscript Points (72 dots/inch) * * and printed to stdout * ************************************************************************/ /* calculate the bounding box in postscript points, given a resolution in dpi */ void readppm_and_calcbb(const char *name, const unsigned int resolution, const unsigned char tight) { FILE *inputfile; char inputline[1024]; unsigned char magic_found= 0; int x,y,byte_x,i; unsigned int x_min, x_max, y_min, y_max; unsigned int llx, lly, urx, ury; /* bounding box */ double hllx, hlly, hurx, hury; /* hires bounding box */ unsigned char *image_row, /* ImageRow */ *tmprowp; unsigned int xmax,ymax; /* Image Size */ unsigned int byte_xmax; unsigned char stepsize; unsigned char colmax= 0; /* max color value */ unsigned int ui_colmax= 0; /* max color value */ if ( name == NULL ) { inputfile = stdin; name = "- STDIN -"; } else { inputfile = fopen(name,"r"); if ( inputfile == NULL ) { fprintf(stderr,"%s: ERROR -- could not open file %s\n", prgname, name); return; } } /** check for magic number **/ do { fgets(inputline, 1024, inputfile); #ifdef DEBUG fprintf(stderr,"read:[%s]\n",inputline); #endif if ( strcmp(inputline,"P4\n") == 0 ) { stepsize= 1; magic_found= 4; } else if ( strcmp(inputline,"P6\n") == 0 ) { stepsize= 3; magic_found= 6; } } while ( !feof(inputfile) && !magic_found ); if ( !magic_found ) { fprintf(stderr,"%s: ERROR -- %s is not in ppmraw or pbmraw format\n", prgname, name); return; } /** skip comments **/ do { fgets(inputline, 1024, inputfile); #ifdef DEBUG fprintf(stderr,"read:[%s]\n",inputline); #endif if (*inputline == '#') continue; else break; } while ( !feof(inputfile) ); /** read picture size: width, height **/ sscanf(inputline,"%u %u",&xmax,&ymax); if ( magic_found == 6 ) /* PPM file has maximum color-component value */ { fgets(inputline, 1024, inputfile); sscanf(inputline,"%u",&ui_colmax); colmax = (unsigned char) ui_colmax; /* this is safer */ } #ifdef DEBUG fprintf(stderr,"\nreading picture: %s X: %u Y: %u\n",name,xmax,ymax); #endif x_min= xmax; x_max= 0; y_min= ymax; y_max= 0; if ( magic_found == 4 ) /* PBMRAW = Bitmap */ { /** read raw pbmfile **/ byte_xmax= xmax / 8; if (xmax % 8 != 0) byte_xmax++; } else /** assume ppm raw **/ { byte_xmax= xmax * 3; /* we have RGB, i.e. three bytes for each pixel */ } image_row= malloc(byte_xmax); if ( image_row ) { #if defined(_WIN32) && !defined(__CYGWIN__) /* this is really braindead stuff for MSVC */ i= _setmode( _fileno(stdin), _O_BINARY); if (i == -1) fprintf(stderr,"%s: ERROR - Cannot set binary mode for STDIN\n"); #endif for (y= 0; y= xmax ) break; #ifdef DEBUG printf("(%04d,%04d): \n",y,x); #endif } } /* end for */ } /* end if magic_found 4 */ else { /* assume PPM */ x= byte_x/3; /* we have 3 bytes per pixel */ #ifdef DEBUG printf("(%04d,%04d)%04d: \n",y,x,byte_x,colmax); #endif } /* update bounding box */ if ( x < x_min ) x_min= x; if ( x > x_max ) x_max= x; if ( y < y_min ) y_min= y; if ( y > y_max ) y_max= y; #ifdef DEBUG printf("ymin,ymax:(%04d,%04d) xmin,xmax:(%04d,%04d)", y_min,y_max,x_min,x_max); #endif break; /* stop here */ } /* if there are pixels not white */ } /* end for byte_x */ if ( byte_x != byte_xmax ) { /* there was a pixel with no background color */ tmprowp= image_row+byte_xmax-1; /* inspect this line from the right */ for (byte_x= byte_xmax-1; byte_x >= 0; byte_x--,tmprowp--) { if ( *tmprowp != colmax ) /* there are pixels not white */ { if ( magic_found == 4 ) { for (i= 0; i<8 ; i++) { if ( *tmprowp & bitval[i] ) { x= byte_x*8+i; if (x >= xmax) break; #ifdef DEBUG printf("(%04d,%04d): \n",y,x); #endif } } /* end for */ } /* end if magic_found 4 */ else { /* assume PPM */ x= byte_x/3; /* we have 3 bytes per pixel */ } /* update bounding box */ if ( x < x_min ) x_min= x; if ( x > x_max ) x_max= x; if ( y < y_min ) y_min= y; if ( y > y_max ) y_max= y; break; } /* if there are pixels not white */ } /* end for byte_x */ } /* if line contained not only background color */ } /* end for y */ #ifdef DEBUG_BOX fprintf(stderr,"(%04d,%04d), (%04d,%04d)\n", x_min,ymax-y_max,x_max,ymax-y_min); #endif /* distance from the left edge to the leftmost point */ hllx= (x_min*72.0)/resolution; /* distance from the bottom edge to the bottommost point */ hlly= ((ymax-y_max)*72.0)/resolution; /* distance from the left edge to the righmost point */ hurx= (x_max*72.0)/resolution; /* distance from the bottom edge to the uppermost point */ hury= ((ymax-y_min)*72.0)/resolution; if ( !tight ) { /* distance from the left edge to the leftmost point */ llx= minus_one((unsigned int) ((unsigned long) x_min*72UL)/resolution); /* distance from the bottom edge to the bottommost point */ lly= minus_one((unsigned int) ((unsigned long) (ymax-y_max)*72UL)/resolution); /* distance from the left edge to the righmost point */ urx= plus_one((unsigned int) ((unsigned long) x_max*72UL)/resolution); /* distance from the bottom edge to the uppermost point */ ury= plus_one((unsigned int) ((unsigned long) (ymax-y_min)*72UL)/resolution); } else /* tight bounding box */ { /* distance from the left edge to the leftmost point */ llx= (unsigned int) ((unsigned long) x_min*72UL)/resolution; /* distance from the bottom edge to the bottommost point */ lly= (unsigned int) ((unsigned long) (ymax-y_max)*72UL)/resolution; /* distance from the left edge to the righmost point */ urx= (unsigned int) ((unsigned long) x_max*72UL)/resolution; if ( (((unsigned long) x_max*72UL) % resolution) != 0 ) urx= plus_one(urx); /* distance from the bottom edge to the uppermost point */ ury= (unsigned int) ((unsigned long) (ymax-y_min)*72UL)/resolution; if ( (((unsigned long) (y_max-y_min)*72UL) % resolution) != 0 ) ury= plus_one(ury); } /* skip the rest of the file if any data is still present */ while ( !feof(inputfile) ) { fgets(inputline, 1024, inputfile); } /* give out Bounding Box */ printf("%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury); printf("%%%%HiResBoundingBox: %f %f %f %f\n", hllx, hlly, hurx, hury); } else fprintf(stderr,"%s: ERROR -- not enough memory to read in one row of the picture\n",prgname); fclose(inputfile); free(image_row); } int main(int argc, char **argv) { int i; char *filename= NULL; unsigned int resolution= 72; /* use 72 dpi as default resolution */ unsigned char tight= 1; for (i= 1; i