📄 tif_ojpeg.c
字号:
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)# ifdef C_LOSSLESS_SUPPORTED ( compptr->width_in_data_units * size# else ( compptr->width_in_blocks * size# endif - clumps_per_line * compptr->h_samp_factor ); if (compptr->h_samp_factor == 1) /* Cb & Cr fast path */ do *outptr++ = *inptr; while ((inptr += sp->samplesperclump),--clumps_per_line > 0); else /* general case */ do { xpos = 0; do *outptr++ = inptr[xpos]; while (++xpos < compptr->h_samp_factor); } while ((inptr += sp->samplesperclump),--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 >= size) { if ( CALLJPEG(sp,-1,jpeg_write_raw_data(&sp->cinfo.c,sp->ds_buffer,lines_per_MCU)) != lines_per_MCU ) return 0; sp->scancount = 0; }; ++tif->tif_row++ buf += sp->bytesperline; }; return 1; }static intOJPEGSetupEncode(register TIFF *tif) { static const char module[]={"OJPEGSetupEncode"}; uint32 segment_height, segment_width; int status = 1; /* Assume success by default */ 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 != 8) { TIFFError(module,bad_bps,td->td_bitspersample); status = 0; }; /* The TIFF Version 6.0 specification and IJG JPEG Library accept different sets of color spaces, so verify that our image belongs to the common subset and map its photometry code, then initialize to handle subsampling and optional JPEG Library YCbCr <-> RGB color-space conversion. */ switch (td->td_photometric) { case PHOTOMETRIC_YCBCR : /* ISO IS 10918-1 requires that JPEG subsampling factors be 1-4, but TIFF Version 6.0 is more restrictive: only 1, 2, and 4 are allowed. */ if ( ( td->td_ycbcrsubsampling[0] == 1 || td->td_ycbcrsubsampling[0] == 2 || td->td_ycbcrsubsampling[0] == 4 ) && ( td->td_ycbcrsubsampling[1] == 1 || td->td_ycbcrsubsampling[1] == 2 || td->td_ycbcrsubsampling[1] == 4 ) ) sp->cinfo.c.raw_data_in = ( (sp->h_sampling = td->td_ycbcrsubsampling[0]) << 3 | (sp->v_sampling = td->td_ycbcrsubsampling[1]) ) != 011; else { TIFFError(module,bad_subsampling); status = 0; }; /* A ReferenceBlackWhite field MUST be present, since the default value is inapproriate for YCbCr. Fill in the proper value if the application didn't set it. */ 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); }; sp->cinfo.c.jpeg_color_space = JCS_YCbCr; if (sp->jpegcolormode == JPEGCOLORMODE_RGB) { sp->cinfo.c.raw_data_in = FALSE; sp->in_color_space = JCS_RGB; break; }; goto L2; case PHOTOMETRIC_MINISBLACK: sp->cinfo.c.jpeg_color_space = JCS_GRAYSCALE; goto L1; case PHOTOMETRIC_RGB : sp->cinfo.c.jpeg_color_space = JCS_RGB; goto L1; case PHOTOMETRIC_SEPARATED : sp->cinfo.c.jpeg_color_space = JCS_CMYK; L1: sp->jpegcolormode = JPEGCOLORMODE_RAW; /* No JPEG Lib. conversion */ L2: sp->cinfo.d.in_color_space = sp->cinfo.d.jpeg_color-space; break; default : TIFFError(module,bad_photometry,td->td_photometric); status = 0; }; tif->tif_encoderow = tif->tif_encodestrip = tif->tif_encodetile = sp->cinfo.c.raw_data_in ? OJPEGEncodeRaw : OJPEGEncode; if (isTiled(tif)) { tsize_t size;# ifdef C_LOSSLESS_SUPPORTED if ((size = sp->v_sampling*sp->cinfo.c.data_unit) < 16) size = 16;# else if ((size = sp->v_sampling*DCTSIZE) < 16) size = 16;# endif if ((segment_height = td->td_tilelength) % size) { TIFFError(module,"JPEG tile height must be multiple of %d",size); status = 0; };# ifdef C_LOSSLESS_SUPPORTED if ((size = sp->h_sampling*sp->cinfo.c.data_unit) < 16) size = 16;# else if ((size = sp->h_sampling*DCTSIZE) < 16) size = 16;# endif if ((segment_width = td->td_tilewidth) % size) { TIFFError(module,"JPEG tile width must be multiple of %d",size); status = 0; }; sp->bytesperline = TIFFTileRowSize(tif); } else { tsize_t size;# ifdef C_LOSSLESS_SUPPORTED if ((size = sp->v_sampling*sp->cinfo.c.data_unit) < 16) size = 16;# else if ((size = sp->v_sampling*DCTSIZE) < 16) size = 16;# endif if (td->td_rowsperstrip < (segment_height = td->td_imagelength)) { if (td->td_rowsperstrip % size) { TIFFError(module,"JPEG RowsPerStrip must be multiple of %d",size); status = 0; }; segment_height = td->td_rowsperstrip; }; segment_width = td->td_imagewidth; sp->bytesperline = tif->tif_scanlinesize; }; if (segment_width > 65535 || segment_height > 65535) { TIFFError(module,"Strip/tile too large for JPEG"); status = 0; }; /* Initialize all JPEG parameters to default values. Note that the JPEG Library's "jpeg_set_defaults()" method needs legal values for the "in_color_space" and "input_components" fields. */ sp->cinfo.c.input_components = 1; /* Default for JCS_UNKNOWN */ if (!CALLVJPEG(sp,jpeg_set_defaults(&sp->cinfo.c))) status = 0; switch (sp->jpegtablesmode & (JPEGTABLESMODE_HUFF|JPEGTABLESMODE_QUANT)) { register JHUFF_TBL *htbl; register JQUANT_TBL *qtbl; case 0 : sp->cinfo.c.optimize_coding = TRUE; case JPEGTABLESMODE_HUFF : if (!CALLVJPEG(sp,jpeg_set_quality(&sp->cinfo.c,sp->jpegquality,FALSE))) return 0; if (qtbl = sp->cinfo.c.quant_tbl_ptrs[0]) qtbl->sent_table = FALSE; if (qtbl = sp->cinfo.c.quant_tbl_ptrs[1]) qtbl->sent_table = FALSE; goto L3; case JPEGTABLESMODE_QUANT : sp->cinfo.c.optimize_coding = TRUE; /* We do not support application-supplied JPEG tables, so mark the field "not present". */ L3: TIFFClrFieldBit(tif,FIELD_JPEGTABLES); break; case JPEGTABLESMODE_HUFF|JPEGTABLESMODE_QUANT: if ( !CALLVJPEG(sp,jpeg_set_quality(&sp->cinfo.c,sp->jpegquality,FALSE)) || !CALLVJPEG(sp,jpeg_suppress_tables(&sp->cinfo.c,TRUE)) ) { status = 0; break; }; if (qtbl = sp->cinfo.c.quant_tbl_ptrs[0]) qtbl->sent_table = FALSE; if (htbl = sp->cinfo.c.dc_huff_tbl_ptrs[0]) htbl->sent_table = FALSE; if (htbl = sp->cinfo.c.ac_huff_tbl_ptrs[0]) htbl->sent_table = FALSE; if (sp->cinfo.c.jpeg_color_space == JCS_YCbCr) { if (qtbl = sp->cinfo.c.quant_tbl_ptrs[1]) qtbl->sent_table = FALSE; if (htbl = sp->cinfo.c.dc_huff_tbl_ptrs[1]) htbl->sent_table = FALSE; if (htbl = sp->cinfo.c.ac_huff_tbl_ptrs[1]) htbl->sent_table = FALSE; }; if ( TIFFojpeg_tables_dest(sp,tif) && CALLVJPEG(sp,jpeg_write_tables(&sp->cinfo.c)) ) { /* Mark the field "present". We can't use "TIFFSetField()" because "BEENWRITING" is already set! */ TIFFSetFieldBit(tif,FIELD_JPEGTABLES); tif->tif_flags |= TIFF_DIRTYDIRECT; } else status = 0; }; if ( sp->cinfo.c.raw_data_in && !alloc_downsampled_buffers(tif,sp->cinfo.c.comp_info, sp->cinfo.c.num_components) ) status = 0; if (status == 0) return 0; /* If TIFF errors, don't bother to continue */ /* Grab parameters that are same for all strips/tiles. */ sp->dest.init_destination = std_init_destination; sp->dest.empty_output_buffer = std_empty_output_buffer; sp->dest.term_destination = std_term_destination; sp->cinfo.c.dest = &sp->dest; sp->cinfo.c.data_precision = td->td_bitspersample; sp->cinfo.c.write_JFIF_header = /* Don't write extraneous markers */ sp->cinfo.c.write_Adobe_marker = FALSE; sp->cinfo.c.image_width = segment_width; sp->cinfo.c.image_height = segment_height; sp->cinfo.c.comp_info[0].h_samp_factor = sp->cinfo.c.comp_info[0].v_samp_factor = 1; return CALLVJPEG(sp,jpeg_start_compress(&sp->cinfo.c,FALSE));# undef td }static intOJPEGPreEncode(register TIFF *tif,tsample_t s) { register OJPEGState *sp = OJState(tif);# define td (&tif->tif_dir) /* If we are about to write the first row of an image plane, which should coincide with a JPEG "scan", reset the JPEG Library's compressor. Otherwise let the compressor run "as is" and return a "success" status without further ado. */ if ( (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip) % td->td_stripsperimage == 0 ) { if ( (sp->cinfo.c.comp_info[0].component_id = s) == 1) && sp->cinfo.c.jpeg_color_space == JCS_YCbCr ) { 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; sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling; sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling; /* Scale expected strip/tile size to match a downsampled component. */ sp->cinfo.c.image_width = TIFFhowmany(segment_width,sp->h_sampling); sp->cinfo.c.image_height=TIFFhowmany(segment_height,sp->v_sampling); }; sp->scancount = 0; /* Mark subsampling buffer(s) empty */ }; return 1;# undef td }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -