-
-
Notifications
You must be signed in to change notification settings - Fork 322
Description
Describe the bug
With JPEGImageReader using java.desktop/sun.java2d.cmm.lcms.LCMS, reading the same file a 2nd time causes
java.awt.color.CMMException: LCMS error 13: LUT is not suitable to be saved as LutAToB
Version information
-
The version of the TwelveMonkeys ImageIO library in use.
3.12.0 -
The exact output of
java --version(orjava -versionfor older Java releases).
java version "25" 2025-09-16 LTS
Java(TM) SE Runtime Environment (build 25+37-LTS-3491)
Java HotSpot(TM) 64-Bit Server VM (build 25+37-LTS-3491, mixed mode, sharing) -
Extra information about OS version, server version, standalone program or web application packaging, executable wrapper, etc. Please state exact version numbers where applicable.
OS version: Windows 11 24H2 (Build 26100.6584)
To Reproduce
Steps to reproduce the behavior:
- Compile the below sample code
- Download the attached sample image file CMMException.jpg
- Run the code with the sample file
- See error
Expected behavior
The 2nd read should not fail, at least not after renewed
iis = ImageIO.createImageInputStream(new File(testFileName));
reader.setInput(iis);
Example code
package com.agfa.hap;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.spi.IIORegistry;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class ProblemCmmException {
public static void main(String[] args) {
ImageIO.setUseCache(false);
IIORegistry iioRegistry = IIORegistry.getDefaultInstance();
com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReaderSpi jpegImageReaderSpi = iioRegistry.getServiceProviderByClass(com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReaderSpi.class);
ImageReader reader;
try {
reader = jpegImageReaderSpi.createReaderInstance();
} catch (IOException e) {
throw new RuntimeException(e);
}
if (!(reader instanceof com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader)) {
throw new RuntimeException("reader is not of type Twelvemonkeys JPEGImageReader");
}
String testFileName = "CMMException.jpg";
URL testFileUrl = ProblemCmmException.class.getResource("/CMMException.jpg");
if (testFileUrl == null) {
throw new RuntimeException("Test file CMMException.jpg not found");
} else {
testFileName = testFileUrl.getPath();
}
Image image = null;
ImageInputStream iis = null;
try {
iis = ImageIO.createImageInputStream(new File(testFileName));
reader.setInput(iis);
image = reader.read(0);
} catch (IOException e) {
throw new RuntimeException("Failed reading test file 1st time, reason: ",e);
}
try {
iis = ImageIO.createImageInputStream(new File(testFileName));
reader.setInput(iis);
image = reader.read(0);
} catch (Exception e) {
throw new RuntimeException("Failed reading test file 2nd time, reason: ",e);
}
}
}Sample file(s)
Attached CMMException.jpg:

Stack trace
Exception in thread "main" java.lang.RuntimeException: Failed reading test file 1st time, reason:
at com.agfa.hap.ProblemCmmException.main(ProblemCmmException.java:54)
Caused by: java.awt.color.CMMException: LCMS error 13: LUT is not suitable to be saved as LutAToB
at java.desktop/sun.java2d.cmm.lcms.LCMS.getProfileDataNative(Native Method)
at java.desktop/sun.java2d.cmm.lcms.LCMSProfile.getProfileData(LCMSProfile.java:52)
at java.desktop/sun.java2d.cmm.lcms.LCMS.getProfileData(LCMS.java:80)
at java.desktop/java.awt.color.ICC_Profile.getData(ICC_Profile.java:1106)
at com.twelvemonkeys.imageio.color.ColorProfiles.getProfileHeaderWithProfileId(ColorProfiles.java:99)
at com.twelvemonkeys.imageio.color.ColorProfiles.isCS_sRGB(ColorProfiles.java:149)
at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:340)
at java.desktop/javax.imageio.ImageReader.read(ImageReader.java:938)
Additional context
My analysis so far:
Apparently it has to do with the color space, which is altered on 1st read, but cached and reused on 2nd read.
When during debug setting both the color space retrieved from cache and the CMMProfile retrieved from cache to null, the 2nd read succeeds.