1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/* pnminvert.c - read a portable anymap and invert it
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/
#include "pnm.h"
/* Implementation note: A suitably advanced compiler, such as Gcc 4,
implements the for statements in our algorithm with instructions that do 16
bytes at a time on CPUs that have them (movdqa on x86). This is "tree
vectorization." A more primitive compiler will do one byte at a time; we
could change the code to use libnetpbm's wordaccess.h facility and it will
do one word at a time. (But we don't think it's worth complicating the
code for that).
*/
#define CHARBITS (sizeof(unsigned char)*8)
static void
invertPbm(FILE * const ifP,
FILE * const ofP,
int const cols,
int const rows,
int const format) {
/*----------------------------------------------------------------------------
Invert a PBM image. Use the "packed" PBM functions for speed.
-----------------------------------------------------------------------------*/
int const colChars = pbm_packed_bytes(cols);
unsigned char * bitrow;
unsigned int row;
bitrow = pbm_allocrow_packed(cols);
for (row = 0; row < rows; ++row) {
unsigned int colChar;
pbm_readpbmrow_packed(ifP, bitrow, cols, format);
for (colChar = 0; colChar < colChars; ++colChar)
bitrow[colChar] = ~ bitrow[colChar];
/* Clean off remainder of fractional last character */
if (cols % CHARBITS > 0) {
bitrow[colChars-1] >>= CHARBITS - cols % CHARBITS;
bitrow[colChars-1] <<= CHARBITS - cols % CHARBITS;
}
pbm_writepbmrow_packed(ofP, bitrow, cols, 0);
}
pbm_freerow_packed(bitrow);
}
static void
invertPnm(FILE * const ifP,
FILE * const ofP,
int const cols,
int const rows,
xelval const maxval,
int const format) {
xel * xelrow;
unsigned int row;
xelrow = pnm_allocrow(cols);
for (row = 0; row < rows; ++row) {
unsigned int col;
pnm_readpnmrow(ifP, xelrow, cols, maxval, format);
for (col = 0; col < cols; ++col)
pnm_invertxel(&xelrow[col], maxval, format);
pnm_writepnmrow(ofP, xelrow, cols, maxval, format, 0);
}
pnm_freerow(xelrow);
}
int
main(int argc, char * argv[]) {
FILE* ifP;
xelval maxval;
int rows, cols, format;
pnm_init(&argc, argv);
if (argc-1 > 1)
pm_error("There is at most 1 argument - the input file name. "
"You specified %d", argc-1);
if (argc-1 == 1)
ifP = pm_openr(argv[1]);
else
ifP = stdin;
pnm_readpnminit(ifP, &cols, &rows, &maxval, &format);
pnm_writepnminit(stdout, cols, rows, maxval, format, 0);
if (PNM_FORMAT_TYPE(format) == PBM_TYPE)
/* Take fast path */
invertPbm(ifP, stdout, cols, rows, format);
else
/* PPM , PGM (logic also works for PBM) */
invertPnm(ifP, stdout, cols, rows, maxval, format);
pm_close(ifP);
pm_close(stdout);
return 0;
}
|