Skip to content

[Fixes #48][2.4.x] Reinstate png, jpg support. Removes imagen-legacy dependency.#81

Merged
aaime merged 2 commits into
mapfish:2.4.xfrom
etj:48_legacy_24x
Jun 17, 2026
Merged

[Fixes #48][2.4.x] Reinstate png, jpg support. Removes imagen-legacy dependency.#81
aaime merged 2 commits into
mapfish:2.4.xfrom
etj:48_legacy_24x

Conversation

@etj

@etj etj commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Key changes:

  • Removed the imagen-legacy-codec-core dependency to resolve downstream project conflicts.
  • Replaced legacy FileSeekableStream with standard javax.imageio.ImageIO, utilizing ImageIO.setUseCache(true) to maintain disk-backed memory efficiency without needing JAI's TileCache.
  • Refactored the core image stitching logic (e.g., in FileCachingJaiMosaicOutputFactory) to use standard java.awt.Graphics2D and BufferedImage instead of JAI's RenderedOp and ParameterBlock.

Copilot AI review requested due to automatic review settings June 12, 2026 14:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR replaces the existing JAI/Imagen-based TIFF mosaic assembly with a Java2D/ImageIO implementation and removes a legacy Imagen codec dependency, aiming to reduce reliance on the legacy codec stack and simplify image composition.

Changes:

  • Reworked mosaic generation to use BufferedImage + Graphics2D drawing rather than ImageN mosaic/translate operations.
  • Enabled ImageIO disk cache usage during mosaic generation.
  • Removed imagen-legacy-codec-core from Maven dependencies.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
src/main/java/org/mapfish/print/output/FileCachingJaiMosaicOutputFactory.java Replaces Imagen mosaic pipeline with Java2D/ImageIO-based mosaic creation and disk caching.
pom.xml Drops legacy Imagen codec dependency corresponding to the removed codec usage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +103 to +105
if (images == null || images.isEmpty()) {
return;
}
Comment on lines +108 to +116
int totalHeight = 0;
int maxWidth = 0;

for (ImageInfo imageinfo : images) {
totalHeight += imageinfo.height + MARGIN;
if (maxWidth < imageinfo.width) {
maxWidth = (int) imageinfo.width;
}
}
Comment on lines +151 to +152
g2d.drawImage(pageImage, 0, currentY, null);
currentY += imageinfo.height + MARGIN;
Comment on lines +132 to +134
// Explicitly enable ImageIO disk caching. This honors the original intent
// of the "FileCaching" class by preventing stream data from flooding the RAM.
ImageIO.setUseCache(true);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the javadoc, this does not seem necessary, true is the default (also, it shoud be done once at startup, not for every image write):

Sets a flag indicating whether a disk-based cache file should be used when creating ImageInputStreams and ImageOutputStreams.
When reading from a standard InputStream, it may be necessary to save previously read information in a cache since the underlying stream does not allow data to be re-read. Similarly, when writing to a standard OutputStream, a cache may be used to allow a previously written value to be changed before flushing it to the final destination.
The cache may reside in main memory or on disk. Setting this flag to false disallows the use of disk for future streams, which may be advantageous when working with small images, as the overhead of creating and destroying files is removed.
On startup, the value is set to true.


if (pageImage == null) {
g2d.dispose();
throw new IllegalArgumentException("Cannot read image: " + imageinfo.imageFile.getAbsolutePath() + " - missing ImageIO plugin for this format.");

pbMosaic.addSource(translated);
i++;
LOGGER.debug("Adding page image " + i + " bounds: [0," + currentY + " " + pageImage.getWidth() + "," + (currentY + pageImage.getHeight()) + "]");

@aaime aaime left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this fixes the issue at hand, it looks like it also significantly regresses on memory usage, I would not trust this to be stable under load. Suggestions below:

Comment on lines +132 to +134
// Explicitly enable ImageIO disk caching. This honors the original intent
// of the "FileCaching" class by preventing stream data from flooding the RAM.
ImageIO.setUseCache(true);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the javadoc, this does not seem necessary, true is the default (also, it shoud be done once at startup, not for every image write):

Sets a flag indicating whether a disk-based cache file should be used when creating ImageInputStreams and ImageOutputStreams.
When reading from a standard InputStream, it may be necessary to save previously read information in a cache since the underlying stream does not allow data to be re-read. Similarly, when writing to a standard OutputStream, a cache may be used to allow a previously written value to be changed before flushing it to the final destination.
The cache may reside in main memory or on disk. Setting this flag to false disallows the use of disk for future streams, which may be advantageous when working with small images, as the overhead of creating and destroying files is removed.
On startup, the value is set to true.

i++;
LOGGER.debug("Adding page image " + i + " bounds: [" + 0 + "," + height + " " + source.getWidth() + "," + (height + source.getHeight()) + "]");
RenderedOp translated = translateImage(height, source);
BufferedImage pageImage = ImageIO.read(imageinfo.imageFile);

@aaime aaime Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a serious regression, it materializes in memory all the input images instead of allowing a tiled approach.
The class was designed to use JAI/ImageN exactly to avoid materializing everything in memory.
I suggest to keep the ImageIO writing bits while retaining the ImageN code (and fix it as necessary).
For reading use ImageN ImageRead operation (mimicks what GT/GS do), it can perform deferred and tiled loading and uses ImageIO t actually read the tiles.
You'll need to add the dependency in the POM.

Comment thread pom.xml
<groupId>org.eclipse.imagen</groupId>
<artifactId>imagen-core</artifactId>
</dependency>
<dependency>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, not really needed, ImageIO direct writing is fine.

@etj etj requested a review from Copilot June 15, 2026 11:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment on lines +136 to +138
TileCache cache = ImageN.createTileCache((long) (height * width * 400));
RenderingHints hints = new RenderingHints(ImageN.KEY_TILE_CACHE, cache);
RenderedOp mosaic = ImageN.create("mosaic", pbMosaic, hints);
}

RenderedOp mosaic = ImageN.create("mosaic", pbMosaic);
TileCache cache = ImageN.createTileCache((long) (height * width * 400));
Comment on lines +123 to +125
if(LOGGER.isDebugEnabled()) {
LOGGER.debug("Adding page image " + i + " bounds: [" + 0 + "," + height + " " + source.getWidth() + "," + (height + source.getHeight()) + "]");
}
@etj etj force-pushed the 48_legacy_24x branch from 6d270d6 to 24977f1 Compare June 15, 2026 11:23
@etj etj force-pushed the 48_legacy_24x branch from 24977f1 to da8ac77 Compare June 15, 2026 12:58
@etj etj requested a review from aaime June 15, 2026 13:20
pb.add(null);
pb.add(null);
RenderedOp source = ImageN.create("TIFF", pb);
ParameterBlockImageN pb = new ParameterBlockImageN("ImageRead");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused here... this is the right code, but I don't see a new dependency on the ImageN imageread module. Maybe it is included transitively?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aaime
The dependency:tree says

  • org.geotools:gt-render:jar:34.0:compile
    • org.geotools:gt-coverage:jar:34.0:compile
      • org.eclipse.imagen:imageread:jar:0.9.0:compile
Full dependency tree
[INFO] Scanning for projects...
[INFO] 
[INFO] --------------------< org.mapfish.print:print-lib >---------------------
[INFO] Building print-lib 2.4-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- dependency:3.7.0:tree (default-cli) @ print-lib ---
[INFO] org.mapfish.print:print-lib:jar:2.4-SNAPSHOT
[INFO] +- org.geotools:gt-epsg-hsql:jar:34.0:compile
[INFO] |  +- org.geotools:gt-referencing:jar:34.0:compile
[INFO] |  |  +- org.ejml:ejml-ddense:jar:0.41:compile
[INFO] |  |  |  \- org.ejml:ejml-core:jar:0.41:compile
[INFO] |  |  +- commons-pool:commons-pool:jar:1.5.4:compile
[INFO] |  |  +- org.geotools:gt-metadata:jar:34.0:compile
[INFO] |  |  |  +- org.geotools:gt-api:jar:34.0:compile
[INFO] |  |  |  |  +- systems.uom:systems-common:jar:2.1:compile
[INFO] |  |  |  |  |  +- si.uom:si-quantity:jar:2.1:compile
[INFO] |  |  |  |  |  \- si.uom:si-units:jar:2.1:compile
[INFO] |  |  |  |  |     \- jakarta.annotation:jakarta.annotation-api:jar:1.3.4:compile
[INFO] |  |  |  |  \- tech.units:indriya:jar:2.2:compile
[INFO] |  |  |  |     +- tech.uom.lib:uom-lib-common:jar:2.2:compile
[INFO] |  |  |  |     +- jakarta.inject:jakarta.inject-api:jar:2.0.1:compile
[INFO] |  |  |  |     \- org.apiguardian:apiguardian-api:jar:1.1.2:compile
[INFO] |  |  |  +- org.apache.commons:commons-lang3:jar:3.18.0:compile
[INFO] |  |  |  \- org.geotools.ogc:net.opengis.ows:jar:34.0:compile
[INFO] |  |  |     +- org.geotools.ogc:org.w3.xlink:jar:34.0:compile
[INFO] |  |  |     +- org.eclipse.emf:org.eclipse.emf.common:jar:2.15.0:compile
[INFO] |  |  |     +- org.eclipse.emf:org.eclipse.emf.ecore:jar:2.15.0:compile
[INFO] |  |  |     \- org.eclipse.emf:org.eclipse.emf.ecore.xmi:jar:2.15.0:compile
[INFO] |  |  +- it.geosolutions.jgridshift:jgridshift-core:jar:1.3:compile
[INFO] |  |  \- net.sf.geographiclib:GeographicLib-Java:jar:1.49:compile
[INFO] |  \- org.hsqldb:hsqldb:jar:2.7.2:compile
[INFO] +- org.geotools:gt-render:jar:34.0:compile
[INFO] |  +- javax.measure:unit-api:jar:2.2:compile
[INFO] |  +- org.geotools:gt-main:jar:34.0:compile
[INFO] |  |  +- org.geotools:gt-http:jar:34.0:compile
[INFO] |  |  +- org.apache.commons:commons-text:jar:1.13.0:compile
[INFO] |  |  +- com.google.re2j:re2j:jar:1.8:compile
[INFO] |  |  \- org.eclipse.imagen:utilities:jar:0.9.0:compile
[INFO] |  +- org.geotools:gt-coverage:jar:34.0:compile
[INFO] |  |  +- it.geosolutions.imageio-ext:imageio-ext-tiff:jar:2.0.0:compile
[INFO] |  |  |  +- it.geosolutions.imageio-ext:imageio-ext-utilities:jar:2.0.0:compile
[INFO] |  |  |  |  \- org.eclipse.imagen:rendered-image-browser:jar:0.9.0:compile
[INFO] |  |  |  +- it.geosolutions.imageio-ext:imageio-ext-geocore:jar:2.0.0:compile
[INFO] |  |  |  |  +- it.geosolutions.imageio-ext:imageio-ext-streams:jar:2.0.0:compile
[INFO] |  |  |  |  +- javax.xml.bind:jaxb-api:jar:2.4.0-b180830.0359:compile
[INFO] |  |  |  |  +- org.glassfish.jaxb:jaxb-runtime:jar:2.4.0-b180830.0438:runtime
[INFO] |  |  |  |  |  +- org.glassfish.jaxb:txw2:jar:2.4.0-b180830.0438:runtime
[INFO] |  |  |  |  |  +- com.sun.istack:istack-commons-runtime:jar:3.0.7:runtime
[INFO] |  |  |  |  |  +- org.jvnet.staxex:stax-ex:jar:1.8:runtime
[INFO] |  |  |  |  |  \- com.sun.xml.fastinfoset:FastInfoset:jar:1.2.15:runtime
[INFO] |  |  |  |  \- javax.activation:javax.activation-api:jar:1.2.0:compile
[INFO] |  |  |  \- io.airlift:aircompressor:jar:0.27:compile
[INFO] |  |  +- org.eclipse.imagen:affine:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:algebra:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:bandmerge:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:bandselect:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:bandcombine:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:border:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:buffer:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:crop:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:iterators:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:lookup:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:mosaic:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:nullop:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:rescale:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:scale:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:scale2:jar:0.9.0:compile
[INFO] |  |  |  \- org.huldra.math:bigint:jar:0.7.1:compile
[INFO] |  |  +- org.eclipse.imagen:stats:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:translate:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:warp:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:zonal:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:binarize:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:format:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:colorconvert:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:errordiffusion:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:orderdither:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:colorindexer:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:imagefunction:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:piecewise:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:classifier:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:rlookup:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:vectorbin:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:shadedrelief:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:imageread:jar:0.9.0:compile
[INFO] |  |  +- org.eclipse.imagen:convolve:jar:0.9.0:compile
[INFO] |  |  \- commons-io:commons-io:jar:2.19.0:compile
[INFO] |  +- org.geotools:gt-cql:jar:34.0:compile
[INFO] |  \- com.conversantmedia:disruptor:jar:1.2.15:compile
[INFO] +- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:jar:2.19.0:compile
[INFO] |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.19.0:compile
[INFO] |  |  \- com.fasterxml.jackson.core:jackson-annotations:jar:2.19.0:compile
[INFO] |  +- org.yaml:snakeyaml:jar:2.4:compile
[INFO] |  \- com.fasterxml.jackson.core:jackson-core:jar:2.19.0:compile
[INFO] +- org.locationtech.jts:jts-core:jar:1.20.0:compile
[INFO] +- javax.servlet:servlet-api:jar:2.5:provided
[INFO] +- org.apache.logging.log4j:log4j-core:jar:2.24.3:compile
[INFO] +- org.apache.logging.log4j:log4j-api:jar:2.24.3:compile
[INFO] +- com.google.guava:guava:jar:33.4.8-jre:compile
[INFO] |  +- com.google.guava:failureaccess:jar:1.0.3:compile
[INFO] |  +- com.google.guava:listenablefuture:jar:9999.0-empty-to-avoid-conflict-with-guava:compile
[INFO] |  +- org.jspecify:jspecify:jar:1.0.0:compile
[INFO] |  +- com.google.errorprone:error_prone_annotations:jar:2.36.0:compile
[INFO] |  \- com.google.j2objc:j2objc-annotations:jar:3.0.0:compile
[INFO] +- org.apache.pdfbox:pdfbox:jar:2.0.34:compile
[INFO] |  +- org.apache.pdfbox:fontbox:jar:2.0.34:compile
[INFO] |  \- commons-logging:commons-logging:jar:1.3.5:compile
[INFO] +- org.apache.pdfbox:pdfbox-tools:jar:2.0.34:compile
[INFO] |  \- org.apache.pdfbox:pdfbox-debugger:jar:2.0.34:compile
[INFO] |     \- org.bouncycastle:bcpkix-jdk18on:jar:1.80:compile
[INFO] |        \- org.bouncycastle:bcutil-jdk18on:jar:1.80.2:compile
[INFO] |           \- org.bouncycastle:bcprov-jdk18on:jar:1.80.2:compile
[INFO] +- javax.media:jai_imageio:jar:1.1:compile
[INFO] +- commons-httpclient:commons-httpclient:jar:3.1:compile
[INFO] |  \- commons-codec:commons-codec:jar:1.2:compile
[INFO] +- org.mockito:mockito-core:jar:5.15.2:test
[INFO] |  +- net.bytebuddy:byte-buddy:jar:1.15.11:test
[INFO] |  +- net.bytebuddy:byte-buddy-agent:jar:1.15.11:test
[INFO] |  \- org.objenesis:objenesis:jar:3.3:test
[INFO] +- org.apache.xmlgraphics:batik-transcoder:jar:1.18:compile
[INFO] |  +- org.apache.xmlgraphics:batik-anim:jar:1.18:compile
[INFO] |  |  +- org.apache.xmlgraphics:batik-css:jar:1.18:compile
[INFO] |  |  +- org.apache.xmlgraphics:batik-ext:jar:1.18:compile
[INFO] |  |  +- org.apache.xmlgraphics:batik-parser:jar:1.18:compile
[INFO] |  |  \- org.apache.xmlgraphics:batik-svg-dom:jar:1.18:compile
[INFO] |  +- org.apache.xmlgraphics:batik-awt-util:jar:1.18:compile
[INFO] |  |  \- org.apache.xmlgraphics:xmlgraphics-commons:jar:2.10:compile
[INFO] |  +- org.apache.xmlgraphics:batik-bridge:jar:1.18:compile
[INFO] |  |  \- org.apache.xmlgraphics:batik-script:jar:1.18:compile
[INFO] |  +- org.apache.xmlgraphics:batik-dom:jar:1.18:compile
[INFO] |  +- org.apache.xmlgraphics:batik-gvt:jar:1.18:compile
[INFO] |  +- org.apache.xmlgraphics:batik-shared-resources:jar:1.18:compile
[INFO] |  +- org.apache.xmlgraphics:batik-svggen:jar:1.18:compile
[INFO] |  +- org.apache.xmlgraphics:batik-util:jar:1.18:compile
[INFO] |  |  +- org.apache.xmlgraphics:batik-constants:jar:1.18:compile
[INFO] |  |  \- org.apache.xmlgraphics:batik-i18n:jar:1.18:compile
[INFO] |  +- org.apache.xmlgraphics:batik-xml:jar:1.18:compile
[INFO] |  \- xml-apis:xml-apis-ext:jar:1.3.04:compile
[INFO] +- xerces:xercesImpl:jar:2.7.1:compile
[INFO] +- com.github.librepdf:openpdf:jar:1.3.26:compile
[INFO] |  \- com.google.code.findbugs:jsr305:jar:3.0.2:compile
[INFO] +- org.json:json:jar:20231013:compile
[INFO] +- org.eclipse.imagen:imagen-core:jar:0.9.0:compile
[INFO] +- org.springframework:spring-context:jar:5.3.39:compile
[INFO] |  +- org.springframework:spring-aop:jar:5.3.39:compile
[INFO] |  +- org.springframework:spring-beans:jar:5.3.39:compile
[INFO] |  +- org.springframework:spring-core:jar:5.3.39:compile
[INFO] |  |  \- org.springframework:spring-jcl:jar:5.3.39:compile
[INFO] |  \- org.springframework:spring-expression:jar:5.3.39:compile
[INFO] +- org.springframework:spring-web:jar:5.3.39:compile
[INFO] +- xalan:xalan:jar:2.7.0:compile
[INFO] |  \- xml-apis:xml-apis:jar:1.0.b2:compile
[INFO] +- io.dropwizard.metrics:metrics-core:jar:4.2.30:compile
[INFO] |  \- org.slf4j:slf4j-api:jar:2.0.16:compile
[INFO] +- io.dropwizard.metrics:metrics-servlet:jar:4.2.30:compile
[INFO] +- io.dropwizard.metrics:metrics-httpclient:jar:4.2.30:compile
[INFO] |  +- org.apache.httpcomponents:httpcore:jar:4.4.16:compile
[INFO] |  \- org.apache.httpcomponents:httpclient:jar:4.5.14:compile
[INFO] +- io.dropwizard.metrics:metrics-servlets:jar:4.2.30:compile
[INFO] |  +- io.dropwizard.metrics:metrics-healthchecks:jar:4.2.30:compile
[INFO] |  +- io.dropwizard.metrics:metrics-json:jar:4.2.30:compile
[INFO] |  +- io.dropwizard.metrics:metrics-jvm:jar:4.2.30:compile
[INFO] |  \- com.helger:profiler:jar:1.1.1:compile
[INFO] +- io.dropwizard.metrics:metrics-log4j2:jar:4.2.30:compile
[INFO] +- io.dropwizard.metrics:metrics-jmx:jar:4.2.30:compile
[INFO] \- junit:junit:jar:4.7:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.219 s
[INFO] Finished at: 2026-06-15T16:35:14+02:00
[INFO] ------------------------------------------------------------------------

@etj etj requested a review from aaime June 16, 2026 08:05
@etj etj changed the title [Fixes #48] Reinstate png, jpg support. Removes imagen-legacy dependency. [Fixes #48][2.4.x] Reinstate png, jpg support. Removes imagen-legacy dependency. Jun 16, 2026
@aaime aaime merged commit fedd087 into mapfish:2.4.x Jun 17, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants