うな(。・ε・。)

Android, iOS, AppEngine まわりのめもめも

Medium方式のプログレッシブ画像読み込みの予備調査

Medium は 30x30pixel の画像を表示しておいてから、原寸画像を表示しているらしい。

そこで、30x30pixel というのがどの程度のクオリティ、サイズなのかを調査してみた。

iPhone 5S で撮った写真を題材にします。

原寸

2448 × 3264, 1.8MB

30x30 画像

30 × 40, 7KB (8016 bytes)

単純にリサイズするだけでは 7KB もあり大きさにしてはちょっと重い。

ここまで小さいと画像のクオリティも不必要なので色情報を落とすことにする。

30x30 画像(gif

色を落とすのに一番楽な gif にしてみた。ここまですると 2KB.

30 x 40, 2KB (2146 bytes)

dataURL 形式

gif 画像を dataURL にし、html に直接埋め込めるようにしてみる。

2866 bytes

コード

画像スワップのもっとも単純なコードは次のような感じ

document.addEventListener("DOMContentLoaded", function() {
    Array.prototype.forEach.call(document.querySelectorAll("img"), function(el) {
        var originalSrc = el.getAttribute("data-original");
        if (!originalSrc) return;
        var shdwImg = new Image();
        shdwImg.src = originalSrc;
        shdwImg.onload = function () {
            el.src = originalSrc;
        };
    });
});

↑リロードしてみてください(Shift + F5 でも!)

追記

Color reduction + jpegoptim + quality down で 30x40 px で 716 bytes まで落ちました。 1,200pixel ありますから、そんなものでしょうか。 ちなみに Color reduction は適当に 256 色に減色しました。

1pxあたり4-5bit程度になりました。 JPEGですから単純には言えませんが、色空間をもっと絞れば軽くなるでしょう… クライアントがアプリならJPEGのヘッダーまるまる落とすことも可能です。

Base64 956bytes

ちなみに Base64 の結果を deflate すると 677 bytes になります

eJylkEvPsjoUhX+QgyJykcEZtFCl3JQCCswEBAGVl4u0+us/zJec5LzT02Sne6dP1l6rQGuABKEftKlFK4igD5dpuaEBRIYMCDsTscpEVUd0WDl61TnGrfKNSvCMm3Da3XBC+PZu6aQkNX7Yn3y26lawA1y7GHPPaNVjI62sQMZB5G4DI9eOzfxX2+8cnUmLDvMxYqqtk+7wGdX/VzNgEFJ9MQ6RZMCAQHjDCHKMwNaH+2++yl3y/T4RRlVufBmHfxmCICO67vvGv4hPDIQwRJTcXD9FmPt1FO9Rl5kI8eSdpCYVZrAA1fKPGEL2e4e72ML4u8Pky7sfLT6I8R/EhzpkPiWUNG7jUaB10IBfv4QuGeCR6YNY/Gwum7no4+x5r28tPee1Ox5mvzno8Ppo28nIuQ263m383YeR2oCDbB5zzbtoUjTwcgw+2U4MijuVN+ldl5khkO1YoJ900rxTz/rS2sWyJORWLiUhs+VF1vH60ftxgrxHoQFl7UwUYEaA8+mUZZfVWkwS8XzhZyqvkycqqrBN1eIlTta56hIMNS8atGTPXyMmiO/r7qiwCihr6lSScXV8NtllZl29kunaEcoxvtfpTQAtMFXz1AycSmYG9v0nGZia+qLYNaOQ3JVWE9mGgOiSr7NO4tXbeR+uivuiK49GCrun6epqX8ePrWyrDX72VzML5rw/b1RQvEKRrC61wOLWLSq08gKwdAlxLZSZ4xuowjCEuRK1TMnVXCxbbkrCSW2vjRZGVA6SaNqGMbnc5ywaQ8rt+WePyulphqqiZMVr9B7WOfhEjjtPKEaHsnnSbl1Eso5zSbvFBYhPTQMf1UPyNnbB1Tk/Dr03aUGwHl1nSNo6P1t1SbXmnT8/wsUzywNtdkIExhho7T9/APAjNFk=

WebPにすると492bytesにもなりました。 Base64 -> deflate で 515 bytes の文字列に出来ます(ASCII)

UklGRs4BAABXRUJQVlA4IMIBAADQCACdASoeACgAPp1GnUslo6KhpWswsBOJYgCdMwNtvSYiyvtM
w56Ala3goMH6PLiFhzia0QdinyIhepGlg8ibpRNrfC1Nl3pkkmttCnnAAP7qXRTmseb0z2b0x2nq
LIVjG0hhDqxf9Wfk8TDunPCdwd5mVkDjOH0j/QRIdp2y1UYdvdTVHe0LU0WZSv3aURxWNVRdqjpp
wnDo9T+jga2qtPXFffebScNv6xxA1b5SDFB9GuH0UcCielWXizpEAge3+OI9It23/hZcOmq0JW8O
x8iHu0dpMh8681nw0q90Ommw2SJiLg/8bNdlvGg3f+4DieLt/ONMj3Tg7CF8iqh3NT4EwiJ4hsR4
kjiEWcfE/VUFzHKr5QhajTRtuof6WY0mpW+GV7Y6P0akaI/pCdap+uL9hOePenx+kUwqumODIhat
9WrbfvsmPDSNHrKuWoLFPlrLNCDfcc3HCWBdhnCXXkQX4GcxUVk1W1byotQvJprhDxWpfAI79afz
dJNJ3TJ6JoCc0eB2lsq0Gzwjwq4EfmBFXIbZbvX2Yoo8Uh/geZx/OfN02oOGZDQzmwezSElxw6V7
NEE9ggqzFYFjrQdAAAA=