/*----------------------------------------------------------------------*/ /* Copyright (c) 1988-1989 */ /* by CompuServe Inc., Tucson, AZ. All Rights Reserved */ /* GIFTIF.C can be copied and distributed freely for any */ /* non-commercial purposes. GIFTIF.C can only be incorporated */ /* into commercial software with the permission of CompuServe Inc. */ /*----------------------------------------------------------------------*/ /* GIFTIF.C */ /* * ABSTRACT: * This file contains main program to convert GIF files into * one-dimensional group-3 FAX compressed files. * * AUTHOR: Doug Chinnock * * REVISION HISTORY: * */ #include #include #include #include "GIFbase.h" #include "cnvhuf.h" #include "rletif.h" #include "writetif.h" #include "readgif.h" #include "gifreade.h" #include "expander.h" extern int scan_lines; /* Define all the prototypes */ #include "writetif.h" short int write_TIF_pixel( unsigned char TIF_pixel ); void add_TIF_tag( short int TT_tag_code, short int TT_value_type, long int TT_value_count, short int TT_value1, short int TT_value2 ); /* Top scope variables and constants: */ static rle_line TIF_cur_line; static IFD_header * IFD_body; static struct { short int entry_idx; /* Entry with offset values */ short int entry_offset; /* Values loc in ifd_offset_params */ /* Or -1 if not yet determined */ } ifd_offset_entries[5]; static unsigned char ifd_offset_params[250]; /* Place to accum oversize parameters */ static short int ifd_offsets_count, /* Number of ifd_offset_entries */ ifd_offset_free, /* 1st free byte in ifd_offset_params */ ifd_offsets_begin, /* 1st byte in file for offset values */ ifd_offsets_end, /* Last byte in file for offset values */ OBJ_screen_width, /* Length of lines to use to make TIF */ tot_lines; /* Count of lines compressed */ static unsigned scaling; short int write_TIF_pixel( unsigned char TIF_pixel ) { colors BW_pixel; unsigned scale_count; if ( TIF_pixel == 0 ) BW_pixel = WHITE; else BW_pixel = BLACK; for (scale_count = scaling; scale_count > 0; scale_count --) { TIF_cur_line.current_column ++; if ( TIF_cur_line.rle_pointer < LONGEST_RLE ) { /* Buffer not full yet */ if ( BW_pixel == TIF_cur_line.rle_color ) { /* More of same color */ TIF_cur_line.rle_list[TIF_cur_line.rle_pointer] ++; } else { /* Color change */ TIF_cur_line.rle_color = BW_pixel; TIF_cur_line.rle_pointer ++; TIF_cur_line.rle_list[TIF_cur_line.rle_pointer] = 1; }; } else { /* Buffer overflowed */ return -1; } } if ( TIF_cur_line.current_column >= OBJ_screen_width ) { /* Line full now */ while (TIF_cur_line.current_column < FAX_line_width ) { if ( TIF_cur_line.rle_color != WHITE ) { TIF_cur_line.rle_color = WHITE; TIF_cur_line.rle_pointer ++; TIF_cur_line.rle_list[TIF_cur_line.rle_pointer] = 1; } else { TIF_cur_line.rle_list[TIF_cur_line.rle_pointer] ++; } TIF_cur_line.current_column ++; } /* while (TIF_cur_line.current_column < FAX_line_screen_width ) */ TIF_cur_line.rle_pointer ++; /* Count the run */ TIF_cur_line.line_length = TIF_cur_line.current_column; TIF_cur_line.rle_count = TIF_cur_line.rle_pointer; for (scale_count = scaling; scale_count > 0; scale_count --) compress_huffman_line( &TIF_cur_line ); /* Start new line */ TIF_cur_line.current_column = 0; TIF_cur_line.rle_color = 0; TIF_cur_line.rle_pointer = 0; TIF_cur_line.rle_list[TIF_cur_line.rle_pointer] = 0; }; return 0; } /* write_TIF_pixel */ void add_TIF_tag( short int TT_tag_code, short int TT_value_type, long int TT_value_count, short int TT_value1, short int TT_value2 ) { (*IFD_body).IFD_tag_element[(*IFD_body).IFD_ele_cnt]. IFD_tag = TT_tag_code, (*IFD_body).IFD_tag_element[(*IFD_body).IFD_ele_cnt]. IFD_type = TT_value_type; (*IFD_body).IFD_tag_element[(*IFD_body).IFD_ele_cnt]. IFD_length = TT_value_count; switch ( TT_value_type ) { case 3 : /* 16 bit unsigned integer(s) */ (*IFD_body).IFD_tag_element[(*IFD_body).IFD_ele_cnt]. params.short_pair[0] = TT_value1; (*IFD_body).IFD_tag_element[(*IFD_body).IFD_ele_cnt]. params.short_pair[1] = TT_value2; break; case 4 : /* 32 bit unsigned integer(s) */ (*IFD_body).IFD_tag_element[(*IFD_body).IFD_ele_cnt]. params.long_one = (long)TT_value1; break; case 5 : /* fraction(2) of 2 32 bit integers */ ifd_offset_entries[ifd_offsets_count].entry_idx = (*IFD_body).IFD_ele_cnt; ifd_offset_entries[ifd_offsets_count ++].entry_offset = ifd_offset_free; ifd_offset_params[ifd_offset_free ++] = (unsigned char)( (long)(TT_value1) & 0xFF ); ifd_offset_params[ifd_offset_free ++] = (unsigned char)( ( (long)(TT_value1) >> 8 ) & 0xFF ); ifd_offset_params[ifd_offset_free ++] = (unsigned char)( ( (long)(TT_value1) >> 16 ) & 0xFF ); ifd_offset_params[ifd_offset_free ++] = (unsigned char)( (long)(TT_value1) >> 24 ); ifd_offset_params[ifd_offset_free ++] = (unsigned char)( (long)(TT_value2) & 0xFF ); ifd_offset_params[ifd_offset_free ++] = (unsigned char)( ( (long)(TT_value2) >> 8 ) & 0xFF ); ifd_offset_params[ifd_offset_free ++] = (unsigned char)( ( (long)(TT_value2) >> 16 ) & 0xFF ); ifd_offset_params[ifd_offset_free ++] = (unsigned char)( (long)(TT_value2) >> 24 ); break; case 1 : /* 8 bit unsigned integer(s) */ case 2 : /* ASCIZ string */ default : printf( "\nTIF type not supported yet\n" ); break; }; /* switch ( IFD_type ) */ (*IFD_body).IFD_ele_cnt ++; } /* add_TIF_tag */ void main (void) { char LetterAnswer[2], input_name[25], output_name[25]; unsigned done; short GIF_screen_width, GIF_screen_height, GIF_color_res, GIF_fill_color, GIF_default_color_cnt, GIF_left_edge, GIF_top_edge, GIF_width, GIF_height, GIF_interlaced, GIF_img_color_cnt, i, status; static struct ColorEntry GIF_default_map[MaxColors], GIF_img_map[MaxColors]; static union { /* Buffer to hold whole TIF header */ TIF_header TIF_member; char TIF_buffer[sizeof(TIF_header)+sizeof(IFD_header)]; } TIF_work_bfr; static char TIF_sign_contents[4] = TIF_sign_par; /* Access and prepare the GIF file */ do { printf( "\nGIF source file: " ); scanf( "%25s", input_name ); } while ( init_GIF_input(input_name) != 0 ); status = ReadScreenDesc( next_GIF_byte, & GIF_screen_width, & GIF_screen_height, & GIF_color_res, & GIF_fill_color, & GIF_default_color_cnt, GIF_default_map, MaxColors ); if ( status == 0 ) { /* GIF data set not acceptable */ printf( "\nGIF file not acceptable for conversion\n" ); return; }; printf( "GIF file has %d lines %d pixels long\n Is scaling wanted? ", GIF_screen_height, GIF_screen_width ); scanf( "%1s", LetterAnswer ); if ( LetterAnswer[0] == 'Y' || LetterAnswer[0] == 'y' ) { scaling = 0; while ( scaling == 0 || GIF_screen_width*scaling > FAX_line_width ) { printf( " Desired enlargement multiplier: "); scanf( "%u", &scaling ); } } else { scaling = 1; } OBJ_screen_width = GIF_screen_width * scaling; /* Activate the TIF file builder */ printf( "TIF product file: " ); scanf( "%25s", output_name ); init_TIF_output(output_name); tot_lines = 0; done = 0; while (! done) { switch ( next_GIF_byte() ) /* Get character after header */ { case ',' : /* Start of image */ if (! ReadImageDesc( next_GIF_byte, & GIF_left_edge, & GIF_top_edge, & GIF_width, & GIF_height, & GIF_interlaced, & GIF_img_color_cnt, GIF_img_map, MaxColors ) ) { printf( "\nGIF file not acceptable for conversion\n" ); return; }; /* Test compatibility */ if ( GIF_interlaced ) { printf( "\nCannot handle interlaced GIF\n" ); return; }; /* Create TIF header */ for (i = 0; i < 4; i ++ ) TIF_work_bfr.TIF_member.TIF_sign[i] = TIF_sign_contents[i]; TIF_work_bfr.TIF_member.IFD_offset = sizeof(TIF_header); IFD_body = (IFD_header *)(&TIF_work_bfr); FP_OFF(IFD_body) += sizeof(TIF_header); (*IFD_body).IFD_ele_cnt = 0; ifd_offsets_count = 0; ifd_offset_free = 0; /* Following must be in ascending order by IFD_tag field */ add_TIF_tag( TT_width, TT_width_type, TT_width_cnt, 1728, 0 ); add_TIF_tag( TT_length, TT_length_type, TT_length_cnt, GIF_height, 0 ); add_TIF_tag( TT_PixBits, TT_PixBits_type, TT_PixBits_cnt, TT_PixBits_par, 0 ); add_TIF_tag( TT_Cmprs, TT_Cmprs_type, TT_Cmprs_cnt, TT_Cmprs_par, 0 ); add_TIF_tag( TT_Revrs, TT_Revrs_type, TT_Revrs_cnt, TT_Revrs_par, 0 ); add_TIF_tag( TT_MSBend, TT_MSBend_type, TT_MSBend_cnt, TT_MSBend_par, 0 ); (*IFD_body).IFD_tag_element[(*IFD_body).IFD_ele_cnt]. IFD_tag = TT_Image; (*IFD_body).IFD_tag_element[(*IFD_body).IFD_ele_cnt]. IFD_type = TT_Image_type; (*IFD_body).IFD_tag_element[(*IFD_body).IFD_ele_cnt]. IFD_length = 1; ifd_offset_entries[ifd_offsets_count].entry_idx = (*IFD_body).IFD_ele_cnt; ifd_offset_entries[ifd_offsets_count ++].entry_offset = -1; (*IFD_body).IFD_ele_cnt ++; add_TIF_tag( TT_Orient, TT_Orient_type, TT_Orient_cnt, TT_Orient_par, 0 ); add_TIF_tag( TT_Samps, TT_Samps_type, TT_Samps_cnt, TT_Samps_par, 0 ); add_TIF_tag( TT_X_dense, TT_X_dense_type, TT_X_dense_cnt, TT_X_dense_par1, TT_X_dense_par2 ); add_TIF_tag( TT_Y_dense, TT_Y_dense_type, TT_Y_dense_cnt, TT_Y_dense_par1, TT_Y_dense_par2 ); add_TIF_tag( TT_Grp3Opt, TT_Grp3Opt_type, TT_Grp3Opt_cnt, TT_Grp3Opt_par, 0 ); add_TIF_tag( TT_Resol, TT_Resol_type, TT_Resol_cnt, TT_Resol_par, 0 ); add_TIF_tag( TT_PagNum, TT_PagNum_type, TT_PagNum_cnt, TT_PagNum_par1, TT_PagNum_par2 ); ifd_offsets_begin = sizeof(TIF_header) + sizeof(short int) + sizeof(IFD_tag_body) * (*IFD_body).IFD_ele_cnt + 4; ifd_offsets_end = ifd_offsets_begin + ifd_offset_free; /* Insert offset pointers into header just build */ for ( i = 0; i < ifd_offsets_count; i ++ ) { if ( ifd_offset_entries[i].entry_offset >= 0 ) (*IFD_body) .IFD_tag_element[ ifd_offset_entries[i].entry_idx ] .params.offset = ifd_offsets_begin + ifd_offset_entries[i].entry_offset; else (*IFD_body) .IFD_tag_element[ ifd_offset_entries[i].entry_idx ] .params.offset = ifd_offsets_end; }; /* Write out the header */ for ( i = 0; i < ifd_offsets_begin - 4; i ++ ) put_TIF_byte( TIF_work_bfr.TIF_buffer[ i ] ); /* Write out the link to the next IFD */ for ( i = 0; i < 4; i ++ ) put_TIF_byte( 0 ); /* NULL */ /* Write out the indirect parameters */ for ( i = 0; i < ifd_offset_free; i ++ ) put_TIF_byte( ifd_offset_params[ i ] ); /* Setup for conversion of GIF to TIF images */ TIF_cur_line.current_column = 0; TIF_cur_line.rle_pointer = 0; TIF_cur_line.rle_list[TIF_cur_line.rle_pointer] = 0; /* Perform the conversion */ status = Expand_Data( next_GIF_byte, write_TIF_pixel ); if ( status != 0 ) { printf( "\nGIF file not acceptable for conversion\n" ); return; }; for ( i = 0; i < 6; i ++ ) TIF_write_bits( 12, 0x1); /* Write end of page code */ break; case ';' : /* End of dataset */ done = 1; break; case '!' : /* undefined extension */ printf( "\nGIF file not acceptable for conversion\n" ); return; default : /* Unknown delimiter */ printf( "\nGIF file not acceptable for conversion\n" ); return; } /* switch */ } /* while (! done) */ close_stream( ); finish_output( ); }