ニコンとキャノンとパナソニックがフルサイズのミラーレスカメラを出すと発表したので、どんなのが出てくるかちょっと楽しみだ。「好きなカメラを買っていい券」をここまで温存してきた甲斐があるというものだ。像面位相差AFとチルト液晶と手ぶれ補正を備えたE-M5的な大きさの機種がオリンパスから出るのを待っていたが、出そうにないので諦めていたところだ。スペックが発表されているニコン機とキャノン機、そしてすでに市場にあるソニー機を見ると、やはり先行しているソニーが良さげだ。像面位相差でチルト液晶で手ぶれ補正がついて小さい筐体でセンサー性能が優秀なので。しかし、ソニー機はカメラ内RAW現像ができないのがネックで、出先でシェア的な使い方をする妻との共用を考えると採用しづらい。常にRAW+JPEGで撮るのも馬鹿馬鹿しい。そうすると、同様の機能でセンサー性能が優秀っぽくてカメラ内RAW現像ができるニコン機が欲しくなるけど、高くてでかい。ソニーがカメラ内RAW現像に対応するか、ニコンが小型な廉価版を出すかしてくれればいいのだが、どうなることやら。いったい私はいつになったらカメラを買い換えられるのか。つか、オリ頑張れよオリ。
閑話休題。最近は撮った写真を様々なサイズにトリミングして保存するので、アスペクト比ごとの最適サイズについてまた整理してみた。個人用の写真管理プログラムをRubyからPythonに移植するついでに、サイズ判定部分についても考え直してみた。以前の記事と述べていることはほぼ同じである。
総有効画素数がわかれば、√(画素数 / 短辺比率 * 長辺比率) で長辺のサイズが出て、√(画素数 / 長辺比率 * 短辺比率) で短辺のサイズが出る。例えば画素数16Mピクセルでアスペクト比4:3のオリンパスE-M10は、長編4618ピクセルで短辺3464ピクセルくらいになるはずだ。画素数30Mピクセルだという噂のEOS-Rは、長辺7745ピクセルで短辺4472ピクセルくらいになるはずだ。ところで、私はGoogle Photosに写真をTIFF形式で保存しているのだが、無料枠だと1枚のデータ量が50MBまでという制限がある。50MBは8ビット深度のTIFFだと、50M / (8+8+8) で、16Mピクセルが上限になる。16ビット深度だとその半分で8Mピクセルということになる。実際はZIP圧縮TIFFにすると16ビット深度の10Mピクセルまでなら50MBに収まることが多いので、それがベストソリューションだと考えている。
で、16MP、10MP、8MPのそれぞれに画像をリサイズして保存する際に、長辺と短辺はいくつにすれば良いのか。まずはその画像のアスペクト比を知る必要がある。実際の画像サイズを調べて、1:1や3:2や4:3などのクリーンなアスペクト比に近い(誤差1%以内)なら、そういったクリーンな比であるとみなす。そうでない場合、実際の比を約分して使う。アスペクト比がわかれば、先ほどと同様の式で保存サイズを導けば良いわけだが、その際に各辺の長さをキリのいい数値にしたい。後でさらにリサイズした場合の画質劣化を最小限に抑えたいからだ。まず、アスペクト比が単純な場合には、長辺と短辺の比が正確になるように配慮する。そして、長辺、短辺とも、できれば60で割り切れてほしくて、無理なら12、4、2と可能性を探る。それでいて、実際の保存サイズが理論的な最大サイズの90%より小さくなってほしくはない。以上の条件を満たす設定の一覧を出すPythonスクリプトは以下のものになる。
#! /usr/bin/python import math import fractions def clean_image_aspect(width, height): actual_ratio = float(width) / height clean_aspects = ((1, 1), (7, 6), (5, 4), (4, 3), (7, 5), (3, 2), (8, 5), (16, 9), (2, 1), (12, 5), (3, 1), (4, 1), (5, 1), (6, 1)) margin_ratio = 1.01 for clean_aspect in clean_aspects: clean_ratio = float(clean_aspect[0]) / clean_aspect[1] if actual_ratio >= clean_ratio / margin_ratio and actual_ratio <= clean_ratio * margin_ratio: return clean_aspect for clean_aspect in clean_aspects: clean_aspect = (clean_aspect[1], clean_aspect[0]) clean_ratio = float(clean_aspect[0]) / clean_aspect[1] if actual_ratio >= clean_ratio / margin_ratio and actual_ratio <= clean_ratio * margin_ratio: return clean_aspect gcd = fractions.gcd(width, height) return int(width / gcd), int(height / gcd) def shrink_image_size(max_area, width, height): if width * height <= max_area: return width, height aspect = clean_image_aspect(width, height) is_simple = aspect[0] <= 20 and aspect[1] <= 20 ratio = float(aspect[0]) / aspect[1] max_width = int(math.sqrt(max_area * aspect[0] / aspect[1])) max_height = int(math.sqrt(max_area * aspect[1] / aspect[0])) tries = int(max_width * 0.04) dividers = [60, 12, 4, 2, 1] for divider in dividers: for i in range(0, tries): width = max_width - i if width <= 1000: break if width % divider != 0: continue height = width / ratio if is_simple and height != int(height): continue height = int(height) if height % divider != 0: continue return width, height return max_width, max_height for mp in [16, 10, 8]: print("%dMP" % mp) aspects = [(1, 1), (7, 6), (5, 4), (4, 3), (7, 5), (3, 2), (8, 5), (16, 9), (2, 1), (12, 5), (3, 1), (4, 1), (5, 1), (6, 1)] for aspect in aspects: (width, height) = shrink_image_size(mp * 1000000, aspect[0] * 10000, aspect[1] * 10000) print("|%d|%d|%d|%d|%d" % (aspect[0], aspect[1], width, height, width * height))
結果として、8ビットTIFF用の16Mピクセルだと、この設定がよさげ。Google PhotoはJPEGでも16Mピクセルが上限となるので、この値を使うといいだろう。
長辺比 | 短辺比 | 長辺サイズ | 短辺サイズ | 画素数 |
1 | 1 | 3960 | 3960 | 15681600 |
7 | 6 | 4172 | 3576 | 14919072 |
5 | 4 | 4440 | 3552 | 15770880 |
4 | 3 | 4560 | 3420 | 15595200 |
7 | 5 | 4620 | 3300 | 15246000 |
3 | 2 | 4860 | 3240 | 15746400 |
8 | 5 | 4992 | 3120 | 15575040 |
16 | 9 | 5184 | 2916 | 15116544 |
2 | 1 | 5640 | 2820 | 15904800 |
12 | 5 | 6192 | 2580 | 15975360 |
3 | 1 | 6840 | 2280 | 15595200 |
4 | 1 | 7920 | 1980 | 15681600 |
5 | 1 | 8700 | 1740 | 15138000 |
6 | 1 | 9720 | 1620 | 15746400 |
16ビットTIFFのZIP圧縮で投機的に保存するならこの10Mピクセル設定を使う。これで保存して50MBを超えてしまった場合には、8Mピクセルにフォールバックすればよい。
長辺比 | 短辺比 | 長辺サイズ | 短辺サイズ | 画素数 |
1 | 1 | 3120 | 3120 | 9734400 |
7 | 6 | 3360 | 2880 | 9676800 |
5 | 4 | 3480 | 2784 | 9688320 |
4 | 3 | 3600 | 2700 | 9720000 |
7 | 5 | 3696 | 2640 | 9757440 |
3 | 2 | 3780 | 2520 | 9525600 |
8 | 5 | 3936 | 2460 | 9682560 |
16 | 9 | 4160 | 2340 | 9734400 |
2 | 1 | 4440 | 2220 | 9856800 |
12 | 5 | 4896 | 2040 | 9987840 |
3 | 1 | 5400 | 1800 | 9720000 |
4 | 1 | 6240 | 1560 | 9734400 |
5 | 1 | 6900 | 1380 | 9522000 |
6 | 1 | 7560 | 1260 | 9525600 |
8ビットTIFFを保存するならこれ。確実に50MB以下のサイズになるはずだ。
長辺比 | 短辺比 | 長辺サイズ | 短辺サイズ | 画素数 |
1 | 1 | 2820 | 2820 | 7952400 |
7 | 6 | 2940 | 2520 | 7408800 |
5 | 4 | 3120 | 2496 | 7787520 |
4 | 3 | 3264 | 2448 | 7990272 |
7 | 5 | 3276 | 2340 | 7665840 |
3 | 2 | 3420 | 2280 | 7797600 |
8 | 5 | 3552 | 2220 | 7885440 |
16 | 9 | 3648 | 2052 | 7485696 |
2 | 1 | 3960 | 1980 | 7840800 |
12 | 5 | 4320 | 1800 | 7776000 |
3 | 1 | 4860 | 1620 | 7873200 |
4 | 1 | 5520 | 1380 | 7617600 |
5 | 1 | 6300 | 1260 | 7938000 |
6 | 1 | 6840 | 1140 | 7797600 |
こうして出てきたサイズをもとに画像を保存してから、Google Photosやその他のサービスにアップロードすればいい。、Lightroomの書き出し時にリサイズしてもいいし、一括で書き出してからImageMagick等でリサイズしてもいい。バッチで回してアスペクト比の判定とリサイズを同時に行うスクリプトはこれから書く。
OLYMPUS ミラーレス一眼 OM-D E-M10 MarkII 14-42mm EZレンズキット シルバー
- 出版社/メーカー: オリンパス
- 発売日: 2015/11/07
- メディア: Camera
- この商品を含むブログを見る
ソニー デジタルスチルカメラ「DSC-RX100M5」SONY Cyber-shot(サイバーショット) RX100V DSC-RX100M5
- 出版社/メーカー: ソニー
- メディア: エレクトロニクス
- この商品を含むブログ (3件) を見る