mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-04 20:15:28 -04:00
#399 Rewritten getSourceCSType to mimic libjpeg
This commit is contained in:
parent
cdb2d72f8b
commit
3a86bfab98
@ -536,131 +536,86 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JPEGColorSpace getSourceCSType(JFIF jfif, AdobeDCT adobeDCT, final Frame startOfFrame) throws IIOException {
|
private JPEGColorSpace getSourceCSType(final JFIF jfif, final AdobeDCT adobeDCT, final Frame startOfFrame) throws IIOException {
|
||||||
/*
|
// Adapted from libjpeg jdapimin.c:
|
||||||
ADAPTED from http://download.oracle.com/javase/6/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html:
|
// Guess the input colorspace
|
||||||
|
// (Wish JPEG committee had provided a real way to specify this...)
|
||||||
When reading, the contents of the stream are interpreted by the usual JPEG conventions, as follows:
|
|
||||||
|
|
||||||
• If a JFIF APP0 marker segment is present, the colorspace should be either grayscale or YCbCr.
|
|
||||||
If an APP2 marker segment containing an embedded ICC profile is also present, then YCbCr is converted to RGB according
|
|
||||||
to the formulas given in the JFIF spec, and the ICC profile is assumed to refer to the resulting RGB space.
|
|
||||||
But, as software does not follow the spec, we can't really assume anything.
|
|
||||||
|
|
||||||
• If an Adobe APP14 marker segment is present, the colorspace is determined by consulting the transform flag.
|
|
||||||
The transform flag takes one of three values:
|
|
||||||
o 2 - The image is encoded as YCCK (implicitly converted from CMYK on encoding).
|
|
||||||
o 1 - The image is encoded as YCbCr (implicitly converted from RGB on encoding).
|
|
||||||
o 0 - Unknown. 1-channel images are assumed to be Gray, 3-channel images are assumed to be RGB,
|
|
||||||
4-channel images are assumed to be CMYK.
|
|
||||||
|
|
||||||
• If neither marker segment is present, the following procedure is followed: Single-channel images are assumed
|
|
||||||
to be grayscale, and 2-channel images are assumed to be grayscale with an alpha channel. For 3- and 4-channel
|
|
||||||
images, the component ids are consulted. If these values are 1-3 for a 3-channel image, then the image is
|
|
||||||
assumed to be YCbCr. If these values are 1-4 for a 4-channel image, then the image is assumed to be YCbCrA. If
|
|
||||||
these values are > 4, they are checked against the ASCII codes for 'R', 'G', 'B', 'A', 'C', 'c', 'M', 'Y', 'K'.
|
|
||||||
These can encode the following colorspaces:
|
|
||||||
|
|
||||||
RGB
|
|
||||||
RGBA
|
|
||||||
YCC (as 'Y','C','c'), assumed to be PhotoYCC
|
|
||||||
YCCA (as 'Y','C','c','A'), assumed to be PhotoYCCA
|
|
||||||
CMYK (as 'C', 'M', 'Y', 'K').
|
|
||||||
|
|
||||||
Otherwise, 3-channel subsampled images are assumed to be YCbCr, 3-channel non-subsampled images are assumed to
|
|
||||||
be RGB, 4-channel subsampled images are assumed to be YCCK, and 4-channel, non-subsampled images are assumed to
|
|
||||||
be CMYK.
|
|
||||||
|
|
||||||
• All other images are declared uninterpretable and an exception is thrown if an attempt is made to read one as
|
|
||||||
a BufferedImage. Such an image may be read only as a Raster. If an image is interpretable but there is no Java
|
|
||||||
ColorSpace available corresponding to the encoded colorspace (e.g. YCbCr/YCCK), then ImageReader.getRawImageType
|
|
||||||
will return null.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (adobeDCT != null) {
|
|
||||||
switch (adobeDCT.transform) {
|
|
||||||
case AdobeDCT.YCC:
|
|
||||||
if (startOfFrame.componentsInFrame() != 3) {
|
|
||||||
// This probably means the Adobe marker is bogus
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return JPEGColorSpace.YCbCr;
|
|
||||||
case AdobeDCT.YCCK:
|
|
||||||
if (startOfFrame.componentsInFrame() != 4) {
|
|
||||||
// This probably means the Adobe marker is bogus
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return JPEGColorSpace.YCCK;
|
|
||||||
case AdobeDCT.Unknown:
|
|
||||||
if (startOfFrame.componentsInFrame() == 1) {
|
|
||||||
return JPEGColorSpace.Gray;
|
|
||||||
}
|
|
||||||
else if (startOfFrame.componentsInFrame() == 3) {
|
|
||||||
return JPEGColorSpace.RGB;
|
|
||||||
}
|
|
||||||
else if (startOfFrame.componentsInFrame() == 4) {
|
|
||||||
return JPEGColorSpace.CMYK;
|
|
||||||
}
|
|
||||||
// Else fall through
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: We should probably allow component ids out of order (ie. BGR or KMCY)...
|
|
||||||
switch (startOfFrame.componentsInFrame()) {
|
switch (startOfFrame.componentsInFrame()) {
|
||||||
case 1:
|
case 1:
|
||||||
return JPEGColorSpace.Gray;
|
return JPEGColorSpace.Gray;
|
||||||
case 2:
|
case 2:
|
||||||
return JPEGColorSpace.GrayA;
|
return JPEGColorSpace.GrayA; // Java special case: Gray + Alpha
|
||||||
case 3:
|
case 3:
|
||||||
if (startOfFrame.components[0].id == 1 && startOfFrame.components[1].id == 2 && startOfFrame.components[2].id == 3) {
|
if (jfif != null) {
|
||||||
// NOTE: Due to a bug in JPEGMetadata, standard format will report RGB for non-subsampled, non-JFIF files
|
return JPEGColorSpace.YCbCr; // JFIF implies YCbCr
|
||||||
return JPEGColorSpace.YCbCr;
|
|
||||||
}
|
}
|
||||||
else if (startOfFrame.components[0].id == 'R' && startOfFrame.components[1].id == 'G' && startOfFrame.components[2].id == 'B') {
|
else if (adobeDCT != null) {
|
||||||
return JPEGColorSpace.RGB;
|
switch (adobeDCT.transform) {
|
||||||
}
|
case AdobeDCT.Unknown:
|
||||||
else if (startOfFrame.components[0].id == 'Y' && startOfFrame.components[1].id == 'C' && startOfFrame.components[2].id == 'c') {
|
return JPEGColorSpace.RGB;
|
||||||
return JPEGColorSpace.PhotoYCC;
|
case AdobeDCT.YCC:
|
||||||
}
|
|
||||||
else {
|
|
||||||
// If subsampled, YCbCr else RGB
|
|
||||||
for (Frame.Component component : startOfFrame.components) {
|
|
||||||
if (component.hSub != 1 || component.vSub != 1) {
|
|
||||||
return JPEGColorSpace.YCbCr;
|
return JPEGColorSpace.YCbCr;
|
||||||
}
|
default:
|
||||||
|
// TODO: Warning!
|
||||||
|
return JPEGColorSpace.YCbCr; // assume it's YCbCr
|
||||||
}
|
}
|
||||||
|
|
||||||
return jfif != null ? JPEGColorSpace.YCbCr : JPEGColorSpace.RGB;
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
if (startOfFrame.components[0].id == 1 && startOfFrame.components[1].id == 2 && startOfFrame.components[2].id == 3 && startOfFrame.components[3].id == 4) {
|
|
||||||
// NOTE: Due to a bug in JPEGMetadata, standard format will report RGBA for non-subsampled, non-JFIF files
|
|
||||||
return JPEGColorSpace.YCbCrA;
|
|
||||||
}
|
|
||||||
else if (startOfFrame.components[0].id == 'R' && startOfFrame.components[1].id == 'G' && startOfFrame.components[2].id == 'B' && startOfFrame.components[3].id == 'A') {
|
|
||||||
return JPEGColorSpace.RGBA;
|
|
||||||
}
|
|
||||||
else if (startOfFrame.components[0].id == 'Y' && startOfFrame.components[1].id == 'C' && startOfFrame.components[2].id == 'c' && startOfFrame.components[3].id == 'A') {
|
|
||||||
return JPEGColorSpace.PhotoYCCA;
|
|
||||||
}
|
|
||||||
else if (startOfFrame.components[0].id == 'C' && startOfFrame.components[1].id == 'M' && startOfFrame.components[2].id == 'Y' && startOfFrame.components[3].id == 'K') {
|
|
||||||
return JPEGColorSpace.CMYK;
|
|
||||||
}
|
|
||||||
else if (startOfFrame.components[0].id == 'Y' && startOfFrame.components[1].id == 'C' && startOfFrame.components[2].id == 'c' && startOfFrame.components[3].id == 'K') {
|
|
||||||
return JPEGColorSpace.YCCK;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO: JPEGMetadata (standard format) will report YCbCrA for 4 channel subsampled... :-/
|
// Saw no special markers, try to guess from the component IDs
|
||||||
// If subsampled, YCCK else CMYK
|
int cid0 = startOfFrame.components[0].id;
|
||||||
for (Frame.Component component : startOfFrame.components) {
|
int cid1 = startOfFrame.components[1].id;
|
||||||
if (component.hSub != 1 || component.vSub != 1) {
|
int cid2 = startOfFrame.components[2].id;
|
||||||
return JPEGColorSpace.YCCK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return JPEGColorSpace.CMYK;
|
if (cid0 == 1 && cid1 == 2 && cid2 == 3) {
|
||||||
|
return JPEGColorSpace.YCbCr; // assume JFIF w/out marker
|
||||||
|
}
|
||||||
|
else if (cid0 == 'R' && cid1 == 'G' && cid2 == 'B') {
|
||||||
|
return JPEGColorSpace.RGB; // ASCII 'R', 'G', 'B'
|
||||||
|
}
|
||||||
|
else if (cid0 == 'Y' && cid1 == 'C' && cid2 == 'c') {
|
||||||
|
return JPEGColorSpace.PhotoYCC; // Java special case: YCc
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: Warning!
|
||||||
|
return JPEGColorSpace.YCbCr; // assume it's YCbCr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if (adobeDCT != null) {
|
||||||
|
switch (adobeDCT.transform) {
|
||||||
|
case AdobeDCT.Unknown:
|
||||||
|
return JPEGColorSpace.CMYK;
|
||||||
|
case AdobeDCT.YCCK:
|
||||||
|
return JPEGColorSpace.YCCK;
|
||||||
|
default:
|
||||||
|
// TODO: Warning!
|
||||||
|
return JPEGColorSpace.YCCK; // assume it's YCCK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Saw no special markers, try to guess from the component IDs
|
||||||
|
int cid0 = startOfFrame.components[0].id;
|
||||||
|
int cid1 = startOfFrame.components[1].id;
|
||||||
|
int cid2 = startOfFrame.components[2].id;
|
||||||
|
int cid3 = startOfFrame.components[3].id;
|
||||||
|
|
||||||
|
if (cid0 == 1 && cid1 == 2 && cid2 == 3 && cid3 == 4) {
|
||||||
|
return JPEGColorSpace.YCbCrA; // Java special case: YCbCrA
|
||||||
|
}
|
||||||
|
else if (cid0 == 'R' && cid1 == 'G' && cid2 == 'B' && cid3 == 'A') {
|
||||||
|
return JPEGColorSpace.RGBA; // Java special case: RGBA
|
||||||
|
}
|
||||||
|
else if (cid0 == 'Y' && cid1 == 'C' && cid2 == 'c' && cid3 == 'A') {
|
||||||
|
return JPEGColorSpace.PhotoYCCA; // Java special case: YCcA
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: Warning!
|
||||||
|
// No special markers, assume straight CMYK.
|
||||||
|
return JPEGColorSpace.CMYK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new IIOException("Cannot determine source color space");
|
throw new IIOException("Cannot determine source color space");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user