📄 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 <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 + -