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

📄 wavelet.c

📁 c++ Builder中网络图象渐进传输实例
💻 C
📖 第 1 页 / 共 4 页
字号:
	for (i = 0; i <= bl->max_quant; i++)
	{
		t_wv_quantised_block* ebl = &bl->quant[i];

		if (bits_left - ebl->compressed_size >= need_left)
		{ // fit
			float lmse;
			unsigned char wd;

			if (went_down)
				*went_down = 1; 
			lmse = recursive_selector_bits(cc, block_idx + 1, bits_left - ebl->compressed_size, mse + ebl->mse, &wd);
			if (lmse < bl->best_mse)
			{
				if (!wd)
				{ // we didn't fit another block, so set their quant to max
					int j;

					for (j = block_idx + 1; j < cc->num_blocks; j++)
						cc->blocks[j].best_quant = cc->blocks[j].max_quant;
				}
				bl->best_quant = i;
				bl->best_mse = best_lmse = lmse;
			}
		}
	}
	return best_lmse;
}


static int recursive_selector_mse(t_wv_cchannel* cc, const int block_idx, const int total_bits, const float mse, unsigned char *went_down)
{
	int i;
	t_wv_cblock* bl;
	int best_bits;
	float min_mse, max_mse;

	if (went_down)
		*went_down = 0;
	
	min_mse = max_mse = mse;
	for (i = block_idx; i < cc->num_blocks; i++)
	{
		min_mse += cc->blocks[i].quant[0].mse;
		max_mse += cc->blocks[i].quant[cc->blocks[i].max_quant].mse;
	}
	
	if (max_mse <= cc->max_mse)
	{
		cc->final_mse = max_mse;
		return total_bits;
	}

	if ((total_bits != 0 && cc->max_bits - total_bits < RICE_MIN_SPACE) || block_idx >= cc->num_blocks)
		return cc->max_bits + 1; // didn't meet the requirements

	if (min_mse > cc->max_mse)
		return cc->max_bits + 1; // only try this if it can possibly be better (with infite bits)
	
	best_bits = cc->max_bits + 1;
	
	bl = &cc->blocks[block_idx];	
	for (i = 0; i <= bl->max_quant; i++)
	{
		t_wv_quantised_block* ebl = &bl->quant[i];

		if (total_bits + ebl->compressed_size <= cc->max_bits)
		{ // fit
			int lbits;
			unsigned char wd;

			if (went_down)
				*went_down = 1; 
			lbits = recursive_selector_mse(cc, block_idx + 1, total_bits + ebl->compressed_size, mse + ebl->mse, &wd);
			if (lbits <= cc->max_bits && lbits < bl->best_bits)
			{
				if (!wd)
				{ // we didn't fit another block, so set their quant to max
					int j;
					
					for (j = block_idx + 1; j < cc->num_blocks; j++)
					{
						cc->blocks[j].best_quant = cc->blocks[j].max_quant;
						cc->blocks[j].best_bits = lbits;
					}
				}

				bl->best_quant = i;
				bl->best_bits = best_bits = lbits;
			}
		}
	}
	return best_bits;
}


//----------------------------------------------------------------------------
// wv_init_channel_settings	initialises compression settings for a single
//				channel, stores it to the userdefined pointer and
//				returns the number of bits used (0 on failure)
// CC			handle to the channel (gotten from wv_init_channel)
// MaxBits		(maximum) bits to be used for the channel (0 ^= quality-based)
// MaxMSE		maximum mean square error to be incurred by the compression
//				0.0f => lossless, 65536.0f => don't care
// Settings		pointer where the channel-setting handle is stored on success
//----------------------------------------------------------------------------
WAVELET_DLL_API int WAVELET_DLL_CC wv_init_channel_settings(t_wv_cchannel* CC, const int MaxBits, const float MaxMSE, t_wv_csettings** Settings)
{
	int bits = 0;

	if (CC && Settings)
	{
		int i, size;

		for (i = 0; i < CC->num_blocks; i++)
		{
			CC->blocks[i].best_bits = 1 << 30;
			CC->blocks[i].best_mse = 65536.0f;
			CC->blocks[i].best_quant = CC->blocks[i].max_quant;
		}

		CC->max_bits = size = max(0, MaxBits);
		CC->max_mse = min(65536.0f, max(0.0f, MaxMSE));

		if (CC->max_mse < 65536.0f)
		{

			if (CC->max_bits == 0)
				CC->max_bits = 1 << 30;
			size = recursive_selector_mse(CC, 0, 0, 0.0f, NULL);
		}
		else
		{
			CC->final_mse = recursive_selector_bits(CC, 0, CC->max_bits, 0.0f, NULL); // only bit-constraint
			size = 0;
			for (i = 0; i < CC->num_blocks; i++)
				size += CC->blocks[i].quant[CC->blocks[i].best_quant].compressed_size;
		}
		
		if (CC->max_bits == 0 || size <= CC->max_bits)
		{
			t_wv_csettings* set = malloc(sizeof *set);

			set->cchannel = CC;
			set->size_min_block = CC->size_min_block;
			set->emse = 0.0f;
			set->num_bits = 0;
			set->num_blocks = CC->num_blocks;
			set->blocks = malloc(CC->num_blocks * sizeof *set);
			for (i = 0; i < CC->num_blocks; i++)
			{
				set->blocks[i].max_bpp = CC->blocks[i].max_bpp;
				set->blocks[i].quant = CC->blocks[i].best_quant;
				set->blocks[i].num_bits = CC->blocks[i].quant[CC->blocks[i].best_quant].compressed_size;
				set->num_bits += set->blocks[i].num_bits;
				set->emse += CC->blocks[i].quant[CC->blocks[i].best_quant].mse;
//				printf("%i ", set->blocks[i].num_bits);
			}
//			printf("\n");
			bits = set->num_bits;
			*Settings = set;
		}
		else
			*Settings = NULL;
	}
	return bits;
}


//----------------------------------------------------------------------------
// wv_done_channel_settings	frees the channels settings
// Settings		channel-settings handle to be freed
//----------------------------------------------------------------------------
WAVELET_DLL_API void WAVELET_DLL_CC wv_done_channel_settings(t_wv_csettings* Settings)
{
	if (Settings)
	{
		free(Settings->blocks);
		free(Settings);
	}
}


//----------------------------------------------------------------------------
// wv_encode_channels	encodes a number of channels progressively
//				interleaved	into a given bit_file. it includes a small header
//				containing # channels, power of 2 width & height
//				returns the number of bits written
// NumChannels	# of channels to be encoded
// ChannelSettings	array of channel-settings handles to be used for encoding.
//				all channels / settings need to have the same width, height
//				and number of blocks to be encoded into the same file
// BF			bit-file handle to be written to (opened in WRITE-mode)
//----------------------------------------------------------------------------
WAVELET_DLL_API int WAVELET_DLL_CC wv_encode_channels(const int NumChannels, t_wv_csettings** ChannelSettings, t_bit_file* BF)
{
	int bits = 0;

	if (NumChannels > 0 && NumChannels <= wv_MAX_CHANNELS && ChannelSettings && BF)
	{
		int i;

		// check that the channels are the same size & # of blocks
		for (i = 1; i < NumChannels; i++)
		{
			if (ChannelSettings[0]->num_blocks != ChannelSettings[i]->num_blocks)
				break;
			if (ChannelSettings[0]->cchannel->width != ChannelSettings[i]->cchannel->width)
				break;
			if (ChannelSettings[0]->cchannel->height != ChannelSettings[i]->cchannel->height)
				break;
			if (ChannelSettings[0]->cchannel->size_min_block != ChannelSettings[i]->cchannel->size_min_block)
				break;
		}
		if (i == NumChannels)
		{ // they all match
			static const unsigned int magic = 0x5b765d;
			int j;

			bits += bit_write(magic, 24, BF);
			bits += bit_write(wv_CUR_HEADER_VERSION, 4, BF);
			bits += bit_write(wv_CUR_BITSTREAM_VERSION, 4, BF);

			bits += bit_write(ChannelSettings[0]->cchannel->width != ChannelSettings[0]->cchannel->owidth ||
				ChannelSettings[0]->cchannel->height != ChannelSettings[0]->cchannel->oheight, 1, BF); // write dimension flag
			if (ChannelSettings[0]->cchannel->width != ChannelSettings[0]->cchannel->owidth ||
				ChannelSettings[0]->cchannel->height != ChannelSettings[0]->cchannel->oheight)
			{
				bits += bit_write(ChannelSettings[0]->cchannel->owidth - 1, 16, BF);
				bits += bit_write(ChannelSettings[0]->cchannel->oheight - 1, 16, BF);
			}
			
			bits += bit_write(NumChannels - 1, 4, BF);
			bits += bit_write(wv_log2i(ChannelSettings[0]->cchannel->width) - 1, 4, BF);
			bits += bit_write(wv_log2i(ChannelSettings[0]->cchannel->height) - 1, 4, BF);
			bits += bit_write(ChannelSettings[0]->num_blocks - 1, 4, BF);
			bits += bit_write(wv_log2i(ChannelSettings[0]->size_min_block), 5, BF);			
			
			for (i = 0; i < ChannelSettings[0]->num_blocks; i++)
				for (j = 0; j < NumChannels; j++)
					bits += rice_encode_block(ChannelSettings[j]->cchannel->reordered_channel + ChannelSettings[j]->cchannel->blocks[i].offset, ChannelSettings[j]->cchannel->blocks[i].size, ChannelSettings[j]->blocks[i].quant, 0, ChannelSettings[j]->cchannel->blocks[i].max_value, BF); // write channel-blocks interleaved
		}
	}
	return bits;
}


//----------------------------------------------------------------------------
// wv_init_decode_channels	decodes a number of channels from a bit-file
//				written to by wv_encode_channels.
//				returns Header if header read successfully, NULL otherwise
// Header		Place to store the information (only valid if != NULL was returned)
// BF			bit-file handle to be read from (opened in READ-mode)
//----------------------------------------------------------------------------
WAVELET_DLL_API t_wv_header* WAVELET_DLL_CC wv_read_header(t_wv_header* Header, t_bit_file* BF)
{
	static const unsigned int magic = 0x5b765d;
	int header_version, bitstream_version;

	if (!Header)
		return NULL;

	Header->num_channels = 0;
	Header->width = Header->height = 0;
	Header->owidth = Header->oheight = 0;
	Header->header_version = bitstream_version = 0;

	if (!BF)
		return NULL;

	if (bit_read(24, BF) != magic)
		return NULL;

	header_version= bit_read(4, BF);
	if (header_version < wv_MIN_HEADER_VERSION || header_version > wv_CUR_HEADER_VERSION)
		return NULL;

	bitstream_version = bit_read(4, BF);
	if (bitstream_version < wv_MIN_BITSTREAM_VERSION || bitstream_version > wv_CUR_BITSTREAM_VERSION)
		return NULL;

	Header->header_version = header_version;
	Header->bitstream_version = bitstream_version;
		
	if (bit_read_single(BF))
	{ // read original dimensions
		Header->owidth = bit_read(16, BF) + 1;
		Header->oheight = bit_read(16, BF) + 1;
	}
	Header->num_channels = bit_read(4, BF) + 1;
	Header->width = 1 << bit_read(4, BF);
	Header->height = 1 << bit_read(4, BF);
	if (Header->owidth == 0)
	{ // they were equal
		Header->owidth = Header->width;
		Header->oheight = Header->height;
	}
	Header->num_blocks = bit_read(4, BF) + 1;
	Header->size_min_block = bit_read(5, BF);
	Header->size_min_block = Header->size_min_block ? (1 << (Header->size_min_block - 1)) : 0;

	if (Header->width >= 1 && Header->height >= 1 && Header->size_min_block > 0)
		return Header;
	return NULL;
}


//----------------------------------------------------------------------------
// wv_init_decode_channels	decodes a number of channels from a bit-file
//				written to by wv_encode_channels.
//				returns a structure containing all the channels (NULL on fail)
//				BF has to be aligned to the header
// Reduction	Indicates how often to halve the dimensions of the stored channels (minimum is 4x4)
// BF			bit-file handle to be read from (opened in READ-mode)
//----------------------------------------------------------------------------
WAVELET_DLL_API t_wv_dchannels* WAVELET_DLL_CC wv_init_decode_channels(int Reduction, t_bit_file* BF)
{
	t_wv_header hdr;

	if (wv_read_header(&hdr, BF) != NULL)
	{
		t_wv_dchannels* dc = NULL;
		int max_levels = max(0, wv_log2i(min(hdr.width, hdr.height)) - 2);
		int** reorder_table;
		wv_pel* tmp;
		int i, j;

		Reduction = max(0, min(Reduction, min(max_levels - 1, hdr.num_blocks - 1)));

		reorder_table = init_reorder_tables(hdr.width, hdr.owidth, hdr.height, hdr.oheight, max_levels - Reduction, Reduction);
		
		hdr.width >>= Reduction;
		hdr.height >>= Reduction;
		hdr.owidth >>= Reduction;
		hdr.oheight >>= Reduction;
		hdr.num_blocks -= Reduction;
		max_levels -= Reduction;

		dc = malloc(sizeof *dc);
		dc->channels = malloc(hdr.num_channels * sizeof *dc->channels);
		for (i = 0; i < hdr.num_channels; i++)
			dc->channels[i] = malloc(hdr.width * hdr.height * sizeof *dc->channels[i]);
		
		for (i = 0; i < hdr.num_blocks; i++)
		{
			int ofs = (i == 0) ? 0 : (hdr.size_min_block << (2 * (i - 1)));
//			int size = (i == 0) ? size_min_block : ((size_min_block << (2 * i)) - ofs); // original
			int size = (i == 0) ? hdr.size_min_block : 3 * reorder_table[i - 1][0]; // do not read zeroes

			for (j = 0; j < hdr.num_channels; j++)
				rice_decode_block(dc->channels[j] + ofs, size, 0, BF);
		}
		
		tmp = malloc(hdr.width * hdr.height * sizeof *tmp);

		for (i = 0; i < hdr.num_channels; i++)
		{
			unreorder(tmp, dc->channels[i], reorder_table, hdr.width, hdr.height, max_levels);
			inverse_wavelet_transform(tmp, hdr.width, hdr.height, max_levels);
			memcpy(dc->channels[i], tmp, hdr.width * hdr.height * sizeof *dc->channels[i]);
		}

		free(tmp);
		free_reorder_tables(reorder_table, max_levels);
		
		dc->hdr = hdr;
		return dc;
	}
	return NULL;
}


//----------------------------------------------------------------------------
// wv_done_decode_channels	frees the structure allocated
//				by wv_init_decode_channels.
// dc			decompressed channel structure to be freed
//----------------------------------------------------------------------------
WAVELET_DLL_API void WAVELET_DLL_CC wv_done_decode_channels(t_wv_dchannels* dc)
{
	if (dc)
	{
		int i;

		for (i = 0; i < dc->hdr.num_channels; i++)
			free(dc->channels[i]);
		free(dc->channels);
		free(dc);
	}
}

⌨️ 快捷键说明

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