// binary-helpers.ts // Helper functions for handling binary data from Base64-encoded JSON /** * Convert Base64 string to Uint8Array * @param {string} base64 - Base64 encoded string * @returns {Uint8Array} - Decoded binary data */ export function base64ToUint8Array(base64: string): Uint8Array { const binaryString = atob(base64); const bytes = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes; } /** * Convert Uint8Array to Base64 string * @param {Uint8Array} uint8Array - Binary data * @returns {string} - Base64 encoded string */ export function uint8ArrayToBase64(uint8Array: Uint8Array): string { let binary = ''; const len = uint8Array.byteLength; for (let i = 0; i < len; i++) { binary += String.fromCharCode(uint8Array[i]); } return btoa(binary); } /** * Convert Blob to Base64 string (alternative implementation using arrayBuffer) * @param {Blob} blob - Blob object to convert * @returns {Promise} - Promise that resolves to Base64 encoded string */ export async function blobToBase64(blob: Blob): Promise { const arrayBuffer = await blob.arrayBuffer(); const uint8Array = new Uint8Array(arrayBuffer); return uint8ArrayToBase64(uint8Array); } /** * Create a blob URL from a Uint8Array for displaying images * @param {Uint8Array} uint8Array - Binary image data * @param {string} mimeType - MIME type of the image * @returns {string} - Blob URL that can be used in img.src */ export function createImageBlobUrl(uint8Array: Uint8Array, mimeType: string = 'image/jpeg'): string { const blob = new Blob([uint8Array as any], { type: mimeType }); return URL.createObjectURL(blob); } /** * Create a data URL directly from a Base64 string * @param {string} base64 - Base64 encoded image data * @param {string} mimeType - MIME type of the image * @returns {string} - Data URL that can be used in img.src */ export function createImageDataUrlFromBase64(base64: string, mimeType: string = 'image/jpeg'): string { return `data:${mimeType};base64,${base64}`; } /** * Process the UploadReadyData object by converting Base64 strings to Uint8Arrays * @param {any} uploadData - The parsed JSON upload data * @returns {any} - Processed upload data with typed arrays */ export function processUploadReadyData(uploadData: any): any { if (!uploadData) return uploadData; const result = { ...uploadData }; // Convert SignedVideoPackage if (typeof result.SignedVideoPackage === 'string') { result.SignedVideoPackage = base64ToUint8Array(result.SignedVideoPackage); } // Convert ImagePreview if (typeof result.ImagePreview === 'string') { result.ImagePreview = base64ToUint8Array(result.ImagePreview); } // Convert AuxiliaryImages array of base64 strings if (Array.isArray(result.AuxiliaryImages)) { result.AuxiliaryImages = result.AuxiliaryImages.map((base64: string | unknown) => typeof base64 === 'string' ? base64ToUint8Array(base64) : base64 ); } return result; } /** * Get mime type based on the first few bytes of a binary file * This is a simple implementation that handles common image formats * @param {Uint8Array} data - The binary data * @returns {string} - The detected MIME type or default 'application/octet-stream' */ export function detectMimeType(data: Uint8Array): string { if (!data || data.length < 4) { return 'application/octet-stream'; } // Check for JPEG signature: starts with FF D8 FF if (data[0] === 0xFF && data[1] === 0xD8 && data[2] === 0xFF) { return 'image/jpeg'; } // Check for PNG signature: starts with 89 50 4E 47 if (data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4E && data[3] === 0x47) { return 'image/png'; } // Check for GIF signature: 'GIF87a' or 'GIF89a' if (data[0] === 0x47 && data[1] === 0x49 && data[2] === 0x46 && data[3] === 0x38 && (data[4] === 0x37 || data[4] === 0x39) && data[5] === 0x61) { return 'image/gif'; } // Check for BMP signature: starts with 'BM' if (data[0] === 0x42 && data[1] === 0x4D) { return 'image/bmp'; } // Check for WebP signature if (data[0] === 0x52 && data[1] === 0x49 && data[2] === 0x46 && data[3] === 0x46 && data[8] === 0x57 && data[9] === 0x45 && data[10] === 0x42 && data[11] === 0x50) { return 'image/webp'; } // Default to generic binary return 'application/octet-stream'; } /** * Creates an optimal image blob URL based on the image data * Detects the MIME type from the data * @param {Uint8Array} imageData - The binary image data * @returns {string} - A blob URL for the image */ export function createOptimalImageUrl(imageData: Uint8Array): string { const mimeType = detectMimeType(imageData); return createImageBlobUrl(imageData, mimeType); } /** * Creates an optimal image blob URL directly from Base64 data * @param {string} base64 - Base64 encoded image data * @returns {string} - A blob URL for the image */ export function createOptimalImageUrlFromBase64(base64: string): string { const imageData = base64ToUint8Array(base64); return createOptimalImageUrl(imageData); }