?? tif_jpeg.c
字號:
/* fast path for at least Cb and Cr */
for (nclump = clumps_per_line; nclump-- > 0; ) {
*outptr++ = inptr[0];
inptr += samples_per_clump;
}
} else {
/* general case */
for (nclump = clumps_per_line; nclump-- > 0; ) {
for (xpos = 0; xpos < hsamp; xpos++)
*outptr++ = inptr[xpos];
inptr += samples_per_clump;
}
}
/* pad each scanline as needed */
for (xpos = 0; xpos < padding; xpos++) {
*outptr = outptr[-1];
outptr++;
}
clumpoffset += hsamp;
}
}
sp->scancount++;
if (sp->scancount >= DCTSIZE) {
int n = sp->cinfo.c.max_v_samp_factor * DCTSIZE;
if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n)
return (0);
sp->scancount = 0;
}
if (nrows > 0)
tif->tif_row++;
buf += sp->bytesperline;
}
return (1);
}
/*
* Finish up at the end of a strip or tile.
*/
static int
JPEGPostEncode(TIFF* tif)
{
JPEGState *sp = JState(tif);
if (sp->scancount > 0) {
/*
* Need to emit a partial bufferload of downsampled data.
* Pad the data vertically.
*/
int ci, ypos, n;
jpeg_component_info* compptr;
for (ci = 0, compptr = sp->cinfo.c.comp_info;
ci < sp->cinfo.c.num_components;
ci++, compptr++) {
int vsamp = compptr->v_samp_factor;
tsize_t row_width = compptr->width_in_blocks * DCTSIZE
* sizeof(JSAMPLE);
for (ypos = sp->scancount * vsamp;
ypos < DCTSIZE * vsamp; ypos++) {
_TIFFmemcpy((tdata_t)sp->ds_buffer[ci][ypos],
(tdata_t)sp->ds_buffer[ci][ypos-1],
row_width);
}
}
n = sp->cinfo.c.max_v_samp_factor * DCTSIZE;
if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n)
return (0);
}
return (TIFFjpeg_finish_compress(JState(tif)));
}
static void
JPEGCleanup(TIFF* tif)
{
if (tif->tif_data) {
JPEGState *sp = JState(tif);
if( sp->cinfo_initialized )
TIFFjpeg_destroy(sp); /* release libjpeg resources */
if (sp->jpegtables) /* tag value */
_TIFFfree(sp->jpegtables);
_TIFFfree(tif->tif_data); /* release local state */
tif->tif_data = NULL;
}
}
static int
JPEGVSetField(TIFF* tif, ttag_t tag, va_list ap)
{
JPEGState* sp = JState(tif);
TIFFDirectory* td = &tif->tif_dir;
uint32 v32;
switch (tag) {
case TIFFTAG_JPEGTABLES:
v32 = va_arg(ap, uint32);
if (v32 == 0) {
/* XXX */
return (0);
}
_TIFFsetByteArray(&sp->jpegtables, va_arg(ap, void*),
(long) v32);
sp->jpegtables_length = v32;
TIFFSetFieldBit(tif, FIELD_JPEGTABLES);
break;
case TIFFTAG_JPEGQUALITY:
sp->jpegquality = va_arg(ap, int);
return (1); /* pseudo tag */
case TIFFTAG_JPEGCOLORMODE:
sp->jpegcolormode = va_arg(ap, int);
/*
* Mark whether returned data is up-sampled or not
* so TIFFStripSize and TIFFTileSize return values
* that reflect the true amount of data.
*/
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[0] != 1 ||
td->td_ycbcrsubsampling[1] != 1)
; /* XXX what about up-sampling? */
}
}
/*
* Must recalculate cached tile size
* in case sampling state changed.
*/
tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
return (1); /* pseudo tag */
case TIFFTAG_JPEGTABLESMODE:
sp->jpegtablesmode = va_arg(ap, int);
return (1); /* pseudo tag */
case TIFFTAG_YCBCRSUBSAMPLING:
/* mark the fact that we have a real ycbcrsubsampling! */
sp->ycbcrsampling_fetched = 1;
return (*sp->vsetparent)(tif, tag, ap);
default:
return (*sp->vsetparent)(tif, tag, ap);
}
tif->tif_flags |= TIFF_DIRTYDIRECT;
return (1);
}
/*
* Some JPEG-in-TIFF produces do not emit the YCBCRSUBSAMPLING values in
* the TIFF tags, but still use non-default (2,2) values within the jpeg
* data stream itself. In order for TIFF applications to work properly
* - for instance to get the strip buffer size right - it is imperative
* that the subsampling be available before we start reading the image
* data normally. This function will attempt to load the first strip in
* order to get the sampling values from the jpeg data stream. Various
* hacks are various places are done to ensure this function gets called
* before the td_ycbcrsubsampling values are used from the directory structure,
* including calling TIFFGetField() for the YCBCRSUBSAMPLING field from
* TIFFStripSize(), and the printing code in tif_print.c.
*
* Note that JPEGPreDeocode() will produce a fairly loud warning when the
* discovered sampling does not match the default sampling (2,2) or whatever
* was actually in the tiff tags.
*
* Problems:
* o This code will cause one whole strip/tile of compressed data to be
* loaded just to get the tags right, even if the imagery is never read.
* It would be more efficient to just load a bit of the header, and
* initialize things from that.
*
* See the bug in bugzilla for details:
*
* http://bugzilla.remotesensing.org/show_bug.cgi?id=168
*
* Frank Warmerdam, July 2002
*/
static void
JPEGFixupTestSubsampling( TIFF * tif )
{
#ifdef CHECK_JPEG_YCBCR_SUBSAMPLING
JPEGState *sp = JState(tif);
TIFFDirectory *td = &tif->tif_dir;
JPEGInitializeLibJPEG( tif );
/*
* Some JPEG-in-TIFF files don't provide the ycbcrsampling tags,
* and use a sampling schema other than the default 2,2. To handle
* this we actually have to scan the header of a strip or tile of
* jpeg data to get the sampling.
*/
if( !sp->cinfo.comm.is_decompressor
|| sp->ycbcrsampling_fetched
|| td->td_photometric != PHOTOMETRIC_YCBCR )
return;
sp->ycbcrsampling_fetched = 1;
if( TIFFIsTiled( tif ) )
{
if( !TIFFFillTile( tif, 0 ) )
return;
}
else
{
if( !TIFFFillStrip( tif, 0 ) )
return;
}
TIFFSetField( tif, TIFFTAG_YCBCRSUBSAMPLING,
(uint16) sp->h_sampling, (uint16) sp->v_sampling );
#endif /* CHECK_JPEG_YCBCR_SUBSAMPLING */
}
static int
JPEGVGetField(TIFF* tif, ttag_t tag, va_list ap)
{
JPEGState* sp = JState(tif);
switch (tag) {
case TIFFTAG_JPEGTABLES:
/* unsigned short is bogus --- should be uint32 ??? */
/* TIFFWriteNormalTag needs fixed XXX */
*va_arg(ap, unsigned short*) =
(unsigned short) sp->jpegtables_length;
*va_arg(ap, void**) = sp->jpegtables;
break;
case TIFFTAG_JPEGQUALITY:
*va_arg(ap, int*) = sp->jpegquality;
break;
case TIFFTAG_JPEGCOLORMODE:
*va_arg(ap, int*) = sp->jpegcolormode;
break;
case TIFFTAG_JPEGTABLESMODE:
*va_arg(ap, int*) = sp->jpegtablesmode;
break;
case TIFFTAG_YCBCRSUBSAMPLING:
JPEGFixupTestSubsampling( tif );
return (*sp->vgetparent)(tif, tag, ap);
break;
default:
return (*sp->vgetparent)(tif, tag, ap);
}
return (1);
}
static void
JPEGPrintDir(TIFF* tif, FILE* fd, long flags)
{
JPEGState* sp = JState(tif);
(void) flags;
if (TIFFFieldSet(tif,FIELD_JPEGTABLES))
fprintf(fd, " JPEG Tables: (%lu bytes)\n",
(unsigned long) sp->jpegtables_length);
}
static uint32
JPEGDefaultStripSize(TIFF* tif, uint32 s)
{
JPEGState* sp = JState(tif);
TIFFDirectory *td = &tif->tif_dir;
s = (*sp->defsparent)(tif, s);
if (s < td->td_imagelength)
s = TIFFroundup(s, td->td_ycbcrsubsampling[1] * DCTSIZE);
return (s);
}
static void
JPEGDefaultTileSize(TIFF* tif, uint32* tw, uint32* th)
{
JPEGState* sp = JState(tif);
TIFFDirectory *td = &tif->tif_dir;
(*sp->deftparent)(tif, tw, th);
*tw = TIFFroundup(*tw, td->td_ycbcrsubsampling[0] * DCTSIZE);
*th = TIFFroundup(*th, td->td_ycbcrsubsampling[1] * DCTSIZE);
}
/*
* The JPEG library initialized used to be done in TIFFInitJPEG(), but
* now that we allow a TIFF file to be opened in update mode it is necessary
* to have some way of deciding whether compression or decompression is
* desired other than looking at tif->tif_mode. We accomplish this by
* examining {TILE/STRIP}BYTECOUNTS to see if there is a non-zero entry.
* If so, we assume decompression is desired.
*
* This is tricky, because TIFFInitJPEG() is called while the directory is
* being read, and generally speaking the BYTECOUNTS tag won't have been read
* at that point. So we try to defer jpeg library initialization till we
* do have that tag ... basically any access that might require the compressor
* or decompressor that occurs after the reading of the directory.
*
* In an ideal world compressors or decompressors would be setup
* at the point where a single tile or strip was accessed (for read or write)
* so that stuff like update of missing tiles, or replacement of tiles could
* be done. However, we aren't trying to crack that nut just yet ...
*
* NFW, Feb 3rd, 2003.
*/
static int JPEGInitializeLibJPEG( TIFF * tif )
{
JPEGState* sp = JState(tif);
uint32 *byte_counts = NULL;
int data_is_empty = TRUE;
if( sp->cinfo_initialized )
return 1;
/*
* Do we have tile data already? Make sure we initialize the
* the state in decompressor mode if we have tile data, even if we
* are not in read-only file access mode.
*/
if( TIFFIsTiled( tif )
&& TIFFGetField( tif, TIFFTAG_TILEBYTECOUNTS, &byte_counts )
&& byte_counts != NULL )
{
data_is_empty = byte_counts[0] == 0;
}
if( !TIFFIsTiled( tif )
&& TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &byte_counts)
&& byte_counts != NULL )
{
data_is_empty = byte_counts[0] == 0;
}
/*
* Initialize libjpeg.
*/
if (tif->tif_mode == O_RDONLY || !data_is_empty ) {
if (!TIFFjpeg_create_decompress(sp))
return (0);
} else {
if (!TIFFjpeg_create_compress(sp))
return (0);
}
sp->cinfo_initialized = TRUE;
return 1;
}
int
TIFFInitJPEG(TIFF* tif, int scheme)
{
JPEGState* sp;
assert(scheme == COMPRESSION_JPEG);
/*
* Allocate state block so tag methods have storage to record values.
*/
tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (JPEGState));
if (tif->tif_data == NULL) {
TIFFError("TIFFInitJPEG", "No space for JPEG state block");
return (0);
}
_TIFFmemset( tif->tif_data, 0, sizeof(JPEGState));
sp = JState(tif);
sp->tif = tif; /* back link */
/*
* Merge codec-specific tag information and
* override parent get/set field methods.
*/
_TIFFMergeFieldInfo(tif, jpegFieldInfo, N(jpegFieldInfo));
sp->vgetparent = tif->tif_tagmethods.vgetfield;
tif->tif_tagmethods.vgetfield = JPEGVGetField; /* hook for codec tags */
sp->vsetparent = tif->tif_tagmethods.vsetfield;
tif->tif_tagmethods.vsetfield = JPEGVSetField; /* hook for codec tags */
tif->tif_tagmethods.printdir = JPEGPrintDir; /* hook for codec tags */
/* Default values for codec-specific fields */
sp->jpegtables = NULL;
sp->jpegtables_length = 0;
sp->jpegquality = 75; /* Default IJG quality */
sp->jpegcolormode = JPEGCOLORMODE_RAW;
sp->jpegtablesmode = JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF;
sp->ycbcrsampling_fetched = 0;
/*
* Install codec methods.
*/
tif->tif_setupdecode = JPEGSetupDecode;
tif->tif_predecode = JPEGPreDecode;
tif->tif_decoderow = JPEGDecode;
tif->tif_decodestrip = JPEGDecode;
tif->tif_decodetile = JPEGDecode;
tif->tif_setupencode = JPEGSetupEncode;
tif->tif_preencode = JPEGPreEncode;
tif->tif_postencode = JPEGPostEncode;
tif->tif_encoderow = JPEGEncode;
tif->tif_encodestrip = JPEGEncode;
tif->tif_encodetile = JPEGEncode;
tif->tif_cleanup = JPEGCleanup;
sp->defsparent = tif->tif_defstripsize;
tif->tif_defstripsize = JPEGDefaultStripSize;
sp->deftparent = tif->tif_deftilesize;
tif->tif_deftilesize = JPEGDefaultTileSize;
tif->tif_flags |= TIFF_NOBITREV; /* no bit reversal, please */
sp->cinfo_initialized = FALSE;
/*
* Mark the TIFFTAG_YCBCRSAMPLES as present even if it is not
* see: JPEGFixupTestSubsampling().
*/
TIFFSetFieldBit( tif, FIELD_YCBCRSUBSAMPLING );
return (1);
}
#endif /* JPEG_SUPPORT */
/* vim: set ts=8 sts=8 sw=8 noet: */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -