#!/usr/bin/env ruby1.8
#
#= dcmodel 用お絵描きサムネイル作成スクリプト
#
#Authors :: Yukiko YAMADA, Yasuhiro MORIKAWA, Shin-ichi TAKEHIRO
#Version :: $Id: dcmodel-thum.rb,v 1.31 2007/05/22 05:13:14 morikawa Exp $
#Source  :: $Source: /GFD_Dennou_Club/ftp/arch/dcmodel/cvsroot/dcmodel-tools/dcmodel-thum.rb,v $
#
#== Overview
#
#実験結果 (主に dcmodel のモデル群によって得られた結果を描画したもの)
#を手っ取り早くサムネイル化して表示するための
#クラスライブラリです。
#
#NetCDF などの流体データから画像を作成する作業に関しては別途
#行う必要があります。このクラスライブラリはあくまで、HTML を記述する
#(特に TABLE タグ等を記述する) 労力を低減することを目的としています。
#
#このファイル自体は、クラスライブラリ本体に加え、
#クラスを用いたサンプルスクリプトを出力するためのメソッドも記載
#されています。使い方に関しては Usage を参照ください。
#
#
#= Operation Environment
#
#本プログラムは、ruby 1.8.2 (2005-01-10) [i386-linux] での
#動作を確認しています。
#
#なお、ruby 1.6.7 (2002-03-19) [i386-linux] でならば、
#pathname.rb を RUBYPATH の通ったところに置けば動作します。
#
#
#== Usage
#
#まず、画像ファイル置き場として figdir を、サムネイル作成の
#ための情報置き場として thum-src ディレクトリを作成します。
#そして thum-src ディレクトリへ移動した後、このスクリプト本体
#を実行してください。
#
#  $ mkdir figdir thum-src
#  $ cd thum-src
#  $ ruby dcmodel-thum.rb
#
#すると、サンプルとなる Ruby スクリプトが出力されます。
#
#次にそのスクリプトを実行します。
#
#  $ ruby dcmodel-thum-make.rb
#
#すると、../sample_thum.htm などのようなファイルが生成されるはずです。
#そのファイルにチュートリアルが載っているので、これより以降の
#詳しい手順はそちらを参照してください。
#同様に sample_thum.txt というファイルも作成れます。
#そちらはサムネイルの個々の画像用のコメント等を記述するファイルです。
#
#大雑把な流れは以下のようになります。
#
#* dcmodel-thum.rb を実行して dcmodel-thum-make.rb を作成。
#* dcmodel-thum-make.rb を編集。(主に、サムネイル HTML のスタイルなどを設定)
#* sample_thum.txt を編集
#* dcmodel-thum-make.rb を再度実行
#
#なお、生成された Ruby スクリプトは本スクリプトに依存おり、
#生成される際に絶対パスで本スクリプトを指定するようになります。
#本スクリプトの移動や他のホストでの利用の際には注意しましょう。
#
#
#== Desctiption
#
#このプログラムの内部仕様に関しては、この Ruby スクリプトに RDoc を
#使うと見やすいドキュメントが生成されるでしょう。
#
#   $ rdoc --op doc --title DCModelThumbnail --charset euc-jp --inline-source --line-numbers --all dcmodel-thum.rb
#
#機能の拡張以外にも、外部から別箇呼べるメソッドもあるので、
#参考にしてください。
#
#== Future Plans
#
#* rttool を用いた DCModelThumbnail.rt2html を作成する。
#  * DCModelThumbnail.rd2html と同様にしてやってみる。
#* DCModelThumbnail.rd2html において、現在 rd2html-ext-lib の使用が
#  必須になっているが、ライブラリが存在するかサーチする必要があるだろう。
#  サーチして存在しない場合は、Warning を発して rd2html-lib を用いるか、
#  エラーを吐くようにする。
#
#== Notes
#
#今のところ、特になし。
#
#== Acknowledgements
#
#本プログラムは、
#dcphoto.pl <http://www.ep.sci.hokudai.ac.jp/~totera/official/program/dcphoto/>
#Ver 1.02 - 写真用 HTML作成スクリプト (Chihiro MITSUDA) を元に
#ruby で作成された ape-thum.rb (Yukiko YAMADA) を dcmodel の開発者が
#共有できるように改良したものです。そのオリジナルは
#<http://www.gfd-dennou.org/library/dcmodel/ClipBoard/dcmodel-thum_2005-04-06/> (Yukiko Yamada) です。
#これはちょうど本プログラムのバージョン 1.1 に対応します。
#
#== History
#
#These entries is generated by CVS automatically.
#So don't add new information manually.
#(But please adjust old log format to latest log format manually,
#if format gap between them causes).
#
#$Log: dcmodel-thum.rb,v $
#Revision 1.31  2007/05/22 05:13:14  morikawa
#* Documents are modified again.
#
#* ドキュメントの再度の修正.
#
#Revision 1.30  2007/05/22 05:11:19  morikawa
#* Documents are modified.
#
#* ドキュメントの修正.
#
#Revision 1.29  2007/05/22 05:00:31  morikawa
#* Documents are modified.
#* Hyperlinks with RD label between header, thumbnail, footer are available.
#
#* ドキュメントの修正.
#* RD ラベルに対するハイパーリンクをヘッダ, サムネイル, フッタ間で
#  可能にする.
#
#Revision 1.28  2006/02/11 19:48:19  morikawa
#* A misprint of tutorial is modified.
#
#* チュートリアルの誤植を修正.
#
#Revision 1.27  2006/02/11 17:25:14  morikawa
#* Messages can be added to footer.
#
#* フッターにメッセージを追加できるよう修正.
#
#Revision 1.26  2006/02/11 13:49:13  morikawa
#* URL of web site of RD is modified.
#
#* RD に関する Web サイトの URL を修正.
#
#Revision 1.25  2006/02/11 13:39:48  morikawa
#* URL of dcmodel site is modified.
#* "blankfig" is added. This is a flag for nodisplay of file names.
#* A display of file names is controlled by giving the modifier "b".
#* In "dcmodel-thumb-make.rb", a format of comments is changed to
#  trailing comments.
#
#* dcmodel のページの URL を修正.
#* ファイル非表示用のフラグ blankfig を追加.
#* 修飾子に b を与えることで, そのファイル名の表示を抑止.
#* dcmodel-thumb-make.rb の各インスタンスに関するコメントの書式をトレイ
#  リングコメントに変更.
#
#Revision 1.24  2005/12/09 07:45:36  morikawa
#* If "DCModelThumbnail.convert_overwrite" is false, modified time of
#  files are checked too.
#
#* フラグ DCModelThumbnail.convert_overwrite のチェックの際,
#  ファイルの存在だけでなく, タイムスタンプでチェックするよう修正.
#
#Revision 1.23  2005/12/09 07:23:12  morikawa
#* "DCModelThumbnail.convert_overwrite" is added. If this variable is
#  false and converted files are exist, convert command is not executed.
#
#* convert コマンドが実行される, 既に出力先のファイルがある場合に上書きする
#  ためのフラグ DCModelThumbnail.convert_overwrite を追加.
#  これが false の場合, 出力先のファイルが存在する時は変換コマンドの
#  実行をスキップする.
#
#Revision 1.22  2005/12/07 14:57:31  yukiko
#* Fixed bug which cannot generate of thumbnail figures when the "thumb.headlimit" is specified
#
#* "thumb.headlimit" を指定すると convert 出来ないバグを修正
#
#Revision 1.21  2005/11/09 10:43:15  morikawa
#* If the "verbose" argument is nil in "DCModelThumbnail.create"
#  method, messages about generation of images for the thumbnail are
#  not outputted.
#
#* DCModelThumbnail.create メソッドの verbose に nil を与えた場合に,
#  サムネイル用画像生成メッセージも出力しないよう修正.
#
#Revision 1.20  2005/11/05 01:06:32  takepiro
#* Regular expression for extracting tailing suffix from the figure filenames modified.
#* 画像ファイルの拡張子を取りだす正規表現を変更した。
#
#Revision 1.19  2005/11/02 03:50:29  morikawa
#* When the label of the info file is "title" or "message",
#  images are not converted.
#
#* 情報ファイルのラベルが "title", "message" の場合には画像変換
#  しないよう修正.
#
#Revision 1.18  2005/11/02 00:59:59  takepiro
#* Cheking the status of thumnail generation process.
#* サムネイル画像生成プロセスステータスのチェックを追加.
#
#Revision 1.17  2005/11/01 09:31:00  morikawa
#* New instance variable "convert_cmd" is added to change "convert"
#  command by users.
#* The command for image conversion is checked.
#* Messages in process of conversion are decorated.
#* The SIGEN file for the directory for thumbnail images is created
#  automatically.
#* "Maintainer" in SIGEN file is specified to account name when
#  "gate-toroku-system" is not available.
#
#* convert コマンドをユーザレベルで変更できるよう新たなインスタンス
#  変数 convert_cmd を追加.
#* 画像変換ツールの有無をチェックする機能を追加.
#* 画像変換中のメッセージを装飾.
#* サムネイル画像置き場ディレクトリの SIGEN ファイルを作成するようにし
#  た.
#* gate システムからユーザ名を取得できない場合, アカウント名を SIGEN
#  ファイルに書き出すよう修正.
#
#Revision 1.16  2005/11/01 06:46:24  takepiro
#* Automatic generation of thumbnail figures implemented.
#* Each one page can be extracted as a thumbnail from each animation file, such as gif-anime.
#
#* サムネイル画像の自動生成機能を追加した。
#* アニメーションファイル(gif-anime 等)から 1 ページを取りだしてサムネイル化できるようにした。
#
#Revision 1.15  2005/10/31 02:41:34  morikawa
#* Methods "DCModelThumbnail.create", "DCModelThumbnail.create_sample_rb"
#  are moved up.
#
#* DCModelThumbnail.create メソッドと DCModelThumbnail.create_sample_rb
#  メソッドを上の方に移動する.
#
#Revision 1.14  2005/05/25 15:54:32  morikawa
#* Enable to specify whether to allow search of robots by
#  DCModelThumbnail.norobots .
#* Allow search of robots by default.
#* Add to tutorial about generation of SIGEN file.
#* Add to tutorial about search of robots.
#
#* HTML のロボット検索を許可するかどうか指定できるようにした。
#* デフォルトでロボット検索を許可するようにした。
#* SIGEN ファイル生成に関してチュートリアルにも記載した。
#* ロボット検索の指定に関してチュートリアルにも記載した。
#
#Revision 1.13  2005/05/15 20:21:51  morikawa
#* Use "ruby1.8" instead of "ruby" in dcmodel-thum-make.rb .
#  (This should be modified by modification before).
#
#Revision 1.12  2005/05/15 19:58:29  morikawa
#* Use "ruby1.8" instead of "ruby". (This program depends on
#  pathname.rb that is included ruby 1.8).
#
#Revision 1.11  2005/04/30 20:30:37  morikawa
#* Create SIGEN file automatically.
#
#Revision 1.10  2005/04/30 18:54:24  morikawa
#* Add directly css setting to DCModelThumbnail.html_header by
#  DCModelThumbnail.style .
#
#Revision 1.9  2005/04/30 18:18:02  morikawa
#* Modify DCModelThumbnail.info_get to get correct default value.
#
#Revision 1.8  2005/04/30 17:50:05  morikawa
#* Hard code "dcmodel-thum.rb" to @self_name. (Otherwise, not
#  "dcmodel-thum.rb" but executed file is wrote footer of HTML).
#
#Revision 1.7  2005/04/30 09:43:19  morikawa
#* In "info_get", when multi-line input, permit input ":".
#
#Revision 1.6  2005/04/30 09:07:14  morikawa
#* In "info_make", cause error if any image files are not found.
#
#Revision 1.5  2005/04/21 13:03:17  morikawa
#* Change comment of DCModelThumbnail.info_get format.
#
#Revision 1.4  2005/04/21 12:57:23  morikawa
#* Change log format.
#
#Revision 1.3  2005/04/21 09:24:06  morikawa
#* Add "Operation Environment"
#* Output detail sample messages.
#* In DCModelThumbnail.rd2html , modify to remove only "^=begin" and
#  "^=end"
#* Add Comment for sample rb script.
#* Output Help message when argument is given.
#
#Revision 1.2  2005/04/19 20:32:19  morikawa
#* Modify internal structure.
#* Revise for "rdoc" documentation format.
#* RD format context is supported.
#* Add various options in "infofile".
#* Use "keyword substitution" in CVS for version control.
#
#Revision 1.1  2005/04/19 19:54:23  morikawa
#* This script generate Thumbnail HTML for calculation result figures.
#  The author of the original is Yukiko Yamada. She rename her "ape-thum.rb"
#  to "dcmodel-thum.rb" for sharing by dcmodel developers and users.
#
##################################################

require 'date'
require 'etc'
require 'kconv'
require 'pathname'

##################################################

#
#== DCModelThumbnail
#
# 「dcmodel お絵描きサムネイル HTML 作成スクリプト」の作成用のクラス
#
class DCModelThumbnail

  #
  # 定数の設定
  #

  # CopyRight
  COPYRIGHT = "GFD Dennou Club"

  # 項目の区切り文字
  INFO_DELIMITER = ":"

  # 情報ファイルにおける、複数行の開始文字
  INFO_MULTI_START = "{"

  # 情報ファイルにおける、複数行の終了
  INFO_MULTI_STOP  = "}"

  # SIGEN ファイル作成時の情報を得るための gate コマンド
  GATE_USER_SHOW   = "/usr/local/bin/gate-user-show"

  # 公開本体置き場
  PUB_BIN_URL = "http://www.gfd-dennou.org/library/dcmodel/bin/dcmodel-thum.rb"

  # 公開ドキュメントの URL
  PUB_DOC_URL = "http://www.gfd-dennou.org/library/dcmodel/doc/dcmodel-tools/dcmodel-thum-rdoc"

  # 公開サンプルの URL
  PUB_SAMPLE_URL = "http://www.gfd-dennou.org/library/dcmodel/doc/dcmodel-tools/dcmodel-thum-sample"

  # CVSHOST
  CVS_HOST       = "www.gfd-dennou.org"

  # CVSROOT
  CVS_ROOT       = "/GFD_Dennou_Club/ftp/arch/dcmodel/cvsroot"

  # CVS のプロジェクト名
  CVS_PROJECT    = "dcmodel-tools"

  # バージョンナンバー (CVS により自動管理)
  VER = "$Revision: 1.31 $ : $Date: 2007/05/22 05:13:14 $"

  #
  # インスタンス変数群
  #

  # バージョン
  attr_reader   :version

  # copyright
  attr_accessor :copyright

  # 公開ドキュメントの URL
  attr_reader   :pub_doc_url

  # 公開サンプルの URL
  attr_reader   :pub_sample_url

  # 実行ファイルの basename
  attr_reader   :self_name

  # サンプル ruby スクリプト名
  attr_reader   :sub_rb_name

  # 作成されるサムネイルのファイル名 (拡張子除く)
  attr_accessor :index

  # 作成されるサムネイルの拡張子名
  attr_accessor :index_ext

  # 「情報ファイル (infofile)」のファイル名
  attr_accessor :infofile

  # 画像ファイルとして認識する拡張子
  attr_accessor :ext_list

  # headlimit に当てはまらないものは画像としては無視され、
  # 当てはまるものは「情報ファイル」において、接頭部分 headlimit が
  # 省略可能になる。
  attr_accessor :headlimit

  # ファイル名の非表示のフラグ
  attr_accessor :blankfig

  # 絵のあるディレクトリの名前。必ず存在していなければならない。
  attr_accessor :figdir

  # サムネイル画像を置くディレクトリ名。カレントディレクトリから 
  # "#{@thumbaildir}" の場所に指定される.
  attr_accessor :thumbnaildir

  # サムネイル画像の最後部名. 
  # サムネイル画像名は元画像の拡張子と置換された名前になる. 
  attr_accessor :thumbnailtail

  # サムネイル画像化する元画像のページ番号
  attr_accessor :thumbnailpage

  # convert コマンドおよびオプション. この後ろに画像サイズが 200x150
  # のような形式で指定される.
  attr_accessor :convert_cmd

  # convert コマンドが実行される際, 既に出力先のファイルがある場合に
  # 上書きするためのフラグ. これが false の場合, 出力先のファイルが
  # 存在し, 且つ元のファイルよりも新しい場合は変換を行わない.
  attr_accessor :convert_overwrite

  # スタイルシートファイル
  attr_accessor :css

  # スタイルシートを直接設定するためのもの
  # (css ファイルに書き込む情報を直接指定できる)
  attr_accessor :style

  # rd2 コマンドへのパス
  attr_accessor :rd2_path

  # rd2-ext-lib へのライブラリへのパス
  attr_accessor :rd2htmlextlib

  # SIGEN ファイル作成時の情報を得るための gate コマンド
  attr_accessor :gate_user_show

  # 画像ファイルサイズ (幅)
  attr_accessor :img_width

  # 画像ファイルサイズ (高さ)
  attr_accessor :img_height

  # 横にならべるファイル数
  attr_accessor :figtable_num

  # html の作成者情報  (デフォルトはユーザアカウント名が自動取得される)
  attr_accessor :html_author

  # html ヘッダのタイトル
  attr_accessor :title

  # 本体に書き出すメッセージ。サムネイルの部分よりも上に出力される。
  # この変数自体は Array オブジェクトで、その内部に String オブジェクトが
  # 格納される。
  attr_accessor :message

  # フッターとして書き出すメッセージ。サムネイルの部分よりも下に出力される。
  # この変数自体は Array オブジェクトで、その内部に String オブジェクトが
  # 格納される。
  attr_accessor :footer

  # テンポラリファイル置き場 (UNIX 系ならば変える必要なし)
  attr_accessor :tmp

  # SIGEN ファイルを作らない場合は false にセットする
  attr_accessor :mksigen

  # HTML のロボット検索を禁止する
  attr_accessor :norobots

  #
  # これを呼ぶことで、最低限必要な情報が生成される。
  # 最終的には DCModelThumbnail.create メソッドを呼ぶことで
  # ファイルが作成される。
  #
  def initialize()
    #
    # version
    #
    @version = VER

    #
    # copyright
    #
    @copyright = COPYRIGHT

    # 公開ドキュメントの URL
    @pub_doc_url = PUB_DOC_URL

    # 公開サンプルの URL
    @pub_sample_url = PUB_SAMPLE_URL

    # dcmodel-thum.rb 自身の名前
    # @self_name   = File.basename($0.to_s)
    @self_name   = "dcmodel-thum.rb"

    # サンプル ruby スクリプト名
    @sub_rb_name = "#{File.basename($0, ".*")}" + "-make.rb"

    # html の置き場・ファイル名・拡張子。カレントディレクトリから
    #
    #    "#{@index}#{index_ext}" 
    #
    #に置かれる。
    @index     = "../sample_thum"
    @index_ext = ".htm"

    # 絵のあるディレクトリ名。カレントディレクトリから 
    # "#{@figdir}" の場所を探査する。
    @figdir = "../figdir"

    # サムネイル画像を置くディレクトリ名。カレントディレクトリから 
    # "#{@thumbaildir}" の場所に指定される.
    @thumbnaildir = "../thumbdir"

    # サムネイル画像の最後部名. 
    # サムネイル画像名は元画像の拡張子と置換された名前になる. 
    @thumbnailtail = "_thumb.png"

    # サムネイル画像化する元画像のページ番号
    @thumbnailpage = "1"

    # convert コマンドおよびオプション。この後ろに画像サイズが 200x150
    # のような形式で指定される。
    @convert_cmd = "convert -depth 8 -geometry"

    # convert コマンドが実行される際, 既に出力先のファイルがある場合に
    # 上書きするためのフラグ. これが false の場合, 出力先のファイルが
    # 存在し, 且つ元のファイルよりも新しい場合は変換を行わない.
    @convert_overwrite = false

    # 情報ファイル, $PWD/${infofile}
    @infofile = File.basename(@index).chomp.strip + ".txt"

    # 画像ファイルとして認識する拡張子
    @ext_list = ["gif", "png", "jpg", "jpeg"]

    # 接頭子制限 @headlimit = "figure_head"。
    # これにより、@headlimit に当てはまらないものは無視される
    @headlimit = ""

    # ファイル名の非表示のフラグ
    @blankfig = false

    # スタイルシートファイル
#    @css    = "../dcmodel.css"  # for morikawa (I'm sorry...)
    @css    = "/GFD_Dennou_Club/ftp/arch/dcmodel/htmltools/dcmodel.css"

    # スタイルシートを直接設定するためのもの
    # (css ファイルに書き込む情報を直接指定できる)
    @style = nil

    # rd2 ファイルのパス
    @rd2_path = "/usr/bin/rd2"

    # rd2-ext-lib へのライブラリのパス
#    @rd2htmlextlib = ".."       # for morikawa (I'm sorry...)
    @rd2htmlextlib = "/GFD_Dennou_Club/ftp/arch/dcmodel/lib/ruby/1.8"

    # SIGEN ファイル作成時の情報を得るための gate コマンド
    @gate_user_show = GATE_USER_SHOW

    # テンポラリファイル置き場 (UNIX 系ならば変える必要なし)
    @tmp     = "/tmp"

    # SIGEN ファイルを作らない場合は false にセットする
    @mksigen = true

    # HTML のロボット検索を禁止する場合には true にセットする
    @norobots = false

    # 画像ファイルサイズ
    @img_width  = 200
    @img_height = 150

    # 横にならべるファイル数
    @figtable_num = 3

    # NAME, HREF タグ内のラベルナンバー
    @label_num = 0

    # ラベルナンバーと対応するヘッダ文字列のハッシュ
    @label_num_header_hash = {}

    # html の作成者情報 (ユーザアカウント名)
    @html_author = username_from_gid

    # html ヘッダタイトル
    @title  = "dcmodel-thum : 実験結果サムネイル簡易作成スクリプト"

    # フッター (サムネイルの部分よりも下にメッセージ)
    # 指定方法は message と同様です。
    @footer = Array.new

    # 本体 (サムネイルの部分よりも上にメッセージ)
    @message = Array.new
    @message << <<-EndOfTutorial
=begin
[((<地球流体電脳倶楽部|URL:http://www.gfd-dennou.org>))]
[((<dcmodel|URL:http://www.gfd-dennou.org/library/dcmodel>)) |
((<dcmodel-tools|URL:http://www.gfd-dennou.org/library/dcmodel/doc/dcmodel-tools/SIGEN.htm>))]
[((<#{@self_name}|URL:#{PUB_DOC_URL}>))]

= #{@title}

* ((<概要・利用・動作環境の概説>))
* ((<バージョン 1.1 (オリジナルやまだ由ツール) からの仕様変更>))
* ((<利用の手引き>))
* ((<画像の用意>))
* ((<#{@self_name} の用意>))
* ((<とりあえず実行>))
* ((<子スクリプトの実行>))
* ((<できたものを見てみる>))
* ((<スクリプトの編集 (入門編)>))
* ((<再度実行>))
* ((<「情報ファイル」の編集 (入門編)>))
* ((<もう一度実行>))
* ((<スクリプトの編集 (応用編)>))
* ((<「情報ファイル」の編集 (応用編)>))


== 概要・利用・動作環境の概説

((<#{@self_name} の rdoc マニュアル|URL:#{PUB_DOC_URL}>))

Overview と Operation Environment と Usage をさらっと読んだら戻ってきてね。

なお、以下の URL にはこの出力結果と同等のものが置いてあるはずです。

((<#{@self_name} の サンプル|URL:#{PUB_SAMPLE_URL}>))

== バージョン 1.1 (オリジナルやまだ由ツール) からの仕様変更

ここは、バージョン 1.2 以降から利用している人には不要です。
バージョン 1.1 のオリジナルのやまだ由ツールから利用している
方は、以下の変更点にご注意ください。

  * 「情報ファイル (infofile)」の書式
    * 画像名に拡張子を加えるようになった
    * 1.1 では <画像名> : <コメント> だったが、
      現在は <画像名> : <修飾子> : <コメント> になっている。
  * pathname.rb を利用するため、ruby 1.8 を利用するか、1.6 ならば
    実行の際に RUBYLIB のパスが通ったところに pathname.rb が必要
    である。


== 利用の手引き

=== #{@self_name} の入手の方法

((<#{@self_name} スクリプト本体|URL:#{PUB_BIN_URL}>)) をダウンロード
してください。もしくは cvsroot をもっている #{CVS_HOST} にログインが
可能であれば、cvs からも直接取得が可能です。

    $ CVS_RSH=ssh; export CVS_RSH
    $ cvs -d :ext:#{CVS_HOST}:#{CVS_ROOT} checkout #{CVS_PROJECT}

既に #{CVS_HOST} にログインした状態であれば、以下のコマンドのみで
取得可能です。

    $ cvs -d #{CVS_ROOT} checkout #{CVS_PROJECT}


== 画像の用意

サムネイル化しようとする画像を (({#{File.basename(@figdir)} })) という
ディレクトリに置いてください。現在、画像として認識されるのは、
(({ #{@ext_list.join(", ")}, #{@ext_list.join(", ").swapcase} }))
です。アニメーション gif にも一応対応していますが, サムネイル化する
ページ番号は全画像共通にしか設定できません. 

他の形式の画像を認識させたい場合は ((<スクリプトの編集 (入門編)>)) 
を参照してください。とりあえず、
まずは (({#{File.basename(@figdir)} })) を作成して下さい。

== #{@self_name} の用意

((<#{@self_name} の入手の方法>)) で取得した #{@self_name} は
(({ thum-src })) というディレクトリを作ってそこに置いて下さい。
結果的に、以下のような構成になっていると良いです。

    ./#{File.basename(@figdir)}/*****.jpg
             *****.gif
    ./thum-src/dcmodel-thum.rb


== とりあえず実行

(({ thum-src })) へ移動し、#{@self_name} を実行してください。

    $ cd thum-src
    $ ruby #{@self_name}

すると、#{@sub_rb_name} という実行スクリプトが作成される
はずです。

== 子スクリプトの実行

今度は #{@sub_rb_name} を実行します。

    $ ruby #{@sub_rb_name}

すると、(({ #{@index}#{@index_ext} }))というファイルが作成されます。
これがサムネイルの HTML です。


== できたものを見てみる

(({ #{@index}#{@index_ext} })) をブラウザで見てみてください。
このページと同様のメッセージが書かれたページが出力されている
はずです。

#{File.basename(@figdir)} に画像をおいてあった場合、それらが
下にサムネイル化されているはずです。


== スクリプトの編集 (入門編)

このままでは使えないので、(({ #{@sub_rb_name} })) を編集してください。
まず、ここに記述されるコメントを削除しましょう。

以下の部分以降を全て消してください。

    thumb.message   << <<-Message
    =begin
    [((<地球流体電脳倶楽部|URL:http://www.gfd-dennou.org>))]
    [((<dcmodel|URL:http://www.gfd-dennou.org/library/dcmodel>)) |
                            :
                            : 

次に、作成される HTML ファイルの名前を希望のものに変更してください。
下記のように infofile を設定しておくと「情報ファイル」(後述) の
名前も一緒に変更されて便利です。

   thumb.index     = "../result"
   thumb.infofile  = "\\\#\\\{File.basename(thumb.index)\\\}.txt"

画像として認識したい拡張子を増やしたい場合は以下のようにしてください。

   thumb.ext_list.push("bmp")

画像ファイル名が長く、ファイル名の頭の部分を取り除いて表示したい、
またはファイル名の頭で出力するファイルの選択を行いたい場合は
以下のように設定してください。

   thumb.headlimit = "exp_name_"

画像ファイル名を HTML に表示したくない場合は以下のように設定してください。
個別的にファイル名を非表示にしたい場合は
((<「情報ファイル」の編集 (応用編)>)) の ((<ファイル名非表示>))
を参照してください。

   thumb.blankfig = true

画像の縦横サイズや、サムネイルで横に表示する画像の数は以下のように
設定してください。

   thumb.img_width  = 200
   thumb.img_height = 150
   thumb.figtable_num = 3

自動生成されるサムネイル画像の置き場と画像の名前の最後部を
次のように指定して下さい. 

   thumb.thumbnaildir  = "../thumb"    # サムネイル画像を置くディレクトリ名
   thumb.thumbnailtail = "_thumb.png"  # サムネイル画像の拡張子名

アニメーション gif 等複数ページを束ねた画像に対してはサムネイル化する
ページ番号を 1 より大きい値に設定できます. 

    thumb.thumbnailpage = "50"      # サムネイル画像化する元画像のページ番号

スタイルシートに書き込む設定を単体でも指定可能です。
例えば、リンクに関する動作を設定するには以下のようにします。

   thumb.style = <<-STYLE
     a:link { color:#269900; }
     a:visited { color:#269900; }
     a:hover { color:#99FF33; }
   STYLE

元々の (({ thumb.title ... })) の行を例えば以下のように書き換え、
タイトルを設定してください。(これは HTML の head タグ内の 
title タグに設定されます )

  thumb.title     = "実験結果"

ちょうどこのチュートリアルが作成される場所に書き出す、
メッセージを設定してください。ここに書き込む内容がそのまま
HTML として出力されるので、HTML タグも書き込んでください。

((* 注意！！ *)) message に代入するときの記号は必ず 「=」
ではなく、「<<」にしてください。

    thumb.message   << <<-MSG
    <h1>実験結果</h1>

    <p>
      以下は実験結果を一覧したものである
    </p>

    <h2>実験設定</h2>

    <ul>
      <li>解像度       : T42L20
      <li>時間ステップ : 30 s
    </ul>
                            :
                            : 
      MSG

サムネイル部分の下にメッセージを記述したい場合は、以下のように
設定しましょう。書き方は上記の message と同様です。

    thumb.footer  << <<-MSG
    =begin
    == 参考資料
    
    * 地球流体電脳倶楽部 dcmodel プロジェクト.
      ((<URL:http://www.gfd-dennou.org/library/dcmodel>)), 
      地球流体電脳倶楽部.
    
    =end
    MSG


== 再度実行

再度 #{@sub_rb_name} を実行します。

    $ ruby #{@sub_rb_name}

すると、上記の記述が反映された (({ #{@index}#{@index_ext} })) が
作成されます。ブラウザで確認してください。

ただし、これだけでは、サムネイル内のコメントを編集できないので、
以下の ((<「情報ファイル」の編集 (入門編)>)) を参照してください。


== 「情報ファイル」の編集 (入門編)

#{@sub_rb_name} を実行したディレクトリには上記で設定した
infofile に対応したファイルが作成されるはずです。

   thumb.infofile  = "\\\#\\\{File.basename(thumb.index)\\\}.txt"

このファイルを編集することで、サムネイル内にコメントを記述できます。

まず中身を見てみてください。

    fig1.png::
    fig2.gif::
    fig3.jpg::
    fig3.png::

これは、以下のようなフォーマットになっています。

    <画像名> : <修飾子> : <コメント>

<修飾子> に関しては ((<「情報ファイル」の編集 (応用編)>))
を参照してください。


=== 画像の順序の入れ替え

サムネイルには「情報ファイル」に書き込まれた順に書き出されます。
入れ替えたい時には行ごとその位置を入れ替えてください。

    fig2.gif::
    fig3.jpg::
    fig3.png::
    fig1.png::

=== コメント付け

コメントをつけたいときには、以下のようにしてください。

    fig1.png:: 1 回目の実験
    fig2.gif:: 2 回目の実験
    fig3.jpg:: 3 回目の実験 (jpg 画像)
    fig3.png:: 3 回目の実験 (png 画像)

HTML タグはそのまま認識されるので、以下のように書き込むことが
可能です。

    fig1.png:: <hr> 1 回目の実験 <br> 失敗 <hr>


=== コメントアウト

コメントアウトしたい場合は行頭に 「#」を書き込みます。

    # fig2.gif:: 2 回目の実験


=== ラベル

画像ではなく、コメントのみを書き込みたいときは、<画像名> に
「label」と記述します。

    label:: <hr><table><tr><td>実験設定 2</td><td>パラメータ 3</td></tr></table>

=== スペース

一つ分飛ばして表示したい時は以下のように <画像名> の部分に何も書かないで
下さい。
  
    　::


== もう一度実行

再度 #{@sub_rb_name} を実行します。

    $ ruby #{@sub_rb_name}

すると、上記の記述が反映された (({ #{@index}#{@index_ext} })) が
作成されます。ブラウザで確認してください。


== スクリプトの編集 (応用編)

((<スクリプトの編集 (入門編)>)) の応用版です。

((<#{@self_name} の rdoc マニュアル|URL:#{PUB_DOC_URL}>))
の DCModelThumbnail クラスの Attribute に設定できる全ての値
の情報があるので、詳しくはそちらを参照ください。

=== 電脳サーバ以外で使うために

電脳サーバ以外での利用を考える場合には、下記の設定も編集する
必要があるかもしれません。

コピーライト

   thumb.copyright = "GFD Dennou Club"

スタイルシート

   thumb.css       = "/GFD_Dennou_Club/ftp/arch/dcmodel/htmltools/dcmodel.css"

rd2 コマンドへのパス (これは、下記で紹介する RD という書法で
書く必要が無ければ、設定の必要はありません)

   thumb.rd2_path  = "/usr/bin/rd2"

rd2html-ext-lib の設定 (これも、下記で紹介する RD という書法で
書く必要が無ければ、設定の必要はありません)

   thumb.rd2htmlextlib = "/GFD_Dennou_Club/ftp/arch/dcmodel/lib"
    

=== RD を使いたい人のために

中には、「RD
((-
RD (Ruby Documents) や rdtool に関しては、
((<RD事始め|URL:http://www.rubyist.net/~rubikitch/computer/rd-intro/>))
や
((<RAA - rdtool|URL:http://raa.ruby-lang.org/project/rdtool/>))
を参照してください。
-)) 
で書きたい！！  HTML でなんか書きたくない！！」という
わがままは方もいるかもしれません。(これを書いている私が正にそうです。
そのためにこのツールを改良したと言っても過言ではありません…)。

そういう方は、メッセージの設定の際に、頭に 「=begin」、一番最後に
「=end」と記述してください。

    thumb.message   << <<-MSG
    =begin
    = 実験結果

    以下は実験結果を一覧したものである

    == 実験設定

    * 解像度       : T42L20
    * 時間ステップ : 30 s
                            :
                            : 
    =end
    MSG

すると、この情報を rdtool で HTML 化したものをサムネイルのファイルに
埋め込みます。

=== RT を使いたい人のために (未実装)

((* 注意： *)) この機能はまだバージョン #{VER} では組み込まれていません。

他にも、「RT
((-
((<RT|URL:http://www.rubyist.net/~rubikitch/computer/rt/>))
を参照してください。
-)) 
で書いてみたい！！」という方もいるかもしれません。

そういう方は、メッセージの設定の際に、頭に 「=begin RT」、一番最後に
「=end」と記述してください。

    thumb.message   << <<-MSG
    =begin RT
    caption = 表テスト

         , 人間, == , 犬 , ==
     ||  , 男  , 女 ,オス,メス

      x  , 1.0 , 2.0, 1.1, 1.2
      y  , 0.4 , 0.5, 0.3, 0.1

    =end
    MSG

すると、この情報を rttool で HTML 化したものをサムネイルのファイルに
埋め込みます。


=== SIGEN ファイル生成のコントロール

デフォルトではサムネイルファイルの作成と同時に SIGEN ファイル
<http://www.gfd-dennou.org/library/cc-env/mksigen/desc.htm> を
作成しますが、不要である場合は mksigen を false にしてください。

   thumb.mksigen = false


=== ロボット検索の禁止

生成するサムネイルをロボット検索して欲しくない場合には
norobots を true にしてください。

   thumb.norobots = true

=== サムネイル画像変換ツールの変更

デフォルトでサムネイルを変換するコマンドおよびオプションは
以下の通りです。

    #{@convert_cmd}

これを変換したい場合には以下のように設定を行ってください。
ただし、空白の場合やシステムに存在しないコマンドが設定されている
場合にはエラーを返します。

   thumb.convert_cmd = "mogrify -geometry"

デフォルトでは既に出力先にファイルが存在し、且つ元のファイルよりも
新しい場合、時間の短縮のため、画像ファイルの変換を行いません。
もしも毎回必ずファイルの変換を行いたい場合は以下のように設定してください。

   thumb.convert_overwrite = true


== 「情報ファイル」の編集 (応用編)

((<「情報ファイル」の編集 (入門編)>)) の応用版です。

=== 右寄せ・左寄せ

<修飾子>に ">" を書き込むと右寄せに、"<" を書き込むと左寄せになります。

    fig1.png:>: 右寄せだよ
    fig2.gif:<: 左寄せだよ
    fig3.jpg:: デフォルトは真ん中寄せだよ


=== 複数行入力

<修飾子>に "m" を書き込むことで複数行入力が可能です。
なお、上記の ((<右寄せ・左寄せ>)) と併用する場合にはカンマ "," で
区切ります。内容自体は "{" と "}" でくくります。

    fig1.png:m:{
    <p>
     複数行入力を行うよ。
     こういうことできるよ。
     便利だねー。テーブルも書きやすいね。
    </p>
    }
    fig2.gif:>,m:{
    <ul>
      <li> 併用するにはこうするよ。
    </ul>
    }

=== ファイル名非表示

<修飾子>に "b" を書き込むことでファイル名の表示を抑制します。

    fig1.png:b: ファイル名表示が抑制されます

全てのファイル名を一括で抑制する方法は ((<スクリプトの編集 (入門編)>))
を参照してください。(属性 blankfig を true に設定します)。


=== RD を使いたい人のために

<修飾子>に "rd" を書き込むことで、文字列は RD として解釈され、
rdtool で HTML に変換されます。RD でページ内リンクを作成する 
記法も利用可能で、本文やフッタ、サムネイル内のヘッダにリンクを
貼ることもできます。(例 ((<ヘッダ1>))、((<ヘッダ2>)) )

    fig1.png:m,rd:{
    ((<りんく|URL:./>)) はこんな感じで書けるよ。
    * リストも
      * 簡単
    RD ラベルを使用したページ内リンクは
    ((<RD を使いたい人のために>)) のように記述すれば OK です。
    }


=== RT を使いたい人のために (未実装)

((* 注意： *)) この機能はまだバージョン #{VER} では組み込まれていません。

<修飾子>に "rt" を書き込むことで、文字列は RT として解釈され、
rttool で HTML に変換されます。

    fig1.png:m,rt:{
    caption = 表テスト

         , 人間, == , 犬 , ==
     ||  , 男  , 女 ,オス,メス

      x  , 1.0 , 2.0, 1.1, 1.2
      y  , 0.4 , 0.5, 0.3, 0.1
    }


=== 「情報ファイル」からタイトルの設定

((<スクリプトの編集 (入門編)>)) でタイトルの設定に関して
記述しましたが、「情報ファイル」からの設定も可能です。
<画像名> に title と記述し <コメント> にタイトルを書き込んでください。

     title:: 実験設定 其の弐

((<スクリプトの編集 (入門編)>)) は上書きされます。


=== 「情報ファイル」から本文メッセージの追加

((<スクリプトの編集 (入門編)>)) で本文メッセージの設定に関して
記述しましたが、「情報ファイル」から追加も可能です。
<画像名> に message と記述し、本文メッセージを書き込んでください。

     message:m,rd:{
     = サンプルだー

     == 目次です

     === さらに目次です

     ((<ほげ|URL:thum/sample_thum.txt>))
     }
     message:m:{
     <b>HTML</b> ですが何か問題でも？
     <ul>
       <li>ちいさな  
       <li>テーブルを
       <li>作って    
       <li>みたよ♪
     </ul>
     <hr>
     }

=== 「情報ファイル」からフッターメッセージの追加

((<スクリプトの編集 (入門編)>)) でフッターメッセージの設定に関して
記述しましたが、「情報ファイル」から追加も可能です。
<画像名> に footer と記述し、フッターメッセージを書き込んでください。

     footer:m,rd:{
     == フッターです
     参考文献とか書き込むのに便利かもしれません。
     }

=end
    EndOfTutorial
    debug(@message)
  end

  #
  # HTML ファイルの最終的な作成メソッド。最後にこのメソッドを呼ぶことで
  # 作業が完了する。
  #
  # overwrite に false を与えると、上書きを禁止する。
  #
  # quiet を true にするとエラーを除く全てのメッセージが表示されなくなる。
  #
  # verbose を true にすると作業の進捗状況がメッセージとして出力される。
  #
  # err を true にした場合、意図しない動作が起きた場合にすぐに
  # エラーを起こす。
  #
  def create(overwrite=true, quiet=nil, verbose=true, err=true)

    #
    # サムネイルファイル名
    #
    index_file_name = @index.chomp.strip  +
                      @index_ext.chomp.strip

    #
    # 元ファイル削除 (overwrite が nil の場合はエラー)
    #
    if File.exist?(index_file_name)
      if overwrite then
        File.delete(index_file_name)
      else
        raise ArgumentError, "\n\n  Error : \"#{index_file_name}\" exist already.\n\n"
      end
    end


    #
    # infofile の作成 (既に存在する場合はそのまま)。
    # DCModelThumbnail.info_make メソッドを呼ぶ
    #
    status = info_make(@figdir, @infofile, @ext_list,
                       @headlimit, nil, nil,
                       true, err)
    if verbose then
      if /create/ =~ status
        $stdout.print "  Message : Infofile \"#{@infofile}\" is created.\n"
      elsif /exist/ =~ status
        $stdout.print "  Message : Infofile \"#{@infofile}\" is already exist.\n"
      end
    end

    #
    # @message が Array オブジェクト以外の場合はエラーを返す。
    #
    if !@message.instance_of?(Array) then
      warn_or_err(
                  "\"message\" must be Array Object. " +
                  "Please \"message = Array.new\" initially.\n", 
                  true, nil, ArgumentError)
    end

    #
    # infofile から情報の取得。
    # DCModelThumbnail.info_get メソッドを呼ぶ。
    #
    $stdout.print "  Message : Get information from \"#{@infofile}\".... " if verbose
    info_list = info_get(@infofile, @headlimit, nil, quiet, err)
    #
    # infofile からの情報のうち、画像ファイル名を "title" にしている
    # ものに関して @title に上書きして、info_list から除く。
    #
    # infofile からの情報のうち、画像ファイル名を "message" にしている
    # ものに関して @message に追加して、info_list から除く。
    #
    info_list_buff = Array.new
    info_list.each{ |info_part|
      if /title/ =~ info_part['fig_name']
        @title = info_part['comment']
      elsif /message/ =~ info_part['fig_name']
        # フォーマットの情報を受けて、"=begin" 等の補完
        if /rd/ =~ info_part['format'] then
          mess_body  = "=begin\n"
          mess_body << info_part['comment']
          mess_body << "\n=end\n"
        elsif /rt/ =~ info_part['format'] then
          mess_body  = "=begin RT\n"
          mess_body << info_part['comment']
          mess_body << "\n=end\n"
        else
          mess_body = info_part['comment']
        end

        @message << mess_body

      elsif /footer/ =~ info_part['fig_name']
        # フォーマットの情報を受けて、"=begin" 等の補完
        if /rd/ =~ info_part['format'] then
          foot_body  = "=begin\n"
          foot_body << info_part['comment']
          foot_body << "\n=end\n"
        elsif /rt/ =~ info_part['format'] then
          foot_body  = "=begin RT\n"
          foot_body << info_part['comment']
          foot_body << "\n=end\n"
        else
          foot_body = info_part['comment']
        end

        @footer << foot_body

      # サムネイルに書き込む情報 (これが本命)
      else
        info_list_buff << info_part
      end
    }
    info_list = Array.new
    info_list << info_list_buff
    info_list.flatten!          # 配列の平滑化 (1次元配列化)

    $stdout.print "  done.\n" if verbose


    # @convert_cmd が存在するかどうかチェック
    $stdout.print "  Message : Check converter command .... " if verbose
    convert_cmd_no_opt = @convert_cmd.strip.gsub(/\s+.*/, '')
    convert_cmd_check1 = convert_cmd_no_opt + " -help &> /dev/null"
    convert_cmd_check2 = convert_cmd_no_opt + " --help &> /dev/null"
    raise ArgumentError, "\n\n  Error : \"#{convert_cmd_no_opt}\": command not found.\n\n" \
       if !system(convert_cmd_check1) && !system(convert_cmd_check2)
    $stdout.print "  done.\n" if verbose

    # サムネイル画像置き場の作成
    raise IOError, "\n\n  Error: Existing #{@thumbnaildir} is not a directory.\n\n" \
       if File.exists?(@thumbnaildir) && ! File.stat(@thumbnaildir).directory?
    Dir.mkdir(@thumbnaildir) unless File.exists?(@thumbnaildir)

    # サムネイル画像の作成
    $stdout.print "  Message : Create small images for thumbnail ....\n" if verbose
    info_list.each_index{ |i|
      thumbnail_name = info_list[i]['fig_name'].sub(/\.\w+$/, @thumbnailtail)
      fig_name = info_list[i]['fig_name']
      $stdout.print "    [#{i + 1}/#{info_list.size}]: " if verbose
      if info_list[i]['fig_name_nohead'].strip.chomp == "label" ||
          info_list[i]['fig_name_nohead'].strip.chomp == "message" ||
          info_list[i]['fig_name_nohead'].strip.chomp == "title" ||
          info_list[i]['fig_name_nohead'].strip.chomp.empty?
        $stdout.print "Skip: No image file.\n" if verbose
      elsif !@convert_overwrite && \
          File.exists?("#{@thumbnaildir}/#{thumbnail_name}") && \
          File.mtime("#{@thumbnaildir}/#{thumbnail_name}") > \
          File.mtime("#{@figdir}/#{fig_name}")
        $stdout.print "Skip: \"#{@thumbnaildir}/#{thumbnail_name}\" is already exist, and newer than \"#{@figdir}/#{fig_name}\"\n" if verbose
      else
        cmd = "#{@convert_cmd} #{@img_width.to_s}x#{@img_height.to_s} '#{@figdir}/#{fig_name}[#{@thumbnailpage}]' '#{@thumbnaildir}/#{thumbnail_name}'"
        $stdout.print cmd if verbose
        $stdout.print "\n" if verbose
        raise "\n\n  Error : \"#{cmd}\": failed.\n\n" if !system(cmd)
      end
      info_list[i]['thumbnail_name']=thumbnail_name
    }

    #
    # @message のフォーマットを解析し、HTML に変換する。
    #
    html_message = Array.new
    @message.each{ |mess|
      format = format_parser(mess)

      if /rd/ =~ format then
        html_buff = rd2html(mess, true)
      elsif /rt/ =~ format then
        html_buff = rd2html(mess, true)
      else
        html_buff = mess
      end

      html_message << html_buff if html_buff
      debug(html_message)
    }
    debug(html_message)


    #
    # @footer のフォーマットを解析し、HTML に変換する。
    #
    footer_mess = Array.new
    @footer.each{ |mess|
      format = format_parser(mess)

      if /rd/ =~ format then
        html_buff = rd2html(mess, true)
      elsif /rt/ =~ format then
        html_buff = rd2html(mess, true)
      else
        html_buff = mess
      end

      footer_mess << html_buff if html_buff
      debug(footer_mess)
    }
    debug(footer_mess)
    if !footer_mess.empty?
      footer_mess.unshift "\n<hr size=\"1\">\n"
    end

    # 初期化
    html_entire = ""

    # HTML ヘッダ部分
    $stdout.print "  Message : Generate HTML Header...." if verbose
    html_entire << html_header 
    $stdout.print "  done.\n" if verbose

    # 本文
    $stdout.print "  Message : Insert body messages...." if verbose
    html_message.each { |message|
      html_entire << message
    }
    $stdout.print "  done.\n" if verbose

    # サムネイル部分
    $stdout.print "  Message : Generate Thumbnail Lists...." if verbose
    html_entire << html_thum(info_list, quiet, true)
    $stdout.print "  done.\n" if verbose

    # フッタメッセージ部分
    $stdout.print "  Message : Insert footer messages...." if verbose
    footer_mess.each { |message|
      html_entire << message
    }
    $stdout.print "  done.\n" if verbose

    # HTML フッタ部分
    $stdout.print "  Message : Generate HTML Footer...." if verbose
    html_entire << html_footer
    $stdout.print "  done.\n" if verbose

    # ヘッダ, サムネイル, フッタ間のハイパーリンクを有効にする.
    $stdout.print "  Message : Cross hyperlinks between header and thumbnail and footer .... " if verbose
    html_entire = relabel(html_entire)
    $stdout.print "  done.\n" if verbose

    # ファイルの書きだし
    $stdout.print "  Message : Output to \"#{index_file_name}\"...." if verbose
    ifile = open(index_file_name, "w")
    ifile.print html_entire
    ifile.close
    $stdout.print "  Successfull. \n" if verbose

    # 最後までうまくいったら、SIGEN ファイルも作成する。
    if @mksigen then
      mksigen_file = index_file_name.chomp.strip + ".SIGEN"
      mksigen_thumbdir = @thumbnaildir + ".SIGEN"
      mksigen_thumbdir_title = @title || ""
      mksigen_thumbdir_title << " サムネイル画像置き場ディレクトリ"
      mksigen_src  = relative_str("#{$0}"  , mksigen_file)
      mksigen_info = relative_str(@infofile, mksigen_file)

      mksigen_desc = <<-DESC
relative:#{mksigen_src} と
		relative:#{mksigen_info}
		により自動生成
      DESC

      mksigen_note = <<-NOTE
この SIGEN ファイル自体も
		relative:#{mksigen_src}
		からの自動生成である
      NOTE

      $stdout.print "  Message : Create \"#{mksigen_file}\"...." if verbose
      mksigen_write(mksigen_file, @title, nil,
                    nil, "自動生成",
                    mksigen_desc, mksigen_note)
      mksigen_write(mksigen_thumbdir, mksigen_thumbdir_title, nil,
                    nil, "自動生成",
                    mksigen_desc, mksigen_note) if File.exists?(@thumbnaildir) 
      $stdout.print "  Successfull. \n" if verbose
    end

  end

  #
  # サンプルスクリプト出力用のメソッド。
  # この DCModelThumbnail クラスに依存するサンプルスクリプトを
  # 引数 filename という名前で出力する。実際には、このファイル
  # を編集・実行することでサムネイルが作成される寸法である。
  #
  def create_sample_rb(filename)
    if !(str_and_notspace?(filename)) then
      return warn_or_err("filename is invalid.\n",
                         true, nil, ArgumentError)
    end
    
    rb_file_body = <<-EndOfFile
#!/usr/bin/env ruby1.8
#
#= dcmodel thumbnail generate ruby script
#
#  Editor :: #{username_from_uid}
#  Version:: #{Time.now.strftime("%Y/%m/%d %H:%M:%S")}
#
#== Overview
#
#This file is generate by following ruby script automatically.
#
#      #{File.expand_path($0.to_s)}
#      version "#{VER}"
#
#Please edit this file according to your purpose.
#
#== Usage
#
#Please check following sample page and reference manual.
#
#  #{PUB_SAMPLE_URL}
#  #{PUB_DOC_URL}
#
##################################################

require "#{File.expand_path($0.to_s)}"

######################################################
# DCModelThumbnail のインスタンスを作成 (必須)
thumb = DCModelThumbnail.new

# サムネイル実行コマンド (必須)。最後に実行すること
END{
  thumb.create
}

#thumb.copyright = "#{@copyright}"
                              # コピーライト

thumb.index     = "#{@index}"
                              # 作成されるサムネイルのファイル名 (拡張子除く)

#thumb.index_ext = "#{@index_ext}"
                              # 作成されるサムネイルの拡張子名

thumb.infofile  = "\#\{File.basename(thumb.index)\}.txt"
                              # 「情報ファイル (infofile)」のファイル名

#thumb.ext_list.push("bmp")
                              # 画像ファイルとして認識させたい拡張子の
                              # 追加。デフォルトでは 
                              # #{@ext_list.join(", ")},
                              # #{@ext_list.join(", ").swapcase}
                              # が認識される。

#thumb.headlimit = "headlimit_"
                              # headlimit に当てはまらないものは画像と
                              # しては無視され、当てはまるものは「情報
                              # ファイル」において、接頭部分 headlimit 
                              # を省略して指定することが可能となる。

#thumb.blankfig = true
                              # 画像ファイル名を表示しない

#thumb.figdir    = "#{@figdir}"
                              # 絵のあるディレクトリの名前。
                              # 必ず存在していなければならない。

#thumb.thumbnaildir    = "#{@thumbnaildir}"
                              # サムネイル画像を置くディレクトリの名前

#thumb.thumbnailtail    = "#{@thumbnailtail}"
                              # サムネイル画像の拡張子名

#thumb.thumbnailpage = "1"
                              # サムネイル画像化する元画像のページ番号

#thumb.convert_cmd = "#{@convert_cmd}"
                              # convert コマンドおよびオプション。この
                              # 後ろに画像サイズが 200x150 のような形
                              # 式で指定される。

#thumb.convert_overwrite = #{@convert_overwrite}
                              # convert コマンドが実行される際、既に出
                              # 力先のファイルがある場合に上書きするた
                              # めのフラグ。これが false の場合、出力
                              # 先のファイルが存在し、且つ元のファイル
                              # よりも新しい場合は変換を行わない。

#thumb.css       = "#{@css}"
                              # スタイルシートファイル

#thumb.rd2_path  = "#{@rd2_path}"
                              # rd2 コマンドへのパス

#thumb.rd2htmlextlib = "#{@rd2htmlextlib}"
                              # rd2-ext-lib へのライブラリへのパス

#thumb.mksigen = false
                              # SIGEN ファイルを作らない場合は false 
                              # にセットする

#thumb.norobots = true
                              # HTML のロボット検索を禁止する場合には 
                              # true にセットする

#thumb.img_width  = #{@img_width}
                              # 画像ファイルサイズ (幅)

#thumb.img_height = #{@img_height}
                              # 画像ファイルサイズ (高さ)

#thumb.figtable_num = #{@figtable_num}
                              # 横にならべるファイル数

#thumb.style = <<-STYLE
#  a:link { color:#269900; }
#  a:visited { color:#269900; }
#  a:hover { color:#99FF33; }
#STYLE
                              # スタイルシートを直接設定するためのもの 
                              # (css ファイルに書き込む情報を直接指定
                              # できる)

#thumb.html_author  = "#{@html_author}"
                              # html の作成者情報 (デフォルトはユーザ
                              # アカウント名が自動取得される)

thumb.title     = "#{@title}"
                              # html ヘッダのタイトル

                              # 本体に書き出すメッセージ。サムネイルの
                              # 部分よりも上に出力される。この変数自体
                              # は Array オブジェクトで、その内部に 
                              # String オブジェクトが格納される。

                              # フッターメッセージ。
                              # "=" ではなく、"<<" で代入することに注意！！
thumb.footer    = Array.new
#thumb.footer    << <<-Footer
# #{@footer.join("\n\n")}
#Footer

                              # メッセージ。
                              # "=" ではなく、"<<" で代入することに注意！！
thumb.message   = Array.new
thumb.message   << <<-Message
#{@message.join("\n\n")}
Message

    EndOfFile

    #
    # ファイルの作成
    #
    ifile = open(filename, "w")
    ifile.print "#{rb_file_body}"
    ifile.close

    #
    # パーミッションの設定
    #
    File.chmod(0755, filename)

  end


  #
  # デバッグ出力用メソッド。組み込み関数 $DEBUG が真の場合 (つまり、
  # プログラムを $ ruby -d ./xxxxxx.rb として呼び出した場合) に
  # debug メソッドに代入された変数を出力する。
  #
  def debug(*args)
    p [caller.first, *args] if $DEBUG
  end
  private :debug

  #
  # 警告またはエラー。
  # err が nil や false の場合、mes に与えられたメッセージを
  # 警告として表示する。err が真の場合はそのメッセージの出力
  # と同時にエラーを発生させ、プログラムを終了させる。
  # errvar に変数を与えると、エラーの種類を指定できる。
  # quiet を true にすると、err が nil の場合、何も動作しなくなる。
  #
  def warn_or_err(mes=nil, err=nil, quiet=nil, errvar=nil)
    return nil if !mes

    errvar = RuntimeError if !errvar

    if err then
      raise errvar, "Error: #{mes}"
    elsif !quiet
      $stdout.print "[#{caller.first}] \n     Warning: #{mes}"
      return nil
    end
  end
  private :warn_or_err

  #
  #画像ファイル名・修飾情報・コメントを含む「情報ファイル」を作成するための
  #メソッド。
  #
  #figdir (String オブジェクト)
  #内の拡張子 ext_list (Array オブジェクト) にヒットするファイル名
  #をリストにし、infofile (String オブジェクト) に書き出す。
  #
  #headlimit (String オブジェクト) を渡すと、ファイル名の頭が
  #headlimit にヒットするものだけを拾い、リストからはその部分を
  #取り除くようにする。
  #
  #overwrite を true にすると、infofile が存在する場合でも
  #上書きする。また、quiet を true にすると警告メッセージを表示しない。
  #
  #delimiter (String オブジェクト) は情報ファイルの
  #画像ファイル名・修飾情報・コメントの区切り文字を設定する
  #ものであり、デフォルトは定数 INFO_DELIMITER にて設定されている。
  #一応変更できるようになっているが、原則的に変更しない
  #事を薦める。
  #
  #ファイルを作成したときは "create"、既存のものがすでに存在する
  #場合には "exist" を返す。画像ファイルが一つも読み込めない、
  #すなわち空のファイルを作成してしまった時や、既存のものが無く、
  #なおかつ作成に失敗した場合はエラーを起こす。(引数 err を
  #false にした場合には警告を表示するだけである)
  #
  #ここで作成されるファイルは DCModelThumbnail.info_get で取得される
  #ファイルの雛形である。
  #
  def info_make(figdir=nil, infofile=nil, ext_list=nil,
                headlimit=nil, overwrite=nil, delimiter=nil,
                quiet=nil, err=true)

    # infofile があり、overwrite が false の場合は終了。
    if File.exist?(infofile) && !overwrite then
      warn_or_err("Infofile \"#{infofile}\" already exist. " +
                  "So not generate infofile once again.\n",
                  nil, quiet)
      return "exist"
    end

    # 引数の有効性の検証
    if !(str_and_notspace?(figdir)) then
      return warn_or_err("\"figdir\" is not specified. " + 
                         "So \"infofile\" is not generated. \n",
                         err, quiet, ArgumentError)

    elsif !(str_and_notspace?(infofile)) then
      return warn_or_err("\"infofile\" is not specified. " + 
                         "So \"infofile\" is not generated. \n",
                         err, quiet, ArgumentError)

    elsif !(array_and_notzero?(ext_list)) then
      return warn_or_err("\"ext_list\" is not specified. " + 
                         "So \"infofile\" is not generated. \n",
                         err, quiet, ArgumentError)
    end

    # delimiter のセット
    if !(str_and_notspace?(delimiter)) then
      delimiter = INFO_DELIMITER
    end

    # headlimit の整形
    if !(str_and_notspace?(headlimit)) then
      headlimit = ""
    end

    # figdir から画像ファイル名一覧をとりだし, 配列 imgfiles へ代入
    imgfiles = Array.new
    Dir.foreach("#{figdir}") { |item|
      ext_list.each{ |ext|
        next if !(str_and_notspace?(ext))

        # ドットが付いていない場合はドットをつける
        if !(/^\.(.*)/ =~ ext) then
          ext = "." + ext.chomp.strip
        end

        # 拡張から有効か判定
        next unless /#{ext}$/i =~ item

        # headlimit から有効か判定
        if str_and_notspace?(headlimit) then
          if /^#{headlimit}(.+)$/ =~ item
            bodyname = $1
          else
            next
          end
        else
          bodyname = item
        end

        # imgfiles への格納
        #imgfiles.push( (File.basename(bodyname, ext) )  )
        imgfiles.push( bodyname )
      }
    }

    # もしも画像情報が取り出せていなかったら警告 or エラー
    if !(imgfiles.size > 0) then
      if str_and_notspace?(headlimit)
        errmsg = "Image files \"#{headlimit}...\" are not found in \"#{figdir}\".\n"
      else
        errmsg = "Image files are not found in \"#{figdir}\".\n"
      end
      return warn_or_err(errmsg, err, quiet, ArgumentError)
    end

    imgfiles = imgfiles.sort

    # infofile に書き込み
    ifile = open(infofile, "w")
    imgfiles.each{ |filename|
      ifile.print "#{filename}#{delimiter}#{delimiter}\n"
    }
    ifile.close

    return "create"
  end


  #
  # DCModelThumbnail.info_make によって作成される「情報ファイル」
  # infofile から画像ファイル名とコメント、および修飾情報を取り出し、
  # Array[Hash, ...] にして返す。
  # 各要素の Hash にはキーに値の種類の文字列を格納してある。
  # 以下は現在 Hash のキーとして取得されるものである。
  #
  # * fig_name
  #   * ファイル名である。1 つ目の区切り文字 
  #     (DCModelThumbnail.info_make の INFO_DELIMITER 参照)
  #     よりも前の文字列をこのキーの値として取得する。なお、
  #     引数 headlimit が与えられる場合、情報ファイルの文字列の
  #     頭に headlimit を付加する。
  # * fig_name_nohead
  #   * fig_name と同様にファイル名である。ただし、こちらは
  #     引数 headlimit が与えられる場合でも、情報ファイルから得られる
  #     文字列のみを格納する。
  # * comment
  #   * サムネイルの個々の画像の下に付加されるコメントである。
  #     2 つ目の区切り文字以降の文字列がこのキーの値として取得される。
  #     なお、デフォルトでは改行文字までをコメントとして読み込むが、
  #     修飾子に "m" が入る場合、その後の"{" から "}" までの間の文字
  #     を読み込む。(改行文字も含める)。
  # * align
  #   * コメントの文字寄せ情報である。1つ目と2つ目の区切り文字の間に
  #     下記の文字列を入れることで、下記のそれに対応する値が格納される。
  #     なお、デフォルトでは "center" が格納される。
  #     * "<" : 左寄せを示し、値に "left" を格納する。
  #     * ">" : 右寄せを示し、値に "right" を格納する。
  # * format
  #   * フォーマットの情報である。
  #     下記の文字列を入れることで、下記のそれに対応する値が格納される。
  #     なお、デフォルトでは "html" が格納される。
  #     * "rd" : RD フォーマットであることを示す。
  #     * "rt" : RT フォーマットであることを示す。
  # * blankfig
  #   * HTML へファイル名を表示しない。
  # * line
  #   * 情報ファイルの該当情報の「行数」が格納される。
  #     複数行が指定される場合は "4-10" というように格納される。
  #
  # delimiter (String オブジェクト) は情報ファイルの
  # 画像ファイル名・修飾情報・コメントの区切り文字を設定する
  # ものであり、デフォルトは定数 INFO_DELIMITER にて設定されている。
  # 一応変更できるようになっているが、原則的に変更しない
  # 事を薦める。
  #
  # quiet を真にすると、ファイルがない際にもメッセージを表示しない。
  #
  # err を真にすると、ファイルが見つからない際にエラー処理をする。
  #
  def info_get(infofile=nil, headlimit=nil, delimiter=nil, 
               quiet=nil, err=nil)

    # delimiter のセット
    if !(str_and_notspace?(delimiter)) then
      delimiter = INFO_DELIMITER
    end

    info_list = Array.new

    # ファイルが読み取れるかチェック
    if !(File.readable?(infofile)) then
        return warn_or_err("\"#{infofile}\" is not readable. \n",
                           err, quiet, ArgumentError)
    end

    # 実際にファイルを開く
    ifile = open(infofile, "r")

    line_num = 0
    multi_valid = false  # 複数行取得用のフラグ
    multi_first = true  # 複数行取得用のフラグ

    start_char = Regexp.quote(INFO_MULTI_START) # 複数行開始 "{"
    stop_char  = Regexp.quote(INFO_MULTI_STOP)  # 複数行停止 "}"

    info_hash_tmp = Hash.new

    ifile.each { |line|

      # 探索したデータの格納用配列とハッシュ
      info_part = Array.new
      info_hash = Hash.new

      # 行数を数える
      line_num += 1

      debug("line=", line_num, ":", "multi=", multi_valid)

      info_part = line.chomp.split(/#{delimiter}/, 3)
      info_hash['fig_name_nohead'] = info_part[0]  ||  ""
      info_hash['comment']         = info_part[2]  ||  ""
      info_hash['line']            = line_num.to_s

      # 行頭が "#", または完全に空行の場合はコメントアウトと考えて無視。
      if /^\s*#/ =~ info_part[0] then
        next
      elsif !(str_and_notspace?(line)) then
        next
      end

      # info_hash['fig_name'] の設定
      if str_and_notspace?(headlimit) then
        info_hash['fig_name'] = 
           headlimit.chomp.strip + info_hash['fig_name_nohead'].chomp.strip
      else
        info_hash['fig_name'] = info_hash['fig_name_nohead']
      end

      #
      # 修飾子の解析 (万が一のことを考え、日本語も処理)。
      #
      if !(str_and_notspace?(info_part[1])) then
        modifier = ""
      else
        modifier = Kconv::toeuc(info_part[1].chomp.strip)
        #
        # 日本語らしきものが入っていたら警告またはエラー
        # ただし、複数行処理の場合は気にしない。(文中に「:」が
        # 入っていることも考えられるので
        #
        if !(modifier == Kconv::toeuc(modifier)) ||
           !(modifier == Kconv::tojis(modifier)) ||
           !(modifier == Kconv::tosjis(modifier)) then

          if !(multi_valid) then
            warn_or_err(
                        "\"#{modifier}\" include 2 bite code, " +
                        "so this may not be parsed correctly.\n",
                        err, quiet, ArgumentError)
          end
        end
      end

      #
      # 修飾子の分割
      #
      modifier_parts = modifier.split(",")

      # 文字寄せ情報の解析
      info_hash['align'] = "center"  # デフォルト値
      modifier_parts.each{ |char|
        if />/ =~ char.chomp.strip then
          info_hash['align'] = "right"
          break
        elsif /</ =~ char.chomp.strip then
          info_hash['align'] = "left"
          break
        end
      }

      # フォーマット情報の解析
      info_hash['format'] = "html" # デフォルト値
      modifier_parts.each{ |char|
        if /rd/ =~ char.chomp.strip then
          info_hash['format'] = "rd"
          break
        elsif /rt/ =~ char.chomp.strip then
          info_hash['format'] = "rt"
          break
        end
      }

      # ファイル名の非表示フラグ
      info_hash['blankfig'] = false # デフォルト値
      modifier_parts.each{ |char|
        if /b/ =~ char.chomp.strip then
          info_hash['blankfig'] = true
          break
        end
      }

      # 複数行を取得するかどうかの解析
      modifier_parts.each{ |char|
        if /m/ =~ char.chomp.strip then
          debug(info_hash['comment'])
          debug(str_and_notspace?(info_hash['comment']))
          if str_and_notspace?(info_hash['comment']) &&
              /#{start_char}/e =~ Kconv::toeuc(info_hash['comment']) then
            multi_valid = true
            break
          end
        end
      }

      # 複数行取得が有効になっている場合は、値を一時
      # ここで止め、次のループへ回す。
      if multi_valid then

        # 文字コード変換等をまともに行うため、line および
        # info_hash['comment'] を別の文字列に置き換え
        if !(str_and_notspace?(line)) then
          line_tmp = "\n"
        else
          line_tmp = line
        end
        if !(str_and_notspace?(info_hash['comment']))  then
          comment_tmp = "\n"
        else
          comment_tmp = info_hash['comment']
        end

        # 初回の場合は、各値を保持しておく。
        if multi_first then
          info_hash_tmp = info_hash.dup

          # "{" 以降のみを comment として保持
          if !(line_tmp.split(INFO_MULTI_START)[1])
            info_hash_tmp['comment'] = "\n"
          else
            info_hash_tmp['comment'] = 
                         line_tmp.split(INFO_MULTI_START)[1]
          end

          multi_first = false

          # もしも同じ行に "}" もある場合にはそこで終了
          if /#{stop_char}/e =~ Kconv::toeuc(info_hash_tmp['comment']) then
            info_hash_tmp['comment'] = 
                 info_hash_tmp['comment'].split(INFO_MULTI_STOP)[0]

            # フラグの初期化
            multi_valid = false
            multi_first = true

            # 値を info_hash に戻す。
            info_hash = info_hash_tmp.dup

            # 脱出して info_hash を info_list へ (next で脱出しない)

          # 同じ行に "}" が無い場合は info_list へ格納せずに次の行へ
          else
            next
          end

        # 初回以降、まだ "}" がコメントに無い場合
        elsif !(/#{stop_char}/e =~ Kconv::toeuc(line_tmp)) then
          info_hash_tmp['comment'] << line_tmp

          # info_list に渡さずにループを回す
          next

        # コメントに "}" が現れ、終了する際
        else
          if !(line_tmp.split(INFO_MULTI_STOP)[0])
            last_comment = ""
          else
            last_comment = line_tmp.split(INFO_MULTI_STOP)[0]
          end
          info_hash_tmp['comment'] << last_comment

          # フラグの初期化
          multi_valid = false
          multi_first = true

          # 値を info_hash に戻す。
          info_hash = info_hash_tmp.dup
        end
      end

      # 値を info_list に格納。
      info_list.push(info_hash)
    }
    ifile.close

    return info_list
  end

  #
  # HTML のヘッダ部分の作成メソッド。相当する文字列を返す。
  # 作成した HTML は DCModelThumbnail.html_footer で得られる文字列で
  # 閉じられることを想定している。
  #
  def html_header()
    # @index のディレクトリから見た、生成スクリプトの相対的な位置
    generator = relative_str("#{$0}", @index)

    # @index のディレクトリから見た、css の相対的な位置
    css       = relative_str(@css, @index)

    # @norobots が ture であれば、meta タグに書き込み。
    if @norobots then
      robots = <<-ROBOTS
  <meta name="robots" content="noindex,nofollow" />
  <meta name="robots" content="noarchive" />
      ROBOTS
    end

    # @style で指定されているものがあれば、それも書き込み。
    if str_and_notspace?(@style) then
      style = <<-CSS
  <style type="text/css">
  <!--
    #{@style}
  -->
  </style>
      CSS
    else
      style = ""
    end

    #
    # ヘッダ全体の生成
    #
    header = <<-HTMLHEADER
<?xml version="1.0" encoding="euc-jp" ?>
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="ja" xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>#{@title}</title>
  <meta http-equiv="Content-Type" content="text/html; charset=x-euc-jp" />
  <meta name="Author" content="#{@html_author}" />
#{robots}
  <meta name="generator" content="#{generator}" />
  <link href="#{css}" type="text/css" rel="stylesheet" />
#{style}
</head>
<body>
    HTMLHEADER
    return header
  end

  #
  # HTML のサムネイル部分 (画像の数に応じて繰り返す部分) を作成するメソッド。
  # 相当する文字列を返す。info_list には DCModelThumbnail.info_get で
  # 取得される形式の情報ファイルが与えられる。
  #
  # それ以外の形のデータが与えられる場合には警告を発して nil を返す。
  # ただし、err に true を与えると、エラーが生じる。
  # quiet が true の場合には警告メッセージも表示しない。
  #
  # 内部で DCModelThumbnail.html_thum_parts を呼び、各要素はそちらで
  # 作成する。
  #
  def html_thum(info_list=nil, quiet=nil, err=nil)

    #
    # 引数に与えられたデータの検証
    #
    if !array_and_notzero?(info_list) then
      return warn_or_err(
                         "\"info_list\" is invalid.\n",
                         err, quiet, ArgumentError)
    end

    #
    # table タグを作成
    #
    html_table = ""

    html_table = <<-HTMLEOF
    <table border="0" cellspacing="10" align="center">
    HTMLEOF

    #
    # 中身を作成
    #
    info_list.size.times{ |num|
      html_table << html_thum_parts(info_list, num, quiet, err)
    }

    #
    # もしも、info_list.size が @figtable_num で割り切れない場合、
    # 残り分の空白 td を作成する
    #
    remain = @figtable_num - (info_list.size % @figtable_num)
    td_width   = (100 / @figtable_num).truncate.to_s + "%"  # 一つの td の幅

    if !(remain == 0) then
      remain.times{ |time|
        html_table << <<-HTMLEOF
       <td width="#{td_width}" valign="top">
          &nbsp;
       </td>
        HTMLEOF
      }
      html_table << <<-HTMLEOF
      </tr>
      HTMLEOF
    end

    #
    # /table タグを作成
    #
    html_table << <<-HTMLEOF
    </table>
    HTMLEOF

    return html_table
  end


  #
  # HTML のサムネイル部分の内部 (テーブルの1要素毎) を作成するメソッド。
  # 相当する文字列を返す。info_list には DCModelThumbnail.info_get で
  # 取得される形式の情報ファイルを、num には何番目のデータなのかを
  # 示す Numerical オブジェクトを与える。
  #
  # それ以外の形のデータが与えられる場合には警告を発して nil を返す。
  # ただし、err に true を与えると、エラーが生じる。
  # quiet が true の場合には警告メッセージも表示しない。
  #
  def html_thum_parts(info_list=nil, num=nil, quiet=nil, err=nil)
    #
    # 引数に与えられたデータの検証
    #
    if !array_and_notzero?(info_list) then
      return warn_or_err(
                         "\"info_list\" is invalid.\n",
                         err, quiet, ArgumentError)
    end

    if !num.kind_of?(Integer)
      return warn_or_err(
                         "\"num\" is not integer.\n",
                         err, quiet, ArgumentError)
    end

    #
    # info_list からデータの取得
    #
    fig_name        = info_list[num]['fig_name'] # 画像ファイル名
    thumbnail_name  = info_list[num]['thumbnail_name'] # サムネイル画像名
    comment         = info_list[num]['comment']  # コメント
    align           = info_list[num]['align']    # 文字寄せ
    fig_name_nohead = info_list[num]['fig_name_nohead'] # 省略画像ファイル名
    format          = info_list[num]['format']   # comment のフォーマット
    blankfig        = info_list[num]['blankfig'] # 画像名非表示
    debug(fig_name, comment, align, fig_name_nohead)

    #
    # format から、comment の変換処理
    #
    if /rd/ =~ format then
      comment_buff = rd2html(comment)
    elsif /rt/ =~ format then
      comment_buff = rd2html(comment)
    else
      comment_buff = "#{comment}"
    end
    comment = "#{comment_buff}"

    #
    # @index からの相対的な @figdir の設定
    #
    rel_figdir = relative_str(@figdir, @index)

    #
    # @index からの相対的な @thumbaildir の設定
    #
    rel_thumbnaildir = relative_str(@thumbnaildir, @index)

    #
    # テーブルの配置によって <tr> のつけたしをおこなう。
    # (num はゼロからスタートすることに注意)
    # 左端 : @figtable_num * n       (remainder == 0)
    # 右端 : @figtable_num * n - 1   (remainder == @figtable - 1)
    #
    remainder  = num % @figtable_num    # 余り
    figtable_1 = @figtable_num - 1      # 列数 - 1
    td_width   = (100 / @figtable_num).truncate.to_s + "%"  # 一つの td の幅
    debug(num, remainder, figtable_1, @figtable_num, td_width)

    html_table_part  = ""

    # 左端用の <tr> タグ
    if remainder == 0 then
      html_table_part = <<-HTMLEOF
      <tr valign="center">
      HTMLEOF
    end

    # 画像ファイル名が "label" の場合には comment をそのまま書き出す。
    if /^label$/ =~ fig_name_nohead.chomp.strip then
      html_table_part << <<-HTMLEOF
       <td align="#{align}" width="#{td_width}" valign="center">
        <small>
         #{comment}
        </small>
       </td>
      HTMLEOF

    # 画像ファイル名が存在しない場合は空白を書き出す。
    elsif !(str_and_notspace?(fig_name_nohead)) then
      html_table_part << <<-HTMLEOF
       <td align="#{align}" width="#{td_width}" valign="top">
          &nbsp;
       </td>
      HTMLEOF

    # 上記以外の場合には、絵の縮小版とそのリンクを張り込む
    else
      if blankfig || @blankfig
        fig_name_show = ""
      else
        fig_name_show = "\n             #{fig_name_nohead}<br>\n"
      end
      html_table_part << <<-HTMLEOF
       <td align="center" width="#{td_width}" valign="top">
         <a href="#{rel_figdir}/#{fig_name}">
         <img src="#{rel_thumbnaildir}/#{thumbnail_name}" border="1" width="#{@img_width.to_s}" height="#{@img_height.to_s}">
         </a>
         <div align="#{align}">
           <small>#{fig_name_show}
             #{comment}<br><br>
           </small>
         </div>
       </td>
      HTMLEOF
    end

    # 右端用の </tr> タグ
    if remainder == figtable_1 then
      html_table_part << <<-HTMLEOF
      </tr>
      HTMLEOF
    end

    return html_table_part
  end

  #
  # フッター作成用メソッド。相当する文字列を返す。
  # DCModelThumbnail.html_header で得られる文字列で始まる HTML を
  # 閉じることを想定している。
  #
  def html_footer()
    # @index のディレクトリから見た、生成スクリプトの相対的な位置
    generator = relative_str("#{$0}", @index)

    # @index のディレクトリから見た、情報ファイルの相対的な位置
    infofile  = relative_str(@infofile, @index)

    #
    # フッターとして書き出し
    #
    html_footer = <<-HTMLEOF
<hr size="1">
<center>
<small>
  This page is generated by <a href=\"#{generator}\">#{generator}</a>
  and <a href=\"#{infofile}\">#{infofile}</a>
  (#{Time.now.strftime("%Y/%m/%d %H:%M:%S")} #{username_from_uid})<br>
  #{@self_name} 
  [<a href="#{PUB_BIN_URL}">Script</a> |
  <a href="#{PUB_DOC_URL}">Doc</a> | <a href="#{PUB_SAMPLE_URL}">Sample</a>]
  is provided by 
  <a href="http://www.gfd-dennou.org/library/dcmodel">dcmodel project</a> 
  in
  <a href="http://www.gfd-dennou.org">GFD Dennou Club</a> <br>
  Copyright &copy; #{@copyright} #{Time.now.strftime("%Y")}
</small>
</center>
</body>
</html>
    HTMLEOF
    return html_footer
  end

  #
  # mes で与えられる本文の行頭を解析し、その本文が HTML であるか、
  # RD であるか、RT であるのかを判別する。現在、以下のように判定している。
  #
  # * 行頭文字が「=begin」、「=begin RD」、「=begin rd」
  #   * RD のフォーマットであると判別
  #
  # * 行頭文字が「=begin RT」、「=begin rt」
  #   * RT のフォーマットであると判別
  #
  # * 上記以外
  #   * HTML フォーマットであると判別
  #
  # 返り値は "html", "rd", "rt" のいづれかである。なお、body に
  # String オブジェクト以外、もしくは完全に空白のみが入っている場合、
  # nil を返す。
  #
  def format_parser(body=nil)
    debug(body)
    if !(str_and_notspace?(body)) then
      return warn_or_err("\"body\" is not String Object.\n")
    end

    Kconv::toeuc(body)
    body_parts = body.split("\n")

    body_parts.each{ |line|
      next unless /\w+/e =~ line.chomp.strip
      if /=begin\s+(rt)/ie =~ line.chomp.strip
        return "rt"
      elsif /=begin/ie =~ line.chomp.strip
        return "rd"
      elsif /=begin\s+(rd)/ie =~ line.chomp.strip
        return "rd"
      else
        return "html"
      end
    }
    return nil
  end

  #
  # 引数 rd に与えられた文字列を rd2html を掛けた文字列として
  # 返す。デフォルトでは "=begin" や "=end" が存在しない文字列を
  # 想定している。この場合、rd 文字列を "=begin" と "=end"
  # ではさまれたものとして自動的に解釈する。もしも "=begin"
  # や "=end" が書き込まれた文字列を rd として与えたい場合は
  # 引数 beginend を true にすること。返される html は <body> 以上と
  # </body> 以下は省かれた本文部分のみである。
  #
  # err が nil や false の場合、mes に与えられたメッセージを
  # 警告として表示する。err が真の場合はそのメッセージの出力
  # と同時にエラーを発生させ、プログラムを終了させる。
  #
  # もしも rd2 コマンドが存在しない場合には nil を返す。
  #
  # なお、現在は rd2html-ext-lib を必ず利用するようになっているので
  # インスタンス変数 rd2htmlextlib を適宜設定しないとまともに
  # 動かないので注意すること。
  #
  # 返される文字列を探査し、A タグの NAME, HREF 属性に用いられる
  # "label-XX" のナンバーを保持しておき、再度このメソッドが呼ばれた場合には、
  # 文字列内の "label-XX" のナンバーを自動的に繰り上げる。
  #
  # relabel メソッドを呼ぶことで、別々の rd2html で HTML に変換された
  # 文字列内のラベルのリンクを作成する。
  #
  def rd2html(rd=nil, beginend=true, quiet=nil, err=nil)
    debug(rd)

    if !(FileTest.executable?(@rd2_path)) then
      return warn_or_err(
                         "\"#{@rd2_path}\" is not excutable.\n",
                         err, quiet, ArgumentError)
    elsif !rd
      return warn_or_err(
                         "\"rd\" is invalid.\n",
                         err, quiet, ArgumentError)
    end

    debug(@rd2_path)

    # "=begin" や "=end" を消去するための処理 (行頭のものしか消さない)
    rd_body = ""
    if beginend then
      rd_parts = rd.split("\n")
      debug(rd_parts)
      rd_parts.each { |line|
        if /^=begin\s+.*/ =~ line then
          next
        elsif /^=begin$/ =~ line then
          next
        elsif /^=end\s+.*/ =~ line then
          next
        elsif /^=end$/ =~ line then
          next
        else
          rd_body << line + "\n"
        end
      }
    else
      rd_body = "#{rd}"
    end
    debug(rd_body)


    # rd で得られた文字列を /tmp/dcmodel-thum-$$.rd に一時的に格納
    rdfile_tmp = @tmp + "/" + File.basename($0.to_s) + "-" + $$.to_s
    debug(rdfile_tmp)

    tmpfile = open(rdfile_tmp, "w")
    tmpfile.print "=begin\n"
    tmpfile.print rd_body
    tmpfile.print "\n=end\n"
    tmpfile.close

    debug(open(rdfile_tmp){|io| io.read})
#    print "#{open(rdfile_tmp){|io| io.read}}"

#    # ライブラリパスを $: に追加
#    @rd2lib.each{ |path|
#      next if !(str_and_notspace?(path))
##      $:.push(path)
#      $:.unshift(path)
#    }
#    debug($:)

    #
    # コマンドの文字列を整形
    #
    cmd  = "#{@rd2_path}"
    cmd << " -r rd/rd2html-ext-lib"
    cmd << " --with-css=#{@css}"
    cmd << " --with-part=\'RT:rt\'"
    cmd << " --with-part=\'HTML:html\'"
    cmd << " --out-code=euc"
    cmd << " --ref-extension"
    cmd << " --native-inline"
    cmd << " --head-element"
#    cmd << " --headline-secno"
#    cmd << " --enable-br"

    debug(cmd)
    html_org = IO.popen("export RUBYLIB=#{@rd2htmlextlib} ; #{cmd} #{rdfile_tmp}").read
    debug(html_org)

    html_body_each_line = html_org.split(/\n/)
    debug(html_body_each_line)

    html_body = ""
    bodyflag = false
    html_body_each_line.each{ |line|
      if /^.*<body.*$/ =~ line then
        bodyflag  = true
        next
      elsif /^.*<\/body.*$/ =~ line
        bodyflag  = false
      else
        html_body << line + "\n" if bodyflag
      end
    }

    # ラベルの張り替え
    html_body_relabeled = "#{html_body}"

    last_label_num = -1
    while html_body =~ /\<a\s+name\=\"label\-(\d+)\"\s+id\=\"label\-\d+\"\>(.*?)\<\/a\>/i
      last_label_num = $1.to_i
      html_body = $~.post_match
      labeled_str = $2
      @label_num_header_hash.store(last_label_num + @label_num, labeled_str)
    end

    if last_label_num >= 0
      if @label_num < 1
        @label_num = last_label_num + 1
      else
        last_label_num.downto(0){|i|
          html_body_relabeled.gsub!(/(\<a\s+name\=\"label\-)#{i.to_s}(\"\s+id\=\"label\-)#{i.to_s}(\"\>.*?\<\/a\>)/i, "\\1#{(i + @label_num).to_s}\\2#{(i + @label_num).to_s}\\3")
          html_body_relabeled.gsub!(/(\<a\s+href\=\"\#label\-)#{i.to_s}(\"\>)/i, "\\1#{(i + @label_num).to_s}\\2")
        }
        @label_num = @label_num + last_label_num + 1
      end
    end

    # テンポラリファイルを削除
    File.delete(rdfile_tmp)

    debug(html_body_relabeled)
    return html_body_relabeled
  end

  #
  # rd2html メソッドで呼ばれた別々の HTML 同士のラベル間に関して
  # ハイパーリンクを貼る. rd2html を一通り呼び終わった後に, その
  # rd2html から返る HTML をまとめたものを引数 *html* として与える.
  #
  def relabel(html=nil, quiet=nil, err=nil)
    debug(html)

    if !html
      return warn_or_err(
                         "\"html\" is invalid.\n",
                         err, quiet, ArgumentError)
    end

    html_relabeled = "#{html}"
    @label_num_header_hash.each{|num, word|
      html_relabeled.gsub!(
                           /\<\!\-\-\s+Reference\,\s+RDLabel\s+\"#{word}\"\s+doesn\'t\s+exist\s+\-\-\>\<em\s+class\=\"label\-not\-found\"\>#{word}\<\/em\>\<\!\-\-\s+Reference\s+end\s+\-\-\>/im, 
                           "<a href=\"#label-#{num.to_s}\">#{word}</a>")
    }

    debug(html_relabeled)
    return html_relabeled
  end

  #
  # target で与えられたパス (String オブジェクト) を from (String 
  # オブジェクト) から見た相対パスとして String オブジェクトで返す。
  # 内部で Pathname クラスを利用している。
  # 与えられるパスは絶対パスでも相対パスでもかまわない。
  #
  def relative_str(target=nil, from=nil)
    return nil    unless str_and_notspace?(target)
    return target unless str_and_notspace?(from)

    from_dir     = File.dirname(from)
    target_dir   = File.dirname(target)
    target_base  = File.basename(target)

    from_ab_path   = Pathname.new(File.expand_path(from_dir))
    target_ab_path = Pathname.new(File.expand_path(target_dir))

    target_re_path = target_ab_path.relative_path_from(from_ab_path)

    result = target_re_path.to_s + "/" + target_base

    return result
  end

  #
  # SIGEN ファイル作成メソッド。
  # 書式等詳しいことは
  # <http://www.gfd-dennou.org/library/cc-env/mksigen/desc.htm>
  # を参照のこと
  #
  def mksigen_write(file=nil  , subject=nil    , maintainer=nil, 
                    update=nil, update_info=nil,
                    desc=nil  , note=nil       , prune=nil     , 
                    quiet=nil , err=true)
    # 引数の検査
    if !(str_and_notspace?(file)) then
      return warn_or_err("\"file\" is not specified.",
                         err, quiet, ArgumentError)
    end
    if !(str_and_notspace?(subject)) then
      return warn_or_err("\"subject\" is not specified.",
                         err, quiet, ArgumentError)
    end

    # 引数が無効でも補完するもの
    if !(str_and_notspace?(maintainer)) then
      maintainer = jpname_from_uid || username_from_uid || "Unknown"
    end
    if !(str_and_notspace?(update)) then
      update = Time.now.strftime("%Y/%m/%d")
    end
    if !(str_and_notspace?(update_info)) then
      update_info  = ""
    end
    if !(str_and_notspace?(desc)) then
      desc   = ""
    end
    if !(str_and_notspace?(note)) then
      note   = ""
    end
    if prune then
      prune  = "Prune: 1"
    else
      prune  = ""
    end

    #
    # 出力内容の格納
    #
    sigen = <<-SIGEN
Subject:	#{subject.chomp}
Maintainer:	#{maintainer.chomp}
Description:	#{desc.chomp}
Note:		#{note.chomp}
Update:		#{update.chomp}  #{update_info.chomp}
#{prune}
    SIGEN

    #
    # 文字コード設定
    #
    Kconv::toeuc(sigen)

    #
    # ファイルの作成
    #
    ifile = open(file, "w")
    ifile.print "#{sigen}"
    ifile.close

  end


  #
  # 以降は Private メソッド
  #

  #
  # 引数 uid に対応するユーザ名 (ログイン名) を返す。
  # uid に nil を与えた場合はプロセスの uid に対応するユーザ名 (ログイン名)
  # を返す。uid が無効なものである場合、エラーを返す。
  #
  def username_from_uid(uid=nil)
    unless uid
      pw = Etc.getpwuid(Process.uid) or return nil
    else
      pw = Etc.getpwuid(uid) or return nil
    end

    user_name = pw.name
    return user_name
  end
  private :username_from_uid

  #
  # 引数 gid に対応するユーザ名 (ログイン名) を返す。
  # gid に nil を与えた場合はプロセスの gid に対応するユーザ名 (ログイン名)
  # を返す。gid が無効なものである場合、エラーを返す。
  #
  def username_from_gid(gid=nil)
    unless gid
      pw = Etc.getpwuid(Process.gid) or return nil
    else
      pw = Etc.getpwuid(gid) or return nil
    end

    user_name = pw.name
    return user_name
  end
  private :username_from_gid

  #
  # 引数 uid に対応するユーザ名 (日本語) を返す。
  # uid に nil を与えた場合はプロセスの uid に対応するユーザ名 (日本語)
  # を返す。
  #
  # 日本語名は gate-toroku-system <http://www.ep.sci.hokudai.ac.jp/~gate>
  # によるデータベースから取得するため、このシステムがインストールされて
  # いない場合には nil を返す。
  #
  # 引数 family_name に true を与えた場合、姓のみを返そうと試みる。
  # データベースの和名が半角空白または全角空白で区切られる場合、
  # 姓のみを返すことが可能である。
  #
  def jpname_from_uid(uid=nil, family_name=nil)
    if FileTest.executable?(@gate_user_show)
      gate_user_database = IO.popen("#{@gate_user_show} #{username_from_uid(uid)}")

      #
      # 以下は、完全に gate-toroku-system のデータベース依存である。
      # 詳しくは <http://www.ep.sci.hokudai.ac.jp/~gate/doc/gate-user-db.htm>
      # を参照せよ。
      #
      while gate_user_data = gate_user_database.gets do
        gate_user_data.chomp!
        if /^kname/ =~ gate_user_data
          jpname_key, jpname_value = gate_user_data.split(/: /, 2)
          Kconv::toeuc(jpname_value)
        end
        # 名字だけ取り出そうと試みる。
        #   (姓名の間に半角空白または全角空白が無い時は無理)
        if family_name && /(.+)[\s|　]+.+/e =~ jpname_value then
          jpname = $1
        else
          jpname = jpname_value
        end
      end
    else
      jpname = nil
    end

    return jpname
  end
  private :jpname_from_uid


  #
  # 代入された変数が、文字列で、且つ空白文字のみではないことを
  # 調べるメソッド。日本語であっても、文字列が入っていれば true を返す。
  #
  def str_and_notspace?(obj)
    debug(obj)

    if !obj.instance_of?(String) then
      return false
    end

    # 日本語の文字列も対応できるように
    Kconv::toeuc(obj)

    if /\S+/e =~ obj.chomp.strip then
      return true
    else
      return false
    end
  end
  private :str_and_notspace?

  #
  # 代入された変数が、配列で、且つゼロ配列ではないことを
  # 調べるメソッド
  #
  def array_and_notzero?(obj)
    debug(obj)

    if obj.instance_of?(Array) && obj.size > 0 then
      return true
    else
      return false
    end

  end
  private :array_and_notzero?

end

######################################################
if $0 == __FILE__
  thumb = DCModelThumbnail.new

  # 引数が与えられたらヘルプを表示
  if ARGV.size > 0 then
    $stdout.print <<-EndOfHelp

#{thumb.self_name} -- version \"#{thumb.version}\"

Please see following documents.
(Sorry, I do not prepare enough help message, and roff format for man(1).)

  #{thumb.pub_sample_url}
  #{thumb.pub_doc_url}

EndOfHelp

    exit(1)
  end

  # 子プログラムの存在をチェック
  if File.exist?(thumb.sub_rb_name)
    raise IOError, "\n\n  Error : \"#{thumb.sub_rb_name}\" is already exist.\n\n"
  end

  # 子プログラム生成
  $stdout.print "\n#{thumb.self_name} -- version \"#{thumb.version}\" ...\n\n"
  $stdout.print "  Message : Generating Sample Ruby script \"#{thumb.sub_rb_name}\"...."
  thumb.create_sample_rb(thumb.sub_rb_name)
  $stdout.print "  done.\n\n"

end
