CLAW Library (a C++ Library Absolutely Wonderful) 1.5.5
gif.hpp
Go to the documentation of this file.
00001 /*
00002   CLAW - a C++ Library Absolutely Wonderful
00003 
00004   CLAW is a free library without any particular aim but being useful to 
00005   anyone.
00006 
00007   Copyright (C) 2005-2010 Julien Jorge
00008 
00009   This library is free software; you can redistribute it and/or
00010   modify it under the terms of the GNU Lesser General Public
00011   License as published by the Free Software Foundation; either
00012   version 2.1 of the License, or (at your option) any later version.
00013 
00014   This library is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017   Lesser General Public License for more details.
00018 
00019   You should have received a copy of the GNU Lesser General Public
00020   License along with this library; if not, write to the Free Software
00021   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023   contact: julien_jorge@yahoo.fr
00024 */
00030 #ifndef __CLAW_GIF_HPP__
00031 #define __CLAW_GIF_HPP__
00032 
00033 #include <claw/color_palette.hpp>
00034 #include <claw/functional.hpp>
00035 #include <claw/image.hpp>
00036 #include <claw/iterator.hpp>
00037 #include <claw/lzw_decoder.hpp>
00038 #include <claw/types.hpp>
00039 
00040 #include <list>
00041 
00042 namespace claw
00043 {
00044   namespace graphic
00045   {
00050     class gif:
00051       public image
00052     {
00053     public:
00055       class frame:
00056         public image
00057       {
00058       public:
00060         typedef image super;
00061 
00062       public:
00063         frame();
00064         frame( std::size_t w, std::size_t h );
00065 
00066         void set_delay(unsigned int d);
00067         unsigned int get_delay() const;
00068 
00069       private:
00072         unsigned int m_delay;
00073 
00074       }; // class frame
00075 
00076     private:
00078       typedef std::list<frame*> frame_list;
00079 
00081       typedef image super;
00082 
00083     public:
00085       typedef wrapped_iterator
00086       < frame,
00087         frame_list::iterator,
00088         claw::dereference<frame> >::iterator_type frame_iterator;
00089 
00091       typedef wrapped_iterator
00092       < const frame,
00093         frame_list::const_iterator,
00094         claw::const_dereference<frame> >::iterator_type const_frame_iterator;
00095 
00096     private:
00097 #pragma pack(push, 1)
00098 
00100       struct header
00101       {
00103         u_int_8 signature[3];
00104 
00106         u_int_8 version[3];
00107 
00108       }; // struct header
00109 
00111       struct screen_descriptor
00112       {
00113       public:
00114         bool has_global_color_table() const;
00115         unsigned int color_palette_size() const;
00116 
00117       public:
00119         u_int_16 screen_width;
00120 
00122         u_int_16 screen_height;
00123 
00125         u_int_8 packed;
00126 
00128         u_int_8 background_color;
00129 
00131         u_int_8 aspect_ratio;
00132 
00133       }; // struct screen_descriptor
00134 
00136       struct image_descriptor
00137       {
00138       public:
00140         static const u_int_8 block_id = 0x2C;
00141 
00142       public:
00143         bool has_color_table() const;
00144         bool is_interlaced() const;
00145         unsigned int color_palette_size() const;
00146 
00147       public:
00149         u_int_16 left;
00150 
00152         u_int_16 top;
00153 
00155         u_int_16 width;
00156 
00158         u_int_16 height;
00159 
00161         u_int_8 packed;
00162 
00163       }; // struct image_descriptor
00164 
00166       struct extension
00167       {
00169         static const u_int_8 block_id = 0x21;
00170 
00171         // no field
00172       }; // struct extension
00173 
00175       struct trailer
00176       {
00178         static const u_int_8 block_id = 0x3B;
00179 
00180         // no field
00181       }; // trailer
00182 
00184       struct graphic_control_extension
00185       {
00186       public:
00188         static const u_int_8 block_label = 0xF9;
00189 
00192         enum disposal_method
00193         {
00196           dispose_none,
00197 
00199           dispose_do_not_dispose,
00200 
00203           dispose_background,
00204 
00208           dispose_previous
00209 
00210         }; // enum disposal_method
00211 
00212       public:
00213         disposal_method get_disposal_method() const;
00214         bool has_transparent_color() const;
00215 
00216       public:
00218         u_int_8 block_size;
00219 
00221         u_int_8 packed;
00222 
00224         u_int_16 delay;
00225 
00227         u_int_8 transparent_color;
00228 
00230         u_int_8 terminator;
00231 
00232       }; // struct graphic_control_extension
00233 
00235       struct comment_extension
00236       {
00237       public:
00239         static const u_int_8 block_label = 0xFE;
00240 
00241       public:
00242         // this block is ignored.
00243 
00244       }; // struct comment_extension
00245 
00247       struct plain_text_extension
00248       {
00249       public:
00251         static const u_int_8 block_label = 0x01;
00252 
00253       public:
00254         // this block is ignored.
00255 
00256       }; // struct plain_text_extension
00257 
00259       struct application_extension
00260       {
00261       public:
00263         static const u_int_8 block_label = 0xFF;
00264 
00265       public:
00266         // this block is ignored.
00267 
00268       }; // struct application_extension
00269 #pragma pack(pop)
00270 
00271     public:
00272       /*----------------------------------------------------------------------*/
00279       class reader
00280       {
00281       private:
00283         typedef color_palette<rgb_pixel> palette_type;
00284 
00286         struct reader_info
00287         {
00289           screen_descriptor sd;
00290 
00292           palette_type* palette;
00293 
00295           int transparent_color_index;
00296 
00298           std::vector<graphic_control_extension::disposal_method>
00299           disposal_method;
00300 
00301         }; // struct reader_info
00302 
00304         class input_buffer
00305         {
00306         public:
00307           input_buffer( std::istream& is, u_int_8 code_size );
00308 
00309           bool end_of_data() const;
00310           bool end_of_information() const;
00311           unsigned int symbols_count() const;
00312           unsigned int get_next();
00313 
00314           void reset();
00315           void new_code( unsigned int code );
00316 
00317         private:
00318           void fill_buffer();
00319 
00320         private:
00322           unsigned int m_val;
00323 
00325           std::istream& m_input;
00326 
00333           char m_buffer[257];
00334 
00336           std::size_t m_pending;
00337 
00339           unsigned char m_pending_bits;
00340 
00342           std::size_t m_pending_end;
00343 
00345           u_int_8 m_next_data_length;
00346 
00348           const unsigned int m_initial_code_size;
00349 
00351           unsigned int m_code_size;
00352 
00354           unsigned int m_code_limit;
00355 
00356         }; // class input_buffer
00357 
00359         class output_buffer
00360         {
00361         public:
00362           output_buffer
00363           ( const palette_type& p, const image_descriptor& id,
00364             int transparent_color_index, image& output );
00365 
00366           void write( unsigned int code );
00367 
00368         private:
00370           const palette_type& m_palette;
00371 
00373           const image_descriptor& m_id;
00374 
00376           const int m_transparent_color_index;
00377 
00379           image& m_output;
00380 
00382           std::size_t m_x;
00383 
00385           std::size_t m_y;
00386 
00388           int m_interlace_pass;
00389 
00391           int m_interlace_step;
00392 
00393         }; // class output_buffer
00394 
00396         typedef claw::lzw_decoder<input_buffer, output_buffer> gif_lzw_decoder;
00397 
00398       public:
00399         reader( image& img );
00400         reader( image& img, std::istream& f );
00401         reader( frame_list& frames, std::istream& f );
00402         reader( image& img, frame_list& frames, std::istream& f );
00403         ~reader();
00404 
00405         void load( std::istream& f );
00406 
00407       private:
00408         void clear();
00409         void inside_load( std::istream& f );
00410         void make_frames( const reader_info& info );
00411         void fill_background( image& img, const reader_info& info ) const;
00412 
00413         void check_if_gif( std::istream& f ) const;
00414         void read_screen_descriptor( std::istream& f, reader_info& info );
00415 
00416         void read_palette( std::istream& f, palette_type& p ) const;
00417         void read_data( std::istream& f, reader_info& info );
00418         void read_frame( std::istream& f, reader_info& info );
00419         void read_frame_with_gce( std::istream& f, reader_info& info );
00420 
00421         void skip_extension( std::istream& f ) const;
00422         void read_frame_data
00423         ( std::istream& f, const reader_info& info, frame& the_frame ) const;
00424 
00425         void decode_data
00426         ( std::istream& f, const palette_type& palette,
00427           const image_descriptor& id, int transparent_color_index,
00428           frame& the_frame ) const;
00429 
00430       private:
00432         image* m_image;
00433 
00435         frame_list m_frame;
00436 
00437       }; // class reader
00438 
00439     public:
00440       gif();
00441       gif( const gif& that );
00442       gif( std::istream& f );
00443       ~gif();
00444 
00445       gif& operator=( const gif& that );
00446       void swap( gif& that );
00447 
00448       frame_iterator frame_begin();
00449       frame_iterator frame_end();
00450       const_frame_iterator frame_begin() const;
00451       const_frame_iterator frame_end() const;
00452 
00453     private:
00455       frame_list m_frame;
00456 
00457     }; // class gif
00458   } // namespace graphic
00459 } // namespace claw
00460 
00461 namespace std
00462 {
00463   void swap( claw::graphic::gif& a, claw::graphic::gif& b );
00464 } // namespace std
00465 
00466 #endif // __CLAW_GIF_HPP__