1 /* pnmpad.c - add border to sides of a portable anymap
2 ** AJCD 4/9/90
3 */
4
5 #include <assert.h>
6 #include <string.h>
7 #include <stdio.h>
8
9 #include "pm_c_util.h"
10 #include "mallocvar.h"
11 #include "shhopt.h"
12 #include "pnm.h"
13
14 #define MAX_WIDTHHEIGHT INT_MAX-10
15 /* The maximum width or height value we can handle without risking
16 arithmetic overflow
17 */
18
19 struct cmdlineInfo {
20 /* All the information the user supplied in the command line,
21 in a form easy for the program to use.
22 */
23 const char * input_filespec; /* Filespecs of input files */
24 unsigned int xsize;
25 unsigned int xsizeSpec;
26 unsigned int ysize;
27 unsigned int ysizeSpec;
28 unsigned int left;
29 unsigned int right;
30 unsigned int top;
31 unsigned int bottom;
32 unsigned int leftSpec;
33 unsigned int rightSpec;
34 unsigned int topSpec;
35 unsigned int bottomSpec;
36 float xalign;
37 float yalign;
38 unsigned int mwidth;
39 unsigned int mheight;
40 unsigned int white; /* >0: pad white; 0: pad black */
41 unsigned int reportonly;
42 unsigned int verbose;
43 };
44
45
46
47 static void
parseCommandLine(int argc,const char ** argv,struct cmdlineInfo * const cmdlineP)48 parseCommandLine(int argc, const char ** argv,
49 struct cmdlineInfo * const cmdlineP) {
50 /*----------------------------------------------------------------------------
51 Note that the file spec array we return is stored in the storage that
52 was passed to us as the argv array.
53 -----------------------------------------------------------------------------*/
54 optEntry *option_def;
55 /* Instructions to OptParseOptions3 on how to parse our options.
56 */
57 optStruct3 opt;
58
59 unsigned int option_def_index;
60 unsigned int blackOpt;
61 unsigned int xalignSpec, yalignSpec, mwidthSpec, mheightSpec;
62
63 MALLOCARRAY_NOFAIL(option_def, 100);
64
65 option_def_index = 0; /* incremented by OPTENT3 */
66 OPTENT3(0, "xsize", OPT_UINT, &cmdlineP->xsize,
67 &cmdlineP->xsizeSpec, 0);
68 OPTENT3(0, "width", OPT_UINT, &cmdlineP->xsize,
69 &cmdlineP->xsizeSpec, 0);
70 OPTENT3(0, "ysize", OPT_UINT, &cmdlineP->ysize,
71 &cmdlineP->ysizeSpec, 0);
72 OPTENT3(0, "height", OPT_UINT, &cmdlineP->ysize,
73 &cmdlineP->ysizeSpec, 0);
74 OPTENT3(0, "left", OPT_UINT, &cmdlineP->left,
75 &cmdlineP->leftSpec, 0);
76 OPTENT3(0, "right", OPT_UINT, &cmdlineP->right,
77 &cmdlineP->rightSpec, 0);
78 OPTENT3(0, "top", OPT_UINT, &cmdlineP->top,
79 &cmdlineP->topSpec, 0);
80 OPTENT3(0, "bottom", OPT_UINT, &cmdlineP->bottom,
81 &cmdlineP->bottomSpec, 0);
82 OPTENT3(0, "xalign", OPT_FLOAT, &cmdlineP->xalign,
83 &xalignSpec, 0);
84 OPTENT3(0, "halign", OPT_FLOAT, &cmdlineP->xalign,
85 &xalignSpec, 0);
86 OPTENT3(0, "yalign", OPT_FLOAT, &cmdlineP->yalign,
87 &yalignSpec, 0);
88 OPTENT3(0, "valign", OPT_FLOAT, &cmdlineP->yalign,
89 &yalignSpec, 0);
90 OPTENT3(0, "mwidth", OPT_UINT, &cmdlineP->mwidth,
91 &mwidthSpec, 0);
92 OPTENT3(0, "mheight", OPT_UINT, &cmdlineP->mheight,
93 &mheightSpec, 0);
94 OPTENT3(0, "black", OPT_FLAG, NULL,
95 &blackOpt, 0);
96 OPTENT3(0, "white", OPT_FLAG, NULL,
97 &cmdlineP->white, 0);
98 OPTENT3(0, "reportonly", OPT_FLAG, NULL,
99 &cmdlineP->reportonly, 0);
100 OPTENT3(0, "verbose", OPT_FLAG, NULL,
101 &cmdlineP->verbose, 0);
102
103 opt.opt_table = option_def;
104 opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */
105 opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */
106
107 pm_optParseOptions3(&argc, (char **)argv, opt, sizeof opt, 0);
108 /* Uses and sets argc, argv, and some of *cmdlineP and others. */
109
110 if (blackOpt && cmdlineP->white)
111 pm_error("You cannot specify both -black and -white");
112
113 if (cmdlineP->topSpec > 1)
114 pm_error("You can specify -top only once");
115
116 if (cmdlineP->bottomSpec > 1)
117 pm_error("You can specify -bottom only once");
118
119 if (cmdlineP->leftSpec > 1)
120 pm_error("You can specify -left only once");
121
122 if (cmdlineP->rightSpec > 1)
123 pm_error("You can specify -right only once");
124
125 if (cmdlineP->xsizeSpec > 1)
126 pm_error("You can specify -width only once");
127
128 if (cmdlineP->ysizeSpec > 1)
129 pm_error("You can specify -height only once");
130
131 if (xalignSpec && (cmdlineP->leftSpec || cmdlineP->rightSpec))
132 pm_error("You cannot specify both -xalign and -left or -right");
133
134 if (yalignSpec && (cmdlineP->topSpec || cmdlineP->bottomSpec))
135 pm_error("You cannot specify both -yalign and -top or -bottom");
136
137 if (xalignSpec && !cmdlineP->xsizeSpec)
138 pm_error("-xalign is meaningless without -width");
139
140 if (yalignSpec && !cmdlineP->ysizeSpec)
141 pm_error("-yalign is meaningless without -height");
142
143 if (xalignSpec) {
144 if (cmdlineP->xalign < 0)
145 pm_error("You have specified a negative -halign value (%f)",
146 cmdlineP->xalign);
147 if (cmdlineP->xalign > 1)
148 pm_error("You have specified a -halign value (%f) greater than 1",
149 cmdlineP->xalign);
150 } else
151 cmdlineP->xalign = 0.5;
152
153 if (yalignSpec) {
154 if (cmdlineP->yalign < 0)
155 pm_error("You have specified a negative -halign value (%f)",
156 cmdlineP->yalign);
157 if (cmdlineP->yalign > 1)
158 pm_error("You have specified a -valign value (%f) greater than 1",
159 cmdlineP->yalign);
160 } else
161 cmdlineP->yalign = 0.5;
162
163 if (!mwidthSpec)
164 cmdlineP->mwidth = 1;
165
166 if (!mheightSpec)
167 cmdlineP->mheight = 1;
168
169 /* get optional input filename */
170 if (argc-1 > 1)
171 pm_error("This program takes at most 1 parameter. You specified %d",
172 argc-1);
173 else if (argc-1 == 1)
174 cmdlineP->input_filespec = argv[1];
175 else
176 cmdlineP->input_filespec = "-";
177 }
178
179
180
181 static void
parseCommandLineOld(int argc,const char ** argv,struct cmdlineInfo * const cmdlineP)182 parseCommandLineOld(int argc, const char ** argv,
183 struct cmdlineInfo * const cmdlineP) {
184
185 /* This syntax was abandoned in February 2002. */
186 pm_message("Warning: old style options are deprecated!");
187
188 cmdlineP->xsize = cmdlineP->ysize = 0;
189 cmdlineP->left = cmdlineP->right = cmdlineP->top = cmdlineP->bottom = 0;
190 cmdlineP->xalign = cmdlineP->yalign = 0.5;
191 cmdlineP->white = cmdlineP->verbose = FALSE;
192
193 while (argc >= 2 && argv[1][0] == '-') {
194 if (strcmp(argv[1]+1,"black") == 0) cmdlineP->white = FALSE;
195 else if (strcmp(argv[1]+1,"white") == 0) cmdlineP->white = TRUE;
196 else switch (argv[1][1]) {
197 case 'l':
198 if (atoi(argv[1]+2) < 0)
199 pm_error("left border too small");
200 else if (atoi(argv[1]+2) > MAX_WIDTHHEIGHT)
201 pm_error("left border too large");
202 else
203 cmdlineP->left = atoi(argv[1]+2);
204 break;
205 case 'r':
206 if (atoi(argv[1]+2) < 0)
207 pm_error("right border too small");
208 else if (atoi(argv[1]+2) > MAX_WIDTHHEIGHT)
209 pm_error("right border too large");
210 else
211 cmdlineP->right = atoi(argv[1]+2);
212 break;
213 case 'b':
214 if (atoi(argv[1]+2) < 0)
215 pm_error("bottom border too small");
216 else if (atoi(argv[1]+2) > MAX_WIDTHHEIGHT)
217 pm_error("bottom border too large");
218 else
219 cmdlineP->bottom = atoi(argv[1]+2);
220 break;
221 case 't':
222 if (atoi(argv[1]+2) < 0)
223 pm_error("top border too small");
224 else if (atoi(argv[1]+2) > MAX_WIDTHHEIGHT)
225 pm_error("top border too large");
226 else
227 cmdlineP->top = atoi(argv[1]+2);
228 break;
229 default:
230 pm_usage("[-white|-black] [-l#] [-r#] [-t#] [-b#] [pnmfile]");
231 }
232 argc--, argv++;
233 }
234
235 cmdlineP->xsizeSpec = (cmdlineP->xsize > 0);
236 cmdlineP->ysizeSpec = (cmdlineP->ysize > 0);
237
238 if (argc > 2)
239 pm_usage("[-white|-black] [-l#] [-r#] [-t#] [-b#] [pnmfile]");
240
241 if (argc == 2)
242 cmdlineP->input_filespec = argv[1];
243 else
244 cmdlineP->input_filespec = "-";
245 }
246
247
248
249 static void
validateHorizontalSize(struct cmdlineInfo const cmdline,unsigned int const cols)250 validateHorizontalSize(struct cmdlineInfo const cmdline,
251 unsigned int const cols) {
252 /*----------------------------------------------------------------------------
253 Abort the program if the padding parameters in 'cmdline', applied to
254 an image width 'cols', would result in numbers too large for us to
255 compute with easily.
256 -----------------------------------------------------------------------------*/
257 unsigned int const lpad = cmdline.leftSpec ? cmdline.left : 0;
258 unsigned int const rpad = cmdline.rightSpec ? cmdline.right : 0;
259 unsigned int const mwidthMaxPad = cmdline.mwidth - 1;
260
261 if (cmdline.xsizeSpec && cmdline.xsize > MAX_WIDTHHEIGHT)
262 pm_error("The width value you specified is too large.");
263
264 if (lpad > MAX_WIDTHHEIGHT)
265 pm_error("The left padding value you specified is too large.");
266
267 if (rpad > MAX_WIDTHHEIGHT)
268 pm_error("The right padding value you specified is too large.");
269
270 if ((double) cols +
271 (double) lpad +
272 (double) rpad +
273 (double) mwidthMaxPad > MAX_WIDTHHEIGHT)
274 pm_error("Given padding parameters make output width too large "
275 "for this program to compute");
276
277 if (cmdline.xsizeSpec &&
278 (double) cmdline.xsize + (double) mwidthMaxPad> MAX_WIDTHHEIGHT)
279 pm_error("Given padding parameters make output width too large "
280 "for this program to compute");
281 }
282
283
284
285 static void
computePadSizeBeforeMult(unsigned int const unpaddedSize,bool const sizeSpec,unsigned int const sizeReq,bool const begPadSpec,unsigned int const begPadReq,bool const endPadSpec,unsigned int const endPadReq,double const align,unsigned int * const begPadP,unsigned int * const endPadP)286 computePadSizeBeforeMult(unsigned int const unpaddedSize,
287 bool const sizeSpec,
288 unsigned int const sizeReq,
289 bool const begPadSpec,
290 unsigned int const begPadReq,
291 bool const endPadSpec,
292 unsigned int const endPadReq,
293 double const align,
294 unsigned int * const begPadP,
295 unsigned int * const endPadP) {
296 /*----------------------------------------------------------------------------
297 Compute the padding on each end that would be required if user did not
298 request any "multiple" padding; i.e. he didn't say request e.g. that the
299 output width be a multiple of 10 pixels.
300 -----------------------------------------------------------------------------*/
301 if (sizeSpec) {
302 if (begPadSpec && endPadSpec) {
303 if (begPadReq + unpaddedSize + endPadReq < unpaddedSize) {
304 pm_error("Beginning adding (%u), and end "
305 "padding (%u) are insufficient to bring the "
306 "image size of %u up to %u.",
307 begPadReq, endPadReq, unpaddedSize, sizeReq);
308 } else {
309 *begPadP = begPadReq;
310 *endPadP = endPadReq;
311 }
312 } else if (begPadSpec) {
313 *begPadP = begPadReq;
314 *endPadP = MAX(sizeReq, unpaddedSize + begPadReq) -
315 (begPadReq + unpaddedSize);
316 } else if (endPadSpec) {
317 *endPadP = endPadReq;
318 *begPadP = MAX(sizeReq, unpaddedSize + endPadReq) -
319 (unpaddedSize + endPadReq);
320 } else {
321 if (sizeReq > unpaddedSize) {
322 assert(align <= 1.0 && align >= 0.0);
323 *begPadP = ROUNDU((sizeReq - unpaddedSize) * align);
324 *endPadP = sizeReq - unpaddedSize - *begPadP;
325 assert(*begPadP + unpaddedSize + *endPadP == sizeReq);
326 } else {
327 *begPadP = 0;
328 *endPadP = 0;
329 }
330 }
331 } else {
332 *begPadP = begPadSpec ? begPadReq : 0;
333 *endPadP = endPadSpec ? endPadReq : 0;
334 }
335 }
336
337
338
339 static void
computePadSizesOneDim(unsigned int const unpaddedSize,bool const sizeSpec,unsigned int const sizeReq,bool const begPadSpec,unsigned int const begPadReq,bool const endPadSpec,unsigned int const endPadReq,double const align,unsigned int const multiple,unsigned int * const begPadP,unsigned int * const endPadP)340 computePadSizesOneDim(unsigned int const unpaddedSize,
341 bool const sizeSpec,
342 unsigned int const sizeReq,
343 bool const begPadSpec,
344 unsigned int const begPadReq,
345 bool const endPadSpec,
346 unsigned int const endPadReq,
347 double const align,
348 unsigned int const multiple,
349 unsigned int * const begPadP,
350 unsigned int * const endPadP) {
351 /*----------------------------------------------------------------------------
352 Compute the number of pixels of padding needed before and after a row or
353 column ("before" means on the left side of a row or the top side of a
354 column). Return them as *padBegP and *padEndP, respectively.
355
356 'unpaddedSize' is the size (width/height) of the row or column before
357 any padding.
358
359 The rest of the inputs are the padding parameters, equivalent to the
360 program's corresponding command line options.
361 -----------------------------------------------------------------------------*/
362 unsigned int begPadBeforeMult, endPadBeforeMult;
363 /* The padding we would apply if user did not request multiple
364 padding (such as "make the output a multiple of 10 pixels")
365 */
366
367 computePadSizeBeforeMult(unpaddedSize, sizeSpec, sizeReq,
368 begPadSpec, begPadReq, endPadSpec, endPadReq,
369 align,
370 &begPadBeforeMult, &endPadBeforeMult);
371
372 {
373 unsigned int const sizeBeforeMpad =
374 unpaddedSize + begPadBeforeMult + endPadBeforeMult;
375 unsigned int const paddedSize =
376 ROUNDUP(sizeBeforeMpad, multiple);
377 unsigned int const morePadNeeded = paddedSize - sizeBeforeMpad;
378 unsigned int const totalPadBeforeMult =
379 begPadBeforeMult + endPadBeforeMult;
380 double const begFrac =
381 totalPadBeforeMult > 0 ?
382 (double)begPadBeforeMult / totalPadBeforeMult :
383 0.0;
384 unsigned int const addlMsizeBegPad = ROUNDU(morePadNeeded * begFrac);
385 /* # of pixels we have to add to the beginning to satisfy
386 user's desire for the final size to be a multiple of something
387 */
388 unsigned int const addlMsizeEndPad = morePadNeeded - addlMsizeBegPad;
389 /* Analogous to 'addlMsizeBegPad' */
390
391 *begPadP = begPadBeforeMult + addlMsizeBegPad;
392 *endPadP = endPadBeforeMult + addlMsizeEndPad;
393 }
394 }
395
396
397
398 static void
computeHorizontalPadSizes(struct cmdlineInfo const cmdline,unsigned int const cols,unsigned int * const lpadP,unsigned int * const rpadP)399 computeHorizontalPadSizes(struct cmdlineInfo const cmdline,
400 unsigned int const cols,
401 unsigned int * const lpadP,
402 unsigned int * const rpadP) {
403
404 validateHorizontalSize(cmdline, cols);
405
406 computePadSizesOneDim(cols,
407 cmdline.xsizeSpec > 0, cmdline.xsize,
408 cmdline.leftSpec > 0, cmdline.left,
409 cmdline.rightSpec > 0, cmdline.right,
410 cmdline.xalign,
411 cmdline.mwidth,
412 lpadP, rpadP);
413 }
414
415
416
417 static void
validateVerticalSize(struct cmdlineInfo const cmdline,unsigned int const rows)418 validateVerticalSize(struct cmdlineInfo const cmdline,
419 unsigned int const rows) {
420 /*----------------------------------------------------------------------------
421 Abort the program if the padding parameters in 'cmdline', applied to
422 an image width 'cols', would result in numbers too large for us to
423 compute with easily.
424 -----------------------------------------------------------------------------*/
425 unsigned int const tpad =
426 cmdline.topSpec ? cmdline.top : 0;
427 unsigned int const bpad =
428 cmdline.bottomSpec ? cmdline.bottom : 0;
429 unsigned int const mheightMaxPad = cmdline.mheight - 1;
430
431 if (cmdline.ysizeSpec && cmdline.ysize > MAX_WIDTHHEIGHT)
432 pm_error("The width value you specified is too large.");
433
434 if (tpad > MAX_WIDTHHEIGHT)
435 pm_error("The top padding value you specified is too large.");
436
437 if (bpad > MAX_WIDTHHEIGHT)
438 pm_error("The bottom padding value you specified is too large.");
439
440 if ((double) rows +
441 (double) tpad +
442 (double) bpad +
443 (double) mheightMaxPad > MAX_WIDTHHEIGHT)
444 pm_error("Given padding parameters make output height too large "
445 "for this program to compute");
446
447 if (cmdline.ysizeSpec &&
448 (double) cmdline.ysize && (double) mheightMaxPad > MAX_WIDTHHEIGHT)
449 pm_error("Given padding parameters make output height too large "
450 "for this program to compute");
451 }
452
453
454
455 static void
computeVerticalPadSizes(struct cmdlineInfo const cmdline,int const rows,unsigned int * const tpadP,unsigned int * const bpadP)456 computeVerticalPadSizes(struct cmdlineInfo const cmdline,
457 int const rows,
458 unsigned int * const tpadP,
459 unsigned int * const bpadP) {
460
461 validateVerticalSize(cmdline, rows);
462
463 computePadSizesOneDim(rows,
464 cmdline.ysizeSpec > 0, cmdline.ysize,
465 cmdline.topSpec > 0, cmdline.top,
466 cmdline.bottomSpec > 0, cmdline.bottom,
467 cmdline.yalign,
468 cmdline.mheight,
469 tpadP, bpadP);
470 }
471
472
473
474 static void
computePadSizes(struct cmdlineInfo const cmdline,int const cols,int const rows,unsigned int * const lpadP,unsigned int * const rpadP,unsigned int * const tpadP,unsigned int * const bpadP)475 computePadSizes(struct cmdlineInfo const cmdline,
476 int const cols,
477 int const rows,
478 unsigned int * const lpadP,
479 unsigned int * const rpadP,
480 unsigned int * const tpadP,
481 unsigned int * const bpadP) {
482
483 computeHorizontalPadSizes(cmdline, cols, lpadP, rpadP);
484
485 computeVerticalPadSizes(cmdline, rows, tpadP, bpadP);
486
487 if (cmdline.verbose)
488 pm_message("Padding: left: %u; right: %u; top: %u; bottom: %u",
489 *lpadP, *rpadP, *tpadP, *bpadP);
490 }
491
492
493
494 static void
reportPadSizes(int const inCols,int const inRows,unsigned int const lpad,unsigned int const rpad,unsigned int const tpad,unsigned int const bpad)495 reportPadSizes(int const inCols,
496 int const inRows,
497 unsigned int const lpad,
498 unsigned int const rpad,
499 unsigned int const tpad,
500 unsigned int const bpad) {
501
502 unsigned int const outCols = inCols + lpad + rpad;
503 unsigned int const outRows = inRows + tpad + bpad;
504
505 printf("%u %u %u %u %u %u\n", lpad, rpad, tpad, bpad, outCols, outRows);
506
507 }
508
509
510
511 static void
padPbm(FILE * const ifP,unsigned int const cols,unsigned int const rows,int const format,unsigned int const newcols,unsigned int const lpad,unsigned int const rpad,unsigned int const tpad,unsigned int const bpad,bool const colorWhite)512 padPbm(FILE * const ifP,
513 unsigned int const cols,
514 unsigned int const rows,
515 int const format,
516 unsigned int const newcols,
517 unsigned int const lpad,
518 unsigned int const rpad,
519 unsigned int const tpad,
520 unsigned int const bpad,
521 bool const colorWhite) {
522 /*----------------------------------------------------------------------------
523 Fast padding routine for PBM
524 -----------------------------------------------------------------------------*/
525 unsigned char * const bgrow = pbm_allocrow_packed(newcols);
526 unsigned char * const newrow = pbm_allocrow_packed(newcols);
527
528 unsigned char const padChar =
529 0xff * (colorWhite ? PBM_WHITE : PBM_BLACK);
530
531 unsigned int const newColChars = pbm_packed_bytes(newcols);
532
533 unsigned int row;
534 unsigned int charCnt;
535
536 /* Set up margin row, input-output buffer */
537 for (charCnt = 0; charCnt < newColChars; ++charCnt)
538 bgrow[charCnt] = newrow[charCnt] = padChar;
539
540 if (newcols % 8 > 0) {
541 bgrow[newColChars-1] <<= 8 - newcols % 8;
542 newrow[newColChars-1] <<= 8 - newcols % 8;
543 }
544
545 pbm_writepbminit(stdout, newcols, rows + tpad + bpad, 0);
546
547 /* Write top margin */
548 for (row = 0; row < tpad; ++row)
549 pbm_writepbmrow_packed(stdout, bgrow, newcols, 0);
550
551 /* Read rows, shift and write with left and right margins added */
552 for (row = 0; row < rows; ++row) {
553 pbm_readpbmrow_bitoffset(ifP, newrow, cols, format, lpad);
554 pbm_writepbmrow_packed(stdout, newrow, newcols, 0);
555 }
556
557 pnm_freerow(newrow);
558
559 /* Write bottom margin */
560 for (row = 0; row < bpad; ++row)
561 pbm_writepbmrow_packed(stdout, bgrow, newcols, 0);
562
563 pnm_freerow(bgrow);
564 }
565
566
567 static void
padGeneral(FILE * const ifP,unsigned int const cols,unsigned int const rows,xelval const maxval,int const format,unsigned int const newcols,unsigned int const lpad,unsigned int const rpad,unsigned int const tpad,unsigned int const bpad,bool const colorWhite)568 padGeneral(FILE * const ifP,
569 unsigned int const cols,
570 unsigned int const rows,
571 xelval const maxval,
572 int const format,
573 unsigned int const newcols,
574 unsigned int const lpad,
575 unsigned int const rpad,
576 unsigned int const tpad,
577 unsigned int const bpad,
578 bool const colorWhite) {
579 /*----------------------------------------------------------------------------
580 General padding routine (logic works for PBM)
581 -----------------------------------------------------------------------------*/
582 xel * const bgrow = pnm_allocrow(newcols);
583 xel * const xelrow = pnm_allocrow(newcols);
584 xel background;
585 unsigned int row, col;
586
587 if (colorWhite)
588 background = pnm_whitexel(maxval, format);
589 else
590 background = pnm_blackxel(maxval, format);
591
592 for (col = 0; col < newcols; ++col)
593 xelrow[col] = bgrow[col] = background;
594
595 pnm_writepnminit(stdout, newcols, rows + tpad + bpad, maxval, format, 0);
596
597 for (row = 0; row < tpad; ++row)
598 pnm_writepnmrow(stdout, bgrow, newcols, maxval, format, 0);
599
600 for (row = 0; row < rows; ++row) {
601 pnm_readpnmrow(ifP, &xelrow[lpad], cols, maxval, format);
602 pnm_writepnmrow(stdout, xelrow, newcols, maxval, format, 0);
603 }
604
605 for (row = 0; row < bpad; ++row)
606 pnm_writepnmrow(stdout, bgrow, newcols, maxval, format, 0);
607
608 pnm_freerow(xelrow);
609 pnm_freerow(bgrow);
610 }
611
612
613
614 int
main(int argc,const char ** argv)615 main(int argc, const char ** argv) {
616
617 struct cmdlineInfo cmdline;
618 FILE * ifP;
619
620 xelval maxval;
621 int rows, cols, newcols, format;
622 bool depr_cmd; /* use deprecated commandline interface */
623 unsigned int lpad, rpad, tpad, bpad;
624
625 pm_proginit(&argc, argv);
626
627 /* detect deprecated options */
628 depr_cmd = FALSE; /* initial assumption */
629 if (argc > 1 && argv[1][0] == '-') {
630 if (argv[1][1] == 't' || argv[1][1] == 'b'
631 || argv[1][1] == 'l' || argv[1][1] == 'r') {
632 if (argv[1][2] >= '0' && argv[1][2] <= '9')
633 depr_cmd = TRUE;
634 }
635 }
636 if (argc > 2 && argv[2][0] == '-') {
637 if (argv[2][1] == 't' || argv[2][1] == 'b'
638 || argv[2][1] == 'l' || argv[2][1] == 'r') {
639 if (argv[2][2] >= '0' && argv[2][2] <= '9')
640 depr_cmd = TRUE;
641 }
642 }
643
644 if (depr_cmd)
645 parseCommandLineOld(argc, argv, &cmdline);
646 else
647 parseCommandLine(argc, argv, &cmdline);
648
649 ifP = pm_openr(cmdline.input_filespec);
650
651 pnm_readpnminit(ifP, &cols, &rows, &maxval, &format);
652
653 if (cmdline.verbose) pm_message("image WxH = %dx%d", cols, rows);
654
655 computePadSizes(cmdline, cols, rows, &lpad, &rpad, &tpad, &bpad);
656
657 newcols = cols + lpad + rpad;
658
659 if (cmdline.reportonly)
660 reportPadSizes(cols, rows, lpad, rpad, tpad, bpad);
661 else {
662 if (PNM_FORMAT_TYPE(format) == PBM_TYPE)
663 padPbm(ifP, cols, rows, format, newcols, lpad, rpad, tpad, bpad,
664 !!cmdline.white);
665 else
666 padGeneral(ifP, cols, rows, maxval, format,
667 newcols, lpad, rpad, tpad, bpad, !!cmdline.white);
668 }
669
670 pm_close(ifP);
671
672 return 0;
673 }
674