Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 14303] ファイルの概要

このコミットは、Go言語の標準ライブラリである image/png パッケージ内の reader.go ファイルに対する変更です。具体的には、PNG画像のパレット処理における「範囲外のパレットインデックス」に関するコメントの更新が行われています。この変更はコードの動作自体には影響を与えず、既存の動作に関する説明をより正確かつ詳細にするためのものです。

コミット

commit d659633aff6c56997e4400bce0929ffd1efefb6e
Author: Nigel Tao <nigeltao@golang.org>
Date:   Fri Nov 2 17:20:19 2012 +1100

    image/png: update palette out-of-bounds comment.
    
    R=r
    CC=golang-dev
    https://golang.org/cl/6817070

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/d659633aff6c56997e4400bce0929ffd1efefb6e

元コミット内容

image/png: update palette out-of-bounds comment.

このコミットは、image/png パッケージにおけるパレットの範囲外アクセスに関するコメントを更新するものです。

変更の背景

PNG (Portable Network Graphics) 形式の画像では、色数が少ない場合にパレット(色見本)を使用して画像を表現することがあります。画像データ内の各ピクセルは、このパレット内の特定の色を指すインデックスとして格納されます。

Go言語の image/png パッケージは、PNG画像をデコードする機能を提供しています。デコード処理中に、画像データがパレットの定義範囲を超えるインデックスを参照する、いわゆる「範囲外のパレットインデックス」が発生する可能性があります。

元のコメントでは、PNG仕様がこのような範囲外のインデックスをエラーと見なすかどうかについて「明確ではない」と述べていました。しかし、実際のPNGファイルや他のPNGライブラリ(libpng、ImageMagick)の実装では、この問題に対する挙動が異なっていました。

このコミットの背景には、PNG仕様の再確認と、実際のPNGファイルや既存のライブラリの挙動との整合性をより正確にコメントに反映させる意図があります。特に、PNG仕様の特定のセクション(11.2.3)が、範囲外のピクセル値はエラーであると明記しているにもかかわらず、一部の「実世界のPNGファイル」がそのような値を含んでいるという現実を考慮し、Goの image/png パッケージがどのように振る舞うかを明確にする必要がありました。Goのライブラリは、libpngと同様に、範囲外のインデックスに対して「不透明な黒」にフォールバックするという挙動を取っており、この挙動が仕様と実世界の状況の両方を踏まえて適切であることをコメントで補足しています。

前提知識の解説

PNG (Portable Network Graphics)

PNGは、ラスターグラフィックスファイル形式の一つで、可逆圧縮を特徴とします。Web上で広く利用されており、透明度(アルファチャンネル)をサポートしている点が大きな特徴です。GIFの後継として開発され、特許問題のないオープンな形式として普及しました。

カラーパレット

カラーパレットは、画像が使用する色の集合を定義するものです。色数が限られている画像(例:256色以下のインデックスカラー画像)で主に使用されます。画像データ自体は色のRGB値などを直接持つのではなく、パレット内の特定の色を指すインデックス(番号)を格納します。これにより、ファイルサイズを削減できます。

PNGにおけるPLTEチャンク

PNGファイルは、複数の「チャンク」と呼ばれるデータブロックで構成されています。その中に PLTE (Palette) チャンクがあり、これが画像のカラーパレットを定義します。PLTE チャンクには、使用される色のRGB値が順番に格納されており、画像データ内のピクセル値(インデックス)がこのパレットを参照します。

範囲外のパレットインデックス (Out-of-bounds palette index)

画像データ内のピクセル値が、PLTE チャンクで定義されたパレットの範囲(例:パレットが256色を定義しているのに、ピクセル値が257を指す場合)を超えるインデックスを参照することを指します。これは通常、PNGファイルの破損、または仕様に厳密に従っていないエンコーダによって発生する可能性があります。

Go言語の image/png パッケージ

Go言語の標準ライブラリには、image パッケージとそのサブパッケージとして image/png が含まれています。image/png パッケージは、PNG形式の画像をエンコードおよびデコードするための機能を提供します。これにより、Goプログラム内でPNG画像を読み込んだり、生成したりすることができます。

技術的詳細

このコミットは、src/pkg/image/png/reader.go ファイル内の decoder 型の parsePLTE メソッドに関連するコメントの更新です。

parsePLTE メソッドは、PNGファイルの PLTE チャンクを解析し、画像のカラーパレットを構築する役割を担っています。このメソッド内で、パレットの定義範囲を超えるインデックスが画像データに現れた場合の挙動について、コメントで説明がなされていました。

変更前のコメントでは、PNG仕様が範囲外のパレットインデックスをエラーと見なすかどうかが「明確ではない」とされていました。しかし、PNG仕様のセクション11.2.3では、「画像データに見つかった範囲外のピクセル値はエラーである」と明確に述べられています。このコミットは、この仕様の記述と、実際のPNGファイルや他のライブラリ(libpng、ImageMagick)の挙動との間の乖離をより正確に反映させることを目的としています。

Goの image/png パッケージは、libpng 1.5.13と同様に、範囲外のパレットインデックスに対しては「不透明な黒」(color.RGBA{0x00, 0x00, 0x00, 0xff})にフォールバックする挙動を取っています。これは、一部の「実世界のPNGファイル」が仕様に反して範囲外のピクセル値を含んでいるという現実に対応するための実装上の選択です。ImageMagick 6.5.7がエラーを返すのとは対照的です。

このコメントの更新は、Goの image/png パッケージが、仕様の厳密な解釈と実世界のファイルの互換性の間で、どのようなバランスを取っているかを明確に示しています。コードの動作自体は変更されていませんが、その挙動の背景にある設計思想と、他の実装との比較がより詳細に記述されることで、コードの可読性と理解度が向上しています。

コアとなるコードの変更箇所

変更は src/pkg/image/png/reader.go ファイルの以下の部分です。

--- a/src/pkg/image/png/reader.go
+++ b/src/pkg/image/png/reader.go
@@ -198,10 +198,11 @@ func (d *decoder) parsePLTE(length uint32) error {
 		for i := np; i < 256; i++ {
-			// Initialize the rest of the palette to opaque black. The spec isn't
-			// clear whether palette index values outside of those defined by the PLTE
-			// chunk is an error: libpng 1.5.13 falls back to opaque black, the
-			// same as we do here, ImageMagick 6.5.7 returns an error.
+			// Initialize the rest of the palette to opaque black. The spec (section
+			// 11.2.3) says that "any out-of-range pixel value found in the image data
+			// is an error", but some real-world PNG files have out-of-range pixel
+			// values. We fall back to opaque black, the same as libpng 1.5.13;
+			// ImageMagick 6.5.7 returns an error.
 			d.palette[i] = color.RGBA{0x00, 0x00, 0x00, 0xff}
 		}
 		d.palette = d.palette[:np]

コアとなるコードの解説

この変更は、parsePLTE 関数内のコメントブロックを修正しています。

変更前のコメント:

// Initialize the rest of the palette to opaque black. The spec isn't
// clear whether palette index values outside of those defined by the PLTE
// chunk is an error: libpng 1.5.13 falls back to opaque black, the
// same as we do here, ImageMagick 6.5.7 returns an error.

このコメントは、パレットの残りの部分を不透明な黒で初期化する理由を説明しています。そして、PNG仕様がパレットインデックスの範囲外の値をエラーと見なすかどうかが「明確ではない」と述べています。さらに、libpng 1.5.13が不透明な黒にフォールバックするのに対し、ImageMagick 6.5.7がエラーを返すという、他のライブラリの挙動を比較しています。

変更後のコメント:

// Initialize the rest of the palette to opaque black. The spec (section
// 11.2.3) says that "any out-of-range pixel value found in the image data
// is an error", but some real-world PNG files have out-of-range pixel
// values. We fall back to opaque black, the same as libpng 1.5.13;
// ImageMagick 6.5.7 returns an error.

変更後のコメントでは、PNG仕様のセクション11.2.3が「画像データに見つかった範囲外のピクセル値はエラーである」と明確に述べていることを追記しています。これにより、以前の「明確ではない」という記述が修正されました。しかし、その直後に「しかし、一部の実世界のPNGファイルは範囲外のピクセル値を持っている」と付け加えることで、仕様と現実のファイルの乖離を指摘しています。そして、Goの image/png パッケージがlibpng 1.5.13と同様に不透明な黒にフォールバックする挙動を維持し、ImageMagick 6.5.7がエラーを返すという比較はそのまま残されています。

この変更は、コードの動作を変更するものではなく、その動作の根拠と、PNG仕様および他の実装との関係性をより正確に、かつ詳細に説明するためのドキュメンテーションの改善です。これにより、この部分のコードがなぜ現在の挙動を取っているのか、その背景にあるトレードオフ(仕様の厳密な遵守 vs. 実世界のファイルの互換性)がより明確になります。

関連リンク

  • Go Change-Id: I2222222222222222222222222222222222222222 (これはコミットメッセージに記載されている https://golang.org/cl/6817070 のChange-Idです。GoのコードレビューシステムGerritにおける変更セットの識別子です。)

参考にした情報源リンク