Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.         SDL_anim:  an animation library for SDL
  3.         Copyright (C) 2001, 2002  Michael Leonhard
  4.  
  5.         This library is free software; you can redistribute it and/or
  6.         modify it under the terms of the GNU Library General Public
  7.         License as published by the Free Software Foundation; either
  8.         version 2 of the License, or (at your option) any later version.
  9.  
  10.         This library is distributed in the hope that it will be useful,
  11.         but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.         Library General Public License for more details.
  14.  
  15.         You should have received a copy of the GNU Library General Public
  16.         License along with this library; if not, write to the Free
  17.         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.        
  19.         Michael Leonhard
  20.         mike@tamale.net
  21. */
  22.  
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <png.h>
  26.  
  27. /* deal with MSVC++ crappiness */
  28. #ifdef WIN32
  29.         #define snprintf _snprintf
  30.         #endif
  31.  
  32. typedef struct inputstruct {
  33.         FILE *file;
  34.         char *name;
  35.         png_structp read_ptr;
  36.         png_infop read_info_ptr;
  37.         };
  38.  
  39. int numfiles;
  40. struct inputstruct *input;
  41.  
  42. int main( int argc, char *argv[] ) {
  43.         int f, rowbytes;
  44.         char buf[256];
  45.         static FILE *fpout;  /* "static" prevents setjmp corruption */
  46.         png_structp write_ptr;
  47.         png_infop write_info_ptr, end_info_ptr;
  48.         png_bytep row_buf, here;
  49.         png_uint_32 y;
  50.         png_textp text_ptr, new_text_ptr;
  51.         int num_text;
  52.  
  53.         int interlace_type, compression_type, filter_type, bit_depth, color_type;
  54.         int it, ct, ft, bd, clrt;
  55.         png_uint_32 width, height, w, h;
  56.  
  57.         int duration;
  58.  
  59.         if( argc < 4 ) {
  60.                 printf( "makeanim v0.2\nusage: makeanim <duration in milliseconds> <input files ...> <output file>\n" );
  61.                 printf( "example: makeanim 1500 a00.png a01.png a02.png a03.png a04.png a.anim\n" );
  62.                 return 1;
  63.                 }
  64.  
  65.         duration = atoi( argv[1] );
  66.         if( duration < 1 ) {
  67.                 printf( "duration is incorrect\n" );
  68.                 return 1;
  69.                 }
  70.  
  71.         numfiles = argc - 3;
  72.         input = (struct inputstruct *)malloc( sizeof( struct inputstruct ) * numfiles );
  73.         if( !input ) return 1;
  74.  
  75.         for( f = 0; f < numfiles; f++ ) {
  76.                 input[f].name = argv[f + 2];
  77.                 printf( "opening file %d, \"%s\"\n", f, input[f].name );
  78.  
  79.                 /* open the file handle */
  80.                 input[f].file = fopen( input[f].name, "rb" );
  81.                 if( input[f].file == NULL ) {
  82.                         printf( "fopen() failed\n" );
  83.                         return 1;
  84.                         }
  85.  
  86.                 /* check if it's PNG */
  87.                 if( fread( buf, 1, 8, input[f].file ) != 8 ) {
  88.                         printf( "fread() failed for file \"%s\"\n", input[f].name );
  89.                         return 1;
  90.                         }
  91.                 if( png_sig_cmp( buf, (png_size_t)0, 8 ) ) {
  92.                         printf( "not a PNG file\n" );
  93.                         return 1;
  94.                         }
  95.                 fseek( input[f].file, 0, SEEK_SET );
  96.  
  97.                 /* allocate read structure */
  98.                 input[f].read_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL );
  99.                 if( input[f].read_ptr == NULL ) {
  100.                         printf( "png_create_read_struct() failed\n" );
  101.                         return 1;
  102.                         }
  103.                
  104.                 /* allocate read info structure */
  105.                 input[f].read_info_ptr = png_create_info_struct( input[f].read_ptr );
  106.                 if( input[f].read_info_ptr == NULL ) {
  107.                         printf( "png_create_info_struct() failed\n" );
  108.                         return 1;
  109.                         }
  110.  
  111.  
  112.                 /* set error handler code */
  113.                 if( setjmp( input[f].read_ptr->jmpbuf ) ) {
  114.                         printf( "libpng read error\n" );
  115.                         return 1;
  116.                         }
  117.  
  118.                 /* initialize stream */
  119.                 png_init_io( input[f].read_ptr, input[f].file );
  120.                 png_set_read_status_fn( input[f].read_ptr, NULL );
  121.  
  122.                 /* read png info struct */
  123.                 png_read_info( input[f].read_ptr, input[f].read_info_ptr );
  124.  
  125.                 /* get the info */
  126.                 if( !png_get_IHDR( input[f].read_ptr, input[f].read_info_ptr, &w, &h, &bd, &clrt, &it, &ct, &ft ) ) {
  127.                         printf( "png_get_IHDR() failed\n" );
  128.                         return 1;
  129.                         }
  130.  
  131.                 /* save the info of the first frame */
  132.                 if( f == 0 ) {
  133.                         width = w;
  134.                         height = h;
  135.                         bit_depth = bd;
  136.                         color_type = clrt;
  137.                         interlace_type = it;
  138.                         compression_type = ct;
  139.                         filter_type = ft;
  140.                         }
  141.                 /* compare all other frames to first frame */
  142.                 else if( (w != width) ||
  143.                                 (h != height) ||
  144.                                 (bd != bit_depth) ||
  145.                                 (clrt != color_type) ||
  146.                                 (it != interlace_type) ||
  147.                                 (ct != compression_type) ||
  148.                                 (ft != filter_type) ) {
  149.                         if( w != width ) printf( "width is different\n" );
  150.                         if( h != height ) printf( "height  is different\n" );
  151.                         if( bd != bit_depth ) printf( "bit depth is different\n" );
  152.                         if( clrt != color_type ) printf( "color type is different\n" );
  153.                         if( it != interlace_type ) printf( "interlace type is different\n" );
  154.                         if( ct != compression_type ) printf( "compression type is different\n" );
  155.                         if( ft != filter_type ) printf( "filter type is different\n" );
  156.                         return 1;
  157.                         }
  158.                 }
  159.        
  160.         row_buf = (png_bytep)NULL;
  161.        
  162.         /* open output file */
  163.         printf( "opening file \"%s\"\n", argv[numfiles + 2] );
  164.         fpout = fopen( argv[numfiles + 2], "wb" );
  165.         if( fpout == NULL ) {
  166.                 printf( "fopen() failed\n" );
  167.                 return 1;
  168.                 }
  169.  
  170.         /* allocate write structure */
  171.         write_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL );
  172.  
  173.         /* allocate info structures */
  174.         write_info_ptr = png_create_info_struct( write_ptr );
  175.         end_info_ptr = png_create_info_struct( write_ptr );
  176.  
  177.         /* error handling */
  178.         if( setjmp( write_ptr->jmpbuf ) ) {
  179.                 printf( "libpng write error\n" );
  180.                 return 1;
  181.                 }
  182.  
  183.         /* initialize output stream */
  184.         png_init_io( write_ptr, fpout );
  185.         png_set_write_status_fn( write_ptr, NULL );
  186.  
  187.         /* set info */
  188.         png_set_IHDR( write_ptr, write_info_ptr, width * numfiles, height, bit_depth, color_type, PNG_INTERLACE_NONE, compression_type, filter_type);
  189.  
  190.         /* image characteristics */
  191.         {
  192.                 png_color_16p background;
  193.                 double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
  194.                 double gamma;
  195.                 int intent;
  196.                 png_uint_16p hist;
  197.                 png_uint_32 offset_x, offset_y;
  198.                 int unit_type;
  199.                 png_charp purpose, units;
  200.                 png_charpp params;
  201.                 png_int_32 X0, X1;
  202.                 int type, nparams;
  203.                 png_uint_32 res_x, res_y;
  204.                 png_colorp palette;
  205.                 int num_palette;
  206.                 png_color_8p sig_bit;
  207.                 png_bytep trans;
  208.                 int num_trans;
  209.                 png_color_16p trans_values;
  210.  
  211.                 /* background color */
  212.                 if( png_get_bKGD( input[0].read_ptr, input[0].read_info_ptr, &background ) ) {
  213.                         png_set_bKGD( write_ptr, write_info_ptr, background );
  214.                         }
  215.  
  216.                 if( png_get_cHRM( input[0].read_ptr, input[0].read_info_ptr, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y ) ) {
  217.                         png_set_cHRM( write_ptr, write_info_ptr, white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y );
  218.                         }
  219.  
  220.                 /* gamma */
  221.                 if( png_get_gAMA( input[0].read_ptr, input[0].read_info_ptr, &gamma ) ) {
  222.                         png_set_gAMA( write_ptr, write_info_ptr, gamma );
  223.                         }
  224.  
  225.                 /* rendering intent */
  226.                 if( png_get_sRGB( input[0].read_ptr, input[0].read_info_ptr, &intent ) ) {
  227.                         png_set_sRGB( write_ptr, write_info_ptr, intent );
  228.                         }
  229.  
  230.                 /* Histogram */
  231.                 if( png_get_hIST( input[0].read_ptr, input[0].read_info_ptr, &hist ) ) {
  232.                         png_set_hIST( write_ptr, write_info_ptr, hist );
  233.                         }
  234.  
  235.                 /* offsets */
  236.                 if( png_get_oFFs( input[0].read_ptr, input[0].read_info_ptr, &offset_x, &offset_y, &unit_type ) ) {
  237.                         png_set_oFFs( write_ptr, write_info_ptr, offset_x, offset_y, unit_type );
  238.                         }
  239.  
  240.                 if( png_get_pCAL( input[0].read_ptr, input[0].read_info_ptr, &purpose, &X0, &X1, &type, &nparams, &units, &params ) ) {
  241.                         png_set_pCAL( write_ptr, write_info_ptr, purpose, X0, X1, type, nparams, units, params );
  242.                         }
  243.  
  244.                 /* pixel density */
  245.                 if( png_get_pHYs( input[0].read_ptr, input[0].read_info_ptr, &res_x, &res_y, &unit_type ) ) {
  246.                         png_set_pHYs( write_ptr, write_info_ptr, res_x, res_y, unit_type );
  247.                         }
  248.  
  249.                 /* text chunks */
  250. /*              if( png_get_text( input[0].read_ptr, input[0].read_info_ptr, &text_ptr, &num_text ) > 0 ) {
  251.                         printf( "Handling %d tEXt/zTXt chunks\n", num_text );
  252.                         png_set_text( write_ptr, write_info_ptr, text_ptr, num_text );
  253.                         }
  254. */
  255.                 /* palette */
  256.                 if( png_get_PLTE( input[0].read_ptr, input[0].read_info_ptr, &palette, &num_palette ) ) {
  257.                         png_set_PLTE( write_ptr, write_info_ptr, palette, num_palette );
  258.                         }
  259.  
  260.                 /* significant bits */
  261.                 if( png_get_sBIT( input[0].read_ptr, input[0].read_info_ptr, &sig_bit ) ) {
  262.                         png_set_sBIT( write_ptr, write_info_ptr, sig_bit );
  263.                         }
  264.  
  265.                 /* transparency */
  266.                 if( png_get_tRNS( input[0].read_ptr, input[0].read_info_ptr, &trans, &num_trans, &trans_values ) ) {
  267.                         png_set_tRNS( write_ptr, write_info_ptr, trans, num_trans, trans_values );
  268.                         }
  269.                 }
  270.  
  271.         /* text chunks */
  272.         num_text = 0;
  273.         if( !png_get_text( input[0].read_ptr, input[0].read_info_ptr, &text_ptr, &num_text ) ) num_text = 0;
  274.         new_text_ptr = (struct png_text_struct *)malloc( sizeof( struct png_text_struct ) * num_text + 1 );
  275.         if( !new_text_ptr ) {
  276.                 printf( "malloc() failed\n" );
  277.                 return 1;
  278.                 }
  279.        
  280.         memcpy( new_text_ptr, text_ptr, sizeof( struct png_text_struct ) * num_text );
  281.  
  282.         snprintf( buf, 255, "SDL_anim %d %d %d", duration, width, numfiles );
  283.         buf[255] = 0;
  284.         new_text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
  285.         new_text_ptr[num_text].key = "format";
  286.         new_text_ptr[num_text].text = buf;
  287.         new_text_ptr[num_text].text_length = strlen( buf );
  288.         num_text++;
  289.         png_set_text( write_ptr, write_info_ptr, new_text_ptr, num_text );
  290.  
  291.         /* write info */
  292.         png_write_info( write_ptr, write_info_ptr );
  293.  
  294.         /* allocate buffer */
  295.         rowbytes = png_get_rowbytes( input[0].read_ptr, input[0].read_info_ptr );
  296.         row_buf = (png_bytep)png_malloc( write_ptr, rowbytes * numfiles );
  297.         if( row_buf == NULL ) {
  298.                 printf( "png_malloc() failed\n" );
  299.                 return 1;
  300.                 }
  301.  
  302.         /* copy raw data */
  303.         for( y = 0; y < height; y++ ) {
  304.                 /* grab a scanline from each file */
  305.                 here = row_buf;
  306.                 for( f = 0; f < numfiles; f++ ) {
  307.                         png_read_rows( input[f].read_ptr, (png_bytepp)&here, (png_bytepp)NULL, 1 );
  308.                         here += rowbytes;
  309.                         }
  310.                 /* write the long scanline */
  311.                 png_write_rows( write_ptr, (png_bytepp)&row_buf, 1 );
  312.                 }
  313.  
  314.         /* end io */
  315.         for( f = 0; f < numfiles; f++ ) png_read_end( input[f].read_ptr, end_info_ptr );
  316.         png_write_end( write_ptr, end_info_ptr );
  317.  
  318.         /* cleanup */
  319.         png_free( write_ptr, row_buf );
  320.         for( f = 0; f < numfiles; f++ ) {
  321.                 png_destroy_read_struct( &input[f].read_ptr, &input[f].read_info_ptr, &end_info_ptr);
  322.                 fclose( input[f].file );
  323.                 }
  324.         png_destroy_write_struct( &write_ptr, &write_info_ptr );
  325.         fclose( fpout );
  326.  
  327.         return 0;
  328.         }
  329.