PNGはどう組み立てられているか
PNGは8バイトのシグネチャで始まります。これは固定の指紋 であり、どんなプログラムでもそのファイルが本当にPNGであることを確認でき ます。それ以降はすべて一連のチャンクで、各チャンクは きちんと整理された小さなパッケージです——長さ、4文字のタイプ、データ そのもの、そして4バイトのチェックサム。
3種類のチャンクが画像全体を担います。IHDRが最初に来て、 要となる情報を保存します——幅、高さ、ビット深度、そしてカラータイプ。IDATは圧縮された画像データを保持し、ときには連続する 複数のIDATチャンクに分割されます。IENDは、ファイルが 完結していることを示す小さな終端マーカーです。IDATチャンクの内部では、 ピクセルがdeflate——ZIPが使うのと同じアルゴリズム——で圧縮され、画像の 一番上の行から一番下まで、ひとつの連続したストリームになっています。
PNGを先頭から末尾まで:シグネチャ、寸法を持つヘッダー、圧縮された画像データ、そして終端マーカー。
PNGを特別なものにしている細部は、すべてのチャンクに付くチェックサムです。 それはチャンクのタイプとデータから計算されるCRC-32であり、このフォーマット を絶えず自己監査するものへと変えています。だからこそPNGは、ほとんどの フォーマットには到底できない精度で、自分自身の損傷を指し示せるのです。
PNGが平然と受け流せる損傷
各チャンクが自己検査と自己記述を備えているため、PNGの損傷のまるごと一つ のカテゴリーには、きれいで確定的な修正法があります。正しい答えは推測する ものではなく、知りうるものなのです。
チェックサムは誤り、データは正しい
最も穏やかなケースです。チャンクのデータは正常なのに、保存されている CRCがもはや一致せず、厳格なデコーダーがファイルを拒否します。データから CRCを再計算して書き戻せば、ファイルは損失ゼロで再び有効になります。 誤っていたのはチェックサムだけだったのです。
ゼロ化された、または誤った寸法
IHDR内の幅や高さがゼロ化されたりかき乱されたりすると、どのデコーダーも キャンバスを用意できず、ファイルは開きません。しかしIHDRは、寸法が正しかった 当時に計算された自分自身のCRCを持っています。これにより、修復ツールは答え を総当たりで求められます——幅と高さの候補値を試し、そのたびにチェックサム を再計算し、保存されているCRCと一致したところで止める。元の寸法は計算から そのまま導き出され、推測は一切要りません。
転送中に壊された改行
定番の例です。改行コードを「気を利かせて」変換してしまうシステムを通った PNG、テキストモードの古いFTPクライアント、あるいはファイルをテキストとして 書き直したスクリプト。それはすべてのキャリッジリターンとラインフィードの組 を単独のラインフィードに、あるいはその逆に置き換え、ファイル全体のバイトを 破損させます。PNGのシグネチャは、まさにこれを検出するために設計されており、 この改変が一貫した可逆的な置換であるとき、その変換は取り消され、元のバイト を復元できます。
切り詰め:上部の行は戻ってくる
切り詰めは、PNGが壊れる最もよくある原因です——80パーセントで止まった ダウンロード、ドライブが抜かれて中断されたコピー、書き込みの途中で クラッシュしたプログラムが保存したファイル。ファイルの前半は無傷で、 末尾は単に存在せず、たいていはIENDマーカーも含めて失われています。 だからこそ、これほど多くのビューアがファイルは不完全だと訴えるのです。
切り詰められたPNG:ヘッダーと画像データの上部は生き残り、ストリームの残りと終端マーカーは届かなかった。
画像は上から下へ書き込まれるため、切り詰められたPNGは絵の上部として サルベージできます——データが終わる地点までの本物のピクセルです。修復は、 デコーダーがファイルを受け入れて生き残った部分を描けるよう、有効な終端を 書き直します。切断より下の行は損傷しているのではなく、存在しないのであり、 だから戻すことはできません。これは正直な部分結果であり、写真修復の側で切り詰められたJPEGが返すのと同じ形の結果です。
ストリーム途中の損傷:なぜ下の行が失われるのか
末尾ではなくIDATデータの途中に起きる損傷は難しいケースであり、その理由は deflateにあります。deflateは画像を、各部分がそれ以前の部分に依存するひとつ の連続したストリームとして圧縮します。再同期のための周期的なマーカーを持た ないため、デコーダーはひとたび破損したバイトにぶつかると、筋道を見失い、 それを取り戻せません。損傷より後のすべてがノイズとしてデコードされます。
実際には、これは途中の1つの不良バイトが、たった1行だけでなく、その下の すべての行を奪いうるということです。絵は被害地点より上ではきれいで、その下 ではゴミになります。修復は、損傷より前にデコードできた行はなおもサルベージ でき、それは確かに得るに値するものですが、破断を越えてストリームを縫い合わせ 直すことはできません。これを、インデックスをデータとは別に保存するフォーマット と比べてみてください。そちらではインデックスを再構築すれば全体を救い出せる ことがあります。PNGはピクセルを分割できないひとつのdeflateストリームに保持 しているため、ストリーム途中の傷は切断より下では永久に残ります。
復元できるもの、ひとつの正直なリストで
壊れたPNGを次のいずれかに分類すれば、労力を費やす前に見通しがわかります。
- チェックサムの不一致、データは無傷。 確定的な修正、 損失なし。CRCを再計算すればファイルは再び有効になります。
- ゼロ化された、またはかき乱された寸法。 ほとんどの場合、 確定的な修正。保存されたIHDRのチェックサムが元のサイズを明かします。
- 転送による改行の破損。 置換が一貫していれば可逆。 変換を取り消し、バイトを復元します。
- 切り詰められたファイル。 部分的。画像の上部は戻り ますが、欠けた末尾は戻りません。
- ストリーム途中のIDAT破損。 よくても部分的。損傷より 上はきれい、下は失われます。deflateが再同期できないからです。
- ゼロバイト、あるいはすべてゼロ。 修復のケースでは ありません。ファイルに再構築すべき画像がそもそもありません。それは 復旧(リカバリ)の問題です。
PNG修復は、修復ツール一覧にある他のフォーマット用 ツールと並んでいます。あなたのファイルがどの区分に入ろうと、良いツールは グレーの行を取り戻すと約束するのではなく、それについての真実を伝えます。
FAQ
なぜPNGが開かないのか?
たいていは次の3つのうちのどれかです。先頭にある8バイトのシグネチャが壊れていて、ビューアがそもそもファイルをPNGだと認識できない。画像の寸法を保持するヘッダーチャンク(IHDR)が誤っていたりゼロで埋められていたりして、デコーダーがキャンバスを用意できない。あるいは、圧縮された画像データが途中で切り詰められたり破損したりしている。最初の2つは、PNGがすべてのチャンクにチェックサムを保存しているため、確定的に直せることが多いです。3つ目は正直な限界が始まる場所です。ファイルに存在しなかった画像の行は、どうやっても取り戻せません。
PNGのCRCエラーとは何を意味するのか?
PNGのすべてのチャンクは、そのチャンクのタイプとデータから計算された4バイトのCRC-32チェックサムで終わります。デコーダーがチェックサムを再計算し、保存されている値と一致しない場合、CRCエラーが報告されます。これは、ファイルが書き込まれてから、そのチャンクのバイトが変化したことを意味します。もしチェックサム自体だけが誤っていてデータは正常なら、それを再計算するだけでファイルは完全に直ります。データが変化していた場合、CRCは警告を出すという本来の役目を果たしているのであり、画像がどれだけ復元できるかは、どのチャンクが被害を受けたかによります。
切り詰められたPNGは復元できるか?
部分的に、しかも上部だけです。PNGは画像をdeflateで圧縮し、行を上から下へと書き込みます。そのため、途中で切れたファイルは、データが終わる地点まではきれいにデコードでき、そこで止まります。画像の上部が本物のピクセルとして戻ってきます。切断より下の行は、そもそもファイルに存在しなかったので、どんなツールでも復元できません。修復された切り詰めPNGは正直な部分結果です。バイトが続くところまでの、あなたの本物の画像です。
なぜPNGの下部が欠けていたり乱れていたりするのか?
PNGが使う圧縮方式であるdeflateが、損傷後に再同期する手段を持たない連続的なストリームだからです。破損が末尾ではなく画像データの途中に起きると、デコーダーはそのバイトで筋道を見失い、それ以降のすべてが、被害を受けた1行だけでなくノイズとしてデコードされます。だからこそ、ストリーム途中の損傷は通常、被害地点より下のすべての行を奪う一方で、きれいな切り詰めなら少なくとも上部は無傷で残るのです。
下半分がグレーで開く写真には、JPEGの世界に近い親戚がいます:JPEGの半分がグレーになる理由。