@@ -172,102 +172,76 @@ namespace QuickView {
172172static std::wstring DetectFormatFromContent (const uint8_t * magic, size_t size) {
173173 if (size < 4 ) return L" Unknown" ;
174174
175- // Check JPEG: FF D8 FF
176- if (size >= 3 && magic[0 ] == 0xFF && magic[1 ] == 0xD8 && magic[2 ] == 0xFF ) return L" JPEG" ;
177-
178- // Check PNG: 89 50 4E 47
179- if (size >= 4 && magic[0 ] == 0x89 && magic[1 ] == 0x50 && magic[2 ] == 0x4E && magic[3 ] == 0x47 ) return L" PNG" ;
180-
181- // Check WebP: RIFF ... WEBP
182- if (size >= 12 && magic[0 ] == ' R' && magic[1 ] == ' I' && magic[2 ] == ' F' && magic[3 ] == ' F' &&
183- magic[8 ] == ' W' && magic[9 ] == ' E' && magic[10 ] == ' B' && magic[11 ] == ' P' ) return L" WebP" ;
184-
185- // Check AVIF: ftypavif OR ftypavis (AVIF Sequence)
186- if (size >= 12 && magic[4 ] == ' f' && magic[5 ] == ' t' && magic[6 ] == ' y' && magic[7 ] == ' p' ) {
187- bool isAvif = (magic[8 ] == ' a' && magic[9 ] == ' v' && magic[10 ] == ' i' && magic[11 ] == ' f' );
188- bool isAvis = (magic[8 ] == ' a' && magic[9 ] == ' v' && magic[10 ] == ' i' && magic[11 ] == ' s' );
189- if (isAvif || isAvis) return L" AVIF" ;
190- }
175+ struct MagicSignature {
176+ const wchar_t * name;
177+ size_t offset;
178+ std::initializer_list<uint8_t > signature;
179+ };
191180
192- // Check HEIC/HEIF/CR3: ftyp + brand
193- if (size >= 12 && magic[4 ] == ' f' && magic[5 ] == ' t' && magic[6 ] == ' y' && magic[7 ] == ' p' ) {
194- // Canon CR3 (Raw)
195- if (magic[8 ] == ' c' && magic[9 ] == ' r' && magic[10 ] == ' x' ) return L" RAW" ; // crx
181+ static const MagicSignature signatures[] = {
182+ { L" JPEG" , 0 , {0xFF , 0xD8 , 0xFF } },
183+ { L" PNG" , 0 , {0x89 , 0x50 , 0x4E , 0x47 } },
184+ { L" WebP" , 8 , {' W' , ' E' , ' B' , ' P' } },
185+ { L" JXL" , 0 , {0xFF , 0x0A } },
186+ { L" JXL" , 4 , {' J' , ' X' , ' L' , ' ' } }, // For "00 00 00 0C JXL "
187+ { L" DDS" , 0 , {' D' , ' D' , ' S' , ' ' } },
188+ { L" BMP" , 0 , {' B' , ' M' } },
189+ { L" PSD" , 0 , {' 8' , ' B' , ' P' , ' S' } },
190+ { L" HDR" , 0 , {' #' , ' ?' } },
191+ { L" EXR" , 0 , {0x76 , 0x2F , 0x31 , 0x01 } },
192+ { L" PIC" , 0 , {0x53 , 0x80 , 0xF6 , 0x34 } },
193+ { L" QOI" , 0 , {' q' , ' o' , ' i' , ' f' } },
194+ { L" PCX" , 0 , {0x0A } },
195+ { L" ICO" , 0 , {0x00 , 0x00 , 0x01 , 0x00 } },
196+ { L" TIFF" , 0 , {0x49 , 0x49 , 0x2A , 0x00 } },
197+ { L" TIFF" , 0 , {0x4D , 0x4D , 0x00 , 0x2A } }
198+ };
196199
197- // Check brand at offset 8
198- if ((magic[8 ] == ' h' && magic[9 ] == ' e' && magic[10 ] == ' i' && (magic[11 ] == ' c' || magic[11 ] == ' x' || magic[11 ] == ' s' || magic[11 ] == ' m' )) || // heic, heix, heis, heim
199- (magic[8 ] == ' h' && magic[9 ] == ' e' && magic[10 ] == ' v' && (magic[11 ] == ' c' || magic[11 ] == ' m' || magic[11 ] == ' s' )) || // hevc, hevm, hevs
200- (magic[8 ] == ' m' && magic[9 ] == ' i' && magic[10 ] == ' f' && magic[11 ] == ' 1' ) || // mif1
201- (magic[8 ] == ' m' && magic[9 ] == ' s' && magic[10 ] == ' f' && magic[11 ] == ' 1' )) // msf1
202- {
203- return L" HEIC" ; // Unified as HEIC/HEIF
200+ for (const auto & sig : signatures) {
201+ if (size >= sig.offset + sig.signature .size ()) {
202+ bool match = true ;
203+ size_t i = 0 ;
204+ for (uint8_t byte : sig.signature ) {
205+ if (magic[sig.offset + i] != byte) {
206+ match = false ;
207+ break ;
208+ }
209+ i++;
210+ }
211+ // Additional context rules for WebP / JXL box
212+ if (match) {
213+ if (wcscmp (sig.name , L" WebP" ) == 0 && !(magic[0 ] == ' R' && magic[1 ] == ' I' && magic[2 ] == ' F' && magic[3 ] == ' F' )) match = false ;
214+ if (sig.offset == 4 && wcscmp (sig.name , L" JXL" ) == 0 && !(magic[0 ] == 0x00 && magic[1 ] == 0x00 && magic[2 ] == 0x00 && magic[3 ] == 0x0C )) match = false ;
215+ }
216+ if (match) return sig.name ;
204217 }
205218 }
206-
207- // Check JXL: FF 0A or 00 00 00 0C JXL
208- if (size >= 2 && magic[0 ] == 0xFF && magic[1 ] == 0x0A ) return L" JXL" ;
209- if (size >= 8 && magic[0 ] == 0x00 && magic[1 ] == 0x00 && magic[2 ] == 0x00 && magic[3 ] == 0x0C &&
210- magic[4 ] == ' J' && magic[5 ] == ' X' && magic[6 ] == ' L' && magic[7 ] == ' ' ) return L" JXL" ;
211-
212- // Check DDS: DDS\x20 (Magic Number: 0x20534444)
213- if (size >= 4 && magic[0 ] == ' D' && magic[1 ] == ' D' && magic[2 ] == ' S' && magic[3 ] == ' ' ) return L" DDS" ;
214219
215- // Check GIF: GIF87a or GIF89a
216- if (size >= 6 && magic[0 ] == ' G' && magic[1 ] == ' I' && magic[2 ] == ' F' && magic[3 ] == ' 8' &&
217- (magic[4 ] == ' 7' || magic[4 ] == ' 9' ) && magic[5 ] == ' a' ) return L" GIF" ;
218-
219- // Check BMP: BM
220- if (size >= 2 && magic[0 ] == ' B' && magic[1 ] == ' M' ) return L" BMP" ;
221-
222- // Check PSD: 8BPS
223- if (size >= 4 && magic[0 ] == ' 8' && magic[1 ] == ' B' && magic[2 ] == ' P' && magic[3 ] == ' S' ) return L" PSD" ;
224-
225- // Check HDR: #?RADIANCE or #?RGBE
226- if (size >= 2 && magic[0 ] == ' #' && magic[1 ] == ' ?' ) return L" HDR" ;
220+ // Complex / Heuristic checks
221+ if (size >= 12 && magic[4 ] == ' f' && magic[5 ] == ' t' && magic[6 ] == ' y' && magic[7 ] == ' p' ) {
222+ if (magic[8 ] == ' a' && magic[9 ] == ' v' && magic[10 ] == ' i' && (magic[11 ] == ' f' || magic[11 ] == ' s' )) return L" AVIF" ;
223+ if (magic[8 ] == ' c' && magic[9 ] == ' r' && magic[10 ] == ' x' ) return L" RAW" ;
224+ if ((magic[8 ] == ' h' && magic[9 ] == ' e' && magic[10 ] == ' i' && (magic[11 ] == ' c' || magic[11 ] == ' x' || magic[11 ] == ' s' || magic[11 ] == ' m' )) ||
225+ (magic[8 ] == ' h' && magic[9 ] == ' e' && magic[10 ] == ' v' && (magic[11 ] == ' c' || magic[11 ] == ' m' || magic[11 ] == ' s' )) ||
226+ (magic[8 ] == ' m' && magic[9 ] == ' i' && magic[10 ] == ' f' && magic[11 ] == ' 1' ) ||
227+ (magic[8 ] == ' m' && magic[9 ] == ' s' && magic[10 ] == ' f' && magic[11 ] == ' 1' )) return L" HEIC" ;
228+ }
227229
228- // Check EXR: v/1\x01 (0x76 0x2f 0x31 0x01)
229- if (size >= 4 && magic[0 ] == 0x76 && magic[1 ] == 0x2F && magic[2 ] == 0x31 && magic[3 ] == 0x01 ) return L" EXR" ;
230-
231- // Check PIC: 0x53 0x80 ...
232- if (size >= 4 && magic[0 ] == 0x53 && magic[1 ] == 0x80 && magic[2 ] == 0xF6 && magic[3 ] == 0x34 ) return L" PIC" ;
233-
234- // Check PNM: P1-P7
230+ if (size >= 6 && magic[0 ] == ' G' && magic[1 ] == ' I' && magic[2 ] == ' F' && magic[3 ] == ' 8' && (magic[4 ] == ' 7' || magic[4 ] == ' 9' ) && magic[5 ] == ' a' ) return L" GIF" ;
235231 if (size >= 2 && magic[0 ] == ' P' && magic[1 ] >= ' 1' && magic[1 ] <= ' 7' ) return L" PNM" ;
236-
237- // Check QOI: qoif
238- if (size >= 4 && magic[0 ] == ' q' && magic[1 ] == ' o' && magic[2 ] == ' i' && magic[3 ] == ' f' ) return L" QOI" ;
239-
240- // Check PCX: 0x0A ...
241- if (size >= 1 && magic[0 ] == 0x0A ) return L" PCX" ;
242-
243- // Check ICO: 00 00 01 00
244- if (size >= 4 && magic[0 ] == 0x00 && magic[1 ] == 0x00 && magic[2 ] == 0x01 && magic[3 ] == 0x00 ) return L" ICO" ;
245232
246- // Check TIFF: II (49 49 2A 00) or MM (4D 4D 00 2A)
247- if (size >= 4 && magic[0 ] == 0x49 && magic[1 ] == 0x49 && magic[2 ] == 0x2A && magic[3 ] == 0x00 ) return L" TIFF" ;
248- if (size >= 4 && magic[0 ] == 0x4D && magic[1 ] == 0x4D && magic[2 ] == 0x00 && magic[3 ] == 0x2A ) return L" TIFF" ;
249-
250- // [v6.9.7] PRIORITIZE TGA Check over WBMP (since TGA often starts with 00 00)
251- // Check TGA (Heuristic): ColorMapType(0/1) + ImageType(1/2/3/9/10/11) + PixelDepth(8/15/16/24/32) at offset 16
252233 if (size >= 18 ) {
253234 bool validColorMap = (magic[1 ] == 0 || magic[1 ] == 1 );
254235 bool validType = (magic[2 ] == 1 || magic[2 ] == 2 || magic[2 ] == 3 || magic[2 ] == 9 || magic[2 ] == 10 || magic[2 ] == 11 );
255236 bool validBpp = (magic[16 ] == 8 || magic[16 ] == 15 || magic[16 ] == 16 || magic[16 ] == 24 || magic[16 ] == 32 );
256237 if (validColorMap && validType && validBpp) return L" TGA" ;
257238 }
258239
259- // [v6.9.6] Check WBMP: Type 0, Fixed Header 0
260- // [Fix] Must exclude ISOBMFF (ftyp) to avoid hijacking CR3/MP4 which start with size 00 00 ...
261240 if (size >= 2 && magic[0 ] == 0x00 && magic[1 ] == 0x00 ) {
262- // If it looks like ftyp, it's NOT WBMP
263- if (size >= 8 && magic[4 ] == ' f' && magic[5 ] == ' t' && magic[6 ] == ' y' && magic[7 ] == ' p' ) {
264- // Check known brands like crx? Already handled above.
265- // If we are here, it's an UNKNOWN ftyp. Return Unknown, not WBMP.
266- return L" Unknown" ;
267- }
241+ if (size >= 8 && magic[4 ] == ' f' && magic[5 ] == ' t' && magic[6 ] == ' y' && magic[7 ] == ' p' ) return L" Unknown" ;
268242 return L" WBMP" ;
269243 }
270-
244+
271245 return L" Unknown" ;
272246}
273247
0 commit comments