summaryrefslogtreecommitdiff
path: root/src/sz_compat.c
diff options
context:
space:
mode:
authorMathis Rosenhauer <rosenhauer@dkrz.de>2012-11-20 14:25:36 +0100
committerThomas Jahns <jahns@dkrz.de>2013-02-19 11:33:00 +0100
commit2a2e588b28df54c3ef91b32b65d4f1aeca6c779c (patch)
tree5d168c0d30f72ad7543e68a48d924d479daa98f6 /src/sz_compat.c
parent0c6860cffa71638b8a263665fb71f3bcda6c5b2d (diff)
downloadlibaec-2a2e588b28df54c3ef91b32b65d4f1aeca6c779c.tar.gz
libaec-2a2e588b28df54c3ef91b32b65d4f1aeca6c779c.tar.bz2
libaec-2a2e588b28df54c3ef91b32b65d4f1aeca6c779c.zip
Addition and removal of padding in SZ compatibility
Diffstat (limited to 'src/sz_compat.c')
-rw-r--r--src/sz_compat.c196
1 files changed, 165 insertions, 31 deletions
diff --git a/src/sz_compat.c b/src/sz_compat.c
index 655f90a..3d4ffed 100644
--- a/src/sz_compat.c
+++ b/src/sz_compat.c
@@ -23,6 +23,16 @@ static int convert_options(int sz_opts)
return opts;
}
+static int bits_to_bytes(int bit_length)
+{
+ if (bit_length > 16)
+ return 4;
+ else if (bit_length > 8)
+ return 2;
+ else
+ return 1;
+}
+
static void interleave_buffer(void *dest, const void *src,
size_t n, int wordsize)
{
@@ -53,43 +63,126 @@ static void deinterleave_buffer(void *dest, const void *src,
dest8[i * wordsize + j] = src8[j * (n / wordsize) + i];
}
+static size_t add_padding(void *dest, const void *src, size_t total,
+ size_t line_size, size_t padding_size,
+ int pixel_size, int pp)
+{
+ size_t i, j, k;
+ const char *pixel;
+ const char zero_pixel[] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+ for (i = 0, j = 0;
+ i < total;
+ i += pixel_size, j += pixel_size) {
+ if (i > 0 && (i % line_size) == 0) {
+ if (pp)
+ pixel = (char *)src + i - 1;
+ else
+ pixel = zero_pixel;
+ for (k = 0; k < padding_size; k += pixel_size)
+ memcpy((char *)dest + j + k, pixel, pixel_size);
+ j += padding_size;
+ }
+ memcpy((char *)dest + j, (char *)src + i, pixel_size);
+ }
+ return j;
+}
+
+static size_t remove_padding(void *buf, size_t total,
+ size_t line_size, size_t padding_size,
+ int pixel_size)
+{
+ size_t i, j;
+
+ for (i = 0, j = padding_size;
+ i < total;
+ i += pixel_size, j += pixel_size) {
+ if (i % (line_size + padding_size) == 0)
+ j -= padding_size;
+ memcpy((char *)buf + j, (char *)buf + i, pixel_size);
+ }
+ if ((i % (line_size + padding_size)) == 0)
+ j -= padding_size;
+ return j;
+}
+
int SZ_BufftoBuffCompress(void *dest, size_t *destLen,
const void *source, size_t sourceLen,
SZ_com_t *param)
{
- int status;
struct aec_stream strm;
+ int status;
+ void *padbuf;
void *buf;
+ size_t padding_size;
+ size_t padded_length;
+ size_t scanlines;
+ size_t buf_size;
+ int pixel_size;
+ int pad_scanline;
+ int interleave;
+
+ strm.block_size = param->pixels_per_block;
+ strm.rsi = (param->pixels_per_scanline + param->pixels_per_block - 1)
+ / param->pixels_per_block;
+ strm.flags = convert_options(param->options_mask);
+ strm.avail_out = *destLen;
+ strm.next_out = dest;
- if (param->bits_per_pixel == 32 || param->bits_per_pixel == 64) {
+ pad_scanline = param->pixels_per_scanline % param->pixels_per_block;
+ interleave = param->bits_per_pixel == 32 || param->bits_per_pixel == 64;
+
+ if (interleave) {
+ strm.bit_per_sample = 8;
buf = malloc(sourceLen);
if (buf == NULL)
return SZ_MEM_ERROR;
-
interleave_buffer(buf, source, sourceLen, param->bits_per_pixel / 8);
- strm.bit_per_sample = 8;
- strm.next_in = buf;
} else {
- strm.next_in = source;
strm.bit_per_sample = param->bits_per_pixel;
+ buf = (void *)source;
}
- strm.avail_in = sourceLen;
- strm.block_size = param->pixels_per_block;
- strm.rsi = param->pixels_per_scanline / param->pixels_per_block;
- strm.flags = convert_options(param->options_mask);
- strm.avail_out = *destLen;
- strm.next_out = dest;
+ pixel_size = bits_to_bytes(strm.bit_per_sample);
+
+ if (pad_scanline) {
+ scanlines = (sourceLen / pixel_size + param->pixels_per_scanline - 1)
+ / param->pixels_per_scanline;
+ buf_size = strm.rsi * param->pixels_per_block * pixel_size * scanlines;
+
+ padbuf = malloc(buf_size);
+ if (padbuf == NULL)
+ return SZ_MEM_ERROR;
+
+ padding_size = (
+ param->pixels_per_block -
+ (param->pixels_per_scanline % param->pixels_per_block)
+ ) * pixel_size;
+
+ padded_length = add_padding(padbuf, buf, sourceLen,
+ param->pixels_per_scanline * pixel_size,
+ padding_size, pixel_size,
+ strm.flags & AEC_DATA_PREPROCESS);
+
+ strm.next_in = padbuf;
+ strm.avail_in = padded_length;
+ } else {
+ strm.next_in = buf;
+ strm.avail_in = sourceLen;
+ }
status = aec_buffer_encode(&strm);
if (status != AEC_OK)
return status;
- if (param->bits_per_pixel == 32 || param->bits_per_pixel == 64) {
+ *destLen = strm.total_out;
+
+ if (pad_scanline)
+ free(padbuf);
+
+ if (interleave)
free(buf);
- }
- *destLen = strm.total_out;
return SZ_OK;
}
@@ -97,39 +190,80 @@ int SZ_BufftoBuffDecompress(void *dest, size_t *destLen,
const void *source, size_t sourceLen,
SZ_com_t *param)
{
- int status;
struct aec_stream strm;
+ int status;
void *buf;
+ size_t padding_size;
+ size_t scanlines;
+ size_t buf_size, total_out;
+ int pixel_size;
+ int pad_scanline;
+ int deinterleave;
+ int extra_buffer;
- if (param->bits_per_pixel == 32 || param->bits_per_pixel == 64) {
- buf = malloc(*destLen);
- if (buf == NULL)
- return SZ_MEM_ERROR;
+ strm.block_size = param->pixels_per_block;
+ strm.rsi = (param->pixels_per_scanline + param->pixels_per_block - 1)
+ / param->pixels_per_block;
+ strm.flags = convert_options(param->options_mask);
+ strm.avail_in = sourceLen;
+ strm.next_in = source;
+
+ pad_scanline = param->pixels_per_scanline % param->pixels_per_block;
+ deinterleave = param->bits_per_pixel == 32 || param->bits_per_pixel == 64;
+ extra_buffer = pad_scanline || deinterleave;
+ if (deinterleave)
strm.bit_per_sample = 8;
+ else
+ strm.bit_per_sample = param->bits_per_pixel;
+
+ pixel_size = bits_to_bytes(strm.bit_per_sample);
+
+ if (extra_buffer) {
+ if (pad_scanline) {
+ scanlines = (*destLen / pixel_size + param->pixels_per_scanline - 1)
+ / param->pixels_per_scanline;
+ buf_size = strm.rsi * param->pixels_per_block
+ * pixel_size * scanlines;
+ } else {
+ buf_size = *destLen;
+ }
+ buf = malloc(buf_size);
+ if (buf == NULL)
+ return SZ_MEM_ERROR;
strm.next_out = buf;
+ strm.avail_out = buf_size;
} else {
strm.next_out = dest;
- strm.bit_per_sample = param->bits_per_pixel;
+ strm.avail_out = *destLen;
}
- strm.block_size = param->pixels_per_block;
- strm.rsi = param->pixels_per_scanline / param->pixels_per_block;
- strm.flags = convert_options(param->options_mask);
- strm.avail_in = sourceLen;
- strm.avail_out = *destLen;
- strm.next_in = source;
-
status = aec_buffer_decode(&strm);
if (status != AEC_OK)
return status;
- *destLen = strm.total_out;
+ if (pad_scanline) {
+ padding_size = (
+ param->pixels_per_block -
+ (param->pixels_per_scanline % param->pixels_per_block)
+ ) * pixel_size;
+ total_out = remove_padding(buf, strm.total_out,
+ param->pixels_per_scanline * pixel_size,
+ padding_size, pixel_size);
+ } else {
+ total_out = strm.total_out;
+ }
+
+ if (total_out < *destLen)
+ *destLen = total_out;
- if (param->bits_per_pixel == 32 || param->bits_per_pixel == 64) {
+ if (deinterleave)
deinterleave_buffer(dest, buf, *destLen, param->bits_per_pixel / 8);
+ else if (pad_scanline)
+ memcpy(dest, buf, *destLen);
+
+ if (extra_buffer)
free(buf);
- }
return SZ_OK;
}