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