Your SlideShare is downloading. ×
0
iOS での PDF 処理あれこれ       越智 修司     @ponpoko1968
自己紹介越智修司•       KLab( くらぶ ) 株式会社•       ソシャゲの会社でソシャゲじゃ無いもの作ってます•       アプリ・サービスのプロトタイピング•       有名アーティスト・アイドルのファンクラブアプリ開発•...
動機•   自炊始めた•   PDF リーダーをいろいろ試してみた•   要望    •       読書内容を残したい・シェア        •    evernote        •    facebook    •       視力が落...
クリップリーダー•   PDF リーダー
苦労したこと•   メモリ消費•   目次の抽出•   文字列の抽出
PDF 描画 (1)•   CGContextDrawPDFPage() を使えば OK•   ビットマップコンテクストに描画して永    続化すればキャッシュできる
PDF 描画 (2)CGPDFDocumentRef pdfDocument    = CGPDFDocumentCreateWithURL(url);// ページ番号からページを取得CGPDFPageRef page    = CGPDFDo...
PDF 描画 (3)•       注意点    •       メモリを消費します。    •       しかもページを取得して描画するたびに消費量            が増えます。    •       対策        •    ペ...
「目次」機能
Core Graphics での PDF の構造•    階層化されたオブジェクトの集合体    • ページ    • フォント    • コンテントストリーム
Document management — Portabledocument format — Part 1: PDF 1.7 より
PDF 描画 (2)CGPDFDocumentRef pdfDocument    = CGPDFDocumentCreateWithURL(url);// ページ番号からページを取得CGPDFPageRef page    = CGPDFDo...
Core Graphics での PDF の構造•   Document Catalog という辞書から文書構    造を取り出す•   オブジェクト単位の情報は    CGPDFDictionary として扱われる• 配列は CGPDFArr...
リンクリスト        NextFirst
Pages
ページ 並びの取得CGPDFDictionaryRef catalog=CGPDFDocumentGetCatalog( document_ );CGPDFDictionaryRef pages =NULL;CGPDFDictionaryGet...
目次構造の取得Document management — Portable documentformat — Part 1: PDF 1.7 より
PDF 文書構造(1)CGPDFDictionaryRef catalog=CGPDFDocumentGetCatalog( document_ );CGPDFDictionaryRef outlines=NULL;CGPDFDictionar...
PDF 文書構造(2)// ページオブジェクトを取得CGPDFDictionaryRef page;CGPDFDictionaryDictionary ( first, "D", &title );// 「 D 」キーがなく、ページオブジェクト...
Document management — Portabledocument format — Part 1: PDF 1.7 より
ページ番号と文書構造のリンクval       key 0  1 2 3      ・      ・      ・  n             Pages   Contents
文字列抽出機能•   コンテントストリームのなかから、文字    列描画命令部分を取り出す
コンテントストリームページ上で表現される一連の描画命令とデータ
PDF のオペレータparam1 param2 param3 param4 op•   後置記法•   パラメータは LIFO スタックに積まれる           param4           param3           para...
PDF の文字列描画BT                             % Begin Text/F1 24 Tf                      % フォント指定                              ...
文字列描画オペレータ•   Tj オペレータ
文字列抽出// コールバック関数を設定するCGPDFOperatorTableRef table_;CGPDFOperatorTableSetCallback(table_,   "BT",stringBlockBeginsCallback);...
文字列抽出コールバックstatic void stringCallback(CGPDFScannerRef inScanner, void *userInfo){  PDFStringExtractor *zelf = (PDFStringEx...
文字列抽出コールバックstatic void stringCallback(CGPDFScannerRef inScanner, void *userInfo){  PDFStringExtractor *zelf = (PDFStringEx...
レンダラの気持ちになって考える
CID•   PDF における " 文字列 " は、実際には CID の列で    あることがある•   CID= グリフ ( 字形 ) を一意に識別するための ID•   CID と文字コードのマッピングは文字列描画に用    いるフォントに...
フォント指定が重要BT                             % Begin Text/F1 24 Tf                      % フォント指定                               ...
CGPDFDictionaryRef pageDict = CGPDFPageGetDictionary(page);CGPDFDictionaryRef resourceDict = NULL;CGPDFDictionaryRef fontD...
フォントのエンコーディング情報•   Encoding    •   "Identity-H","Identity-V"        •   DescendantFont            •   /Registry (Adobe)   ...
CID ファイル :EUC-H の例100 begincidrange    ← 100 個の区間があることを示す<20> <7e>      231   ← cid231 〜 313 は printable ASCII の区間<8ea0> <...
課題•   対応できてないパターンがある•   テキスト領域認識•   全文検索
参考文献•   Life is Beautiful ( 中島聡氏 )    •   CloudReaders の開発    •   PDF レンダリングのメモリ消費の問題        を指摘    •   超巨大ページにも対応•   木下誠氏...
参考文献 (2)     •   通称フグ本     •   CID などアドビ社の多国         語対応の情報     •   鈍器としても使えます
参考文献 (3)     •   もっと早く出ていれ         ば。。。
PDF Voyeurhttps://github.com/below/PDF-Voyeur.git
Cocoa勉強会pdf関連
Upcoming SlideShare
Loading in...5
×

Cocoa勉強会pdf関連

2,738

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,738
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
17
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Transcript of "Cocoa勉強会pdf関連"

  1. 1. iOS での PDF 処理あれこれ 越智 修司 @ponpoko1968
  2. 2. 自己紹介越智修司• KLab( くらぶ ) 株式会社• ソシャゲの会社でソシャゲじゃ無いもの作ってます• アプリ・サービスのプロトタイピング• 有名アーティスト・アイドルのファンクラブアプリ開発• 最近はデータ解析 • python,R など
  3. 3. 動機• 自炊始めた• PDF リーダーをいろいろ試してみた• 要望 • 読書内容を残したい・シェア • evernote • facebook • 視力が落ちてきた人 ( つまり自分 ) も 読みやすく
  4. 4. クリップリーダー• PDF リーダー
  5. 5. 苦労したこと• メモリ消費• 目次の抽出• 文字列の抽出
  6. 6. PDF 描画 (1)• CGContextDrawPDFPage() を使えば OK• ビットマップコンテクストに描画して永 続化すればキャッシュできる
  7. 7. PDF 描画 (2)CGPDFDocumentRef pdfDocument = CGPDFDocumentCreateWithURL(url);// ページ番号からページを取得CGPDFPageRef page = CGPDFDocumentGetPage ( pdfDocument, pageNum );CGContextDrawPDFPage( context, page );CGPDFDocumentRelease( pdfDocument );
  8. 8. PDF 描画 (3)• 注意点 • メモリを消費します。 • しかもページを取得して描画するたびに消費量 が増えます。 • 対策 • ページレンダリングの都度 CGPDFDocument を開放して 開き直す。→パフォーマンス劣化 • didReceiveMemoryWarning を受け取ったらいったん閉じ て再開。
  9. 9. 「目次」機能
  10. 10. Core Graphics での PDF の構造• 階層化されたオブジェクトの集合体 • ページ • フォント • コンテントストリーム
  11. 11. Document management — Portabledocument format — Part 1: PDF 1.7 より
  12. 12. PDF 描画 (2)CGPDFDocumentRef pdfDocument = CGPDFDocumentCreateWithURL(url);// ページ番号からページを取得CGPDFPageRef page = CGPDFDocumentGetPage ( pdfDocument, pageNum );CGContextDrawPDFPage( context, page );CGPDFDocumentRelease( pdfDocument );
  13. 13. Core Graphics での PDF の構造• Document Catalog という辞書から文書構 造を取り出す• オブジェクト単位の情報は CGPDFDictionary として扱われる• 配列は CGPDFArray として扱われる場合と 、 First,Next キーから参照できるリンク リストになっている場合がある( Lisp の car と cdr のようなもの )• しかも Composite 構造になっている
  14. 14. リンクリスト NextFirst
  15. 15. Pages
  16. 16. ページ 並びの取得CGPDFDictionaryRef catalog=CGPDFDocumentGetCatalog( document_ );CGPDFDictionaryRef pages =NULL;CGPDFDictionaryGetDictionary(catalog, "Pages", &pages);// 先頭の要素を取得CGPDFArrayRef pagesArray= NULL;CGPDFDictionaryGetDictionary(pages, "Kids", &pagesArray);int cnt = CGPDFArrayGetCount (pagesArray );for ( int i = 0; i < cnt; i++ ){ const char *typeString; CGPDFDictionaryRef pageDict; CGPDFArrayGetDictionary(pagesArray, i, &pageDict ); CGPDFDictionaryGetName(pageDict, "Type", &typeString ); if(strncmp("Page",typeString,strlen("Page"))==0 ){ // pageDict オブジェクトへのポインタと、ページ番号を NSDictionary に保存 [pageNumDict setValue:[NSNumber numberWithInt:pageNum] forKey:[NSString stringWithFormat:@"%p",pageDict] ]; }
  17. 17. 目次構造の取得Document management — Portable documentformat — Part 1: PDF 1.7 より
  18. 18. PDF 文書構造(1)CGPDFDictionaryRef catalog=CGPDFDocumentGetCatalog( document_ );CGPDFDictionaryRef outlines=NULL;CGPDFDictionaryGetDictionary(catalog, "Outlines", &outlines );// 先頭の要素を取得CGPDFDictionaryRef first = NULL;CGPDFDictionaryGetDictionary(outlines, "First", &first );// 見出しを取得CGPDFStringRef title;CGPDFDictionaryGetString ( first, "Title", &title );// 次の章 (cdr 部 ) を取得CGPDFDictionaryRef next = NULL;CGPDFDictionaryGetDictionary(outlines, "Next", &next);// 小見出し( car 部)を取得CGPDFDictionaryRef children;CGPDFDictionaryGetString ( first, "First", &children);
  19. 19. PDF 文書構造(2)// ページオブジェクトを取得CGPDFDictionaryRef page;CGPDFDictionaryDictionary ( first, "D", &title );// 「 D 」キーがなく、ページオブジェクトを直接参照できない場合CGPDFStringRef dest;CGPDFDictionaryGetString(dict, "Dest", &dest );
  20. 20. Document management — Portabledocument format — Part 1: PDF 1.7 より
  21. 21. ページ番号と文書構造のリンクval key 0 1 2 3 ・ ・ ・ n Pages Contents
  22. 22. 文字列抽出機能• コンテントストリームのなかから、文字 列描画命令部分を取り出す
  23. 23. コンテントストリームページ上で表現される一連の描画命令とデータ
  24. 24. PDF のオペレータparam1 param2 param3 param4 op• 後置記法• パラメータは LIFO スタックに積まれる param4 param3 param2 param1
  25. 25. PDF の文字列描画BT % Begin Text/F1 24 Tf % フォント指定 % /F1 がフォントを表現するシンボ ル1 0 0 1 72 648 Tm % 描画位置の指定(Hello World) Tj % 文字列描画 -- (と )が引用符1 0 0 1 72 612 Tm % non-ASCII 文字列<4D53835383568362834E3234837C834383938367> Tj1 0 0 1 72 576 Tm0.5 g % グレイスケール<82BB82EA82F08A44904682C982B582BD82E082CC> TjET % End Text 「 PDF by Hand 」 http://www.kobu.com/doc s/pdf/pdfxhand.htm より
  26. 26. 文字列描画オペレータ• Tj オペレータ
  27. 27. 文字列抽出// コールバック関数を設定するCGPDFOperatorTableRef table_;CGPDFOperatorTableSetCallback(table_, "BT",stringBlockBeginsCallback);CGPDFOperatorTableSetCallback(table_, "ET", stringBlockEndedCallback);CGPDFOperatorTableSetCallback(table_, "TJ", stringArrayCallback);CGPDFOperatorTableSetCallback(table_, "Tj", stringCallback);CGPDFOperatorTableSetCallback(table_, "Tf", fontCallback);// ページに適用CGPDFContentStreamRef contentStream = CGPDFContentStreamCreateWithPage(page);CGPDFScannerRef scanner = CGPDFScannerCreate(contentStream, table_, self); // userinfo として self を指定bool ret = CGPDFScannerScan(scanner);
  28. 28. 文字列抽出コールバックstatic void stringCallback(CGPDFScannerRef inScanner, void *userInfo){ PDFStringExtractor *zelf = (PDFStringExtractor *)userInfo; CGPDFStringRef string=NULL; if(CGPDFScannerPopString(inScanner, &string)) { // ↑LIFO なのでポップする // 座標関連の命令を取り出すときは注意 NSString* s = [zelf stringWithPDFString:string];
  29. 29. 文字列抽出コールバックstatic void stringCallback(CGPDFScannerRef inScanner, void *userInfo){ PDFStringExtractor *zelf = (PDFStringExtractor *)userInfo; CGPDFStringRef string=NULL; if(CGPDFScannerPopString(inScanner, &string)) { // ↑ 全然文字列じゃない!!! NSString* s = [zelf stringWithPDFString:string];
  30. 30. レンダラの気持ちになって考える
  31. 31. CID• PDF における " 文字列 " は、実際には CID の列で あることがある• CID= グリフ ( 字形 ) を一意に識別するための ID• CID と文字コードのマッピングは文字列描画に用 いるフォントによって異なる
  32. 32. フォント指定が重要BT % Begin Text/F1 24 Tf % フォント指定 % /F1 がフォントを表現するシンボ ル1 0 0 1 72 648 Tm % 描画位置の指定(Hello World) Tj % 文字列描画 -- (と )が引用符1 0 0 1 72 612 Tm % non-ASCII 文字列<4D53835383568362834E3234837C834383938367> Tj1 0 0 1 72 576 Tm0.5 g % グレイスケール<82BB82EA82F08A44904682C982B582BD82E082CC> TjET % End Text 「 PDF by Hand 」 http://www.kobu.com/doc s/pdf/pdfxhand.htm より
  33. 33. CGPDFDictionaryRef pageDict = CGPDFPageGetDictionary(page);CGPDFDictionaryRef resourceDict = NULL;CGPDFDictionaryRef fontDict = NULL;// フォント辞書をスキャンif(CGPDFDictionaryGetDictionary(pageDict, "Resources", &resourceDict ) ) { if(CGPDFDictionaryGetDictionary(resourceDict, "Font", &fontDict ) ) { CGPDFDictionaryApplyFunction(fontDict,enumerateFontsInDictionary,se lf); } }static void enumerateFontsInDictionary(const char *key, CGPDFObjectRef value, void *info) { // フォント情報をキャッシュする}
  34. 34. フォントのエンコーディング情報• Encoding • "Identity-H","Identity-V" • DescendantFont • /Registry (Adobe) • /Ordering (Japan-1) • /Supplement (6) • CMAP 名
  35. 35. CID ファイル :EUC-H の例100 begincidrange ← 100 個の区間があることを示す<20> <7e> 231 ← cid231 〜 313 は printable ASCII の区間<8ea0> <8edf> 326<a1a1> <a1fe> 633<a2a1> <a2ae> 727<a2ba> <a2c1> 741 . . .endcidrange
  36. 36. 課題• 対応できてないパターンがある• テキスト領域認識• 全文検索
  37. 37. 参考文献• Life is Beautiful ( 中島聡氏 ) • CloudReaders の開発 • PDF レンダリングのメモリ消費の問題 を指摘 • 超巨大ページにも対応• 木下誠氏のマイコミジャーナルの記事 • Core Text を用いた CID→Unicode の簡便 な解決案が提示されています • http://news.mynavi.jp/column/iphone/03 9/index.html
  38. 38. 参考文献 (2) • 通称フグ本 • CID などアドビ社の多国 語対応の情報 • 鈍器としても使えます
  39. 39. 参考文献 (3) • もっと早く出ていれ ば。。。
  40. 40. PDF Voyeurhttps://github.com/below/PDF-Voyeur.git
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×