JPEGの色数の上限は?
【要約】JPEGの最大色数は1677万ではなく400万くらいのようだ。未確認だが、MPEG-4なども同様だろう。
「JPEGは最大65536色表せる」という間違った説明があって、2563 ≒ 1677万色の間違いだろうととっさに思ったが、JPEGは一般にRGB→YCbCr→RGBと色空間を変換するため、1677万色全部をカバーするとは言えない。それなら何色くらい表せるのか。
JPEGは8×8ブロック単位でDCT変換を行うので、8×8ブロックを256×256含む2048×2048の画像を256枚作れば、ブロック単位ですべての色のパターンが尽くせる。これをいったん保存してから読み出し、何通りの色が使われていたかを調べる。GPT-4に手伝ってもらって、次のようなプログラムを作った。
import numpy as np from PIL import Image ary = np.zeros((2048, 2048, 3), dtype=np.uint8) flg = np.zeros((256, 256, 256), dtype=np.uint8) for k in range(256): for i in range(256): for j in range(256): ary[8*i:8*i+8, 8*j:8*j+8] = [i, j, k] img = Image.fromarray(ary) img.save("image.jpg", "JPEG", quality=100) img2 = Image.open("image.jpg") img2 = img2.convert('RGB') width, height = img2.size for x in range(width): for y in range(height): r, g, b = img2.getpixel((x, y)) flg[r, g, b] = 1 print(np.sum(flg)) # 4006938
この実験では400万通りほどの色が再現された。1677万色の24%ほどである。22ビットくらいの情報量だ。
パターンを変えると色数は変わるが、上限は400万よりそんなに大きくならないようだ。
だいたいの分布を見てみる:
for k in range(16): print() print(k) for i in range(16): for j in range(16): s = np.sum(flg[16*k:16*k+16, 16*i:16*i+16, 16*j:16*j+16]) print(f"{s:5d}", end="") print()
特にどの色域が手薄ということはなく、ほぼまんべんなく1/4くらいの色が再現されるという感じのようだ。
未確認だが、同様なDCTを使っているMPEG-4などの動画もおそらく同じであろう。
[追記] WebP形式で同じことをやってみたら、約267万色(2671414色)であった。HEICはPILが対応していないようだ。