PDFをJPEG画像に変換して表示する機能が欲しい

PDFをJPEG画像に変換して表示する機能が欲しい

- Tatsuya Shirai の投稿
返信数: 20

 WiiやPS3をWeb閲覧用のキオスク端末(Moodle専用)にできないか?ということを少し検討してみました.これらのゲーム端末はメンテナンスが容易であり,単価がPCより安いというのが一番の理由です.USBキーボードを接続可能であるのも携帯端末機器との違いです.

 ところがどちらもPDFの表示に対応していません.Moodle閲覧専用に学内に設置すると考えたときに,PDFが表示できないのは困ります.

 諦めるのは少し早すぎるのかも知れません.たとえば私が知らないだけで,バージョンアップの結果,WiiでもPS3でもPDFが表示可能になっているのかも知れないですし,ファームウェアに内蔵された(:PS3の場合)Webブラウザ以外にも市販のWebブラウザが販売されているのかも知れない.この点に関して情報をお持ちの方,よろしくお願いします.

 さて,PDFが表示できないとして,簡単に諦めずに発展的に考えると,ではPDFファイルをfile.php経由でダウンロードする際に,クライアントPCがWiiやPS3の場合はJPEG画像に変換して送れば良いのではないか,と考えました.
 簡単に調べたところ,PDFファイルを画像ファイル(JPEG,PNGなど)に変換したり,HTMLファイルに変換するPHPのライブラリがあるらしいことが少し分かってきました.ただ,それらのソフトウェアが最新のPDFのファイル形式にも対応できているのか,マルチバイト文字にも対応しているのか,は,ものによって微妙に異なるようです.どなたか詳しい方,いらっしゃらないでしょうか.

 もちろん問題はそれほど簡単ではなく,複数ページからなるPDFファイルを一枚の巨大なJPEGファイルに変換してクライアントPCへ転送されては大変なことになります.1ページずつ送ったり,特定のページを表示したりといったユーザインタフェースを備えた機能を用意してあげないといけないですね.

 まとめます.

 PDFを表示できないWeb端末でPDFファイルを表示可能とする技術やサービスは存在するのでしょう?

Tatsuya Shirai への返信

Re: PDFをJPEG画像に変換して表示する機能が欲しい

- Tatsuya Shirai の投稿

 PHPだけでPDFをJPEGに変換するのはなかなか難しそうですね.

 PDFを作成することに関しては情報が多いのですが,「そんな意味の無いことを考える理由が分からない」と一刀両断されている方もいました.お気の毒に.

 ImageMagickとの連携がいまのところ有望でしょうか.Linux版,Windows版,Mac版があるようですので.(Ghostscriptを使ってPPMファイルを取得し,それをさらにJPEGへ,という流れもあるようですが,少し煩雑ですね).とりあえずImageMagickのconvertで,ページを指定して1枚単位でJPEGに変換できそうですので,これが一番無難でしょうか.一旦,調査はここで止めておきます.

Tatsuya Shirai への返信

Re: PDFをJPEG画像に変換して表示する機能が欲しい

- Haruhiko Okumura の投稿
そうなんですか。私の携帯(アドエス)でもPDFくらい表示できるので,当然できるだろうと思っていました。

PDFをJPEGに変換するソフトはいろいろあるみたいですね。どれがいいのかよくわかりませんが,とりあえずGhostscriptならよく知っています。
Haruhiko Okumura への返信

Re: PDFをJPEG画像に変換して表示する機能が欲しい

- Tatsuya Shirai の投稿

 PSPもNintendo DSもPDF表示は対応していないようです.
 PSPに関してはPDFを表示するフリーウェアが存在するようなことがチラリと書いてあるページがあったのですが,Webブラウザでは対応できなさそうです.

 ビジネスマンにアピールしなくてはならない携帯電話と,子供中心のゲーム機との違いが明らかですね.俄然,PDFを表示できる機能があると面白いような気がしてきます.

 なお,ImageMagickはextensionを組み込むことでPHPから呼び出せそうな感じです.Windows版も可能かどうか,分かりませんが.

http://hashi4.civil.tohoku.ac.jp/soft/node43.html
http://www.imagemagick.org/script/api.php#php
http://jp.php.net/imagick

 サーバサイドでPDFの指定したページを指定したサイズのJPEGファイルに変換することさえできてしまえば,実は技術的にハードルがそれほど高くない問題なのかも知れません.それでPDF非対応の機器でもPDFが閲覧(拡大縮小なども)ができるならばアピール度は大きいですね.

#パフォーマンスは呆れるくらいに悪いかも知れません.

Tatsuya Shirai への返信

ImageMagickのインストール

- Tatsuya Shirai の投稿

 試しにImageMagickをインストールしてみました.なお,eps, ps, pdfを取り扱うにはGhostScript (gswin32c.exe)も必要らしいので,そちらもインストールしました.

 さして難しいこともなく両方ともインストールが完了.ImageMagicのインストーラは環境変数の設定もしてくれます.GhostScriptもPATHの追加だけですね.

 次はPHPのextension経由で呼び出せるか,の確認ですね.

Tatsuya Shirai への返信

Re: ImageMagickのインストール

- Haruhiko Okumura の投稿
ImageMagickは単にGhostscriptを呼び出しているだけなんでしょうね。Ghostscript単体でやるには

http://matome.info/pdf2jpg/

のようにすればいいのでしょうか。
Haruhiko Okumura への返信

Re: ImageMagickのインストール

- Tatsuya Shirai の投稿

 php_imagick.dll (Windowsの場合)というextensionを追加するだけで,PHP中からImagickという関数群が使えるはずだったのですが...なぜかモジュールの読み込みに失敗して利用できません.PHPのバージョンのせいかも知れませんが.(PECLの拡張モジュールですので汎用性が高そう) PHP5.2.0 ですので,PECLの5.2.0を探してきたり色々としたのですが好転しません.

 奥村先生の仰るように,PHPから外部コマンドとして,ImageMagickやGhostScriptを呼び出せば,ほぼ同じことが実現できると思います.ただ,PECLのImagickを介すればLinuxでもWindowsでも全く同じコードで実現できると思うと,こちらで進めたいですね.

 PHPのバージョンを上げるのは避けたいですし,困った困った.


 ちなみにGhostScriptでも出力するJPEGのサイズを変えたりはできそうですか?

 ImageMagickを介すると,色々な画像処理ができて良いようなのですが(不要...),いかにもメモリを浪費しそうな感じです.PHPとのインタフェースがうまく取れるのであればGhostScriptの外部呼出しだけの方がトラブルは少なそうですね.

Haruhiko Okumura への返信

Re: ImageMagickのインストール

- Tatsuya Shirai の投稿

 では,Ghostscriptでダイレクトに,ということで,御紹介いただいたページにあったバッチファイルを使用してtest.pdfというファイルのJPEGへの変換を試みたところ,

GPL Ghostscript 8.62 (2008-02-29)
Copyright (C) 2008 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Error: /undefined in リ澎
Operand stack:

Execution stack:
   %interp_exit   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--   --nostringval--   --nostringval--   false   1   %stopped_push   1937   1   3   %oparray_pop   1936   1   3   %oparray_pop   1920   1   3   %oparray_pop   1803   1   3   %oparray_pop   --nostringval--   %errorexec_pop   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--
Dictionary stack:
   --dict:1157/1684(ro)(G)--   --dict:0/20(G)--   --dict:72/200(L)--
Current allocation mode is local
Current file position is 5

とエラーが発生して変換できませんでした.ImageMagickのconvertを使えば同じtest.pdfをjpegファイルに変換できるのですが...

 教えていただいたページのオプション指定では,どうやら複数ページのPDFを連番JPEGファイルに変換しているようですが,指定した1ページを1枚のJPEGに変換することも当然できるのですよね.

 もし,Windows版でもLinux版でも実行するコマンド本体の名前(Windows版ではgswin32c.exe)は違ってもオプションが同一であるならば,Ghostscriptをsystem()で呼び出して使った方が楽そうです.ただ,PHPから外部コマンドを実行するには何か設定変更が必要のような感じもします.スペルチェックやTeXフィルタは動いているので問題ないとは思うのですが,Windowsのバッチファイルは実行できていない感じです.コマンドラインで実行して動いたバッチファイルが,エラー値4を返して異常終了しているようです.

Tatsuya Shirai への返信

Re: ImageMagickのインストール

- Haruhiko Okumura の投稿
バッチでなくてsystem("gswin32c ...")と直接書いたらどうなるんでしょう。

エラーは何ページ目で置きているんでしょう。
「gswin32c hoge.pdf」のように直接開いたら画面に表示できるでしょうか。

あとは環境変数などの設定の問題でしょうか。
Haruhiko Okumura への返信

Re: ImageMagickのインストール

- Tatsuya Shirai の投稿

 先に試したtest.pdfは1ページ目にも到達していないようでした.

 別のPDFファイルを試したところ,そちらはうまくオプションなしで画面上に表示,-sDEVICE=jpeg でJPEGファイルへ変換できました.PDFファイルのバージョンの違いか,あるいはエラーの発生したPDFファイルには(EPSでのプレビューのような)余計なデータが混ざっているPDFファイルだったのでしょうか.

 ImageMagickでは,エラーの発生したPDFファイルでも正しくJPEGファイルに変換できました.何か前処理で余分なデータを取り除いているのか,あるいはGhostscriptを適切なパラメータを付きで呼び出しているのか.

 とりあえずコマンドラインで実行してPDFをJPEGに変換できたので,次はPHPからsystem()でjpegに変換できるか試してみます.


Ghostscriptの使い方,というWebページの大半がインストール方法の説明です.
コマンドラインオプションを全て網羅しかつ読みやすくまとめられた日本語のページは無いでしょうか^^.

P.S. ああ,ここにありました.英語ですが.

http://ghostscript.com/doc/current/Use.htm

Tatsuya Shirai への返信

Re: ImageMagickのインストール

- Tatsuya Shirai の投稿

 特別な設定をphp.iniなどに行わないでも,Ghostscriptのインストールされた環境でPHP上からPDFファイルをJPEGファイルにページ単位で変換できました.

$src = 'testA';
$page = '2';
$gsexec = 'gswin32c.exe ';
$options = '-dSAFER -dBATCH -dNOPAUSE -sDEVICE=jpeg ';
$options.= '-sOutputFile='.$src.'.jpg ';
$options.= '-dFirstPage='.$page.' -dLastPage='.$page.' ';
system($gsexec.$options.$src.'.pdf', $ret);

$pageを1,2と変えると,testA.jpgの中身がページ1,ページ2の画像に変わりました.

-dFirstPage と -dLastPage を同じ値にしただけです.


 ストーリーはこんな感じです.

 まず,PDFファイルをJPEGに変換する必要があるのかどうかは,クッキーなどを用いてクライアントPC(あるいは携帯端末)毎に覚えておく仕組み(ボタンなど)が必要です.

 file.php で受け取ったファイル名を調べ,それがPDFファイルであるならば,optional_param()でページ番号が渡されているかどうかを調べる(たとえば'PDFpage'など).もし指定されていないならば $pageは1.

 moodledata/tempフォルダにユニークな名前のフォルダを作成してフォルダ名を変数に記憶しておく.そのフォルダ内にPDFファイルを特定の名前(例えばsource.pdfなど)でコピーする.GhostscriptでJPEGファイルに変換する.もし,ページ1ならば'page1.jpg'.この画像をOBJECTタブで埋め込んだ簡単なインタフェースを持つHTMLファイルをポップアップウィンドウとして出力する.インタフェースとしては,「最初のページ」「最後のページ」「前のページ」「次のページ」「指定したページ」「閉じる」といったところでしょうか.このインタフェースをもつページには,先に作成したユニークなフォルダ名と現在のページ番号をパラメータとして渡しておく.
 例えば「次のページ」が押された場合は,file.php(あるいは別のphpファイル)にユニークなフォルダ名と表示したいページ番号($page+1)を引き渡す.そして現在のページの代わりに新しいページに書き換える.もし既に新しいページのJPEGが作成済みならばGhostscriptを起動する必要は無いが,もし存在しないならば新しく作成する('page2.jpg').

 大雑把にはこんなメカニズムです.インタフェースとして「拡大」「縮小」や,現在のクライアントPCのウィンドウサイズを考慮に入れてJPEGのサイズをフィットできると良いですね.JavaScriptでウィンドウサイズは獲得できたと思います.

 あとはいつ,そのユニークなフォルダを削除するか.しまった.まったく考えていないですね.勝手にウィンドウを強制的に閉じられたら感知できない...キャッシュの仕組みはナシにしましょうか.


 出力するJPEGファイルの大きさ(ピクセル数)はどうやって変えれば良いのでしょう? -rは解像度ですよね.

Tatsuya Shirai への返信

Re: ImageMagickのインストール

- Haruhiko Okumura の投稿
すばらしいです!

JPEGのサイズは,元のPDFがA4だと仮定すれば,-rの値が決まりますよね。一般にはどうすればいいかわかりません。
Haruhiko Okumura への返信

Re: ImageMagickのインストール

- Tatsuya Shirai の投稿

 PHPの関数で,getimagesize()で大きさを調べて,リサイズして出力すれば可能は可能ですね.でも,せっかくGhostscriptでPDFからJPEGに変換するので,その段階でリサイズ(あるいはトリミングも?)した方が綺麗で速いでしょうね.


-r300 のJPEGに比べて -r30 のJPEGは横幅,縦幅共にピクセル数が半分になりました.ただ,やはり横幅,あるいは縦幅を何ピクセルにするか,という指定の方法は無さそうです.

 とりあえず300dpi(72dpi?)で出力した後に拡大縮小して下さいね,という方法が良いのか,それともPHPでゴチョゴチョと細工する方が良いのか.少し悩むところですね.早い段階で仕様を決めないと,後で痛い目を見ますから.

#あ,また本業を...

Tatsuya Shirai への返信

Re: ImageMagickのインストール

- Haruhiko Okumura の投稿
-r300 は -r30 の10倍ではなくて2倍ですか? おかしいですね。私が何か誤解しているのかな。それとも最小の値があるのでしょうか。ソースの gdevjpeg.c をちゃんと読めばいいのですが……。
Haruhiko Okumura への返信

Re: ImageMagickのインストール

- Tatsuya Shirai の投稿

すみません,すみません,書き間違いです!

きちんと1/10になっていました.


なお,ちょっとソースを眺めていて,いい加減な実験を思い付きました.

file.phpの最後のところ,send_file()を呼び出す手前で”ぶんどってしまえば”いいのじゃないのか? (安直ですし,副作用も確認)

     // ========================================
    // finally send the file
    // ========================================
    session_write_close(); // unlock session during fileserving
    $filename = $args[count($args)-1];
// FS_TEST: ここから追加
    if (mimeinfo('type', $filename) == 'application/pdf') {
        $filename = basename($filename, 'pdf').'.jpg';     // 拡張非をjpegに
        $temproot = $CFG->dataroot.'/temp/pdf2jpeg';   // 一時フォルダの
        if (!file_exists($temproot)) mkdir($temproot);    // 用意
        $org_filename = $filename;                                // 変換前のPDFのフルパス名
        $pathname = tempnam($temproot, 'temp');         // ユニークなファイル名を作成する
        unlink($pathname);                                            // でも,実際に作成されると邪魔なので消す
        $pathname .= '.jpg';                                           // 拡張子を追加.これがすり替えられた実体になる.

        $page = '1';  // 元の$pathnameのPDFをJPEGに変換して一時フォルダに出力.
        $resolution = '300';
        $gsexec = 'gswin32c.exe ';
        $options = '-dSAFER -dBATCH -dNOPAUSE -sDEVICE=jpeg ';
        $options.= '-sOutputFile='.$pathname.' ';
        $options.= '-dFirstPage='.$page.' -dLastPage='.$page.' ';
        $options.= '-r'.$resolution.' ';
        exec($gsexec.$options.$org_pathname, $ret);
    }
// FS_TEST: ここまで追加
    send_file($pathname, $filename, $lifetime, $CFG->filteruploadedfiles, false, $forcedownload);

send_file()の手前でfile.phpは$filename(パスなし,UTF-8のダウンロード用ファイル名)と$pathname(実際のサーバ上のフルパス名)を用意します.これをコッソリと入れ替えてしまう.mimetypeの違いによる処理はsend_file()の中で行ないますので,最初からPDFではなく,JPEGファイルを送出しろと言われていたのだよ,というフリです.

 これでファイルエディタやリソースの”ダイレクトリンク”で,PDFファイルの1ページ目を300dpiでJPEG化したファイルが送られてくることを確認しました.
 現状での問題点は2点.

 ・一時的に作成したファイルを削除できない: send_file()は行ったきりの関数のようですので,send_file()の呼び出しの次の行に削除コマンドを書いたのですが,ファイルは削除されませんでした.
 ・<OBJCET>タグでウィンドウ内に表示しているPDFファイルはうまくJPEGに変換して表示されない:mod/resource/view.phpの方でHTMLソース内に,

<object data="/mech/moodle/file.php/3/Syllabus/H19_2007_Jousho.pdf" type="application/pdf">

と,type=でPDFを指定してしまっている.ここはまぁ,jpegに変えれば何とかなるかも知れません.

でも,思ったよりも簡単かも知れないですよ,ここまでは.

 複数ページに対応させる,拡大/縮小を行なうために特別なコントロールを埋め込んだポップアップウィンドウを開くのは,意外と大変そうです.

 

Haruhiko Okumura への返信

Re: ImageMagickのインストール

- Tatsuya Shirai の投稿

おお,できました.

一時的にmod/resource/type/file/resource.class.phpの中のfunction display(), その中の,

            } elseif ($resourcetype == 'pdf') {

で,PDFファイルの表示のみに特化した箇所,

//              echo '<object data="' . $fullurl_object . '" type="application/pdf">';
                echo '<object data="' . $fullurl_object . '" type="image/jpeg">';

OBJECTタグの出力の"application/pdf"を"image/jpeg"に変えたところ,リソースとして割り当てたPDFファイルもウィンドウ内にJPEG画像で埋め込むことができました.デカいですけれども...

 技術的には可能ですね.ここまでならば修正箇所も少ないです.

添付 pdf2jpeg.jpg
Tatsuya Shirai への返信

Re: ImageMagickのインストール

- Tatsuya Shirai の投稿

 Moodle内のリソースであれば,HTMLエディタで作成したPDFファイルへのリンクもJPEGに変換可能であることが確認できました.携帯電話のフルブラウザですと,画像がジジジジジと少しずつ表示されるのがシュールです.

 ブラウザの種類にもよるのでしょう.300dpiの巨大なJPEGファイルを送っても,私の携帯電話(922SH)のブラウザは画面ぴったりに合わせこんでしまいますので,小さな文字は読めません.IEですとスクロールバーが表示されるので,逆に小さい画像(72dpiなど)で全体をピッタリに表示するのは無意味です.ちょっと悩ましいところですね.特に携帯電話のブラウザ(922SH)は拡大表示にしても文字しか大きくなりません.埋め込み表示ではなく,単純にダイレクトリンクで出力されたJPEG画像も同じく.
 少しがっかりしていたのですが,画像をファイルに保存し,ビューワで見れば拡大縮小可能ですね.回転もできる.それほど悪くないです.無理に画面にフィットさせるよりも良いかも知れません.

 ファイル名がマルチバイト文字の場合,WindowsですとGhostscript(gswin32c.exe)に実体のファイルのパスをシフトJISに変換してから渡さないといけないなど,多少の問題点はありますが.(あ,exec()をfs_exec()というfs関数にすれば良いのか)

 一時ファイルが削除できない問題は,send_file()の中で消すかcronに任せるか,ですね.ちなみにmoodledata/temp/latexフォルダに1年前からの*****.texという一時ファイルが残っています.これらのファイルはcron.phpが自動的に削除してくれるものではないのですか?

 残すは複数ページへの対応ですね.

Tatsuya Shirai への返信

(この考えを流用し)Ghostscriptを利用すれば

- Tatsuya Shirai の投稿

・ファイルエディタ画面でPDFファイルを連番JPEGファイルに展開できるようになる.
 時々,「PDFの中の図をコピーしたいのだけれど」と質問を受けることがある.
 私はPhotoshopでJPEG化しているが,誰もがPhotoshopを持っている訳ではない.MoodleにPDFをアップして,連番JPEGファイルを作成し,ZIP書庫化してダウンロードする,という手順も薦められる.

・ファイルエディタ画面でJPEG画像の解像度を変えることができるようになる.
 同じく,「JPEG(顔写真とか)の大きさを変えたいのだけれど」と質問を受けることがある.
 これも私はPhotoshopで(以下同文)

 もちろん,教師権限の者以外には”ファイル編集”の機能は提供できないが...

Tatsuya Shirai への返信

完成しました (PDF2JPEG機能)

- Tatsuya Shirai の投稿

 PDFファイルを表示できない端末(PS3, Wii, PSP, Nintendo DS etc...)でMoodleサイト上のPDFファイルを閲覧可能とする機能拡張が完成しました.

 仕組みを簡単に説明します.(以前に構想したものとほぼ同じです)

 拡張子がpdfのファイルを引数としてfile.phpが呼ばれたら,そのPDFファイルをGhostscriptでJPEGファイルに変換します(moodledata/temp/pdf2jpegフォルダ内に作成).file.phpに渡されたファイル名とパスの情報をこのJPEGファイルのものとすり替えてsend_file()関数を素知らぬ顔で呼びます.これでMoodleは騙されます.
 ただ,リソースでインライン表示する場合だけは<OBJECT>タグで呼ばれますので,ここだけは少し誤魔化しが必要です.

 JPEGファイルは単一ページの画像ファイルですので,複数ページのPDFファイルを表示するにはページ番号を指定する必要があります.また,PDFファイルをJPEGファイルに変換して送出する際に,画像の解像度を変換できると便利です.この二つのパラメータは添付した画像にあるように,画面下のフッター部に追加したボタンとテキストフォーム(常に表示...)で設定できます.この設定した値はクッキーで30日間,記憶されます.

 少し困ったのはPDFファイルの画像サイズをGhostscriptで知る方法が無いこと.仕方が無いので,最初に300dpiでPDFからJPEGに変換し,それをPHPのgetimagesize()関数で読み取ります.試しに変換したJPEG画像の横幅の情報を元にして,指定された倍率×1000pixelの幅の画像が生成されるように解像度(-r)のオプション値を計算して,再度,PDFからJPEGに変換しています.つまり1回のPDF2JPEG処理に2回の画像変換を行なっています.PHPの関数でリサイズしようか?と考えて試したのですが,処理に異常に時間が掛かること,画質が悪いことから,そうだ,2回,処理を行えば良いのだと開き直りました.

 あと,PDF2JPEG変換を行なった一時ファイルの削除.send_file()関数の中でファイルをunlink()すると誤って大事なオリジナルの画像ファイルを消してしまうのではないか,という心配もあり,現在はcron.phpで1時間以上経過したら削除するようになっています.あまり大量のアクセスがあるとパンクするかも知れませんね.変換後のファイルを再利用する可能性を考えて寿命を1時間としましたが,特に現状では再利用をしていませんので,5分でも経過したら消して良いかも知れません.


 実際にPDF2JPEGの機能を試すことができます.以下のURL(mechMoodle)にアクセスして見て下さい.ゲストでもログイン可です.あるいは アカウント:fsuser/パスワード:fsconverter でアクセスして下さい.

http://www.suzuka-ct.ac.jp/mech/moodle/course/view.php?id=42

JPEG2PDFの動作確認
のトピックスに,HTMLのハイパーリンク版とリソース版(どちらも同じPDFファイル)のサンプルを用意しました.まずは普通にPDFファイルとして閲覧できることを確認したら,次は画面下のフッターにある「PDF2JPEG: Off」ボタンを押して「PDF2JPEG: On」にして下さい.その右に現れる,Pageと倍率に色々な値を入力し,Setボタンを押せば設定した値が有効になります.

添付 PDF2JPEG_Control.jpg
Tatsuya Shirai への返信

中心部分のコードを公開

- Tatsuya Shirai の投稿

 これはfile.phpで中心的に働く箇所のみの抜粋ですので,このコードだけを移植してもPDF2JPEG機能は働きません.これくらいのコードの追加で済みました,という説明のためのものです.(少し汚いコードも残っていますが...)

    // ========================================
    // finally send the file
    // ========================================
    session_write_close(); // unlock session during fileserving
    $filename = $args[count($args)-1];
// (Shirai076): PDFを表示できない端末上でもPDFをJPEG画像に変換して表示可能とする機能拡張 (2008/07/31)
// (Shirai076): ここから追加
    if ((!FS_DISABLE_PDF2JPEG) && (is_pdf2jpeg_on())) {
        if (mimeinfo('type', $filename) == 'application/pdf') {
            // 現在のファイル名(パスなし)をバックアップし,拡張子を'jpg'に変更.
            $org_filename = $filename;
            $filename = basename($filename, 'pdf').'.jpg';
            // 現在の実体(PDF)を作業用フォルダにコピーする.
            if (!fs_file_exists($pathname)) $pathname = rawurldecode($pathname);
            $pathname = mb_convert_encoding($pathname, 'SJIS-WIN', 'UTF-8');
            $org_pathname = $pathname;
            $temproot = $CFG->dataroot.'/temp/pdf2jpeg';
            if (!file_exists($temproot)) mkdir($temproot);
            $pathname = tempnam($temproot, 'temp');
            unlink($pathname);
            $pathname .= '.jpg';
            // PDFをJPEGファイルに変換 (Ghostscript)
            // パラメータの取得
            $page  = (isset($_COOKIE['fs_pdfpage']))  ? $_COOKIE['fs_pdfpage']  : 1;
            $ratio = (isset($_COOKIE['fs_jpgratio'])) ? $_COOKIE['fs_jpgratio'] : 1.0;
            if ($page <= 0) $page = 1;
            if ($ratio <= 0.0) $ratio = -1.0;
            // 試しに変換
            $resolution = 300;
            exec(pdf2jpeg_cmd($org_pathname, $pathname, $page, $page, $resolution), $msgs, $ret);
            // エラー処理
            if (!file_exists($pathname)) $ret = 9; // error
            if ($ret) {
                foreach($msgs as $msg) echo $msg.'<br/>';
                die;
            }
            // 実行(画像リサイズして出力)
            if ($ratio > 0.0) {
                $newx = 1000 * $ratio;
                $im_info = getimagesize($pathname);
                $resolution = intval($resolution * $newx / $im_info[0]);
                exec(pdf2jpeg_cmd($org_pathname, $pathname, $page, $page, $resolution), $msgs, $ret);
                // エラー処理
                if (!file_exists($pathname)) $ret = 9; // error
                if ($ret) {
                    foreach($msgs as $msg) echo $msg.'<br/>';
                    die;
                }
            }
        }
    }
// (Shirai076): ここまで追加
    send_file($pathname, $filename, $lifetime, $CFG->filteruploadedfiles, false, $forcedownload);

これ以外に,Cookieの処理のためのJavascriptを少しだけ追加,フッターにボタンを表示するためにlib/weblib.phpに少し追加,<OBJECT>タグに対応するためにmod/resource/type/file/resource.class.phpにほんの少しだけ追加,一時ファイルの削除のためにcron.phpに少しコードを追加.

Tatsuya Shirai への返信

表示できないPDFファイル

- Tatsuya Shirai の投稿
  1. パスに多分,5Cを含む日本語名(シフトJISに変換)の場合にファイルが開けません.これはWindowsをサーバとする場合にのみ発生する問題でしょう.取り合えず一時フォルダにPDFファイルをコピーした上でghostscriptに渡すことで解決しました.
  2. フォントが埋め込みではないPDFファイルがJPEGファイルに変換されないらしい.これは環境に固有の問題かも知れません.ともかく当方のサーバに導入したgs8.62 (Windows版)では,
    GPL Ghostscript 8.62 (2008-02-29)
    Copyright (C) 2008 Artifex Software, Inc. All rights reserved.
    This software comes with NO WARRANTY: see the file PUBLIC for details.
    Processing pages 1 through 1.
    Page 1
    Substituting CID font resource/Adobe-Japan1 for /MSゴシック.
    Error: /undefinedresource in findresource
    Operand stack:
    このように,CIDフォントを”MSゴシック”に代替しようとしてエラーになっています.lib/cidfmapに,/MSゴシック /MS-Gothic ; を追加したら,今度は,
    While reading gs_cidfm.ps:
    Error: /syntaxerror in (bin obj seq, type=130, elements=108, size=33394, non-zero unused field)
    Operand stack:
    このようにgs_cidfm.psがエラーを発生しました.多分,cidfmapにシフトJISコードを書いたせいでしょう.

 フォント埋め込みではない場合に代替フォントとしてMSゴシックを探しに行くのが元のPDFに原因があるのか,それともghostscriptなのかは分かりません.もう一度,設定を見直してみるか,新しいバージョンのgsにアップデートしてみるか,でしょうね.C:\WINDOWS\fonts\msgothic.ttcを参照しろ,と,MS-Gothicの設定にありますが,これも妙です.存在するのはmsgohic04.ttcというファイルです.mkcidfm.psが自動生成した(のですよね)cidfmapに見直しが必要ですね.Moodleの話では無くなってしまいました.