11 #define MIN(a, b) (((a) < (b))? (a): (b))
13 static int convert_options(int sz_opts)
19 memset(co, 0, sizeof(int) * NOPTS);
20 co[SZ_MSB_OPTION_MASK] = AEC_DATA_MSB;
21 co[SZ_NN_OPTION_MASK] = AEC_DATA_PREPROCESS;
23 for (i = 1; i < NOPTS; i <<= 1)
30 static int bits_to_bytes(int bit_length)
34 else if (bit_length > 8)
40 static void interleave_buffer(void *dest, const void *src,
41 size_t n, int wordsize)
45 const unsigned char *src8;
48 src8 = (unsigned char *)src;
49 dest8 = (unsigned char *)dest;
51 for (i = 0; i < n / wordsize; i++)
52 for (j = 0; j < wordsize; j++)
53 dest8[j * (n / wordsize) + i] = src8[i * wordsize + j];
56 static void deinterleave_buffer(void *dest, const void *src,
57 size_t n, int wordsize)
61 const unsigned char *src8;
64 src8 = (unsigned char *)src;
65 dest8 = (unsigned char *)dest;
67 for (i = 0; i < n / wordsize; i++)
68 for (j = 0; j < wordsize; j++)
69 dest8[i * wordsize + j] = src8[j * (n / wordsize) + i];
72 static void add_padding(void *dest, const void *src, size_t src_length,
73 size_t line_size, size_t padding_size,
74 int pixel_size, int pp)
76 size_t i, j, k, ls, ps;
78 const char zero_pixel[] = {0, 0, 0, 0};
83 while (i < src_length) {
84 ls = MIN(src_length - i, line_size);
85 memcpy((char *)dest + j, (char *)src + i, ls);
89 pixel = (char *)src + i - pixel_size;
90 ps = line_size + padding_size - ls;
91 for (k = 0; k < ps; k += pixel_size)
92 memcpy((char *)dest + j + k, pixel, pixel_size);
97 static void remove_padding(void *buf, size_t buf_length,
98 size_t line_size, size_t padding_size,
102 size_t padded_line_size = line_size + padding_size;
105 for (j = padded_line_size; j < buf_length; j += padded_line_size) {
106 memmove((char *)buf + i, (char *)buf + j, line_size);
111 int SZ_BufftoBuffCompress(void *dest, size_t *destLen,
112 const void *source, size_t sourceLen,
115 struct aec_stream strm;
126 strm.block_size = param->pixels_per_block;
127 strm.rsi = (param->pixels_per_scanline + param->pixels_per_block - 1)
128 / param->pixels_per_block;
129 strm.flags = AEC_NOT_ENFORCE | convert_options(param->options_mask);
130 strm.avail_out = *destLen;
131 strm.next_out = dest;
135 interleave = param->bits_per_pixel == 32 || param->bits_per_pixel == 64;
137 strm.bits_per_sample = 8;
138 buf = malloc(sourceLen);
140 status = SZ_MEM_ERROR;
143 interleave_buffer(buf, source, sourceLen, param->bits_per_pixel / 8);
145 strm.bits_per_sample = param->bits_per_pixel;
146 buf = (void *)source;
149 pixel_size = bits_to_bytes(strm.bits_per_sample);
151 scanlines = (sourceLen / pixel_size + param->pixels_per_scanline - 1)
152 / param->pixels_per_scanline;
153 padbuf_size = strm.rsi * strm.block_size * pixel_size * scanlines;
154 padbuf = malloc(padbuf_size);
155 if (padbuf == NULL) {
156 status = SZ_MEM_ERROR;
161 (strm.rsi * strm.block_size - param->pixels_per_scanline)
164 add_padding(padbuf, buf, sourceLen,
165 param->pixels_per_scanline * pixel_size,
166 padding_size, pixel_size,
167 strm.flags & AEC_DATA_PREPROCESS);
168 strm.next_in = padbuf;
169 strm.avail_in = padbuf_size;
171 aec_status = aec_buffer_encode(&strm);
172 if (aec_status == AEC_STREAM_ERROR)
173 status = SZ_OUTBUFF_FULL;
176 *destLen = strm.total_out;
181 if (interleave && buf)
186 int SZ_BufftoBuffDecompress(void *dest, size_t *destLen,
187 const void *source, size_t sourceLen,
190 struct aec_stream strm;
195 size_t buf_size, total_out;
201 strm.block_size = param->pixels_per_block;
202 strm.rsi = (param->pixels_per_scanline + param->pixels_per_block - 1)
203 / param->pixels_per_block;
204 strm.flags = convert_options(param->options_mask);
205 strm.avail_in = sourceLen;
206 strm.next_in = source;
209 pad_scanline = param->pixels_per_scanline % param->pixels_per_block;
210 deinterleave = param->bits_per_pixel == 32 || param->bits_per_pixel == 64;
211 extra_buffer = pad_scanline || deinterleave;
214 strm.bits_per_sample = 8;
216 strm.bits_per_sample = param->bits_per_pixel;
218 pixel_size = bits_to_bytes(strm.bits_per_sample);
222 scanlines = (*destLen / pixel_size + param->pixels_per_scanline - 1)
223 / param->pixels_per_scanline;
224 buf_size = strm.rsi * strm.block_size * pixel_size * scanlines;
228 buf = malloc(buf_size);
230 status = SZ_MEM_ERROR;
234 strm.avail_out = buf_size;
236 strm.next_out = dest;
237 strm.avail_out = *destLen;
240 status = aec_buffer_decode(&strm);
241 if (status != AEC_OK)
246 (strm.rsi * strm.block_size - param->pixels_per_scanline)
248 remove_padding(buf, strm.total_out,
249 param->pixels_per_scanline * pixel_size,
250 padding_size, pixel_size);
251 total_out = scanlines * param->pixels_per_scanline * pixel_size;
253 total_out = strm.total_out;
256 if (total_out < *destLen)
257 *destLen = total_out;
260 deinterleave_buffer(dest, buf, *destLen, param->bits_per_pixel / 8);
261 else if (pad_scanline)
262 memcpy(dest, buf, *destLen);
265 if (extra_buffer && buf)
271 int SZ_encoder_enabled(void)
276 /* netcdf searches for SZ_Compress in configure */
277 char SZ_Compress() { return SZ_OK; }