From: Svjatoslav Agejenko Date: Sat, 1 Aug 2026 22:18:40 +0000 (+0300) Subject: Properly handle big PNG files X-Git-Url: http://www2.svjatoslav.eu/gitweb/?a=commitdiff_plain;ds=inline;p=meviz.git Properly handle big PNG files --- diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/Constants.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/Constants.java index ea32774..6725f64 100755 --- a/src/main/java/eu/svjatoslav/meviz/htmlindexer/Constants.java +++ b/src/main/java/eu/svjatoslav/meviz/htmlindexer/Constants.java @@ -10,7 +10,7 @@ public class Constants { public static final String DEFAULT_GALLERY_TITLE = "Gallery"; - public static final String METADATA_FILE_NAME = "metadata_7.dat"; + public static final String METADATA_FILE_NAME = "metadata_8.dat"; public static final String THUMBNAILS_DIRECTORY_NAME = ".thumbnails"; @@ -36,6 +36,6 @@ public class Constants { public static final String[] SUPPORTED_VIDEO_EXTENSIONS = { "avi", "mp4", "mpeg", "mpg", "mkv", "flv", "ogv"}; - public static final String THUMBNAIL_VERSION = "3"; + public static final String THUMBNAIL_VERSION = "4"; } diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/Utils.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/Utils.java index 78ad63a..98c96f4 100755 --- a/src/main/java/eu/svjatoslav/meviz/htmlindexer/Utils.java +++ b/src/main/java/eu/svjatoslav/meviz/htmlindexer/Utils.java @@ -34,6 +34,15 @@ import static org.openimaj.image.ImageUtilities.createBufferedImage; import static org.openimaj.image.ImageUtilities.readMBF; public class Utils { + /** + * Read-ahead limit (in bytes) hard-coded inside OpenIMAJ's + * {@code ExtendedImageIO.read()} stream mark. Apache Sanselan scans the + * whole file while sniffing the image format, so for files larger than + * this limit the stream mark gets invalidated and every subsequent + * {@code reset()} throws {@code IOException: Resetting to invalid mark}. + */ + private static final long OPENIMAJ_STREAM_MARK_LIMIT = 104857600L; + private static File lastLoadedFile; private static BufferedImage lastLoadedBufferedImage; @@ -53,7 +62,7 @@ public class Utils { if ("jxl".equals(extension)) { lastLoadedBufferedImage = loadJxlImage(file); } else { - lastLoadedBufferedImage = createBufferedImage(readMBF(file)); + lastLoadedBufferedImage = loadWithOpenImaj(file); } lastLoadedFile = file; @@ -67,6 +76,39 @@ public class Utils { return lastLoadedBufferedImage; } + /** + * Decode an image with OpenIMAJ (which handles CMYK JPEGs and other + * exotic variants that plain JDK ImageIO chokes on). + * + * Files larger than {@link #OPENIMAJ_STREAM_MARK_LIMIT} are decoded + * directly with JDK {@link ImageIO#read(File)}, because OpenIMAJ cannot + * handle them: its {@code ExtendedImageIO.read()} marks the input stream + * with a 100 MB read-ahead limit, Apache Sanselan then scans the entire + * file while sniffing the format, the mark gets invalidated and every + * subsequent {@code reset()} fails with + * {@code IOException: Resetting to invalid mark}. + * {@code ImageIO.read(File)} uses a random-access + * {@code FileImageInputStream} instead of mark/reset on the raw stream, + * so it decodes such files without trouble. + * + * For smaller files OpenIMAJ stays the primary decoder, with the same + * JDK ImageIO fallback in case it still fails. + */ + private static BufferedImage loadWithOpenImaj(final File file) + throws IOException { + if (file.length() > OPENIMAJ_STREAM_MARK_LIMIT) + return ImageIO.read(file); + + try { + return createBufferedImage(readMBF(file)); + } catch (final IOException e) { + System.out.println("OpenIMAJ failed to decode \"" + + file.getName() + "\" (" + e.getMessage() + + "), retrying with JDK ImageIO."); + return ImageIO.read(file); + } + } + /** * Load a JPEG XL (.jxl) image by converting it to PNG using the djxl decoder * from libjxl-tools, since Java's ImageIO and OpenIMAJ do not natively