Applied big patch from Scott for TIFFTAG_JPEGCOLORMODE support.

Did some surgery on "OJPEGDecode()" to handle Zack the Cat's problems,
and to copy the Wang color-correction hack that Scott previously put only in
"OJPEGDecodeRaw()".  Also corrected a couple of small bugs elsewhere in the
module.
This commit is contained in:
Frank Warmerdam 2001-09-08 16:58:17 +00:00
parent 335d2428c1
commit 0759b2fbf9

View File

@ -27,8 +27,8 @@
#ifdef FAR
#undef FAR /* Undefine FAR to avoid conflict with JPEG definition */
#endif
#undef INLINE
#define JPEG_INTERNALS /* Include "jpegint.h" for "DSTATE_*" symbols */
#undef INLINE
#include "jpeglib.h"
#undef JPEG_INTERNALS
@ -57,6 +57,7 @@ extern void jpeg_reset_huff_decode(j_decompress_ptr,float *);
#define FIELD_JPEGDCTABLES (FIELD_CODEC+8)
#define FIELD_JPEGACTABLES (FIELD_CODEC+9)
#define FIELD_WANG_PAGECONTROL (FIELD_CODEC+10)
#define FIELD_JPEGCOLORMODE (FIELD_CODEC+11)
typedef struct jpeg_destination_mgr jpeg_destination_mgr;
typedef struct jpeg_source_mgr jpeg_source_mgr;
@ -84,7 +85,7 @@ typedef struct /* This module's private, per-image state variable */
# ifdef never
/* (The following two fields could be a "union", but they're small enough that
it's not worth the effort.
it's not worth the effort.)
*/
jpeg_destination_mgr dest; /* Destination for compressed data */
# endif
@ -106,7 +107,10 @@ typedef struct /* This module's private, per-image state variable */
v_sampling,
photometric; /* Copy of "PhotometricInterpretation" tag value */
u_char is_WANG, /* <=> Microsoft Wang Imaging for Windows output file? */
jpegcolormode; /* <=> Automatic RGB <-> YCbCr conversion? */
jpegcolormode; /* Who performs RGB <-> YCbCr conversion? */
/* JPEGCOLORMODE_RAW <=> TIFF Library does conversion */
/* JPEGCOLORMODE_RGB <=> JPEG Library does conversion */
} OJPEGState;
#define OJState(tif)((OJPEGState*)(tif)->tif_data)
@ -171,6 +175,17 @@ static const TIFFFieldInfo ojpegFieldInfo[]= /* JPEG-specific TIFF-record tags *
TIFFTAG_WANG_PAGECONTROL ,1 ,1 ,
TIFF_LONG ,FIELD_WANG_PAGECONTROL ,FALSE,FALSE,"WANG PageControl"
},
/* This is a pseudo tag intended for internal use only by the TIFF Library and
its clients, which should never appear in an input/output image file. It
specifies whether the TIFF Library will perform YCbCr<->RGB color-space
conversion (JPEGCOLORMODE_RAW <=> 0) or ask the JPEG Library to do it
(JPEGCOLORMODE_RGB <=> 1).
*/
{
TIFFTAG_JPEGCOLORMODE ,0 ,0 ,
TIFF_ANY ,FIELD_PSEUDO ,FALSE,FALSE,"JPEGColorMode"
}
};
static const char JPEGLib_name[]={"JPEG Library"},
bad_bps[]={"%u BitsPerSample not allowed for JPEG"},
@ -945,19 +960,50 @@ OJPEGSetupDecode(register TIFF *tif)
OJPEGDecode(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s)
{ tsize_t nrows;
register OJPEGState *sp = OJState(tif);
# ifndef COLORIMETRY_SUPPORT
static float zeroes[6];
/* BEWARE OF KLUDGE: If our input file was produced by Microsoft's Wang
Imaging for Windows application, the DC coefficients of
each JPEG image component (Y,Cb,Cr) must be reset at the beginning of each
TIFF "strip", and any JPEG data bits remaining in the decoder's input buffer
must be discarded, up to the next input-Byte storage boundary. To do so, we
create an "ad hoc" interface in the "jdhuff.c" module of IJG JPEG Library
Version 6, and we invoke that interface here before decoding each "strip".
*/
if (sp->is_WANG) jpeg_reset_huff_decode(&sp->cinfo.d,zeroes);
# else /* COLORIMETRY_SUPPORT */
if (sp->is_WANG)
jpeg_reset_huff_decode(&sp->cinfo.d,tif->tif_dir.td_refblackwhite);
# endif
/* Decode a chunk of pixels, where returned data is NOT down-sampled (the
standard case). The data is expected to be read in scan-line multiples.
*/
if (nrows = sp->cinfo.d.image_height)
do
{ JSAMPROW bufptr = (JSAMPROW)buf;
{ unsigned int bytesperline = isTiled(tif)
? TIFFTileRowSize(tif)
: TIFFScanlineSize(tif);
if (TIFFojpeg_read_scanlines(sp,&bufptr,1) != 1) return 0;
++tif->tif_row;
buf += sp->bytesperline;
}
while ((cc -= sp->bytesperline) > 0 && --nrows > 0);
/* WARNING: Unlike "OJPEGDecodeRaw()", below, the no. of Bytes in each
decoded row is calculated here as "bytesperline" instead of
using "sp->bytesperline", which might be a little smaller. This can
occur for an old tiled image whose width isn't a multiple of 8 pixels.
That's illegal according to the TIFF Version 6 specification, but some
test files, like "zackthecat.tif", were built that way. In those cases,
we want to embed the image's true width in our caller's buffer (which is
presumably allocated according to the expected tile width) by
effectively "padding" it with unused Bytes at the end of each row.
*/
do
{ JSAMPROW bufptr = (JSAMPROW)buf;
if (TIFFojpeg_read_scanlines(sp,&bufptr,1) != 1) return 0;
buf += bytesperline;
++tif->tif_row;
}
while ((cc -= bytesperline) > 0 && --nrows > 0);
}
return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height
|| TIFFojpeg_finish_decompress(sp);
}
@ -1048,8 +1094,8 @@ OJPEGDecodeRaw(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s)
while (++compptr,++ci < sp->cinfo.d.num_components);
};
++sp->scancount;
++tif->tif_row;
buf += sp->bytesperline;
++tif->tif_row;
}
while ((cc -= sp->bytesperline) > 0 && --nrows > 0);
return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height
@ -1118,7 +1164,7 @@ OJPEGPreDecode(register TIFF *tif,tsample_t s)
case PHOTOMETRIC_SEPARATED : in_color_space = JCS_CMYK;
break;
case PHOTOMETRIC_YCBCR : in_color_space = JCS_YCbCr;
/* Convert YCbCr to RGB? */
/* JPEG Library converts YCbCr to RGB? */
if ( sp->jpegcolormode
== JPEGCOLORMODE_RGB
) downsampled_output = FALSE;
@ -1309,6 +1355,7 @@ OJPEGPreDecode(register TIFF *tif,tsample_t s)
p = (unsigned char *)sp->jpegtables + sp->jpegtables_length;
p[-2] = 0xFF; p[-1] = JPEG_EOI; /* Append EOI marker */
TIFFSetFieldBit(tif,FIELD_JPEGTABLES);
tif->tif_flags |= TIFF_DIRTYDIRECT;
}
else sp->jpegtables = 0; /* Don't simulate "JPEGTables" */
if (TIFFojpeg_read_header(sp,TRUE) != JPEG_HEADER_OK) return 0;
@ -1480,12 +1527,40 @@ OJPEGPreDecode(register TIFF *tif,tsample_t s)
sp->src.bytes_in_buffer = td->td_stripoffset[i] -
td->td_stripoffset[0] + td->td_stripbytecount[i];
/* Force the TIFF Library to create a default array of reference black
and white levels in case our input file doesn't define them, since
we need these for our "jpeg_reset_huff_decode()" hook into the JPEG
Library.
/* We need reference black levels for our "jpeg_reset_huff_decode()"
hook into the JPEG Library, so create a default array of reference
black and white levels in case our input file doesn't define them.
BOGOSITY ALERT! Microsoft's Wang Imaging application seems to alter
the intensity and hue of JPEG images when it
encapsulates them in TIFF files, and the exact reason/algorithm is
currently unknown to this author (is it a bug?), but we try to
correct them by debiassing, using the DC coefficient of each image
component (the 0th element of each JPEG quantization table)
weighted by the corresponding CCIR 601-1 luminance coefficient
(this is strictly a wild-ass guess at what Microsoft might have
screwed up). Experiments with a few test images indicate that this
does not produce an exact correction, but it is reasonably close.
Can someone else figure out a better algorithm?
*/
(void)TIFFGetFieldDefaulted(tif,TIFFTAG_REFERENCEBLACKWHITE,&refbw);
if (!TIFFGetFieldDefaulted(tif,TIFFTAG_REFERENCEBLACKWHITE,&refbw))
{
TIFFError(tif->tif_name,"Can't extract reference black and white levels");
return 0;
};
if (refbw[0] == 0.0 && refbw[2] == 0.0 && refbw[4] == 0.0)
{ /* default reference black levels */
refbw[2] =
sp->cinfo.d.quant_tbl_ptrs[sp->cinfo.d.comp_info[1].quant_tbl_no]
->quantval[0] * 1.402;
refbw[4] =
sp->cinfo.d.quant_tbl_ptrs[sp->cinfo.d.comp_info[2].quant_tbl_no]
->quantval[0] * 1.772;
refbw[0] =
refbw[2] + refbw[4] -
sp->cinfo.d.quant_tbl_ptrs[sp->cinfo.d.comp_info[0].quant_tbl_no]
->quantval[0];
};
i = TIFFojpeg_read_header(sp,TRUE);
};
if (i != JPEG_HEADER_OK) return 0;
@ -1518,6 +1593,7 @@ static int
OJPEGVSetField(register TIFF *tif,ttag_t tag,va_list ap)
{ uint32 v32;
register OJPEGState *sp = OJState(tif);
# define td (&tif->tif_dir)
switch (tag)
{
@ -1532,7 +1608,8 @@ OJPEGVSetField(register TIFF *tif,ttag_t tag,va_list ap)
case TIFFTAG_JPEGQTABLES :
case TIFFTAG_JPEGDCTABLES :
case TIFFTAG_JPEGACTABLES :
case TIFFTAG_WANG_PAGECONTROL : ;
case TIFFTAG_WANG_PAGECONTROL :
case TIFFTAG_JPEGCOLORMODE : ;
};
v32 = va_arg(ap,uint32); /* No. of values in this TIFF record */
@ -1688,9 +1765,41 @@ OJPEGVSetField(register TIFF *tif,ttag_t tag,va_list ap)
};
sp->is_WANG = 1;
tag = TIFFTAG_JPEGPROC+FIELD_WANG_PAGECONTROL-FIELD_JPEGPROC;
break;
/* This pseudo tag indicates whether we think that our caller is supposed
to do YCbCr<->RGB color-space conversion (JPEGCOLORMODE_RAW <=> 0) or
whether we must ask the JPEG Library to do it (JPEGCOLORMODE_RGB <=> 1).
*/
case TIFFTAG_JPEGCOLORMODE :
sp->jpegcolormode = v32;
/* Mark the image to indicate whether returned data is up-sampled, so
that "TIFF{Strip,Tile}Size()" reflect the true amount of data present.
*/
v32 = tif->tif_flags; /* Save flags temporarily */
tif->tif_flags &= ~TIFF_UPSAMPLED;
if (td->td_planarconfig == PLANARCONFIG_CONTIG)
if ( td->td_photometric == PHOTOMETRIC_YCBCR
&& sp->jpegcolormode == JPEGCOLORMODE_RGB
) tif->tif_flags |= TIFF_UPSAMPLED;
else
if ( (td->td_ycbcrsubsampling[1]<<16|td->td_ycbcrsubsampling[0])
!= (1 << 16 | 1)
) /* XXX what about up-sampling? */;
/* If the up-sampling state changed, re-calculate tile size. */
if ((tif->tif_flags ^ v32) & TIFF_UPSAMPLED)
{
tif->tif_tilesize = TIFFTileSize(tif);
tif->tif_flags |= TIFF_DIRTYDIRECT;
};
return 1;
};
TIFFSetFieldBit(tif,tag-TIFFTAG_JPEGPROC+FIELD_JPEGPROC);
return 1;
# undef td
}
static int
@ -1713,6 +1822,14 @@ OJPEGVGetField(register TIFF *tif,ttag_t tag,va_list ap)
return 1;
};
/* This pseudo tag indicates whether we think that our caller is supposed
to do YCbCr<->RGB color-space conversion (JPEGCOLORMODE_RAW <=> 0) or
whether we must ask the JPEG Library to do it (JPEGCOLORMODE_RGB <=> 1).
*/
case TIFFTAG_JPEGCOLORMODE :
*va_arg(ap,uint32 *) = sp->jpegcolormode;
return 1;
/* The following tags are defined by the TIFF Version 6.0 specification
and are obsolete. If our caller asks for information about them, do not
return anything, even if we parsed them in an old-format "source" image.