?? tif_jpeg.c
字號(hào):
if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) return (0); sp->scancount = 0; } tif->tif_row += sp->v_sampling; buf += sp->bytesperline; nrows -= sp->v_sampling; } return (1);}/* * Finish up at the end of a strip or tile. */static intJPEGPostEncode(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 voidJPEGCleanup(TIFF* tif){ JPEGState *sp = JState(tif); assert(sp != 0); tif->tif_tagmethods.vgetfield = sp->vgetparent; tif->tif_tagmethods.vsetfield = sp->vsetparent; tif->tif_tagmethods.printdir = sp->printdir; 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; _TIFFSetDefaultCompressionState(tif);}static void JPEGResetUpsampled( TIFF* tif ){ JPEGState* sp = JState(tif); TIFFDirectory* td = &tif->tif_dir; /* * 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 {#ifdef notdef if (td->td_ycbcrsubsampling[0] != 1 || td->td_ycbcrsubsampling[1] != 1) ; /* XXX what about up-sampling? */#endif } } /* * Must recalculate cached tile size in case sampling state changed. * Should we really be doing this now if image size isn't set? */ tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;}static intJPEGVSetField(TIFF* tif, ttag_t tag, va_list ap){ JPEGState* sp = JState(tif); const TIFFFieldInfo* fip; uint32 v32; assert(sp != NULL); 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); JPEGResetUpsampled( tif ); return (1); /* pseudo tag */ case TIFFTAG_PHOTOMETRIC: { int ret_value = (*sp->vsetparent)(tif, tag, ap); JPEGResetUpsampled( tif ); return ret_value; } 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; /* should we be recomputing upsampling info here? */ return (*sp->vsetparent)(tif, tag, ap); case TIFFTAG_FAXRECVPARAMS: sp->recvparams = va_arg(ap, uint32); break; case TIFFTAG_FAXSUBADDRESS: _TIFFsetString(&sp->subaddress, va_arg(ap, char*)); break; case TIFFTAG_FAXRECVTIME: sp->recvtime = va_arg(ap, uint32); break; case TIFFTAG_FAXDCS: _TIFFsetString(&sp->faxdcs, va_arg(ap, char*)); break; default: return (*sp->vsetparent)(tif, tag, ap); } if ((fip = _TIFFFieldWithTag(tif, tag))) { TIFFSetFieldBit(tif, fip->field_bit); } else { return (0); } 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, 0, 0 ); /* * 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 intJPEGVGetField(TIFF* tif, ttag_t tag, va_list ap){ JPEGState* sp = JState(tif); assert(sp != NULL); switch (tag) { case TIFFTAG_JPEGTABLES: *va_arg(ap, uint32*) = 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); case TIFFTAG_FAXRECVPARAMS: *va_arg(ap, uint32*) = sp->recvparams; break; case TIFFTAG_FAXSUBADDRESS: *va_arg(ap, char**) = sp->subaddress; break; case TIFFTAG_FAXRECVTIME: *va_arg(ap, uint32*) = sp->recvtime; break; case TIFFTAG_FAXDCS: *va_arg(ap, char**) = sp->faxdcs; break; default: return (*sp->vgetparent)(tif, tag, ap); } return (1);}static voidJPEGPrintDir(TIFF* tif, FILE* fd, long flags){ JPEGState* sp = JState(tif); assert(sp != NULL); (void) flags; if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) fprintf(fd, " JPEG Tables: (%lu bytes)\n", (unsigned long) sp->jpegtables_length); if (TIFFFieldSet(tif,FIELD_RECVPARAMS)) fprintf(fd, " Fax Receive Parameters: %08lx\n", (unsigned long) sp->recvparams); if (TIFFFieldSet(tif,FIELD_SUBADDRESS)) fprintf(fd, " Fax SubAddress: %s\n", sp->subaddress); if (TIFFFieldSet(tif,FIELD_RECVTIME)) fprintf(fd, " Fax Receive Time: %lu secs\n", (unsigned long) sp->recvtime); if (TIFFFieldSet(tif,FIELD_FAXDCS)) fprintf(fd, " Fax DCS: %s\n", sp->faxdcs);}static uint32JPEGDefaultStripSize(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 voidJPEGDefaultTileSize(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, int force_encode, int force_decode ){ JPEGState* sp = JState(tif); uint32 *byte_counts = NULL; int data_is_empty = TRUE; int decompress; 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; } if( force_decode ) decompress = 1; else if( force_encode ) decompress = 0; else if( tif->tif_mode == O_RDONLY ) decompress = 1; else if( data_is_empty ) decompress = 0; else decompress = 1; /* * Initialize libjpeg. */ if ( decompress ) { if (!TIFFjpeg_create_decompress(sp)) return (0); } else { if (!TIFFjpeg_create_compress(sp)) return (0); } sp->cinfo_initialized = TRUE; return 1;}intTIFFInitJPEG(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) { TIFFErrorExt(tif->tif_clientdata, "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 */ sp->printdir = tif->tif_tagmethods.printdir; 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->recvparams = 0; sp->subaddress = NULL; sp->faxdcs = NULL; 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; /* ** Create a JPEGTables field if no directory has yet been created. ** We do this just to ensure that sufficient space is reserved for ** the JPEGTables field. It will be properly created the right ** size later. */ if( tif->tif_diroff == 0 ) {#define SIZE_OF_JPEGTABLES 2000 TIFFSetFieldBit(tif, FIELD_JPEGTABLES); sp->jpegtables_length = SIZE_OF_JPEGTABLES; sp->jpegtables = (void *) _TIFFmalloc(sp->jpegtables_length); _TIFFmemset(sp->jpegtables, 0, SIZE_OF_JPEGTABLES);#undef SIZE_OF_JPEGTABLES } /* * 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: */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -