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)
{
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;
}
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;
}