📄 tif_jpeg.c
字号:
/* No work necessary here */ /* Or must we update tif->tif_rawcp, tif->tif_rawcc ??? */ /* (if so, need empty tables_term_source!) */ (void) cinfo;}static voidTIFFjpeg_data_src(JPEGState* sp, TIFF* tif){ (void) tif; sp->cinfo.d.src = &sp->src; sp->src.init_source = std_init_source; sp->src.fill_input_buffer = std_fill_input_buffer; sp->src.skip_input_data = std_skip_input_data; sp->src.resync_to_restart = jpeg_resync_to_restart; sp->src.term_source = std_term_source; sp->src.bytes_in_buffer = 0; /* for safety */ sp->src.next_input_byte = NULL;}/* * Alternate source manager for reading from JPEGTables. * We can share all the code except for the init routine. */static voidtables_init_source(j_decompress_ptr cinfo){ JPEGState* sp = (JPEGState*) cinfo; sp->src.next_input_byte = (const JOCTET*) sp->jpegtables; sp->src.bytes_in_buffer = (size_t) sp->jpegtables_length;}static voidTIFFjpeg_tables_src(JPEGState* sp, TIFF* tif){ TIFFjpeg_data_src(sp, tif); sp->src.init_source = tables_init_source;}/* * Allocate downsampled-data buffers needed for downsampled I/O. * We use values computed in jpeg_start_compress or jpeg_start_decompress. * We use libjpeg's allocator so that buffers will be released automatically * when done with strip/tile. * This is also a handy place to compute samplesperclump, bytesperline. */static intalloc_downsampled_buffers(TIFF* tif, jpeg_component_info* comp_info, int num_components){ JPEGState* sp = JState(tif); int ci; jpeg_component_info* compptr; JSAMPARRAY buf; int samples_per_clump = 0; for (ci = 0, compptr = comp_info; ci < num_components; ci++, compptr++) { samples_per_clump += compptr->h_samp_factor * compptr->v_samp_factor; buf = TIFFjpeg_alloc_sarray(sp, JPOOL_IMAGE, compptr->width_in_blocks * DCTSIZE, (JDIMENSION) (compptr->v_samp_factor*DCTSIZE)); if (buf == NULL) return (0); sp->ds_buffer[ci] = buf; } sp->samplesperclump = samples_per_clump; return (1);}/* * JPEG Decoding. */static intJPEGSetupDecode(TIFF* tif){ JPEGState* sp = JState(tif); TIFFDirectory *td = &tif->tif_dir; assert(sp != NULL); assert(sp->cinfo.comm.is_decompressor); /* Read JPEGTables if it is present */ if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) { TIFFjpeg_tables_src(sp, tif); if(TIFFjpeg_read_header(sp,FALSE) != JPEG_HEADER_TABLES_ONLY) { TIFFError("JPEGSetupDecode", "Bogus JPEGTables field"); return (0); } } /* Grab parameters that are same for all strips/tiles */ sp->photometric = td->td_photometric; switch (sp->photometric) { case PHOTOMETRIC_YCBCR: sp->h_sampling = td->td_ycbcrsubsampling[0]; sp->v_sampling = td->td_ycbcrsubsampling[1]; break; default: /* TIFF 6.0 forbids subsampling of all other color spaces */ sp->h_sampling = 1; sp->v_sampling = 1; break; } /* Set up for reading normal data */ TIFFjpeg_data_src(sp, tif); tif->tif_postdecode = _TIFFNoPostDecode; /* override byte swapping */ return (1);}/* * Set up for decoding a strip or tile. */static intJPEGPreDecode(TIFF* tif, tsample_t s){ JPEGState *sp = JState(tif); TIFFDirectory *td = &tif->tif_dir; static const char module[] = "JPEGPreDecode"; uint32 segment_width, segment_height; int downsampled_output; int ci; assert(sp != NULL); assert(sp->cinfo.comm.is_decompressor); /* * Reset decoder state from any previous strip/tile, * in case application didn't read the whole strip. */ if (!TIFFjpeg_abort(sp)) return (0); /* * Read the header for this strip/tile. */ if (TIFFjpeg_read_header(sp, TRUE) != JPEG_HEADER_OK) return (0); /* * Check image parameters and set decompression parameters. */ segment_width = td->td_imagewidth; segment_height = td->td_imagelength - tif->tif_row; if (isTiled(tif)) { if (segment_height > td->td_tilelength) segment_height = td->td_tilelength; sp->bytesperline = TIFFTileRowSize(tif); } else { if (segment_height > td->td_rowsperstrip) segment_height = td->td_rowsperstrip; sp->bytesperline = TIFFScanlineSize(tif); } if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) { /* * For PC 2, scale down the expected strip/tile size * to match a downsampled component */ segment_width = TIFFhowmany(segment_width, sp->h_sampling); segment_height = TIFFhowmany(segment_height, sp->v_sampling); } if (sp->cinfo.d.image_width != segment_width || sp->cinfo.d.image_height != segment_height) { TIFFError(module, "Improper JPEG strip/tile size"); return (0); } if (sp->cinfo.d.num_components != (td->td_planarconfig == PLANARCONFIG_CONTIG ? td->td_samplesperpixel : 1)) { TIFFError(module, "Improper JPEG component count"); return (0); } if (sp->cinfo.d.data_precision != td->td_bitspersample) { TIFFError(module, "Improper JPEG data precision"); return (0); } if (td->td_planarconfig == PLANARCONFIG_CONTIG) { /* Component 0 should have expected sampling factors */ if (sp->cinfo.d.comp_info[0].h_samp_factor != sp->h_sampling || sp->cinfo.d.comp_info[0].v_samp_factor != sp->v_sampling) { TIFFError(module, "Improper JPEG sampling factors"); return (0); } /* Rest should have sampling factors 1,1 */ for (ci = 1; ci < sp->cinfo.d.num_components; ci++) { if (sp->cinfo.d.comp_info[ci].h_samp_factor != 1 || sp->cinfo.d.comp_info[ci].v_samp_factor != 1) { TIFFError(module, "Improper JPEG sampling factors"); return (0); } } } else { /* PC 2's single component should have sampling factors 1,1 */ if (sp->cinfo.d.comp_info[0].h_samp_factor != 1 || sp->cinfo.d.comp_info[0].v_samp_factor != 1) { TIFFError(module, "Improper JPEG sampling factors"); return (0); } } downsampled_output = FALSE; if (td->td_planarconfig == PLANARCONFIG_CONTIG && sp->photometric == PHOTOMETRIC_YCBCR && sp->jpegcolormode == JPEGCOLORMODE_RGB) { /* Convert YCbCr to RGB */ sp->cinfo.d.jpeg_color_space = JCS_YCbCr; sp->cinfo.d.out_color_space = JCS_RGB; } else { /* Suppress colorspace handling */ sp->cinfo.d.jpeg_color_space = JCS_UNKNOWN; sp->cinfo.d.out_color_space = JCS_UNKNOWN; if (td->td_planarconfig == PLANARCONFIG_CONTIG && (sp->h_sampling != 1 || sp->v_sampling != 1)) downsampled_output = TRUE; /* XXX what about up-sampling? */ } if (downsampled_output) { /* Need to use raw-data interface to libjpeg */ sp->cinfo.d.raw_data_out = TRUE; tif->tif_decoderow = JPEGDecodeRaw; tif->tif_decodestrip = JPEGDecodeRaw; tif->tif_decodetile = JPEGDecodeRaw; } else { /* Use normal interface to libjpeg */ sp->cinfo.d.raw_data_out = FALSE; tif->tif_decoderow = JPEGDecode; tif->tif_decodestrip = JPEGDecode; tif->tif_decodetile = JPEGDecode; } /* Start JPEG decompressor */ if (!TIFFjpeg_start_decompress(sp)) return (0); /* Allocate downsampled-data buffers if needed */ if (downsampled_output) { if (!alloc_downsampled_buffers(tif, sp->cinfo.d.comp_info, sp->cinfo.d.num_components)) return (0); sp->scancount = DCTSIZE; /* mark buffer empty */ } return (1);}/* * Decode a chunk of pixels. * "Standard" case: returned data is not downsampled. *//*ARGSUSED*/ static intJPEGDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s){ JPEGState *sp = JState(tif); tsize_t nrows; /* data is expected to be read in multiples of a scanline */ if (nrows = sp->cinfo.d.image_height) do { JSAMPROW bufptr = (JSAMPROW)buf; if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1) return (0); ++tif->tif_row; buf += sp->bytesperline; cc -= sp->bytesperline; } while (--nrows > 0); /* Close down the decompressor if we've finished the strip or tile. */ return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height || TIFFjpeg_finish_decompress(sp);}/* * Decode a chunk of pixels. * Returned data is downsampled per sampling factors. *//*ARGSUSED*/ static intJPEGDecodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s){ JPEGState *sp = JState(tif); tsize_t nrows; /* data is expected to be read in multiples of a scanline */ if (nrows = sp->cinfo.d.image_height) { /* Cb,Cr both have sampling factors 1, so this is correct */ JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width; int samples_per_clump = sp->samplesperclump; do { jpeg_component_info *compptr; int ci, clumpoffset; /* Reload downsampled-data buffer if needed */ if (sp->scancount >= DCTSIZE) { int n = sp->cinfo.d.max_v_samp_factor * DCTSIZE; if (TIFFjpeg_read_raw_data(sp, sp->ds_buffer, n) != n) return (0); sp->scancount = 0; } /* * Fastest way to unseparate data is to make one pass * over the scanline for each row of each component. */ clumpoffset = 0; /* first sample in clump */ for (ci = 0, compptr = sp->cinfo.d.comp_info; ci < sp->cinfo.d.num_components; ci++, compptr++) { int hsamp = compptr->h_samp_factor; int vsamp = compptr->v_samp_factor; int ypos; for (ypos = 0; ypos < vsamp; ypos++) { JSAMPLE *inptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos]; JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset; JDIMENSION nclump; if (hsamp == 1) { /* fast path for at least Cb and Cr */ for (nclump = clumps_per_line; nclump-- > 0; ) { outptr[0] = *inptr++; outptr += samples_per_clump; } } else { int xpos; /* general case */ for (nclump = clumps_per_line; nclump-- > 0; ) { for (xpos = 0; xpos < hsamp; xpos++) outptr[xpos] = *inptr++; outptr += samples_per_clump; } } clumpoffset += hsamp; } } ++sp->scancount; ++tif->tif_row; buf += sp->bytesperline; cc -= sp->bytesperline; } while (--nrows > 0); } /* Close down the decompressor if done. */ return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height || TIFFjpeg_finish_decompress(sp);}/* * JPEG Encoding. */static voidunsuppress_quant_table (JPEGState* sp, int tblno){ JQUANT_TBL* qtbl; if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL) qtbl->sent_table = FALSE;}static voidunsuppress_huff_table (JPEGState* sp, int tblno){ JHUFF_TBL* htbl; if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL) htbl->sent_table = FALSE; if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL) htbl->sent_table = FALSE;}static intprepare_JPEGTables(TIFF* tif){ JPEGState* sp = JState(tif); /* Initialize quant tables for current quality setting */ if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE)) return (0); /* Mark only the tables we want for output */ /* NB: chrominance tables are currently used only with YCbCr */ if (!TIFFjpeg_suppress_tables(sp, TRUE)) return (0); if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) { unsuppress_quant_table(sp, 0); if (sp->photometric == PHOTOMETRIC_YCBCR) unsuppress_quant_table(sp, 1); } if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) { unsuppress_huff_table(sp, 0); if (sp->photometric == PHOTOMETRIC_YCBCR) unsuppress_huff_table(sp, 1); } /* Direct libjpeg output into jpegtables */ if (!TIFFjpeg_tables_dest(sp, tif)) return (0); /* Emit tables-only datastream */ if (!TIFFjpeg_write_tables(sp)) return (0); return (1);}static intJPEGSetupEncode(TIFF* tif){ JPEGState* sp = JState(tif); TIFFDirectory *td = &tif->tif_dir; static const char module[] = "JPEGSetupEncode"; assert(sp != NULL); assert(!sp->cinfo.comm.is_decompressor); /* * Initialize all JPEG parameters to default values. * Note that jpeg_set_defaults needs legal values for * in_color_space and input_components. */ sp->cinfo.c.in_color_space = JCS_UNKNOWN; sp->cinfo.c.input_components = 1; if (!TIFFjpeg_set_defaults(sp)) return (0); /* Set per-file parameters */ sp->photometric = td->td_photometric; switch (sp->photometric) { case PHOTOMETRIC_YCBCR: sp->h_sampling = td->td_ycbcrsubsampling[0]; sp->v_sampling = td->td_ycbcrsubsampling[1]; /* * A ReferenceBlackWhite field *must* be present since the * default value is inappropriate for YCbCr. Fill in the * proper value if application didn't set it. */#ifdef COLORIMETRY_SUPPORT if (!TIFFFieldSet(tif, FIELD_REFBLACKWHITE)) { float refbw[6]; long top = 1L << td->td_bitspersample; refbw[0] = 0; refbw[1] = (float)(top-1L); refbw[2] = (float)(top>>1); refbw[3] = refbw[1]; refbw[4] = refbw[2]; refbw[5] = refbw[1]; TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE, refbw); }#endif break; case PHOTOMETRIC_PALETTE: /* disallowed by Tech Note */ case PHOTOMETRIC_MASK: TIFFError(module, "PhotometricInterpretation %d not allowed for JPEG", (int) sp->photometric); return (0); default: /* TIFF 6.0 forbids subsampling of all other color spaces */ sp->h_sampling = 1; sp->v_sampling = 1; break; } /* Verify miscellaneous parameters */ /* * This would need work if libtiff ever supports different * depths for different components, or if libjpeg ever supports * run-time selection of depth. Neither is imminent. */ if (td->td_bitspersample != BITS_IN_JSAMPLE) { TIFFError(module, "BitsPerSample %d not allowed for JPEG", (int) td->td_bitspersample); return (0); } sp->cinfo.c.data_precision = td->td_bitspersample; if (isTiled(tif)) { if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) { TIFFError(module, "JPEG tile height must be multiple of %d", sp->v_sampling * DCTSIZE); return (0); } if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) { TIFFError(module, "JPEG tile width must be multiple of %d", sp->h_sampling * DCTSIZE); return (0); } } else { if (td->td_rowsperstrip < td->td_imagelength && (td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0) { TIFFError(module, "RowsPerStrip must be multiple of %d for JPEG", sp->v_sampling * DCTSIZE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -