#include <stdlib.h>#include <stdio.h>#include <string.h>#include <limits.h>#include "cbf.h"#include "cbf_alloc.h"#include "cbf_compress.h"#include "cbf_file.h"#include "cbf_packed.h"
Go to the source code of this file.
Classes | |
| struct | cbf_packed_data |
Defines | |
| #define | CBF_SHIFT63 (sizeof (int) * CHAR_BIT > 64 ? 63 : 0) |
| #define | CBF_PACKED_BITS1 4 |
| #define | CBF_PACKED_BITS2 5 |
| #define | CBF_PACKED_BITS3 6 |
| #define | CBF_PACKED_BITS4 7 |
| #define | CBF_PACKED_BITS5 8 |
| #define | CBF_PACKED_BITS6 16 |
| #define | CBF_PACKED_MASK1 ~15 |
| #define | CBF_PACKED_MASK2 ~31 |
| #define | CBF_PACKED_MASK3 ~63 |
| #define | CBF_PACKED_MASK4 ~127 |
| #define | CBF_PACKED_MASK5 ~255 |
| #define | CBF_PACKED_MASK6 ~65535 |
Functions | |
| int | cbf_add_offset (cbf_packed_data *data, unsigned int element, unsigned int last_element) |
| int | cbf_pack_chunk (cbf_packed_data *data, int size, int chunk, cbf_file *file, unsigned long *bitcount) |
| unsigned int | cbf_maximum_size (cbf_packed_data *data, unsigned int start, unsigned int chunk) |
| int | cbf_pack_nextchunk (cbf_packed_data *data, cbf_file *file, unsigned long *bitcount) |
| int | cbf_compress_packed (void *source, size_t elsize, int elsign, size_t nelem, unsigned int compression, cbf_file *file, size_t *compressedsize, int *storedbits) |
| int | cbf_decompress_packed (void *destination, size_t elsize, int elsign, size_t nelem, size_t *nelem_read, unsigned int compression, cbf_file *file) |
Variables | |
| static const unsigned int | cbf_packed_bits [8] |
| #define CBF_PACKED_BITS1 4 |
Definition at line 149 of file cbf_packed.c.
| #define CBF_PACKED_BITS2 5 |
Definition at line 150 of file cbf_packed.c.
| #define CBF_PACKED_BITS3 6 |
Definition at line 151 of file cbf_packed.c.
| #define CBF_PACKED_BITS4 7 |
Definition at line 152 of file cbf_packed.c.
| #define CBF_PACKED_BITS5 8 |
Definition at line 153 of file cbf_packed.c.
| #define CBF_PACKED_BITS6 16 |
Definition at line 154 of file cbf_packed.c.
| #define CBF_PACKED_MASK1 ~15 |
Definition at line 156 of file cbf_packed.c.
Referenced by cbf_add_offset().
| #define CBF_PACKED_MASK2 ~31 |
Definition at line 157 of file cbf_packed.c.
Referenced by cbf_add_offset().
| #define CBF_PACKED_MASK3 ~63 |
Definition at line 158 of file cbf_packed.c.
Referenced by cbf_add_offset().
| #define CBF_PACKED_MASK4 ~127 |
Definition at line 159 of file cbf_packed.c.
Referenced by cbf_add_offset().
| #define CBF_PACKED_MASK5 ~255 |
Definition at line 160 of file cbf_packed.c.
Referenced by cbf_add_offset().
| #define CBF_PACKED_MASK6 ~65535 |
Definition at line 161 of file cbf_packed.c.
Referenced by cbf_add_offset().
| #define CBF_SHIFT63 (sizeof (int) * CHAR_BIT > 64 ? 63 : 0) |
Definition at line 135 of file cbf_packed.c.
Referenced by cbf_compress_packed(), and cbf_decompress_packed().
| int cbf_add_offset | ( | cbf_packed_data * | data, |
| unsigned int | element, | ||
| unsigned int | last_element | ||
| ) |
Definition at line 173 of file cbf_packed.c.
References CBF_PACKED_MASK1, CBF_PACKED_MASK2, CBF_PACKED_MASK3, CBF_PACKED_MASK4, CBF_PACKED_MASK5, CBF_PACKED_MASK6, cbf_packed_data::offset, cbf_packed_data::offsets, cbf_packed_data::size, and cbf_packed_data::start.
Referenced by cbf_compress_packed().
{
int offset;
unsigned int index, m;
/* Save the offset */
index = (data->offsets + data->start) & 127;
offset = element - last_element;
data->offset [index][0] = offset;
/* How many bits do we need to save? */
if (offset == 0)
data->size [index] = 0;
else
if ((element < last_element && offset > 0) ||
(element > last_element && offset < 0))
{
data->offset [index][1] = -(offset > 0);
data->size [index] = 7;
}
else
{
m = (offset ^ (offset << 1));
if ((m & CBF_PACKED_MASK1) == 0)
data->size [index] = 1;
else
if ((m & CBF_PACKED_MASK2) == 0)
data->size [index] = 2;
else
if ((m & CBF_PACKED_MASK3) == 0)
data->size [index] = 3;
else
if ((m & CBF_PACKED_MASK4) == 0)
data->size [index] = 4;
else
if ((m & CBF_PACKED_MASK5) == 0)
data->size [index] = 5;
else
if ((m & CBF_PACKED_MASK6) == 0)
data->size [index] = 6;
else
data->size [index] = 7;
}
/* Success */
data->offsets++;
return 0;
}
| int cbf_compress_packed | ( | void * | source, |
| size_t | elsize, | ||
| int | elsign, | ||
| size_t | nelem, | ||
| unsigned int | compression, | ||
| cbf_file * | file, | ||
| size_t * | compressedsize, | ||
| int * | storedbits | ||
| ) |
Definition at line 390 of file cbf_packed.c.
References cbf_compress_nodestruct::bitcount, cbf_add_offset(), cbf_alloc(), CBF_ARGUMENT, cbf_failnez, cbf_free(), cbf_onfailnez, cbf_pack_nextchunk(), cbf_put_integer(), CBF_SHIFT63, and cbf_compress_nodestruct::count.
Referenced by cbf_compress().
{
unsigned int minelement, maxelement;
unsigned int count, element, lastelement, unsign, sign, limit;
unsigned char *unsigned_char_data;
unsigned long bitcount, chunkbits;
cbf_packed_data *data;
/* Is the element size valid? */
if (elsize != sizeof (int) &&
elsize != sizeof (short) &&
elsize != sizeof (char))
return CBF_ARGUMENT;
/* Allocate memory */
cbf_failnez (cbf_alloc ((void **) &data, NULL, sizeof (cbf_packed_data), 1))
data->start = 0;
data->offsets = 0;
/* Count the expected number of bits */
minelement = 0;
maxelement = 0;
/* Write the number of elements (64 bits) */
cbf_onfailnez (cbf_put_integer (file, nelem, 0, 64),
cbf_free ((void **) data, NULL))
/* Write the minimum element (64 bits) */
cbf_onfailnez (cbf_put_integer (file, minelement, elsign, 64),
cbf_free ((void **) data, NULL))
/* Write the maximum element (64 bits) */
cbf_onfailnez (cbf_put_integer (file, maxelement, elsign, 64),
cbf_free ((void **) data, NULL))
/* Write the reserved entry (64 bits) */
cbf_onfailnez (cbf_put_integer (file, 0, 0, 64),
cbf_free ((void **) data, NULL))
bitcount = 4 * 64;
/* Initialise the pointers */
unsigned_char_data = (unsigned char *) source;
/* Maximum limit (unsigned) is 64 bits */
if (elsize * CHAR_BIT > 64)
{
sign = 1 << CBF_SHIFT63;
limit = ~-(sign << 1);
if (storedbits)
*storedbits = 64;
}
else
{
sign = 1 << (elsize * CHAR_BIT - 1);
limit = ~0;
if (storedbits)
*storedbits = elsize * CHAR_BIT;
}
/* Offset to make the value unsigned */
if (elsign)
unsign = sign;
else
unsign = 0;
/* Start from 0 */
lastelement = unsign;
for (count = 0; count < nelem; count++)
{
/* Get the next element */
if (elsize == sizeof (int))
element = *((unsigned int *) unsigned_char_data);
else
if (elsize == sizeof (short))
element = *((unsigned short *) unsigned_char_data);
else
element = *unsigned_char_data;
unsigned_char_data += elsize;
/* Make the element unsigned */
element += unsign;
/* Limit the value to 64 bits */
if (element > limit)
if (elsign && (int) (element - unsign) < 0)
element = 0;
else
element = limit;
/* Add the offset to the buffer */
cbf_add_offset (data, element, lastelement);
/* Is the buffer full? */
if (data->offsets == 128)
{
/* Write the next block as economically as possible */
cbf_onfailnez (cbf_pack_nextchunk (data, file, &chunkbits),
cbf_free ((void **) data, NULL))
bitcount += chunkbits;
}
/* Update the previous element */
lastelement = element;
}
/* Flush the buffers */
while (data->offsets > 0)
{
cbf_onfailnez (cbf_pack_nextchunk (data, file, &chunkbits),
cbf_free ((void **) data, NULL))
bitcount += chunkbits;
}
/* Return the number of characters written */
if (compressedsize)
*compressedsize = (bitcount + 7) / 8;
/* Free memory */
return cbf_free ((void **) &data, NULL);
}
| int cbf_decompress_packed | ( | void * | destination, |
| size_t | elsize, | ||
| int | elsign, | ||
| size_t | nelem, | ||
| size_t * | nelem_read, | ||
| unsigned int | compression, | ||
| cbf_file * | file | ||
| ) |
Definition at line 594 of file cbf_packed.c.
References bits(), CBF_ARGUMENT, cbf_failnez, cbf_get_bits(), cbf_get_integer(), CBF_SHIFT63, cbf_compress_nodestruct::count, and cbf_compress_nodestruct::next.
Referenced by cbf_decompress().
{
unsigned int next, pixel, pixelcount;
unsigned int bits, element, sign, unsign, limit, count64, count;
unsigned char *unsigned_char_data;
unsigned int offset [4], last_element [4];
int errorcode;
/* Is the element size valid? */
if (elsize != sizeof (int) &&
elsize != sizeof (short) &&
elsize != sizeof (char))
return CBF_ARGUMENT;
/* Initialise the pointer */
unsigned_char_data = (unsigned char *) destination;
/* Maximum limit (unsigned) is 64 bits */
if (elsize * CHAR_BIT > 64)
{
sign = 1 << CBF_SHIFT63;
limit = ~-(sign << 1);
}
else
{
sign = 1 << (elsize * CHAR_BIT - 1);
if (elsize == sizeof (int))
limit = ~0;
else
limit = ~-(1 << (elsize * CHAR_BIT));
}
/* Offset to make the value unsigned */
if (elsign)
unsign = sign;
else
unsign = 0;
/* How many ints do we need to hold 64 bits? */
count64 = (64 + sizeof (int) * CHAR_BIT - 1) / (sizeof (int) * CHAR_BIT);
/* Initialise the first element */
last_element [0] = unsign;
for (count = 1; count < count64; count++)
last_element [count] = 0;
/* Discard the reserved entry (64 bits) */
cbf_failnez (cbf_get_integer (file, NULL, 0, 64))
/* Read the elements */
count = 0;
while (count < nelem)
{
/* Get the next 6 bits of data */
errorcode = cbf_get_integer (file, (int *) &next, 0, 6);
if (errorcode)
{
if (nelem_read)
*nelem_read = count + pixel;
return errorcode;
}
/* Decode bits 0-5 */
pixelcount = 1 << (next & 7);
bits = cbf_packed_bits [(next >> 3) & 7];
/* Read the offsets */
if (pixelcount + count > nelem)
pixelcount = nelem - count;
for (pixel = 0; pixel < pixelcount; pixel++)
{
/* Read an offset */
if (bits)
{
errorcode = cbf_get_bits (file, (int *) offset, bits);
if (errorcode)
{
if (nelem_read)
*nelem_read = count + pixel;
return errorcode;
}
/* Update the current element */
last_element [0] += offset [0];
}
element = last_element [0];
/* Limit the value to fit the element size */
if (element > limit)
if (elsign && (int) (element - unsign) < 0)
element = 0;
else
element = limit;
/* Make the element signed? */
element -= unsign;
/* Save the element */
if (elsize == sizeof (int))
*((unsigned int *) unsigned_char_data) = element;
else
if (elsize == sizeof (short))
*((unsigned short *) unsigned_char_data) = element;
else
*unsigned_char_data = element;
unsigned_char_data += elsize;
}
count += pixelcount;
}
/* Number read */
if (nelem_read)
*nelem_read = count;
/* Success */
return 0;
}
| unsigned int cbf_maximum_size | ( | cbf_packed_data * | data, |
| unsigned int | start, | ||
| unsigned int | chunk | ||
| ) |
Definition at line 311 of file cbf_packed.c.
References cbf_compress_nodestruct::count, cbf_packed_data::size, and cbf_packed_data::start.
Referenced by cbf_pack_nextchunk().
| int cbf_pack_chunk | ( | cbf_packed_data * | data, |
| int | size, | ||
| int | chunk, | ||
| cbf_file * | file, | ||
| unsigned long * | bitcount | ||
| ) |
Definition at line 259 of file cbf_packed.c.
References cbf_failnez, cbf_put_bits(), cbf_put_integer(), cbf_compress_nodestruct::count, cbf_packed_data::offset, cbf_packed_data::offsets, and cbf_packed_data::start.
Referenced by cbf_pack_nextchunk().
{
unsigned int count, index;
/* Write the codes */
cbf_failnez (cbf_put_integer (file, (size << 3) | chunk, 0, 6))
chunk = 1 << chunk;
if (size > 0)
{
index = data->start;
for (count = chunk; count; count--, index++)
cbf_failnez (cbf_put_bits (file, data->offset [index & 127],
cbf_packed_bits [size]))
}
/* Update the buffer count and start */
data->start = (data->start + chunk) & 127;
data->offsets -= chunk;
/* Calculate the number of bits written */
if (bitcount)
if (size)
*bitcount = 6 + chunk * cbf_packed_bits [size];
else
*bitcount = 6;
/* Success */
return 0;
}
| int cbf_pack_nextchunk | ( | cbf_packed_data * | data, |
| cbf_file * | file, | ||
| unsigned long * | bitcount | ||
| ) |
Definition at line 338 of file cbf_packed.c.
References bits(), cbf_maximum_size(), cbf_pack_chunk(), and cbf_packed_data::offsets.
Referenced by cbf_compress_packed().
{
unsigned int bits, next_bits, chunk, size, next_size,
combined_bits, combined_size;
/* Number of bits to encode a single offset */
size = cbf_maximum_size (data, 0, 0);
bits = cbf_packed_bits [size] + 6;
chunk = 0;
while (data->offsets >= (2 << chunk))
{
next_size = cbf_maximum_size (data, 1 << chunk, chunk);
next_bits = (cbf_packed_bits [next_size] << chunk) + 6;
if (size > next_size)
{
combined_bits = bits * 2 - 6;
combined_size = size;
}
else
{
combined_bits = next_bits * 2 - 6;
combined_size = next_size;
}
if (combined_bits > bits + next_bits)
return cbf_pack_chunk (data, size, chunk, file, bitcount);
bits = combined_bits;
size = combined_size;
chunk++;
}
return cbf_pack_chunk (data, size, chunk, file, bitcount);
}
const unsigned int cbf_packed_bits[8] [static] |
{ 0, CBF_PACKED_BITS1,
CBF_PACKED_BITS2,
CBF_PACKED_BITS3,
CBF_PACKED_BITS4,
CBF_PACKED_BITS5,
CBF_PACKED_BITS6, 65 }
Definition at line 163 of file cbf_packed.c.
1.7.3