www.pudn.com > Jpeg2000en.rar > BIT.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  
#include  
#include  
#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->mask = 0x80; 
		f->mode[0] = toupper(mode[0]); 
		f->mode[1] = toupper(mode[1]); 
		if (f->mode[0] == 'W') 
			memset(f->buffer, 0, f->bufsize * sizeof *f->buffer); 
	} 
	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 + (f->mask != 0x80 && f->mask != 0x00); 
 
		if (num > 0) 
		{ 
			fwrite(f->buffer, sizeof *f->buffer, num, f->file); 
			f->idx = 0; 
			f->mask = 0x80; 
			f->bufleft = f->bufsize; 
			memset(f->buffer, 0, f->bufsize * sizeof *f->buffer); 
		} 
	} 
} 
 
 
//---------------------------------------------------------------------------- 
// 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 (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 int WAVELET_DLL_CC bit_read(const int num, t_bit_file* f) 
{ 
	int out = 0; 
 
	if (num > 0 && f) 
	{ 
		int i; 
 
		for (i = 0; i < num; i++) 
		{ 
			out <<= 1; 
			if (f->bits_left-- > 0 && f->idx < f->bufleft) 
			{ 
				out |= (f->buffer[f->idx] & 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); 
					} 
				} 
			} 
		} 
	} 
	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 int bits, const int num, t_bit_file* f) 
{ 
	if (f && num > 0) 
	{ 
		int in_mask = 1 << (num - 1); 
		int i; 
 
		for (i = 0; i < num; i++, in_mask >>= 1) 
		{ 
			f->buffer[f->idx] |= (bits & in_mask) ? f->mask : 0; 
			f->bits_left++; 
			f->mask >>= 1; 
			if (f->mask == 0x00) 
			{ // filled a byte 
				f->mask = 0x80; 
				if (++f->idx >= f->bufsize) 
				{ 
					if (f->file) 
						bit_flush(f); 
					else 
					{ 
						f->bufsize *= 2; 
						f->buffer = realloc(f->buffer, f->bufsize); 
						memset(f->buffer + f->bufsize / 2, 0, (f->bufsize / 2) * sizeof *f->buffer); 
					} 
				} 
			} 
		} 
	} 
	return num; 
} 
 
// some debug things for tracking down memory leaks using the VisualC debug-heap 
 
/*#include  
 
WAVELET_DLL_API void WAVELET_DLL_CC wv_debug_init(void) 
{ 
//	_CrtSetBreakAlloc(222); 
} 
 
WAVELET_DLL_API void WAVELET_DLL_CC wv_debug(void) 
{ 
   _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_WNDW); 
   _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_WNDW); 
   _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_WNDW); 
   _CrtDumpMemoryLeaks(); 
} 
*/