PNG の "CRC error" と IDAT の破損

PNG はそれ自体を監査します。すべてのチャンクが CRC-32 で終わるため、この形式は自らの破損を稀なほどの精度で指し示せます。同じ構造が明確な一線を引きます—正常なデータに対する誤ったチェックサムは無損失で直せる一方、IDAT の deflate ストリーム内で失われた 1 バイトはその下のすべての行を奪います。あなたのファイルを正しい分類に振り分けるのに、どこかへアップロードする必要はありません。

ファイルがデバイスから出ることはありません — 修復はブラウザ内で実行されます。アップロードは 0 バイトです。

Your data is the big block — usually intact. What breaks is the small index. Repair rebuilds it.

Drop a file here or browseTap to choose a file

ZIP · Office · PDF · video · JPG · PNG · RAR/7z · SQLite — repaired right here in your browser. Nothing is uploaded

0 bytes uploadedFree: 3 repairs/day — up to 500 MB video, 100 MB docs & archives, 50 MB photos. Free download. Single repair €5.90. No account required.

今すぐ修復

  1. ファイルをドロップ
  2. 修復はローカルで実行
  3. 結果をダウンロード

ビューアー、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 バイトのビッグエンディアン長さ(データ部分のみを数える)、IHDRIDATIEND のような 4 バイトの ASCII タイプデータそのもの、そして末尾の 4 バイトの CRC-32 です。このチェックサムは、チャンクのタイプとデータに対して—長さは含めず—標準の ISO-3309 / ITU-T V.42 多項式(反転形の 0xEDB88320)を使って計算されます。"CRC error" とは、デコーダーがその値を再計算した結果、ディスク上の 4 バイトと一致しなかったということ、すなわちファイルが書き込まれて以降にそのチャンクのバイト列が変化したという証拠です。

各ツールはそれぞれの言い回しで表現します。pngcheckCRC 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)チャンク—tEXtgAMApHYssRGB のように、タイプが小文字で始まるもの—の CRC error は見た目上のものにすぎず、画像は問題なくデコードされます。クリティカルチャンク(タイプが大文字で始まる 4 つ、IHDRPLTEIDATIEND)の CRC error こそが、ファイルが開かなくなる本当の原因です。

画像を運ぶ 3 つのチャンクは IHDRIDATIEND です。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 backinvalid literal/length codeinvalid 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)パス—それらが加えるはずだった細部は失われています

修復が失敗した場合、その理由(データの欠落か構造の破損か)をお伝えします。失敗した修復に料金が請求されることはありません。

よくある質問

PNG の "CRC error" は、私の画像が失われたということですか?

必ずしもそうではありません。各チャンクの CRC-32 は、そのチャンクのバイト列がファイルの書き込み以降に変化したことを告げるだけです。チェックサムだけが誤っていてデータが無傷なら、再計算すればファイルは無損失で直ります。データそのものが変化した場合、どれだけ復元できるかはどのチャンクが被害を受けたかによります—tEXt のような補助チャンクの不良は見た目上のものですが、IDAT 内部の破損はその下の行を奪いかねません。

IDAT とは何ですか。なぜそこの破損は画像の下部を失わせるのですか?

IDAT は圧縮されたピクセルを、上から下へ書き込まれた 1 本の連続した deflate ストリームとして保持します。deflate には再同期するための周期的なマーカーがないので、デコーダーが壊れたバイトにぶつかると流れの糸を見失い、それより後はすべてノイズとしてデコードされます。だからこそ、途中の 1 バイトの不良がその下のすべての行を奪う一方、きれいな切り詰めなら少なくとも上部は無傷で残るのです。

私の PNG はあるプログラムでは開くのに、別のプログラムでは CRC error になります—なぜですか?

寛容なビューアーの多くは CRC の不一致を無視してファイルをそのまま描画しますが、pngcheck や libpng のような厳格なツールはそれを拒否します。どこかで開けるということは、たいていピクセルデータは正常でチェックサムだけが古いということ—決定論的で無損失のケースです。CRC を再計算すれば、どの厳格なデコーダーも受け入れるファイルができあがります。

ゼロ化された画像の寸法(IHDR)は本当に正確に復元できるのですか?

はい、ほとんどの場合できます。IHDR チャンクは、幅と高さがまだ正しかったときに計算された CRC-32 を持っています。復元は候補となる寸法を試し、それぞれについてチャンクの CRC を再計算し、保存された値と一致したところで止めます—したがって元のサイズは推測ではなく数学から導かれます。

私の PNG は修復のためにアップロードされますか?

いいえ。ファイルはあなたのディスクから読み込まれ、ブラウザのタブ内で再構築されます。パーサーは純粋な TypeScript で、何も送信されません。Network タブ(ネットワーク)を開いて、出ていくバイトが 0 であることを確認できます—PNG が私的な写真、機密性のある何かのスクリーンショット、あるいはスキャンした書類であるときに、これは重要です。

関連: JPEG を修復する · PNG が開かない理由: チャンク、CRC、そして何が復元できるか · "Unexpected end of archive"(deflate の切り詰め) · アップロードが 0 であることを検証する