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(); } */