mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
The pic2mpg script of the 'pictures' plugin now generates HD images
This commit is contained in:
parent
5e2f8e7613
commit
c13d6e6070
@ -2153,6 +2153,7 @@ Andr
|
||||
recording if Setup.UseDolbyDigital is true
|
||||
for suggesting that the primary device should only be avoided for recording if
|
||||
it is an old SD full featured card
|
||||
for his support in using convert/ffmpeg in the pic2mpg script of the 'pictures' plugin
|
||||
|
||||
Jürgen Schilling <juergen_schilling@web.de>
|
||||
for reporting that color buttons were displayed in the recording info menu if it
|
||||
|
5
HISTORY
5
HISTORY
@ -6650,7 +6650,7 @@ Video Disk Recorder Revision History
|
||||
- Added support for "content identifier descriptor" and "default authority descriptor"
|
||||
to 'libsi' (thanks to Dave Pickles).
|
||||
|
||||
2011-08-13: Version 1.7.20
|
||||
2011-08-14: Version 1.7.20
|
||||
|
||||
- Added some missing 'const' to tChannelID (reported by Sundararaj Reel).
|
||||
- The isnumber() function now checks the given pointer for NULL (thanks to Holger
|
||||
@ -6683,3 +6683,6 @@ Video Disk Recorder Revision History
|
||||
by a call to cIndexFile::GetLength() (suggested by Christoph Haubrich).
|
||||
- Fixed some crashes in subtitle display (thanks to Rolf Ahrenberg).
|
||||
- Made DELETENULL() thread safe (reported by Rolf Ahrenberg).
|
||||
- The pic2mpg script of the 'pictures' plugin now generates HD images (thanks to
|
||||
Andre Weidemann for his support in using convert/ffmpeg). The old SD version is
|
||||
still available as pic2mpg-sd.
|
||||
|
@ -49,3 +49,9 @@ VDR Plugin 'pictures' Revision History
|
||||
2011-07-23:
|
||||
|
||||
- Now rotating images according to the EXIF 'Orientation' parameter.
|
||||
|
||||
2011-08-14:
|
||||
|
||||
- The pic2mpg script now generates HD images (thanks to Andre Weidemann for his
|
||||
support in using convert/ffmpeg). The old SD version is still available as
|
||||
pic2mpg-sd.
|
||||
|
@ -7,63 +7,45 @@
|
||||
#
|
||||
# See the README file for copyright information and how to reach the author.
|
||||
#
|
||||
# $Id: pic2mpg 2.1 2011/07/23 14:23:59 kls Exp $
|
||||
|
||||
## TODO implement HDTV (1920 x 1080)
|
||||
# $Id: pic2mpg 2.2 2011/08/14 13:34:15 kls Exp $
|
||||
|
||||
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
|
||||
Options: -f Force conversion
|
||||
-h print Help
|
||||
-i Ignore unknown file types
|
||||
-n NTSC (default is PAL)
|
||||
-s size Screen size (WIDTHxHEIGHT, default is 1920x1080)
|
||||
-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;
|
||||
getopts("fhs:v:") || die $Usage;
|
||||
|
||||
die $Usage if $opt_h;
|
||||
|
||||
$Aspect = $opt_a;
|
||||
$Force = $opt_f;
|
||||
$Ignore = $opt_i;
|
||||
$NTSC = $opt_n;
|
||||
$Size = $opt_s || "1920x1080";
|
||||
$Verbose = $opt_v;
|
||||
$OverscanX = $opt_x;
|
||||
$OverscanY = $opt_y;
|
||||
|
||||
$ListFiles = $Verbose >= 1;
|
||||
$Detailed = $Verbose >= 2;
|
||||
|
||||
# Screen size:
|
||||
# Supported picture types:
|
||||
|
||||
$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",
|
||||
%PICTYPES = (
|
||||
bmp => 1,
|
||||
gif => 1,
|
||||
jpeg => 1,
|
||||
jpg => 1,
|
||||
png => 1,
|
||||
pnm => 1,
|
||||
tif => 1,
|
||||
tiff => 1,
|
||||
);
|
||||
|
||||
# Command options:
|
||||
@ -72,13 +54,6 @@ 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]) {
|
||||
@ -96,7 +71,7 @@ $MPGDIR = File::Spec->rel2abs($ARGV[1]);
|
||||
|
||||
chdir($PICDIR) || die "$PICDIR: $!\n";
|
||||
|
||||
@Pictures = `find -type f`;
|
||||
@Pictures = `find -type f | sort`;
|
||||
chomp(@Pictures);
|
||||
|
||||
for $pic (@Pictures) {
|
||||
@ -146,39 +121,18 @@ 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);
|
||||
return if (!defined $PICTYPES{$Type});
|
||||
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";
|
||||
my $Rotate = $Degrees ? "-rotate $Degrees" : "";
|
||||
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";
|
||||
my $Cmd = "convert $Pict -background '#000000' $Rotate -resize $Size -gravity center -extent $Size ppm:- | "
|
||||
. "ffmpeg -f image2pipe -vcodec ppm -i pipe:0 -an -vcodec libx264 -vpre baseline -s $Size -qscale 2 -f mpegts -y $Mpeg "
|
||||
. ($Detailed ? "" : "2>/dev/null");
|
||||
!system($Cmd) || die "$Cmd: $!\n";
|
||||
$Cmd = "touch -r $Pict $Mpeg";
|
||||
!system($Cmd) || die "$Cmd: $!\n";
|
||||
|
193
PLUGINS/src/pictures/pic2mpg-sd
Executable file
193
PLUGINS/src/pictures/pic2mpg-sd
Executable file
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user