1 | /************************************************************************
|
---|
2 |
|
---|
3 | MxRaster
|
---|
4 |
|
---|
5 | Copyright (C) 1998 Michael Garland. See "COPYING.txt" for details.
|
---|
6 |
|
---|
7 | $Id: MxRaster.cxx,v 1.1 2002/09/24 16:53:54 wimmer Exp $
|
---|
8 |
|
---|
9 | ************************************************************************/
|
---|
10 |
|
---|
11 | #include "stdmix.h"
|
---|
12 | #include "MxRaster.h"
|
---|
13 |
|
---|
14 |
|
---|
15 | ////////////////////////////////////////////////////////////////////////
|
---|
16 | //
|
---|
17 | // Raster manipulation
|
---|
18 | //
|
---|
19 |
|
---|
20 | // !!BUG: This could probably be made significantly faster.
|
---|
21 | //
|
---|
22 | void MxRaster::reverse(uint start, uint end)
|
---|
23 | {
|
---|
24 | if(end >= length()) end = length() - channels();
|
---|
25 |
|
---|
26 | uint i=start;
|
---|
27 | uint j=end;
|
---|
28 | unsigned char t;
|
---|
29 |
|
---|
30 | while(i<j)
|
---|
31 | {
|
---|
32 | for(uint k=0; k<channels(); k++)
|
---|
33 | {
|
---|
34 | t=(*this)[i+k];
|
---|
35 | (*this)[i+k] = (*this)[j+k];
|
---|
36 | (*this)[j+k] = t;
|
---|
37 | }
|
---|
38 | i += channels();
|
---|
39 | j -= channels();
|
---|
40 | }
|
---|
41 | }
|
---|
42 |
|
---|
43 | void MxRaster::hflip()
|
---|
44 | {
|
---|
45 | uint i = 0;
|
---|
46 | uint j = channels()*(width()-1);
|
---|
47 |
|
---|
48 | while( i<length() )
|
---|
49 | {
|
---|
50 | reverse(i, i+j);
|
---|
51 | i += j + channels();
|
---|
52 | }
|
---|
53 | }
|
---|
54 |
|
---|
55 | void MxRaster::vflip()
|
---|
56 | {
|
---|
57 | reverse();
|
---|
58 | hflip();
|
---|
59 | }
|
---|
60 |
|
---|
61 | ////////////////////////////////////////////////////////////////////////
|
---|
62 | //
|
---|
63 | // PNM output
|
---|
64 | //
|
---|
65 | ostream& pnm_write_header(ostream& out, const MxRaster& r, bool is_raw)
|
---|
66 | {
|
---|
67 | return out << "P" << (is_raw?r.channels()*2:r.channels())
|
---|
68 | << " " << r.width() << " " << r.height() << " 255" << endl;
|
---|
69 | }
|
---|
70 |
|
---|
71 | ostream& pnm_write_data(ostream& out, const MxRaster& r, bool is_raw)
|
---|
72 | {
|
---|
73 | if( is_raw )
|
---|
74 | out.write((const char *)(const unsigned char *)r, r.length());
|
---|
75 | else
|
---|
76 | {
|
---|
77 | for(uint i=0; i<r.length(); i++)
|
---|
78 | {
|
---|
79 | out << (uint)(r[i]);
|
---|
80 | if( i%6 ) out << " ";
|
---|
81 | else out << endl;
|
---|
82 | }
|
---|
83 | }
|
---|
84 |
|
---|
85 | return out;
|
---|
86 | }
|
---|
87 |
|
---|
88 | ////////////////////////////////////////////////////////////////////////
|
---|
89 | //
|
---|
90 | // PNM input
|
---|
91 | //
|
---|
92 | static
|
---|
93 | istream& pnm_skip(istream& in)
|
---|
94 | {
|
---|
95 | for(;;)
|
---|
96 | {
|
---|
97 | in >> ws;
|
---|
98 | if( in.peek() == '#' )
|
---|
99 | in.ignore(65535, '\n');
|
---|
100 | else
|
---|
101 | return in;
|
---|
102 | }
|
---|
103 | }
|
---|
104 |
|
---|
105 | static
|
---|
106 | void pnm_read_ascii(istream& in, MxRaster& img)
|
---|
107 | {
|
---|
108 | unsigned char *current = img;
|
---|
109 | uint val;
|
---|
110 |
|
---|
111 | for(uint j=0; j<img.height(); j++) for(uint i=0; i<img.width(); i++)
|
---|
112 | for(uint k=0; k<img.channels(); k++)
|
---|
113 | {
|
---|
114 | pnm_skip(in) >> val;
|
---|
115 | *current++ = (unsigned char)val;
|
---|
116 | }
|
---|
117 | }
|
---|
118 |
|
---|
119 | static
|
---|
120 | void pnm_read_ascii(istream& in, MxRaster& img, float scale)
|
---|
121 | {
|
---|
122 | unsigned char *current = img;
|
---|
123 | float val;
|
---|
124 |
|
---|
125 | for(uint j=0; j<img.height(); j++) for(uint i=0; i<img.width(); i++)
|
---|
126 | for(uint k=0; k<img.channels(); k++)
|
---|
127 | {
|
---|
128 | pnm_skip(in) >> val;
|
---|
129 | *current++ = (unsigned char)(val*scale);
|
---|
130 | }
|
---|
131 | }
|
---|
132 |
|
---|
133 | static
|
---|
134 | void pnm_read_raw(istream& in, MxRaster& img)
|
---|
135 | {
|
---|
136 | char c; in.get(c); // extract 1 whitespace character
|
---|
137 |
|
---|
138 | //
|
---|
139 | // Is this guaranteed to read all the requested bytes?
|
---|
140 | //
|
---|
141 | in.read((char *)(unsigned char *)img, img.length());
|
---|
142 | }
|
---|
143 |
|
---|
144 | MxRaster *pnm_read(istream& in)
|
---|
145 | {
|
---|
146 | unsigned char P, N;
|
---|
147 |
|
---|
148 | in >> P >> N;
|
---|
149 |
|
---|
150 | if( P!='P' ) return NULL;
|
---|
151 |
|
---|
152 | uint width, height, maxval;
|
---|
153 | pnm_skip(in) >> width;
|
---|
154 | pnm_skip(in) >> height;
|
---|
155 | pnm_skip(in) >> maxval;
|
---|
156 |
|
---|
157 | bool is_raw = false;
|
---|
158 | uint channels = N - '0';
|
---|
159 | if( channels > 3 )
|
---|
160 | {
|
---|
161 | channels /= 2;
|
---|
162 | is_raw = true;
|
---|
163 | }
|
---|
164 |
|
---|
165 | if( channels > 3 ) return NULL;
|
---|
166 |
|
---|
167 | MxRaster *img = new MxRaster(width, height, channels);
|
---|
168 |
|
---|
169 | if( is_raw )
|
---|
170 | {
|
---|
171 | if( maxval>255 ) return NULL;
|
---|
172 | if( maxval < 255 )
|
---|
173 | mxmsg_signal(MXMSG_WARN, "Ignoring scaled raw PNM data.");
|
---|
174 |
|
---|
175 | pnm_read_raw(in, *img);
|
---|
176 | }
|
---|
177 | else if( maxval==255 )
|
---|
178 | pnm_read_ascii(in, *img);
|
---|
179 | else
|
---|
180 | pnm_read_ascii(in, *img, 255.0f/(float)maxval);
|
---|
181 |
|
---|
182 | return img;
|
---|
183 | }
|
---|