Documentación

Documentación de BIC

Todo lo necesario para usar BIC: los paquetes, su API, los plugins de build, la línea de comandos y el formato. Los ejemplos son código real de los paquetes publicados.

Resumen

BIC es un formato de imagen sin pérdida. Guarda gráficas, logotipos, íconos, diagramas y pixel art en menos bytes que un PNG optimizado, y conserva las fotografías como su JPEG original (agregando solo 32 bytes). El proyecto tiene tres partes:

  • @proteo5/bic-runtime: un decodificador para navegadores y Node.js. Sin dependencias, salvo fzstd; 5.7 KiB con gzip.
  • @proteo5/bic-build: un paso de build para Vite y webpack que convierte las imágenes que se benefician, y un comando bic-build.
  • bic: la herramienta de línea de comandos y el visor, para Windows, Linux y macOS.

El formato de archivo está descrito en FORMAT.md.

Instalación

Instala los paquetes que necesites. El decodificador basta para leer archivos .bic; el paso de build es para proyectos que convierten imágenes.

npm install @proteo5/bic-runtime
npm install --save-dev @proteo5/bic-build

El paso de build necesita el programa bic. Al instalarse descarga el binario de tu plataforma desde el release con el mismo número de versión, lo verifica contra las sumas del release y lo guarda en vendor/.

Variable de entornoEfecto
BIC_SKIP_DOWNLOAD=1No descarga el binario (instalaciones sin red).
BIC_BIN=/ruta/a/bicUsa este binario en lugar del descargado.

Sin ninguna de las dos, se usa bic del PATH. Los binarios de cada versión están en la página de releases.

API del decodificador

Importa desde @proteo5/bic-runtime. Las funciones funcionan en navegadores y en Node.js.

decodeBic(entrada, opciones?)

Decodifica un archivo BIC dado como Uint8Array o ArrayBuffer. Devuelve uno de dos resultados:

  • { kind: 'pixels', width, height, rgba, icc }: la codificación propia de BIC. rgba es un Uint8Array de píxeles RGBA de 8 bits, por filas.
  • { kind: 'file', mime, bytes, width, height, icc }: un PNG o un JPEG/WebP original guardado en el archivo. Muestra bytes tal cual.

icc es el perfil de color ICC cuando el archivo lo tiene, si no, null. Opciones: maxPixels (por defecto 100 millones) rechaza imágenes más grandes antes de usar memoria.

import { decodeBic, BicError } from '@proteo5/bic-runtime';

const bytes = new Uint8Array(await (await fetch('grafica.bic')).arrayBuffer());
try {
  const imagen = decodeBic(bytes);
  if (imagen.kind === 'pixels') {
    const canvas = document.createElement('canvas');
    canvas.width = imagen.width;
    canvas.height = imagen.height;
    canvas.getContext('2d').putImageData(
      new ImageData(new Uint8ClampedArray(imagen.rgba), imagen.width, imagen.height), 0, 0);
    document.body.append(canvas);
  } else {
    const url = URL.createObjectURL(new Blob([imagen.bytes], { type: imagen.mime }));
    document.body.insertAdjacentHTML('beforeend', `<img src="${url}" alt="">`);
  }
} catch (error) {
  if (error instanceof BicError) console.error('No es un archivo .bic válido:', error.message);
  else throw error;
}

Otras exportaciones

  • parseContainer(entrada, opciones?): los campos del encabezado y la carga del archivo, sin decodificar los píxeles.
  • sniffImageType(bytes): image/png, image/jpeg, image/webp o image/heif, según la firma; null si no se reconoce.
  • BicError: se lanza con entradas mal formadas o dañadas. Otras excepciones no se esperan.

Rendimiento: una gráfica de 1600 píxeles se decodifica en unos 20 a 40 ms en JavaScript. El decodificador se prueba contra el de Rust con 53 casos, y con corrupción aleatoria.

Plugin de Vite

El plugin convierte las imágenes que cumplen la regla durante vite build, y las sirve con un Service Worker bajo sus URL originales. Tu HTML, CSS y JavaScript no cambian.

// vite.config.js
import { bicVite } from '@proteo5/bic-build/vite';

export default {
  plugins: [bicVite({ policy: { minSaving: 0.1, maxDistinctColors: 4096 } })],
};

Opciones: policy (ver la regla de conversión), y bic para la ruta del binario. El plugin corre solo en vite build.

El build escribe estos archivos junto a tus assets:

  • bic-sw.js: el Service Worker, con la lista de imágenes convertidas incluida.
  • bic-loader.js: registra el worker. Se agrega a cada página HTML antes de </head>.
  • bic-report.json: la decisión y el motivo de cada imagen.

Requisitos y límites

  • La ruta base debe ser absoluta (/, /app/). Con una base relativa no se convierte nada.
  • Los Service Workers necesitan HTTPS o localhost.
  • La primera visita descarga el PNG de siempre. Las siguientes muestran la imagen convertida, y la imagen decodificada se guarda en caché, así que cada .bic se descarga una vez por dispositivo.
  • Las imágenes incrustadas como data URL y los archivos copiados desde public/ no se convierten.
  • Si una conversión falla, se conserva el archivo original y se imprime una advertencia; el build no falla.

Plugin de webpack

El mismo comportamiento para webpack 5, en builds de producción. Necesita un output.publicPath absoluto.

// webpack.config.mjs
import { BicWebpackPlugin } from '@proteo5/bic-build/webpack';

export default {
  mode: 'production',
  output: { publicPath: '/' },
  plugins: [new BicWebpackPlugin({ policy: { minSaving: 0.1 } })],
};

Opciones: policy, bic, y enableInDevelopment: true para convertir también en builds de desarrollo. El loader se agrega a las páginas HTML generadas por html-webpack-plugin u otro plugin que escriba HTML.

Regla de conversión

El paso de build convierte una imagen solo cuando se cumplen todas estas condiciones:

  • La imagen no es un JPEG. El JPEG tiene pérdida, y BIC lo conserva tal cual.
  • Tiene como máximo maxDistinctColors colores (por defecto 4096). Más colores significa una imagen parecida a una fotografía.
  • El archivo BIC es al menos minSaving más pequeño que el mejor formato sin pérdida: PNG, oxipng o WebP sin pérdida (por defecto 0.1, es decir 10%).

La misma regla está disponible como función, para tus herramientas:

import { decide, DEFAULT_POLICY } from '@proteo5/bic-build';

// medición: el JSON de `bic inspect --json <imagen>`
const decision = decide(medicion, { minSaving: 0.2 });
// decision.use, decision.reason, decision.saving, decision.best

Línea de comandos

El programa bic codifica, decodifica, verifica y mide imágenes. El paso de build lo usa por ti; estos comandos son para scripts y trabajo manual.

ComandoQué hace
bic encode <entrada> <salida.bic>Codifica una imagen. Opciones: --max-error N (casi sin pérdida), --png-fallback, --fast-decode, --transcode, --zstd-level N.
bic decode <entrada.bic> <salida>Decodifica a PNG, JPEG, WebP o BMP, según la extensión.
bic verify <original> <entrada.bic>Comprueba que el archivo se decodifica a los píxeles originales. --max-error N acepta diferencias acotadas.
bic inspect <imagen> [--json]Tamaños de PNG, oxipng, WebP sin pérdida y BIC para una imagen.
bic compare <rutas...> [--csv salida.csv]Compara BIC con los otros formatos sin pérdida, en archivos o carpetas.
bic view <archivo>Abre un .bic o cualquier imagen soportada en el visor.
bic install-associationAsocia los archivos .bic con el visor para el usuario de Windows actual.
bic-build <entrada> <salida>Convierte una carpeta con la regla de arriba. Opciones: --min-saving 10, --max-colors 4096, --bic ruta.
# Sin pérdida, verificado
bic encode logo.png logo.bic
bic verify logo.png logo.bic

# Casi sin pérdida: ninguna muestra difiere más de 2
bic encode foto.png foto.bic --max-error 2

# Convierte una carpeta y escribe bic-manifest.json junto a los archivos
npx bic-build src/images dist/bic

Formato de archivo

Un archivo BIC2 tiene un encabezado de 32 bytes y una carga. La carga es la codificación propia de BIC (planos, paletas o transformadas de color, predictores y bloques de longitud de series, comprimidos con Zstandard), un PNG, o el archivo JPEG, WebP o HEIF original. La especificación completa, con los límites del decodificador, está en FORMAT.md.

El formato es experimental. Puede cambiar entre versiones; las pruebas mantienen idénticos los decodificadores de JavaScript y de Rust.

Solución de problemas

SíntomaCausa y solución
El build dice que la ruta base no es absolutaPon base en Vite o output.publicPath en webpack con una ruta absoluta como /.
No se convierte ninguna imagenRevisa bic-report.json: cada imagen tiene un motivo. Los JPEG nunca se convierten, y las imágenes con más colores que el límite se conservan.
Las imágenes no se sirven como BIC en la primera visitaEs lo esperado: el worker se instala en la primera visita. Recarga una vez; las siguientes visitas lo usan.
La página funciona en local pero no en el servidorLos Service Workers necesitan HTTPS. GitHub Pages, Netlify y servicios similares lo ofrecen.
bic is older than the bic-build packageEl binario no tiene el comando inspect. Instala un release actual, o usa BIC_BIN.
La instalación dice que no pudo descargar el binarioRevisa la red, o usa BIC_BIN. El paquete sigue funcionando con un binario del PATH.
Navegador no soportadoProbado en Chrome. Firefox y Safari todavía no están probados.

Recursos