none
PDFファイルに埋め込まれているグリフとテキストの関係を変更したい。 RRS feed

  • 質問

  • PDFファイル内にフォントが埋め込まれているとします。

    例えばの話ですが、「αβγδ」とPDF上では表示されているのに、その部分をPDFビュワーなどのアプリで選択してコピーすると、「abgd」というテキストが取得できるものがあります。

    これは、見た目のグリフとテキストが一致しないフォントが埋め込まれているという事になります。こういうフォントは少数ではあると思いますがそれなりに存在すると思います。Symbolフォントなどがそうでしょうか。

    PDFの見た目はそのままにして、グリフと対応するテキストを変更したいのですが、このような事を行う方法はありますでしょうか?

    上記の例でいいますと、PDFファイルをプログラムで読み込んで特定のフォントの「αβγδ」というグリフに対応するテキストを「abgd」から「αβγδ」に変更するという処理を行いたいのです。

    VB.NETあるいはC#で開発したいと思っています。

    どうぞ、よろしくお願いいたします。

    2016年3月3日 15:58

すべての返信

  • Symbol Fonts

    C#でSymbol Fonts⇔Unicode変換ははこんな感じでしょうか?(もっと簡単な方法があるかもしれませんが・・・)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public class SymbolToUnicodeConverter
        {
            readonly int[] table = { 
                      63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,
                      32,  33,8704,  35,8707,  37,  38,8717,  40,  41,8727,  43,  44,8722,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
                    8773, 913, 914, 935, 916, 917, 934, 915, 919, 921, 977, 922, 923, 924, 925, 927, 928, 920, 929, 931, 932, 933, 962, 937, 926, 936,  90,  91,8756,  93,8869,  95,
                      63, 945, 946, 967, 948, 949, 966, 947, 951, 953, 981, 954, 955, 956, 957, 959, 960, 952, 961, 963, 964, 965, 982, 969, 958, 968, 950, 123, 124, 125, 126,  63,
                      63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,
                      63, 978,8242,8804,8260,8734, 402,9827,9830,9829,9824,8596,8592,8593,8594,8595,  63, 177,8243,8805, 215,8733,8706,8729, 247,8800,8801,8776,8230,  63,  63,8629,
                    8501,8465,8476,8472,8855,8853,8709,8745,8746,8835,8839,8836,8834,8838,8712,8713,8736,8711, 174, 169,8482,8719,8730,8901, 172,8743,8744,8660,8656,8657,8658,8659,
                    9674,9001, 174, 169,8482,8721,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,9002,8747,8992,  63,8993,  63,  63,  63,  63,  63,  63,  63,  63,  63,  63,
                };
    
            public string SymbolToUnicode(string symbol)
            {
                var unicode = string.Empty;
                foreach (var s in symbol)
                {
                    var index = s & 0x0fff;
                    var value = index < table.Length ? table[index] : 63;
                    unicode += Convert.ToChar(value);
                }
                return unicode;
            }
        }
    
        static class Program
        {
            [STAThread]
            static void Main()
            {
                SymbolToUnicodeConverter converter = new SymbolToUnicodeConverter();
                String str1 = "abcdefghijklmnopqrstuvwxyzABCDEFGEFGHIJKLMNOPQRSTUVWXYZ";
                String str2 = converter.SymbolToUnicode(str1);
                MessageBox.Show(str2);
            }
        }
    }
    

    2016年3月3日 19:52
  • コメントありがとうございます。

    申し訳ございません。

    私のやりたい事はPDFファイルを開いてグリフとテキストの関係を変更し,新たにPDFを保存するというものです。

    PDF内のグリフ情報へのアクセス,変更,保存などPDFまわりの手段を探しています。

    説明不足で誠に申し訳ございませんでした。

    2016年3月9日 4:44
  • コメントありがとうございます。

    申し訳ございません。

    私のやりたい事はPDFファイルを開いてグリフとテキストの関係を変更し,新たにPDFを保存するというものです。

    PDF内のグリフ情報へのアクセス,変更,保存などPDFまわりの手段を探しています。

    説明不足で誠に申し訳ございませんでした。

    こちらこそ勘違いでした。申し訳ございません。

    ご存知かもしれませんが、PDFを開いて編集し再保存するMicorosoftの標準的なものはまだ存在しないようです。Windows 8.1から使うことができるWindows.Data.PdfもPDFデータの文字列の編集・保存までは対応していないようです。

    そこでサードパーティ製のPDF読み込み保存機能のあるライブラリですが、有名なところでは「iTextSharp」、「PDFSharp」というライブラリがあるそうです。

    以上、参考になりましたら幸いです。

    2016年3月10日 12:09
  •  何がしたいのか、よくわかんない。

     HTML で、「<p style="font-family:Century;">abgd</p>」と、「<p style="font-family:Symbol;">abgd</p>」を表示させると、コードを変えますが、
    abgd
    αβγδ
    のように表示されます。ここで、ギリシャ文字の方をコピーして、メモ帳にペーストすると、「abgd」が表示されます。
    ・・・ということでしょうか?

     そういうことならば、PDF 規格を入手して、ファイルを解析し、フォントを指定している部分を置き換えれば良いと思います。


     なんか、違う気がするなぁ。
    「見た目のグリフとテキストが一致しないフォント」
    「PDFの見た目はそのままにして、グリフと対応するテキストを変更したい」
    「特定のフォントの「αβγδ」というグリフに対応するテキストを「abgd」から「αβγδ」に変更する」
    「グリフとテキストの関係を変更」
    このあたりが、わからない。「グリフ」「テキスト」「フォント」の定義が違っているように思う。

     「abgd」は、キャラクターコードでそれぞれ 0x61 0x62, 0x67, 0x64 なわけで、このキャラクターコードを Symbols というフォントを使うと、ギリシャ文字として表示される。つまり、「αβγδ」という“データ”は、「0x61 0x62, 0x67, 0x64」という“内容”と、「Symbols フォントを使って表示する」という“指示”によって成り立っている。そこから「0x61 0x62, 0x67, 0x64」という内容だけ取り出して、Gothic や Serif のフォントで表示すれば「abgd」になる。

     Adobe Reader では、コピーしたときに Text だけでなく、Rich TextFormat も作成していました。Rich TextFormat の方をリッチテキストを再現できるものにペーストすれば、「αβγδ」は「αβγδ」で見えると思います。まぁ、クリップボードデータを作るアプリケーションと、そこからデータを取り出すアプリケーションと、それぞれのアプリケーション次第なのですが。

     蛇足。Word に「abgd」を入力し、フォントを Symbols に変更、コピーすると、内容が「0xf061, 0xf062, 0xf067, 0xf064」に変わる。なんでじゃ?


    Jitta@わんくま同盟

    2016年3月10日 21:22
  • なんだか、セキュリティツール(コピペができないPDFをつくるツール)が作りたいのかな、という感じがします。
    その前提でうろ覚えレベルの話をします。(PDF仕様を参照して下さい。)
    PDFの文字描画、というのは面倒くさくて、というのもフォント埋め込み有り無しの他に、文字コードが複数あることによります。
    明らかに、フォントを埋め込まない場合、描画はOSに頼むしかないので、コピペを防止するのは無理ですね。
    次に文字コードですが、SJIS,UNICODE,CIDの3種類があったはずです。で埋め込まれているフォントの中に、CID<->UNICODEの変換テーブルとかがあって、コピペの際は内蔵変換テーブルでUNICODEに変換がかかった気がします。

    もう判りましたよね。Text描画のデータを適当に変換して、それに合うように埋め込まれたフォントのテーブルをいじってやればいい、という話です。(埋め込まれていない場合にフォントを埋め込む方法と、フォントのライセンスについての楽しい話は除きます)。
    たとえば、UNICODEの’あ'を、CID=95とかに変換して、フォントの'あ'というグリフを指すように埋め込みフォントを変換し、埋め込みフォント中のUNICODEの逆変換テーブルは’N'を返すように作えればよい、ということです。

    PDFの生データとかフォントをゴリゴリバイナリで編集する必要があるでしょう。
    ライブラリがあるのかどうかは判然としません。


    jzkey

    2016年3月11日 6:21
  • みなさん、ありがとうございます。

    意図が伝わらなかったようで申し訳ございません。
    PDFファイルがあり、「あ」という形の文字が表示されています。
    この「あ」をAcrobat Readerなどで選択コピーし、テキストエディタに貼ると「A」となってしまう状態のものがあります。
    このグリフとテキストデータのコードポイントの関係を変更したいのです。

    現在「iTextSharp」で調べ始めたところですが、可能か不可能かの判断までは到達していません。
    kenjinote様からお教えいただいた「PDFSharp」については全く調べていませんので、「iTextSharp」に挫折した場合は調査してみようと思います。

    取り急ぎ、お礼まで。


    2016年3月11日 6:53
  • VB User1 さま よろしく。

    こう言う事でしょうか?。
    PDF で「αβγδ」と表示されるものを、別の拡張子のファイル形式で、類似の表示形態(グリフ)を持つフォントで代替して表示したいと。

    そうなら、前提として、グリフの種類が豊富な OTF フォントが使いたくなると思うので、 Form ではなく、WPF になると思います。

    埋め込みフォントと同じものが使える環境を整備する方が楽な気がしますが。

    見当外れでしたらご容赦下さい。

    2016年3月11日 15:10
  • PDFファイルがあり、「あ」という形の文字が表示されています。
    この「あ」をAcrobat Readerなどで選択コピーし、テキストエディタに貼ると「A」となってしまう状態のものがあります。
    このグリフとテキストデータのコードポイントの関係を変更したいのです。


    ん~。おなじ「あ」でも、メイリオ フォントと勘亭流 フォントで、グリフは異なります。そういうことじゃない、ということなんですね?
    Free Clipboard Viewer」とかで、クリップボードに何が入るか調べてみる、とか。


    Jitta@わんくま同盟

    2016年3月13日 12:05
  • ShiroYuki_Motさま

    コメントありがとうございます。

    「αβγδ」と表示されいるPDFを選択コピーすると「abcd」となるものがあります。

    このPDFファイルの内容を書き換えて,見た目はそのままで選択コピーしたときに「αβγδ」となるようにしたいというものです。

    Jittaさま

    コメントありがとうございます。

    >ん~。おなじ「あ」でも、メイリオ フォントと勘亭流 フォントで、グリフは異なります。そういうことじゃない、ということなんですね?

    はい。フォントごとに処理分けが必要となるであろうとは考えておりました。

    2016年4月1日 9:26
  • VB User1 さま 拝見しました。 PDF 上で ですね。

    abcd αβγδ フォント で検索するとギリシャ文字みたいですね。

    でしたら、αβγδ を αβγδ U+03B1~U+03B4 に置換しては如何でしょうか?。 そうなっているから表示されるのかな?。  メモ帳(フォント MS ゴシック/メイリオ)でも全角ですが表示されます。

    或いは、上記コードがちゃんとギリシャ文字になる(Unicode も Shift-JIS もコード記載がある)フォントに変更するかですね。  IME パッド等で確認出来る筈です。

    https://ja.wikipedia.org/wiki/%E3%82%AE%E3%83%AA%E3%82%B7%E3%82%A2%E6%96%87%E5%AD%97

    因みに、ですが。  コピー先のフォントを別のものに変更すると正確に表示している 等と言う おち は無いですよね。

    • 編集済み ShiroYuki_Mot 2016年4月2日 6:30 因みに 追記
    2016年4月2日 6:23
  • うーん、逆の話でしたか。

    前述したとおり、埋め込みフォントの描画であれば、PDFリーダーソフトは、PDF文書中の「座標X,YにフォントFでグリフ番号1,2,3,3,4,5を描画してね」という指示に従って描画をしておしまいです。埋め込まれたフォントFのグリフ番号1が「A」の形をしていようが「α」のかたちをしていようが何かのロゴであろうが、関知しません。

    では、PDFで埋め込みフォントを選択してコピーした場合にどんな文字列になるか、という話ですが、PDF仕様の9.10 Extraction of Text Contentに記載があります。

    ここでは簡単のために、PDFにType-1フォントとして埋め込まれたものと考えてみましょう(なので日本語は除外)。
    PDF中にはフォント定義と中身(グリフ)がありますが、フォント定義にToUnicodeエントリーが定義されている場合、そこで指示されたstreamがCMAPファイルであると解釈され、cmapをつかってグリフ番号とUNICODEの変換がなされます。そうでない場合、フォントのエンコーディング情報から、グリフ番号とUNICODEの変換がなされます。どれにも当てはまらないばあい、どうしようもありません。(コピーしようとしても、空の文字列になると思われる)

    では、この埋め込みフォントのマッピングがおかしいPDFをどうすれば修正できるのでしょうか。一番汎用であろうのは、グリフを実際に描画して、人に判断させる手ですね。で、一通り埋め込みフォントのただしいUNICODEが解ったら、CMAPを作成して、ToUnicodeエントリを追加する、という手になるかとおもいます。

    何度も言いますが、あまりに低水準な話なのでライブラリの内部クラスを持ってくるとか(圧縮とかstreamとdisctionaryとかのベースサポート)、「PDFをバイト単位で自分で操作する」くらいの覚悟でないと出来ない気がします。


    jzkey

    2016年4月2日 12:03
  • jzkeyさま

    まさにその通りで,仰っている内容の処理をしたいという事になります。

    低水準なのは覚悟していますが,なかなか取っ掛かりが掴めずにおりました。

    「ToUnicodeエントリー」というキーワードは初めて知りました。私のイメージではPDF内の特定フォントのCMAPを書き換える事で実現できるのではないかと漠然としたイメージを持っておりました。

    新しいキーワードをお教えいただきましたので,引き続き調べてみようと思います。

    取り急ぎお礼まで。

    2016年4月6日 10:16
  • ShiroYuki_Mot さま

    コメントありがとうございます。


    PDFの表示状態を変更する事はしないというのが今回の案件の仕様となっております。

    ですので,フォントを変更するという事はできません。申し訳ありません。

    また,PDF上でコピーしたときに見た目と同じテキストを取得するというのが目的ですので,コピーした後にテキストエディタなどで置換するといった方法もできないのです。

    このPDFを選択コピーしてテキストを利用するというのが,私ではない第三者という想定なのです。

    2016年4月6日 10:23