File indexing completed on 2024-03-24 05:44:51
0001 #! /usr/bin/perl 0002 0003 ## This script is based on cyclo.cgi, see http://homepage2.nifty.com/sophia0/ 0004 ## cyclo.cgi v0.3c (CYCLIC IMAGE) 2001.04.15 by techan 0005 0006 # Made slightly less brain-damaged in 2007 by Michael Pyne <michael.pyne@kdemail.net> 0007 # * Added command line arguments. 0008 # * Wee bit more error checking. 0009 # * Help output. 0010 # 0011 # usage: png2mng <basename> <width> <height> 0012 0013 use Getopt::Long; 0014 use Pod::Usage; 0015 0016 $basename = $ARGV[0]; 0017 0018 # Image Width Height 0019 $width = $ARGV[1]; 0020 $height = $ARGV[2]; 0021 0022 # The number of repeats for base (integer > 1) 0023 $b_repeat = 1; 0024 0025 # Ticks per second 0026 $tps = 20; 0027 0028 # Width of number portion of filename. 0029 $fieldWidth = 4; 0030 0031 # Number of file name to start with. (i.e. 0 or 1) 0032 $start = 1; 0033 0034 # User wants help? 0035 $help = 0; 0036 0037 ## Main 0038 0039 $result = GetOptions( 0040 "basename:s" => \$basename, 0041 "width:i" => \$width, 0042 "height:i" => \$height, 0043 "fps:i" => \$tps, 0044 "fieldwidth:i" => \$fieldWidth, 0045 "start-number:i" => \$start, 0046 "help|h|?" => \$help, 0047 ) or pod2usage(-exitstatus => 2); 0048 0049 pod2usage(-verbose => 1, -exitstatus => 0) if $help; 0050 0051 &InitCrcTable; 0052 0053 $r = "NG\r\n\x1a\n"; 0054 $sig_p = "\x89P".$r; 0055 $sig_m = "\x8aM".$r; 0056 0057 # Check File 0058 @png = (); 0059 $size = 1; 0060 for ($i=0;$size > 0;) { 0061 $file = $basename.sprintf('%.*d.png', $fieldWidth, $i+$start); 0062 $size = -s $file; 0063 if ($size > 0) 0064 { 0065 open(IN, "< $file") || &Error(1); 0066 binmode(IN); 0067 read(IN, $sig, 8); 0068 if ($sig ne $sig_p) { close(IN); &Error(2); } 0069 read(IN, $png[$i], $size-8); 0070 close(IN); 0071 $i++; 0072 } 0073 } 0074 $number = $i; 0075 $it = $number * $b_repeat; 0076 $ti = $it; 0077 0078 if ($number == 0) { 0079 print STDERR "No files were read.\n"; 0080 exit 1; 0081 } 0082 0083 $|=1; 0084 binmode(STDOUT); 0085 0086 # Signature 0087 print $sig_m; 0088 0089 # MHDR 0090 $data = 'MHDR'.pack("N7", 0091 $width, 0092 $height, 0093 $tps, # Ticks per second 0094 $number, # Layers 0095 $ti, # Frames 0096 $ti, # Time 0097 583); # Simplicity 0098 &OutputData; 0099 0100 # DEFI define objects of the number specified by $number 0101 for ($i=0;$i<$number;$i++) { 0102 $data = 'DEFI'.pack("n", 0103 $i+1); # Object_id 0104 # Do_not_show: 1 byte (unsigned integer) 0105 # Concrete_flag: 1 byte (unsigned integer) 0106 # X_location: 4 bytes (signed integer) 0107 # Y_location: 4 bytes (signed integer) 0108 # Left_cb: 4 bytes (signed integer) 0109 # Right_cb: 4 bytes (signed integer) 0110 # Top_cb: 4 bytes (signed integer) 0111 # Bottom_cb: 4 bytes (signed integer) 0112 &OutputData; 0113 print $png[$i]; 0114 } 0115 undef(@png); 0116 0117 # LOOP 0118 $data = 'LOOP'.pack("CNC", 0119 0, # Nest_level 0120 $it, # Iteration_count 0121 6); # Termination_condition: 0122 # 1: Decoder discretion, not cacheable. 0123 # 2: User discretion, not cacheable. 0124 # *3: External signal, not cacheable. 0125 # 4: Deterministic, cacheable. 0126 # 5: Decoder discretion, cacheable. 0127 # 6: User discretion, cacheable. 0128 # *7: External signal, cacheable. 0129 # Iteration_min: 4 bytes(unsigned integer) 0130 # Iteration_max: 4 bytes (unsigned integer) 0131 # Signal_number: 4 bytes (unsigned integer) 0132 # Additional signal_number: 4 bytes (unsigned integer) 0133 &OutputData; 0134 0135 # SHOW 0136 $data = 'SHOW'.pack("nnC", 0137 1, # First_image 0138 $number, # Last_image 0139 6); # Show_mode: 0140 # 0: Make the images potentially visible and display them. 0141 # 1: Make the images invisible. 0142 # 2: Display those that are potentially visible. 0143 # 3: Mark images "potentially visible" but do not display 0144 # them. 0145 # 4: Display any that are potentially visible after toggling. 0146 # 5: Do not display even if potentially visible after toggling. 0147 # 6: Step through the images in the given range, making the 0148 # next image potentially visible and display it. Jump to 0149 # the beginning of the range when reaching the end of the 0150 # range. Perform one step for each SHOW chunk (in reverse 0151 # order if last_image < first_image). 0152 # 7: Make the next image in the range (cycle) potentially 0153 # visible but do not display it. 0154 &OutputData; 0155 0156 # ENDL 0157 $data = "ENDL\0"; # Nest_level: 1 byte 0158 &OutputData; 0159 0160 # MEND 0161 print "\0\0\0\0MEND! \xf7\xd5"; 0162 0163 exit(0); 0164 0165 sub Error 0166 { 0167 my $e = $_[0]; 0168 0169 $black = "\0\0\0"; 0170 $red = "\xff\0\0"; 0171 $white = "\xff\xff\xff"; 0172 0173 if ($e == 1) { $plte = $white.$black; } 0174 elsif ($e == 2) { $plte = $white.$red; } 0175 else { $plte = $red.$white; } 0176 0177 $plte = "PLTE".$plte; 0178 0179 $p = $sig_p; 0180 $p.="\0\0\0\rIHDR"; 0181 $p.="\0\0\0\x1e\0\0\0\x0c\x01\x03\0\0\0"; 0182 $p.="\x4f\xe0\x9f\x71"; 0183 $p.="\0\0\0\x06".$plte.&CalcCrc($plte); 0184 $p.="\0\0\0\x2eIDAT"; 0185 $p.="\x78\x9c\x63\x60\x40\x05\xbf\xcf\xcb\x7c\x60\x68\xd2\x58\xd4\x01"; 0186 $p.="\x21\x3e\x81\x88\xe6\xf3\x4a\x40\xb1\x2e\xa5\x05\x0c\x4d\x9e\x4a"; 0187 $p.="\x13\x18\x7e\x69\xcc\xe9\0\xab\x05\0\xb0\x88\x10\xb8"; 0188 $p.="\x57\x3a\0\xa1"; 0189 $p.="\0\0\0\0IEND\xaeB`\x82"; 0190 0191 $|=1; 0192 # print "Content-type: $mime\n"; 0193 # print "Content-length: 121\n\n"; 0194 binmode(STDOUT); 0195 print $p; 0196 exit(1); 0197 } 0198 0199 sub InitCrcTable 0200 { 0201 my $d; 0202 @crc_table = (); 0203 for (0 .. 255) { 0204 $d = $_; 0205 for (0 .. 7) { 0206 if ($d & 1) { $d = 0xedb88320 ^ (($d >> 1) & 0x7fffffff); } 0207 else { $d = ($d >> 1) & 0x7fffffff; } 0208 } 0209 $crc_table[$_] = $d; 0210 } 0211 } 0212 0213 sub CalcCrc 0214 { 0215 my $data = $_[0]; 0216 my $c = 0xffffffff; 0217 foreach (unpack("C*", $data)) { 0218 $c = $crc_table[($c ^ $_) & 0xff] ^ (($c >> 8) & 0xffffff); 0219 } 0220 return(pack("N", ~$c)); 0221 } 0222 0223 sub OutputData 0224 { 0225 print pack("N", length($data)-4).$data.&CalcCrc($data); 0226 undef($data); 0227 } 0228 0229 sub usage() 0230 { 0231 } 0232 0233 __END__ 0234 0235 =head1 NAME 0236 0237 png2mng.pl - Converts PNG files in a sequence to a MNG animation. 0238 0239 =head1 SYNOPSIS 0240 0241 png2mng.pl basename width height [options] > output.mng 0242 0243 Options: 0244 0245 --basename Base file name of the PNG frames. The script adds numbers to 0246 the file name until it can find no more frames. 0247 0248 --width Width of the animation. Each PNG frame should be this width. 0249 0250 --height Height of the animation. Each PNG frame should be this 0251 height. 0252 0253 --fps Frames of animation per second (Default 20) 0254 0255 --fieldwidth Number of characters in the number (Default 4) 0256 0257 --start-number Start looking for files from the given number. (e.g. foo002 0258 rather than foo001.png) (Default 1) 0259 0260 --help Show help output. 0261 0262 The MNG output file is printed straight to standard out so be sure to redirect 0263 to where you want it to go. 0264 0265 =head1 DESCRIPTION 0266 0267 This script reads in a collection of PNG frames, and assembles them into a 0268 MNG animation file. This file can be read in any MNG viewer, including 0269 Konqueror and Gwenview (when appropriately configured). 0270 0271 =head1 BUGS 0272 0273 Width and height are not checked to make sure individual frames are the 0274 required size. In fact very little to no error checking is done. 0275 0276 Must specify a basename. It is not possible to just specify all the PNG files 0277 on the command line. 0278 0279 All the PNG files are read into memory before the MNG starts to output. This 0280 makes the script unsuitable for converting a large amount of PNGs to a MNG 0281 animation. 0282 0283 =head1 AUTHOR 0284 0285 This script is based on cyclo.cgi, see http://homepage2.nifty.com/sophia0/ 0286 cyclo.cgi v0.3c (CYCLIC IMAGE) 2001.04.15 by techan. 0287 0288 Man page was written, and a few changes were made by Michael Pyne 0289 <michael.pyne@kdemail.net> 0290 0291 =cut