tif_jpeg.c

来自「支持各种栅格图像和矢量图像读取的库」· C语言 代码 · 共 2,014 行 · 第 1/4 页

C
2,014
字号
				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];#ifdef JPEG_LIB_MK1					JSAMPLE *outptr = (JSAMPLE*)tmpbuf + clumpoffset;#else					JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset;#endif					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;				}			}#ifdef JPEG_LIB_MK1			{				if (sp->cinfo.d.data_precision == 8)				{					int i=0;					int len = sp->cinfo.d.output_width * sp->cinfo.d.num_components;					for (i=0; i<len; i++)					{						((unsigned char*)buf)[i] = tmpbuf[i] & 0xff;					}				}				else				{         // 12-bit					int value_pairs = (sp->cinfo.d.output_width					    * sp->cinfo.d.num_components) / 2;					int iPair;					for( iPair = 0; iPair < value_pairs; iPair++ )					{						unsigned char *out_ptr = ((unsigned char *) buf) + iPair * 3;						JSAMPLE *in_ptr = tmpbuf + iPair * 2;						out_ptr[0] = (in_ptr[0] & 0xff0) >> 4;						out_ptr[1] = ((in_ptr[0] & 0xf) << 4)						    | ((in_ptr[1] & 0xf00) >> 8);						out_ptr[2] = ((in_ptr[1] & 0xff) >> 0);					}				}			}#endif			sp->scancount ++;			tif->tif_row += sp->v_sampling;			/* increment/decrement of buf and cc is still incorrect, but should not matter			 * TODO: resolve this */			buf += sp->bytesperline;			cc -= sp->bytesperline;			nrows -= sp->v_sampling;		} while (nrows > 0);#ifdef JPEG_LIB_MK1		_TIFFfree(tmpbuf);#endif	}	/* 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);        JPEGInitializeLibJPEG( tif, 0, 0 );	/* 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";        JPEGInitializeLibJPEG( tif, 1, 0 );	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.		 */		{			float *ref;			if (!TIFFGetField(tif, TIFFTAG_REFERENCEBLACKWHITE,					  &ref)) {				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);			}		}		break;	case PHOTOMETRIC_PALETTE:		/* disallowed by Tech Note */	case PHOTOMETRIC_MASK:		TIFFErrorExt(tif->tif_clientdata, 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.	 */#ifdef JPEG_LIB_MK1        /* BITS_IN_JSAMPLE now permits 8 and 12 --- dgilbert */	if (td->td_bitspersample != 8 && td->td_bitspersample != 12) #else	if (td->td_bitspersample != BITS_IN_JSAMPLE )#endif	{		TIFFErrorExt(tif->tif_clientdata, module, "BitsPerSample %d not allowed for JPEG",			  (int) td->td_bitspersample);		return (0);	}	sp->cinfo.c.data_precision = td->td_bitspersample;#ifdef JPEG_LIB_MK1        sp->cinfo.c.bits_in_jsample = td->td_bitspersample;#endif	if (isTiled(tif)) {		if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) {			TIFFErrorExt(tif->tif_clientdata, module,				  "JPEG tile height must be multiple of %d",				  sp->v_sampling * DCTSIZE);			return (0);		}		if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) {			TIFFErrorExt(tif->tif_clientdata, 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) {			TIFFErrorExt(tif->tif_clientdata, module,				  "RowsPerStrip must be multiple of %d for JPEG",				  sp->v_sampling * DCTSIZE);			return (0);		}	}	/* Create a JPEGTables field if appropriate */	if (sp->jpegtablesmode & (JPEGTABLESMODE_QUANT|JPEGTABLESMODE_HUFF)) {		if (!prepare_JPEGTables(tif))			return (0);		/* Mark the field present */		/* Can't use TIFFSetField since BEENWRITING is already set! */		TIFFSetFieldBit(tif, FIELD_JPEGTABLES);		tif->tif_flags |= TIFF_DIRTYDIRECT;	} else {		/* We do not support application-supplied JPEGTables, */		/* so mark the field not present */		TIFFClrFieldBit(tif, FIELD_JPEGTABLES);	}	/* Direct libjpeg output to libtiff's output buffer */	TIFFjpeg_data_dest(sp, tif);	return (1);}/* * Set encoding state at the start of a strip or tile. */static intJPEGPreEncode(TIFF* tif, tsample_t s){	JPEGState *sp = JState(tif);	TIFFDirectory *td = &tif->tif_dir;	static const char module[] = "JPEGPreEncode";	uint32 segment_width, segment_height;	int downsampled_input;	assert(sp != NULL);	assert(!sp->cinfo.comm.is_decompressor);	/*	 * Set encoding parameters for this strip/tile.	 */	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 = TIFFOldScanlineSize(tif);	}	if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) {		/* for PC 2, scale down the 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) {		TIFFErrorExt(tif->tif_clientdata, module, "Strip/tile too large for JPEG");		return (0);	}	sp->cinfo.c.image_width = segment_width;	sp->cinfo.c.image_height = segment_height;	downsampled_input = FALSE;	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 (!TIFFjpeg_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 (!TIFFjpeg_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 (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN))			return (0);		sp->cinfo.c.comp_info[0].component_id = s;		/* jpeg_set_colorspace() set sampling factors to 1 */		if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) {			sp->cinfo.c.comp_info[0].quant_tbl_no = 1;			sp->cinfo.c.comp_info[0].dc_tbl_no = 1;			sp->cinfo.c.comp_info[0].ac_tbl_no = 1;		}	}	/* ensure libjpeg won't write any extraneous markers */	sp->cinfo.c.write_JFIF_header = FALSE;	sp->cinfo.c.write_Adobe_marker = FALSE;	/* set up table handling correctly */	if (! (sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) {		if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE))			return (0);		unsuppress_quant_table(sp, 0);		unsuppress_quant_table(sp, 1);	}	if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF)		sp->cinfo.c.optimize_coding = FALSE;	else		sp->cinfo.c.optimize_coding = TRUE;	if (downsampled_input) {		/* Need to use raw-data interface to libjpeg */		sp->cinfo.c.raw_data_in = TRUE;		tif->tif_encoderow = JPEGEncodeRaw;		tif->tif_encodestrip = JPEGEncodeRaw;		tif->tif_encodetile = JPEGEncodeRaw;	} else {		/* Use normal interface to libjpeg */		sp->cinfo.c.raw_data_in = FALSE;		tif->tif_encoderow = JPEGEncode;		tif->tif_encodestrip = JPEGEncode;		tif->tif_encodetile = JPEGEncode;	}	/* Start JPEG compressor */	if (!TIFFjpeg_start_compress(sp, FALSE))		return (0);	/* Allocate downsampled-data buffers if needed */	if (downsampled_input) {		if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info,					       sp->cinfo.c.num_components))			return (0);	}	sp->scancount = 0;	return (1);}/* * Encode a chunk of pixels. * "Standard" case: incoming data is not downsampled. */static intJPEGEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s){	JPEGState *sp = JState(tif);	tsize_t nrows;	JSAMPROW bufptr[1];	(void) s;	assert(sp != NULL);	/* data is expected to be supplied in multiples of a scanline */	nrows = cc / sp->bytesperline;	if (cc % sp->bytesperline)		TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline discarded");	while (nrows-- > 0) {		bufptr[0] = (JSAMPROW) buf;		if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1)			return (0);		if (nrows > 0)			tif->tif_row++;		buf += sp->bytesperline;	}	return (1);}/* * Encode a chunk of pixels. * Incoming data is expected to be downsampled per sampling factors. */static intJPEGEncodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s){	JPEGState *sp = JState(tif);	JSAMPLE* inptr;	JSAMPLE* outptr;	tsize_t nrows;	JDIMENSION clumps_per_line, nclump;	int clumpoffset, ci, xpos, ypos;	jpeg_component_info* compptr;	int samples_per_clump = sp->samplesperclump;	tsize_t bytesperclumpline;	(void) s;	assert(sp != NULL);	/* data is expected to be supplied in multiples of a clumpline */	/* a clumpline is equivalent to v_sampling desubsampled scanlines */	/* TODO: the following calculation of bytesperclumpline, should substitute calculation of sp->bytesperline, except that it is per v_sampling lines */	bytesperclumpline = (((sp->cinfo.c.image_width+sp->h_sampling-1)/sp->h_sampling)			     *(sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7)			    /8;	nrows = ( cc / bytesperclumpline ) * sp->v_sampling;	if (cc % bytesperclumpline)		TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline discarded");	/* Cb,Cr both have sampling factors 1, so this is correct */	clumps_per_line = sp->cinfo.c.comp_info[1].downsampled_width;	while (nrows > 0) {		/*		 * Fastest way to separate the 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.c.comp_info;		     ci < sp->cinfo.c.num_components;		     ci++, compptr++) {		    int hsamp = compptr->h_samp_factor;		    int vsamp = compptr->v_samp_factor;		    int padding = (int) (compptr->width_in_blocks * DCTSIZE -					 clumps_per_line * hsamp);		    for (ypos = 0; ypos < vsamp; ypos++) {			inptr = ((JSAMPLE*) buf) + clumpoffset;			outptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos];			if (hsamp == 1) {			    /* 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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?