diff options
author | Klaus Schmidinger <vdr@tvdr.de> | 2011-08-14 13:50:26 +0200 |
---|---|---|
committer | Klaus Schmidinger <vdr@tvdr.de> | 2011-08-14 13:50:26 +0200 |
commit | c13d6e6070d895dd33f82e80b5d045cbb417bc6c (patch) | |
tree | c5b2a1cc93137e50c95da713504af997afe9a3f4 /PLUGINS/src/pictures/pic2mpg-sd | |
parent | 5e2f8e761343f72ed0c491c6b2caa64637a04f54 (diff) | |
download | vdr-c13d6e6070d895dd33f82e80b5d045cbb417bc6c.tar.gz vdr-c13d6e6070d895dd33f82e80b5d045cbb417bc6c.tar.bz2 |
The pic2mpg script of the 'pictures' plugin now generates HD images
Diffstat (limited to 'PLUGINS/src/pictures/pic2mpg-sd')
-rwxr-xr-x | PLUGINS/src/pictures/pic2mpg-sd | 193 |
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; +} |