45claw::graphic::gif::reader::input_buffer::input_buffer(std::istream& is,
52 , m_initial_code_size(code_size)
53 , m_code_size(m_initial_code_size + 1)
54 , m_code_limit(1 << m_code_size)
56 m_input.read(
reinterpret_cast<char*
>(&m_next_data_length),
57 sizeof(m_next_data_length));
64bool claw::graphic::gif::reader::input_buffer::end_of_data()
const
66 return (m_val == (
unsigned int)(1 << m_initial_code_size))
67 || end_of_information();
73bool claw::graphic::gif::reader::input_buffer::end_of_information()
const
75 return !m_input || (m_val == (
unsigned int)(1 << m_initial_code_size) + 1)
76 || ((m_next_data_length == 0)
77 && (m_pending == m_pending_end)
78 && (m_pending_bits < m_code_size));
84unsigned int claw::graphic::gif::reader::input_buffer::symbols_count()
const
86 return (1 << m_initial_code_size) + 2;
92unsigned int claw::graphic::gif::reader::input_buffer::get_next()
94 if(m_pending == m_pending_end)
96 else if(m_pending_bits + (m_pending_end - m_pending - 1) * CHAR_BIT
102 std::size_t n(m_code_size);
103 unsigned int cur_size = 0;
104 char* buf =
reinterpret_cast<char*
>(&m_val);
106 while((n != 0) && m_input)
108 while((m_pending_bits != 0) && (n != 0) && m_input)
110 unsigned int bits = std::min((std::size_t)m_pending_bits, n);
112 if(CHAR_BIT - cur_size < bits)
113 bits = CHAR_BIT - cur_size;
115 unsigned int mask = (1 << bits) - 1;
117 *buf |= (m_buffer[m_pending] & mask) << cur_size;
119 m_pending_bits -= bits;
120 m_buffer[m_pending] >>= bits;
123 if(cur_size == CHAR_BIT)
130 if(m_pending_bits == 0)
134 if((m_pending == m_pending_end) && (n != 0))
137 if(m_pending == m_pending_end)
140 m_pending_bits = CHAR_BIT;
150void claw::graphic::gif::reader::input_buffer::reset()
153 m_code_size = m_initial_code_size + 1;
154 m_code_limit = 1 << m_code_size;
162void claw::graphic::gif::reader::input_buffer::new_code(
unsigned int code)
164 if((code == m_code_limit) && (m_code_size != 12))
167 m_code_limit = 1 << m_code_size;
174void claw::graphic::gif::reader::input_buffer::fill_buffer()
177 std::copy(m_buffer + m_pending, m_buffer + m_pending_end, m_buffer);
178 m_pending_end = m_pending_end - m_pending;
181 if(m_next_data_length != 0)
183 assert(m_pending_end + m_next_data_length <=
sizeof(m_buffer));
185 m_input.read(m_buffer + m_pending_end, m_next_data_length);
186 m_pending_end += m_next_data_length;
188 if((m_pending_bits == 0) && (m_pending != m_pending_end))
189 m_pending_bits = CHAR_BIT;
191 m_input.read(
reinterpret_cast<char*
>(&m_next_data_length),
192 sizeof(m_next_data_length));
203claw::graphic::gif::reader::output_buffer::output_buffer(
204 const palette_type& p,
const image_descriptor&
id,
205 int transparent_color_index,
image& output)
208 , m_transparent_color_index(transparent_color_index)
212 , m_interlace_pass(0)
213 , m_interlace_step(8)
220void claw::graphic::gif::reader::output_buffer::write(
unsigned int code)
222 assert(code < m_palette.size());
223 assert(m_x < m_id.width);
224 assert(m_y < m_id.height);
226 m_output[m_y + m_id.top][m_x + m_id.left] = m_palette[code];
228 if(m_transparent_color_index != -1)
229 if(code == (
unsigned int)m_transparent_color_index)
230 m_output[m_y + m_id.top][m_x + m_id.left].components.alpha = 0;
234 if(m_x == m_id.width)
238 if(!m_id.is_interlaced())
242 m_y += m_interlace_step;
244 while((m_y >= m_id.height) && (m_interlace_pass != 3))
247 switch(m_interlace_pass)
251 m_interlace_step = 8;
255 m_interlace_step = 4;
259 m_interlace_step = 2;
338 if(!m_frame.empty() && (m_image != NULL))
339 *m_image = *m_frame.front();
345void claw::graphic::gif::reader::clear()
347 std::for_each(m_frame.begin(), m_frame.end(),
356void claw::graphic::gif::reader::inside_load(std::istream& f)
358 std::istream::pos_type init_pos = f.tellg();
366 read_screen_descriptor(f, info);
376 f.seekg(init_pos, std::ios_base::beg);
385void claw::graphic::gif::reader::make_frames(
const reader_info& info)
387 it_index<frame_list::const_iterator> it(m_frame.begin());
390 std::size_t cumul_count(0);
391 frame cumul(info.sd.screen_width, info.sd.screen_height);
394 if(!info.disposal_method.empty())
396 if(info.disposal_method[0]
397 == graphic_control_extension::dispose_background)
398 fill_background(cumul, info);
403 for(; it != m_frame.end(); ++it)
405 if(info.disposal_method[it]
406 == graphic_control_extension::dispose_previous)
410 cumul.set_delay((*it)->get_delay());
413 if(cumul.get_delay() > 0)
415 result.push_back(
new frame(cumul));
419 switch(info.disposal_method[it])
421 case graphic_control_extension::dispose_background:
422 fill_background(cumul, info);
424 case graphic_control_extension::dispose_previous:
434 result.push_back(
new frame(cumul));
445void claw::graphic::gif::reader::fill_background(
image& img,
446 const reader_info& info)
const
450 if(info.sd.has_global_color_table() && (info.palette != NULL))
451 if(info.sd.background_color < info.palette->size())
452 clr = (*info.palette)[info.sd.background_color];
454 std::fill(img.begin(), img.end(), clr);
461void claw::graphic::gif::reader::check_if_gif(std::istream& f)
const
466 f.read(
reinterpret_cast<char*
>(&h),
sizeof(header));
470 if(f.rdstate() == std::ios_base::goodbit)
471 if((h.signature[0] ==
'G') && (h.signature[1] ==
'I')
472 && (h.signature[2] ==
'F') && (h.version[0] ==
'8')
473 && ((h.version[1] ==
'7') || (h.version[1] ==
'9'))
474 && (h.version[2] ==
'a'))
478 throw claw::bad_format(
"Not a GIF file.");
486void claw::graphic::gif::reader::read_screen_descriptor(std::istream& f,
489 f.read(
reinterpret_cast<char*
>(&info.sd),
sizeof(screen_descriptor));
491 if(info.sd.has_global_color_table())
493 info.palette =
new palette_type(info.sd.color_palette_size());
494 read_palette(f, *info.palette);
503void claw::graphic::gif::reader::read_palette(std::istream& f,
504 palette_type& p)
const
508 for(std::size_t i = 0; i != p.size(); ++i)
510 f.read(
reinterpret_cast<char*
>(&red),
sizeof(
u_int_8));
511 f.read(
reinterpret_cast<char*
>(&green),
sizeof(
u_int_8));
512 f.read(
reinterpret_cast<char*
>(&blue),
sizeof(
u_int_8));
514 p[i].components.red = red;
515 p[i].components.green = green;
516 p[i].components.blue = blue;
525void claw::graphic::gif::reader::read_data(std::istream& f, reader_info& info)
532 f.read(
reinterpret_cast<char*
>(&code),
sizeof(code));
537 case extension::block_id:
538 f.read(
reinterpret_cast<char*
>(&code),
sizeof(code));
540 if(code == graphic_control_extension::block_label)
541 read_frame_with_gce(f, info);
546 case image_descriptor::block_id:
549 case trailer::block_id:
552 throw claw::bad_format(
"gif::reader: invalid code");
555 while(f && (code != trailer::block_id));
563void claw::graphic::gif::reader::read_frame(std::istream& f, reader_info& info)
565 frame* new_frame(NULL);
569 new_frame =
new frame;
570 read_frame_data(f, info, *new_frame);
572 info.disposal_method.push_back(graphic_control_extension::dispose_none);
573 m_frame.push_back(new_frame);
587void claw::graphic::gif::reader::read_frame_with_gce(std::istream& f,
590 graphic_control_extension gce;
593 f.read(
reinterpret_cast<char*
>(&gce),
sizeof(gce));
594 f.read(
reinterpret_cast<char*
>(&code),
sizeof(code));
596 while((code == extension::block_id) && f)
598 f.read(
reinterpret_cast<char*
>(&code),
sizeof(code));
600 if(code == graphic_control_extension::block_label)
601 f.read(
reinterpret_cast<char*
>(&gce),
sizeof(gce));
606 f.read(
reinterpret_cast<char*
>(&code),
sizeof(code));
609 if(code == image_descriptor::block_id)
614 info.disposal_method.push_back(gce.get_disposal_method());
616 if(gce.has_transparent_color())
617 info.transparent_color_index = gce.transparent_color;
619 info.transparent_color_index = -1;
621 read_frame_data(f, info, *new_frame);
622 m_frame.push_back(new_frame);
631void claw::graphic::gif::reader::skip_extension(std::istream& f)
const
635 f.read(
reinterpret_cast<char*
>(&block_size),
sizeof(block_size));
637 while(f && (block_size != 0))
639 f.seekg(block_size, std::ios_base::cur);
640 f.read(
reinterpret_cast<char*
>(&block_size),
sizeof(block_size));
652void claw::graphic::gif::reader::read_frame_data(std::istream& f,
653 const reader_info& info,
654 frame& the_frame)
const
658 f.read(
reinterpret_cast<char*
>(&
id),
sizeof(
id));
660 the_frame.set_size(info.sd.screen_width, info.sd.screen_height);
664 palette_type* palette(info.palette);
666 if(
id.has_color_table())
668 palette =
new palette_type(
id.color_palette_size());
669 read_palette(f, *palette);
672 decode_data(f, *palette,
id, info.transparent_color_index, the_frame);
674 if(
id.has_color_table())
688void claw::graphic::gif::reader::decode_data(std::istream& f,
689 const palette_type& palette,
690 const image_descriptor&
id,
691 int transparent_color_index,
692 frame& the_frame)
const
696 f.read(
reinterpret_cast<char*
>(&code_size),
sizeof(code_size));
697 input_buffer input(f, code_size);
698 output_buffer output(palette,
id, transparent_color_index, the_frame);
702 gif_lzw_decoder decoder;
704 decoder.decode(input, output);
706 while(!input.end_of_information());
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Function object that deletes a pointer.
One frame in the animation.
void set_delay(unsigned int d)
Set the time duration of this frame.
reader(image &img)
Constructor.
void load(std::istream &f)
Load the image data from a stream.
image()
Constructor. Creates an image without datas.
A simple class to use as exception with string message.
Some function object classes.
Image class for gif files.
void swap(claw::graphic::gif &a, claw::graphic::gif &b)
Swap the content of two gifs.
rgba_pixel transparent_pixel
A transparent color.
A class to manage an index and an iterator easily.
unsigned_integer_of_size< 8 >::type u_int_8
An unsigned integer on 8 bits.