Skip to content

Unified ChartEncoder + optional export deps (#772)#993

Open
timmolter wants to merge 2 commits into
developfrom
issue-772-unified-chart-encoder
Open

Unified ChartEncoder + optional export deps (#772)#993
timmolter wants to merge 2 commits into
developfrom
issue-772-unified-chart-encoder

Conversation

@timmolter

Copy link
Copy Markdown
Member

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.

ChartEncoder.saveChart(chart, "./MyChart", "png");   // raster via ImageIO
ChartEncoder.saveChart(chart, "./MyChart", "tiff");  // raster, built into the JDK
ChartEncoder.saveChart(chart, "./MyChart", "webp");  // raster, via any ImageIO WebP plugin
ChartEncoder.saveChart(chart, "./MyChart", "svg");   // vector
ChartEncoder.saveChart(chart, "./MyChart", "pdf");   // vector
byte[] bytes = ChartEncoder.getBytes(chart, "png");

What changed

  • ChartEncoder — new facade. svg/eps/pdf route to the existing vector encoders; every other format name is delegated to ImageIO, so any registered ImageWriter plugin (WebP, AVIF, …) works with no XChart code change. Includes getBytes(...) and getSupportedRasterFormats().
  • Optional deps fixedVectorGraphics2D, pdfbox-graphics2d and animated-gif-lib are 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.
  • Friendly errorsUtils.requireOnClasspath(...) makes a missing optional encoder throw an IllegalStateException naming the exact artifact to add, instead of a raw NoClassDefFoundError.
  • Deprecations — the per-format saveBitmap / saveVectorGraphic / savePdfboxGraphics methods are deprecated in favor of ChartEncoder. saveBitmapWithDPI and saveJPGWithQuality remain (no facade equivalent).
  • SamplesExample1 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. Size story that motivated Export in AVIF #772: PNG 15.7 KB → WebP 7.1 KB → AVIF 5.4 KB.
  • Tests / docsChartEncoderTest covers every available raster format, the vector formats, byte output, extension handling, and the unsupported-format error. README gains an "Exporting Charts" section.

Notes / caveats

  • ⚠️ Behavior change for consumers: because the export libs are no longer transitive, projects that use PDF/SVG/EPS/GIF export must now add the matching dependency themselves. Worth a release-note. Fits the 4.x line.
  • AVIF is not yet an in-library format. There is no bundleable Maven-Central ImageIO AVIF writer (vavi isn't on Central; the nemanjastokuca plugin is reader-only; JDeli is commercial). ExampleAvif therefore uses the avifenc CLI as a portable fallback. If/when a viable AVIF ImageWriter exists, ChartEncoder.saveChart(chart, "avif") will work with no code change.
  • The demo's WebP plugin is com.github.usefulness:webp-imageio (maintained fork with macOS arm64 natives); the older gotson fork ships no Apple-Silicon binary.

Full build green: 122 tests pass, demo + site build.

Closes #772

🤖 Generated with Claude Code

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>

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

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 ChartEncoder with saveChart(...), getBytes(...), and getSupportedRasterFormats(); 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 xchart module 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>
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.

Export in AVIF

2 participants