1616
1717import me .tamkungz .codecmedia .CodecMediaEngine ;
1818import me .tamkungz .codecmedia .CodecMediaException ;
19+ import me .tamkungz .codecmedia .internal .audio .mp3 .Mp3Codec ;
1920import me .tamkungz .codecmedia .internal .audio .mp3 .Mp3Parser ;
2021import me .tamkungz .codecmedia .internal .audio .mp3 .Mp3ProbeInfo ;
22+ import me .tamkungz .codecmedia .internal .audio .ogg .OggCodec ;
2123import me .tamkungz .codecmedia .internal .audio .ogg .OggParser ;
2224import me .tamkungz .codecmedia .internal .audio .ogg .OggProbeInfo ;
25+ import me .tamkungz .codecmedia .internal .audio .wav .WavCodec ;
2326import me .tamkungz .codecmedia .internal .audio .wav .WavParser ;
2427import me .tamkungz .codecmedia .internal .audio .wav .WavProbeInfo ;
2528import me .tamkungz .codecmedia .internal .convert .ConversionHub ;
2629import me .tamkungz .codecmedia .internal .convert .ConversionRequest ;
2730import me .tamkungz .codecmedia .internal .convert .DefaultConversionHub ;
31+ import me .tamkungz .codecmedia .internal .image .bmp .BmpParser ;
32+ import me .tamkungz .codecmedia .internal .image .bmp .BmpProbeInfo ;
33+ import me .tamkungz .codecmedia .internal .image .heif .HeifParser ;
34+ import me .tamkungz .codecmedia .internal .image .heif .HeifProbeInfo ;
2835import me .tamkungz .codecmedia .internal .image .jpeg .JpegParser ;
2936import me .tamkungz .codecmedia .internal .image .jpeg .JpegProbeInfo ;
3037import me .tamkungz .codecmedia .internal .image .png .PngParser ;
3138import me .tamkungz .codecmedia .internal .image .png .PngProbeInfo ;
39+ import me .tamkungz .codecmedia .internal .image .tiff .TiffParser ;
40+ import me .tamkungz .codecmedia .internal .image .tiff .TiffProbeInfo ;
41+ import me .tamkungz .codecmedia .internal .image .webp .WebpParser ;
42+ import me .tamkungz .codecmedia .internal .image .webp .WebpProbeInfo ;
43+ import me .tamkungz .codecmedia .internal .video .mp4 .Mp4Codec ;
3244import me .tamkungz .codecmedia .internal .video .mp4 .Mp4Parser ;
3345import me .tamkungz .codecmedia .internal .video .mp4 .Mp4ProbeInfo ;
3446import me .tamkungz .codecmedia .model .ConversionResult ;
@@ -70,7 +82,7 @@ public ProbeResult probe(Path input) throws CodecMediaException {
7082 if ("mp3" .equals (extension ) || isLikelyMp3 (bytes )) {
7183 if (bytes .length >= 4 ) {
7284 try {
73- Mp3ProbeInfo info = Mp3Parser . parse (bytes );
85+ Mp3ProbeInfo info = Mp3Codec . decode (bytes , input );
7486 return new ProbeResult (
7587 input ,
7688 "audio/mpeg" ,
@@ -91,7 +103,7 @@ public ProbeResult probe(Path input) throws CodecMediaException {
91103 }
92104
93105 if ("ogg" .equals (extension ) || isLikelyOgg (bytes )) {
94- OggProbeInfo info = OggParser . parse (bytes );
106+ OggProbeInfo info = OggCodec . decode (bytes , input );
95107 return new ProbeResult (
96108 input ,
97109 "audio/ogg" ,
@@ -108,7 +120,7 @@ public ProbeResult probe(Path input) throws CodecMediaException {
108120
109121 if ("wav" .equals (extension ) || WavParser .isLikelyWav (bytes )) {
110122 try {
111- WavProbeInfo info = WavParser . parse (bytes );
123+ WavProbeInfo info = WavCodec . decode (bytes , input );
112124 return new ProbeResult (
113125 input ,
114126 "audio/wav" ,
@@ -169,12 +181,118 @@ public ProbeResult probe(Path input) throws CodecMediaException {
169181 return new ProbeResult (input , "image/jpeg" , outputExt , MediaType .IMAGE , null , List .of (), Map .of ("sizeBytes" , String .valueOf (size )));
170182 }
171183
184+ if ("webp" .equals (extension ) || WebpParser .isLikelyWebp (bytes )) {
185+ try {
186+ WebpProbeInfo info = WebpParser .parse (bytes );
187+ java .util .LinkedHashMap <String , String > tags = new java .util .LinkedHashMap <>();
188+ tags .put ("sizeBytes" , String .valueOf (size ));
189+ if (info .bitDepth () != null ) {
190+ tags .put ("bitDepth" , String .valueOf (info .bitDepth ()));
191+ }
192+ return new ProbeResult (
193+ input ,
194+ "image/webp" ,
195+ "webp" ,
196+ MediaType .IMAGE ,
197+ null ,
198+ List .of (new StreamInfo (0 , StreamKind .VIDEO , "webp" , null , null , null , info .width (), info .height (), null )),
199+ tags
200+ );
201+ } catch (CodecMediaException ignored ) {
202+ // Fall back to extension-only probe for malformed/partial files.
203+ }
204+ return new ProbeResult (input , "image/webp" , "webp" , MediaType .IMAGE , null , List .of (), Map .of ("sizeBytes" , String .valueOf (size )));
205+ }
206+
207+ if ("bmp" .equals (extension ) || BmpParser .isLikelyBmp (bytes )) {
208+ try {
209+ BmpProbeInfo info = BmpParser .parse (bytes );
210+ return new ProbeResult (
211+ input ,
212+ "image/bmp" ,
213+ "bmp" ,
214+ MediaType .IMAGE ,
215+ null ,
216+ List .of (new StreamInfo (0 , StreamKind .VIDEO , "bmp" , null , null , null , info .width (), info .height (), null )),
217+ Map .of (
218+ "sizeBytes" , String .valueOf (size ),
219+ "bitsPerPixel" , String .valueOf (info .bitsPerPixel ())
220+ )
221+ );
222+ } catch (CodecMediaException ignored ) {
223+ // Fall back to extension-only probe for malformed/partial files.
224+ }
225+ return new ProbeResult (input , "image/bmp" , "bmp" , MediaType .IMAGE , null , List .of (), Map .of ("sizeBytes" , String .valueOf (size )));
226+ }
227+
228+ if ("tif" .equals (extension ) || "tiff" .equals (extension ) || TiffParser .isLikelyTiff (bytes )) {
229+ String outputExt = "tiff" .equals (extension ) ? "tiff" : "tif" ;
230+ try {
231+ TiffProbeInfo info = TiffParser .parse (bytes );
232+ java .util .LinkedHashMap <String , String > tags = new java .util .LinkedHashMap <>();
233+ tags .put ("sizeBytes" , String .valueOf (size ));
234+ if (info .bitDepth () != null ) {
235+ tags .put ("bitDepth" , String .valueOf (info .bitDepth ()));
236+ }
237+ return new ProbeResult (
238+ input ,
239+ "image/tiff" ,
240+ outputExt ,
241+ MediaType .IMAGE ,
242+ null ,
243+ List .of (new StreamInfo (0 , StreamKind .VIDEO , "tiff" , null , null , null , info .width (), info .height (), null )),
244+ tags
245+ );
246+ } catch (CodecMediaException ignored ) {
247+ // Fall back to extension-only probe for malformed/partial files.
248+ }
249+ return new ProbeResult (input , "image/tiff" , outputExt , MediaType .IMAGE , null , List .of (), Map .of ("sizeBytes" , String .valueOf (size )));
250+ }
251+
252+ if ("heic" .equals (extension ) || "heif" .equals (extension ) || "avif" .equals (extension ) || HeifParser .isLikelyHeif (bytes )) {
253+ String outputExt = "heif" .equals (extension ) ? "heif" : "heic" ;
254+ if ("avif" .equals (extension )) {
255+ outputExt = "avif" ;
256+ }
257+ String mimeType = "image/" + outputExt ;
258+ try {
259+ HeifProbeInfo info = HeifParser .parse (bytes );
260+ String majorBrand = info .majorBrand ();
261+ if ("avif" .equals (majorBrand ) || "avis" .equals (majorBrand )) {
262+ outputExt = "avif" ;
263+ mimeType = "image/avif" ;
264+ }
265+ java .util .List <StreamInfo > streams = List .of ();
266+ if (info .width () != null && info .height () != null ) {
267+ streams = List .of (new StreamInfo (0 , StreamKind .VIDEO , outputExt , null , null , null , info .width (), info .height (), null ));
268+ }
269+ java .util .LinkedHashMap <String , String > tags = new java .util .LinkedHashMap <>();
270+ tags .put ("sizeBytes" , String .valueOf (size ));
271+ tags .put ("majorBrand" , majorBrand );
272+ if (info .bitDepth () != null ) {
273+ tags .put ("bitDepth" , String .valueOf (info .bitDepth ()));
274+ }
275+ return new ProbeResult (
276+ input ,
277+ mimeType ,
278+ outputExt ,
279+ MediaType .IMAGE ,
280+ null ,
281+ streams ,
282+ tags
283+ );
284+ } catch (CodecMediaException ignored ) {
285+ // Fall back to extension-only probe for malformed/partial files.
286+ }
287+ return new ProbeResult (input , mimeType , outputExt , MediaType .IMAGE , null , List .of (), Map .of ("sizeBytes" , String .valueOf (size )));
288+ }
289+
172290 if ("mp4" .equals (extension ) || "m4a" .equals (extension ) || Mp4Parser .isLikelyMp4 (bytes )) {
173291 String outputExt = "m4a" .equals (extension ) ? "m4a" : "mp4" ;
174292 String mimeType = "m4a" .equals (outputExt ) ? "audio/mp4" : "video/mp4" ;
175293 MediaType mediaType = "m4a" .equals (outputExt ) ? MediaType .AUDIO : MediaType .VIDEO ;
176294 try {
177- Mp4ProbeInfo info = Mp4Parser . parse (bytes );
295+ Mp4ProbeInfo info = Mp4Codec . decode (bytes , input );
178296 java .util .LinkedHashMap <String , String > tags = new java .util .LinkedHashMap <>();
179297 tags .put ("sizeBytes" , String .valueOf (size ));
180298 if (info .majorBrand () != null && !info .majorBrand ().isBlank ()) {
@@ -211,12 +329,18 @@ public ProbeResult probe(Path input) throws CodecMediaException {
211329 case "wav" -> "audio/wav" ;
212330 case "png" -> "image/png" ;
213331 case "jpg" , "jpeg" -> "image/jpeg" ;
332+ case "webp" -> "image/webp" ;
333+ case "bmp" -> "image/bmp" ;
334+ case "tif" , "tiff" -> "image/tiff" ;
335+ case "heic" -> "image/heic" ;
336+ case "heif" -> "image/heif" ;
337+ case "avif" -> "image/avif" ;
214338 default -> "application/octet-stream" ;
215339 };
216340 MediaType mediaType = switch (extension ) {
217341 case "mp4" -> MediaType .VIDEO ;
218342 case "m4a" , "mp3" , "ogg" , "wav" -> MediaType .AUDIO ;
219- case "png" , "jpg" , "jpeg" -> MediaType .IMAGE ;
343+ case "png" , "jpg" , "jpeg" , "webp" , "bmp" , "tif" , "tiff" , "heic" , "heif" , "avif" -> MediaType .IMAGE ;
220344 default -> MediaType .UNKNOWN ;
221345 };
222346
@@ -441,6 +565,30 @@ public ValidationResult validate(Path input, ValidationOptions options) {
441565 } catch (CodecMediaException e ) {
442566 return new ValidationResult (false , List .of (), List .of ("Strict validation failed for " + extension + ": " + e .getMessage ()));
443567 }
568+ } else if ("webp" .equals (extension )) {
569+ try {
570+ WebpParser .parse (bytes );
571+ } catch (CodecMediaException e ) {
572+ return new ValidationResult (false , List .of (), List .of ("Strict validation failed for webp: " + e .getMessage ()));
573+ }
574+ } else if ("bmp" .equals (extension )) {
575+ try {
576+ BmpParser .parse (bytes );
577+ } catch (CodecMediaException e ) {
578+ return new ValidationResult (false , List .of (), List .of ("Strict validation failed for bmp: " + e .getMessage ()));
579+ }
580+ } else if ("tif" .equals (extension ) || "tiff" .equals (extension )) {
581+ try {
582+ TiffParser .parse (bytes );
583+ } catch (CodecMediaException e ) {
584+ return new ValidationResult (false , List .of (), List .of ("Strict validation failed for tif/tiff: " + e .getMessage ()));
585+ }
586+ } else if ("heic" .equals (extension ) || "heif" .equals (extension ) || "avif" .equals (extension )) {
587+ try {
588+ HeifParser .parse (bytes );
589+ } catch (CodecMediaException e ) {
590+ return new ValidationResult (false , List .of (), List .of ("Strict validation failed for heic/heif/avif: " + e .getMessage ()));
591+ }
444592 }
445593 }
446594
@@ -504,7 +652,7 @@ private static MediaType mediaTypeByExtension(String extension) {
504652 return switch (normalizeExtension (extension )) {
505653 case "mp3" , "ogg" , "wav" , "pcm" , "m4a" , "aac" , "flac" -> MediaType .AUDIO ;
506654 case "mp4" , "mkv" , "mov" , "avi" , "webm" -> MediaType .VIDEO ;
507- case "png" , "jpg" , "jpeg" , "gif" , "bmp" , "webp" -> MediaType .IMAGE ;
655+ case "png" , "jpg" , "jpeg" , "gif" , "bmp" , "webp" , "tif" , "tiff" , "heic" , "heif" , "avif" -> MediaType .IMAGE ;
508656 default -> MediaType .UNKNOWN ;
509657 };
510658 }
0 commit comments