File indexing completed on 2025-07-13 05:10:07

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