📄 tif_ojpeg.c
字号:
TIFFError(module,"JPEG tile height must be multiple of %d", sp->v_sampling*DCTSIZE); return 0; }; if (td->td_tilewidth % (sp->h_sampling*DCTSIZE)) { 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)) ) { TIFFError(module,"RowsPerStrip must be multiple of %d for JPEG", sp->v_sampling*DCTSIZE); return 0; }; if (sp->jpegtablesmode & (JPEGTABLESMODE_QUANT|JPEGTABLESMODE_HUFF)) { /* create a JPEGTables field */ if (!prepare_JPEGTables(tif)) return 0; /* Mark the field "present". We can't use "TIFFSetField()" because "BEENWRITING" is already set! */ TIFFSetFieldBit(tif,FIELD_JPEGTABLES); tif->tif_flags |= TIFF_DIRTYDIRECT; } else /* We do not support application-supplied JPEG tables, so mark the field "not present". */ TIFFClrFieldBit(tif,FIELD_JPEGTABLES); TIFFojpeg_data_dest(sp,tif); /* send JPEG output to TIFF Library's buffer */ return 1;# undef td }/*ARGSUSED*/ static intOJPEGEncode(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s) { register OJPEGState *sp = OJState(tif); /* Encode a chunk of pixels, where returned data is NOT down-sampled (the standard case). The data is expected to be written in scan-line multiples. */ if (cc % sp->bytesperline) TIFFWarning(tif->tif_name,no_write_frac); cc /= sp->bytesperline; while (--cc >= 0) { JSAMPROW bufptr = (JSAMPROW)buf; if (TIFFojpeg_write_scanlines(sp,&bufptr,1) != 1) return 0; ++tif->tif_row; buf += sp->bytesperline; }; return 1; }/*ARGSUSED*/ static intOJPEGEncodeRaw(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s) { register OJPEGState *sp = OJState(tif); /* Encode a chunk of pixels, where returned data is down-sampled as per the sampling factors. The data is expected to be written in scan-line multiples. */ if (cc % sp->bytesperline) TIFFWarning(tif->tif_name,no_write_frac); cc /= sp->bytesperline; while (--cc >= 0) { if (sp->cinfo.c.num_components > 0) { int ci = 0, clumpoffset = 0; register jpeg_component_info *compptr = sp->cinfo.c.comp_info; /* The fastest way to separate the data is to make 1 pass over the scan line for each row of each component. */ do { int ypos = 0; do { int padding; register JSAMPLE *inptr = (JSAMPLE*)buf + clumpoffset, *outptr = sp->ds_buffer[ci][sp->scancount*compptr->v_samp_factor+ypos]; /* Cb,Cr both have sampling factors 1, so this is correct */ register int clumps_per_line = sp->cinfo.c.comp_info[1].downsampled_width, xpos; padding = (int) ( compptr->width_in_blocks * DCTSIZE - clumps_per_line * compptr->h_samp_factor ); if (compptr->h_samp_factor == 1) /* Cb & Cr fast path */ do { *outptr++ = inptr[0]; inptr += sp->samplesperclump; } while (--clumps_per_line > 0); else /* general case */ do { xpos = 0; do *outptr++ = inptr[xpos]; while (++xpos < compptr->h_samp_factor); inptr += sp->samplesperclump; } while (--clumps_per_line > 0); xpos = 0; /* Pad each scan line as needed */ do outptr[0]=outptr[-1]; while (++outptr,++xpos < padding); clumpoffset += compptr->h_samp_factor; } while (++ypos < compptr->v_samp_factor); } while (++compptr,++ci < sp->cinfo.c.num_components); }; if (++sp->scancount >= DCTSIZE) { int n = sp->cinfo.c.max_v_samp_factor*DCTSIZE; if (TIFFojpeg_write_raw_data(sp,sp->ds_buffer,n) != n) return 0; sp->scancount = 0; }; ++tif->tif_row++ buf += sp->bytesperline; }; return 1; }static intOJPEGPreEncode(register TIFF *tif,tsample_t s) { static const char module[]={"OJPEGPreEncode"}; uint32 segment_width, segment_height; int downsampled_input = FALSE; register OJPEGState *sp = OJState(tif);# define td (&tif->tif_dir) /* Set encoding state at the start of a strip or tile. */ if (td->td_planarconfig == PLANARCONFIG_CONTIG) { sp->cinfo.c.input_components = td->td_samplesperpixel; if (sp->photometric == PHOTOMETRIC_YCBCR) { if (sp->jpegcolormode == JPEGCOLORMODE_RGB) sp->cinfo.c.in_color_space = JCS_RGB; else { sp->cinfo.c.in_color_space = JCS_YCbCr; if (sp->h_sampling != 1 || sp->v_sampling != 1) downsampled_input = TRUE; }; if (!TIFFojpeg_set_colorspace(sp,JCS_YCbCr)) return 0; /* Set Y sampling factors; we assume "jpeg_set_colorspace()" set the rest to 1. */ sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling; sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling; } else { sp->cinfo.c.in_color_space = JCS_UNKNOWN; if (!TIFFojpeg_set_colorspace(sp,JCS_UNKNOWN)) return 0; /* "jpeg_set_colorspace()" set all sampling factors to 1. */ } } else { sp->cinfo.c.input_components = 1; sp->cinfo.c.in_color_space = JCS_UNKNOWN; if (!TIFFojpeg_set_colorspace(sp,JCS_UNKNOWN)) return 0; sp->cinfo.c.comp_info[0].component_id = s; /* "jpeg_set_colorspace()" set all sampling factors to 1. */ if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) sp->cinfo.c.comp_info[0].quant_tbl_no = sp->cinfo.c.comp_info[0].dc_tbl_no = sp->cinfo.c.comp_info[0].ac_tbl_no = 1; }; if (isTiled(tif)) { segment_width = td->td_tilewidth; segment_height = td->td_tilelength; sp->bytesperline = TIFFTileRowSize(tif); } else { segment_width = td->td_imagewidth; segment_height = td->td_imagelength - tif->tif_row; if (segment_height > td->td_rowsperstrip) segment_height = td->td_rowsperstrip; sp->bytesperline = TIFFScanlineSize(tif); }; if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) { /* Scale 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 (segment_width > 65535 || segment_height > 65535) { TIFFError(module,"Strip/tile too large for JPEG"); return 0; }; sp->cinfo.c.image_width = segment_width; sp->cinfo.c.image_height = segment_height; sp->cinfo.c.write_JFIF_header = /* Don't write extraneous markers */ sp->cinfo.c.write_Adobe_marker = FALSE; if (!(sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) /* setup table handling */ { if (!TIFFojpeg_set_quality(sp,sp->jpegquality,FALSE)) return 0; unsuppress_quant_table(sp,0); unsuppress_quant_table(sp,1); }; sp->cinfo.c.optimize_coding = !(sp->jpegtablesmode & JPEGTABLESMODE_HUFF); tif->tif_encoderow = tif->tif_encodestrip = tif->tif_encodetile = (sp->cinfo.c.raw_data_in = downsampled_input) ? OJPEGEncodeRaw : OJPEGEncode; if ( !TIFFojpeg_start_compress(sp,FALSE) /* start JPEG compressor */ || downsampled_input /* allocate downsampled-data buffers */ && !alloc_downsampled_buffers(tif,sp->cinfo.c.comp_info, sp->cinfo.c.num_components) ) return 0; sp->scancount = 0; return 1;# undef td }static intOJPEGPostEncode(register TIFF *tif) { register OJPEGState *sp = OJState(tif); /* Finish up at the end of a strip or tile. */ if (sp->scancount > 0) /* emit partial buffer of down-sampled data */ { if (sp->scancount < DCTSIZE && sp->cinfo.c.num_components > 0) { int ci = 0, n; /* Pad the data vertically */ register jpeg_component_info *compptr = sp->cinfo.c.comp_info; do { tsize_t row_width = compptr->width_in_blocks*DCTSIZE*sizeof(JSAMPLE); int ypos = sp->scancount*compptr->v_samp_factor; do _TIFFmemcpy( (tdata_t)sp->ds_buffer[ci][ypos] , (tdata_t)sp->ds_buffer[ci][ypos-1] , row_width ); while (++ypos < compptr->v_samp_factor*DCTSIZE); } while (++compptr,++ci < sp->cinfo.c.num_components); }; n = sp->cinfo.c.max_v_samp_factor*DCTSIZE; if (TIFFojpeg_write_raw_data(sp,sp->ds_buffer,n) != n) return 0; }; return TIFFojpeg_finish_compress(sp); }#endif /* never *//* JPEG Decoding begins here. */static intOJPEGSetupDecode(register TIFF *tif) { static const char module[]={"OJPEGSetupDecode"}; register OJPEGState *sp = OJState(tif);# define td (&tif->tif_dir) /* Verify miscellaneous parameters. This will need work if the TIFF Library ever supports different depths for different components, or if the JPEG Library ever supports run-time depth selection. Neither seems imminent. */ if (td->td_bitspersample != BITS_IN_JSAMPLE) { TIFFError(module,bad_bps,td->td_bitspersample); return 0; }; /* Almost all old JPEG-in-TIFF encapsulations use 8 bits per sample, but the following is just a "sanity check", since "OJPEGPreDecode()" actually depends upon this assumption in certain cases. */ if (td->td_bitspersample != 8) { TIFFError(module,"Cannot decompress %u bits per sample"); return 0; }; /* Grab parameters that are same for all strips/tiles. */ if ((sp->photometric = td->td_photometric) == PHOTOMETRIC_YCBCR) { sp->h_sampling = td->td_ycbcrsubsampling[0]; sp->v_sampling = td->td_ycbcrsubsampling[1]; } else /* TIFF 6.0 forbids subsampling of all other color spaces */ sp->h_sampling = sp->v_sampling = 1; 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; tif->tif_postdecode = _TIFFNoPostDecode; /* Override Byte-swapping */ return 1;# undef td }/*ARGSUSED*/ static intOJPEGDecode(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s) { static float zeroes[6]; tsize_t nrows; register OJPEGState *sp = OJState(tif); /* 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -