EY-Office ブログ

自分専用Web記事保存アプリのサムネイル画像がへんだ!

以前ブログに書いた 新たに自分専用Web記事保存アプリの開発を始めた新たに自分専用Web記事保存アプリその2 iOSアプリですが現在も使っています。

このアプリは、いつか役に立つかもしれないWeb記事をPDFに変換し保存できるアプリです。
保存したWeb記事が実際に役立ったことはは数回しかありませんが、いつか役に立つかもしれないという気持ちを否定せず、ただただ保存できるのが、このアプリの良いところです! バックエンドにはFirebaseを使っていますが今のところ無料で使えています。😁

thumbnail https://www.flickr.com/photos/seanfx/14337700149より

サムネイル画像がへん

保存した記事の一覧にはWebページの一部をサムネール画像で表示しているのですが、最近なんかへんです。画像がとても小さいです!?

昔キャプチャーしたWebページのサムネイルは下の画像のように、Webページの最初の方がちゃんと234x256dotで表示されています。

調査開始

なぜだろうと、調査を開始しました。サムネイル画像を作るところは以下のようになっています。
簡単に説明すると、

  1. PDFに変換されたWebページから1ページ目を取り出す
  2. サムネイル画像の縦横比からサムネール画像に変換するPDFエリアの高さを計算
  3. 上で計算されたエリアのPDFのみが画像に変換されるように領域を指定
  4. PDFからサムネイル画像に変換しPNG画像データを取得
func thumbOfPDF(pdfPath: String, thumbSize: CGSize) -> Data {
    let pdfPage = PDFDocument(url: URL(fileURLWithPath: pdfPath))!.page(at: 0)! // ①

    let rect = pdfPage.bounds(for: .trimBox)
    let height = rect.size.width * (thumbSize.height / thumbSize.width) // ②

    pdfPage.setBounds(CGRect(x: 0, y: rect.size.height - height,
       width: rect.size.width, height: height), for: .trimBox)  // ③

    return pdfPage.thumbnail(of: thumbSize, for: .trimBox).pngData()!  // ④
}

調べてみると、③で設定したエリアが無視されPDF全体からサムネイル画像を作っているようです。

2021年9月23日にリリースされた iOS12.5.5以降から、この現象が起きているようです。iOSのバグまたは仕様変更でしょうか?

対応

iOSのバグであればいつか修正されるかもしれませんが、仕様変更ならずっとこのままです。そこでコードを変更することにしました。😭

  1. まずサムネイル画像の幅に合わせ、PDF全体のサムネイル画像を作成します
  2. サムネイル画像の高さに合わせ、サムネイル画像の上の方のみを取り出します(トリミング)
  3. 上で出来た画像(CGImage)からPNGデータを取得しています

以前のコードに比べると①でやや大きなサムネイル画像を作るので、効率はよくありませんが我慢しましょう。

func thumbOfPDF(pdfPath: String, thumbSize: CGSize) -> Data {
    let pdfPage = PDFDocument(url: URL(fileURLWithPath: pdfPath))!.page(at: 0)!
    let rect = pdfPage.bounds(for: .mediaBox)
    let height = rect.size.height / (rect.size.width / thumbSize.width)

    let pdfImage = pdfPage.thumbnail(of: CGSize(width: thumbSize.width, height: height),
       for: .mediaBox)  // ①

    let thumbImage = pdfImage.cgImage!.cropping(to: 
       CGRect(x: 0.0, y: 0.0, width: thumbSize.width, height: thumbSize.height))!  // ②
    return UIImage(cgImage: thumbImage).pngData()!  // ③
}

既存サムネイルはどうしよう?

さて、これで新規にキャプチャーしたサムネール画像は正しくなりましたが、過去にキャプチャーした91個のサムネール画像はどうしましょうか?

ツールを作ってFirebaseからPDFを取得しサムネール画像を再生成しFirebaseデータを更新するアプリを書きましょうか・・・😭

- about -

EY-Office代表取締役
・プログラマー
吉田裕美の
開発者向けブログ