{"version":3,"sources":["../../src/encode/ico.ts"],"names":["createCanvas","canvasToBlob","buffer"],"mappings":"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","file":"ico.cjs","sourcesContent":["import type { FormatMeta, EncodeOptions } from '../types.js';\n\nimport { canvasToBlob, createCanvas } from '../transform/canvas.js';\n\nexport const meta: FormatMeta = {\n  key: 'ico',\n  aliases: [],\n  label: 'ICO',\n  mime: 'image/x-icon',\n  ext: 'ico',\n  supportsCompression: false,\n  compressionType: 'none',\n  defaultQuality: null,\n  qualityRange: null,\n  qualityHint: 'ICO uses PNG compression internally for ≥256px',\n  requiresAlphaCompositing: false,\n  supportsTransparency: true,\n};\n\n/** Standard ICO sizes to include (largest to smallest) */\nconst ICO_SIZES = [256, 128, 64, 48, 32, 16] as const;\n\n/**\n * Encode a Canvas to ICO format.\n * Produces a multi-size ICO with PNG-compressed entries.\n * Includes sizes: 256, 128, 64, 48, 32, 16 (all that fit within the source).\n */\nexport async function encode(\n  canvas: HTMLCanvasElement | OffscreenCanvas,\n  _options?: EncodeOptions,\n): Promise<Blob> {\n  const srcW = canvas.width;\n  const srcH = canvas.height;\n  const size = Math.min(srcW, srcH);\n\n  // Filter sizes that fit within the source image\n  const sizes: number[] = ICO_SIZES.filter((s) => s <= size);\n  if (sizes.length === 0) {\n    // Source is smaller than 16px — just use its actual size\n    sizes.push(Math.min(size, 16));\n  }\n\n  // Generate PNG blobs for each size\n  const pngEntries: { size: number; data: Uint8Array }[] = [];\n\n  for (const s of sizes) {\n    const scaled = createCanvas(s, s);\n    const ctx = scaled.getContext('2d') as\n      | CanvasRenderingContext2D\n      | OffscreenCanvasRenderingContext2D;\n\n    if (!ctx) throw new Error('Failed to get 2D context for ICO encoding');\n\n    // Draw source scaled to fit\n    ctx.drawImage(canvas as HTMLCanvasElement, 0, 0, s, s);\n\n    const pngBlob = await canvasToBlob(scaled, 'image/png');\n    const buffer = await pngBlob.arrayBuffer();\n    pngEntries.push({ size: s, data: new Uint8Array(buffer) });\n  }\n\n  // Build ICO file\n  // ICO Header: 6 bytes\n  // Each directory entry: 16 bytes\n  // Then PNG data blocks\n  const numImages = pngEntries.length;\n  const headerSize = 6;\n  const dirSize = 16 * numImages;\n  let dataOffset = headerSize + dirSize;\n\n  // Calculate total file size\n  let totalSize = dataOffset;\n  for (const entry of pngEntries) {\n    totalSize += entry.data.length;\n  }\n\n  const buffer = new ArrayBuffer(totalSize);\n  const view = new DataView(buffer);\n  const bytes = new Uint8Array(buffer);\n\n  // ICO Header\n  view.setUint16(0, 0, true);              // Reserved: 0\n  view.setUint16(2, 1, true);              // Type: 1 = ICO\n  view.setUint16(4, numImages, true);      // Number of images\n\n  // Directory entries + PNG data\n  for (let i = 0; i < pngEntries.length; i++) {\n    const entry = pngEntries[i]!;\n    const dirOffset = headerSize + i * 16;\n\n    // ICO directory entry (16 bytes)\n    view.setUint8(dirOffset, entry.size >= 256 ? 0 : entry.size);  // Width (0 = 256)\n    view.setUint8(dirOffset + 1, entry.size >= 256 ? 0 : entry.size);  // Height\n    view.setUint8(dirOffset + 2, 0);       // Color palette: 0\n    view.setUint8(dirOffset + 3, 0);       // Reserved: 0\n    view.setUint16(dirOffset + 4, 1, true);  // Color planes: 1\n    view.setUint16(dirOffset + 6, 32, true); // Bits per pixel: 32\n    view.setUint32(dirOffset + 8, entry.data.length, true);  // Image data size\n    view.setUint32(dirOffset + 12, dataOffset, true);         // Offset to image data\n\n    // Write PNG data\n    bytes.set(entry.data, dataOffset);\n    dataOffset += entry.data.length;\n  }\n\n  return new Blob([buffer], { type: meta.mime });\n}\n"]}