mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 11:35:29 -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/>
|
* <p/>
|
||||||
* Main features:
|
* Main features:
|
||||||
* <ul>
|
* <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 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 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>
|
* <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);
|
ICC_Profile profile = getEmbeddedICCProfile(false);
|
||||||
AdobeDCTSegment adobeDCT = getAdobeDCT();
|
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)
|
// 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.
|
// - or only filter out the bad ICC profiles in the JPEGSegmentImageInputStream.
|
||||||
if (delegate.canReadRaster() && (
|
if (delegate.canReadRaster() && (
|
||||||
unsupported ||
|
sourceCSType == JPEGColorSpace.CMYK ||
|
||||||
|
sourceCSType == JPEGColorSpace.YCCK ||
|
||||||
adobeDCT != null && adobeDCT.getTransform() == AdobeDCTSegment.YCCK ||
|
adobeDCT != null && adobeDCT.getTransform() == AdobeDCTSegment.YCCK ||
|
||||||
profile != null && !ColorSpaces.isCS_sRGB(profile))) {
|
profile != null && !ColorSpaces.isCS_sRGB(profile)) ||
|
||||||
// profile != null && (ColorSpaces.isOffendingColorProfile(profile) || profile.getColorSpaceType() == ColorSpace.TYPE_CMYK))) {
|
sourceCSType == JPEGColorSpace.YCbCr && getRawImageType(imageIndex) != null) { // TODO: Issue warning?
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
System.out.println("Reading using raster and extra conversion");
|
System.out.println("Reading using raster and extra conversion");
|
||||||
System.out.println("ICC color profile: " + profile);
|
System.out.println("ICC color profile: " + profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
return readImageAsRasterAndReplaceColorProfile(imageIndex, param, ensureDisplayProfile(profile));
|
return readImageAsRasterAndReplaceColorProfile(imageIndex, param, sof, sourceCSType, adobeDCT, ensureDisplayProfile(profile));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@ -327,14 +327,10 @@ public class JPEGImageReader extends ImageReaderBase {
|
|||||||
return delegate.read(imageIndex, param);
|
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 origWidth = getWidth(imageIndex);
|
||||||
int origHeight = getHeight(imageIndex);
|
int origHeight = getHeight(imageIndex);
|
||||||
|
|
||||||
AdobeDCTSegment adobeDCT = getAdobeDCT();
|
|
||||||
SOFSegment startOfFrame = getSOF();
|
|
||||||
JPEGColorSpace csType = getSourceCSType(adobeDCT, startOfFrame);
|
|
||||||
|
|
||||||
Iterator<ImageTypeSpecifier> imageTypes = getImageTypes(imageIndex);
|
Iterator<ImageTypeSpecifier> imageTypes = getImageTypes(imageIndex);
|
||||||
BufferedImage image = getDestination(param, imageTypes, origWidth, origHeight);
|
BufferedImage image = getDestination(param, imageTypes, origWidth, origHeight);
|
||||||
WritableRaster destination = image.getRaster();
|
WritableRaster destination = image.getRaster();
|
||||||
|
@ -600,6 +600,38 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTestCase<JPEGImageRe
|
|||||||
reader.dispose();
|
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
|
// TODO: Test RGBA/YCbCrA handling
|
||||||
|
|
||||||
@Test
|
@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