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

📄 bit.c

📁 c++ Builder中网络图象渐进传输实例
💻 C
字号:
// --------------- BIT ROUTINES ---------------
// wavelet image compression
// these provide bit-access to files either on disk or in memory
// (c) 2001-2002 Daniel Vollmer (maven@maven.de)

/* 	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA	02111-1307	USA
*/

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "bit.h"


// default size of the buffer (in bytes)
#define BIT_BUFFER 1024



//----------------------------------------------------------------------------
// bit_open		opens a file as bit-stream
//				returns a handle to the bit_file
// name			filename of the file (if mode != 'm') or pointer to the
//				memory block to read from
// mode			mode[0] = 'r' or 'w' (read / write), mode[1] = 'b' or 'm'
//				(disk or memory)
// mem_size		size of the buffer (in bits) (when reading from mem) or
//				maximum number of bits_to read from disk (0 reads all bits)
//----------------------------------------------------------------------------
WAVELET_DLL_API t_bit_file* WAVELET_DLL_CC bit_open(char* name, const char *mode, const int mem_size)
{
	t_bit_file* f = NULL;
	int mem_bytes = mem_size ? mem_size / 8 + (mem_size % 8 != 0) : 0;

	if (mode[1] == 'm' || mode[1] == 'M')
	{ // from / to mem
		if (((mode[0] == 'r' || mode[0] == 'R') && name && mem_size > 0) || (mode[0] == 'w' || mode[0] == 'W'))
		{
			f = malloc(sizeof *f);
			f->file = NULL;
			f->bits_left = 0;
			if ((mode[0] == 'r' || mode[0] == 'R'))
			{
				f->bufsize = f->bufleft = mem_bytes;
				f->buffer = (unsigned char*)name;
				f->bits_left = mem_size;
			}
			else
			{
				f->bufsize = f->bufleft = mem_bytes ? mem_bytes : BIT_BUFFER;
				f->buffer = malloc(f->bufsize * sizeof *f->buffer);
			}
		}
	}
	else
	{
		FILE* file = fopen(name, mode);

		if (file)
		{
			f = malloc(sizeof *f);

			f->file = file;
			f->bits_left = 0;
			f->bufsize = f->bufleft = mem_bytes ? mem_bytes : BIT_BUFFER;
			f->buffer = malloc(f->bufsize * sizeof *f->buffer);
			if (mode[0] == 'r' || mode[0] == 'R')
			{
				f->bufleft = fread(f->buffer, sizeof *f->buffer, f->bufsize, f->file);
				f->bits_left = mem_size ? mem_size : (1 << 30);
			}
		}
	}
	if (f)
	{
		f->idx = 0;
		f->mode[0] = (char)toupper(mode[0]);
		f->mode[1] = (char)toupper(mode[1]);
		if (f->mode[0] == 'W')
		{
			f->mask = 8;
			f->current_byte = 0;
		}
		else
		{
			f->mask = 0x80;
			f->current_byte = f->buffer[f->idx];
		}
	}
	return f;
}

// flushes the contents of the buffer into the file
static void bit_flush(t_bit_file* f)
{
	if (f && f->file)
	{
		int num = f->idx;

		if (f->mask != 8 && f->mask != 0)
		{
			while (f->mask > 0)
			{
				f->current_byte <<= 1;
				f->mask--;
			}
			f->buffer[f->idx] = f->current_byte;
			num++;
		}

		if (num > 0)
		{
			fwrite(f->buffer, sizeof *f->buffer, num, f->file);
			f->idx = 0;
			f->mask = 8;
			f->bufleft = f->bufsize;
			f->current_byte = 0;
		}
	}
}


//----------------------------------------------------------------------------
// bit_close	closes a bit-stream opened with bit_open
//				returns the number fo bits written (in WRITE-mode)
// f			handle to the bit_file
// mem			when writing to memory and mem != NULL,
//				then mem receives the pointer to the write-buffer
//				when reading from memory and mem == the pointer passed 
//				on bit_open, the buffer is freed
//----------------------------------------------------------------------------
WAVELET_DLL_API int WAVELET_DLL_CC bit_close(t_bit_file* f, unsigned char** mem)
{
	int ret = 0;

	if (f)
	{
		if (f->file)
		{
			if (f->mode[0] == 'W')
			{
				ret = f->bits_left;
				bit_flush(f);
			}
			free(f->buffer);
			fclose(f->file);
		}
		else 
		{
			if (f->mode[0] == 'W')
			{
				ret = f->bits_left;
				if (f->mask != 8 && f->mask != 0)
				{
					while (f->mask > 0)
					{
						f->current_byte <<= 1;
						f->mask--;
					}
					f->buffer[f->idx] = f->current_byte;
				}				
				if (mem)
					*mem = f->buffer;
				else
					free(f->buffer);
			}
			else if (f->mode[0] == 'R' && f->buffer == (unsigned char*)mem)
				free(f->buffer);
		}
		free(f);
	}
	return ret;
}


//----------------------------------------------------------------------------
// bit_read		reads the number of given bits from a bit_file
//				(which has to be opened in READ-mode)
//				returns the bits as an integer
//				(bits read first are in higher bit-positions)
// num			number of bits to read
// f			handle to the bit_file (READ-mode)
//----------------------------------------------------------------------------
WAVELET_DLL_API unsigned int WAVELET_DLL_CC bit_read(int num, t_bit_file* f)
{
	unsigned int out = 0;

	while (num > 0)
	{
		out <<= 1;
		num--;
		if (f->bits_left-- > 0 && f->idx < f->bufleft)
		{
			out += (f->current_byte & f->mask) != 0x00;
			f->mask >>= 1;
			if (f->mask == 0x00)
			{ // read a byte
				f->mask = 0x80;
				if (++f->idx >= f->bufleft)
				{
					f->idx = 0;
					f->bufleft = 0;
					if (f->file)
						f->bufleft = fread(f->buffer, 1, f->bufsize * sizeof *f->buffer, f->file);
				}
				while (num >= 8 && f->bits_left >= 8 && f->idx < f->bufleft - 1)
				{ // write whole bytes directly
					out = (out << 8) + f->buffer[f->idx++];
					f->bits_left -= 8;
					num -= 8;
				}
				f->current_byte = f->buffer[f->idx];
			}
		}
	}
	return out;
}


//----------------------------------------------------------------------------
// bit_read_single	reads a single bit from a bit_file
//				(which has to be opened in READ-mode)
//				returns the bit as an integer
// f			handle to the bit_file (READ-mode)
//----------------------------------------------------------------------------
WAVELET_DLL_API unsigned int WAVELET_DLL_CC bit_read_single(t_bit_file* f)
{
	unsigned int out = 0;

	if (f->bits_left-- > 0 && f->idx < f->bufleft)
	{
		out = (f->current_byte & f->mask) != 0x00;
		f->mask >>= 1;
		if (f->mask == 0x00)
		{ // read a byte
			f->mask = 0x80;
			if (++f->idx >= f->bufleft)
			{
				f->idx = 0;
				f->bufleft = 0;
				if (f->file)
					f->bufleft = fread(f->buffer, 1, f->bufsize * sizeof *f->buffer, f->file);
			}
			f->current_byte = f->buffer[f->idx];
		}
	}
	return out;
}

//----------------------------------------------------------------------------
// bit_write	writes the number of given bits to a bit_file
//				(which has to be opened in WRITE-mode)
//				returns number of bits written
// bits			bits to be written (most significant bits are written first)
// num			number of bits to write
// f			handle to the bit_file (WRITE-mode)
//----------------------------------------------------------------------------
WAVELET_DLL_API int WAVELET_DLL_CC bit_write(const unsigned int bits, const int num, t_bit_file* f)
{
	int num_left = num;

	while (num_left > 0)
	{
		unsigned int in_mask = 1 << (num_left - 1);

		f->current_byte = (f->current_byte << 1) + ((bits & in_mask) != 0);
		f->bits_left++;
		num_left--;
		if (--f->mask == 0x00)
		{ // filled a byte
			f->buffer[f->idx] = f->current_byte;
			f->current_byte = 0;
			f->mask = 8;
			if (++f->idx >= f->bufsize - (int)sizeof(bits))
			{ // so that we have enough space for up to three bytes (and the next bit)
				if (f->file)
					bit_flush(f);
				else
				{
					f->bufsize *= 2;
					f->buffer = realloc(f->buffer, f->bufsize);
				}
			}
			while (num_left >= 8)
			{ // write whole bytes directly
				f->buffer[f->idx++] = (unsigned char)(bits >> (num_left - 8));
				in_mask >>= 8;
				f->bits_left += 8;
				num_left -= 8;
			}
		}
	}
	return num;
}

//----------------------------------------------------------------------------
// bit_write_zero	writes a single zero bit to a bit_file
//				(which has to be opened in WRITE-mode)
//				returns number of bits written
// f			handle to the bit_file (WRITE-mode)
//----------------------------------------------------------------------------
WAVELET_DLL_API int WAVELET_DLL_CC bit_write_zero(t_bit_file* f)
{
	f->bits_left++;
	f->current_byte <<= 1;
	if (--f->mask == 0x00)
	{ // filled a byte
		f->buffer[f->idx] = f->current_byte;
		f->current_byte = 0;
		f->mask = 8;
		if (++f->idx >= f->bufsize)
		{
			if (f->file)
				bit_flush(f);
			else
			{
				f->bufsize *= 2;
				f->buffer = realloc(f->buffer, f->bufsize);
			}
		}
	}
	return 1;
}

⌨️ 快捷键说明

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