UNPKG

ico-utils

Version:

A javascript library to create ICO file from PNG images and extract PNG images from ICO file.

41 lines (40 loc) 1.83 kB
import { isPngSignatureValid, parsePng } from './png-utils.js'; import { getBlob, getArrayBuffer } from './helpers/binaryConverter.js'; import { joinBytesToNumber } from './helpers/bytesConverter.js'; const FILE_HEADER_SIZE = 6; const IMAGE_HEADER_SIZE = 16; export async function decodeIco(icoImage) { const buffer = await getArrayBuffer(icoImage); const uint8 = new Uint8Array(buffer); if (isPngSignatureValid(uint8.slice(0, 8))) { return [getParsedPngAndBlob(uint8)]; } if (!isIcoSignatureValid(uint8.slice(0, 4))) { throw new Error('INVALID_ICO_IMAGE'); } const imagesCount = joinBytesToNumber(Array.from(uint8.slice(4, 6))); const initialImagePosition = FILE_HEADER_SIZE + IMAGE_HEADER_SIZE * imagesCount; const imagesHeader = Array.from(uint8.slice(FILE_HEADER_SIZE, initialImagePosition)); const imagesDetails = getImagesDetails(imagesHeader); const images = imagesDetails.map((imageDetails) => { const imageUint8 = uint8.slice(imageDetails.position, imageDetails.position + imageDetails.size); return getParsedPngAndBlob(imageUint8); }); return images; } function getImagesDetails(imagesHeader) { if (imagesHeader.length < 1) { return []; } const imageHeader = imagesHeader.splice(0, IMAGE_HEADER_SIZE); const position = joinBytesToNumber(imageHeader.slice(12, 16)); const size = joinBytesToNumber(imageHeader.slice(8, 12)); return [{ position, size }, ...getImagesDetails(imagesHeader)]; } function isIcoSignatureValid(imageSignatureBytes) { const icoSignatureBytes = [0x00, 0x00, 0x01, 0x00]; return icoSignatureBytes.toString() === imageSignatureBytes.toString(); } function getParsedPngAndBlob(uint8) { return Object.assign(Object.assign({}, parsePng(uint8)), { blob: getBlob(uint8) }); }