1 /* pnmtile.c - replicate a portable anymap into a specified size
2 **
3 ** Copyright (C) 1989 by Jef Poskanzer.
4 **
5 ** Permission to use, copy, modify, and distribute this software and its
6 ** documentation for any purpose and without fee is hereby granted, provided
7 ** that the above copyright notice appear in all copies and that both that
8 ** copyright notice and this permission notice appear in supporting
9 ** documentation.  This software is provided "as is" without express or
10 ** implied warranty.
11 */
12 
13 #include "pm_c_util.h"
14 #include "mallocvar.h"
15 #include "shhopt.h"
16 #include "pnm.h"
17 
18 
19 
20 struct cmdlineInfo {
21     /* All the information the user supplied in the command line,
22        in a form easy for the program to use.
23     */
24     const char * inputFileName;
25     unsigned int width;
26     unsigned int height;
27 };
28 
29 
30 
31 static void
parseCommandLine(int argc,const char ** argv,struct cmdlineInfo * const cmdlineP)32 parseCommandLine(int argc, const char ** argv,
33                  struct cmdlineInfo * const cmdlineP) {
34 /*----------------------------------------------------------------------------
35    Note that the file spec array we return is stored in the storage that
36    was passed to us as the argv array.
37 -----------------------------------------------------------------------------*/
38     optEntry *option_def;
39         /* Instructions to OptParseOptions3 on how to parse our options.
40          */
41     optStruct3 opt;
42 
43     unsigned int option_def_index;
44 
45     MALLOCARRAY_NOFAIL(option_def, 100);
46 
47     option_def_index = 0;   /* incremented by OPTENT3 */
48 
49     opt.opt_table = option_def;
50     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
51     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
52 
53     OPTENTINIT;
54 
55     pm_optParseOptions3(&argc, (char**)argv, opt, sizeof opt, 0);
56         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
57 
58     if (argc-1 < 2)
59         pm_error("You must specify at least two parameters: "
60                  "width and height.  You specified %u",
61                  argc-1);
62     else {
63         cmdlineP->width  = pm_parse_width(argv[1]);
64         cmdlineP->height = pm_parse_height(argv[2]);
65 
66         if (argc-1 > 2) {
67             cmdlineP->inputFileName = argv[3];
68 
69             if (argc-1 > 3)
70                 pm_error("There are at most three arguments: "
71                          "width, height, file name.  You specified %u",
72                          argc-1);
73         } else
74             cmdlineP->inputFileName = "-";
75     }
76 }
77 
78 
79 
80 int
main(int argc,const char ** argv)81 main(int argc, const char ** argv) {
82 
83     struct cmdlineInfo cmdline;
84     FILE * ifP;
85     xel ** xels;
86     xel * xelrow;
87     xelval maxval;
88     int rows, cols;
89     int format;
90     unsigned int row;
91 
92     pm_proginit(&argc, argv);
93 
94     parseCommandLine(argc, argv, &cmdline);
95 
96     ifP = pm_openr(cmdline.inputFileName);
97 
98     xels = pnm_readpnm(ifP, &cols, &rows, &maxval, &format);
99     pm_close(ifP);
100 
101     xelrow = pnm_allocrow(cmdline.width);
102 
103     pnm_writepnminit(stdout, cmdline.width, cmdline.height, maxval, format, 0);
104     for (row = 0; row < cmdline.height; ++row) {
105         unsigned int col;
106         for (col = 0; col < cmdline.width; ++col)
107             xelrow[col] = xels[row % rows][col % cols];
108         pnm_writepnmrow(stdout, xelrow, cmdline.width, maxval, format, 0);
109     }
110 
111     pm_close(stdout);
112 
113     return 0;
114 }
115