jdmarker.cpp

来自「Windows 图形编程 书籍」· C++ 代码 · 共 1,577 行 · 第 1/3 页

CPP
1,577
字号
}

#else /* ! D_ARITH_CODING_SUPPORTED */

#define get_dac(cinfo)  skip_variable(cinfo)

#endif /* D_ARITH_CODING_SUPPORTED */


LOCAL(boolean) get_dht (j_decompress_ptr cinfo)
/* Process a DHT marker */
{
	long length;
	UINT8 bits[17];
	UINT8 huffval[256];
	int i, index, count;
	JHUFF_TBL **htblptr;
  
	KInput input(cinfo);

	if ( ! input.INPUT_2BYTES(cinfo, length) )
		return FALSE;
  
	length -= 2;
  
	while (length > 16) 
	{
		if ( ! input.INPUT_BYTE(cinfo, index) )
			return FALSE;

		TRACEMS1(cinfo, 1, JTRC_DHT, index);
      
		bits[0] = 0;
		count = 0;
		for (i = 1; i <= 16; i++) 
		{
			if ( ! input.INPUT_BYTE(cinfo, bits[i]) )
				return FALSE;
      
			count += bits[i];
		}

		length -= 1 + 16;

		TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
			bits[1], bits[2], bits[3], bits[4],
			bits[5], bits[6], bits[7], bits[8]);
		TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
			bits[9], bits[10], bits[11], bits[12],
			bits[13], bits[14], bits[15], bits[16]);

		/* Here we just do minimal validation of the counts to avoid walking
		* off the end of our table space.  jdhuff.c will check more carefully.
		*/
		if (count > 256 || ((long) count) > length)
			cinfo->ERREXIT(JERR_BAD_HUFF_TABLE);

		for (i = 0; i < count; i++)
			if ( ! input.INPUT_BYTE(cinfo, huffval[i]) )
				return FALSE;

		length -= count;

		if (index & 0x10) 		/* AC table definition */
		{
			index -= 0x10;
			htblptr = &cinfo->ac_huff_tbl_ptrs[index];
		} 
		else 			/* DC table definition */
		{
			htblptr = &cinfo->dc_huff_tbl_ptrs[index];
		}

		if (index < 0 || index >= NUM_HUFF_TBLS)
			cinfo->ERREXIT1(JERR_DHT_INDEX, index);

		if (*htblptr == NULL)
			*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
  
		memcpy((*htblptr)->bits, bits, sizeof((*htblptr)->bits));
		memcpy((*htblptr)->huffval, huffval, sizeof((*htblptr)->huffval));
	}

	if (length != 0)
		cinfo->ERREXIT(JERR_BAD_LENGTH);

	input.INPUT_SYNC(cinfo);
	
	return TRUE;
}


LOCAL(boolean) get_dqt (j_decompress_ptr cinfo)
/* Process a DQT marker */
{
	long length;
	int n, i, prec;
	int tmp;
	JQUANT_TBL *quant_ptr;
	
	KInput input(cinfo);

	if ( ! input.INPUT_2BYTES(cinfo, length) )
		return FALSE;
	length -= 2;

	while (length > 0) 
	{
		if ( ! input.INPUT_BYTE(cinfo, n) )
			return FALSE;
    
		prec = n >> 4;
		n &= 0x0F;

		TRACEMS2(cinfo, 1, JTRC_DQT, n, prec);

		if (n >= NUM_QUANT_TBLS)
			cinfo->ERREXIT1(JERR_DQT_INDEX, n);
      
		if (cinfo->quant_tbl_ptrs[n] == NULL)
			cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo);
			quant_ptr = cinfo->quant_tbl_ptrs[n];

		for (i = 0; i < DCTSIZE2; i++) 
		{
			if (prec)
			{
				if ( ! input.INPUT_2BYTES(cinfo, tmp) )
					return FALSE;
			}
			else
			{
				if ( ! input.INPUT_BYTE(cinfo, tmp) )
					return FALSE;
			}
      
			/* We convert the zigzag-order table to natural array order. */
			quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp;
		}

		if (cinfo->err->trace_level >= 2) 
		{
			for (i = 0; i < DCTSIZE2; i += 8) 
			{
				TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
					quant_ptr->quantval[i],   quant_ptr->quantval[i+1],
					quant_ptr->quantval[i+2], quant_ptr->quantval[i+3],
					quant_ptr->quantval[i+4], quant_ptr->quantval[i+5],
					quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]);
			}
		}

		length -= DCTSIZE2+1;
		if (prec) length -= DCTSIZE2;
	}

	if (length != 0)
		cinfo->ERREXIT(JERR_BAD_LENGTH);

	input.INPUT_SYNC(cinfo);
	
	return TRUE;
}


LOCAL(boolean) get_dri (j_decompress_ptr cinfo)
/* Process a DRI marker */
{
	long length;
	unsigned int tmp;
	
	KInput input(cinfo);

	if ( ! input.INPUT_2BYTES(cinfo, length) )
		return FALSE;
  
	if (length != 4)
		cinfo->ERREXIT(JERR_BAD_LENGTH);

	if ( ! input.INPUT_2BYTES(cinfo, tmp) )
		return FALSE;

	TRACEMS1(cinfo, 1, JTRC_DRI, tmp);

	cinfo->restart_interval = tmp;

	input.INPUT_SYNC(cinfo);
	
	return TRUE;
}


/*
 * Routines for processing APPn and COM markers.
 * These are either saved in memory or discarded, per application request.
 * APP0 and APP14 are specially checked to see if they are
 * JFIF and Adobe markers, respectively.
 */

#define APP0_DATA_LEN	14	/* Length of interesting data in APP0 */
#define APP14_DATA_LEN	12	/* Length of interesting data in APP14 */
#define APPN_DATA_LEN	14	/* Must be the largest of the above!! */


LOCAL(void)
examine_app0 (j_decompress_ptr cinfo, JOCTET * data, unsigned int datalen, long remaining)
/* Examine first few bytes from an APP0.
 * Take appropriate action if it is a JFIF marker.
 * datalen is # of bytes at data[], remaining is length of rest of marker data.
 */
{
	long totallen = (long) datalen + remaining;

	if (datalen >= APP0_DATA_LEN &&
		GETJOCTET(data[0]) == 0x4A &&
		GETJOCTET(data[1]) == 0x46 &&
		GETJOCTET(data[2]) == 0x49 &&
		GETJOCTET(data[3]) == 0x46 &&
		GETJOCTET(data[4]) == 0) 
	{
		/* Found JFIF APP0 marker: save info */
		cinfo->saw_JFIF_marker = TRUE;
		cinfo->JFIF_major_version = GETJOCTET(data[5]);
		cinfo->JFIF_minor_version = GETJOCTET(data[6]);
		cinfo->density_unit = GETJOCTET(data[7]);
		cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]);
		cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]);
    
		/* Check version.
		* Major version must be 1, anything else signals an incompatible change.
		* (We used to treat this as an error, but now it's a nonfatal warning,
		* because some bozo at Hijaak couldn't read the spec.)
		* Minor version should be 0..2, but process anyway if newer.
		*/
		if (cinfo->JFIF_major_version != 1)
			cinfo->WARNMS2(JWRN_JFIF_MAJOR, cinfo->JFIF_major_version, cinfo->JFIF_minor_version);
		
		/* Generate trace messages */
		TRACEMS5(cinfo, 1, JTRC_JFIF,
			cinfo->JFIF_major_version, cinfo->JFIF_minor_version,
			cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
    
		/* Validate thumbnail dimensions and issue appropriate messages */
		if ( GETJOCTET(data[12]) | GETJOCTET(data[13]) )
			TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, GETJOCTET(data[12]), GETJOCTET(data[13]));
    
		totallen -= APP0_DATA_LEN;
		if ( totallen != ((long)GETJOCTET(data[12]) * (long)GETJOCTET(data[13]) * (long) 3) )
			TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen);
	} 
	else if (datalen >= 6 &&
			GETJOCTET(data[0]) == 0x4A &&
			GETJOCTET(data[1]) == 0x46 &&
			GETJOCTET(data[2]) == 0x58 &&
			GETJOCTET(data[3]) == 0x58 &&
			GETJOCTET(data[4]) == 0) 
	{
		/* Found JFIF "JFXX" extension APP0 marker */
		/* The library doesn't actually do anything with these,
		* but we try to produce a helpful trace message.
		*/
		switch (GETJOCTET(data[5])) 
		{
			case 0x10:
				TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen);
				break;
				
			case 0x11:
				TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen);
				break;
    
			case 0x13:
				TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen);
				break;
    
			default:
				TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, GETJOCTET(data[5]), (int) totallen);
				break;
		}
	} 
	else 
	{
		/* Start of APP0 does not match "JFIF" or "JFXX", or too short */
		TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen);
	}
}


LOCAL(void) examine_app14 (j_decompress_ptr cinfo, JOCTET * data,
	       unsigned int datalen, long remaining)
/* Examine first few bytes from an APP14.
 * Take appropriate action if it is an Adobe marker.
 * datalen is # of bytes at data[], remaining is length of rest of marker data.
 */
{
	unsigned int version, flags0, flags1, transform;

	if (datalen >= APP14_DATA_LEN &&
		GETJOCTET(data[0]) == 0x41 &&
		GETJOCTET(data[1]) == 0x64 &&
		GETJOCTET(data[2]) == 0x6F &&
		GETJOCTET(data[3]) == 0x62 &&
		GETJOCTET(data[4]) == 0x65) 
	{
		/* Found Adobe APP14 marker */
		version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]);
		flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]);
		flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]);
		transform = GETJOCTET(data[11]);
		TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
		cinfo->saw_Adobe_marker = TRUE;
		cinfo->Adobe_transform = (UINT8) transform;
	} 
	else 
	{
		/* Start of APP14 does not match "Adobe", or too short */
		TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining));
	}
}


boolean get_interesting_appn (j_decompress_ptr cinfo)
/* Process an APP0 or APP14 marker without saving it */
{
	long length;
	JOCTET b[APPN_DATA_LEN];
	unsigned int i, numtoread;
	
	KInput input(cinfo);

	if ( ! input.INPUT_2BYTES(cinfo, length) )
		return FALSE;
	length -= 2;

	/* get the interesting part of the marker data */
	if (length >= APPN_DATA_LEN)
		numtoread = APPN_DATA_LEN;
	else if (length > 0)
		numtoread = (unsigned int) length;
	else
		numtoread = 0;
  
	for (i = 0; i < numtoread; i++)
		if ( ! input.INPUT_BYTE(cinfo, b[i]) )
			return FALSE;
	
	length -= numtoread;

	/* process it */
	switch (cinfo->unread_marker) 
	{
		case M_APP0:
			examine_app0(cinfo, (JOCTET *) b, numtoread, length);
			break;
  
		case M_APP14:
			examine_app14(cinfo, (JOCTET *) b, numtoread, length);
			break;
  
		default:
			/* can't get here unless jpeg_save_markers chooses wrong processor */
			cinfo->ERREXIT1(JERR_UNKNOWN_MARKER, cinfo->unread_marker);
			break;
	}

	/* skip any remaining data -- could be lots */
  	input.INPUT_SYNC(cinfo);
	
	if (length > 0)
		cinfo->src->skip_input_data(cinfo, (long) length);

	return TRUE;
}


#ifdef SAVE_MARKERS_SUPPORTED

boolean save_marker (j_decompress_ptr cinfo)
/* Save an APPn or COM marker into the marker list */
{
	my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
	jpeg_saved_marker_ptr cur_marker = marker->cur_marker;
	unsigned int bytes_read, data_length;
	JOCTET * data;
	long length = 0;
	
	KInput input(cinfo);
	
	if (cur_marker == NULL) 
	{
		/* begin reading a marker */
		if ( ! input.INPUT_2BYTES(cinfo, length) )
			return FALSE;
    
		length -= 2;
		if (length >= 0) 		/* watch out for bogus length word */
		{
			/* figure out how much we want to save */
			unsigned int limit;
			
			if (cinfo->unread_marker == (int) M_COM)
				limit = marker->length_limit_COM;
			else
				limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0];
      
			if ((unsigned int) length < limit)
				limit = (unsigned int) length;
      
			/* allocate and initialize the marker item */
			cur_marker = (jpeg_saved_marker_ptr) cinfo->mem->alloc_large(JPOOL_IMAGE, sizeof(struct jpeg_marker_struct) + limit);
      
			cur_marker->next = NULL;
			cur_marker->marker = (UINT8) cinfo->unread_marker;
			cur_marker->original_length = (unsigned int) length;
			cur_marker->data_length = limit;
      
			/* data area is just beyond the jpeg_marker_struct */
			data = cur_marker->data = (JOCTET *) (cur_marker + 1);
			marker->cur_marker = cur_marker;
			marker->bytes_read = 0;
			bytes_read = 0;
			data_length = limit;
		} 
		else 
		{
			/* deal with bogus length word */
			bytes_read = data_length = 0;
			data = NULL;
		}
	} 
	else 
	{
		/* resume reading a marker */
		bytes_read = marker->bytes_read;
		data_length = cur_marker->data_length;
		data = cur_marker->data + bytes_read;
	}

	while (bytes_read < data_length) 
	{
		input.INPUT_SYNC(cinfo);		/* move the restart point to here */
    
		marker->bytes_read = bytes_read;
		/* If there's not at least one byte in buffer, suspend */
		
		if ( ! input.MAKE_BYTE_AVAIL(cinfo) )
			return FALSE;
		
		/* Copy bytes with reasonable rapidity */
		while (bytes_read < data_length && input.bytes_in_buffer > 0) 
		{
			*data++ = * input.next_input_byte++;
			input.bytes_in_buffer--;
			bytes_read++;
		}
	}

	/* Done reading what we want to read */
	if (cur_marker != NULL) 	/* will be NULL if bogus length word */
	{
		/* Add new marker to end of list */
		if (cinfo->marker_list == NULL) 
		{
			cinfo->marker_list = cur_marker;
		} 
		else 
		{
			jpeg_saved_marker_ptr prev = cinfo->marker_list;
      
			while (prev->next != NULL)
				prev = prev->next;
			prev->next = cur_marker;
		}
    
		/* Reset pointer & calc remaining data length */
		data = cur_marker->data;
		length = cur_marker->original_length - data_length;
	}
  
	/* Reset to initial state for next marker */
	marker->cur_marker = NULL;

	/* Process the marker if interesting; else just make a generic trace msg */
	switch (cinfo->unread_marker) 
	{
		case M_APP0:
			examine_app0(cinfo, data, data_length, length);
			break;
  
		case M_APP14:
			examine_app14(cinfo, data, data_length, length);
			break;
  
		default:
			TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) (data_length + length));
			break;
	}

	/* skip any remaining data -- could be lots */
	input.INPUT_SYNC(cinfo);		/* do before skip_input_data */
  
	if (length > 0)
		cinfo->src->skip_input_data(cinfo, (long) length);

	return TRUE;
}

#endif /* SAVE_MARKERS_SUPPORTED */


boolean skip_variable (j_decompress_ptr cinfo)
/* Skip over an unknown or uninteresting variable-length marker */
{
	long length;
	KInput input(cinfo);

	if ( ! input.INPUT_2BYTES(cinfo, length) )
		return FALSE;
  
	length -= 2;
  
	TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length);

	input.INPUT_SYNC(cinfo);		/* do before skip_input_data */
  
	if (length > 0)

⌨️ 快捷键说明

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