1 /************************************************************************/
2 /*                                                                      */
3 /*               Copyright 2002 by Ullrich Koethe                       */
4 /*                                                                      */
5 /*    This file is part of the VIGRA computer vision library.           */
6 /*    The VIGRA Website is                                              */
7 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
8 /*    Please direct questions, bug reports, and contributions to        */
9 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
10 /*        vigra@informatik.uni-hamburg.de                               */
11 /*                                                                      */
12 /*    Permission is hereby granted, free of charge, to any person       */
13 /*    obtaining a copy of this software and associated documentation    */
14 /*    files (the "Software"), to deal in the Software without           */
15 /*    restriction, including without limitation the rights to use,      */
16 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
17 /*    sell copies of the Software, and to permit persons to whom the    */
18 /*    Software is furnished to do so, subject to the following          */
19 /*    conditions:                                                       */
20 /*                                                                      */
21 /*    The above copyright notice and this permission notice shall be    */
22 /*    included in all copies or substantial portions of the             */
23 /*    Software.                                                         */
24 /*                                                                      */
25 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
26 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
27 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
28 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
29 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
30 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
31 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
32 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
33 /*                                                                      */
34 /************************************************************************/
35 
36 #include <fstream>
37 #include <stdexcept>
38 #include <vector>
39 #include <algorithm>
40 #include "vigra/config.hxx"
41 #include "vigra/sized_int.hxx"
42 #include "error.hxx"
43 #include "byteorder.hxx"
44 #include "void_vector.hxx"
45 #include "gif.hxx"
46 
47 #define BitSet(byte,bit)  (((byte) & (bit)) == (bit))
48 
49 namespace vigra {
50 
51 namespace {
52 
read_data_block(std::ifstream & stream,void_vector<UInt8> & data)53     int read_data_block(std::ifstream & stream, void_vector<UInt8> & data)
54     {
55         int count;
56 
57         count = stream.get();
58         if(!stream.good())
59             return -1;
60         if(count == 0)
61             return 0;
62         data.resize(count);
63         stream.read( reinterpret_cast< char * >(data.begin()), count);
64         if(!stream.good())
65             return -1;
66         return count;
67     }
68 
69     struct ColorCluster
70     {
71         UInt8 cmin[3], cmax[3];
72         std::vector<UInt8 *> entries;
73         mutable int largest_dim, largest_diff;
74 
75         typedef UInt8 rgb[3];
76 
77         struct ColorSorter
78         {
79             int dim;
80 
ColorSortervigra::__anonce5766b20111::ColorCluster::ColorSorter81             ColorSorter(int d)
82             : dim(d)
83             {}
84 
operator ()vigra::__anonce5766b20111::ColorCluster::ColorSorter85             bool operator()(UInt8 * l, UInt8 * r) const
86             {
87                 return l[dim] < r[dim];
88             }
89         };
90 
ColorClustervigra::__anonce5766b20111::ColorCluster91         ColorCluster()
92         : largest_dim(-1)
93         {
94             reset_minmax();
95         }
96 
addvigra::__anonce5766b20111::ColorCluster97         void add(UInt8 * entry)
98         {
99             entries.push_back(entry);
100 
101             update_minmax(entry);
102         }
103 
reset_minmaxvigra::__anonce5766b20111::ColorCluster104         void reset_minmax()
105         {
106             for(int i=0; i<3; ++i)
107             {
108                 cmin[i] = 255;
109                 cmax[i] = 0;
110             }
111 
112             largest_dim = -1;
113         }
114 
update_minmaxvigra::__anonce5766b20111::ColorCluster115         void update_minmax(UInt8 * entry)
116         {
117             for(int i=0; i<3; ++i)
118             {
119                 if(entry[i] < cmin[i])
120                     cmin[i] = entry[i];
121                 if(cmax[i] < entry[i])
122                     cmax[i] = entry[i];
123             }
124 
125             largest_dim = -1;
126         }
127 
update_largestvigra::__anonce5766b20111::ColorCluster128         void update_largest() const
129         {
130             if(largest_dim >= 0)
131                 return;
132             largest_diff = cmax[0] - cmin[0];
133             largest_dim = 0;
134 
135             for(int i=1; i<3; ++i)
136             {
137                 if(largest_diff < cmax[i] - cmin[i])
138                 {
139                     largest_dim = i;
140                     largest_diff = cmax[i] - cmin[i];
141                 }
142             }
143         }
144 
operator <vigra::__anonce5766b20111::ColorCluster145         bool operator<(ColorCluster const & o) const
146         {
147             update_largest();
148             o.update_largest();
149             return largest_diff < o.largest_diff;
150         }
151 
splitvigra::__anonce5766b20111::ColorCluster152         void split(ColorCluster & o)
153         {
154             update_largest();
155             std::sort(entries.begin(), entries.end(), ColorSorter(largest_dim));
156 
157             std::vector<UInt8 *> old_list;
158             old_list.swap(entries);
159             reset_minmax();
160 
161             UInt32 i = 0;
162             for(; i<old_list.size()/2; ++i)
163             {
164                 add(old_list[i]);
165             }
166             for(; i<old_list.size(); ++i)
167             {
168                 o.add(old_list[i]);
169             }
170         }
171 
averagevigra::__anonce5766b20111::ColorCluster172         void average(UInt8 * color) const
173         {
174             UIntBiggest r = 0, g = 0, b = 0;
175 
176             for(size_t i=0; i<entries.size(); ++i)
177             {
178                 r += entries[i][0];
179                 g += entries[i][1];
180                 b += entries[i][2];
181             }
182 
183             color[0] = (UInt8)(r / entries.size());
184             color[1] = (UInt8)(g / entries.size());
185             color[2] = (UInt8)(b / entries.size());
186         }
187 
sizevigra::__anonce5766b20111::ColorCluster188         size_t size() const
189         {
190             return entries.size();
191         }
192     };
193 
194 
find_color_clusters(void_vector<UInt8> & data,std::vector<ColorCluster> & clusters,void_vector<UInt8> & colors)195     void find_color_clusters(void_vector<UInt8> & data,
196             std::vector<ColorCluster> & clusters, void_vector<UInt8> & colors)
197     {
198         size_t count = clusters.size();
199         size_t size = data.size() / 3;
200         size_t i, current;
201         for(i=0; i<size; ++i)
202         {
203             clusters[0].add(data.begin()+3*i);
204         }
205 
206         for(current = 1; current < count; ++current)
207         {
208             size_t largest_index = 0;
209             for(i=1; i<current; ++i)
210             {
211                 if(clusters[largest_index] < clusters[i])
212                 {
213                     largest_index = i;
214                 }
215             }
216             if(clusters[largest_index].size() == 1)
217                 break;
218             clusters[largest_index].split(clusters[current]);
219         }
220 
221         for(i=0; i<count; ++i)
222         {
223             if(clusters[i].size() == 0)
224             {
225                 colors[3*i] = colors[3*i+1] = colors[3*i+2] = 0;
226             }
227             else
228             {
229                 clusters[i].average(colors.begin() + 3*i);
230             }
231         }
232     }
233 
find_color_indices(void_vector<UInt8> & data,std::vector<ColorCluster> & clusters,void_vector<UInt8> & indices)234     void find_color_indices(void_vector<UInt8> & data,
235            std::vector<ColorCluster> & clusters, void_vector<UInt8> & indices)
236     {
237         size_t count = clusters.size();
238         UInt8 * base = data.begin();
239 
240         size_t i;
241         for(i=0; i<count; ++i)
242         {
243             for(size_t j=0; j<clusters[i].size(); ++j)
244             {
245                 size_t offset = (clusters[i].entries[j] - base) / 3;
246                 indices[offset] = static_cast<UInt8>(i);
247             }
248         }
249     }
250 } // anonymous namespace
251 
getCodecDesc() const252     CodecDesc GIFCodecFactory::getCodecDesc() const
253     {
254         CodecDesc desc;
255 
256         // init file type
257         desc.fileType = "GIF";
258 
259         // init pixel types
260         desc.pixelTypes.resize(1);
261         desc.pixelTypes[0] = "UINT8";
262 
263         // init compression types
264         desc.compressionTypes.resize(0);
265 
266         // init magic strings
267         desc.magicStrings.resize(1);
268         desc.magicStrings[0].resize(4);
269         desc.magicStrings[0][0] = 'G';
270         desc.magicStrings[0][1] = 'I';
271         desc.magicStrings[0][2] = 'F';
272         desc.magicStrings[0][3] = '8';
273 
274         // init file extensions
275         desc.fileExtensions.resize(1);
276         desc.fileExtensions[0] = "gif";
277 
278         desc.bandNumbers.resize(2);
279         desc.bandNumbers[0] = 1;
280         desc.bandNumbers[1] = 3;
281 
282         return desc;
283     }
284 
getDecoder() const285     VIGRA_UNIQUE_PTR<Decoder> GIFCodecFactory::getDecoder() const
286     {
287         return VIGRA_UNIQUE_PTR<Decoder>( new GIFDecoder() );
288     }
289 
getEncoder() const290     VIGRA_UNIQUE_PTR<Encoder> GIFCodecFactory::getEncoder() const
291     {
292         return VIGRA_UNIQUE_PTR<Encoder>( new GIFEncoder() );
293     }
294 
295     struct GIFHeader
296     {
297         // attributes
298 
299         UInt16 width, height, maplength;
300         UInt8  bits_per_pixel;
301         bool  global_colormap, interlace;
302 
303         // methods
304 
305         void global_from_stream( std::ifstream & stream, const byteorder & bo );
306         bool local_from_stream( std::ifstream & stream, const byteorder & bo );
307         void global_to_stream( std::ofstream & stream, const byteorder & bo );
308         void local_to_stream( std::ofstream & stream, const byteorder & bo );
309     };
310 
global_from_stream(std::ifstream & stream,const byteorder & bo)311     void GIFHeader::global_from_stream( std::ifstream & stream, const byteorder & bo )
312     {
313         UInt8 flag, c, background;
314         read_field( stream, bo, width );
315         read_field( stream, bo, height );
316         read_field( stream, bo, flag );
317         read_field( stream, bo, background );
318         read_field( stream, bo, c );
319         global_colormap = BitSet(flag, 0x80);
320         if(global_colormap)
321         {
322             bits_per_pixel = (flag & 0x07)+1;
323             maplength = 3*( 1 << bits_per_pixel);
324         }
325     }
326 
global_to_stream(std::ofstream & stream,const byteorder & bo)327     void GIFHeader::global_to_stream( std::ofstream & stream, const byteorder & bo )
328     {
329         write_field( stream, bo, width );
330         write_field( stream, bo, height );
331         write_field( stream, bo, (UInt8)0xf7 );
332         write_field( stream, bo, (UInt8)0 );  // background
333         write_field( stream, bo, (UInt8)0 );  // must be zero
334     }
335 
local_from_stream(std::ifstream & stream,const byteorder & bo)336     bool GIFHeader::local_from_stream( std::ifstream & stream, const byteorder & bo )
337     {
338         UInt8 c, flag;
339         for ( ; ; )
340         {
341             c = stream.get();
342             if(!stream.good() || c == ';')
343                 return false;
344             if(c == '!')
345             {
346                 void_vector<UInt8> extensions;
347 
348                 // read and ignore extension data
349                 read_field( stream, bo, c );
350                 while (read_data_block(stream, extensions) > 0) /* empty */;
351             }
352             if(c == ',')
353                 break;
354         }
355 
356         UInt16 x,y;
357 
358         read_field( stream, bo, x );
359         read_field( stream, bo, y );
360         read_field( stream, bo, width );
361         read_field( stream, bo, height );
362         read_field( stream, bo, flag );
363         interlace=BitSet(flag,0x40);
364         if(BitSet(flag,0x80))
365         {
366             global_colormap = false;
367             bits_per_pixel = (flag & 0x07)+1;
368             maplength = 3*( 1 << bits_per_pixel);
369         }
370         return true;
371     }
372 
local_to_stream(std::ofstream & stream,const byteorder & bo)373     void GIFHeader::local_to_stream( std::ofstream & stream, const byteorder & bo )
374     {
375         write_field( stream, bo, ',' );
376         write_field( stream, bo, (UInt16)0 ); // x
377         write_field( stream, bo, (UInt16)0 ); // y
378         write_field( stream, bo, width );
379         write_field( stream, bo, height );
380         write_field( stream, bo, (UInt8)0); // use global colormap, no interlace
381    }
382 
383     struct GIFDecoderImpl
384     {
385         // attributes
386 
387         GIFHeader header;
388         std::ifstream stream;
389         byteorder bo;
390         void_vector< UInt8 > maps, bands;
391         UInt32 components;
392         UInt8 * scanline;
393 
394         // methods
395 
396         void decodeGIF();
397 
398         // ctor
399 
400         GIFDecoderImpl( const std::string & filename );
401     };
402 
GIFDecoderImpl(const std::string & filename)403     GIFDecoderImpl::GIFDecoderImpl( const std::string & filename )
404 #ifdef VIGRA_NEED_BIN_STREAMS
405         : stream( filename.c_str(), std::ios::binary ),
406 #else
407         : stream( filename.c_str() ),
408 #endif
409           bo("little endian"),
410           maps(0),
411           bands(0),
412           scanline(0)
413     {
414         if(!stream.good())
415         {
416             std::string msg("Unable to open file '");
417             msg += filename;
418             msg += "'.";
419             vigra_precondition(0, msg.c_str());
420         }
421 
422         // read the magic number
423         char buf[6];
424         read_array( stream, bo, buf, 6 );
425         std::string magic(6, (std::string::value_type)0);
426 
427         std::copy(buf, buf + 6, magic.begin());
428         vigra_precondition( magic == "GIF87a" || magic == "GIF89a",
429                             "the stored magic number is invalid" );
430 
431         // read the header
432         header.global_from_stream( stream, bo );
433 
434         // read the global color map, if there is one
435         if (header.global_colormap)
436         {
437             // read the maps
438             maps.resize(header.maplength);
439             read_array( stream, bo, maps.data(), header.maplength );
440         }
441 
442         if(!header.local_from_stream( stream, bo ))
443         {
444             std::string msg("Unable to read file '");
445             msg += filename;
446             msg += "'.";
447             vigra_precondition(0, msg.c_str());
448         }
449 
450         // read the local color map, if there is one
451         if (!header.global_colormap)
452         {
453             // read the maps
454             maps.resize(header.maplength);
455             read_array( stream, bo, maps.data(), header.maplength );
456         }
457 
458         // check if image is Gray or RGB
459         int i=0;
460         components = 1;
461         for(; i < header.maplength/3; ++i)
462         {
463             if(maps[3*i] != maps[3*i+1] || maps[3*i] != maps[3*i+2])
464             {
465                 components = 3;
466                 break;
467             }
468         }
469     }
470 
decodeGIF()471     void GIFDecoderImpl::decodeGIF()
472     {
473         #define MaxStackSize  4096
474         #define NullCode  (-1)
475 
476         int
477             available,
478             clear,
479             code_mask,
480             code_size,
481             end_of_information,
482             in_code,
483             old_code;
484 
485         int
486             bits,
487             code,
488             count;
489 
490         unsigned long
491         datum;
492 
493         void_vector<Int16> prefix(MaxStackSize);
494         void_vector<UInt8> suffix(MaxStackSize);
495         void_vector<UInt8> pixel_stack(MaxStackSize+1);
496         void_vector<UInt8> packet(256);
497         void_vector<UInt16> indices(header.width*header.height);
498 
499         UInt8 *c;
500         UInt16 *p = indices.begin();
501 
502         UInt8
503         data_size,
504         first,
505         *top_stack;
506 
507         /*
508         Initialize GIF data stream decoder.
509         */
510         data_size = stream.get();
511         clear=1 << data_size;
512         end_of_information=clear+1;
513         available=clear+2;
514         old_code=NullCode;
515         code_size=data_size+1;
516         code_mask=(1 << code_size)-1;
517         for (code=0; code < clear; code++)
518         {
519             prefix[code]=0;
520             suffix[code]=code;
521         }
522         /*
523         Decode GIF pixel stream.
524         */
525         datum=0;
526         bits=0;
527         c=0;
528         count=0;
529         first=0;
530         top_stack=pixel_stack.begin();
531         while (p < indices.end())
532         {
533             if (top_stack == pixel_stack.begin())
534             {
535                 if (bits < code_size)
536                 {
537                     /*
538                       Load bytes until there is enough bits for a code.
539                     */
540                     if (count == 0)
541                     {
542                         /*
543                           Read a new data block.
544                         */
545                         count=read_data_block(stream, packet);
546                         if (count <= 0)
547                           break;
548                         c=packet.begin();
549                     }
550                     datum+=(*c) << bits;
551                     bits+=8;
552                     c++;
553                     count--;
554                     continue;
555                 }
556                 /*
557                   Get the next code.
558                 */
559                 code=datum & code_mask;
560                 datum>>=code_size;
561                 bits-=code_size;
562                 /*
563                   Interpret the code
564                 */
565                 if ((code > available) || (code == end_of_information))
566                   break;
567                 if (code == clear)
568                 {
569                     /*
570                       Reset decoder.
571                     */
572                     code_size=data_size+1;
573                     code_mask=(1 << code_size)-1;
574                     available=clear+2;
575                     old_code=NullCode;
576                     continue;
577                 }
578                 if (old_code == NullCode)
579                 {
580                     *top_stack++=suffix[code];
581                     old_code=code;
582                     first=code;
583                     continue;
584                 }
585                 in_code=code;
586                 if (code == available)
587                 {
588                     *top_stack++=first;
589                     code=old_code;
590                 }
591                 while (code > clear)
592                 {
593                   *top_stack++=suffix[code];
594                   code=prefix[code];
595                 }
596                 first=suffix[code];
597                 /*
598                   Add a new string to the string table,
599                 */
600                 if (available >= MaxStackSize)
601                   break;
602                 *top_stack++=first;
603                 prefix[available]=old_code;
604                 suffix[available]=first;
605                 available++;
606                 if (((available & code_mask) == 0) && (available < MaxStackSize))
607                 {
608                     code_size++;
609                     code_mask+=available;
610                 }
611                 old_code=in_code;
612             }
613             /*
614               Pop a pixel off the pixel stack.
615             */
616             top_stack--;
617             *p++ =(UInt16) *top_stack;
618         }
619 
620         // decode intelaced image
621         if (header.interlace)
622         {
623             void_vector<UInt16> non_interlaced(header.width*header.height);
624 
625             int pass, x, y;
626 
627             UInt16 *q;
628 
629             static int
630               interlace_rate[4] = { 8, 8, 4, 2 },
631               interlace_start[4] = { 0, 4, 2, 1 };
632 
633             p=indices.begin();
634             for (pass=0; pass < 4; pass++)
635             {
636               y=interlace_start[pass];
637               while (y < header.height)
638               {
639                 q=non_interlaced.begin()+(y*header.width);
640                 for (x=0; x < header.width; x++)
641                 {
642                   *q=(*p);
643                   p++;
644                   q++;
645                 }
646                 y+=interlace_rate[pass];
647               }
648             }
649 
650             swap_void_vector( indices, non_interlaced );
651             header.interlace = false;
652         }
653 
654         // apply colormap
655         bands.resize(header.width*header.height*components);
656         for(int i=0; i<header.width*header.height; ++i)
657         {
658             if(components == 1)
659             {
660                 bands[i] = maps[3*indices[i]];
661             }
662             else
663             {
664                 bands[3*i] = maps[3*indices[i]];
665                 bands[3*i+1] = maps[3*indices[i]+1];
666                 bands[3*i+2] = maps[3*indices[i]+2];
667             }
668         }
669     }
670 
init(const std::string & filename)671     void GIFDecoder::init( const std::string & filename )
672     {
673         pimpl = new GIFDecoderImpl( filename );
674     }
675 
~GIFDecoder()676     GIFDecoder::~GIFDecoder()
677     {
678         delete pimpl;
679     }
680 
getFileType() const681     std::string GIFDecoder::getFileType() const
682     {
683         return "GIF";
684     }
685 
getWidth() const686     unsigned int GIFDecoder::getWidth() const
687     {
688         return pimpl->header.width;
689     }
690 
getHeight() const691     unsigned int GIFDecoder::getHeight() const
692     {
693         return pimpl->header.height;
694     }
695 
getNumBands() const696     unsigned int GIFDecoder::getNumBands() const
697     {
698         return pimpl->components;
699     }
700 
getPixelType() const701     std::string GIFDecoder::getPixelType() const
702     {
703         return "UINT8";
704     }
705 
getOffset() const706     unsigned int GIFDecoder::getOffset() const
707     {
708         return pimpl->components;
709     }
710 
currentScanlineOfBand(unsigned int band) const711     const void * GIFDecoder::currentScanlineOfBand( unsigned int band ) const
712     {
713         return pimpl->scanline + band;
714     }
715 
nextScanline()716     void GIFDecoder::nextScanline()
717     {
718         if (pimpl->scanline)
719             pimpl->scanline += getWidth()*getNumBands();
720         else
721         {
722             pimpl->decodeGIF();
723             pimpl->scanline = pimpl->bands.begin();
724         }
725     }
726 
close()727     void GIFDecoder::close() {}
abort()728     void GIFDecoder::abort() {}
729 
730     struct GIFEncoderImpl
731     {
732         // attributes
733 
734         GIFHeader header;
735         std::ofstream stream;
736         byteorder bo;
737         void_vector< UInt8 > bands;
738         void_vector< UInt8 > maps;
739         void_vector< UInt8 > indices;
740         UInt32 components;
741         UInt8 *scanline;
742         bool finalized;
743 
744         // methods
745 
746         void finalize();
747         void writeHeader();
748         void writeColormap();
749         void writeImageData();
750         void reduceTo256Colors();
751         void outputEncodedData(void_vector< UInt8 > &);
752 
753         // ctor
754 
755         GIFEncoderImpl( const std::string & filename );
756     };
757 
GIFEncoderImpl(const std::string & filename)758     GIFEncoderImpl::GIFEncoderImpl( const std::string & filename )
759 #ifdef VIGRA_NEED_BIN_STREAMS
760         : stream( filename.c_str(), std::ios::binary ),
761 #else
762         : stream( filename.c_str() ),
763 #endif
764           bo("little endian"),
765           bands(0),
766           maps(0),
767           indices(0),
768           scanline(0),
769           finalized(false)
770     {
771         if(!stream.good())
772         {
773             std::string msg("Unable to open file '");
774             msg += filename;
775             msg += "'.";
776             vigra_precondition(0, msg.c_str());
777         }
778         // write the magic number
779         write_array( stream, bo, "GIF87a", 6 );
780     }
781 
finalize()782     void GIFEncoderImpl::finalize()
783     {
784         // color depth
785         vigra_precondition( components == 1 || components == 3,
786                             "number of bands is not supported" );
787     }
788 
writeHeader()789     void GIFEncoderImpl::writeHeader()
790     {
791         // write the header
792         header.global_to_stream( stream, bo );
793         writeColormap();
794         header.local_to_stream( stream, bo );
795     }
796 
writeColormap()797     void GIFEncoderImpl::writeColormap()
798     {
799         write_array( stream, bo, maps.data(), header.maplength );
800     }
801 
writeImageData()802     void GIFEncoderImpl::writeImageData()
803     {
804         stream.put(header.bits_per_pixel); // code size
805         if(components == 3)
806         {
807             outputEncodedData(indices);
808         }
809         else
810         {
811             outputEncodedData(bands);
812         }
813         stream.put(0);   // end of raster stream
814         stream.put(';'); // GIF terminator
815     }
816 
reduceTo256Colors()817     void GIFEncoderImpl::reduceTo256Colors()
818     {
819         header.bits_per_pixel = 8;
820         header.maplength = 3*256;
821 
822         maps.resize(header.maplength);
823         if(components == 3)
824         {
825             std::vector<ColorCluster> clusters(256);
826             find_color_clusters(bands, clusters, maps);
827             indices.resize(header.width*header.height);
828             find_color_indices(bands, clusters, indices);
829         }
830         else
831         {
832             for(int i=0; i<256; ++i)
833             {
834                 maps[3*i] = maps[3*i+1] = maps[3*i+2] = i;
835             }
836         }
837     }
838 
outputEncodedData(void_vector<UInt8> & indices)839     void GIFEncoderImpl::outputEncodedData(void_vector<UInt8> & indices)
840     {
841         #define MaxCode(number_bits)  ((1 << (number_bits))-1)
842         #define MaxHashTable  5003
843         #define MaxGIFBits  12
844         #if defined(HasLZW)
845         #define MaxGIFTable  (1 << MaxGIFBits)
846         #else
847         #define MaxGIFTable  max_code
848         #endif
849         #define GIFOutputCode(code) \
850         { \
851           /*  \
852             Emit a code. \
853           */ \
854           if (bits > 0) \
855             datum|=((long) code << bits); \
856           else \
857             datum=(long) code; \
858           bits+=number_bits; \
859           while (bits >= 8) \
860           { \
861             /*  \
862               Add a character to current packet. \
863             */ \
864             packet[byte_count++]=(UInt8) (datum & 0xff); \
865             if (byte_count >= 254) \
866               { \
867                 stream.put(byte_count); \
868                 stream.write(reinterpret_cast< char * >(packet.begin()),byte_count); \
869                 byte_count=0; \
870               } \
871             datum>>=8; \
872             bits-=8; \
873           } \
874           if (free_code > max_code)  \
875             { \
876               number_bits++; \
877               if (number_bits == MaxGIFBits) \
878                 max_code=MaxGIFTable; \
879               else \
880                 max_code=MaxCode(number_bits); \
881             } \
882         }
883 
884         int
885           bits,
886           byte_count,
887           number_bits,
888           data_size = header.bits_per_pixel;
889         UInt32  i;
890 
891         long
892           datum;
893 
894         int k;
895 
896         UInt8 *p;
897 
898         void_vector<Int16> hash_code(MaxHashTable);
899         void_vector<Int16> hash_prefix(MaxHashTable);
900         void_vector<Int16> hash_suffix(MaxHashTable);
901 
902         Int16
903           clear_code,
904           end_of_information_code,
905           free_code,
906           index,
907           max_code,
908           waiting_code;
909 
910         void_vector<UInt8> packet(256);
911 
912         /*
913           Initialize GIF encoder.
914         */
915         number_bits=data_size+1;
916         max_code=MaxCode(number_bits);
917         clear_code=((Int16) 1 << data_size);
918         end_of_information_code=clear_code+1;
919         free_code=clear_code+2;
920         byte_count=0;
921         datum=0;
922         bits=0;
923         for (i=0; i < MaxHashTable; i++)
924           hash_code[i]=0;
925         GIFOutputCode(clear_code);
926         /*
927           Encode pixels.
928         */
929         p=indices.begin();
930         waiting_code=*p;
931         for (i=0; i < indices.size(); i++)
932         {
933           if(i > 0)
934           {
935             /*
936               Probe hash table.
937             */
938             index=*p & 0xff;
939             k=(int) ((int) index << (MaxGIFBits-8))+waiting_code;
940             if (k >= MaxHashTable)
941               k-=MaxHashTable;
942             GIFOutputCode(waiting_code);
943             if (free_code < MaxGIFTable)
944             {
945                 hash_code[k]=free_code++;
946                 hash_prefix[k]=waiting_code;
947                 hash_suffix[k]=index;
948             }
949             else
950             {
951                 /*
952                   Fill the hash table with empty entries.
953                 */
954                 for (k=0; k < MaxHashTable; k++)
955                   hash_code[k]=0;
956                 /*
957                   Reset compressor and issue a clear code.
958                 */
959                 free_code=clear_code+2;
960                 GIFOutputCode(clear_code);
961                 number_bits=data_size+1;
962                 max_code=MaxCode(number_bits);
963             }
964             waiting_code=index;
965           }
966           p++;
967         }
968         /*
969           Flush out the buffered code.
970         */
971         GIFOutputCode(waiting_code);
972         GIFOutputCode(end_of_information_code);
973         if (bits > 0)
974         {
975             /*
976               Add a character to current packet.
977             */
978             packet[byte_count++]=(UInt8) (datum & 0xff);
979             if (byte_count >= 254)
980             {
981                 stream.put(byte_count);
982                 stream.write(reinterpret_cast< char * >(packet.begin()),byte_count);
983                 byte_count=0;
984             }
985         }
986         /*
987           Flush accumulated data.
988         */
989         if (byte_count > 0)
990         {
991                 stream.put(byte_count);
992                 stream.write(reinterpret_cast< char * >(packet.begin()),byte_count);
993         }
994     }
995 
init(const std::string & filename)996     void GIFEncoder::init( const std::string & filename )
997     {
998         pimpl = new GIFEncoderImpl(filename);
999     }
1000 
~GIFEncoder()1001     GIFEncoder::~GIFEncoder()
1002     {
1003         delete pimpl;
1004     }
1005 
getFileType() const1006     std::string GIFEncoder::getFileType() const
1007     {
1008         return "GIF";
1009     }
1010 
setWidth(unsigned int width)1011     void GIFEncoder::setWidth( unsigned int width )
1012     {
1013         VIGRA_IMPEX_FINALIZED(pimpl->finalized);
1014         pimpl->header.width = width;
1015     }
1016 
setHeight(unsigned int height)1017     void GIFEncoder::setHeight( unsigned int height )
1018     {
1019         VIGRA_IMPEX_FINALIZED(pimpl->finalized);
1020         pimpl->header.height = height;
1021     }
1022 
setNumBands(unsigned int numBands)1023     void GIFEncoder::setNumBands( unsigned int numBands )
1024     {
1025         VIGRA_IMPEX_FINALIZED(pimpl->finalized);
1026         pimpl->components = numBands;
1027     }
1028 
setCompressionType(const std::string &,int)1029     void GIFEncoder::setCompressionType( const std::string & /* comp */, int /* quality */)
1030     {
1031         VIGRA_IMPEX_FINALIZED(pimpl->finalized);
1032     }
1033 
setPixelType(const std::string & pixeltype)1034     void GIFEncoder::setPixelType( const std::string & pixeltype )
1035     {
1036         VIGRA_IMPEX_FINALIZED(pimpl->finalized);
1037         vigra_precondition( pixeltype == "UINT8",
1038                             "GIFEncoder::setPixelType(): "
1039                             "GIF raster supports only the UINT8 pixeltype" );
1040     }
1041 
getOffset() const1042     unsigned int GIFEncoder::getOffset() const
1043     {
1044         return pimpl->components;
1045     }
1046 
finalizeSettings()1047     void GIFEncoder::finalizeSettings()
1048     {
1049         pimpl->finalize();
1050         pimpl->finalized = true;
1051     }
1052 
currentScanlineOfBand(unsigned int band)1053     void * GIFEncoder::currentScanlineOfBand( unsigned int band )
1054     {
1055         if (!pimpl->scanline)
1056         {
1057             pimpl->bands.resize(pimpl->header.width*pimpl->header.height*pimpl->components);
1058             pimpl->scanline = pimpl->bands.begin();
1059         }
1060          return pimpl->scanline + band;
1061     }
1062 
nextScanline()1063     void GIFEncoder::nextScanline()
1064     {
1065         pimpl->scanline += pimpl->header.width*pimpl->components;
1066     }
1067 
close()1068     void GIFEncoder::close()
1069     {
1070         pimpl->reduceTo256Colors();
1071         pimpl->writeHeader();
1072         pimpl->writeImageData();
1073     }
1074 
abort()1075     void GIFEncoder::abort() {}
1076 }
1077