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

📄 jpegencoder.c

📁 这是一个JPEG程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************
Copyright (C), 2005-2008, MXIC(Suzhou). Co., Ltd.
File name: JpegEncoder.c
Author:        
Version: V1.0
Date: 2006/04/21
Address: No.338, shenhu Rd, SIP, SuZhou, P.R.China
Description:     
    A BMP truecolor to JPEG encoder    
History:
    <author>   <time>      <version >        <desc>
    Billy    2006/04/21     1.0        throw of DC Table  
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "JpegHeader.h"

//计算量化表的调试开关
//打开:量化时,乘法运算
//关闭:量化时,除法运算
#define QUANT_TABLE_DEBUG

//量化循环次数调试开关
//打开:量化时,连续0的个数超过16个时,停止运算
//关闭:量化时,运算8X8次
//#define QUANT_LOOP_DEBUG

//writebits调试开关
//打开:用Mask运算
//关闭:不用Mask运算,改为移位运算
//#define WRITEBITS_DEBUG

//打开:统计各个长度出现的频率
//关闭:不统计各个长度出现的频率
//#define WRITE_BITS_DEBUG
#ifdef WRITE_BITS_DEBUG
	write_bits_buf[17];
#endif

//打开:统计各个长度出现的频率
//关闭:不统计各个长度出现的频率
//#define PROCESS_DU_DEBUG
#ifdef PROCESS_DU_DEBUG
	process_du_buf[64];
#endif

//YCbCr采样格式调试开关
//打开:
//关闭:
//#define Y_HXV_1X1_DEBUG //4:4:4
//#define Y_HXV_2X1_DEBUG //4:2:2
#define Y_HXV_1X2_DEBUG //4:2:2
//#define Y_HXV_2X2_DEBUG  // 4:2:0

//打开:用原始图像
//关闭:用转换过的图像
#define MCU_FIFO_DEBUG 

//计算Ac位和数值的对应表
//打开:用函数计算
//关闭:用表格查询
//#define GET_AC_BIT_DEBUG

//fdct and quantization debug
//打开:改动前,汇编存储耗时太多
//关闭:改动后,便于汇编运算
#define FDCT_AND_QUANTILIZATION_DEBUG

#ifdef Y_HXV_1X1_DEBUG 	
 	WORD du_X; //Ximage - 8
 	
 	#define MCU_SIZE 64 //8*8*3
 	colorRGB mcu_data[MCU_SIZE];   	 	
#endif

#ifdef Y_HXV_2X2_DEBUG
 	WORD du_X, du_X1; // tempX, tempX1; //du_X = Ximage - 8; du_X1 = tempX << 1;  
 	
 	#define MCU_SIZE 256 //8*8*3*4
 	colorRGB mcu_data[MCU_SIZE];	 	
#endif

#ifdef Y_HXV_2X1_DEBUG
 	WORD du_X, du_X1; //du_X = Ximage - 8; du_X1 = du_X - 8; 	 
 	
 	#define MCU_SIZE 128 //8*8*3*2
 	colorRGB mcu_data[MCU_SIZE];	 	
#endif

#ifdef Y_HXV_1X2_DEBUG
 	WORD du_X, du_X1;; //du_X = Ximage - 8; du_X1 = du_X + Ximage; 
 	
 	#define MCU_SIZE 128 //8*8*3*2
 	colorRGB mcu_data[MCU_SIZE]; 		 	
#endif

//DC差值内容(-2047.. 2047), 差值位数11位
//AC系数范围(-32767..32767), 系数位数15位
//DC: 用来存放DC差值内容和差值位数对照表
//AC: 用来存放AC系数范围和SSSS对照表
//static BYTE CategoryBuffer[JPEGENCODER_CATEGORY_LENGEH * sizeof(BYTE)];
//static BYTE *pCategory;  

//AC系数范围(-32767..32767),系数位数15位
//static bitstring BitcodeBuffer[JPEGENCODER_CATEGORY_LENGEH * sizeof(bitstring)];
//static bitstring *pBitcode = &ACBitCode;//&ACBitCode; //their bitcoded representation
#ifdef GET_AC_BIT_DEBUG
	//Ac and DC 的位数和数值的对应关系一至,可以用一个变量来表示(节省运算量)
	static bitstring ACBitCode; //record AC bit and AC Value
	static bitstring DCBitCode; //record DC bit and DC Value
#else
	#define JPEGENCODER_CATEGORY_LENGEH (512)//65535
	#define JPEGENCODER_BITCODE_LENGEH (JPEGENCODER_CATEGORY_LENGEH / 2)
	static bitstring bitcode[JPEGENCODER_CATEGORY_LENGEH];
	static bitstring *pbitcode;
	
	static bitstring ACBitCode; //record AC bit and AC Value
	static bitstring DCBitCode; //record DC bit and DC Value
#endif

//调用次数太多,使用全局变量,赋初值
//Mask虽然在一个函数里调用,但因为要用到初值,不宜在函数内定义,否则会大量增加cycles
#ifdef WRITEBITS_DEBUG
	static WORD Mask[16] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
#endif

static BYTE bytenew = 0;   //The byte that will be written in the JPG file
static SBYTE bytepos = 7;  //bit position in the byte we write (bytenew)
                           //should be<=7 and >=0
                           
//Precalculated tables for a faster YCbCr->RGB transformation
//定点数据最大值为((153887 * 255) >> 18) = 149.
//定点数据最小值为((-109749 * 255) >> 18) = -106.
static BYTE YRtab[256], YGtab[256], YBtab[256];
static SBYTE CbRtab[256], CbGtab[256];
static BYTE CbBtab[256];
static SBYTE CrGtab[256], CrBtab[256];
static BYTE CrRtab[256];

#define  Y(R, G, B) (YRtab[(R)] + YGtab[(G)] + YBtab[(B)] - 128)
#define Cb(R, G, B) (CbRtab[(R)] + CbGtab[(G)] + CbBtab[(B)])
#define Cr(R, G, B) (CrRtab[(R)] + CrGtab[(G)] + CrBtab[(B)])

static BYTE zigzag[64] = { 
	 0,  1,  5,  6, 14, 15, 27, 28,
	 2,  4,  7, 13, 16, 26, 29, 42,
	 3,  8, 12, 17, 25, 30, 41, 43,
	 9, 11, 18, 24, 31, 40, 44, 53,
	10, 19, 23, 32, 39, 45, 52, 54,
	20, 22, 33, 38, 46, 51, 55, 60,
	21, 34, 37, 47, 50, 56, 59, 61,
	35, 36, 48, 49, 57, 58, 62, 63 
};

/* 
	These are the sample quantization tables given in JPEG spec section K.1. The spec says that 
the values given produce "good" quality, and when divided by 2, "very good" quality.
*/
/*
	亮度量化表和色度量化表是依据心理觉阀制作,对8bit的亮度和色度的图像的处理效果不错,量化表是控制
JPEG压缩比的关键。
	这个步骤除掉了一些高频量,损失了很高细节。但事实上,人眼对高空间频率远没有低频敏感,所以处理后
的视觉影响很小。另一个重要原因是所有的图片的点与点之间会有一个色彩过渡的过程。大量的图像信息被包含
在低空间频率中,经过量化处理后,在高空间频率段,将出现大量连续的零。
	
*/
//亮度量化表(Y量化表)
static BYTE std_luminance_qt[64] = {
	16,  11,  10,  16,  24,  40,  51,  61,
	12,  12,  14,  19,  26,  58,  60,  55,
	14,  13,  16,  24,  40,  57,  69,  56,
	14,  17,  22,  29,  51,  87,  80,  62,
	18,  22,  37,  56,  68, 109, 103,  77,
	24,  35,  55,  64,  81, 104, 113,  92,
	49,  64,  78,  87, 103, 121, 120, 101,
	72,  92,  95,  98, 112, 100, 103,  99
};

//色度量化表(C量化表)  
static BYTE std_chrominance_qt[64] = {
	17,  18,  24,  47,  99,  99,  99,  99,
	18,  21,  26,  66,  99,  99,  99,  99,
	24,  26,  56,  99,  99,  99,  99,  99,
	47,  66,  99,  99,  99,  99,  99,  99,
	99,  99,  99,  99,  99,  99,  99,  99,
	99,  99,  99,  99,  99,  99,  99,  99,
	99,  99,  99,  99,  99,  99,  99,  99,
	99,  99,  99,  99,  99,  99,  99,  99
};
  
//Standard Huffman tables (cf. JPEG standard section K.3)
//定义在 DHT 标记后面. 注意: Haffman代码的长度限制在 16bit 内.

//第 i 字节表示了 i 位长的 Huffman 代码的个数 (i= 1 到 16)
static BYTE std_dc_luminance_nrcodes[17] = {0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0};
//这表的长度 (字节数) = 这 16 个数字之和
static BYTE std_dc_luminance_values[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

static BYTE std_dc_chrominance_nrcodes[17] = {0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
static BYTE std_dc_chrominance_values[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

static BYTE std_ac_luminance_nrcodes[17] = {0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0X7D};
static BYTE std_ac_luminance_values[162] = {//包括EOB,ZRL
	0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
	0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
	0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
	0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
	0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
	0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
	0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
	0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
	0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
	0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
	0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
	0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
	0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
	0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
	0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
	0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
	0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
	0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
	0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
	0xf9, 0xfa 
};

static BYTE std_ac_chrominance_nrcodes[17] = {0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0X77};
static BYTE std_ac_chrominance_values[162] = {//包括EOB,ZRL
	0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
	0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
	0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
	0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
	0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
	0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
	0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
	0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
	0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
	0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
	0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
	0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
	0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
	0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
	0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
	0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
	0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
	0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
	0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
	0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
	0xf9, 0xfa 
};  

//存放运算后的Huffman(DC 和 AC 个两个)表.
static bitstring dc_luminance_ht[12];   //DC luminance huffman table
static bitstring dc_chrominance_ht[12]; //DC chrominance huffman table
static bitstring ac_luminance_ht[256];  //AC luminance huffman table
static bitstring ac_chrominance_ht[256];//AC chrominance huffman table

//存放量化表            
static WORD fdtbl_Y[64];
static WORD fdtbl_Cb[64]; //the same with the fdtbl_Cr[64]

//This is the Data Unit of Y after RGB->YCbCr transformation
//static SBYTE YDU[64]; 
//static SBYTE CbDU[64];
//static SBYTE CrDU[64];
static SWORD YDU[64]; 
static SWORD CbDU[64];
static SWORD CrDU[64];

static SWORD YDU1[64]; 
static SWORD YDU2[64]; 
static SWORD YDU3[64]; 

colorRGB *RGB_buffer; //image to be encoded
WORD Ximage, Yimage;   //image dimensions divisible by 8
FILE *fp_jpeg_stream;
unsigned int TotalNum[16];
/*
function: 
	Huffman编码器可以使用查表方法进行编码。压缩数据符号时,Huffman编码器对出现频率比较高的符号分配比较
短的代码,而对出现频率比较高的符号分配比较长的代码。这种可变长度的Huffman表可以事先定义。
    编码时,每个矩阵数据的DC值与63个AC值,将分别使用不同的Huffman编码器,而亮度和色度也需要不同的Huffman
编码器,所以一共需要四个编码表,才能顺利完成JPEG编码工作。    	
	DC,建立所需位数与差值内容的对照表。
	AC, 建立AC系数范围与AC所需位数对照表。	
input:	
	diffVal: DC或AC的差值
output:
	None	
*/
void get_dc_diff_bits(SWORD diffVal)
{
	SWORD diff;
	
	if (diffVal >= 0) 
	{
		diff = diffVal;	
		
		//DC差值位数               
		DCBitCode.value = diff; 
	}
	else 
	{
		diff = -diffVal;
		
		//DC差值内容
		DCBitCode.value = diffVal - 1;
	}
	
	//判断时,据统计,diff范围从1开始,依次减小
	if (diff == 1) 
	{
		//DC,建立所需位数与差值内容的对照表		
		DCBitCode.length = 1; return;							
	}
	else if (diff <= 3)
	{		
		DCBitCode.length = 2; return;								
	}
	else if (diff <= 7)
	{
		DCBitCode.length = 3; return;									
	}
	else if (diff <= 15)
	{		
		DCBitCode.length = 4; return;
	}
	else if (diff <= 31)
	{			
		DCBitCode.length = 5; return;								
	}
	else if (diff <= 63)
	{
		DCBitCode.length = 6; return;		
	}
	else if (diff <= 127)
	{
		DCBitCode.length = 7; return;
	}
	else if (diff <= 255)
	{
		DCBitCode.length = 8; return;
	}
	else if (diff <= 511)
	{
		DCBitCode.length = 9;  return;
	}
	else if (diff <= 1023)
	{
		DCBitCode.length = 10; return;
	}
	else if (diff == 0) 
	{	
		//DC差值内容为0, AC差值内容不保存	
		DCBitCode.length = 0; return;
	}
	else if (diff <= 2047)
	{
		DCBitCode.length = 11; return;
	}
}

#ifdef GET_AC_BIT_DEBUG
void get_ac_bits_category(SWORD diffVal)
{
	SWORD diff;
	
	if (diffVal < 0) diff = -diffVal;
	else diff = diffVal;
	
	//AC系数所需的位数(SSSS组)
	ACBitCode.value = diff;
	
	//判断时,据统计,diff范围从1开始,依次减小
	if (diff == 1) 
	{		
		//AC, AC系数范围与AC所需位数对照表(正向)(AC实际保存值从负向0开始向正向递增)
		DCBitCode.length = 1; ACBitCode.length = 1; //TotalNum[1]++;
				
		if (diffVal < 0) 
		{
			//实际保存值
			ACBitCode.value = (1 + diffVal); return;			
		}
	}
	else if (diff <= 3)
	{		
		ACBitCode.length = 2; //TotalNum[2]++;
				
		if (diffVal < 0) 
		{
			ACBitCode.value = (3 + diffVal); return;			
		}		
	}
	else if (diff <= 7)
	{
		ACBitCode.length = 3; //TotalNum[3]++;
				
		if (diffVal < 0) 
		{
			ACBitCode.value = (7 + diffVal); return; 			
		}	
	}
	else if (diff <= 15) 
	{		
		ACBitCode.length = 4; //TotalNum[4]++;
				
		if (diffVal < 0) 
		{
			ACBitCode.value = (15 + diffVal); return;			
		}		
	}
	else if (diff <= 31)
	{			
		ACBitCode.length = 5; //TotalNum[5]++;
				
		if (diffVal < 0) 
		{
			ACBitCode.value = (31 + diffVal); return;			
		}	
	}
	else if (diff <= 63)
	{
		ACBitCode.length = 6; //TotalNum[6]++;
				
		if (diffVal < 0) 
		{
			ACBitCode.value = (63 + diffVal); return;			
		}								
	}
	else if (diff <= 127)
	{
		ACBitCode.length = 7; //TotalNum[7]++;
				
		if (diffVal < 0)

⌨️ 快捷键说明

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