Unified ChartEncoder + optional export deps (#772)#993
Open
timmolter wants to merge 2 commits into
Open
Conversation
Introduce ChartEncoder, a single format-agnostic export facade: saveChart(chart, fileNameOrStream, "format") / getBytes(...). Vector formats (svg/eps/pdf) route to the existing encoders; every other name is delegated to javax.imageio.ImageIO, so any registered ImageWriter plugin (tiff built into the JDK, or webp/avif via a classpath plugin) works with no XChart code change. This addresses #772 (AVIF export) by making format support pluggable rather than hard-coded. - Make VectorGraphics2D, pdfbox-graphics2d and animated-gif-lib truly optional in the module pom (the parent dependencyManagement optional flag is not inherited, so they were being pulled transitively). The demo module now declares them explicitly. - Add Utils.requireOnClasspath(...) so a missing optional encoder throws a clear IllegalStateException naming the artifact to add, instead of a raw NoClassDefFoundError. - Deprecate the per-format save methods on BitmapEncoder, VectorGraphicsEncoder and PdfboxGraphicsEncoder in favor of ChartEncoder. saveBitmapWithDPI/saveJPGWithQuality remain (no facade equivalent). - Example1 now uses ChartEncoder and emits a tiff sample; new ExampleWebP (via com.github.usefulness:webp-imageio, demo-only) and ExampleAvif (via the libavif avifenc CLI) generate webp/avif samples. - ChartEncoderTest exercises every available raster format, the vector formats, byte output, extension handling and the unsupported-format error. README documents the unified API and optional dependencies. Note: there is no bundleable ImageIO AVIF writer, so in-library "avif" export via ChartEncoder is not yet possible; ExampleAvif uses the CLI as a portable fallback. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Open
There was a problem hiding this comment.
Pull request overview
This PR introduces a unified export façade (ChartEncoder) that routes vector formats to existing encoders and delegates all raster formats to javax.imageio.ImageIO, enabling new raster formats (e.g., WebP) via ImageIO plugins without XChart code changes. It also corrects Maven dependency optionality so heavy export dependencies are no longer pulled transitively by default, and adds tests/demos/docs around the new API.
Changes:
- Added
ChartEncoderwithsaveChart(...),getBytes(...), andgetSupportedRasterFormats(); raster export is ImageIO/SPI-driven and vector export is routed to existing encoders. - Marked vector/PDF/animated-GIF export dependencies as truly optional in the
xchartmodule POM; demo declares them explicitly. - Added
Utils.requireOnClasspath(...), new demos (WebP + AVIF fallback), new unit tests, and README updates; deprecated older per-format entry points.
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| xchart/src/test/java/org/knowm/xchart/ChartEncoderTest.java | New tests covering raster/vectors, bytes output, extension handling, and unsupported-format errors. |
| xchart/src/main/java/org/knowm/xchart/VectorGraphicsEncoder.java | Deprecates old entry points and adds classpath-guard logic for optional vector deps. |
| xchart/src/main/java/org/knowm/xchart/PdfboxGraphicsEncoder.java | Deprecates old PDF encoder entry points and adds a classpath check for PDF export dependency. |
| xchart/src/main/java/org/knowm/xchart/internal/Utils.java | Adds requireOnClasspath(...) helper for friendly missing-dependency errors. |
| xchart/src/main/java/org/knowm/xchart/GifEncoder.java | Adds a classpath check for the animated GIF dependency before use. |
| xchart/src/main/java/org/knowm/xchart/ChartEncoder.java | New unified export façade (vector routing + ImageIO raster delegation). |
| xchart/src/main/java/org/knowm/xchart/BitmapEncoder.java | Deprecates legacy bitmap save/get-bytes entry points in favor of ChartEncoder. |
| xchart/pom.xml | Marks VectorGraphics2D / pdfbox-graphics2d / animated-gif-lib as <optional>true</optional> at the module level. |
| xchart-demo/src/main/java/org/knowm/xchart/standalone/ExampleWebP.java | New demo showing WebP export via ImageIO plugin + ChartEncoder. |
| xchart-demo/src/main/java/org/knowm/xchart/standalone/ExampleAvif.java | New demo showing AVIF generation via PNG + avifenc CLI fallback. |
| xchart-demo/src/main/java/org/knowm/xchart/standalone/Example1.java | Updates sample to use ChartEncoder for unified export and adds TIFF output. |
| xchart-demo/pom.xml | Adds explicit demo deps for optional export libs + demo-only WebP ImageIO plugin. |
| README.md | Updates examples and adds “Exporting Charts” documentation with optional dependency table. |
| .gitignore | Ignores additional generated export artifacts (tif/tiff/webp/avif). |
Comment on lines
+34
to
+38
| /** | ||
| * @deprecated use {@link ChartEncoder#saveChart(IChart, String, String)} with format {@code | ||
| * "pdf"} instead | ||
| */ | ||
| @Deprecated |
Comment on lines
+51
to
+55
| /** | ||
| * @deprecated use {@link ChartEncoder#saveChart(IChart, OutputStream, String)} with format {@code | ||
| * "pdf"} instead | ||
| */ | ||
| @Deprecated |
Comment on lines
+68
to
+72
| /** | ||
| * @deprecated use {@link ChartEncoder#saveChart(IChart, OutputStream, String)} with format {@code | ||
| * "pdf"} instead | ||
| */ | ||
| @Deprecated |
Comment on lines
+87
to
+90
| /** | ||
| * @deprecated use {@link ChartEncoder} per chart, or merge charts before export | ||
| */ | ||
| @Deprecated |
Comment on lines
+104
to
+107
| /** | ||
| * @deprecated use {@link ChartEncoder} per chart, or merge charts before export | ||
| */ | ||
| @Deprecated |
Comment on lines
+121
to
+124
| /** | ||
| * @deprecated use {@link ChartEncoder} per chart, or merge charts before export | ||
| */ | ||
| @Deprecated |
Comment on lines
+11
to
+14
| * <p>WebP is not built into the JDK. This example works because the demo module declares an ImageIO | ||
| * WebP writer plugin ({@code com.github.gotson:webp-imageio}, which bundles native binaries for | ||
| * Windows/Linux/macOS). With any such plugin on the classpath, {@link ChartEncoder} needs no | ||
| * special-casing: it simply hands the {@code "webp"} format name to {@code javax.imageio.ImageIO}. |
Comment on lines
+49
to
+58
| final Processor p; | ||
|
|
||
| if (VectorGraphicsFormat.PDF != vectorGraphicsFormat) { | ||
| // SVG and EPS are produced by VectorGraphics2D; PDF delegates to the (separately guarded) | ||
| // PdfboxGraphicsEncoder below. | ||
| Utils.requireOnClasspath( | ||
| "de.erichseifert.vectorgraphics2d.VectorGraphics2D", | ||
| vectorGraphicsFormat + " export", | ||
| "de.erichseifert.vectorgraphics2d:VectorGraphics2D"); | ||
| } |
- VectorGraphicsEncoder: PDF export no longer touches any VectorGraphics2D type. saveVectorGraphic(...PDF) now early-returns to PdfboxGraphicsEncoder before referencing Processor/PDFBoxProcessor, so PDF export works when the now-optional VectorGraphics2D dependency is absent (previously NoClassDefFoundError). Removed the now-dead PDFBoxProcessor adapter. - PdfboxGraphicsEncoder: merge the stray second Javadoc block on each deprecated method into a single block carrying the @deprecated tag, so the existing @param/@throws docs are no longer orphaned. - ExampleWebP: fix Javadoc to reference the actual plugin used by the demo pom (com.github.usefulness:webp-imageio, which ships Apple Silicon natives). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a single, format-agnostic export facade and makes the heavy export dependencies genuinely optional. Motivated by #772 (AVIF export): rather than hard-code each format, export becomes pluggable through
javax.imageio.ImageIO.What changed
ChartEncoder— new facade.svg/eps/pdfroute to the existing vector encoders; every other format name is delegated to ImageIO, so any registeredImageWriterplugin (WebP, AVIF, …) works with no XChart code change. IncludesgetBytes(...)andgetSupportedRasterFormats().VectorGraphics2D,pdfbox-graphics2dandanimated-gif-libare now marked<optional>true</optional>in the module pom. They were declared optional only in the parent<dependencyManagement>, where Maven does not inherit the flag, so they were being pulled transitively into every consumer. The demo module now declares them explicitly.Utils.requireOnClasspath(...)makes a missing optional encoder throw anIllegalStateExceptionnaming the exact artifact to add, instead of a rawNoClassDefFoundError.saveBitmap/saveVectorGraphic/savePdfboxGraphicsmethods are deprecated in favor ofChartEncoder.saveBitmapWithDPIandsaveJPGWithQualityremain (no facade equivalent).Example1usesChartEncoderand emits a TIFF sample; newExampleWebP(viacom.github.usefulness:webp-imageio, demo-only) andExampleAvif(via the libavifavifencCLI) generate WebP/AVIF samples. Size story that motivated Export in AVIF #772: PNG 15.7 KB → WebP 7.1 KB → AVIF 5.4 KB.ChartEncoderTestcovers every available raster format, the vector formats, byte output, extension handling, and the unsupported-format error. README gains an "Exporting Charts" section.Notes / caveats
ExampleAviftherefore uses theavifencCLI as a portable fallback. If/when a viable AVIFImageWriterexists,ChartEncoder.saveChart(chart, "avif")will work with no code change.com.github.usefulness:webp-imageio(maintained fork with macOS arm64 natives); the oldergotsonfork ships no Apple-Silicon binary.Full build green: 122 tests pass, demo + site build.
Closes #772
🤖 Generated with Claude Code