unit GIFLZW; // . {$MODE OBJFPC} {$M+} interface uses classes, type_fixes, custom_decoders, bitstreams, LZW; { GIF LZW: 1. A special Clear code is defined which resets all compression/decompression parameters and tables to a start-up state. The value of this code is 2**. For example if the code size indicated was 4 (image was 4 bits/pixel) the Clear code value would be 16 (10000 binary). The Clear code can appear at any point in the image data stream and therefore requires the LZW algorithm to process succeeding codes as if a new data stream was starting. 2. An End of Information code is defined that explicitly indicates the end of the image data stream. LZW processing terminates when this code is encountered. It must be the last code output by the encoder for an image. The value of this code is +1. 3. The first available compression code value is +2. 4. The output codes are of variable length, starting at +1 bits per code, up to 12 bits per code. This defines a maximum code value of 4095 (0xFFF). Whenever the LZW code value would exceed the current code length, the code length is increased by one. The packing/unpacking of these codes must then be altered to reflect the new code length. } type TDecoder = class(LZW.TDecoder) private fClearCode : TUINT16; fEOFCode : TUINT16; published constructor Create(aSource : TStream; abOwnsSource : Boolean; aCodeSize : TByte); protected function HandleSpecialCode(aCode : TUINT16) : TSpecialHandlingVerdict; override; end; implementation uses sysutils; constructor TDecoder.Create(aSource : TStream; aBOwnsSource : Boolean; aCodeSize : TByte); begin if aCodeSize > 12 then raise EFormatError.Create('root size > 12 is not supported by GIF. The file is damaged.'); inherited Create(aSource, aBOwnsSource, aCodeSize { that's root size, actually }, 1, 13 {FIXME or is that 12?}); IncreaseCodeSize(); fClearCode := Self.AddTranslation(-1, 0); fEOFCode := Self.AddTranslation(-1, 0); end; function TDecoder.HandleSpecialCode(aCode : TUINT16) : TSpecialHandlingVerdict; begin if aCode = fClearCode then Result := shReinitialize else if aCode = fEOFCode then Result := shStopParsing else Result := shNothingSpecial; end; end.