Repáralo ahora
- Suelta el archivo
- La reparación ocurre en local
- Descarga el resultado
Cuando un visor, pngcheck, libpng o ImageMagick rechaza un PNG con un "CRC error" — casi siempre libpng error: IDAT: CRC error — significa que los bytes de un chunk ya no coinciden con el checksum guardado junto a ellos. El archivo cambió después de escribirse. Suelta el .png arriba y la herramienta analiza la estructura de chunks en tu navegador, recalcula cada CRC-32 para saber qué chunk se rompió de verdad, y reconstruye un archivo válido en torno a lo que sobreviva — diciéndote con honestidad si tu caso es del tipo determinista y sin pérdida o del tipo parcial, sin que la imagen salga nunca de tu dispositivo.
Qué es realmente un "CRC error" en un PNG
Un PNG empieza con una firma fija de 8 bytes — los bytes 89 50 4E 47 0D 0A 1A 0A — y todo lo que viene después es una cadena de chunks. Cada chunk tiene la misma disposición: una longitud de 4 bytes big-endian (que cuenta solo los datos), un tipo ASCII de 4 bytes como IHDR, IDAT o IEND, los datos en sí, y un CRC-32 final de 4 bytes. Ese checksum se calcula sobre el tipo y los datos del chunk — no sobre su longitud — usando el polinomio estándar ISO-3309 / ITU-T V.42 (en su forma reflejada, 0xEDB88320). Un "CRC error" significa que un decodificador recalculó ese valor y no coincidió con los cuatro bytes del disco: la prueba de que los bytes del chunk cambiaron desde que se escribió el archivo.
Cada herramienta lo expresa a su manera. pngcheck imprime CRC error in chunk IDAT (computed 12ab34cd, expected 89ef01ab); libpng lanza libpng error: IDAT: CRC error o el más escueto Read Error; ImageMagick deja ver la capa zlib de debajo como IDAT: invalid distance too far back; y un navegador simplemente no dibuja nada. El chunk que se nombra en el mensaje te dice lo que está en juego. Un CRC error en un chunk auxiliar (ancillary) — tEXt, gAMA, pHYs, sRGB, cuyo tipo empieza por minúscula — es cosmético y la imagen sigue decodificándose. Un CRC error en un chunk crítico (los cuatro cuyo tipo empieza por mayúscula: IHDR, PLTE, IDAT, IEND) es lo que de verdad impide que el archivo se abra.
Los tres chunks que llevan la imagen son IHDR, IDAT e IEND. IHDR tiene exactamente 13 bytes: anchura y altura (4 bytes cada una), luego la profundidad de bits, el tipo de color (0 escala de grises, 2 color verdadero, 3 indexado, 4 grises+alfa, 6 RGBA), el método de compresión, el método de filtrado y el método de entrelazado. IDAT contiene los píxeles comprimidos y con frecuencia se reparte entre varios chunks consecutivos que hay que concatenar antes de descomprimir. IEND es un marcador vacío, de longitud cero, que indica que el archivo está completo. La herramienta lee esta estructura localmente, comprueba cada CRC e identifica el chunk culpable antes de cambiar un solo byte.
El daño que un PNG puede deshacer con exactitud
Como cada chunk lleva su propio checksum, toda una categoría de daños en un PNG tiene un arreglo determinista — la respuesta correcta se conoce por las matemáticas, no se adivina.
Un CRC incorrecto sobre datos intactos. El fallo más benigno: los datos del chunk son correctos byte a byte, pero su CRC-32 guardado está desactualizado — resultado habitual de un editor que reescribió los datos sin actualizar el checksum, o de un solo bit invertido dentro del propio campo de 4 bytes del CRC. Recalcular el CRC a partir del tipo y los datos y volver a escribirlo deja el archivo válido de nuevo sin pérdida alguna. El checksum era lo único que estaba mal.
Dimensiones puestas a cero o revueltas. Si la anchura o la altura de IHDR se corrompe, ningún decodificador puede reservar un lienzo y el archivo no abre — a menudo como libpng error: Invalid IHDR data. Pero IHDR guarda su propio CRC, calculado cuando las dimensiones aún eran correctas. Eso convierte la recuperación en una búsqueda: se prueban pares candidatos de anchura/altura, se recalcula el CRC-32 del chunk de 13 bytes para cada uno, y se detiene cuando coincide con el valor guardado. Las dimensiones originales salen directamente de la aritmética, exactas, sin adivinar nada.
Estropicio de saltos de línea y del bit alto. La firma de 8 bytes se diseñó como trampa para la corrupción en modo texto: el par 0D 0A detecta una conversión CRLF→LF, el 0A final detecta LF→CRLF, y el 89 inicial (con el bit alto activo) detecta una transferencia de 7 bits que lo eliminó. Cuando un PNG pasó por un cliente FTP en modo ASCII, o por un script que lo reescribió como texto, la sustitución es consistente y reversible — se deshace la transformación y los bytes originales vuelven en todo el archivo, no solo en la firma.
IDAT, deflate y dónde se detiene la recuperación
Dentro de los chunks IDAT los píxeles forman un único flujo de datos zlib: una cabecera de 2 bytes (habitualmente 78 9C), un cuerpo comprimido con deflate y un checksum Adler-32 de 4 bytes al final. Antes de comprimir, cada línea de barrido (scanline) lleva delante un byte de tipo de filtro (0 None, 1 Sub, 2 Up, 3 Average, 4 Paeth) que predice cada píxel a partir de sus vecinos. Las filas se escriben de arriba abajo, y ese único hecho decide qué se puede recuperar una vez que se dañan los datos en sí — no solo un checksum.
Truncamiento. La rotura más común: una descarga que se detuvo antes de tiempo, una copia interrumpida al retirar una unidad, un cierre inesperado a mitad de escritura. La parte delantera del archivo está intacta y la cola — normalmente incluidos IEND y el Adler-32 — sencillamente falta, así que los decodificadores informan de EOF while reading IDAT o del incorrect data check de zlib. Como deflate decodifica de arriba abajo, la herramienta rescata cada línea de barrido completa hasta el corte, escribe un IEND nuevo y válido, y te entrega un parcial honesto: tus píxeles reales, hasta donde alcancen los bytes.
Corrupción en mitad del flujo. Cuando el daño cae dentro del cuerpo deflate y no al final, el límite es duro. Deflate es un flujo continuo sin marcadores periódicos de resincronización, así que en cuanto inflate topa con un byte defectuoso pierde el hilo — verás invalid distance too far back, invalid literal/length code o invalid block type — y todo lo que viene después se decodifica como ruido. Un solo byte corrupto a media altura puede costar todas las filas por debajo, no solo una línea. La herramienta conserva las filas que se decodificaron limpiamente por encima de la herida; no puede volver a coser el flujo por debajo, y un archivo entrelazado (Adam7) pierde además las pasadas posteriores que habrían afinado la parte inferior de la imagen.
Dos casos perdidos, siendo honestos. Un archivo de 0 bytes o todo a ceros no tiene imagen que reconstruir — eso es un problema de recuperación de datos del almacenamiento, no una reparación. Y cuando se sobrescribieron los datos de un chunk (y no solo su CRC), el checksum puede demostrar el daño pero nunca revertirlo. Todo lo anterior se ejecuta enteramente en la pestaña de tu navegador — el analizador es TypeScript sin dependencias — así que un PNG que quizá sea una foto privada, una captura de pantalla o un documento escaneado nunca se copia a un servidor: abre la pestaña Red (Network) y confirma que salen 0 bytes.
Qué puede y qué no puede reparar
Puede reparar
- Un chunk cuyo CRC-32 guardado ya no coincide con su tipo+datos mientras los bytes están intactos — se recalcula y se reescribe sin pérdida alguna
- Un PNG con la anchura/altura de IHDR puesta a cero o revuelta — las dimensiones originales se recuperan por fuerza bruta a partir del CRC de IHDR guardado
- Archivos estropeados por la conversión de saltos de línea CRLF↔LF o por la eliminación del bit alto en una transferencia en modo texto — se deshace la sustitución reversible
- Un PNG truncado al que le falta la cola y el IEND — se rescatan las líneas de barrido superiores que se decodificaron y se escribe un IEND válido
- Las filas por encima de un impacto en mitad de IDAT — se conserva todo lo que deflate decodificó limpiamente antes del byte corrupto
No puede reparar
- Las filas por debajo de una corrupción en mitad de IDAT — deflate no puede resincronizarse, así que todo lo posterior al byte dañado se decodifica como ruido
- Las líneas de barrido posteriores al corte en un archivo truncado — esos bytes nunca se escribieron en el disco
- Un archivo de 0 bytes o todo a ceros — no hay imagen que reconstruir; eso es un problema de recuperación de datos, no una reparación
- Los colores exactos de un chunk cuyos datos (no solo su CRC) se sobrescribieron — el CRC solo prueba el daño, no puede revertirlo
- Las pasadas entrelazadas (Adam7) posteriores que quedan por debajo de una rotura en mitad del flujo — el detalle que añaden se ha perdido
Si una reparación falla, te decimos por qué (datos que faltan frente a estructura dañada), y nunca se te cobra por una reparación fallida.