summaryrefslogtreecommitdiff
path: root/PLUGINS/src/pictures/pic2mpg-sd
diff options
context:
space:
mode:
Diffstat (limited to 'PLUGINS/src/pictures/pic2mpg-sd')
-rwxr-xr-xPLUGINS/src/pictures/pic2mpg-sd193
1 files changed, 193 insertions, 0 deletions
diff --git a/PLUGINS/src/pictures/pic2mpg-sd b/PLUGINS/src/pictures/pic2mpg-sd
new file mode 100755
index 00000000..15549dcd
--- /dev/null
+++ b/PLUGINS/src/pictures/pic2mpg-sd
@@ -0,0 +1,193 @@
+#!/usr/bin/perl
+
+# pic2mpg: Convert picture files to MPEG still frames
+#
+# Converts either a single picture file or all files in a
+# given directory (recursively) to MPEG still frames.
+#
+# See the README file for copyright information and how to reach the author.
+#
+# $Id: pic2mpg-sd 2.1 2011/07/23 14:23:59 kls Exp $
+
+## TODO implement HDTV (1920 x 1080)
+
+use File::Path;
+use File::Spec;
+use Getopt::Std;
+use Image::ExifTool qw(:Public);
+use Image::Size;
+
+$Usage = qq{
+Usage: $0 [options] picture-dir mpeg-dir
+ $0 [options] picture-file mpeg-file
+
+Options: -a Aspect ratio 4:3 (default is 16:9)
+ -f Force conversion
+ -h print Help
+ -i Ignore unknown file types
+ -n NTSC (default is PAL)
+ -v num Verbose (0=none, 1=list files, 2=detailed)
+ -x percent X overscan in percent
+ -y percent Y overscan in percent
+};
+
+getopts("afhinv:x:y:") || die $Usage;
+
+die $Usage if $opt_h;
+
+$Aspect = $opt_a;
+$Force = $opt_f;
+$Ignore = $opt_i;
+$NTSC = $opt_n;
+$Verbose = $opt_v;
+$OverscanX = $opt_x;
+$OverscanY = $opt_y;
+
+$ListFiles = $Verbose >= 1;
+$Detailed = $Verbose >= 2;
+
+# Screen size:
+
+$SW = $NTSC ? 720 : 720;
+$SH = $NTSC ? 480 : 576;
+
+$ScreenRatio = $Aspect ? 4 / 3 : 16 / 9;
+
+# Converter programs:
+
+%PNMCONV = (
+ bmp => "bmptopnm",
+ gif => "giftopnm",
+ jpeg => "jpegtopnm",
+ jpg => "jpegtopnm",
+ png => "pngtopnm",
+ pnm => "cat",
+ tif => "tifftopnm",
+ tiff => "tifftopnm",
+ );
+
+# Command options:
+
+die "$0: missing parameter\n" unless $ARGV[0] && $ARGV[1];
+die "$0: file or directory not found: $ARGV[0]\n" unless -e $ARGV[0];
+die "$0: source and destination must be different\n" if $ARGV[0] eq $ARGV[1];
+
+$verbose1 = $Detailed ? "--verbose" : "";
+$verbose2 = $Detailed ? "-v 2" : "-v 0";
+$system1 = $NTSC ? "" : "--pal";
+$system2 = $NTSC ? "n" : "p";
+$framerate = $NTSC ? "30000:1001" : "25:1";
+$aspect = $Aspect ? "2" : "3";
+
+# Convert a single file:
+
+if (-f $ARGV[0]) {
+ die "$0: mixed file and directory ('$ARGV[0]' <-> '$ARGV[1]')\n" unless !-e $ARGV[1] || -f $ARGV[1];
+ ConvertFile($ARGV[0], $ARGV[1]);
+ exit;
+ }
+
+die "$0: mixed directory and file ('$ARGV[0]' <-> '$ARGV[1]')\n" unless !-e $ARGV[1] || -d $ARGV[1];
+
+$PICDIR = File::Spec->rel2abs($ARGV[0]);
+$MPGDIR = File::Spec->rel2abs($ARGV[1]);
+
+# Convert pictures to mpegs:
+
+chdir($PICDIR) || die "$PICDIR: $!\n";
+
+@Pictures = `find -type f`;
+chomp(@Pictures);
+
+for $pic (@Pictures) {
+ my $mpg = "$MPGDIR/$pic.mpg";
+ if ($Force || !-e $mpg || -M $mpg > -M $pic) {
+ (my $dir = $mpg) =~ s/\/[^\/]*$//;
+ mkpath($dir);
+ ConvertFile($pic, $mpg);
+ }
+ }
+
+# Remove mpegs without pictures:
+
+chdir($MPGDIR) || die "$MPGDIR: $!\n";
+
+@Mpegs = `find -type f`;
+chomp(@Mpegs);
+
+for $mpg (@Mpegs) {
+ my $pic = "$PICDIR/$mpg";
+ $pic =~ s/\.mpg$//;
+ if (!-e $pic) {
+ print "removing $mpg\n";
+ unlink($mpg);
+ }
+ }
+
+# Remove empty directories:
+
+chdir($MPGDIR) || die "$MPGDIR: $!\n";
+
+for ($i = 0; $i < 10; $i++) { # dirs might become empty when removing empty subdirs
+ @Dirs = `find -type d -empty`;
+ chomp(@Dirs);
+ last unless @Dirs;
+
+ for $dir (@Dirs) {
+ $dir = EscapeMeta($dir);
+ print "removing $dir\n";
+ !system("rm -rf $dir") || die "$dir: $!\n";
+ }
+ }
+
+# Actual file conversion:
+
+sub ConvertFile
+{
+ my ($Pict, $Mpeg) = @_;
+ (my $Type) = lc($Pict) =~ /\.([^\.]*)$/;
+ if (!defined $PNMCONV{$Type}) {
+ return if ($Ignore);
+ die "unknown file type '$Type': '$Pict'\n";
+ }
+ my ($w, $h) = imgsize($Pict);
+ print "image size is $w x $h\n" if ($Detailed);
+ my $Exif = ImageInfo($Pict);
+ my $Orientation = $$Exif{"Orientation"};
+ my ($Degrees) = $Orientation =~ /Rotate ([0-9]+) /;
+ my $Rotate = "-null";
+ $Rotate = "-cw" if $Degrees eq "90";
+ $Rotate = "-ccw" if $Degrees eq "270";
+ $Rotate = "-r180" if $Degrees eq "180";
+ print "orientation = '$Orientation' -> rotation = $Rotate\n" if ($Detailed);
+ ($w, $h) = ($h, $w) if ($Degrees eq "90" || $Degrees eq "270");
+ if ($w / $h <= $ScreenRatio) {
+ $w = $h * $ScreenRatio;
+ }
+ else {
+ $h = $w / $ScreenRatio;
+ }
+ my $ScaleW = $SW / $w * (100 - 2 * $OverscanX) / 100;
+ my $ScaleH = $SH / $h * (100 - 2 * $OverscanY) / 100;
+ $Pict = EscapeMeta($Pict);
+ $Mpeg = EscapeMeta($Mpeg);
+ print "$Pict -> $Mpeg $Rotate\n" if $ListFiles;
+ my $Cmd = "$PNMCONV{$Type} $Pict 2> /dev/null |"
+ . "pamflip $verbose1 $Rotate |"
+ . "pnmscale $verbose1 --xscale=$ScaleW --yscale=$ScaleH |"
+ . "pnmpad $verbose1 --black --width $SW --height $SH |"
+ . "ppmntsc $verbose1 $system1 |"
+ . "ppmtoy4m $verbose2 -F $framerate -I p -S 420mpeg2 |"
+ . "mpeg2enc $verbose2 -f 3 -b 12500 -a $aspect -q 1 -n $system2 -o $Mpeg";
+ !system($Cmd) || die "$Cmd: $!\n";
+ $Cmd = "touch -r $Pict $Mpeg";
+ !system($Cmd) || die "$Cmd: $!\n";
+}
+
+sub EscapeMeta
+{
+ my $META = ' !"#$%&\'()*;<>?[\\]`{|}~';
+ my $s = shift;
+ $s =~ s/([$META])/\\$1/g;
+ return $s;
+}