svn update: 51457 (latest:51480)
[framework/uifw/eet.git] / src / lib / eet_image.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif /* ifdef HAVE_CONFIG_H */
4
5 #ifdef HAVE_ALLOCA_H
6 # include <alloca.h>
7 #elif defined __GNUC__
8 # define alloca __builtin_alloca
9 #elif defined _AIX
10 # define alloca __alloca
11 #elif defined _MSC_VER
12 # include <malloc.h>
13 # define alloca _alloca
14 #else /* ifdef HAVE_ALLOCA_H */
15 # include <stddef.h>
16 # ifdef  __cplusplus
17 extern "C"
18 # endif /* ifdef  __cplusplus */
19 void *    alloca (size_t);
20 #endif /* ifdef HAVE_ALLOCA_H */
21
22 #ifdef HAVE_NETINET_IN_H
23 # ifdef __OpenBSD__
24 #  include <sys/types.h>
25 # endif /* ifdef __OpenBSD__ */
26 # include <netinet/in.h>
27 #endif /* ifdef HAVE_NETINET_IN_H */
28
29 #ifdef _WIN32
30 # include <winsock2.h>
31 #endif /* ifdef _WIN32 */
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <setjmp.h>
36 #include <zlib.h>
37 #include <jpeglib.h>
38
39 #include "Eet.h"
40 #include "Eet_private.h"
41
42 /*---*/
43
44 typedef struct _JPEG_error_mgr * emptr;
45
46 /*---*/
47
48 struct _JPEG_error_mgr
49 {
50    struct jpeg_error_mgr pub;
51    jmp_buf               setjmp_buffer;
52 };
53
54 struct jpeg_membuf_src
55 {
56    struct jpeg_source_mgr pub;
57
58    const unsigned char   *buf;
59    size_t                 len;
60 };
61
62 static void
63 _eet_jpeg_membuf_src_init(j_decompress_ptr cinfo)
64 {
65    /* FIXME: Use attribute unused */
66    (void)cinfo;
67 } /* _eet_jpeg_membuf_src_init */
68
69 static boolean
70 _eet_jpeg_membuf_src_fill(j_decompress_ptr cinfo)
71 {
72    static const JOCTET jpeg_eoi[2] = { 0xFF, JPEG_EOI };
73    struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src;
74
75    src->pub.bytes_in_buffer = sizeof(jpeg_eoi);
76    src->pub.next_input_byte = jpeg_eoi;
77
78    return TRUE;
79 } /* _eet_jpeg_membuf_src_fill */
80
81 static void
82 _eet_jpeg_membuf_src_skip(j_decompress_ptr cinfo,
83                           long             num_bytes)
84 {
85    struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src;
86
87    src->pub.bytes_in_buffer -= num_bytes;
88    src->pub.next_input_byte += num_bytes;
89 } /* _eet_jpeg_membuf_src_skip */
90
91 static void
92 _eet_jpeg_membuf_src_term(j_decompress_ptr cinfo)
93 {
94    free(cinfo->src);
95    cinfo->src = NULL;
96 } /* _eet_jpeg_membuf_src_term */
97
98 static int
99 eet_jpeg_membuf_src(j_decompress_ptr cinfo,
100                     const void      *buf,
101                     size_t           len)
102 {
103    struct jpeg_membuf_src *src;
104
105    src = malloc(sizeof(*src));
106    if (!src)
107       return -1;
108
109    cinfo->src = &src->pub;
110    src->buf = buf;
111    src->len = len;
112    src->pub.init_source = _eet_jpeg_membuf_src_init;
113    src->pub.fill_input_buffer = _eet_jpeg_membuf_src_fill;
114    src->pub.skip_input_data = _eet_jpeg_membuf_src_skip;
115    src->pub.resync_to_restart = jpeg_resync_to_restart;
116    src->pub.term_source = _eet_jpeg_membuf_src_term;
117    src->pub.bytes_in_buffer = src->len;
118    src->pub.next_input_byte = src->buf;
119
120    return 0;
121 } /* eet_jpeg_membuf_src */
122
123 struct jpeg_membuf_dst
124 {
125    struct jpeg_destination_mgr pub;
126
127    void                      **dst_buf;
128    size_t                     *dst_len;
129
130    unsigned char              *buf;
131    size_t                      len;
132    int                         failed;
133 };
134
135 static void
136 _eet_jpeg_membuf_dst_init(j_compress_ptr cinfo)
137 {
138    /* FIXME: Use eina attribute */
139    (void)cinfo;
140 } /* _eet_jpeg_membuf_dst_init */
141
142 static boolean
143 _eet_jpeg_membuf_dst_flush(j_compress_ptr cinfo)
144 {
145    struct jpeg_membuf_dst *dst = (struct jpeg_membuf_dst *)cinfo->dest;
146    unsigned char *buf;
147
148    if (dst->len >= 0x40000000 ||
149        (buf = realloc(dst->buf, dst->len * 2)) == NULL)
150      {
151         dst->failed = 1;
152         dst->pub.next_output_byte = dst->buf;
153         dst->pub.free_in_buffer = dst->len;
154         return TRUE;
155      }
156
157    dst->pub.next_output_byte =
158       buf + ((unsigned char *)dst->pub.next_output_byte - dst->buf);
159    dst->buf = buf;
160    dst->pub.free_in_buffer += dst->len;
161    dst->len *= 2;
162
163    return FALSE;
164 } /* _eet_jpeg_membuf_dst_flush */
165
166 static void
167 _eet_jpeg_membuf_dst_term(j_compress_ptr cinfo)
168 {
169    struct jpeg_membuf_dst *dst = (struct jpeg_membuf_dst *)cinfo->dest;
170
171    if (dst->failed)
172      {
173         *dst->dst_buf = NULL;
174         *dst->dst_len = 0;
175         free(dst->buf);
176      }
177    else
178      {
179         *dst->dst_buf = dst->buf;
180         *dst->dst_len = (unsigned char *)dst->pub.next_output_byte - dst->buf;
181      }
182
183    free(dst);
184    cinfo->dest = NULL;
185 } /* _eet_jpeg_membuf_dst_term */
186
187 static int
188 eet_jpeg_membuf_dst(j_compress_ptr cinfo,
189                     void         **buf,
190                     size_t        *len)
191 {
192    struct jpeg_membuf_dst *dst;
193
194    dst = malloc(sizeof(*dst));
195    if (!dst)
196       return -1;
197
198    dst->buf = malloc(32768);
199    if (!dst->buf)
200      {
201         free(dst);
202         return -1;
203      }
204
205    dst->len = 32768;
206
207    cinfo->dest = &dst->pub;
208    dst->pub.init_destination = _eet_jpeg_membuf_dst_init;
209    dst->pub.empty_output_buffer = _eet_jpeg_membuf_dst_flush;
210    dst->pub.term_destination = _eet_jpeg_membuf_dst_term;
211    dst->pub.free_in_buffer = dst->len;
212    dst->pub.next_output_byte = dst->buf;
213    dst->dst_buf = buf;
214    dst->dst_len = len;
215    dst->failed = 0;
216
217    return 0;
218 } /* eet_jpeg_membuf_dst */
219
220 /*---*/
221
222 static void      _JPEGFatalErrorHandler(j_common_ptr cinfo);
223 static void      _JPEGErrorHandler(j_common_ptr cinfo);
224 static void      _JPEGErrorHandler2(j_common_ptr cinfo,
225                                     int          msg_level);
226
227 static int       eet_data_image_jpeg_header_decode(const void   *data,
228                                                    int           size,
229                                                    unsigned int *w,
230                                                    unsigned int *h);
231 static int       eet_data_image_jpeg_rgb_decode(const void   *data,
232                                                 int           size,
233                                                 unsigned int  src_x,
234                                                 unsigned int  src_y,
235                                                 unsigned int *d,
236                                                 unsigned int  w,
237                                                 unsigned int  h,
238                                                 unsigned int  row_stride);
239 static void *    eet_data_image_jpeg_alpha_decode(const void   *data,
240                                                   int           size,
241                                                   unsigned int  src_x,
242                                                   unsigned int  src_y,
243                                                   unsigned int *d,
244                                                   unsigned int  w,
245                                                   unsigned int  h,
246                                                   unsigned int  row_stride);
247 static void *    eet_data_image_lossless_convert(int         *size,
248                                                  const void  *data,
249                                                  unsigned int w,
250                                                  unsigned int h,
251                                                  int          alpha);
252 static void *    eet_data_image_lossless_compressed_convert(int         *size,
253                                                             const void  *data,
254                                                             unsigned int w,
255                                                             unsigned int h,
256                                                             int          alpha,
257                                                             int          compression);
258 static void *    eet_data_image_jpeg_convert(int         *size,
259                                              const void  *data,
260                                              unsigned int w,
261                                              unsigned int h,
262                                              int          alpha,
263                                              int          quality);
264 static void *    eet_data_image_jpeg_alpha_convert(int         *size,
265                                                    const void  *data,
266                                                    unsigned int w,
267                                                    unsigned int h,
268                                                    int          alpha,
269                                                    int          quality);
270
271 /*---*/
272
273 static int _eet_image_words_bigendian = -1;
274
275 /*---*/
276
277 #define SWAP64(x) (x) =\
278    ((((unsigned long long)(x) & 0x00000000000000ffULL) << 56) |\
279     (((unsigned long long)(x) & 0x000000000000ff00ULL) << 40) |\
280     (((unsigned long long)(x) & 0x0000000000ff0000ULL) << 24) |\
281     (((unsigned long long)(x) & 0x00000000ff000000ULL) << 8) |\
282     (((unsigned long long)(x) & 0x000000ff00000000ULL) >> 8) |\
283     (((unsigned long long)(x) & 0x0000ff0000000000ULL) >> 24) |\
284     (((unsigned long long)(x) & 0x00ff000000000000ULL) >> 40) |\
285     (((unsigned long long)(x) & 0xff00000000000000ULL) >> 56))
286 #define SWAP32(x) (x) =\
287    ((((int)(x) & 0x000000ff) << 24) |\
288     (((int)(x) & 0x0000ff00) << 8) |\
289     (((int)(x) & 0x00ff0000) >> 8) |\
290     (((int)(x) & 0xff000000) >> 24))
291 #define SWAP16(x) (x) =\
292    ((((short)(x) & 0x00ff) << 8) |\
293     (((short)(x) & 0xff00) >> 8))
294
295 #ifdef CONV8
296 # undef CONV8
297 #endif /* ifdef CONV8 */
298 #ifdef CONV16
299 # undef CONV16
300 #endif /* ifdef CONV16 */
301 #ifdef CONV32
302 # undef CONV32
303 #endif /* ifdef CONV32 */
304 #ifdef CONV64
305 # undef CONV64
306 #endif /* ifdef CONV64 */
307
308 #define CONV8(x)
309 #define CONV16(x) {if (_eet_image_words_bigendian) {SWAP16(x); }}
310 #define CONV32(x) {if (_eet_image_words_bigendian) {SWAP32(x); }}
311 #define CONV64(x) {if (_eet_image_words_bigendian) {SWAP64(x); }}
312
313 /*---*/
314
315 static void
316 _JPEGFatalErrorHandler(j_common_ptr cinfo)
317 {
318    emptr errmgr;
319
320    errmgr = (emptr)cinfo->err;
321    /*   cinfo->err->output_message(cinfo);*/
322    longjmp(errmgr->setjmp_buffer, 1);
323    return;
324 } /* _JPEGFatalErrorHandler */
325
326 static void
327 _JPEGErrorHandler(j_common_ptr cinfo __UNUSED__)
328 {
329    /*   emptr errmgr; */
330
331    /*   errmgr = (emptr) cinfo->err; */
332    /*   cinfo->err->output_message(cinfo);*/
333    /*   longjmp(errmgr->setjmp_buffer, 1);*/
334    return;
335 } /* _JPEGErrorHandler */
336
337 static void
338 _JPEGErrorHandler2(j_common_ptr cinfo __UNUSED__,
339                    int msg_level      __UNUSED__)
340 {
341    /*   emptr errmgr; */
342
343    /*   errmgr = (emptr) cinfo->err; */
344    /*   cinfo->err->output_message(cinfo);*/
345    /*   longjmp(errmgr->setjmp_buffer, 1);*/
346    return;
347 } /* _JPEGErrorHandler2 */
348
349 static int
350 eet_data_image_jpeg_header_decode(const void   *data,
351                                   int           size,
352                                   unsigned int *w,
353                                   unsigned int *h)
354 {
355    struct jpeg_decompress_struct cinfo;
356    struct _JPEG_error_mgr jerr;
357
358    memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct));
359
360    cinfo.err = jpeg_std_error(&(jerr.pub));
361    jerr.pub.error_exit = _JPEGFatalErrorHandler;
362    jerr.pub.emit_message = _JPEGErrorHandler2;
363    jerr.pub.output_message = _JPEGErrorHandler;
364    if (setjmp(jerr.setjmp_buffer))
365       return 0;
366
367    jpeg_create_decompress(&cinfo);
368
369    if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size))
370      {
371         jpeg_destroy_decompress(&cinfo);
372         return 0;
373      }
374
375    jpeg_read_header(&cinfo, TRUE);
376    cinfo.do_fancy_upsampling = FALSE;
377    cinfo.do_block_smoothing = FALSE;
378    jpeg_start_decompress(&cinfo);
379
380    /* head decoding */
381    *w = cinfo.output_width;
382    *h = cinfo.output_height;
383
384    free(cinfo.src);
385    cinfo.src = NULL;
386
387    jpeg_destroy_decompress(&cinfo);
388
389    if ((*w < 1) || (*h < 1) || (*w > 8192) || (*h > 8192))
390       return 0;
391
392    return 1;
393 } /* eet_data_image_jpeg_header_decode */
394
395 static int
396 eet_data_image_jpeg_rgb_decode(const void   *data,
397                                int           size,
398                                unsigned int  src_x,
399                                unsigned int  src_y,
400                                unsigned int *d,
401                                unsigned int  w,
402                                unsigned int  h,
403                                unsigned int  row_stride)
404 {
405    struct jpeg_decompress_struct cinfo;
406    struct _JPEG_error_mgr jerr;
407    unsigned char *ptr, *line[16], *tdata = NULL;
408    unsigned int *ptr2, *tmp;
409    unsigned int iw, ih;
410    unsigned int x, y, l, scans;
411    unsigned int i;
412
413    /* FIXME: handle src_x, src_y and row_stride correctly */
414    if (!d)
415       return 0;
416
417    memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct));
418
419    cinfo.err = jpeg_std_error(&(jerr.pub));
420    jerr.pub.error_exit = _JPEGFatalErrorHandler;
421    jerr.pub.emit_message = _JPEGErrorHandler2;
422    jerr.pub.output_message = _JPEGErrorHandler;
423    if (setjmp(jerr.setjmp_buffer))
424       return 0;
425
426    jpeg_create_decompress(&cinfo);
427
428    if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size))
429      {
430         jpeg_destroy_decompress(&cinfo);
431         return 0;
432      }
433
434    jpeg_read_header(&cinfo, TRUE);
435    cinfo.dct_method = JDCT_FASTEST;
436    cinfo.do_fancy_upsampling = FALSE;
437    cinfo.do_block_smoothing = FALSE;
438    jpeg_start_decompress(&cinfo);
439
440    /* head decoding */
441    iw = cinfo.output_width;
442    ih = cinfo.output_height;
443    if ((iw != w) || (ih != h))
444      {
445         free(cinfo.src);
446         cinfo.src = NULL;
447
448         jpeg_destroy_decompress(&cinfo);
449         return 0;
450      }
451
452    /* end head decoding */
453    /* data decoding */
454    if (cinfo.rec_outbuf_height > 16)
455      {
456         free(cinfo.src);
457         cinfo.src = NULL;
458
459         jpeg_destroy_decompress(&cinfo);
460         return 0;
461      }
462
463    tdata = alloca((iw) * 16 * 3);
464    ptr2 = d;
465
466    if (cinfo.output_components == 3)
467      {
468         for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++)
469            line[i] = tdata + (i * (iw) * 3);
470         for (l = 0; l < ih; l += cinfo.rec_outbuf_height)
471           {
472              jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
473              scans = cinfo.rec_outbuf_height;
474              if ((ih - l) < scans)
475                 scans = ih - l;
476
477              ptr = tdata;
478
479              if (l + scans >= src_y && l < src_y + h)
480                {
481                   y = src_y - l;
482                   if (src_y < l)
483                      y = 0;
484
485                   for (ptr += 3 * iw * y; y < scans && (y + l) < (src_y + h);
486                        y++)
487                     {
488                        tmp = ptr2;
489                        ptr += 3 * src_x;
490                        for (x = 0; x < w; x++)
491                          {
492                             *ptr2 =
493                                (0xff000000) |
494                                ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]);
495                             ptr += 3;
496                             ptr2++;
497                          }
498                        ptr += 3 * (iw - w);
499                        ptr2 = tmp + row_stride / 4;
500                     }
501                }
502           }
503      }
504    else if (cinfo.output_components == 1)
505      {
506         for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++)
507            line[i] = tdata + (i * (iw));
508         for (l = 0; l < (ih); l += cinfo.rec_outbuf_height)
509           {
510              jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
511              scans = cinfo.rec_outbuf_height;
512              if (((ih) - l) < scans)
513                 scans = (ih) - l;
514
515              ptr = tdata;
516
517              if (l >= src_y && l < src_y + h)
518                {
519                   y = src_y - l;
520                   if (src_y < l)
521                      y = 0;
522
523                   for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++)
524                     {
525                        tmp = ptr2;
526                        ptr += src_x;
527                        for (x = 0; x < w; x++)
528                          {
529                             *ptr2 =
530                                (0xff000000) |
531                                ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]);
532                             ptr++;
533                             ptr2++;
534                          }
535                        ptr += iw - w;
536                        ptr2 = tmp + row_stride / 4;
537                     }
538                }
539           }
540      }
541
542    /* end data decoding */
543    jpeg_finish_decompress(&cinfo);
544    jpeg_destroy_decompress(&cinfo);
545    return 1;
546 } /* eet_data_image_jpeg_rgb_decode */
547
548 static void *
549 eet_data_image_jpeg_alpha_decode(const void   *data,
550                                  int           size,
551                                  unsigned int  src_x,
552                                  unsigned int  src_y,
553                                  unsigned int *d,
554                                  unsigned int  w,
555                                  unsigned int  h,
556                                  unsigned int  row_stride)
557 {
558    struct jpeg_decompress_struct cinfo;
559    struct _JPEG_error_mgr jerr;
560    unsigned char *ptr, *line[16], *tdata = NULL;
561    unsigned int *ptr2, *tmp;
562    unsigned int x, y, l, scans;
563    unsigned int i, iw;
564
565    memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct));
566
567    cinfo.err = jpeg_std_error(&(jerr.pub));
568    jerr.pub.error_exit = _JPEGFatalErrorHandler;
569    jerr.pub.emit_message = _JPEGErrorHandler2;
570    jerr.pub.output_message = _JPEGErrorHandler;
571    if (setjmp(jerr.setjmp_buffer))
572       return NULL;
573
574    jpeg_create_decompress(&cinfo);
575
576    if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size))
577      {
578         jpeg_destroy_decompress(&cinfo);
579         return NULL;
580      }
581
582    jpeg_read_header(&cinfo, TRUE);
583    cinfo.dct_method = JDCT_FASTEST;
584    cinfo.do_fancy_upsampling = FALSE;
585    cinfo.do_block_smoothing = FALSE;
586    jpeg_start_decompress(&cinfo);
587
588    /* head decoding */
589    iw = cinfo.output_width;
590    if (w != cinfo.output_width
591        || h != cinfo.output_height)
592      {
593         free(cinfo.src);
594         cinfo.src = NULL;
595
596         jpeg_destroy_decompress(&cinfo);
597         return NULL;
598      }
599
600    /* end head decoding */
601    /* data decoding */
602    if (cinfo.rec_outbuf_height > 16)
603      {
604         free(cinfo.src);
605         cinfo.src = NULL;
606
607         jpeg_destroy_decompress(&cinfo);
608         return NULL;
609      }
610
611    tdata = alloca(w * 16 * 3);
612    ptr2 = d;
613    if (cinfo.output_components == 1)
614      {
615         for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++)
616            line[i] = tdata + (i * w);
617         for (l = 0; l < h; l += cinfo.rec_outbuf_height)
618           {
619              jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
620              scans = cinfo.rec_outbuf_height;
621              if ((h - l) < scans)
622                 scans = h - l;
623
624              ptr = tdata;
625
626              if (l >= src_y && l < src_y + h)
627                {
628                   y = src_y - l;
629                   if (src_y < l)
630                      y = 0;
631
632                   for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++)
633                     {
634                        tmp = ptr2;
635                        ptr += src_x;
636                        for (x = 0; x < w; x++)
637                          {
638                             *ptr2 =
639                                ((*ptr2) & 0x00ffffff) |
640                                ((ptr[0]) << 24);
641                             ptr++;
642                             ptr2++;
643                          }
644                        ptr += iw - w;
645                        ptr2 = tmp + row_stride / 4;
646                     }
647                }
648           }
649      }
650
651    /* end data decoding */
652    jpeg_finish_decompress(&cinfo);
653    jpeg_destroy_decompress(&cinfo);
654    return d;
655 } /* eet_data_image_jpeg_alpha_decode */
656
657 static void *
658 eet_data_image_lossless_convert(int         *size,
659                                 const void  *data,
660                                 unsigned int w,
661                                 unsigned int h,
662                                 int          alpha)
663 {
664    if (_eet_image_words_bigendian == -1)
665      {
666         unsigned long int v;
667
668         v = htonl(0x12345678);
669         if (v == 0x12345678)
670            _eet_image_words_bigendian = 1;
671         else
672            _eet_image_words_bigendian = 0;
673      }
674
675    {
676       unsigned char *d;
677       int *header;
678
679       d = malloc((w * h * 4) + (8 * 4));
680       if (!d)
681          return NULL;
682
683       header = (int *)d;
684       memset(d, 0, 32);
685
686       header[0] = 0xac1dfeed;
687       header[1] = w;
688       header[2] = h;
689       header[3] = alpha;
690
691       memcpy(d + 32, data, w * h * 4);
692
693       if (_eet_image_words_bigendian)
694         {
695            unsigned int i;
696
697            for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]);
698         }
699
700       *size = ((w * h * 4) + (8 * 4));
701       return d;
702    }
703 } /* eet_data_image_lossless_convert */
704
705 static void *
706 eet_data_image_lossless_compressed_convert(int         *size,
707                                            const void  *data,
708                                            unsigned int w,
709                                            unsigned int h,
710                                            int          alpha,
711                                            int          compression)
712 {
713    if (_eet_image_words_bigendian == -1)
714      {
715         unsigned long int v;
716
717         v = htonl(0x12345678);
718         if (v == 0x12345678)
719            _eet_image_words_bigendian = 1;
720         else
721            _eet_image_words_bigendian = 0;
722      }
723
724    {
725       unsigned char *d;
726       unsigned char *comp;
727       int *header;
728       int ret;
729       uLongf buflen;
730
731       d = malloc((w * h * 4) + (8 * 4));
732       if (!d)
733          return NULL;
734
735       buflen = (((w * h * 101) / 100) + 3) * 4;
736       comp = malloc(buflen);
737       if (!comp)
738         {
739            free(d);
740            return NULL;
741         }
742
743       header = (int *)d;
744       memset(d, 0, 32);
745
746       header[0] = 0xac1dfeed;
747       header[1] = w;
748       header[2] = h;
749       header[3] = alpha;
750       header[4] = compression;
751       memcpy(d + 32, data, w * h * 4);
752
753       if (_eet_image_words_bigendian)
754         {
755            unsigned int i;
756
757            for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]);
758         }
759
760       ret = compress2((Bytef *)comp, &buflen,
761                       (Bytef *)(d + 32),
762                       (uLong)(w * h * 4),
763                       compression);
764       if (ret != Z_OK || buflen > (w * h * 4))
765         {
766            free(comp);
767            free(d);
768            *size = -1;
769            return NULL;
770         }
771
772       memcpy(d + 32, comp, buflen);
773       *size = (8 * 4) + buflen;
774       free(comp);
775       return d;
776    }
777 } /* eet_data_image_lossless_compressed_convert */
778
779 static void *
780 eet_data_image_jpeg_convert(int         *size,
781                             const void  *data,
782                             unsigned int w,
783                             unsigned int h,
784                             int          alpha,
785                             int          quality)
786 {
787    struct jpeg_compress_struct cinfo;
788    struct _JPEG_error_mgr jerr;
789    const int *ptr;
790    void *d = NULL;
791    size_t sz = 0;
792    JSAMPROW *jbuf;
793    unsigned char *buf;
794
795    (void)alpha; /* unused */
796
797    buf = alloca(3 * w);
798
799    memset(&cinfo, 0, sizeof (struct jpeg_compress_struct));
800
801    cinfo.err = jpeg_std_error(&(jerr.pub));
802    jerr.pub.error_exit = _JPEGFatalErrorHandler;
803    jerr.pub.emit_message = _JPEGErrorHandler2;
804    jerr.pub.output_message = _JPEGErrorHandler;
805    if (setjmp(jerr.setjmp_buffer))
806       return NULL;
807
808    jpeg_create_compress(&cinfo);
809
810    if (eet_jpeg_membuf_dst(&cinfo, &d, &sz))
811      {
812         jpeg_destroy_compress(&cinfo);
813         return NULL;
814      }
815
816    cinfo.image_width = w;
817    cinfo.image_height = h;
818    cinfo.input_components = 3;
819    cinfo.in_color_space = JCS_RGB;
820    jpeg_set_defaults(&cinfo);
821    jpeg_set_quality(&cinfo, quality, TRUE);
822    if (quality >= 90)
823      {
824         cinfo.comp_info[0].h_samp_factor = 1;
825         cinfo.comp_info[0].v_samp_factor = 1;
826         cinfo.comp_info[1].h_samp_factor = 1;
827         cinfo.comp_info[1].v_samp_factor = 1;
828         cinfo.comp_info[2].h_samp_factor = 1;
829         cinfo.comp_info[2].v_samp_factor = 1;
830      }
831
832    jpeg_start_compress(&cinfo, TRUE);
833
834    while (cinfo.next_scanline < cinfo.image_height)
835      {
836         unsigned int i, j;
837
838         /* convert scaline from ARGB to RGB packed */
839         ptr = ((const int *)data) + cinfo.next_scanline * w;
840         for (j = 0, i = 0; i < w; i++)
841           {
842              buf[j++] = ((*ptr) >> 16) & 0xff;
843              buf[j++] = ((*ptr) >> 8) & 0xff;
844              buf[j++] = ((*ptr)) & 0xff;
845              ptr++;
846           }
847         jbuf = (JSAMPROW *)(&buf);
848         jpeg_write_scanlines(&cinfo, jbuf, 1);
849      }
850
851    jpeg_finish_compress(&cinfo);
852    jpeg_destroy_compress(&cinfo);
853
854    *size = sz;
855    return d;
856 } /* eet_data_image_jpeg_convert */
857
858 static void *
859 eet_data_image_jpeg_alpha_convert(int         *size,
860                                   const void  *data,
861                                   unsigned int w,
862                                   unsigned int h,
863                                   int          alpha,
864                                   int          quality)
865 {
866    unsigned char *d1, *d2;
867    unsigned char *d;
868    int *header;
869    int sz1, sz2;
870
871    (void)alpha; /* unused */
872
873    if (_eet_image_words_bigendian == -1)
874      {
875         unsigned long int v;
876
877         v = htonl(0x12345678);
878         if (v == 0x12345678)
879            _eet_image_words_bigendian = 1;
880         else
881            _eet_image_words_bigendian = 0;
882      }
883
884    {
885       const int *ptr;
886       void *dst = NULL;
887       size_t sz = 0;
888       struct _JPEG_error_mgr jerr;
889       JSAMPROW *jbuf;
890       struct jpeg_compress_struct cinfo;
891       unsigned char *buf;
892
893       buf = alloca(3 * w);
894
895       cinfo.err = jpeg_std_error(&(jerr.pub));
896       jerr.pub.error_exit = _JPEGFatalErrorHandler;
897       jerr.pub.emit_message = _JPEGErrorHandler2;
898       jerr.pub.output_message = _JPEGErrorHandler;
899       if (setjmp(jerr.setjmp_buffer))
900          return NULL;
901
902       jpeg_create_compress(&cinfo);
903       if (eet_jpeg_membuf_dst(&cinfo, &dst, &sz))
904         {
905            jpeg_destroy_compress(&cinfo);
906            return NULL;
907         }
908
909       cinfo.image_width = w;
910       cinfo.image_height = h;
911       cinfo.input_components = 3;
912       cinfo.in_color_space = JCS_RGB;
913       jpeg_set_defaults(&cinfo);
914       jpeg_set_quality(&cinfo, quality, TRUE);
915       if (quality >= 90)
916         {
917            cinfo.comp_info[0].h_samp_factor = 1;
918            cinfo.comp_info[0].v_samp_factor = 1;
919            cinfo.comp_info[1].h_samp_factor = 1;
920            cinfo.comp_info[1].v_samp_factor = 1;
921            cinfo.comp_info[2].h_samp_factor = 1;
922            cinfo.comp_info[2].v_samp_factor = 1;
923         }
924
925       jpeg_start_compress(&cinfo, TRUE);
926
927       while (cinfo.next_scanline < cinfo.image_height)
928         {
929            unsigned int i, j;
930
931            ptr = ((const int *)data) + cinfo.next_scanline * w;
932            /* convert scaline from ARGB to RGB packed */
933            for (j = 0, i = 0; i < w; i++)
934              {
935                 buf[j++] = ((*ptr) >> 16) & 0xff;
936                 buf[j++] = ((*ptr) >> 8) & 0xff;
937                 buf[j++] = ((*ptr)) & 0xff;
938                 ptr++;
939              }
940            jbuf = (JSAMPROW *)(&buf);
941            jpeg_write_scanlines(&cinfo, jbuf, 1);
942         }
943
944       jpeg_finish_compress(&cinfo);
945       jpeg_destroy_compress(&cinfo);
946
947       d1 = dst;
948       sz1 = sz;
949    }
950    {
951       const int *ptr;
952       void *dst = NULL;
953       size_t sz = 0;
954       struct _JPEG_error_mgr jerr;
955       JSAMPROW *jbuf;
956       struct jpeg_compress_struct cinfo;
957       unsigned char *buf;
958
959       buf = alloca(3 * w);
960
961       cinfo.err = jpeg_std_error(&(jerr.pub));
962       jerr.pub.error_exit = _JPEGFatalErrorHandler;
963       jerr.pub.emit_message = _JPEGErrorHandler2;
964       jerr.pub.output_message = _JPEGErrorHandler;
965       if (setjmp(jerr.setjmp_buffer))
966         {
967            free(d1);
968            return NULL;
969         }
970
971       jpeg_create_compress(&cinfo);
972       if (eet_jpeg_membuf_dst(&cinfo, &dst, &sz))
973         {
974            jpeg_destroy_compress(&cinfo);
975            free(d1);
976            return NULL;
977         }
978
979       cinfo.image_width = w;
980       cinfo.image_height = h;
981       cinfo.input_components = 1;
982       cinfo.in_color_space = JCS_GRAYSCALE;
983       jpeg_set_defaults(&cinfo);
984       jpeg_set_quality(&cinfo, quality, TRUE);
985       if (quality >= 90)
986         {
987            cinfo.comp_info[0].h_samp_factor = 1;
988            cinfo.comp_info[0].v_samp_factor = 1;
989            cinfo.comp_info[1].h_samp_factor = 1;
990            cinfo.comp_info[1].v_samp_factor = 1;
991            cinfo.comp_info[2].h_samp_factor = 1;
992            cinfo.comp_info[2].v_samp_factor = 1;
993         }
994
995       jpeg_start_compress(&cinfo, TRUE);
996
997       while (cinfo.next_scanline < cinfo.image_height)
998         {
999            unsigned int i, j;
1000
1001            ptr = ((const int *)data) + cinfo.next_scanline * w;
1002            /* convert scaline from ARGB to RGB packed */
1003            for (j = 0, i = 0; i < w; i++)
1004              {
1005                 buf[j++] = ((*ptr) >> 24) & 0xff;
1006                 ptr++;
1007              }
1008            jbuf = (JSAMPROW *)(&buf);
1009            jpeg_write_scanlines(&cinfo, jbuf, 1);
1010         }
1011
1012       jpeg_finish_compress(&cinfo);
1013       jpeg_destroy_compress(&cinfo);
1014
1015       d2 = dst;
1016       sz2 = sz;
1017    }
1018    d = malloc(12 + sz1 + sz2);
1019    if (!d)
1020      {
1021         free(d1);
1022         free(d2);
1023         return NULL;
1024      }
1025
1026    header = (int *)d;
1027    header[0] = 0xbeeff00d;
1028    header[1] = sz1;
1029    header[2] = sz2;
1030    if (_eet_image_words_bigendian)
1031      {
1032         int i;
1033
1034         for (i = 0; i < 3; i++) SWAP32(header[i]);
1035      }
1036
1037    memcpy(d + 12,       d1, sz1);
1038    memcpy(d + 12 + sz1, d2, sz2);
1039
1040    free(d1);
1041    free(d2);
1042    *size = 12 + sz1 + sz2;
1043    return d;
1044 } /* eet_data_image_jpeg_alpha_convert */
1045
1046 EAPI int
1047 eet_data_image_write_cipher(Eet_File    *ef,
1048                             const char  *name,
1049                             const char  *cipher_key,
1050                             const void  *data,
1051                             unsigned int w,
1052                             unsigned int h,
1053                             int          alpha,
1054                             int          comp,
1055                             int          quality,
1056                             int          lossy)
1057 {
1058    void *d = NULL;
1059    int size = 0;
1060
1061    d = eet_data_image_encode(data, &size, w, h, alpha, comp, quality, lossy);
1062    if (d)
1063      {
1064         int v;
1065
1066         v = eet_write_cipher(ef, name, d, size, 0, cipher_key);
1067         free(d);
1068         return v;
1069      }
1070
1071    return 0;
1072 } /* eet_data_image_write_cipher */
1073
1074 EAPI int
1075 eet_data_image_write(Eet_File    *ef,
1076                      const char  *name,
1077                      const void  *data,
1078                      unsigned int w,
1079                      unsigned int h,
1080                      int          alpha,
1081                      int          comp,
1082                      int          quality,
1083                      int          lossy)
1084 {
1085    return eet_data_image_write_cipher(ef,
1086                                       name,
1087                                       NULL,
1088                                       data,
1089                                       w,
1090                                       h,
1091                                       alpha,
1092                                       comp,
1093                                       quality,
1094                                       lossy);
1095 } /* eet_data_image_write */
1096
1097 EAPI void *
1098 eet_data_image_read_cipher(Eet_File     *ef,
1099                            const char   *name,
1100                            const char   *cipher_key,
1101                            unsigned int *w,
1102                            unsigned int *h,
1103                            int          *alpha,
1104                            int          *comp,
1105                            int          *quality,
1106                            int          *lossy)
1107 {
1108    unsigned int *d = NULL;
1109    void *data = NULL;
1110    int free_data = 0;
1111    int size;
1112
1113    if (!cipher_key)
1114       data = (void *)eet_read_direct(ef, name, &size);
1115
1116    if (!data)
1117      {
1118         data = eet_read_cipher(ef, name, &size, cipher_key);
1119         free_data = 1;
1120         if (!data)
1121            return NULL;
1122      }
1123
1124    d = eet_data_image_decode(data, size, w, h, alpha, comp, quality, lossy);
1125
1126    if (free_data)
1127       free(data);
1128
1129    return d;
1130 } /* eet_data_image_read_cipher */
1131
1132 EAPI void *
1133 eet_data_image_read(Eet_File     *ef,
1134                     const char   *name,
1135                     unsigned int *w,
1136                     unsigned int *h,
1137                     int          *alpha,
1138                     int          *comp,
1139                     int          *quality,
1140                     int          *lossy)
1141 {
1142    return eet_data_image_read_cipher(ef, name, NULL, w, h, alpha,
1143                                      comp, quality, lossy);
1144 } /* eet_data_image_read */
1145
1146 EAPI int
1147 eet_data_image_read_to_surface_cipher(Eet_File     *ef,
1148                                       const char   *name,
1149                                       const char   *cipher_key,
1150                                       unsigned int  src_x,
1151                                       unsigned int  src_y,
1152                                       unsigned int *d,
1153                                       unsigned int  w,
1154                                       unsigned int  h,
1155                                       unsigned int  row_stride,
1156                                       int          *alpha,
1157                                       int          *comp,
1158                                       int          *quality,
1159                                       int          *lossy)
1160 {
1161    void *data = NULL;
1162    int free_data = 0;
1163    int res = 1;
1164    int size;
1165
1166    if (!cipher_key)
1167       data = (void *)eet_read_direct(ef, name, &size);
1168
1169    if (!data)
1170      {
1171         data = eet_read_cipher(ef, name, &size, cipher_key);
1172         free_data = 1;
1173         if (!data)
1174            return 0;
1175      }
1176
1177    res = eet_data_image_decode_to_surface(data, size, src_x, src_y, d,
1178                                           w, h, row_stride, alpha,
1179                                           comp, quality, lossy);
1180
1181    if (free_data)
1182       free(data);
1183
1184    return res;
1185 } /* eet_data_image_read_to_surface_cipher */
1186
1187 EAPI int
1188 eet_data_image_read_to_surface(Eet_File     *ef,
1189                                const char   *name,
1190                                unsigned int  src_x,
1191                                unsigned int  src_y,
1192                                unsigned int *d,
1193                                unsigned int  w,
1194                                unsigned int  h,
1195                                unsigned int  row_stride,
1196                                int          *alpha,
1197                                int          *comp,
1198                                int          *quality,
1199                                int          *lossy)
1200 {
1201    return eet_data_image_read_to_surface_cipher(ef, name, NULL,
1202                                                 src_x, src_y, d,
1203                                                 w, h, row_stride,
1204                                                 alpha, comp, quality,
1205                                                 lossy);
1206 } /* eet_data_image_read_to_surface */
1207
1208 EAPI int
1209 eet_data_image_header_read_cipher(Eet_File     *ef,
1210                                   const char   *name,
1211                                   const char   *cipher_key,
1212                                   unsigned int *w,
1213                                   unsigned int *h,
1214                                   int          *alpha,
1215                                   int          *comp,
1216                                   int          *quality,
1217                                   int          *lossy)
1218 {
1219    void *data = NULL;
1220    int size = 0;
1221    int free_data = 0;
1222    int d;
1223
1224    if (!cipher_key)
1225       data = (void *)eet_read_direct(ef, name, &size);
1226
1227    if (!data)
1228      {
1229         data = eet_read_cipher(ef, name, &size, cipher_key);
1230         free_data = 1;
1231         if (!data)
1232            return 0;
1233      }
1234
1235    d = eet_data_image_header_decode(data, size, w, h, alpha,
1236                                     comp, quality, lossy);
1237    if (free_data)
1238       free(data);
1239
1240    return d;
1241 } /* eet_data_image_header_read_cipher */
1242
1243 EAPI int
1244 eet_data_image_header_read(Eet_File     *ef,
1245                            const char   *name,
1246                            unsigned int *w,
1247                            unsigned int *h,
1248                            int          *alpha,
1249                            int          *comp,
1250                            int          *quality,
1251                            int          *lossy)
1252 {
1253    return eet_data_image_header_read_cipher(ef, name, NULL,
1254                                             w, h, alpha,
1255                                             comp, quality, lossy);
1256 } /* eet_data_image_header_read */
1257
1258 EAPI void *
1259 eet_data_image_encode_cipher(const void  *data,
1260                              const char  *cipher_key,
1261                              unsigned int w,
1262                              unsigned int h,
1263                              int          alpha,
1264                              int          comp,
1265                              int          quality,
1266                              int          lossy,
1267                              int         *size_ret)
1268 {
1269    void *d = NULL;
1270    void *ciphered_d = NULL;
1271    unsigned int ciphered_sz = 0;
1272    int size = 0;
1273
1274    if (lossy == 0)
1275      {
1276         if (comp > 0)
1277            d = eet_data_image_lossless_compressed_convert(&size, data,
1278                                                           w, h, alpha, comp);
1279
1280         /* eet_data_image_lossless_compressed_convert will refuse to compress something
1281            if the result is bigger than the entry. */
1282         if (comp <= 0 || d == NULL)
1283            d = eet_data_image_lossless_convert(&size, data, w, h, alpha);
1284      }
1285    else
1286      {
1287         if (!alpha)
1288            d = eet_data_image_jpeg_convert(&size, data, w, h, alpha, quality);
1289         else
1290            d = eet_data_image_jpeg_alpha_convert(&size, data,
1291                                                  w, h, alpha, quality);
1292      }
1293
1294    if (cipher_key)
1295      {
1296         if(!eet_cipher(d, size, cipher_key, strlen(cipher_key), &ciphered_d,
1297                        &ciphered_sz))
1298           {
1299              if (d)
1300                 free(d);
1301
1302              d = ciphered_d;
1303              size = ciphered_sz;
1304           }
1305         else
1306         if (ciphered_d)
1307            free(ciphered_d);
1308      }
1309
1310    if (size_ret)
1311       *size_ret = size;
1312
1313    return d;
1314 } /* eet_data_image_encode_cipher */
1315
1316 EAPI void *
1317 eet_data_image_encode(const void  *data,
1318                       int         *size_ret,
1319                       unsigned int w,
1320                       unsigned int h,
1321                       int          alpha,
1322                       int          comp,
1323                       int          quality,
1324                       int          lossy)
1325 {
1326    return eet_data_image_encode_cipher(data, NULL, w, h, alpha,
1327                                        comp, quality, lossy, size_ret);
1328 } /* eet_data_image_encode */
1329
1330 EAPI int
1331 eet_data_image_header_decode_cipher(const void   *data,
1332                                     const char   *cipher_key,
1333                                     int           size,
1334                                     unsigned int *w,
1335                                     unsigned int *h,
1336                                     int          *alpha,
1337                                     int          *comp,
1338                                     int          *quality,
1339                                     int          *lossy)
1340 {
1341    int header[8];
1342    void *deciphered_d = NULL;
1343    unsigned int deciphered_sz = 0;
1344
1345    if (cipher_key)
1346      {
1347         if (!eet_decipher(data, size, cipher_key, strlen(cipher_key),
1348                           &deciphered_d, &deciphered_sz))
1349           {
1350              data = deciphered_d;
1351              size = deciphered_sz;
1352           }
1353         else
1354         if (deciphered_d)
1355            free(deciphered_d);
1356      }
1357
1358    if (_eet_image_words_bigendian == -1)
1359      {
1360         unsigned long int v;
1361
1362         v = htonl(0x12345678);
1363         if (v == 0x12345678)
1364            _eet_image_words_bigendian = 1;
1365         else
1366            _eet_image_words_bigendian = 0;
1367      }
1368
1369    if (size < 32)
1370       return 0;
1371
1372    memcpy(header, data, 32);
1373    if (_eet_image_words_bigendian)
1374      {
1375         int i;
1376
1377         for (i = 0; i < 8; i++) SWAP32(header[i]);
1378      }
1379
1380    if ((unsigned)header[0] == 0xac1dfeed)
1381      {
1382         int iw, ih, al, cp;
1383
1384         iw = header[1];
1385         ih = header[2];
1386         al = header[3];
1387         cp = header[4];
1388         if ((iw < 1) || (ih < 1) || (iw > 8192) || (ih > 8192))
1389            return 0;
1390
1391         if ((cp == 0) && (size < ((iw * ih * 4) + 32)))
1392            return 0;
1393
1394         if (w)
1395            *w = iw;
1396
1397         if (h)
1398            *h = ih;
1399
1400         if (alpha)
1401            *alpha = al ? 1 : 0;
1402
1403         if (comp)
1404            *comp = cp;
1405
1406         if (lossy)
1407            *lossy = 0;
1408
1409         if (quality)
1410            *quality = 100;
1411
1412         return 1;
1413      }
1414    else if ((unsigned)header[0] == 0xbeeff00d)
1415      {
1416         unsigned int iw = 0, ih = 0;
1417         unsigned const char *dt;
1418         int sz1;
1419         int ok;
1420
1421         sz1 = header[1];
1422 /*  sz2 = header[2]; */
1423         dt = data;
1424         dt += 12;
1425         ok = eet_data_image_jpeg_header_decode(dt, sz1, &iw, &ih);
1426         if (ok)
1427           {
1428              if (w)
1429                 *w = iw;
1430
1431              if (h)
1432                 *h = ih;
1433
1434              if (alpha)
1435                 *alpha = 1;
1436
1437              if (comp)
1438                 *comp = 0;
1439
1440              if (lossy)
1441                 *lossy = 1;
1442
1443              if (quality)
1444                 *quality = 75;
1445
1446              return 1;
1447           }
1448      }
1449    else
1450      {
1451         unsigned int iw = 0, ih = 0;
1452         int ok;
1453
1454         ok = eet_data_image_jpeg_header_decode(data, size, &iw, &ih);
1455         if (ok)
1456           {
1457              if (w)
1458                 *w = iw;
1459
1460              if (h)
1461                 *h = ih;
1462
1463              if (alpha)
1464                 *alpha = 0;
1465
1466              if (comp)
1467                 *comp = 0;
1468
1469              if (lossy)
1470                 *lossy = 1;
1471
1472              if (quality)
1473                 *quality = 75;
1474
1475              return 1;
1476           }
1477      }
1478
1479    return 0;
1480 } /* eet_data_image_header_decode_cipher */
1481
1482 EAPI int
1483 eet_data_image_header_decode(const void   *data,
1484                              int           size,
1485                              unsigned int *w,
1486                              unsigned int *h,
1487                              int          *alpha,
1488                              int          *comp,
1489                              int          *quality,
1490                              int          *lossy)
1491 {
1492    return eet_data_image_header_decode_cipher(data,
1493                                               NULL,
1494                                               size,
1495                                               w,
1496                                               h,
1497                                               alpha,
1498                                               comp,
1499                                               quality,
1500                                               lossy);
1501 } /* eet_data_image_header_decode */
1502
1503 static void
1504 _eet_data_image_copy_buffer(const unsigned int *src,
1505                             unsigned int        src_x,
1506                             unsigned int        src_y,
1507                             unsigned int        src_w,
1508                             unsigned int       *dst,
1509                             unsigned int        w,
1510                             unsigned int        h,
1511                             unsigned int        row_stride)
1512 {
1513    src += src_x + src_y * src_w;
1514
1515    if (row_stride == src_w * 4 && w == src_w)
1516       memcpy(dst, src, row_stride * h);
1517    else
1518      {
1519         unsigned int *over = dst;
1520         unsigned int y;
1521
1522         for (y = 0; y < h; ++y, src += src_w, over += row_stride)
1523            memcpy(over, src, w * 4);
1524      }
1525 } /* _eet_data_image_copy_buffer */
1526
1527 static int
1528 _eet_data_image_decode_inside(const void   *data,
1529                               int           size,
1530                               unsigned int  src_x,
1531                               unsigned int  src_y,
1532                               unsigned int  src_w,
1533                               unsigned int  src_h,
1534                               unsigned int *d,
1535                               unsigned int  w,
1536                               unsigned int  h,
1537                               unsigned int  row_stride,
1538                               int           alpha,
1539                               int           comp,
1540                               int           quality,
1541                               int           lossy)
1542 {
1543    if (lossy == 0 && quality == 100)
1544      {
1545         unsigned int *body;
1546
1547         body = ((unsigned int *)data) + 8;
1548         if (!comp)
1549            _eet_data_image_copy_buffer(body, src_x, src_y, src_w, d,
1550                                        w, h, row_stride);
1551         else
1552           {
1553              if (src_h == h && src_w == w && row_stride == src_w * 4)
1554                {
1555                   uLongf dlen;
1556
1557                   dlen = w * h * 4;
1558                   uncompress((Bytef *)d, &dlen, (Bytef *)body,
1559                              (uLongf)(size - 32));
1560                }
1561              else
1562                {
1563                   Bytef *dtmp;
1564                   uLongf dlen = src_w * src_h * 4;
1565
1566                   /* FIXME: This could create a huge alloc. So compressed data and tile could not always work. */
1567                   dtmp = malloc(dlen);
1568                   if (!dtmp)
1569                      return 0;
1570
1571                   uncompress(dtmp, &dlen, (Bytef *)body, (uLongf)(size - 32));
1572
1573                   _eet_data_image_copy_buffer((unsigned int *)dtmp,
1574                                               src_x, src_y, src_w, d,
1575                                               w, h, row_stride);
1576
1577                   free(dtmp);
1578                }
1579           }
1580
1581         /* Fix swapiness. */
1582         if (_eet_image_words_bigendian)
1583           {
1584              unsigned int x;
1585
1586              for (x = 0; x < (w * h); x++) SWAP32(d[x]);
1587           }
1588      }
1589    else if (comp == 0 && lossy == 1)
1590      {
1591         if (alpha)
1592           {
1593              unsigned const char *dt;
1594              int header[8];
1595              int sz1, sz2;
1596
1597              memcpy(header, data, 32);
1598              if (_eet_image_words_bigendian)
1599                {
1600                   int i;
1601
1602                   for (i = 0; i < 8; i++) SWAP32(header[i]);
1603                }
1604
1605              sz1 = header[1];
1606              sz2 = header[2];
1607              dt = data;
1608              dt += 12;
1609
1610              if (eet_data_image_jpeg_rgb_decode(dt, sz1, src_x, src_y, d, w, h,
1611                                                 row_stride))
1612                {
1613                   dt += sz1;
1614                   if (!eet_data_image_jpeg_alpha_decode(dt, sz2, src_x, src_y,
1615                                                         d, w, h, row_stride))
1616                      return 0;
1617                }
1618           }
1619         else if (!eet_data_image_jpeg_rgb_decode(data, size, src_x, src_y, d, w,
1620                                                  h, row_stride))
1621            return 0;
1622      }
1623    else
1624       abort();
1625
1626    return 1;
1627 } /* _eet_data_image_decode_inside */
1628
1629 EAPI void *
1630 eet_data_image_decode_cipher(const void   *data,
1631                              const char   *cipher_key,
1632                              int           size,
1633                              unsigned int *w,
1634                              unsigned int *h,
1635                              int          *alpha,
1636                              int          *comp,
1637                              int          *quality,
1638                              int          *lossy)
1639 {
1640    unsigned int *d = NULL;
1641    unsigned int iw, ih;
1642    int ialpha, icompress, iquality, ilossy;
1643    void *deciphered_d = NULL;
1644    unsigned int deciphered_sz = 0;
1645
1646    if (cipher_key)
1647      {
1648         if (!eet_decipher(data, size, cipher_key, strlen(cipher_key),
1649                           &deciphered_d, &deciphered_sz))
1650           {
1651              data = deciphered_d;
1652              size = deciphered_sz;
1653           }
1654         else
1655         if (deciphered_d)
1656            free(deciphered_d);
1657      }
1658
1659    /* All check are done during header decode, this simplify the code a lot. */
1660    if (!eet_data_image_header_decode(data, size, &iw, &ih, &ialpha, &icompress,
1661                                      &iquality, &ilossy))
1662       return NULL;
1663
1664    d = malloc(iw * ih * 4);
1665    if (!d)
1666       return NULL;
1667
1668    if (!_eet_data_image_decode_inside(data, size, 0, 0, iw, ih, d, iw, ih, iw *
1669                                       4, ialpha, icompress, iquality, ilossy))
1670      {
1671         free(d);
1672         return NULL;
1673      }
1674
1675    if (w)
1676       *w = iw;
1677
1678    if (h)
1679       *h = ih;
1680
1681    if (alpha)
1682       *alpha = ialpha;
1683
1684    if (comp)
1685       *comp = icompress;
1686
1687    if (quality)
1688       *quality = iquality;
1689
1690    if (lossy)
1691       *lossy = ilossy;
1692
1693    return d;
1694 } /* eet_data_image_decode_cipher */
1695
1696 EAPI void *
1697 eet_data_image_decode(const void   *data,
1698                       int           size,
1699                       unsigned int *w,
1700                       unsigned int *h,
1701                       int          *alpha,
1702                       int          *comp,
1703                       int          *quality,
1704                       int          *lossy)
1705 {
1706    return eet_data_image_decode_cipher(data, NULL, size, w, h,
1707                                        alpha, comp, quality, lossy);
1708 } /* eet_data_image_decode */
1709
1710 EAPI int
1711 eet_data_image_decode_to_surface_cipher(const void   *data,
1712                                         const char   *cipher_key,
1713                                         int           size,
1714                                         unsigned int  src_x,
1715                                         unsigned int  src_y,
1716                                         unsigned int *d,
1717                                         unsigned int  w,
1718                                         unsigned int  h,
1719                                         unsigned int  row_stride,
1720                                         int          *alpha,
1721                                         int          *comp,
1722                                         int          *quality,
1723                                         int          *lossy)
1724 {
1725    unsigned int iw, ih;
1726    int ialpha, icompress, iquality, ilossy;
1727    void *deciphered_d = NULL;
1728    unsigned int deciphered_sz = 0;
1729
1730    if (cipher_key)
1731      {
1732         if (!eet_decipher(data, size, cipher_key, strlen(cipher_key),
1733                           &deciphered_d, &deciphered_sz))
1734           {
1735              data = deciphered_d;
1736              size = deciphered_sz;
1737           }
1738         else
1739         if (deciphered_d)
1740            free(deciphered_d);
1741      }
1742
1743    /* All check are done during header decode, this simplify the code a lot. */
1744    if (!eet_data_image_header_decode(data, size, &iw, &ih, &ialpha, &icompress,
1745                                      &iquality, &ilossy))
1746       return 0;
1747
1748    if (!d)
1749       return 0;
1750
1751    if (w * 4 > row_stride)
1752       return 0;
1753
1754    if (w > iw || h > ih)
1755       return 0;
1756
1757    if (!_eet_data_image_decode_inside(data, size, src_x, src_y, iw, ih, d, w, h,
1758                                       row_stride, ialpha, icompress, iquality,
1759                                       ilossy))
1760       return 0;
1761
1762    if (alpha)
1763       *alpha = ialpha;
1764
1765    if (comp)
1766       *comp = icompress;
1767
1768    if (quality)
1769       *quality = iquality;
1770
1771    if (lossy)
1772       *lossy = ilossy;
1773
1774    return 1;
1775 } /* eet_data_image_decode_to_surface_cipher */
1776
1777 EAPI int
1778 eet_data_image_decode_to_surface(const void   *data,
1779                                  int           size,
1780                                  unsigned int  src_x,
1781                                  unsigned int  src_y,
1782                                  unsigned int *d,
1783                                  unsigned int  w,
1784                                  unsigned int  h,
1785                                  unsigned int  row_stride,
1786                                  int          *alpha,
1787                                  int          *comp,
1788                                  int          *quality,
1789                                  int          *lossy)
1790 {
1791    return eet_data_image_decode_to_surface_cipher(data, NULL, size,
1792                                                   src_x, src_y,  d,
1793                                                   w,  h, row_stride,
1794                                                   alpha, comp, quality,
1795                                                   lossy);
1796 } /* eet_data_image_decode_to_surface */
1797