⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jcdctmgr.c

📁 jpeg压缩C代码,包括库的源代码和一个测试程序的源代码
💻 C
字号:
/*
* jcdctmgr.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the forward-DCT management logic.
* This code selects a particular DCT implementation to be used,
* and it performs related housekeeping chores including coefficient
* quantization.
*/

#include "jpeg.h"
extern const int jpeg_zigzag_order[DCTSIZE2];

/* Quantize/descale the coefficients, and store into coef_blocks[] */
void jpeg_quant(short * data, WORD *multipliers, WORD *rounds)
{
	short buffer[64];
	int temp;
	int i;
	
	for (i = 0; i < DCTSIZE2; i++) 
	{
		temp = data[i];

		/* Divide the coefficient value by qval, ensuring proper rounding.
		* Since C does not specify the direction of rounding for negative
		* quotients, we have to force the dividend positive for portability.
		*
		* In most files, at least half of the output values will be zero
		* (at default quantization settings, more like three-quarters...)
		* so we should ensure that this case is fast.  On many machines,
		* a comparison is enough cheaper than a divide to make a special test
		* a win.  Since both inputs will be nonnegative, we need only test
		* for a < b to discover whether a/b is 0.
		* If your machine's division is fast enough, define FAST_DIVIDE.
		*/
		#define DIVIDE_BY(a,b)  (a = (((a+rounds[i])*multipliers[i]) >> 16))

		if (temp < 0) {
			temp = -temp;
			DIVIDE_BY(temp, qval);
			temp = -temp;
		} else {
			DIVIDE_BY(temp, qval);
		}
		buffer[jpeg_zigzag_order[i]] = (short) temp;
	}
	memcpy(data, buffer, 128);
}

/*
* Perform forward DCT on one or more blocks of a component.
* This version is used for integer DCT implementations.
* The input samples are taken from the sample_data[] array starting at
* position start_row/start_col, and moving to the right for any additional
* blocks. The quantized coefficients are returned in coef_blocks[].
*/
void forward_DCT(PBYTE sample_data, short *data, 
				 WORD *multipliers, WORD *rounds, int width)			 
{
	int i;
	
	// 计算差分
	for (i = 0; i < 8; i ++) 
	{
		*data++ = sample_data[0] - CENTERJSAMPLE;
		*data++ = sample_data[1] - CENTERJSAMPLE;
		*data++ = sample_data[2] - CENTERJSAMPLE;
		*data++ = sample_data[3] - CENTERJSAMPLE;
		*data++ = sample_data[4] - CENTERJSAMPLE;
		*data++ = sample_data[5] - CENTERJSAMPLE;
		*data++ = sample_data[6] - CENTERJSAMPLE;
		*data++ = sample_data[7] - CENTERJSAMPLE;
		sample_data += width;
	}
	data -= 64;
	
	/* Perform the DCT */
	jpeg_fdct_islow_ti (data);

	jpeg_quant(data, multipliers, rounds);
}

/*
* Compression initialization.
* Before calling this, all parameters and a data destination must be set up.
*
* We require a write_all_tables parameter as a failsafe check when writing
* multiple datastreams from the same compression object.  Since prior runs
* will have left all the tables marked sent_table=TRUE, a subsequent run
* would emit an abbreviated stream (no tables) by default.  This may be what
* is wanted, but for safety's sake it should not be the default behavior:
* programmers should have to make a deliberate choice to emit abbreviated
* images.  Therefore the documentation and examples should encourage people
* to pass write_all_tables=TRUE; then it will take active thought to do the
* wrong thing.
*/
int jpeg_start_compress (j_compress_ptr cinfo, Bitstream *bs, int width, int height)
{
	bs->ptr = bs->buffer;
	
	/* Initialize bit buffer to empty */
	bs->byte_buf = 0;
	bs->cnt = 0;
	
	/* Write the datastream header (SOI) immediately.
	* Frame and scan headers are postponed till later.
	* This lets application insert special markers after the SOI.
	*/
	return write_file_header(cinfo, bs, width, height);
}


/*
* Finish JPEG compression.
*
* If a multipass operating mode was selected, this may do a great deal of
* work including most of the actual output.
*/
int jpeg_finish_compress (Bitstream *bs)
{
	/* The entropy coder always needs an end-of-pass call,
	* either to analyze statistics or to flush its output buffer.
	*/
	finish_pass_huff(bs);
	
	/* Write EOI, do final cleanup */
	// Write datastream trailer.
	write_file_trailer(bs);

	return (bs->ptr - bs->buffer);
}

/*
* Process some data in the single-pass case.
* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
* per call, ie, v_samp_factor block rows for each component in the image.
* Returns TRUE if the iMCU row is completed, FALSE if suspended.
*
* NB: input_buf contains a plane for each component in image,
* which we index according to the component's SOF position.
*/
int JPEG_Compress(JPEG_COMPRESS_PARAM *cinfo, JPEG_IMAGE_PARAM *image)
{
	short data[6][64];
	int last_dc_val[3];			// last DC coef for each component
	int pix_x, pix_y;
	Bitstream bitstream;

	unsigned short *rounds, *multipliers;
	PBYTE imgY, imgU, imgV;
	int width, height;

	// check parameters
	if(cinfo == NULL) return 0;
	if(image == NULL) return 0;
	if(image->bitstream == 0) return 0;
	if(image->frame == 0) return 0;
	if((image->width % 16) || (image->height % 16)) return 0;

	// init
	rounds = cinfo->rounds;
	multipliers = cinfo->multipliers;

	width = image->width;
	height = image->height;

	imgY = image->frame->y;
	imgU = image->frame->u;
	imgV = image->frame->v;

	bitstream.buffer = image->bitstream;
	bitstream.size   = image->size;

	// Start compressor
	if(!jpeg_start_compress(cinfo, &bitstream, width, height))
	{
		return 0;
	}

	last_dc_val[0] = 0;
	last_dc_val[1] = 0;
	last_dc_val[2] = 0;

	for(pix_y = 0; pix_y < height; pix_y += 16)
	{
		for(pix_x = 0; pix_x < width; pix_x += 16)
		{
			forward_DCT(imgY          , data[0], multipliers, rounds, width);
			forward_DCT(imgY+8        , data[1], multipliers, rounds, width);
			forward_DCT(imgY+width*8  , data[2], multipliers, rounds, width);
			forward_DCT(imgY+width*8+8, data[3], multipliers, rounds, width);
			forward_DCT(imgU          , data[4], multipliers+64, rounds+64, width/2);
			forward_DCT(imgV          , data[5], multipliers+64, rounds+64, width/2);

			// Try to write the MCU.  In event of a suspension failure, we will
			// re-DCT the MCU on restart (a bit inefficient, could be fixed...)
			encode_mcu_huff(cinfo, &bitstream, data, last_dc_val); 

			if(bitstream.ptr > bitstream.buffer + bitstream.size - 512)
			{
				//DebugPrint("\nERROR! bitstream over!\n");
				return 0;
			}

			imgY += 16;
			imgU += 8;
			imgV += 8;
		}
		imgY += width*15;
		imgU += width/2*7;
		imgV += width/2*7;
	}

	image->length = jpeg_finish_compress(&bitstream);

	return image->length;
}


⌨️ 快捷键说明

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