From 2a2e588b28df54c3ef91b32b65d4f1aeca6c779c Mon Sep 17 00:00:00 2001 From: Mathis Rosenhauer Date: Tue, 20 Nov 2012 14:25:36 +0100 Subject: [PATCH] Addition and removal of padding in SZ compatibility --- src/sz_compat.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file 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; } -- 2.7.4