mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-02 02:55:28 -04:00
TMI-JPEG-10: Fixed an issue with JPEGs without JFIF segment being treated as RGB, even when YCbCr.
This commit is contained in:
parent
602e5ec34b
commit
086357694a
@ -66,6 +66,7 @@ import java.util.List;
|
||||
* <p/>
|
||||
* Main features:
|
||||
* <ul>
|
||||
* <li>Support for YCbCr JPEGs without JFIF segment (converted to RGB, using the embedded ICC profile if applicable)</li>
|
||||
* <li>Support for CMYK JPEGs (converted to RGB by default or as CMYK, using the embedded ICC profile if applicable)</li>
|
||||
* <li>Support for Adobe YCCK JPEGs (converted to RGB by default or as CMYK, using the embedded ICC profile if applicable)</li>
|
||||
* <li>Support for JPEGs containing ICC profiles with interpretation other than 'Perceptual' (profile is assumed to be 'Perceptual' and used)</li>
|
||||
@ -298,26 +299,25 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
// }
|
||||
// }
|
||||
|
||||
// NOTE: We rely on the fact that unsupported images has no valid types. This is kind of hacky.
|
||||
// Might want to look into the metadata, to see if there's a better way to identify these.
|
||||
boolean unsupported = !delegate.getImageTypes(imageIndex).hasNext();
|
||||
|
||||
ICC_Profile profile = getEmbeddedICCProfile(false);
|
||||
AdobeDCTSegment adobeDCT = getAdobeDCT();
|
||||
SOFSegment sof = getSOF();
|
||||
JPEGColorSpace sourceCSType = getSourceCSType(adobeDCT, sof);
|
||||
|
||||
// We need to apply ICC profile unless the profile is sRGB/default gray (whatever that is)
|
||||
// - or only filter out the bad ICC profiles in the JPEGSegmentImageInputStream.
|
||||
if (delegate.canReadRaster() && (
|
||||
unsupported ||
|
||||
sourceCSType == JPEGColorSpace.CMYK ||
|
||||
sourceCSType == JPEGColorSpace.YCCK ||
|
||||
adobeDCT != null && adobeDCT.getTransform() == AdobeDCTSegment.YCCK ||
|
||||
profile != null && !ColorSpaces.isCS_sRGB(profile))) {
|
||||
// profile != null && (ColorSpaces.isOffendingColorProfile(profile) || profile.getColorSpaceType() == ColorSpace.TYPE_CMYK))) {
|
||||
profile != null && !ColorSpaces.isCS_sRGB(profile)) ||
|
||||
sourceCSType == JPEGColorSpace.YCbCr && getRawImageType(imageIndex) != null) { // TODO: Issue warning?
|
||||
if (DEBUG) {
|
||||
System.out.println("Reading using raster and extra conversion");
|
||||
System.out.println("ICC color profile: " + profile);
|
||||
}
|
||||
|
||||
return readImageAsRasterAndReplaceColorProfile(imageIndex, param, ensureDisplayProfile(profile));
|
||||
return readImageAsRasterAndReplaceColorProfile(imageIndex, param, sof, sourceCSType, adobeDCT, ensureDisplayProfile(profile));
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
@ -327,14 +327,10 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
return delegate.read(imageIndex, param);
|
||||
}
|
||||
|
||||
private BufferedImage readImageAsRasterAndReplaceColorProfile(int imageIndex, ImageReadParam param, ICC_Profile profile) throws IOException {
|
||||
private BufferedImage readImageAsRasterAndReplaceColorProfile(int imageIndex, ImageReadParam param, SOFSegment startOfFrame, JPEGColorSpace csType, AdobeDCTSegment adobeDCT, ICC_Profile profile) throws IOException {
|
||||
int origWidth = getWidth(imageIndex);
|
||||
int origHeight = getHeight(imageIndex);
|
||||
|
||||
AdobeDCTSegment adobeDCT = getAdobeDCT();
|
||||
SOFSegment startOfFrame = getSOF();
|
||||
JPEGColorSpace csType = getSourceCSType(adobeDCT, startOfFrame);
|
||||
|
||||
Iterator<ImageTypeSpecifier> imageTypes = getImageTypes(imageIndex);
|
||||
BufferedImage image = getDestination(param, imageTypes, origWidth, origHeight);
|
||||
WritableRaster destination = image.getRaster();
|
||||
|
@ -600,6 +600,38 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTestCase<JPEGImageRe
|
||||
reader.dispose();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadNoJFIFYCbCr() throws IOException {
|
||||
// Basically the same issue as http://stackoverflow.com/questions/9340569/jpeg-image-with-wrong-colors
|
||||
JPEGImageReader reader = createReader();
|
||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/no-jfif-ycbcr.jpg")));
|
||||
|
||||
assertEquals(310, reader.getWidth(0));
|
||||
assertEquals(206, reader.getHeight(0));
|
||||
|
||||
ImageReadParam param = reader.getDefaultReadParam();
|
||||
param.setSourceRegion(new Rectangle(0, 0, 310, 8));
|
||||
BufferedImage image = reader.read(0, param);
|
||||
assertNotNull(image);
|
||||
assertEquals(310, image.getWidth());
|
||||
assertEquals(8, image.getHeight());
|
||||
|
||||
int[] expectedRGB = new int[] {
|
||||
0xff3c1b14, 0xff35140b, 0xff4b2920, 0xff3b160e, 0xff49231a, 0xff874e3d, 0xff563d27, 0xff926c61,
|
||||
0xff350005, 0xff84432d, 0xff754f46, 0xff2c2223, 0xff422016, 0xff220f0b, 0xff251812, 0xff1c1209,
|
||||
0xff483429, 0xff1b140c, 0xff231c16, 0xff2f261f, 0xff2e2923, 0xff170c08, 0xff383025, 0xff443b34,
|
||||
0xff574a39, 0xff3b322b, 0xffeee1d0, 0xffebdecd, 0xffe9dccb, 0xffe8dbca, 0xffe7dcca,
|
||||
};
|
||||
|
||||
// Validate strip colors
|
||||
for (int i = 0; i < image.getWidth() / 10; i++) {
|
||||
int actualRGB = image.getRGB(i * 10, 7);
|
||||
assertEquals((actualRGB >> 16) & 0xff, (expectedRGB[i] >> 16) & 0xff, 5);
|
||||
assertEquals((actualRGB >> 8) & 0xff, (expectedRGB[i] >> 8) & 0xff, 5);
|
||||
assertEquals((actualRGB) & 0xff, (expectedRGB[i]) & 0xff, 5);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Test RGBA/YCbCrA handling
|
||||
|
||||
@Test
|
||||
|
BIN
imageio/imageio-jpeg/src/test/resources/jpeg/no-jfif-ycbcr.jpg
Normal file
BIN
imageio/imageio-jpeg/src/test/resources/jpeg/no-jfif-ycbcr.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
Loading…
x
Reference in New Issue
Block a user