機能 #1066
完了複数のサイズが提供されている画像は、各サイズの画像情報を捨てずに扱う
0%
説明
やりたいこと¶
現在のmikutterでは、Twitter画像のオリジナルサイズや、他のサイズのものを取得する方法がなく、常にlargeが使われている。そのため、次のような問題が発生している。
- 取得したい画像のPixbufが小さく、smallが適切な場合でもlargeを取得してしまっている
- 画像ビューアプラグインがオリジナルサイズにアクセスできないため、largeを最大サイズの画像として表示してしまっている
これらを、後方互換性を保ったうえで開発者が適切な画像を選択できるようにしたい。
variantの種類¶
画像を以下の3種類に分ける。originalは、fitのうち最大のものなので、variantとして用意する必要はないかもしれない
- fit : オリジナルを、アスペクト比を保って縮小した画像
- crop: オリジナルの一部を切り取って縮小した画像
- (original): オリジナル画像。二つ以上存在できないので、専用のフィールドにしても良いかも
variantを保持する方法¶
Photo Variantsは、内部に複数のPhoto Variantを持つ。
Photo Mixinをincludeしており、download!に指定されたサイズから適切なPhoto Modelを選択する機能をもつ。
Photo Variantは、variantの名前、Photo Model、幅、高さの情報を持たせる。Variantを作る時には、必ず幅と高さ情報が必要となる。ただし、オリジナルに関してはその必要がない(最も大きいと仮定できるため)。
Photo Model#download¶
現在は、指している画像をダウンロードするだけだが、要求するサイズ(width, height)を設定できるようにする。
Photo Modelはこれを無視するが、Photo Variantsはこの要求に応じてダウンロードする画像を変える。
completed?などの状態を管理するメソッドや、blobフィールドの戻り値については検討しなければいけない(判明している最大のvariantか、originalのどちらかを返せばいい?)。
現実的にはPhoto Variantsのblobは参照されることはない。downloadメソッドの返すDeferredは、Photo Modelを伴って呼ばれるようになっているので、Photo Variantsではなく最終的に選択されたPhoto Modelを渡すことになる。
variantの選択¶
問題「取得したい画像のPixbufが小さく、smallで十分な場合でもlargeを取得してしまっている」を解決するため、要求サイズを上回る、できるだけ小さいPhoto Modelを選択する。
アスペクト比による選択¶
pixbufメソッドは、要求されたサイズに内接するようにアスペクト比を保って縮小(fitcrop)された画像を返すことになっている。したがって、利用するvariantはfitとoriginalだけとなる。
小さすぎるvariantは除外する¶
Photo Variantのサイズを見て、widthまたはheightが小さすぎる場合は、候補から外す。
Photo Modelでは、小さな画像を無理やり引き伸ばして返すことはしない。
最小のvariant¶
要求サイズより大きいPhoto Variantだけが残るので、この中から最も小さいものを選ぶことでメモリとネットワークトラフィックの節約を狙う。
具体的には、Photo Variantsのdownloadメソッドが、選択されたvariantのdownloadメソッドを呼ぶ。
関連するチケット
toshi_a 初音 さんが7年以上前に更新
単一の画像を扱う Plugin::Photo::InnerPhoto を親切し、 Plugin::Photo::Photo に、variantを扱う機能を追加した。
残りのタスク¶
- より大きなvariantがメモリキャッシュされていても、可能な限り小さいvariantを要求してしまい、無駄なダウンロードが発生することがある。対象となりうるvariantのうち、既にダウンロードされてメモリ上にあるvariantを利用したい。(例えばlargeがダウンロード済みの時、mediumを要求されたらlargeを利用する)
- GdkPixbufはvariant毎にキャッシュされるため、実質同じPixbufが複数のvariantにキープされる可能性がある。要求サイズより大きいvariantであればどれを縮小してGdkPixbufを作っても同じなので、GdkPixbufのインスタンスプールをそれらのvariantで共有する