Hatena::ブログ(Diary)

名もないテクノ手 このページをアンテナに追加 RSSフィード

EPUB版『InDesign者のための正規表現入門』

InDesignのTips一覧

2011-12-26

[][][]インタラクティブPDFの作り方

電子書籍といえば、EPUBやリッチなアプリなどが注目されていますが、PDFも立派な電子書籍です。PDFの表現能力はフォントやレイアウトの再現性だけじゃありません。動画も貼れるしボタンもつけられます。インタラクティブなフォームやリンク、電子透かしや認証方式も選べたり、印刷やコピーの許可などのセキュリティも備わっています。リーダーさえ対応していれば、JavaScriptだって動作します。


インタラクティブPDFの詳しい解説書が、インタラクティブPDFによって出版されています。

個々のインタラクティブ機能について、たいへんわかりやすい教材になっています。実際の動きを見ながらインタラクティブPDFを作ることができるでしょう。


出版・印刷業界以外の方々はご存知ないかもしれませんが、現在では出版物のデジタル化はほぼ完了していて、新規出版物は「今すぐ」PDFで電子書籍化できるようになっています(オライリーみたいに)。ADPSのような大掛かりで高コストなソリューションを導入しなくても、たいていのインタラクティブ機能は既にここにあります。PDFをスルーしなければならない理由はありません。

2011-10-17

[][]Adobe Reader for iPhone (and iPad)

iPhoneiPad向けのAdobe純正のPDFビューア「Adobe Reader」が配布されています。

[?] Adobe Reader - iTunes App Store で Adobe Reader をダウンロード

f:id:seuzo:20111017155821p:image


早速iPhone4(iOS5)入れてみました。ファーストリリースなので、いろいろ不具合もあるかもしれませんが、とりあえず第一印象は...

GoodReaderなどに比べてて描画遅いような気がします。

HTMLリンクや手動のリンクも効かないようです。JavaScriptも無視されています。テキスト検索も遅いです(5ページ1000文字程度)。何度かテキスト検索をしていたら、フリーズしてしまいました^^

埋め込まれた注釈は読めるようです。

f:id:seuzo:20111017155819p:image

閲覧時にパスワード制限のかかっているPDFも、パスワード入力で読めました。

f:id:seuzo:20111017155820p:image

2011-08-03

[][][][]作業中のカレントページを、単ページでPDF書出す「export_currentpage_byPDF 1.0」

何をするスクリプトか?

作業中のカレントページを、単ページでPDF書出しします。

一度初期設定をすれば、しばらくの間、設定レスで使い続けられます。

D


同梱ファイル(2Files)

Readme.txt このファイルです。とにかく最初によんでください。

export_currentpage_byPDF.jsx スクリプト本体です。


使用条件

このスクリプトが正常に動作する環境は以下の通りです。Windows環境でも動作する可能性がありますが未検証です。


ダウンロード

http://www.seuzo.jp/st/scripts_InDesignCS5/index.html#export_currentpage_byPDF


インストール

スクリプト本体(export_currentpage_byPDF.jsx)を

~/Library/Preferences/Adobe InDesign/Version 7.0-J/ja_JP/Scripts/Scripts Panel/

にコピーしてください。エイリアスを入れておくだけでもかまいません。

スクリプトパレットから使用します。


使用方法

(0)「ウインドウ」メニューから「スクリプティング」ー「スクリプト」を選択し、スクリプトパレットを出します。

(1)書出したいページを表示します。どのページがカレントページかわからない時は、レイアウトウインドウ左下のページ欄を確認してください。

(2)スクリプトパレットから、スクリプト「export_currentpage_byPDF.jsx」をダブルクリックします。

(3)最初の起動時に「保存フォルダ」「使用する書出しプリセット」を設定するダイアログが出ます。

(4)書出しを確認するダイアログが出ます。ページ数を確認して「はい」をクリックしてください。

  • 最後に起動してから3日間は設定が有効です。起動する度に初期設定は自動更新されます。
  • 初期設定をやりなおしたい時は、このスクリプトと同じ階層にある「export_currentpage_byPDF_config.txt」を削除してください。
  • 保存先に同じ名前のPDFがある場合、上書きするかどうかを選択できます。

特別な設定

ソースコード中の13行目あたりから書かれている設定を変更すると、スクリプトの振る舞いカスタマイズできます。

////////////////////////////////////////////設定
var my_expiration_date = 3;//有効期限(日)。初期設定をしなおさないで済む期間
var my_config_filename = 'export_currentpage_byPDF_config.txt';//設定ファイル名
var my_confirmation = true;//処理前に確認ダイアログを表示するかどうか
var my_digitnum = 3;//ノンブルが数値だったら、桁を揃える。2=>002, 45=>045, 123=>123

既知の不具合、またはToDo



免責事項

  • 本アプリケーションはInDesignにおける作業効率支援なのであって、処理結果を保証するものではありません。かならず確認をされることをおすすめします。
  • このツールを使用する上でデータの破損などのあらゆる不具合・不利益については一切の責任を負いかねますのでご了解ください。
  • このツールはすべてのMacintoshとMac OS上で動作をするという確認をとっていませんし、事実上出来ません。したがって、動作を保証するものではありません。

ライセンス

GNU GPLv3

http://sourceforge.jp/projects/opensource/wiki/licenses%252FGNU_General_Public_License_version_3.0


履 歴

2011-08-02 ver.0.1 AppleScriptで使っていたものをJavaScriptで書き直し


/*
export_currentpage_byPDF.jsx
(c)2011 seuzo

作業中のカレントページを、単ページでPDF書出しします。
一度初期設定をすれば、しばらくの間、設定レスで使い続けられます。

2011-08-02	ver1.0	AppleScriptで使っていたものをJavaScriptで書き直し


*/

#target "InDesign"
////////////////////////////////////////////設定
var my_expiration_date = 3;//有効期限(日)。初期設定をしなおさないで済む期間
var my_config_filename = 'export_currentpage_byPDF_config.txt';//設定ファイル名
var my_confirmation = true;//処理前に確認ダイアログを表示するかどうか
var my_digitnum = 3;//ノンブルが数値だったら、桁を揃える。2=>002, 45=>045, 123=>123
var my_script_version = '1.0';//このスクリプトのバージョン
var my_date_record = '';//最終設定日(あとで設定)
var my_save_folder_path = '';//PDF保存フォルダ(あとで設定)
var my_pdf_presets = '';//PDFプリセット名(あとで設定)


////////////////////////////////////////////エラー処理 
function myerror(mess) { 
  if (arguments.length > 0) { alert(mess); }
  exit();
}

////////////////////////////////////////////カレントスクリプトのフルパスを得る 
function get_my_script_path() {
	try {
		return  app.activeScript;
	} catch (e) {
		return File (e.fileName);//ESTKから実行した時も正しくパスを返す
	}
}

////////////////////////////////////////////OSのファイルセパレータを得る 
function get_separator() {
    if (Folder.fs ==="Macintosh") {
        return "/";
    } else {
        return "\\";
    }
}

////////////////////////////////////////////ファイル・フォルダ選択ダイアログ。パス文字列を返す。
function chooseF(my_prompt, my_kind) {
	var my_path = '';
	if (my_kind === "Folder") {
		my_path = my_path + Folder.selectDialog (my_prompt);
	} else {
		var my_regex = new RegExp('\\' + my_kind + '$');
		my_path = my_path + File.openDialog (my_prompt, function(file){return(file.name.match(my_regex) || file instanceof Folder) ? true : false}, false );
	}
	return my_path
}

////////////////////////////////////////////ファイルの内容を読み込んで返す 
function read_file(my_read_file_path) {
	var my_file_obj = new File(my_read_file_path);
	if (!(my_file_obj.exists)) {myerror("ファイルがありません\n" + my_read_file_path)};
	if(my_file_obj.open("r")) {
		var tmp_str = my_file_obj.read();
		my_file_obj.close();
	} else {
		myerror("ファイルが開けません\n" + my_read_file_path);
	}
	 tmp_str = tmp_str.replace(/[\r\n]+$/, '');//最後の行末の改行を削除
	return tmp_str;
}

////////////////////////////////////////////データをファイルに書き込む 。書き込んだファイルオブジェクトを返す
function write_file(my_write_file_path, my_data) {
	var my_file_obj = new File(my_write_file_path);
	my_file_obj.encoding = "UTF-8";//★この行がないとShift-JISで書き出される
	//if (!(my_file_obj.exists)) {myerror("ファイルがありません\n" + my_write_file_path)};
	if(my_file_obj.open("w")) {
		my_file_obj.write(my_data);
		my_file_obj.close();
		return my_file_obj;
	} else {
		my_error("ファイルが開けません\n" + my_write_file_path);
	}
}

////////////////////////////////////////////ポッップアップダイアログ
function popupDialog(myTitle, myPrompt, myList){
	var myDialog, mySelecteditem, ans;
	myDialog = app.dialogs.add({name:myTitle,canCancel:true});
	with(myDialog){
		with(dialogColumns.add()){
			staticTexts.add({staticLabel:myPrompt});// プロンプト
		}
		with(dialogColumns.add()){
			mySelecteditem = dropdowns.add({stringList:myList, selectedIndex:0});// ポップアップメニュー
		}
	}
	// ダイアログボックスを表示
	if(myDialog.show() === true){
		ans = mySelecteditem.selectedIndex;
		myDialog.destroy();//正常にダイアログを片付ける
		return ans//選択したアイテムの番号を返す
	} else {
		// ユーザが「キャンセル」をクリックしたので、メモリからダイアログボックスを削除
		myDialog.destroy();
		exit();//スクリプト終了
	}
}

////////////////////////////////////////////数値のゼロパディング。str=数値、digitnum=桁数
function set_zaropadding(str, digitnum) {
    var str = str.toString();
    if (str.search(/^[0-9]+$/) === -1) {//数字じゃない
        return str;//そのまま返す
    }
    if (str.length >= digitnum) {//指定桁数以上ある
        return str;//そのまま返す
    }
     var zero_str = '';
     for (var i = 0; i < my_digitnum; i++) {
         zero_str+= "0";
     }
    return (zero_str + str).slice( 0 - digitnum);
}

////////////////////////////////////////////初期設定&設定ファイル書き込み
function write_setting(my_write_file_path) {
    var tmp_data = my_script_version + "\r";//my_script_versionはグローバル変数を期待
    tmp_data += new Date().toString() + "\r";//現在の日付
    tmp_data += chooseF("PDFを保存するフォルダを選んでください", "Folder").toString() + "\r";
    var my_pdf_presets_list = app.pdfExportPresets.everyItem().name;//すべてのプリセット名リスト
    var my_pdf_presets = popupDialog("プリセット選択", "PDF書出しプリセットを選んでください", my_pdf_presets_list);
    tmp_data += my_pdf_presets_list[my_pdf_presets];
    write_file(my_write_file_path, tmp_data);
    return true;//書き込み済みであることのフラグ
}



////////////////////////////////////////////メイン 
if (app.documents.length === 0) {myerror("ドキュメントが開かれていません")}
var my_doc = app.documents[0];
//名前やパスなどの調査
var my_doc_name = (my_doc.name).replace (/\.ind[d0-9]?$/i, "");//拡張子を除いたファイル名
var my_page = app.layoutWindows[0].activePage;
var my_page_no = my_page.name;//ページ名(ノンブル文字列)
var my_separator = get_separator();//パスの区切り文字
var my_activescript_path = get_my_script_path();//このスクリプトのパス
var my_activescript_folder = File(my_activescript_path).parent;//このスクリプトのコンテナフォルダ
var my_config_path = my_activescript_folder + my_separator + my_config_filename;//設定ファイルのフルパス

//設定ファイルの読み書き
var f_modified = false;//ファイルを書き込んだかどうかのフラグ(余計な読み書き回数を減らすために)
//設定ファイルがなかったら
if (File(my_config_path).exists === false) {
    f_modified = write_setting(my_config_path);//設定して書き込み
}
//設定ファイルの読み出し
var my_data_list = read_file(my_config_path);
my_data_list = my_data_list.split(/[\r\n]+/);
var my_date_record = new Date(my_data_list[1]);//最終設定日
var my_save_folder_path = my_data_list[2];//PDF保存フォルダ
var my_pdf_presets = my_data_list[3];//PDFプリセット名
//設定ファイルが古かったら
var my_date_now = new Date();
if (my_date_now - my_date_record > my_expiration_date * 86400000) {
     f_modified = write_setting(my_config_path);//設定して書き込み
    var my_data_list = read_file(my_config_path);//そして読み込み
    my_data_list = my_data_list.split(/[\r\n]+/);
    var my_date_record = new Date(my_data_list[1]);//最終設定日
    var my_save_folder_path = my_data_list[2];//PDF保存フォルダ
    var my_pdf_presets = my_data_list[3];//PDFプリセット名
} 
//今回、新規設定を書き込みしていなければ、現在の設定を上書きして最新にしておく
if ( f_modified === false) {
    var tmp_data = my_script_version + "\r";
    tmp_data+= my_date_now.toString() + "\r";
    tmp_data+= my_save_folder_path + "\r";
    tmp_data+= my_pdf_presets;
    write_file(my_config_path, tmp_data);
}

var my_pdf_file_path = my_save_folder_path + my_separator + my_doc_name + '_' + set_zaropadding(my_page_no, my_digitnum) + '.pdf';//書き出されるPDFのフルパス。ノンブルは指定桁数でzero paddingする。
//確認
if (my_confirmation) {
    var my_button = confirm(my_page_no + "ページを書出しますか\r書出しプリセット:" + my_pdf_presets + "\r書出しパス:" + my_pdf_file_path, false, undefined);
    if (my_button === false){exit()};//終了
}

//PDF書出し
//すでに同名のファイルがあった時
if (File(my_pdf_file_path).exists) {
    var my_button = confirm("同名のPDFファイルがあります:\r"+my_pdf_file_path+"\r上書きしますか?", true, undefined);
    if (my_button === false){exit()};//終了
}
app.pdfExportPreferences.pageRange = my_page_no;
try{
    my_doc.exportFile(ExportFormat.PDF_TYPE, File(my_pdf_file_path), false, my_pdf_presets);//書出し
}catch(e){
    myerror("Error: "+e.message+" (Line "+ e.line+" in this script code.)");//エラー
}

2010-12-03

[][][][]InDesignから書き出されたPDFは、InDesignの操作履歴をもっている。時には大量に。

ExifToolを触っていたらへんなことに気がついてしまった。InDesignから書き出されたPDFは、XMPの中にInDesignの操作履歴をもってるみたい。

$ exiftool A.pdf
ExifTool Version Number         : 7.52
File Name                       : A.pdf
Directory                       : .
File Size                       : 422 kB
File Modification Date/Time     : 2010:12:03 11:26:54+09:00
File Type                       : PDF
MIME Type                       : application/pdf
PDF Version                     : 1.3
XMP Toolkit                     : Image::ExifTool 7.52
Format                          : application/pdf
Doc Change Count                : 107
Creator Tool                    : Adobe InDesign CS5_J (7.0.3)
Metadata Date                   : 2010:12:03 11:19:16+09:00
Document ID                     : xmp.did:FD7F117407206811A961D08B23C087A9
History Action                  : created, saved, saved, saved, saved, saved, saved, saved, saved, saved, saved, saved, saved, saved, saved
History Instance ID             : xmp.iid:FD7F117407206811A961D08B23C087A9, xmp.iid:FE7F117407206811A961D08B23C087A9, xmp.iid:FF7F117407206811A961D08B23C087A9, xmp.iid:0080117407206811A961D08B23C087A9, xmp.iid:27CA6B9219206811A961D08B23C087A9, xmp.iid:28CA6B9219206811A961D08B23C087A9, xmp.iid:2FCA6B9219206811A961D08B23C087A9, xmp.iid:30CA6B9219206811A961D08B23C087A9, xmp.iid:086F72D11A206811A961D08B23C087A9, xmp.iid:FC7F1174072068118C14F973A1F0976C, xmp.iid:FD7F1174072068118C14F973A1F0976C, xmp.iid:FE7F1174072068118C14F973A1F0976C, xmp.iid:FF7F1174072068118C14F973A1F0976C, xmp.iid:00801174072068118C14F973A1F0976C, xmp.iid:B4A18584072068118C14F973A1F0976C
History Software Agent          : Adobe InDesign 6.0, Adobe InDesign 6.0, Adobe InDesign 6.0, Adobe InDesign 6.0, Adobe InDesign 6.0, Adobe InDesign 6.0, Adobe InDesign 6.0, Adobe InDesign 6.0, Adobe InDesign 6.0, Adobe InDesign 7.0, Adobe InDesign 7.0, Adobe InDesign 7.0, Adobe InDesign 7.0, Adobe InDesign 7.0, Adobe InDesign 7.0
History When                    : 2010:07:03 15:08:01+09:00, 2010:07:03 15:08:49+09:00, 2010:07:03 15:08:49+09:00, 2010:07:03 15:15:34+09:00, 2010:07:03 15:21:50+09:00, 2010:07:03 15:22:03+09:00, 2010:07:03 15:28:18+09:00, 2010:07:03 15:28:43+09:00, 2010:07:03 15:29:51+09:00, 2010:12:03 11:18:39+09:00, 2010:12:03 11:18:39+09:00, 2010:12:03 11:18:41+09:00, 2010:12:03 11:18:43+09:00, 2010:12:03 11:18:46+09:00, 2010:12:03 11:18:47+09:00
History Changed                 : /, /metadata, /, /, /, /, /, /, /;/metadata, /metadata, /;/metadata, /;/metadata, /;/metadata, /;/metadata
Instance ID                     : uuid:6288af79-e6ab-d343-8d4f-cbd97649a750
Original Document ID            : xmp.did:FD7F117407206811A961D08B23C087A9
Rendition Class                 : proof:pdf
Version ID                      : 1
Page Count                      : 20
Create Date                     : 2010:12:03 11:19:15+09:00
Creator                         : Adobe InDesign CS5_J (7.0.3)
GTS PDFX Conformance            : PDF/X-1a:2001
GTS PDFX Version                : PDF/X-1:2001
Modify Date                     : 2010:12:03 11:19:16+09:00
Producer                        : Adobe PDF Library 9.9
Title                           : A
Trapped                         : False

「History Action」「History Instance ID」「History Software Agent」「History When」「History Changed」などの項目だ。これらはBridgeからも参照できる。

f:id:seuzo:20101203115209p:image

まあ、この程度だったらまあ許せる範囲なんだけど、操作履歴だからこれがものすごくたくさん残っていることがある。この部分だけで何十KBにもなることがある。あれ、バイナリ開いちゃった? くらいの勢いになる。なぜPDFがInDesignのヒストリを持っている必要があるのかはわからない。「PDFよ、何故親の過去を背負う?」。まあ消しちゃっていいかな? いいとも! ということで消してみました。

# coding: utf-8
#require 'rubygems'
require 'mini_exiftool'

ARGV.each do |my_file|
	tmp_f = MiniExiftool.new(my_file)
	tmp_f['HistoryAction'] = ''
	tmp_f['HistoryChanged'] = ''
	tmp_f['HistoryInstanceID'] = ''
	tmp_f['HistorySoftwareAgent'] = ''
	tmp_f['HistoryWhen'] = ''
	tmp_f.save
end

(追記:2010-12-03T13:00:53+0900)@pictexさんにもご指摘いただきましたが、Rubyを使わなくてもAcrobat Proの最適化を使えば、ユーザーのメタデータは破棄できます。「ユーザーデータの破棄」-「文書情報とメタデータを破棄」です。バッチ処理にも組み込めます。ただし、特定の要素だけを破棄(変更)するには上記のような方法も有効です。

2010-10-14

[]バラバラのPDFをリンクで繋いでいく

PDFをセクションで分けてひとつひとつのPDFを軽くしようとした場合、ナビゲーションというかページ遷移はどうするとよいでしょうか? いちいち目次に戻って次セクションに行くのはちょっとめんどい気がします。

複数のPDFがあった場合、常に目次にリンクするだけじゃなく、1ページ目には前セクションのPDFへリンクできるとか、最終ページは次セクションのPDFへリンクできるとか、って話。本当に、こういうUIがよいのかどうか、いろいろ試行錯誤中です。

D

実物のテストPDFはこちら:makelink.zip 直(1.6MB)

リンク作成そのものは、InDesignから作り込むやり方もあるし、PDF上でリンクを作成する方法もあるけれど、とりあえずスクリプトでやってみました。各ページにJavaScriptを埋め込んで別PDFを開いていますのでAcrobatでないと動作しません^^