UNPKG

@pdfme/schemas

Version:

TypeScript base PDF generator and React base UI. Open source, developed by the community, and completely free to use under the MIT license!

120 lines 4.37 kB
// ref: https://github.com/image-size/image-size ---------------------------- // The following code is adapted from the image-size code. Unnecessary formats and dependencies on Node have been removed. import { Buffer } from 'buffer'; const decoder = new TextDecoder(); const toUTF8String = (input, start = 0, end = input.length) => decoder.decode(input.slice(start, end)); const toHexString = (input, start = 0, end = input.length) => input.slice(start, end).reduce((memo, i) => memo + ('0' + i.toString(16)).slice(-2), ''); const readUInt16BE = (input, offset = 0) => input[offset] * 2 ** 8 + input[offset + 1]; const readUInt32BE = (input, offset = 0) => input[offset] * 2 ** 24 + input[offset + 1] * 2 ** 16 + input[offset + 2] * 2 ** 8 + input[offset + 3]; const extractSize = (input, index) => { return { height: readUInt16BE(input, index), width: readUInt16BE(input, index + 2), }; }; const validateInput = (input, index) => { // index should be within buffer limits if (index > input.length) { throw new TypeError('Corrupt JPG, exceeded buffer limits'); } // Every JPEG block must begin with a 0xFF if (input[index] !== 0xff) { throw new TypeError('Invalid JPG, marker table corrupted'); } }; const JPG = { validate: (input) => toHexString(input, 0, 2) === 'ffd8', calculate(input) { // Skip 4 chars, they are for signature input = input.slice(4); let next; while (input.length) { // read length of the next block const i = readUInt16BE(input, 0); // ensure correct format validateInput(input, i); // 0xFFC0 is baseline standard(SOF) // 0xFFC1 is baseline optimized(SOF) // 0xFFC2 is progressive(SOF2) next = input[i + 1]; if (next === 0xc0 || next === 0xc1 || next === 0xc2) { const size = extractSize(input, i + 5); return size; } // move to the next block input = input.slice(i + 2); } throw new TypeError('Invalid JPG, no size found'); }, }; const pngSignature = 'PNG\r\n\x1a\n'; const pngImageHeaderChunkName = 'IHDR'; // Used to detect "fried" png's: http://www.jongware.com/pngdefry.html const pngFriedChunkName = 'CgBI'; const PNG = { validate(input) { if (pngSignature === toUTF8String(input, 1, 8)) { let chunkName = toUTF8String(input, 12, 16); if (chunkName === pngFriedChunkName) { chunkName = toUTF8String(input, 28, 32); } if (chunkName !== pngImageHeaderChunkName) { throw new TypeError('Invalid PNG'); } return true; } return false; }, calculate(input) { if (toUTF8String(input, 12, 16) === pngFriedChunkName) { return { height: readUInt32BE(input, 36), width: readUInt32BE(input, 32), }; } return { height: readUInt32BE(input, 20), width: readUInt32BE(input, 16), }; }, }; const typeHandlers = { jpg: JPG, png: PNG, }; function detector(input) { const firstBytes = { 0x89: 'png', 0xff: 'jpg', }; const byte = input[0]; if (byte in firstBytes) { const type = firstBytes[byte]; if (type && typeHandlers[type].validate(input)) { return type; } } const keys = Object.keys(typeHandlers); return keys.find((key) => typeHandlers[key].validate(input)); } export const getImageDimension = (value) => { const dataUriPrefix = ';base64,'; const idx = value.indexOf(dataUriPrefix); const imgBase64 = value.substring(idx + dataUriPrefix.length, value.length); return imageSize(Buffer.from(imgBase64, 'base64')); }; const imageSize = (imgBuffer) => { const type = detector(imgBuffer); if (typeof type !== 'undefined' && type in typeHandlers) { const size = typeHandlers[type].calculate(imgBuffer); if (size !== undefined) { return size; } } throw new TypeError('[@pdfme/schemas/images] Unsupported file type: ' + (type === undefined ? 'undefined' : type)); }; // ---------------------------- //# sourceMappingURL=imagehelper.js.map