91ccad7ecc1047bdaebf1bf7d29ea7c06cd4856a
[platform/upstream/libaec.git] / src / sz_compat.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "szlib.h"
5
6 #define NOPTS 129
7
8 static int convert_options(int sz_opts)
9 {
10     int co[NOPTS];
11     int i;
12     int opts = 0;
13
14     memset(co, 0, sizeof(int) * NOPTS);
15     co[SZ_MSB_OPTION_MASK] = AEC_DATA_MSB;
16     co[SZ_NN_OPTION_MASK] = AEC_DATA_PREPROCESS;
17
18     for (i = 1; i < NOPTS; i <<= 1)
19         if (sz_opts & i)
20             opts |= co[i];
21
22     return opts;
23 }
24
25 static int bits_to_bytes(int bit_length)
26 {
27     if (bit_length > 16)
28         return 4;
29     else if (bit_length > 8)
30         return 2;
31     else
32         return 1;
33 }
34
35 static void interleave_buffer(void *dest, const void *src,
36                               size_t n, int wordsize)
37 {
38     size_t i, j;
39     const unsigned char *src8;
40     unsigned char *dest8;
41
42     src8 = (unsigned char *)src;
43     dest8 = (unsigned char *)dest;
44
45     for (i = 0; i < n / wordsize; i++)
46         for (j = 0; j < wordsize; j++)
47             dest8[j * (n / wordsize) + i] = src8[i * wordsize + j];
48 }
49
50 static void deinterleave_buffer(void *dest, const void *src,
51                                 size_t n, int wordsize)
52 {
53     size_t i, j;
54     const unsigned char *src8;
55     unsigned char *dest8;
56
57     src8 = (unsigned char *)src;
58     dest8 = (unsigned char *)dest;
59
60     for (i = 0; i < n / wordsize; i++)
61         for (j = 0; j < wordsize; j++)
62             dest8[i * wordsize + j] = src8[j * (n / wordsize) + i];
63 }
64
65 static size_t add_padding(void *dest, const void *src, size_t total,
66                           size_t line_size, size_t padding_size,
67                           int pixel_size, int pp)
68 {
69     size_t i, j, k;
70     const char *pixel;
71     const char zero_pixel[] = {0, 0, 0, 0, 0, 0, 0, 0};
72     size_t padded_line_size = line_size + padding_size;
73
74     pixel = zero_pixel;
75     j = 0;
76     for (i = 0; i < total; i += line_size) {
77         if (i + line_size > total) {
78             line_size = total - i;
79             padding_size = padded_line_size - line_size;
80         }
81         memcpy((char *)dest + j, (char *)src + i, line_size);
82         j += line_size;
83         if (pp)
84             pixel = (char *)src + i + line_size - pixel_size;
85         for (k = 0; k < padding_size; k += pixel_size)
86             memcpy((char *)dest + j + k, pixel, pixel_size);
87         j += padding_size;
88     }
89     return j;
90 }
91
92 static size_t remove_padding(void *buf, size_t total,
93                              size_t line_size, size_t padding_size,
94                              int pixel_size)
95 {
96     size_t i, j;
97     size_t padded_line_size = line_size + padding_size;
98
99     i = line_size;
100     for (j = padded_line_size; j < total; j += padded_line_size) {
101         memmove((char *)buf + i, (char *)buf + j, line_size);
102         i += line_size;
103     }
104     return i;
105 }
106
107 int SZ_BufftoBuffCompress(void *dest, size_t *destLen,
108                           const void *source, size_t sourceLen,
109                           SZ_com_t *param)
110 {
111     struct aec_stream strm;
112     int status;
113     void *padbuf = 0;
114     void *buf = 0;
115     size_t padding_size;
116     size_t padded_length;
117     size_t scanlines;
118     size_t buf_size;
119     int pixel_size;
120     int pad_scanline;
121     int interleave;
122
123     strm.block_size = param->pixels_per_block;
124     strm.rsi = (param->pixels_per_scanline + param->pixels_per_block - 1)
125         / param->pixels_per_block;
126     strm.flags = convert_options(param->options_mask);
127     strm.avail_out = *destLen;
128     strm.next_out = dest;
129
130     pad_scanline = param->pixels_per_scanline % param->pixels_per_block;
131     interleave = param->bits_per_pixel == 32 || param->bits_per_pixel == 64;
132
133     if (interleave) {
134         strm.bits_per_sample = 8;
135         buf = malloc(sourceLen);
136         if (buf == NULL)
137             return SZ_MEM_ERROR;
138         interleave_buffer(buf, source, sourceLen, param->bits_per_pixel / 8);
139     } else {
140         strm.bits_per_sample = param->bits_per_pixel;
141         buf = (void *)source;
142     }
143
144     pixel_size = bits_to_bytes(strm.bits_per_sample);
145
146     if (pad_scanline) {
147         scanlines = (sourceLen / pixel_size + param->pixels_per_scanline - 1)
148             / param->pixels_per_scanline;
149         buf_size = strm.rsi * param->pixels_per_block * pixel_size * scanlines;
150
151         padbuf = malloc(buf_size);
152         if (padbuf == NULL)
153             return SZ_MEM_ERROR;
154
155         padding_size = (
156             param->pixels_per_block -
157             (param->pixels_per_scanline % param->pixels_per_block)
158             ) * pixel_size;
159
160         padded_length = add_padding(padbuf, buf, sourceLen,
161                                     param->pixels_per_scanline * pixel_size,
162                                     padding_size, pixel_size,
163                                     strm.flags & AEC_DATA_PREPROCESS);
164
165         strm.next_in = padbuf;
166         strm.avail_in = padded_length;
167     } else {
168         strm.next_in = buf;
169         strm.avail_in = sourceLen;
170     }
171
172     status = aec_buffer_encode(&strm);
173     if (status != AEC_OK)
174         return status;
175
176     *destLen = strm.total_out;
177
178     if (pad_scanline && padbuf)
179         free(padbuf);
180
181     if (interleave && buf)
182         free(buf);
183
184     return SZ_OK;
185 }
186
187 int SZ_BufftoBuffDecompress(void *dest, size_t *destLen,
188                             const void *source, size_t sourceLen,
189                             SZ_com_t *param)
190 {
191     struct aec_stream strm;
192     int status;
193     void *buf = 0;
194     size_t padding_size;
195     size_t scanlines;
196     size_t buf_size, total_out;
197     int pixel_size;
198     int pad_scanline;
199     int deinterleave;
200     int extra_buffer;
201
202     strm.block_size = param->pixels_per_block;
203     strm.rsi = (param->pixels_per_scanline + param->pixels_per_block - 1)
204         / param->pixels_per_block;
205     strm.flags = convert_options(param->options_mask);
206     strm.avail_in = sourceLen;
207     strm.next_in = source;
208
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;
212
213     if (deinterleave)
214         strm.bits_per_sample = 8;
215     else
216         strm.bits_per_sample = param->bits_per_pixel;
217
218     pixel_size = bits_to_bytes(strm.bits_per_sample);
219
220     if (extra_buffer) {
221         if (pad_scanline) {
222             scanlines = (*destLen / pixel_size + param->pixels_per_scanline - 1)
223                 / param->pixels_per_scanline;
224             buf_size = strm.rsi * param->pixels_per_block
225                 * pixel_size * scanlines;
226         } else {
227             buf_size = *destLen;
228         }
229         buf = malloc(buf_size);
230         if (buf == NULL)
231             return SZ_MEM_ERROR;
232         strm.next_out = buf;
233         strm.avail_out = buf_size;
234     } else {
235         strm.next_out = dest;
236         strm.avail_out = *destLen;
237     }
238
239     status = aec_buffer_decode(&strm);
240     if (status != AEC_OK)
241         return status;
242
243     if (pad_scanline) {
244         padding_size = (
245             param->pixels_per_block -
246             (param->pixels_per_scanline % param->pixels_per_block)
247             ) * pixel_size;
248         total_out = remove_padding(buf, strm.total_out,
249                                    param->pixels_per_scanline * pixel_size,
250                                    padding_size, pixel_size);
251     } else {
252         total_out = strm.total_out;
253     }
254
255     if (total_out < *destLen)
256         *destLen = total_out;
257
258     if (deinterleave)
259         deinterleave_buffer(dest, buf, *destLen, param->bits_per_pixel / 8);
260     else if (pad_scanline)
261         memcpy(dest, buf, *destLen);
262
263     if (extra_buffer && buf)
264         free(buf);
265
266     return SZ_OK;
267 }
268
269 int SZ_encoder_enabled(void)
270 {
271     return 1;
272 }