w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

bbox.c
Go to the documentation of this file.
1 /********************************************************************/
2 /** bbox -- calculates Bounding Box of a pbmraw/ppmraw-picture **/
3 /** Created: Nov. 1997, revised Feb. 1998, Dec. 1999, June 2009 **/
4 /** Author: Roland Bless <roland -at- bless.de> **/
5 /** Copyright (C) 1998-2009 Roland Bless **/
6 /** To compile simply use: **/
7 /** "cc bbox.c -o bbox" or "make bbox" **/
8 /********************************************************************/
9 /*
10  * $Id: bbox.c,v 1.18 2009-10-13 15:03:49 bless Exp $
11  */
12 
13 /**
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 **/
29 
30 /* Quoting EPSF Spec:
31  http://partners.adobe.com/public/developer/en/ps/5002.EPSF_Spec.pdf
32 
33  %!PS-Adobe-3.0 EPSF-3.0
34  %%BoundingBox: llx lly urx ury
35 
36  The four arguments of the bounding box comment correspond to the
37  lower-left (llx, lly) and upper-right (urx, ury) corners of the
38  bounding box. They are expressed in the default PostScript
39  coordinate system. For an EPS file, the bounding box is the smallest
40  rectangle that encloses all the marks painted on the single page of
41  the EPS file.
42 */
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 
47 #if defined(_WIN32) && !defined(__CYGWIN__)
48 #include <io.h> /* needed for _setmode() */
49 #include <fcntl.h>
50 #endif
51 
52 /**********************
53 * global variables *
54 **********************/
55 const char *const version= "$Revision: 1.18 $ $Date: 2009-10-13 15:03:49 $";
56 const char *const prgname= "bbox";
57 
58 const double round_precision= 1e-6;
59 
60 unsigned char bitval[8]=
61 {
62  1 << 7,
63  1 << 6,
64  1 << 5,
65  1 << 4,
66  1 << 3,
67  1 << 2,
68  1 << 1,
69  1
70 };
71 
72 static
73 unsigned int minus_one(const unsigned x)
74 {
75  return (x == 0) ? x : x-1;
76 }
77 
78 static
79 unsigned int plus_one(const unsigned x)
80 {
81  return (x == (unsigned int) ~0U) ? x : x+1;
82 }
83 
84 /***************************** readppm_and_calcbb ***********************
85 * input: name, resolution, tight *
86 * output: - (stdout) *
87 * *
88 * Reads a RAWPPM or RAWPBM picture file (name or STDIN) and *
89 * calculates its Bounding Box on-the-fly (line-by-line). *
90 * *
91 * Parameters: *
92 * name: name of the PBMRAW file or NULL (input from stdin) *
93 * resolution: Pixel per Inch (DPI) *
94 * tight: boolean value, if false 1 Postscript Point is added to *
95  each Bounding Box parameter, otherwise the BB is tight *
96 * The Bounding Box is given in Postscript Points (72 dots/inch) *
97 * and printed to stdout *
98 ************************************************************************/
99 /* calculate the bounding box in postscript points, given a resolution in dpi */
100 static
101 void readppm_and_calcbb(const char *name,
102  const unsigned int resolution,
103  const unsigned char tight)
104 {
105  FILE *inputfile;
106  char inputline[1024];
107  unsigned char magic_found= 0;
108  int x,y,byte_x,i;
109  const double pt_dpi_dbl= 72.0;
110  unsigned int x_min, x_max, y_min, y_max;
111  unsigned int llx, lly, urx, ury; /* bounding box */
112  double hllx, hlly, hurx, hury; /* hires bounding box */
113  unsigned char *image_row, /* ImageRow */
114  *tmpcolumnbytep;
115  unsigned int width,height; /* Image Size */
116  unsigned int byte_width;
117  unsigned char colormax= 0; /* max color value */
118  unsigned int ui_colormax= 0; /* max color value */
119 
120  if ( name == NULL )
121  {
122  inputfile = stdin;
123  name = "- STDIN -";
124  }
125  else
126  {
127  inputfile = fopen(name,"r");
128  if ( inputfile == NULL )
129  {
130  fprintf(stderr,"%s: ERROR -- could not open file %s\n",
131  prgname, name);
132  return;
133  }
134  }
135  /** check for magic number **/
136  do
137  {
138  fgets(inputline, 1024, inputfile);
139 #ifdef DEBUG
140  fprintf(stderr,"read:[%s]\n",inputline);
141 #endif
142  if ( strcmp(inputline,"P4\n") == 0 )
143  magic_found= 4;
144  else
145  if ( strcmp(inputline,"P6\n") == 0 )
146  magic_found= 6;
147  }
148  while ( !feof(inputfile) && !magic_found );
149 
150  if ( !magic_found )
151  {
152  fprintf(stderr,"%s: ERROR -- %s is not in ppmraw or pbmraw format\n",
153  prgname, name);
154  return;
155  }
156  /** skip comments **/
157  do
158  {
159  fgets(inputline, 1024, inputfile);
160 #ifdef DEBUG
161  fprintf(stderr,"read:[%s]\n",inputline);
162 #endif
163  if (*inputline == '#')
164  continue;
165  else
166  break;
167  }
168  while ( !feof(inputfile) );
169  /** read picture size: width, height **/
170  sscanf(inputline,"%u %u",&width,&height);
171  if ( magic_found == 6 ) /* PPM file has maximum color-component value */
172  {
173  fgets(inputline, 1024, inputfile);
174  sscanf(inputline,"%u",&ui_colormax);
175  colormax = (unsigned char) ui_colormax; /* this is safer */
176  }
177 #ifdef DEBUG
178  fprintf(stderr,"\nreading picture: %s size X: %u Y: %u\n",name,width,height);
179 #endif
180  x = 0; /* avoid uninitialized warning */
181  x_min= width>0 ? width-1 : 0;
182  x_max= 0;
183  y_min= height>0 ? height-1 : 0;
184  y_max= 0;
185  if ( magic_found == 4 ) /* PBMRAW = Bitmap */
186  { /** read raw pbmfile **/
187  byte_width= width / 8;
188  if (width % 8 != 0)
189  byte_width++;
190  }
191  else /** assume ppm raw **/
192  {
193  byte_width= width * 3; /* we have RGB, i.e. three bytes for each pixel */
194  }
195  /*
196  * Now read a raster of Width * Height pixels, proceeding through the image in normal English reading order,
197  * i.e., starting from top left then moving right
198  */
199  /* we allocate only one line */
200  image_row= malloc(byte_width);
201  if ( image_row )
202  {
203 #if defined(_WIN32) && !defined(__CYGWIN__) /* this is really braindead stuff for MSVC */
204  i= _setmode( _fileno(stdin), _O_BINARY);
205  if (i == -1)
206  fprintf(stderr,"%s: ERROR - Cannot set binary mode for STDIN\n", prgname);
207  i= _setmode( _fileno(stdout), _O_BINARY);
208  if (i == -1)
209  fprintf(stderr,"%s: ERROR - Cannot set binary mode for STDOUT\n", prgname);
210 #endif
211  for (y= 0; y<height; y++) /* for every image row 0..height-1 */
212  {
213  if (fread(image_row, byte_width, 1, inputfile) != 1)
214  {
215  fprintf(stderr,"%s: WARNING -- fread incomplete - file %s seems to be corrupt\n", prgname, name);
216  break;
217  }
218  tmpcolumnbytep= image_row;
219  /* inspect this line from left to right */
220  for (byte_x= 0; byte_x<byte_width; byte_x++,tmpcolumnbytep++)
221  {
222  if (*tmpcolumnbytep != colormax) /* there are pixels not white */
223  {
224  if (magic_found == 4)
225  {
226  for (i= 0; i<8 ; i++)
227  {
228  if (*tmpcolumnbytep & bitval[i])
229  {
230  x= byte_x*8+i;
231  if ( x >= width ) break;
232 #ifdef DEBUG
233  printf("(row %04d, %04d): <not white>\n",y,x);
234 #endif
235  }
236  } /* end for */
237  } /* end if magic_found 4 */
238  else
239  { /* assume PPM */
240  x= byte_x/3; /* we have 3 bytes per pixel */
241 #ifdef DEBUG
242  printf("(row %04d, col %04d) byte %04d: <not %d>\n",y,x,byte_x,colormax);
243 #endif
244  }
245  /* update bounding box */
246  if ( x < x_min ) x_min= x;
247  if ( x > x_max ) x_max= x;
248  if ( y < y_min ) y_min= y;
249  if ( y > y_max ) y_max= y;
250 #ifdef DEBUG
251  printf("ymin,height:(%04d,%04d) xmin,width:(%04d,%04d)\n",
253 #endif
254  break;
255  } /* if there are pixels not white */
256  } /* end for byte_x */
257  if ( byte_x != byte_width )
258  { /* there was a pixel with no background color */
259  tmpcolumnbytep= image_row+byte_width-1;
260  /* inspect this line from the right */
261  for (byte_x= byte_width-1;
262  byte_x >= 0;
263  byte_x--,tmpcolumnbytep--)
264  {
265  if ( *tmpcolumnbytep != colormax ) /* there are pixels not white */
266  {
267  if ( magic_found == 4 )
268  {
269  for (i= 0; i<8 ; i++)
270  {
271  if ( *tmpcolumnbytep & bitval[i] )
272  {
273  x= byte_x*8+i;
274  if (x >= width) break;
275 #ifdef DEBUG
276  printf("(%04d,%04d): <not white>\n",y,x);
277 #endif
278  }
279  } /* end for */
280  } /* end if magic_found 4 */
281  else
282  { /* assume PPM */
283  x= byte_x/3; /* we have 3 bytes per pixel */
284  }
285  /* update bounding box */
286  if ( x < x_min ) x_min= x;
287  if ( x > x_max ) x_max= x;
288  if ( y < y_min ) y_min= y;
289  if ( y > y_max ) y_max= y;
290 #ifdef DEBUG
291  printf("ymin,height:(%04d,%04d) xmin,width:(%04d,%04d)\n",
293 #endif
294  break;
295  } /* if there are pixels not white */
296  } /* end for byte_x */
297  } /* if line contained not only background color */
298  } /* end for y */
299 #ifdef DEBUG_BOX
300  fprintf(stderr,"(%04d,%04d), (%04d,%04d)\n", x_min,height-y_max,x_max,height-y_min);
301 #endif
302  /* distance from the left edge to the leftmost point */
303  hllx= (x_min*pt_dpi_dbl)/resolution;
304  /* distance from the bottom edge to the bottommost point */
305  hlly= ((minus_one(height)-y_max)*pt_dpi_dbl)/resolution;
306  /* distance from the left edge to the righmost point */
307  hurx= (plus_one(x_max)*pt_dpi_dbl)/resolution;
308  /* distance from the bottom edge to the uppermost point */
309  hury= ((height-y_min)*pt_dpi_dbl)/resolution;
310 
311 
312  if ( !tight )
313  {
314  /* distance from the left edge to the leftmost point */
315  llx= minus_one((unsigned int) ((unsigned long) x_min*72UL)/resolution);
316  /* distance from the bottom edge to the bottommost point */
317  lly= minus_one((unsigned int) ((unsigned long) (minus_one(height)-y_max)*72UL)/resolution);
318  /* distance from the left edge to the righmost point */
319  urx= plus_one((unsigned int) ((unsigned long) plus_one(x_max)*72UL)/resolution);
320  /* distance from the bottom edge to the uppermost point */
321  ury= plus_one((unsigned int) ((unsigned long) (height-y_min)*72UL)/resolution);
322 
323  /* also loosen hires BBox by default precision */
324  if (hllx-round_precision >= 0.0)
325  hllx-= round_precision;
326  if (hlly-round_precision >= 0.0)
327  hlly-= round_precision;
328 
329  hurx+= round_precision;
330  hury+= round_precision;
331  }
332  else /* tight bounding box */
333  {
334  /* distance from the left edge to the leftmost point */
335  llx= (unsigned int) ((unsigned long) x_min*72UL)/resolution;
336  /* distance from the bottom edge to the bottommost point */
337  lly= (unsigned int) ((unsigned long) (minus_one(height)-y_max)*72UL)/resolution;
338  /* distance from the left edge to the righmost point */
339  urx= (unsigned int) ((unsigned long) plus_one(x_max)*72UL)/resolution;
340  /* round up if we got a remainder */
341  if ( (((unsigned long) plus_one(x_max)*72UL) % resolution) != 0 )
342  urx= plus_one(urx);
343  /* distance from the bottom edge to the uppermost point */
344  ury= (unsigned int) ((unsigned long) (height-y_min)*72UL)/resolution;
345  if ( (((unsigned long) (height-y_min)*72UL) % resolution) != 0 )
346  ury= plus_one(ury);
347  }
348  /* skip the rest of the file if any data is still present */
349  while ( !feof(inputfile) )
350  {
351  fgets(inputline, 1024, inputfile);
352  }
353 
354  /* give out Bounding Box */
355  printf("%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury);
356  printf("%%%%HiResBoundingBox: %f %f %f %f\n", hllx, hlly, hurx, hury);
357  }
358  else
359  fprintf(stderr,"%s: ERROR -- not enough memory to read in one row of the picture\n",prgname);
360 
361  fclose(inputfile);
362  free(image_row);
363 }
364 
365 
366 int
367 main(int argc, char **argv)
368 {
369  int i;
370  char *filename= NULL;
371  unsigned int resolution= 72; /* use 72 dpi as default resolution */
372  unsigned char tight= 1;
373 
374  for (i= 1; i<argc; i++)
375  {
376  if ( strcmp(argv[i],"-r") == 0 )
377  {
378  if (++i<argc)
379  resolution= atol(argv[i]);
380  else
381  fprintf(stderr,"%s: ERROR -- Missing resolution after -r\n",prgname);
382  }
383  else
384  if ( strcmp(argv[i],"-l") == 0 )
385  {
386  tight= 0;
387  }
388  else
389  if ( strcmp(argv[i],"-V") == 0 || strcmp(argv[i],"--version")==0 )
390  {
391  printf("%s: bbox Version %s\n",prgname,version);
392  return 0;
393  }
394  else
395  if ( strcmp(argv[i],"-h")==0 || strcmp(argv[i],"--help")==0 )
396  {
397  printf("%s: Version %s\n",prgname,version);
398  printf(" usage: %s [-l] [-r resolution] [-V] [filename]\n",prgname);
399  printf(" -l: loose bounding box (bbox is expanded by 1 point)\n");
400  printf(" -r: resolution of picture in dpi\n");
401  printf(" -V: version information\n");
402  printf(" -h: this help\n");
403  printf(" bbox reads a rawppm or rawpbm file and prints out the\n");
404  printf(" bounding box of the image. If no filename is specified\n");
405  printf(" input is read from standard input.\n");
406  return 0;
407  }
408  else
409  if ( argv[i][0] == '-' ) /* unkown option */
410  {
411  fprintf(stderr,"%s: ERROR -- unknown option %s\n call %s -h for help on usage\n",
412  prgname, argv[i], prgname);
413  return 1;
414  }
415  else /* filename argument */
416  filename= argv[i];
417  }
418 
420 
421  return 0;
422 }
#define width(a)
Definition: aptex-macros.h:198
#define name
#define height(a)
Definition: aptex-macros.h:200
#define free(a)
Definition: decNumber.cpp:310
#define fopen
Definition: xxstdio.h:21
#define fread
Definition: xxstdio.h:25
#define fgets
Definition: xxstdio.h:29
int strcmp()
Definition: coll.cpp:143
int sscanf()
int printf()
int x_max
int y_min
int y_max
int x_min
FILE * inputfile
Definition: ebb.c:324
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
kerning y
Definition: ttdriver.c:212
long atol(const char *)
static integer urx
Definition: bbox.c:252
static integer llx
Definition: bbox.c:252
static integer lly
Definition: bbox.c:252
static integer ury
Definition: bbox.c:252
#define fclose
Definition: debug.h:100
#define fprintf
Definition: mendex.h:64
#define malloc
Definition: alloca.c:91
int main(int argc, char **argv)
Definition: bbox.c:367
static void readppm_and_calcbb(const char *name, const unsigned int resolution, const unsigned char tight)
Definition: bbox.c:101
unsigned char bitval[8]
Definition: bbox.c:60
static unsigned int plus_one(const unsigned x)
Definition: bbox.c:79
static unsigned int minus_one(const unsigned x)
Definition: bbox.c:73
const char *const prgname
Definition: bbox.c:56
const char *const version
Definition: bbox.c:55
const double round_precision
Definition: bbox.c:58
#define _O_BINARY
Definition: lfs.c:127
float x
Definition: cordic.py:15
integer resolution
Definition: pbmtopk.c:45
char * filename[256]
Definition: pbmtopk.c:46
ShellFileEnvironment e
Definition: sh6.c:388
#define FILE
Definition: t1stdio.h:34
#define feof(f)
Definition: t1stdio.h:109
return() int(((double) *(font_tbl[cur_fnt].wtbl+(int)(*(font_tbl[cur_fnt].char_wi+(int)(ch - font_tbl[cur_fnt].char_f)% 256)))/(double)(1L<< 20)) *(double) font_tbl[cur_fnt].scale)
#define U(a)
Definition: twiddle.h:1
#define argv
Definition: xmain.c:270
#define argc
Definition: xmain.c:269