char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
e21152dc9
char/aliceai-t5-moe
1import { EXIF } from '$lib/constants' ; 2import { MimeTypeImage } from '$lib/enums' ; 3 4/** 5* Read the EXIF orientation tag from a JPEG base64 data URL 6* 7* Only a bounded prefix of the base64 payload is decoded, the APP1 segment 8* always sits near the start of the file. 9* @param base64UrlJpeg - The JPEG base64 data URL to inspect 10* @returns The orientation value (1 to 8), or 1 when absent or unreadable 11*/ 12export function getJpegOrientationFromDataURL ( base64UrlJpeg :string ) :number { 13try { 14const payloadStart = base64UrlJpeg . indexOf ( ',' ) + 1 ; 15 16if ( payloadStart <= 0 ) { 17return 1 ; 18} 19 20// Keep the slice a multiple of 4 characters so atob accepts it 21const charLimit = Math . ceil ( EXIF . SCAN_BYTE_LIMIT / 3 ) * 4 ; 22const slice = base64UrlJpeg . slice ( payloadStart , payloadStart + charLimit ); 23const binary = atob ( slice . slice ( 0 , slice . length - ( slice . length % 4 ))); 24const bytes = new Uint8Array ( binary . length ); 25 26for ( let i = 0 ; i < binary . length ; i ++ ) { 27bytes [ i ] = binary . charCodeAt ( i ); 28} 29 30return findExifOrientation ( new DataView ( bytes . buffer )); 31} catch { 32return 1 ; 33} 34} 35 36/** 37* Walk the JPEG segments of a header buffer looking for the APP1 EXIF block 38* @param view - DataView over the JPEG header bytes 39* @returns The orientation value (1 to 8), or 1 when absent or malformed 40*/ 41function findExifOrientation ( view :DataView ) :number { 42if ( view . byteLength < 4 || view . getUint16 ( 0 ) !== EXIF . JPEG_SOI_MARKER ) { 43return 1 ; 44} 45 46let offset = 2 ; 47 48while ( offset + 4 <= view . byteLength ) { 49if ( view . getUint8 ( offset ) !== 0xff ) { 50return 1 ; 51} 52 53const marker = view . getUint8 ( offset + 1 ); 54 55// Compressed image data starts here: no EXIF past this point 56if ( marker === EXIF . SOS_MARKER ) { 57return 1 ; 58} 59 60const segmentLength = view . getUint16 ( offset + 2 ); 61 62if ( marker === EXIF . APP1_MARKER ) { 63return parseExifOrientation ( view , offset + 4 , segmentLength ); 64} 65 66offset += 2 + segmentLength ; 67} 68 69return 1 ; 70} 71 72/** 73* Parse the orientation tag from an APP1 EXIF payload 74* @param view - DataView over the JPEG header bytes 75* @param start - Offset of the APP1 payload, right after the segment length 76* @param segmentLength - Declared APP1 segment length 77* @returns The orientation value (1 to 8), or 1 when absent or malformed 78*/ 79function parseExifOrientation ( view :DataView , start :number , segmentLength :number ) :number { 80const end = Math . min ( start + segmentLength , view . byteLength ); 81 82// The payload opens with the "Exif\0\0" signature 83if ( 84start + 6 > end || 85view . getUint32 ( start ) !== EXIF . EXIF_SIGNATURE || 86view . getUint16 ( start + 4 ) !== 0 87) { 88return 1 ; 89} 90 91const tiff = start + 6 ; 92 93if ( tiff + 8 > end ) { 94return 1 ; 95} 96 97const littleEndian = view . getUint16 ( tiff ) === EXIF . TIFF_LITTLE_ENDIAN ; 98 99if ( view . getUint16 ( tiff + 2 , littleEndian ) !== EXIF . TIFF_MAGIC ) { 100return 1 ; 101} 102 103const ifdOffset = view . getUint32 ( tiff + 4 , littleEndian ); 104 105if ( tiff + ifdOffset + 2 > end ) { 106return 1 ; 107} 108 109const entryCount = view . getUint16 ( tiff + ifdOffset , littleEndian ); 110 111// Scan IFD0 entries for the orientation tag 112for ( let i = 0 ; i < entryCount ; i ++ ) { 113const entry = tiff + ifdOffset + 2 + i * EXIF . IFD_ENTRY_SIZE ; 114 115if ( entry + EXIF . IFD_ENTRY_SIZE > end ) { 116return 1 ; 117} 118 119if ( view . getUint16 ( entry , littleEndian ) === EXIF . ORIENTATION_TAG ) { 120const orientation = view . getUint16 ( entry + 8 , littleEndian ); 121 122return orientation >= 1 && orientation <= 8 ?orientation :1 ; 123} 124} 125 126return 1 ; 127} 128 129/** 130* Check if a MIME type represents a JPEG 131* @param mimeType - The MIME type to check 132* @returns True if the MIME type is a JPEG variant 133*/ 134export function isJpegMimeType ( mimeType :string ) :boolean { 135return mimeType === MimeTypeImage . JPEG || mimeType === MimeTypeImage . JPG ; 136}