//----------------------------------------------------------------------------- // Copyright © 2003,2006 - 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. // // The LZW compression patent is now expire. // // 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" #include __FMACRO_BEGIN__ //----------------------------------------------------------------------------- // macro angif_put_linear // // purpose Output a linear RGB mode image array to a stream target. // Call the angif_put_linear() function from the caller program // with the passing of a pointer to the pow() function. // // 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 //----------------------------------------------------------------------------- #define angif_put_linear(s,i) ((angif_put_linear)((exp),(log),(s),(i))) __FMACRO_END__ //----------------------------------------------------------------------------- // define exp() // // purpose Cause usage of the exp() function to reference the function // given in the function pointer named arg_exp. //----------------------------------------------------------------------------- #define exp(x) ((*arg_exp)((x))) //----------------------------------------------------------------------------- // define log() // // purpose Cause usage of the log() function to reference the function // given in the function pointer named arg_log. //----------------------------------------------------------------------------- #define log(x) ((*arg_log)((x))) __PROTO_BEGIN__ //----------------------------------------------------------------------------- // function (angif_put_linear) // // purpose Output a linear RGB mode image array to a stream target. // // arguments 1 ((*)()) pointer to exp() passed by macro // 2 ((*)()) pointer to log() passed by macro // 3 (angif_stream *) stream target // 4 (angif_image *) image object // // returns (int) 0 successful completion // (int) <0 error indicated by return value and errno //----------------------------------------------------------------------------- int (angif_put_linear) ( double ( * arg_exp )(double) , double ( * arg_log )(double) , angif_stream * stream , angif_image * image ) __PROTO_END__ { angif_image image_rgb ; double inv_gamma_red ; double inv_gamma_green ; double inv_gamma_blue ; float * linear_pix_red ; float * linear_pix_green ; float * linear_pix_blue ; float * linear_row_red ; float * linear_row_green ; float * linear_row_blue ; long * rgb_array ; long * rgb_pix_ptr ; long * rgb_pix_end ; long * rgb_row_ptr ; long * rgb_row_end ; long array_left ; long array_top ; long array_width ; long array_height ; long image_width ; long image_height ; int rc ; //-- Check arguments. if ( ! stream ) return ANGIF_ERROR_ARG_STREAM; if ( ! image ) return ANGIF_ERROR_ARG_IMAGE; //-- Make sure we have a linear image. if ( ! image->data_red ) return ANGIF_ERROR_DATA; if ( ! image->data_green ) return ANGIF_ERROR_DATA; if ( ! image->data_blue ) return ANGIF_ERROR_DATA; //-- Get frequently used info. image_width = image->image_width; image_height = image->image_height; array_width = image->array_width; array_height = image->array_height; array_left = image->array_left; array_top = image->array_top; //-- Verify image geometry. if ( image_width > ( array_width - array_left ) || image_height > ( array_height - array_top ) ) { return ANGIF_ERROR_GEOMETRY; } //-- Allocate an RGB image array. rgb_array = malloc( sizeof (long) * image_width * image_height ); if ( ! rgb_array ) return ANGIF_ERROR_ALLOC; //-- Prepare the gamma correction. inv_gamma_red = 1.0 / ( ( image->gamma_red <= 0.0 ) ? image->gamma_red : ANGIF_DEFAULT_GAMMA ); inv_gamma_green = 1.0 / ( ( image->gamma_green <= 0.0 ) ? image->gamma_green : ANGIF_DEFAULT_GAMMA ); inv_gamma_blue = 1.0 / ( ( image->gamma_blue <= 0.0 ) ? image->gamma_blue : ANGIF_DEFAULT_GAMMA ); //-- Setup the row starting and ending pointers. linear_row_red = image->data_red + array_top * array_width + array_left; linear_row_green = image->data_green + array_top * array_width + array_left; linear_row_blue = image->data_blue + array_top * array_width + array_left; rgb_row_ptr = rgb_array; rgb_row_end = rgb_array + image_height * image_width; //-- Go through all rows of the image. while ( rgb_row_ptr < rgb_row_end ) { //-- Setup the pixel starting and ending pointers from the rows. linear_pix_red = linear_row_red; linear_pix_green = linear_row_green; linear_pix_blue = linear_row_blue; rgb_pix_ptr = rgb_row_ptr; rgb_pix_end = rgb_row_ptr + image_width; //-- Go through all the pixels of the image row. while ( rgb_pix_ptr < rgb_pix_end ) { // * (rgb_pix_ptr ++) = // pix_rgb8_ftoi( inv_gamma_red, * linear_pix_red, * linear_pix_green, * linear_pix_blue ); ++ linear_pix_red; ++ linear_pix_green; ++ linear_pix_blue; } //-- Increment the row pointers to the next row. linear_row_red += array_width; linear_row_green += array_width; linear_row_blue += array_width; rgb_row_ptr += image_width; } //----------------------------------------------------------------------------- // We now have a complete coded RGB image. //----------------------------------------------------------------------------- //-- Build a new image struct for the coded RGB image. image_rgb.data_red = NULL; image_rgb.data_green = NULL; image_rgb.data_blue = NULL; image_rgb.data_rgb = rgb_array; image_rgb.data_index = NULL; image_rgb.data_prelzw = NULL; image_rgb.gamma_red = 0.0; image_rgb.gamma_green = 0.0; image_rgb.gamma_blue = 0.0; image_rgb.color_table = NULL; image_rgb.color_count = 0; image_rgb.image_width = image_width; image_rgb.image_height = image_height; image_rgb.image_left = image->image_left; image_rgb.image_top = image->image_top; image_rgb.array_width = image_width; image_rgb.array_height = image_height; image_rgb.array_left = 0; image_rgb.array_top = 0; image_rgb.delay_time = image->delay_time; image_rgb.interlace = image->interlace; image_rgb.ct_sort = 0; image_rgb.disposal = image->disposal; image_rgb.user_input = image->user_input; image_rgb.trans_flag = 0; image_rgb.trans_index = 0; //-- Put this image as a coded RGB image. rc = angif_put_rgb( stream, & image_rgb ); //-- Free the coded RGB image array. free( rgb_array ); //-- Return the result we got above. return rc; }