概要
ファイルを直接アップロードするわけじゃありません。ファイルを画像に変換して共有するという話です。
共有したい圧縮ファイル(.zip)を画像に変換して、TwitterとかのSNSにアップロードする。
そのファイルをほしい人が、その画像をダウンロードして再びファイルに変換する。
つまり、SNSなどの画像アップロード機能を使うことによってファイル共有ができる。
(ファイル共有サービスを使った方が早い話はここでは禁句です)
Twitterはある程度の容量以下(3MB以下?)の透過png画像はアップロードしても圧縮処理されません。
参考: 2016年版 Twitterに高画質な画像をアップする方法【透過PNG】:どMなキョンのブロマガ - ブロマガ
よって、3MB以下ぐらいの圧縮ファイルなら画像にして共有することが可能です。
作ったもの
GitHubページを作りました。↓
ZIP⇔画像変換器
現時点でzipとpng変換のみ対応しています。
猫の画像をzipにして、変換した画像
この画像をファイルに変換すると、3枚の猫の画像が見れるはずです。
やっていること
ユーザから指定ファイルをバイナリとして読み込み、画像の画素値に変換しています。
画像の1画素はRGB値(加えて透過値を持つ場合も)を持ち、それぞれ8bitで保存されています。
つまり1画素は24bit(32bit)の情報を持たせることができます。
ファイルの情報をそこに置き換えてあげようという話。
データを画素値に変えてるところです↓詳しくはサイトのソースをみてください。
var data = new Uint8ClampedArray(file_reader.result);
var data = concatTypedArrays(data, magicnumber);
// canvasの大きさ(正方形)
var img_size = Math.ceil(Math.sqrt((data.length/3.0) + 1));
// canvasのcontextの取得
var canvas = document.getElementById("canvas");
canvas.width = img_size;
canvas.height = img_size;
var ctx = canvas.getContext("2d");
var imgData = ctx.createImageData(img_size, img_size);
// データを画素に変更
var tmp_idx = 0;
for (var i=0;i < data.length; i+=3) {
imgData.data[tmp_idx++] = data[i]; //red
imgData.data[tmp_idx++] = data[i+1]; //green
imgData.data[tmp_idx++] = data[i+2]; //blue
// imgData.data[i+3] = data[i+3]; //alpha // 透過を指定するとputImageDataで画素値が変わる現象がある
imgData.data[tmp_idx++] = 255;
}
ちなみに上のソースにも書いてありますが、画像の透明度まで使うと画像の画素値が微妙に変わります。ChromeやIEでも確認しました。バグが分からないのですが、わかる人教えてください。
その他
Androidの公式Twitterクライアントで画像をDLしたらjpgになっていました。画像はWebクライアントからDLしてください。
あとがき
正確には覚えていないのですが、昔の仕様のGoogleフォトだと4000x4000pxぐらい以下の画像が無劣化でほぼ無限に保存できました。これを利用して、バックアップデータを全部画像にして保存しておこう!と考えたのがこのネタの元ネタです。(最終的に利便性が悪すぎるため辞めました。またその当時の利用規約には違反していないと思います。)
今ではおそらくどんなサイズの画像も容量無制限の枠だと圧縮されます。そのためもちろん今回の方法でファイルを画像に変換してGoogleフォトにアップロードしたら、データが壊れます。圧縮されても大丈夫なような変換でやったらできると思います。(画像電子透かしみたいな)
またこの応用でファイルデータを動画に相互変換できたら、もっと容量が上げられるはずです。(誰か作ってください)
宣伝
良かったらフォローお願いします @redshoga