//----------------------------------------------------------------------------- // Copyright © 2003 - Philip Howard - All rights reserved // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //----------------------------------------------------------------------------- // package libh/angif // homepage http://libh.slashusr.org/ //----------------------------------------------------------------------------- // author Philip Howard // email libh at ipal dot org // homepage http://phil.ipal.org/ //----------------------------------------------------------------------------- // This library is "patent free" in that it contains no code to implement // the LZW compression, which is covered by patent number 4,558,302 owned // by Unisys. // // GIF is a service mark, property of CompuServe, Inc. // // The GIF standard is obsolete and is being deprecated in favor of the // PNG (Portable Network Graphics) standard. //----------------------------------------------------------------------------- #include "angif_lib.h" __PROTO_BEGIN__ //----------------------------------------------------------------------------- // function angif_put_prelzw // // purpose Output pre-compressed LZW data to a stream target. // // arguments 1 (angif_stream *) stream target // 2 (angif_image *) image object // // returns (int) 0 successful completion // (int) <0 error indicated by return value and errno //----------------------------------------------------------------------------- // notice // // Due to the LZW compression algorithm, specified in the GIF format, // being subject to a patent held by Unisys, and the unavailability of // licensing for this patent, this code does not contain compression // logic, and only generates uncompressed data codes. //----------------------------------------------------------------------------- int angif_put_prelzw ( angif_stream * stream , angif_image * image ) __PROTO_END__ { unsigned char buffer [288]; long * color_ptr ; unsigned char * buf_ptr ; int color_count ;// Count of actual colors in table int color_size ; int ct_size ;// Color table size indicator (0..7 for 2^(n+1)) int rc ; //-- Check arguments. if ( ! stream ) return ANGIF_ERROR_ARG_STREAM; if ( ! image ) return ANGIF_ERROR_ARG_IMAGE; //-- Make sure we have LZW data. if ( ! image->data_prelzw ) return ANGIF_ERROR_NO_LZW; //-- Calculate the color table size indicator. ct_size = 0; if ( image->color_table ) { color_count = image->color_count - 1; if ( color_count < 1 || color_count > 255 ) return ANGIF_ERROR_COLOR_COUNT; while ( (color_count >>= 1) ) ++ ct_size; } //-- Setup buffer pointer. buf_ptr = buffer; //-- Output a graphic control extension if needed. if ( image->delay_time || image->disposal || image->user_input || image->trans_flag ) { * (buf_ptr ++) = 0x21; // extension introducer * (buf_ptr ++) = 0xf9; // graphic control label * (buf_ptr ++) = 0x04; // block size * (buf_ptr ++) = 0 + ( 0x1c & ( image->disposal << 2 ) ) + ( 0x02 & ( image->user_input << 1 ) ) + ( 0x01 & image->trans_flag ); * (buf_ptr ++) = image->delay_time; * (buf_ptr ++) = image->delay_time >> 8; * (buf_ptr ++) = image->trans_index; * (buf_ptr ++) = 0; // block terminator } //-- Output the image descriptor. * (buf_ptr ++) = 0x2c; // image separator * (buf_ptr ++) = image->image_left; * (buf_ptr ++) = image->image_left >> 8; * (buf_ptr ++) = image->image_top; * (buf_ptr ++) = image->image_top >> 8; * (buf_ptr ++) = image->image_width; * (buf_ptr ++) = image->image_width >> 8; * (buf_ptr ++) = image->image_height; * (buf_ptr ++) = image->image_height >> 8; * (buf_ptr ++) = 0 + ( image->color_table ? 0x80 : 0x00 ) + ( 0x40 & ( image->interlace << 6 ) ) + ( 0x20 & ( image->ct_sort << 5 ) ) + ( 0x07 & ct_size ); //-- If the local color table is provided, output it. if ( image->color_table ) { color_count = image->color_count; color_ptr = image->color_table; color_size = 2 << ct_size; //-- Output as many color table elements as exist. while ( color_count -- ) { * (buf_ptr ++) = * color_ptr >> 16; * (buf_ptr ++) = * color_ptr >> 8; * (buf_ptr ++) = * color_ptr; ++ color_ptr; -- color_size; } //-- Pad the output color table to a power of 2 elements. while ( color_size -- ) { * (buf_ptr ++) = 0; * (buf_ptr ++) = 0; * (buf_ptr ++) = 0; } } //-- Flush the buffer. if ( (rc = angif_write( stream, buffer, (size_t) ( buf_ptr - buffer ) )) < 0 ) return rc; buf_ptr = image->data_prelzw; //-- Loop through all segments of the data block. for (;;) { //-- Write one segment, with length prefix. if ( (rc = angif_write( stream, buf_ptr, (size_t) * buf_ptr )) < 0 ) return rc; //-- If this was the last segment, then break out. if ( 0 == * buf_ptr ) break; } //-- All done. return 0; }