Mobylet 1.01がでてたのでみてみた

「MobyletImageScaler.java」を斜め読みしたところ以前指摘したところは直っている模様。
MediaTrackerがちとつらいが仕方がない。

これ、流れを見て思ったけど、サイズ調整したいってだけだよね?
getScaledInstance()自体いらないとおもう。つまりあのへんごっそりとまるごとカットで。

なんせ書き込むときにサイズ指定しているから。そもそもAreaAveragingScaleFilterでよい(その理由は後述)。


サイズ指定するときにどういった補完がされるかというのに関しては、Graphics2Dのヒントで制御が可能だ。
Graphics2DはGraphicsを継承していて実態はつねにこれなのでキャストしてもいいが、取得メソッドをcreateGraphicsにかえるのが一番スマートでよい。


ヒントのセットにはsetRenderingHintを使う。

RenderingHintsクラスにその使用可能な定数がある。品質重視だったり、速度重視だったりさまざまなセットが可能だ。


ただ、縮小は難しいですね。バイキュービックもバイリニアも本来のパワーがいかせる方式ではないですから。縮小後の画像サイズを想定して適切なぼかしを入れてからの縮小しかありません。


拡大(以下は品質が同じ)に関して以下のような決定的な速度差があるのも注意したほうがいいかもしれません。
縦横8倍に拡大しました。2640*2088です。
Graphics2D + VALUE_INTERPOLATION_NEAREST_NEIGHBOR(ゼロ補完。つまり補完なし)
:99ms

Image.SCALE_SMOOTH
:326ms

メモリの使用量がまったく違います。上は24MBのヒープで動きましたが、下は48MB必要でした。この差は大きいかもしれません。これだけメモリの使用量も速度も違いながら品質の差がまったくないのが驚きです。

ただし、品質が同じなのは整数倍のみ。ドットが綺麗に出る場合ですね。

たとえば4.5倍とかすると画質に多少の差が出ます。そしてこの際のレンダリング品質はGraphics2Dのヒントでは設定できません。バイキュービックにしてもバイリニアにしてもできるだけなめらかにしようとしてエッジがきえてしまいます。ドットをきわだたせたいのか、滑らかにしたいのかは使用するアプリによって違うと思いますのでここは選択できるほうがよいのでしょうね。


逆に縮小してみたところ、Graphices2Dのヒントによるバイキュービックが一番品質がよくて、続いてバイリニアのヒントでした。そしてImage.SCALE_SMOOTHは一番品質が悪いにもかかわらず速度も一番遅かったです。


縮小と拡大で軽く見たところImage.SCALE_SMOOTHとAreaAveragingScaleFilterが品質が一致しました。速度はAreaAveragingScaleFilterのほうが早いのでImage.SCALE_SMOOTHはつかわないほうがいいかもしれません。メモリ使用量は詳しく見ていませんが。


つまり、縮小なのか、拡大なのか、倍率は整数倍なのかどうかなど細かく制御することによって大幅な速度向上やメモリ使用量が数分の1というすさまじい結果に変わるのです。この辺が難しいところではありますが、チューニングしただけ確実にかわってくるので面白いところです。

アクセス数の多いモバイル系では速度優先になることも多いかもしれません。また、動的に文字を埋め込むといったこともよくあると思います。ですから、スケーリングはこのアルゴリズムと決め付けないで、開発者に設定やヒントで選択させるというのが一番よいと思います。