JXLatte
| Language | Java |
|---|---|
| License | MIT |
| Repository | github.com/Traneptora/jxlatte |
| Documentation | README and source |
| Depends on | nothing |
| Read / write | yes / no (decodes JXL, writes PNG and PFM) |
JXLatte is a JPEG XL decoder written from scratch in Java, without libjxl. It decodes all static images: lossless and lossy Modular, VarDCT, and recompressed JPEGs. It can also write the result as PNG (8 or 16 bits, SDR or HDR) or PFM.
It doesn’t support animation, progressive decoding or region-of-interest decoding, and it is slower than libjxl. The project calls itself work in progress. Use it when you need to read JXL images on the JVM without native code.
Installation#
JXLatte is not published on Maven Central. Build it and install it into your local Maven repository:
git clone https://github.com/Traneptora/jxlatte.git
cd jxlatte
mvn clean install
Then add the dependency:
<dependency>
<groupId>com.traneptora</groupId>
<artifactId>jxlatte</artifactId>
<version>0.1.0</version>
</dependency>
It also builds with Meson (meson setup build && ninja -C build) into a runnable jxlatte.jar.
Basic usage: convert JXL to PNG#
import com.traneptora.jxlatte.JXLDecoder;
import com.traneptora.jxlatte.JXLImage;
import com.traneptora.jxlatte.io.PNGWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class JxlToPng {
public static void main(String[] args) throws IOException {
try (JXLDecoder decoder = new JXLDecoder("in.jxl");
OutputStream out = new FileOutputStream("out.png")) {
JXLImage image = decoder.decode();
System.out.println(image.getWidth() + " x " + image.getHeight());
new PNGWriter(image).write(out);
}
}
}
How to read image properties#
JXLImage image = new JXLDecoder("in.jxl").decode();
int width = image.getWidth();
int height = image.getHeight();
boolean alpha = image.hasAlpha();
boolean hdr = image.isHDR();
int channels = image.getColorChannelCount(); // 1 gray, 3 color
if (image.hasICCProfile()) {
byte[] icc = image.getICCProfile();
}
How to get the pixel values#
getBuffer returns one ImageBuffer per channel (color channels, then alpha and other extra channels). A buffer stores samples as int[y][x] or float[y][x]:
import com.traneptora.jxlatte.util.ImageBuffer;
ImageBuffer[] channels = image.getBuffer(false); // false: no copy
ImageBuffer red = channels[0];
if (red.isFloat()) {
float[][] samples = red.getFloatBuffer(); // samples[y][x]
System.out.println(samples[0][0]);
} else {
int[][] samples = red.getIntBuffer();
System.out.println(samples[0][0]);
}
How to write a 16-bit PNG#
import com.traneptora.jxlatte.JXLOptions;
// bit depth 8 or 16, not HDR
new PNGWriter(image, 16, false, JXLOptions.PEAK_DETECT_AUTO).write(out);
Tips#
- From the command line:
java -jar jxlatte.jar in.jxl out.png. - For HDR images use
new PNGWriter(image, true)to keep the HDR transfer function, orimage.toneMap(...)to convert to SDR first.