1 /* cmuwmtopbm.c - read a CMU window manager bitmap and produce a PBM image.
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 /* 2006.10 (afu)
14    Changed bitrow from plain to raw, read function from getc() to fread(),
15    write function from pbm_writepbmrow() to pbm_writepbmrow_packed().
16    Retired bitwise transformation functions.
17 
18    This program does not check the pad bits at the end of each row.
19 */
20 
21 
22 #include "pbm.h"
23 
24 /*--------------------------
25   CMUWN Header format:
26 
27   32 bit const magic = 0xf10040bb ;
28   32 bit int   width;
29   32 bit int   height;
30   16 bit int   depth;
31 
32   values are big-endian.
33 --------------------------*/
34 
35 static void
readCmuwmHeader(FILE * const ifP,unsigned int * const colsP,unsigned int * const rowsP,unsigned int * const depthP)36 readCmuwmHeader(FILE *         const ifP,
37                 unsigned int * const colsP,
38                 unsigned int * const rowsP,
39                 unsigned int * const depthP) {
40 
41     const char * const initReadError =
42         "CMU window manager header EOF / read error";
43     uint32_t const cmuwmMagic = 0xf10040bb;
44 
45     long l;
46     short s;
47     int rc;
48 
49     rc = pm_readbiglong(ifP, &l);
50     if (rc == -1 )
51         pm_error("%s", initReadError);
52     if ((uint32_t)l != cmuwmMagic)
53         pm_error("bad magic number in CMU window manager file");
54     rc = pm_readbiglong(ifP, &l);
55     if (rc == -1)
56         pm_error("%s", initReadError);
57     *colsP = l;
58     rc = pm_readbiglong(ifP, &l);
59     if (rc == -1 )
60         pm_error("%s", initReadError);
61     *rowsP = l;
62     rc = pm_readbigshort(ifP, &s);
63     if (rc == -1)
64         pm_error("%s", initReadError);
65     *depthP = s;
66 }
67 
68 
69 
70 int
main(int argc,const char ** argv)71 main(int           argc,
72      const char ** argv) {
73 
74     FILE * ifP;
75     unsigned char * bitrow;
76     unsigned int rows, cols, depth;
77     unsigned int row;
78 
79     const char * inputFileName;
80 
81     pm_proginit(&argc, argv);
82 
83     if (argc-1 > 1)
84         pm_error("Too many arguments (%u).  "
85                  "Only argument is optional input file", argc-1);
86     if (argc-1 == 1)
87         inputFileName = argv[1];
88     else
89         inputFileName = "-";
90 
91     ifP = pm_openr(inputFileName);
92 
93     readCmuwmHeader(ifP, &cols, &rows, &depth);
94     if (depth != 1)
95         pm_error("CMU window manager file has depth of %u, must be 1", depth);
96 
97     pbm_writepbminit(stdout, cols, rows, 0);
98     bitrow = pbm_allocrow_packed(cols);
99 
100     for (row = 0; row < rows; ++row) {
101         unsigned int const bytesPerRow = pbm_packed_bytes(cols);
102         unsigned int byteSeq;
103         size_t bytesRead;
104 
105         bytesRead = fread(bitrow, 1, bytesPerRow, ifP);
106         if (bytesRead != bytesPerRow)
107             pm_error("CWU window manager bitmap EOF / read error");
108 
109         /* Invert all bits in row - raster formats are similar.
110            CMUWM Black:0 White:1  End of row padded with 1
111            PBM   Black:1 White:0  End preferably padded with 0
112         */
113 
114         for (byteSeq = 0; byteSeq < bytesPerRow; ++byteSeq)
115             bitrow[byteSeq] = ~bitrow[byteSeq];
116 
117         pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
118     }
119 
120     pbm_freerow_packed(bitrow);
121     pm_close(ifP);
122     pm_close(stdout);
123 
124     return 0;
125 }
126