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