今すぐ修復
- ファイルをドロップ
- 修復はローカルで実行
- 結果をダウンロード
ビューアー、pngcheck、libpng、あるいは ImageMagick が PNG を "CRC error"—多くの場合 libpng error: IDAT: CRC error—で拒否するとき、それはあるチャンクのバイト列が、その隣に保存されたチェックサムともはや一致しないことを意味します。ファイルは書き込まれた後に変化したのです。上に .png をドロップすると、ツールはブラウザ内でチャンク構造を解析し、すべての CRC-32 を再計算して実際にどのチャンクが壊れたのかを突き止め、生き残ったものの周りに有効なファイルを再構築します—そして、あなたのケースが決定論的で無損失の種類なのか、それとも部分的な種類なのかを正直に伝えます。画像がデバイスから外に出ることは決してありません。
PNG の "CRC error" とは実際には何か
PNG は 8 バイトの固定シグネチャ—バイト列 89 50 4E 47 0D 0A 1A 0A—で始まり、その後に続くものはすべてチャンクの連なりです。各チャンクはまったく同じ形で並びます。4 バイトのビッグエンディアン長さ(データ部分のみを数える)、IHDR、IDAT、IEND のような 4 バイトの ASCII タイプ、データそのもの、そして末尾の 4 バイトの CRC-32 です。このチェックサムは、チャンクのタイプとデータに対して—長さは含めず—標準の ISO-3309 / ITU-T V.42 多項式(反転形の 0xEDB88320)を使って計算されます。"CRC error" とは、デコーダーがその値を再計算した結果、ディスク上の 4 バイトと一致しなかったということ、すなわちファイルが書き込まれて以降にそのチャンクのバイト列が変化したという証拠です。
各ツールはそれぞれの言い回しで表現します。pngcheck は CRC error in chunk IDAT (computed 12ab34cd, expected 89ef01ab) と出力し、libpng は libpng error: IDAT: CRC error あるいはより素っ気ない Read Error を投げ、ImageMagick はその下層の zlib を IDAT: invalid distance too far back として露わにし、ブラウザは単に何も描画しません。メッセージに名指しされたチャンクが、何が懸かっているのかを教えてくれます。補助(ancillary)チャンク—tEXt、gAMA、pHYs、sRGB のように、タイプが小文字で始まるもの—の CRC error は見た目上のものにすぎず、画像は問題なくデコードされます。クリティカルチャンク(タイプが大文字で始まる 4 つ、IHDR、PLTE、IDAT、IEND)の CRC error こそが、ファイルが開かなくなる本当の原因です。
画像を運ぶ 3 つのチャンクは IHDR、IDAT、IEND です。IHDR はちょうど 13 バイトで、幅と高さ(各 4 バイト)、続いてビット深度、カラータイプ(0 グレースケール、2 トゥルーカラー、3 インデックスカラー、4 グレー+アルファ、6 RGBA)、圧縮方式、フィルター方式、インターレース方式が入ります。IDAT は圧縮されたピクセルを保持し、しばしば複数の連続したチャンクに分割されていて、展開の前に連結する必要があります。IEND は長さゼロの空のマーカーで、ファイルが完結していることを示します。ツールはこの構造をローカルで読み取り、すべての CRC を検証し、1 バイトも変更する前に問題のあるチャンクを特定します。
PNG が正確に元へ戻せる破損
各チャンクが自身のチェックサムを持つため、PNG の破損のうち丸ごと 1 つのカテゴリーには決定論的な直し方があります—正しい答えは数学から分かるのであって、推測するものではありません。
正常なデータに対する誤った CRC。最も穏やかな失敗です。チャンクのデータはバイト単位で正しいのに、保存された CRC-32 が古いままになっている—データを書き換えたのにチェックサムを更新しなかったエディター、あるいは 4 バイトの CRC フィールドそのものの中で反転した 1 ビットが引き起こす、よくある結果です。タイプとデータから CRC を再計算して書き戻せば、ファイルは無損失で再び有効になります。唯一おかしかったのはチェックサムだけだったのです。
ゼロ化された、あるいは掻き乱された寸法。IHDR の幅や高さが破損すると、どのデコーダーもキャンバスを確保できず、ファイルは開きません—しばしば libpng error: Invalid IHDR data として現れます。しかし IHDR は、寸法がまだ正しかったときに計算された自身の CRC を保存しています。これにより復元は探索の問題になります。幅と高さの候補ペアを試し、それぞれについて 13 バイトのチャンクの CRC-32 を再計算し、保存された値と一致したところで止める。元の寸法は演算からそのまま、正確に、何も推測せずに導き出されます。
改行と最上位ビットの破壊。8 バイトのシグネチャは、テキストモードでの破損を捕らえる仕掛けとして設計されました。0D 0A のペアは CRLF→LF の変換を捕らえ、末尾の 0A は LF→CRLF を捕らえ、先頭の 89(最上位ビットが立っている)はそれを剥ぎ取った 7 ビット転送を捕らえます。PNG が ASCII モードの FTP クライアントを通ったり、それをテキストとして書き換えるスクリプトを通ったりしたとき、その置換は一貫していて可逆です—変換を元に戻せば、シグネチャだけでなくファイル全体で元のバイト列が戻ります。
IDAT、deflate、そして復元が止まる場所
IDAT チャンクの内部では、ピクセルは単一の zlib データストリームを成しています。2 バイトのヘッダー(一般に 78 9C)、deflate で圧縮された本体、そして末尾に置かれた 4 バイトの Adler-32 チェックサムです。圧縮の前に、各走査線(scanline)の先頭には 1 バイトのフィルタータイプ(0 None、1 Sub、2 Up、3 Average、4 Paeth)が付き、各ピクセルをその近傍から予測します。行は上から下へ書き込まれ、この一点が、チェックサムだけでなくデータそのものが損なわれたときに何が復元可能かを決めます。
切り詰め(truncation)。最もよくある壊れ方です。途中で止まったダウンロード、ドライブを抜いたときに中断されたコピー、書き込みの最中のクラッシュ。ファイルの前半は無傷で、末尾—通常は IEND と Adler-32 を含む—が単に欠落しているため、デコーダーは EOF while reading IDAT や zlib の incorrect data check を報告します。deflate は上から下へデコードするので、ツールは切断点までの完全な走査線をすべて救い出し、新しい有効な IEND を書き込み、正直な部分結果をあなたに渡します—バイトが届く限りの、あなたの本物のピクセルです。
ストリーム途中の破損。破損が末尾ではなく deflate 本体の内部に落ちると、限界は厳しくなります。deflate は周期的な再同期マーカーを持たない 1 本の連続したストリームなので、inflate が不正なバイトにぶつかった時点で流れの糸を見失い—invalid distance too far back、invalid literal/length code、invalid block type が現れ—その地点より後はすべてノイズとしてデコードされます。途中で 1 バイト壊れただけでも、1 行ではなくその下のすべての行を失いかねません。ツールは傷の上できれいにデコードできた行を保持しますが、その下でストリームを縫い直すことはできません。さらにインターレース(Adam7)ファイルでは、画像下部を鮮明にするはずだった後続のパスも失われます。
正直に言って、どうにもならない 2 つのケース。0 バイトまたは全部ゼロのファイルには再構築すべき画像がありません—それはストレージのデータ復旧の問題であって、修復ではありません。そして、チャンクのデータそのもの(単なる CRC ではなく)が上書きされた場合、チェックサムは破損を証明できても、それを元に戻すことは決してできません。以上のすべてはあなたのブラウザのタブ内で完結して実行されます—パーサーは依存関係のない TypeScript です—ので、私的な写真、スクリーンショット、あるいはスキャンした書類かもしれない PNG がサーバーにコピーされることはありません。Network タブ(ネットワーク)を開いて、出ていくバイトが 0 であることを確認してください。
修復できるものとできないもの
修復できる
- バイトが無傷のまま、保存された CRC-32 がタイプ+データともはや一致しないチャンク—再計算して無損失で書き戻します
- IHDR の幅/高さがゼロ化または掻き乱された PNG—保存された IHDR の CRC から元の寸法を総当たりで割り出します
- テキストモード転送での CRLF↔LF 改行変換や最上位ビットの除去によって壊れたファイル—可逆な置換を元に戻します
- 末尾と IEND が欠けた切り詰められた PNG—デコードできた上部の走査線を救い出し、有効な IEND を書き込みます
- IDAT のストリーム途中の被害より上の行—壊れたバイトの前に deflate がきれいにデコードしたものはすべて保持します
修復できない
- IDAT のストリーム途中の破損より下の行—deflate は再同期できないため、壊れたバイトより後はすべてノイズとしてデコードされます
- 切り詰められたファイルで切断点より後の走査線—それらのバイトはそもそもディスクに書き込まれませんでした
- 0 バイトまたは全部ゼロのファイル—再構築すべき画像がありません。それはデータ復旧の問題であって、修復ではありません
- CRC だけでなくデータそのものが上書きされたチャンクの正確な色—CRC は破損を証明するだけで、元に戻すことはできません
- ストリーム途中の断裂より下の、後続のインターレース(Adam7)パス—それらが加えるはずだった細部は失われています
修復が失敗した場合、その理由(データの欠落か構造の破損か)をお伝えします。失敗した修復に料金が請求されることはありません。