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