Technical Note

Color Tap me のしくみ

X(旧 Twitter)の画像圧縮機構を利用した「タップで色が現れる」画像生成の原理

なぜこれで動くのか — X(Twitter) の仕組み

X(旧 Twitter)は投稿された画像のサイズ・ファイル形式によっては再圧縮・リサイズを行う。本手法が正しく動作するには、いくつかの条件を満たす必要がある。この条件を満たすと、X が生成する低解像度プレビューの処理が 4×4 ブロック内の特定画素だけをサンプリングする性質を利用できる。その結果、プレビューでは白く、タップ後のフル解像度では色がついて見える画像を作ることが可能になる。

⚠️ このしくみがうまくいく正確な条件は未解明です。経験上、PNG で長辺 2048px 以上・4096px 以下の範囲で安定して動作することが多いです。1024px でも動作することは確認していますが、色が滲む場合があります。環境や時期によっても変わる可能性があります。
条件について情報をお持ちの方は @dare_aka2 まで教えていただけると嫁いです🙋
0 W 1 W W 2 W W 3 W 4 W W W W 5 4×4 ブロック(フル解像度) X プレビュー X タップ後 プレビュー(サムネイル) W W W W W W W W W W タップ後(フル解像度) 0 W 1 W W 2 W W 3 W 4 W W W W 5 可変画素の 色が見える
W = 白固定画素(×10) 0 0〜5 = 可変画素(×6)
図 1. X のプレビュー(上)とタップ後(下)。白固定画素(W)のみがサンプリングされると画像全体が白く見え、フル解像度では可変画素(0〜5)の色が現れる。

仕組みをまとめると次の三点になる。

  1. 白固定(W)画素を X のサンプリング規則に合わせて配置する。4×4 ブロックに 10 個の白画素を埋め込む。X のサムネイル生成処理はこれらの白画素だけをサンプリングするため、プレビューは白一色に見える。
  2. 色は {0, 255} の 2 値のみ使える。中間値を含む色を可変画素に使うと、プレビュー(低解像度サムネイル)にも色が滲み出てしまうことを経験的に確認している。そのためチャンネル値は 0255 のみに限定しており、使える色は 2³ = 8 通りのパレットに絞られる。
  3. 可変(0〜5)画素にブロックの平均色を近似する色を割り当てる。6 個の可変画素それぞれに 8 色パレットのどの色を割り当てるかを、元画像のブロック平均値に最も近くなるよう決定する。

市松模様配置のしくみ

市松模様モードでは、1ピクセルおきに元の色と透明ピクセルを交互に配置する(チェッカーボードパターン)。座標 (x, y) に対して (x+y) が偶数 → 元の色、奇数 → 透明 というシンプルなルールで処理される。これにより X のプレビューではサンプリング条件に従い色画素が認識されにくくなり、タップ後の高解像度画像では元の色が表示される。

  1. チェッカーボード配置で 50% の画素を透明にする。市松模様で半分の画素を透明 (Alpha=0) にする。(x+y) が偶数なら元の色、奇数なら透明というシンプルなルール。
  2. X のプレビューではサンプリング条件により色画素が認識されにくくなる。X の低解像度サムネイル生成時のサンプリング条件により、透明画素を通して背景(白)が見えやすくなり、色付きピクセルが認識されにくくなる。
  3. タップ後は別の表示条件で全ピクセルが表示される。高解像度画像では色と透明が全て処理されるため、市松模様処理前の元画像と同じ色彩で表示される。

Indexed-color PNG(Pillow では P mode)の形式

市松模様モードの出力には、PNG の indexed-color 形式(カラータイプ 3、Pillow では P mode)を用いる。PLTE チャンクには最大 256 個の RGB パレットエントリを格納し、tRNS チャンクには各パレットインデックスの透明度を格納できる。本実装では 0〜254 を量子化色、255 を完全透明用インデックスとして予約する。なお、この形式が X(旧 Twitter)上で安定して動作するという点は、PNG 仕様そのものではなく、X 上での観測結果に基づく実装上の選択である。

  1. 本実装では量子化により最大 255 色のパレットを生成する。元画像から非透明ピクセルをサンプリングし、量子化アルゴリズムで最大 255 色のパレットを自動生成する。インデックス 0〜254 に割り当てられる。
  2. 本実装ではインデックス 255 を完全透明用として予約する。tRNS チャンクでインデックス 255 の alpha 値を 0 に設定し、市松模様の透明画素((x+y) 奇数)はすべてインデックス 255 にマッピングされる。
  3. 各画素を最近傍のパレット色に割り当てる。非透明画素は量子化パレットの中から RGB ユークリッド距離が最も近い色のインデックスを割り当てて IDAT に書き込む。
ℹ️ PNG 仕様と実装の区別。Indexed-color PNG(color type 3)は PNG 仕様の一形式で、bit depth を 1, 2, 4, 8 から選べます。本実装は 8-bit(最大 256 色)で統一しており、tRNS により透明度を付与しています。Mode P が X 上で安定して動作するという点は、PNG 仕様そのものではなく、X 上での観測に基づく経験的な選択です。