Album

 view release on metacpan or  search on metacpan

script/album  view on Meta::CPAN

        if ( $doing ) {         # uudecoding...
            if ( /^Xend/ ) {
                close($out);
                $doing = 0;	# Done
		next;
            }
            # Select lines to process.
            next if /[a-z]/;
	    next unless /^X(.*)/s;
	    $_ = $1;
            next unless int((((ord() - 32) & 077) + 2) / 3)
              == int(length() / 4);
            # Decode.
            print $out unpack("u",$_);
            next;
        }

        # Otherwise, search for the uudecode 'begin' line.
        if ( /^Xbegin\s+\d+\s+(.+)$/ ) {
	    next if !$clobber && -s d_icons($1);
	    print STDERR ("Creating icons: ") if $verbose > 1 && !defined($name);
	    $did++;
            $name = d_icons($1);
	    print STDERR ("$1 ") if $verbose > 1;
            open($out, ">", $name);
	    binmode($out);
            $doing = 1;         # Doing
            next;
        }
    }
    print STDERR ("\n") if $verbose > 1;
    if ( $doing ) {
        die("Error in DATA: still processing $name\n");
        unlink($name);
    }
}

################ Style Sheets ################

################ End Style Sheets ################

sub detab {
    my ($line) = @_;
    return $line unless $line;
    my $orig = $line;
    my (@l) = split(/\t/, $line, -1);

    # Replace tabs with blanks, retaining layout

    $line = shift(@l);
    $line .= " " x (8-length($line)%8) . shift(@l) while @l;

    $line;
}

################ Copying: plain files ################

sub copy {
    my ($orig, $new, $time) = @_;

    $time = (stat($orig))[9] unless defined($time);

    my $in = do { local *F; *F };
    open($in, "<", $orig) or die("$orig: $!\n");
    binmode($in);

    my $out = do { local *F; *F };
    open($out, ">", $new) or die("$new: $!\n");
    binmode($out);

    my $buf;

    for (;;) {
	my ($r, $w, $t);
	defined($r = sysread($in, $buf, 10240))
	  or die("$orig: $!\n");
	last unless $r;
	for ( $w = 0; $w < $r; $w += $t ) {
	    $t = syswrite($out, $buf, $r - $w, $w)
	      or die("$new: $!\n");
	}
    }
    close($in);
    close($out) or die("$new: $!\n");
    utime($time, $time, $new);
}

################ Copying: MPG files ################

sub copy_mpg {
    my ($orig, $new, $time, $rotate, $mirror) = @_;
    $time = (stat($orig))[9] unless defined($time);

    # I'm not sure what this does. The resultant file is about 10% of
    # the original, without missing something...
    my $cmd = "$prog_mencoder -of mpeg -oac copy -ovc ".
	($rotate ? "lavc -lavcopts vcodec=mpeg1video -vf rotate=".int($rotate/90)." " : "copy ") .
	  squote($orig) . " -o ". squote($new);
    warn("\n+ $cmd\n") if $verbose > 2;

    my $res = `$cmd 2>&1`;
    die("${res}Aborted\n") if $?;

    utime($time, $time, $new);
}

sub still {
    my ($el) = @_;

    my $new = d_large($el->assoc_name);
    my $still = new Image::Magick;
    if ( $prog_mplayer ) {
	my $tmp = "00000001.jpg";
	my $tmp2 = "00000002.jpg";
	if ( -e $tmp ) {
	    die("ERROR: mplayer needs to create a file $tmp, but it already exists!\n");
	}
	# Sometimes, -frames 1 does not produce anything. Need -frames 2.
	my $cmd = "$prog_mplayer -really-quiet -nojoystick -nolirc -nosound -frames 2 -vo jpeg " .
	  squote(d_large($el->dest_name));
	warn("\n+ $cmd\n") if $verbose > 2;
	my $t = `$cmd 2>&1`;
	warn("$t\n") unless -s $tmp;
	$still->Read($tmp);
	unlink($tmp, $tmp2);
    }
    else {
	# This may take minutes.
	$still->Read(d_large($el->dest_name)."[0]");
    }

    # Get still dimensions.
    my ($hs, $ws) = $still->Get(qw(height width));
    unless ( $hs && $ws ) {
	$still->Read(d_icons("movie.jpg"));
	$still->Write($new);
	return $still;
    }
    # Scale to 640x480 if needed.
    my $r = $hs > $ws ? 640 / $hs : 640 / $ws;
    if ( abs($r - 1) > 0.05 ) {
	$still->Resize(width => $r*$ws, height => $r*$hs);
	($hs, $ws) = $still->Get(qw(height width));
    }

    # Create black canvas.
    my $canvas = new Image::Magick;
    $canvas->Set(size => ($ws+240).'x'.($hs+180));
    $canvas->ReadImage('xc:black');
    my ($hc, $wc) = $canvas->Get(qw(height width));

    # Place the still on top of it.
    # Center image
    $canvas->Composite(image => $still, compose => 'Atop', x => 120, 'y' => 90);
    # Bottom slice.
    $canvas->Composite(image => $still, compose => 'Atop', x => 120, 'y' => $hs+135);
    # Top slice. Cannot place at negative offsets, so crop the still first.
    $still->Crop(width => $ws, height => 45, x => 0, 'y' => $hs-45);
    $canvas->Composite(image => $still, compose => 'Atop', x => 120, 'y' => 0);
    undef $still;

    # Drill spocket holes.
    my $hole = new Image::Magick;
    $hole->Set(size => '60x40');
    $hole->ReadImage("xc:grey90");
    $hole->Draw(primitive => 'polygon', fill => "black",
		points => " 0,0   5,0   0,5");
    $hole->Draw(primitive => 'polygon', fill => "black",
		points => "60,0  55,0  60,5");
    $hole->Draw(primitive => 'polygon', fill => "black",
		points => "60,40 55,40 60,35");
    $hole->Draw(primitive => 'polygon', fill => "black",
		points => " 0,40  5,40  0,35");

    for ( my $v = 0; $v < $hc;  $v += 80 ) {
	for my $h ( 30, $wc-90 ) {
	    $canvas->Composite(image => $hole, compose => 'Atop',
			    geometry => "+$h+$v");
	}
    }

    $canvas->Write($new);
    my $time = $el->timestamp;
    utime($time, $time, $new);
    $canvas;
}

################ Copying: Voice files ################

sub copy_voice {
    my ($orig, $new, $time) = @_;
    $time = (stat($orig))[9] unless defined($time);
    $orig =~ s/\.\w+$/.mpg/;
    return if -s $new;
    return unless $prog_mplayer;

    # This will produce an MP2 file. Good enough for now...
    my $cmd = "$prog_mplayer -nojoystick -nolirc -vo null ".
      "-dumpaudio -dumpfile " . squote($new) . " " . squote($orig);
    warn("\n+ $cmd\n") if $trace;
    my $res = `$cmd 2>&1`;
    die("${res}Aborted\n") if $?;
    die("${res}Aborted\n") unless -s $new;

    utime($time, $time, $new);
}

################ Index Icon Maintenance ################

sub create_master_index {
    my $index = d_dest("index.html");
    return if -e $index;
    update_if_needed($index,
		     process_fmt($format_for{main},
				 title    => html($album_title),
				 css      => css_for("main"),
				 version  => $my_version,
				 link     => ixname(0),
				));
}

sub create_index_icon {
    return unless $icon;
    print STDERR ("Creating index icon\n") if $verbose > 1;
    unless ( indexicon() ) {
	print STDERR ("(Index icon not modified)\n") if $verbose > 1;
    }
}

sub indexicon {
    my @imgs;
    for ( my $i = 0; $i < $index_rows*$index_columns; $i++ ) {
	next if $i >= $num_entries;
	my $el = $filelist->byseq($i+1);
	my $file = $el->dest_name;
	my $img;
	if ( $el->type == T_REF ) {
	    $img = $el->assoc_name;
	}
	else {
	    $img = $el->type == T_MPG ? $el->assoc_name : $file;
	    $img = d_index($img);
	}
	push(@imgs, $img);
    }

    my $iconfile = "icon.jpg";
    my $ii = cache_entry(" indexicon ");
    if ( -f $iconfile && $ii && $ii->dest_name eq "@imgs" ) {
	return 0;
    }
    my $el = new ImageInfo($iconfile);

script/album  view on Meta::CPAN

my @std_fields;
my @exif_fields;
my $exif_rot;

INIT {
    @std_fields  = qw(type seq next prev hidden
		      dest_name orig_name assoc_name
		      timestamp file_size medium_size
		      tag description annotation
		      rotation mirror);

    @exif_fields = qw(DateTime DateTimeOriginal ExifImageLength ExifImageWidth
		      ExposureMode ExposureProgram ExposureTime
		      FNumber Flash FocalLength FocalLengthIn35mmFormat
		      FocusMode ISOSpeedRatings
		      ImageDescription Make Model
		      MeteringMode SceneCaptureType Orientation
		      CreateDate MediaCreateDate TimeZone
		      WhiteBalance
		      height width file_ext);

    $exif_rot = { top_left   => [   0, ''  ],    # 1: no corr. needed
		  top_right  => [   0, 'v' ],    # 2: flop (V)
		  bot_right  => [ 180, ''  ],    # 3: 180
		  bot_left   => [   0, 'h' ],    # 4: flip (H)
		  left_top   => [  90, 'h' ],    # 5: flip 90
		  right_top  => [  90, ''  ],    # 6: 90
		  right_bot  => [  90, 'v' ],    # 7: flop 90
		  left_bot   => [ 270, ''  ],    # 8: 270
		  'Rotate 270 CW' => [ 270, ''  ],    # 270 CW =  90 CCW
		  'Rotate 180'    => [ 180, ''  ],    # 180 CW = 180 CCW
		  'Rotate 90 CW'  => [  90, ''  ],    #  90 CW = 270 CCW
		};
}

my $largepat;
sub basename_nolarge {
    my ($f) = @_;
    unless ( $largepat ) {
	$largepat = quotemeta(::d_large());
	$largepat = qr;^$largepat[/\\];;
    }
    $f =~ s;$largepat;;;
    $f;
}

sub new {
    my ($pkg, $file) = @_;
    $pkg = ref($pkg) if ref($pkg);

    my $self = { $file ?
		 (orig_name    => $file,
		  dest_name    => basename_nolarge($file)) : (),
		 description  => "",
		 annotation   => [],
		 tag	      => "",
		 hidden       => 0,
	       };

    if ( $file && -f $file ) {
	my @st = stat(_);
	my $ii = ::cache_entry($file);
	if ( $ii  ){
	    $self = $ii;
	    delete($self->{$_}) foreach grep { /^_/ } keys(%$self);
	}

	# Else, get image info.
	else {
#	    my $ii = Image::Info::image_info($file);
	    my $ii = Image::ExifTool->new->ImageInfo($file);
	    $self->{file_size} = $st[7];
	    $self->{timestamp} = $st[9];
	    unless ( exists($ii->{error}) ) {
		for my $key ( @exif_fields ) {
		    my $val = $ii->{$key};
		    next unless defined $val;
		    if ( $key eq "Orientation" ) {
			($self->{rotation}, $self->{mirror}) =
			  @{$exif_rot->{$val}}
			    if exists $exif_rot->{$val};
		    }
		    else {
			$val = $val->as_float
			  if UNIVERSAL::can($val,"as_float");
			$self->{$key} = $val;
		    }
		}
		::cache_entry($file, $self);
	    }
	}
	# Actualize.
	$self->{file_size} = $st[7];
	$self->{timestamp} = $st[9];
    }

    bless($self, $pkg);
}

INIT {
    no strict 'refs';
    for my $sub ( @std_fields, @exif_fields ) {
	$sub = "_".$sub if $sub eq "rotation";
	*{"ImageInfo::$sub"} = sub {
	    my ($self, $value) = @_;
	    $self->{$sub} = $value if defined($value);
	    $self->{$sub};
	};
    }
}

sub xDateTime {
    my ( $self ) = @_;
    my $skew = $skew;
    my $dt = $self->DateTimeOriginal || $self->CreateDate || $self->MediaCreateDate || $self->DateTime;

    if ( $self->TimeZone ) {
	my ( $m, $h, $min ) = $self->TimeZone =~ /^([-+])(\d+):(\d+)/;
	$min += 60 * $h;
	$min = -$min if $m eq "-";
	$skew += $min * 60;



( run in 2.030 seconds using v1.01-cache-2.11-cpan-0b5f733616e )