claw 1.9.0
 
Loading...
Searching...
No Matches
pcx_reader.cpp
Go to the documentation of this file.
1/*
2 CLAW - a C++ Library Absolutely Wonderful
3
4 CLAW is a free library without any particular aim but being useful to
5 anyone.
6
7 Copyright (C) 2005-2011 Julien Jorge
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
23 contact: julien.jorge@stuff-o-matic.com
24*/
30#include <claw/graphic/pcx.hpp>
31
32#include <claw/exception.hpp>
33
34#include <limits>
35
42void claw::graphic::pcx::reader::converter_mono::operator()(
43 const std::vector<color_plane_type>& scanline, image& img,
44 unsigned int y) const
45{
46 CLAW_PRECOND(scanline.size() == 1);
47
48 unsigned int x = 0;
49
50 for(unsigned int code = 0; x != img.width(); ++code)
51 {
52 u_int_8 c = scanline[0][code]; // only one color plane for monochrome pcx
53
54 for(unsigned int i = 0; (i != 8) && (x != img.width());
55 ++x, ++i, c <<= 1)
56 if(c & 0x80)
57 img[y][x] = white_pixel;
58 else
59 img[y][x] = black_pixel;
60 }
61}
62
67claw::graphic::pcx::reader::converter_16::converter_16(const header& h)
68 : m_header(h)
69{}
70
77void claw::graphic::pcx::reader::converter_16::operator()(
78 const std::vector<color_plane_type>& scanline, image& img,
79 unsigned int y) const
80{
81 CLAW_PRECOND(scanline.size() == 4);
82
83 unsigned int x = 0;
84
85 for(unsigned int code = 0; x != img.width(); ++code)
86 {
87 u_int_8 c0 = scanline[0][code];
88 u_int_8 c1 = scanline[1][code];
89 u_int_8 c2 = scanline[2][code];
90 u_int_8 c3 = scanline[3][code];
91
92 for(unsigned int i = 0; (i != 8) && (x != img.width()); ++x, ++i)
93 {
94 unsigned int index = ((c3 & 0x80) >> 4) | ((c2 & 0x80) >> 5)
95 | ((c1 & 0x80) >> 6) | ((c0 & 0x80) >> 7);
96
97 img[y][x] = m_header.color_map[index];
98
99 c0 <<= 1;
100 c1 <<= 1;
101 c2 <<= 1;
102 c3 <<= 1;
103 }
104 }
105}
106
111claw::graphic::pcx::reader::converter_256::converter_256(
112 const color_palette32& palette)
113 : m_palette(palette)
114{}
115
122void claw::graphic::pcx::reader::converter_256::operator()(
123 const std::vector<color_plane_type>& scanline, image& img,
124 unsigned int y) const
125{
126 CLAW_PRECOND(scanline.size() == 1);
127
128 for(unsigned int x = 0; x != img.width(); ++x)
129 img[y][x] = m_palette[scanline[0][x]];
130}
131
138void claw::graphic::pcx::reader::converter_true_color::operator()(
139 const std::vector<color_plane_type>& scanline, image& img,
140 unsigned int y) const
141{
142 CLAW_PRECOND(scanline.size() == 3);
143
144 for(unsigned int x = 0; x != img.width(); ++x)
145 {
146 img[y][x].components.red = scanline[0][x];
147 img[y][x].components.green = scanline[1][x];
148 img[y][x].components.blue = scanline[2][x];
149 img[y][x].components.alpha
150 = std::numeric_limits<rgba_pixel_8::component_type>::max();
151 }
152}
153
159claw::graphic::pcx::reader::rle_pcx_output_buffer::rle_pcx_output_buffer(
160 color_plane_type& result)
161 : m_result(result)
162 , m_position(0)
163{}
164
170void claw::graphic::pcx::reader::rle_pcx_output_buffer::fill(unsigned int n,
171 u_int_8 pattern)
172{
173 CLAW_PRECOND(m_position + n <= m_result.size());
174
175 for(unsigned int i = 0; i != n; ++i)
176 m_result[m_position + i] = pattern;
177
178 m_position += n;
179}
180
186void claw::graphic::pcx::reader::rle_pcx_output_buffer::copy(
187 unsigned int n, rle_pcx_input_buffer& buffer)
188{
189 CLAW_ASSERT(false, "This method should not have been called");
190}
191
195bool claw::graphic::pcx::reader::rle_pcx_output_buffer::completed() const
196{
197 return m_position == m_result.size();
198}
199
205void claw::graphic::pcx::reader::rle_pcx_decoder::read_mode(
206 input_buffer_type& input, output_buffer_type& output)
207{
208 this->m_mode = this->stop;
209 bool ok = !output.completed();
210
211 if(ok && (input.remaining() < 1))
212 ok = input.read_more(1);
213
214 if(ok)
215 {
216 unsigned char key = input.get_next();
217 this->m_mode = this->compressed;
218
219 if((key & 0xC0) == 0xC0)
220 {
221 this->m_count = key & 0x3F;
222
223 if(input.remaining() < 1)
224 input.read_more(1);
225
226 this->m_pattern = input.get_next();
227 }
228 else
229 {
230 this->m_count = 1;
231 this->m_pattern = key;
232 }
233 }
234}
235
241 : m_image(img)
242{}
243
251 : m_image(img)
252{
253 load(f);
254}
255
261{
262 CLAW_PRECOND(!!f);
263 std::istream::pos_type init_pos = f.tellg();
264
265 try
266 {
267 header h;
268
269 f.read(reinterpret_cast<char*>(&h), sizeof(header));
270
271 if(f.rdstate() == std::ios_base::goodbit)
272 {
273 check_if_pcx(h);
274
275 m_image.set_size(h.window.x_max - h.window.x_min + 1,
276 h.window.y_max - h.window.y_min + 1);
277
278 bool supported_format = true;
279
280 switch(h.color_planes)
281 {
282 case 1:
283 if(h.bpp == 1)
284 load_mono(h, f);
285 else if(h.bpp == 8)
286 load_256_color_mapped(h, f);
287 else
288 supported_format = false;
289 break;
290 case 3:
291 if(h.bpp == 8)
292 load_true_color(h, f);
293 else
294 supported_format = false;
295 break;
296 case 4:
297 if(h.bpp == 1)
298 load_16_color_mapped(h, f);
299 else
300 supported_format = false;
301 break;
302 default:
303 supported_format = false;
304 }
305
306 if(supported_format == false)
307 throw claw::bad_format("pcx::reader::pcx: unsupported image type");
308 }
309 else
310 throw claw::bad_format("claw::pcx::reader::pcx: can't read header");
311 }
312 catch(...)
313 {
314 f.clear();
315 f.seekg(init_pos, std::ios_base::beg);
316 throw;
317 }
318}
319
324void claw::graphic::pcx::reader::check_if_pcx(const header& h) const
325{
326 if(h.manufacturer != 0x0A)
327 throw CLAW_EXCEPTION("Not a Pcx file.");
328}
329
335void claw::graphic::pcx::reader::load_mono(const header& h, std::istream& f)
336{
337 assert(h.color_planes == 1);
338
339 converter_mono convert;
340 decompress(h, f, convert);
341}
342
348void claw::graphic::pcx::reader::load_16_color_mapped(const header& h,
349 std::istream& f)
350{
351 assert(h.color_planes == 4);
352
353 converter_16 convert(h);
354 decompress(h, f, convert);
355}
356
362void claw::graphic::pcx::reader::load_true_color(const header& h,
363 std::istream& f)
364{
365 assert(h.color_planes == 3);
366
367 converter_true_color convert;
368 decompress(h, f, convert);
369}
370
376void claw::graphic::pcx::reader::load_256_color_mapped(const header& h,
377 std::istream& f)
378{
379 assert(h.color_planes == 1);
380
381 // 256 RGB triplets
382 const unsigned int palette_length = 256 * 3;
383
384 color_palette32 palette(256);
385 std::istream::pos_type init_pos = f.tellg();
386
387 // -1 for the check byte
388 f.seekg(-(std::istream::off_type)palette_length - 1, std::ios_base::end);
389
390 char check;
391 f.read(&check, 1);
392
393 if(check != 12)
394 throw CLAW_EXCEPTION("PCX: The color palette is missing.");
395
396 char buffer[palette_length];
397 f.read(buffer, palette_length);
398
399 for(unsigned int i = 0, j = 0; i != palette_length; i += 3, ++j)
400 {
401 palette[j].components.alpha = 255;
402 palette[j].components.red = buffer[i];
403 palette[j].components.green = buffer[i + 1];
404 palette[j].components.blue = buffer[i + 2];
405 }
406
407 f.seekg(init_pos);
408 converter_256 convert(palette);
409 decompress(h, f, convert);
410}
411
417void claw::graphic::pcx::reader::decompress_line(
418 std::istream& f, color_plane_type& scanline) const
419{
420 rle_pcx_input_buffer input(f);
421 rle_pcx_output_buffer output(scanline);
422
423 rle_pcx_decoder decoder;
424
425 decoder.decode(input, output);
426}
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition assert.hpp:94
#define CLAW_ASSERT(b, s)
Print a message on std::cerr and stop the program if a condition is not true.
Definition assert.hpp:88
Exception thrown when accessing bad formated data.
Definition exception.hpp:74
One line in the image.
Definition image.hpp:62
image()
Constructor. Creates an image without datas.
Definition image.cpp:95
void load(std::istream &f)
Load an image from a pcx file.
reader(image &img)
Constructor.
A simple class to use as exception with string message.
#define CLAW_EXCEPTION(m)
Create an exception and add the name of the current function to the message.
Definition exception.hpp:92
rgba_pixel white_pixel
The white color.
rgba_pixel black_pixel
The black color.
unsigned_integer_of_size< 8 >::type u_int_8
An unsigned integer on 8 bits.
Definition types.hpp:132
A class for pcx pictures.