diff --git a/CHANGES.md b/CHANGES.md
index 2d078e7..6bef7ca 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,7 @@
+## 1.9.0
+
+* Added `Format` constants for the media types `convert` accepts, including JPEG XL (`image/jxl`).
+
## 1.8.9
* Upgraded dependencies (okio 3.12.0, gson 2.13.1, commons-codec 1.21.0)
* Upgraded all Maven plugins to latest stable versions
diff --git a/pom.xml b/pom.xml
index caf2d10..b5fbaec 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
Use these constants with {@link Source#convert(Options)}: + * + *
{@code
+ * Tinify.fromFile("input.png")
+ * .convert(new Options().with("type", Format.JXL))
+ * .toFile("output.jxl");
+ * }
+ *
+ * Multiple types may be supplied, in which case the API returns the + * smallest result: + * + *
{@code
+ * new Options().with("type", new String[]{Format.JXL, Format.WEBP});
+ * }
+ */
+public final class Format {
+ /** WebP, {@code image/webp}. */
+ public static final String WEBP = "image/webp";
+
+ /** PNG, {@code image/png}. */
+ public static final String PNG = "image/png";
+
+ /** JPEG, {@code image/jpeg}. */
+ public static final String JPEG = "image/jpeg";
+
+ /**
+ * JPEG, under the alternative {@code image/jpg} media type the API also
+ * accepts. The API normalises this to {@code image/jpeg}, so the result is
+ * identical to {@link #JPEG}. The two constants hold different strings but
+ * select the same format.
+ */
+ public static final String JPG = "image/jpg";
+
+ /** AVIF, {@code image/avif}. */
+ public static final String AVIF = "image/avif";
+
+ /** JPEG XL, {@code image/jxl}. */
+ public static final String JXL = "image/jxl";
+
+ /** Wildcard, {@code */*}. Returns the smallest of the supported types. */
+ public static final String ANY = "*/*";
+
+ private Format() {
+ }
+}
diff --git a/src/test/java/com/tinify/FormatTest.java b/src/test/java/com/tinify/FormatTest.java
new file mode 100644
index 0000000..acd94eb
--- /dev/null
+++ b/src/test/java/com/tinify/FormatTest.java
@@ -0,0 +1,34 @@
+package com.tinify;
+
+import org.junit.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.equalTo;
+
+public class FormatTest {
+ @Test
+ public void formatShouldExposeSupportedMediaTypes() {
+ assertThat(Format.WEBP, is(equalTo("image/webp")));
+ assertThat(Format.PNG, is(equalTo("image/png")));
+ assertThat(Format.JPEG, is(equalTo("image/jpeg")));
+ assertThat(Format.JPG, is(equalTo("image/jpg")));
+ assertThat(Format.AVIF, is(equalTo("image/avif")));
+ assertThat(Format.JXL, is(equalTo("image/jxl")));
+ assertThat(Format.ANY, is(equalTo("*/*")));
+ }
+
+ @Test
+ public void convertWithFormatShouldSerializeMediaType() {
+ Options options = new Options().with("convert", new Options().with("type", Format.JXL));
+ assertThat(options.toJson(), is(equalTo("{\"convert\":{\"type\":\"image/jxl\"}}")));
+ }
+
+ @Test
+ public void convertWithMultipleFormatsShouldSerializeMediaTypes() {
+ Options options = new Options().with("convert",
+ new Options().with("type", new String[]{Format.JXL, Format.WEBP}));
+ assertThat(options.toJson(),
+ is(equalTo("{\"convert\":{\"type\":[\"image/jxl\",\"image/webp\"]}}")));
+ }
+}