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