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