#!/usr/local/bin/perl -w
#-----------------------------------------------------------------------------------------------
# X-View Maker by Lilia [2003/09/25]
#-----------------------------------------------------------------------------------------------
# 画像ファイル(とそのサムネイル)があるディレクトリに
# アルバムHTMLおよびスライドショーHTMLを生成するスクリプト
# * ローカル実行専用・要 Image::Size [http://search.cpan.org/author/RJRAY/Image-Size/]
# メモ..
#-----------------------------------------------------------------------------------------------
# 実行するとカレントディレクトリに以下のファイルが生成される
# ・index.html
# ・NNNN.html * 画像ファイル数 (例:0001.html 〜 0025.html)
# ・xview.ini
# ・xview.log
#
# 拡張設定ファイル xview.ini とログ xview.log についてのヒント
# とりあえず一度スクリプトを実行したのち、生成された xview.ini を編集して再実行
# するというのが簡単かつ正当な方法。
# xview.ini は実行時に読込まれ、その内容はスクリプト内の設定よりも優先される。
# ページのタイトルおよび一列あたりのサムネイルの個数についてはコメントを外して
# 設定すればOK。
# 画像のタイトル(キャプション)については、先にスクリプトを実行していた場合
# xview.log に画像ファイルのリストが出力されているので、それをコピー&ペースト
# して設定するといいかも。
# 画像ファイルの順番も設定として反映される。
#
# サムネイルの作成も行いたい場合には以下のものが必要になる
# ・Image::Thumbnail [http://search.cpan.org/author/LGODDARD/Image-Thumbnail/]
# ・Image::Magick または GD
# 環境が整っていてかつ必要であれば use Image::Thumbnail; 行のコメントを外して
# 有効にしておく。
# ただし既にサムネイルが存在している場合には作成しない。
# スクリプトはまず設定にもとづいてサムネイルを探し、見つけられなかった場合に
# 作成が許可されていれば、先に探した場所・ファイル名に合致するサムネイルを
# 作成する。
use strict;
use Cwd;
use File::Copy;
use Image::Size;
# use Image::Thumbnail; # サムネイルの作成も行う場合のみ
use vars qw(%Ini %Prt);
%Ini = (
Script => q[X-View Maker],
Ver => q[1.00c],
Sig => q[Lilia],
Dist => q[http://nursery.s8.xrea.com/],
# ユーザー設定..
#-----------------------------------------------------------------------------------------------
Title => '', # タイトル(空欄ならディレクトリ名がタイトルになる)
ImgExt => 'jpg|jpeg|gif|png', # 画像とみなす拡張子(大・小文字同一視)
ThmbDIR => 'th', # サムネイルのあるディレクトリのパス(カレントディレクトリなら「.」)
ThmbPre => 't_', # サムネイルとみなすファイルの接頭辞(「th_xxx.jpg」なら「th_」)
VMax => 5, # 一列に表示するサムネイルの個数
ThmbSize => 100, # サムネイルの長辺の長さ(まちまちでも一応の基準として)
Create => 0, # サムネイルが存在しなければ作成する(1:有効 / 0:無効)
Slideshow => 1, # スライドショー用のページを作成する(1:有効 / 0:無効)
#-- 以下はオプション(不要なら # でコメントアウト)
# ページ制作者を表すメタタグ
Auth => q{},
# ナビゲーション用のメタタグ
Metas => q{
},
# トップページ等へのリンクをつけたければタグで指定
GoLink => q{<< back},
# バナー等を挿入したければ設定
Insert => q{
- xrea ad banner -
}
# ..ここまで
#-----------------------------------------------------------------------------------------------
);
# デバッグ..
#-----------------------------------------------------------------------------------------------
# BEGIN {
# use CGI::Carp qw(carpout);
# open(ERR, ">>error.log") or
# die("Unable to open error.log: $!\n");
# carpout(\*ERR);
# }
# END { # 一応閉じる
# close(ERR);
# }
# ..ここまで
#-----------------------------------------------------------------------------------------------
print "now processing...\n\n";
&mk_album;
print "done!\n";
exit;
# サブルーチン..
#-----------------------------------------------------------------------------------------------
sub mk_album {
# 末尾に「/」を付けて設定されていたら消しておく
$Ini{ThmbDIR} =~ s|/$||;
# 拡張設定ファイルとログファイル
my $ini_file = 'xview.ini';
my $log_file = 'xview.log'; # ログは不要なら空欄可
# 画像ディレクトリを開きファイルのリストを取得
my @img_files;
my $thmb_pre = ($Ini{ThmbPre} eq '') ? '.' : $Ini{ThmbPre}; # 接頭辞なしの場合は $thmb_pre がマッチしないように工夫
opendir(DIR, '.') or
die("Unable to opendir .: $!\n");
foreach(grep(!/^\./, readdir(DIR))) {
next unless(-f && m|[^\./ ]|); # 無効なファイルを除外
next unless(/^(?!\Q$thmb_pre\E).+\.(?:(?i)$Ini{ImgExt})$/o); # 画像以外のファイルとサムネイルは除外
push @img_files, $_ if(-f); # 有効なファイルのみ配列に格納
}
closedir(DIR);
((my $all_files = @img_files) >= 1) or print("No images, aborted.\n"), exit; # 画像がなければ処理中止(以後 $#img_files >= 0)
# いったんソート(名前順)
@img_files = sort {lc($a) cmp lc($b)} @img_files if($#img_files);
# タイトルが付いてなければディレクトリ名をタイトルとしておく
($Ini{Title} = cwd || getcwd || '(Title)') =~ s|^.*/(.+)$|$1| if($Ini{Title} eq '');
# スライドショーの有無
my $slideshow = ($Ini{Slideshow} && $#img_files) ? 1 : 0;
# 設定の下準備
$Prt{Title1} = ($Prt{Title2} = $Ini{Title});
$Prt{VMax} = $Ini{VMax};
$Prt{$_} = '' foreach(@img_files); # 画像タイトルは空白として定義しておく
# 設定ファイルを読込む
if((-e $ini_file) && open(IN, $ini_file)) {
while() {
chomp;
next if(!$_ || /^#/ || !/\w/);
my($name,$value) = split /\t/;
$value = '' unless(defined $value);
$value = sprintf('%04d', $.) . "\t$value" if($name !~ /Title1|Title2|VMax/); # 画像タイトルにはソート用に番号を振っておく
$Prt{$name} = $value;
}
close(IN);
# 設定ファイルでの出現順に画像をソート
@img_files = sort {$Prt{$a} cmp $Prt{$b}} @img_files if($#img_files);
$Prt{$_} =~ s/^\d+?\t// foreach(@img_files); # ソート用に振った番号を削除
} else { # なければ生成
open(INI, ">$ini_file") or
die("Unable to open $ini_file: $!\n");
print INI <<"_TXT_";
#-----------------------------------------------------------------------------------------------
# $Ini{Script} 用 簡易設定ファイル
#-----------------------------------------------------------------------------------------------
# * タブで区切って設定する
# * 空行と「#」で始まる行は無視
#-- Title1 〜 内のタイトル
# Title1 $Prt{Title1}
#-- Title2 ページ上部に表\示するタイトル
# Title2 $Prt{Title2}
#-- VMax 一列に表\示するサムネイルの個数
# VMax $Prt{VMax}
#-- filename.jpg 画像のタイトル
_TXT_
close(INI);
}
# ログファイルを出力(上書き)
if($log_file) {
open(LOG, ">$log_file") or
die("Unable to open $log_file: $!\n");
print LOG "Title1\t$Prt{Title1}\nTitle2\t$Prt{Title2}\nVMax\t$Prt{VMax}\n* Slideshow\t$slideshow\n\n";
print LOG "$_@{[($Prt{$_} && $Prt{$_} ne '') ? qq(\t$Prt{$_}) : '']}\n" foreach(@img_files);
close(LOG);
}
# サムネイルの作成(必要なら)
if($Ini{Create} && (defined %Image::Thumbnail::)) {
my $create_log = '';
unless(-d $Ini{ThmbDIR}) { # サムネイルを保存するディレクトリがなければ作成
mkdir($Ini{ThmbDIR}, 0755) or
die("Unable to mkdir $Ini{ThmbDIR}: $!\n");
$create_log.= "\n$Ini{ThmbDIR}/";
}
my $stretch_copy = 0; # サムネイルの設定サイズよりも小さい画像の扱い { 0:何もしない / 1:拡大して作成 / 2:コピーしてリネーム }
foreach(@img_files) {
local $_ = $_; # 以降の処理で $_ の値が変更されてしまうので(Image::Thumbnail の問題)
my $thumbnail = "$Ini{ThmbDIR}/$Ini{ThmbPre}$_";
next if(-e $thumbnail); # 既に存在していれば作成しない
my($x_wide,$x_high) = imgsize($_);
if($Ini{ThmbSize} >= $x_wide && $Ini{ThmbSize} >= $x_high) { # 小さい画像
next unless($stretch_copy);
if($stretch_copy == 2) {
copy($_ => $thumbnail) or
die("Unable to copy $_ to $thumbnail: $!\n");
$create_log.= "\n$thumbnail (copied)";
next;
}
}
my $t = Image::Thumbnail->new(
size => $Ini{ThmbSize}, # 長辺の長さ
create => 1,
inputpath => $_,
outputpath => $thumbnail,
quality => 80, # 0〜100
);
(defined $t) or
die("Error in creating thumbnail: $!\n");
$create_log.= "\n$thumbnail";
}
if($log_file && $create_log) { # ログファイルに追記
open(LOG, ">>$log_file") or
die("Unable to open $log_file: $!\n");
print LOG "$create_log\n";
close(LOG);
}
}
# ヘッダ部分
my $header = qq`
@{[$Ini{Auth} ? "\n$Ini{Auth}" : '']}
`;
# HTML出力開始
open(OUT, '>index.html') or
die("Unable to open index.html: $!\n");
print OUT <<"_HTML_";
$header$Ini{Metas}
$Prt{Title1}
@{[
($Ini{GoLink} || $slideshow) ? "\n" : ''
]}@{[
$Ini{GoLink} ? $Ini{GoLink} : ''
]}@{[
($Ini{GoLink} && $slideshow) ? ' ' : ''
]}@{[
$slideshow ? qq(#slideshow) : ''
]}@{[
($Ini{GoLink} || $slideshow) ? "
\n" : ''
]}
$Prt{Title2}
_HTML_
my($img_remain,$file_nr,$h_nr) = (1,1,0);
my $title_max = int($Ini{ThmbSize} / 8); # 調整可
while(@img_files) {
last if($img_remain <= 0); # 表示する画像がなくなったらやめる
my $v_start = $Prt{VMax} * $h_nr; # 横にならぶ個数 x 現在何列目か (6x0, 6x1, 6x2, ...)
my $v_end = $v_start + $Prt{VMax} - 1; # 0〜5, 6〜11, 12〜17, ... というふうにしたいので -1
$v_end = $#img_files if($v_end > $#img_files);
print OUT "\n";
foreach(@img_files[$v_start .. $v_end]) { # 1列分ずつ出力
last unless($_);
my($img_title,$long_ok) = ($Prt{$_} ne '') ? ($Prt{$_},1) : ($_,0);
$img_title =~ s/&/&/g; $img_title =~ s/"/"/g;
$img_title =~ s/</g; $img_title =~ s/>/>/g; # 一応
(my $p_title = $img_title);
$p_title =~ s/^(.{$title_max}).{4,}$/$1.../o unless($long_ok); # LongNameFile...
my $img_size = commify(-s);
my($img_src,$resize) = (-e "$Ini{ThmbDIR}/$Ini{ThmbPre}$_") ? ("$Ini{ThmbDIR}/$Ini{ThmbPre}$_",'') : ($_,'');
my($t_wide,$t_high) = imgsize($img_src);
$resize = '' if($Ini{ThmbSize} >= $t_wide && $Ini{ThmbSize} >= $t_high); # 設定サイズより小さい画像はそのまま
if($resize) { # 長辺を $Ini{ThmbSize} にしてリサイズ表示する
($t_wide,$t_high) = ($t_wide > $t_high)
? ($Ini{ThmbSize},int($t_high * $Ini{ThmbSize} / $t_wide))
: (int($t_wide * $Ini{ThmbSize} / $t_high),$Ini{ThmbSize});
}
$img_src =~ s|([^\w\-\./])|'%' . unpack('H2', $1)|eg; # URIエスケープ(Netscape用:特殊ファイル名対応)*うざいのでここだけ
my $this = $slideshow ? sprintf('%04d', $file_nr) : 0;
if($slideshow) { # 個別のスライドショー用HTMLを生成
my($img_wide,$img_high) = imgsize($_);
my($prev,$next) = (sprintf('%04d', $file_nr - 1),sprintf('%04d', $file_nr + 1));
my($prev_navi,$prev_anchor) = ($prev > 0)
? (qq`\n`,
qq`<< prev `)
: ('','');
my($next_navi,$next_anchor) = ($next <= $all_files)
? (qq`\n`,
qq`next >>`)
: ('','');
open(SLID, ">$this.html") or
die("Unable to open $this.html: $!\n");
print SLID <<"_PAGE_";
$header
$prev_navi$next_navi
$file_nr/$all_files $img_title (${img_wide}x$img_high pixels, $img_size bytes)
_PAGE_
close(SLID);
}
# アルバムHTMLのサムネイル表示
my $slide_link = $this ? qq(.) : '';
print OUT <<"_IMG_";
$resize
$p_title $img_size bytes$slide_link
|
_IMG_
$file_nr++;
}
print OUT "
\n\n";
$img_remain = $#img_files - $v_end; # 残り画像数 = 全画像数 - 表示した分
$h_nr++;
}
print OUT <<"_HTML_";
@{[$Ini{Insert} ? $Ini{Insert} : '']}