fix possible crash on task abort and work with new getCD return value
[enigma2.git] / lib / gdi / picload.cpp
1 #include <png.h>        // must be included before Python.h because of setjmp
2 #include <lib/gdi/picload.h>
3 #include "picexif.h"
4 #include <lib/python/python.h>
5
6 #include <fcntl.h>
7 #include <unistd.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10
11 #include <epng.h>       // savePNG need it
12
13 extern "C" {
14 #include <jpeglib.h>
15 #include <gif_lib.h>
16 //#include "transupp.h"
17 }
18
19 unsigned char *pic_buffer=NULL;
20
21 static unsigned char *conv24to32(unsigned char * orgin, int size, int background = 0)
22 {
23         int s, d;
24         unsigned char *cr = new unsigned char[size * 4];
25         if (cr == NULL)
26         {
27                 printf("[CONV32] Error: malloc\n");
28                 return(orgin);
29         }
30
31         unsigned char alpha = 0x00;
32         if(background)  alpha = 0xFF;
33
34         for (s = 0, d = 0 ; s < (size * 3); s += 3, d += 4 )
35         {
36                 cr[d] = orgin[s];
37                 cr[d+1] = orgin[s + 1];
38                 cr[d+2] = orgin[s + 2];
39                 cr[d+3] = alpha;
40         }
41         delete [] orgin;
42         return(cr);
43 }
44
45 static unsigned char *simple_resize(unsigned char * orgin, int ox, int oy, int dx, int dy)
46 {
47         unsigned char *cr, *p, *l;
48         int i, j, k, ip;
49         cr = new unsigned char[dx * dy * 4]; 
50         if (cr == NULL)
51         {
52                 printf("[RESIZE] Error: malloc\n");
53                 return(orgin);
54         }
55         l = cr;
56
57         for (j = 0; j < dy; j++,l += dx * 4)
58         {
59                 p = orgin + (j * oy / dy * ox * 4);
60                 for (i = 0, k = 0; i < dx; i++, k += 4)
61                 {
62                         ip = i * ox / dx * 4;
63                         l[k] = p[ip];
64                         l[k+1] = p[ip + 1];
65                         l[k+2] = p[ip + 2];
66                         l[k+3] = p[ip + 3];
67                 }
68         }
69         delete [] orgin;
70         return(cr);
71 }
72
73 static unsigned char *color_resize(unsigned char * orgin, int ox, int oy, int dx, int dy)
74 {
75         unsigned char *cr, *p, *q;
76         int i, j, k, l, xa, xb, ya, yb;
77         int sq, r, g, b, a;
78         cr = new unsigned char[dx * dy * 4];
79         if (cr == NULL)
80         {
81                 printf("[RESIZE] Error: malloc\n");
82                 return(orgin);
83         }
84         p = cr;
85
86         for (j = 0; j < dy; j++)
87         {
88                 for (i = 0; i < dx; i++, p += 4)
89                 {
90                         xa = i * ox / dx;
91                         ya = j * oy / dy;
92                         xb = (i + 1) * ox / dx; 
93                         if (xb >= ox)
94                                 xb = ox - 1;
95                         yb = (j + 1) * oy / dy; 
96                         if (yb >= oy)
97                                 yb = oy - 1;
98                         for (l = ya, r = 0, g = 0, b = 0, a = 0, sq = 0; l <= yb; l++)
99                         {
100                                 q = orgin + ((l * ox + xa) * 4);
101                                 for (k = xa; k <= xb; k++, q += 4, sq++)
102                                 {
103                                         r += q[0]; g += q[1]; b += q[2]; a += q[3];
104                                 }
105                         }
106                         p[0] = r / sq; p[1] = g / sq; p[2] = b / sq; p[3] = a / sq;
107                 }
108         }
109         delete [] orgin;
110         return(cr);
111 }
112
113 //-------------------------------------------------------------------
114
115 struct r_jpeg_error_mgr
116 {
117         struct jpeg_error_mgr pub;
118         jmp_buf envbuffer;
119 };
120
121 void jpeg_cb_error_exit(j_common_ptr cinfo)
122 {
123         struct r_jpeg_error_mgr *mptr;
124         mptr = (struct r_jpeg_error_mgr *) cinfo->err;
125         (*cinfo->err->output_message) (cinfo);
126         longjmp(mptr->envbuffer, 1);
127 }
128
129 static int jpeg_save(unsigned char *image_buffer, const char * filename, int quality, int image_height, int image_width)
130 {
131         struct jpeg_compress_struct cinfo;
132         struct jpeg_error_mgr jerr;
133         FILE * outfile;         /* target file */
134         JSAMPROW row_pointer[1];/* pointer to JSAMPLE row[s] */
135         int row_stride;         /* physical row width in image buffer */
136  
137         cinfo.err = jpeg_std_error(&jerr);
138         jpeg_create_compress(&cinfo);
139  
140         if ((outfile = fopen(filename, "wb")) == NULL) 
141         {
142                 eDebug("[JPEG] can't open %s", filename);
143                 return -1;
144         }
145         jpeg_stdio_dest(&cinfo, outfile);
146  
147         cinfo.image_width = image_width;
148         cinfo.image_height = image_height;
149         cinfo.input_components = 3;
150         cinfo.in_color_space = JCS_RGB;
151         jpeg_set_defaults(&cinfo);
152         jpeg_set_quality(&cinfo, quality, TRUE );
153         jpeg_start_compress(&cinfo, TRUE);
154         row_stride = image_width * 3;
155         while (cinfo.next_scanline < cinfo.image_height) 
156         {
157                 row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
158                 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
159         }
160         jpeg_finish_compress(&cinfo);
161         fclose(outfile);
162         jpeg_destroy_compress(&cinfo);
163         return 0;
164 }
165
166
167 static int jpeg_load(const char *filename, int *x, int *y)
168 {
169         struct jpeg_decompress_struct cinfo;
170         struct jpeg_decompress_struct *ciptr = &cinfo;
171         struct r_jpeg_error_mgr emgr;
172         FILE *fh;
173
174         if (!(fh = fopen(filename, "rb")))
175                 return 0;
176
177         ciptr->err = jpeg_std_error(&emgr.pub);
178         emgr.pub.error_exit = jpeg_cb_error_exit;
179         if (setjmp(emgr.envbuffer) == 1)
180         {
181                 jpeg_destroy_decompress(ciptr);
182                 fclose(fh);
183                 return 0;
184         }
185
186         jpeg_create_decompress(ciptr);
187         jpeg_stdio_src(ciptr, fh);
188         jpeg_read_header(ciptr, TRUE);
189         ciptr->out_color_space = JCS_RGB;
190         ciptr->scale_denom = 1;
191
192         jpeg_start_decompress(ciptr);
193         
194         *x=ciptr->output_width;
195         *y=ciptr->output_height;
196
197         if(ciptr->output_components == 3)
198         {
199                 JSAMPLE *lb = (JSAMPLE *)(*ciptr->mem->alloc_small)((j_common_ptr) ciptr, JPOOL_PERMANENT, ciptr->output_width * ciptr->output_components);
200                 pic_buffer = new unsigned char[ciptr->output_height * ciptr->output_width * ciptr->output_components];
201                 unsigned char *bp = pic_buffer;
202
203                 while (ciptr->output_scanline < ciptr->output_height)
204                 {
205                         jpeg_read_scanlines(ciptr, &lb, 1);
206                         memcpy(bp, lb, ciptr->output_width * ciptr->output_components);
207                         bp += ciptr->output_width * ciptr->output_components;
208                 }
209         }
210         jpeg_finish_decompress(ciptr);
211         jpeg_destroy_decompress(ciptr);
212         fclose(fh);
213         return 1;
214 }
215
216 //---------------------------------------------------------------------------------------------
217
218 #define BMP_TORASTER_OFFSET 10
219 #define BMP_SIZE_OFFSET 18
220 #define BMP_BPP_OFFSET 28
221 #define BMP_RLE_OFFSET 30
222 #define BMP_COLOR_OFFSET 54
223
224 #define fill4B(a) ((4 - ((a) % 4 )) & 0x03)
225
226 struct color {
227         unsigned char red;
228         unsigned char green;
229         unsigned char blue;
230 };
231
232 static void fetch_pallete(int fd, struct color pallete[], int count)
233 {
234         unsigned char buff[4];
235         lseek(fd, BMP_COLOR_OFFSET, SEEK_SET);
236         for (int i = 0; i < count; i++)
237         {
238                 read(fd, buff, 4);
239                 pallete[i].red = buff[2];
240                 pallete[i].green = buff[1];
241                 pallete[i].blue = buff[0];
242         }
243 }
244
245 static int bmp_load(const char *filename,  int *x, int *y)
246 {
247         unsigned char buff[4];
248         struct color pallete[256];
249
250         int fd = open(filename, O_RDONLY);
251         if (fd == -1) return 0;
252         if (lseek(fd, BMP_SIZE_OFFSET, SEEK_SET) == -1) return 0;
253         read(fd, buff, 4);
254         *x = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
255         read(fd, buff, 4);
256         *y = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
257         if (lseek(fd, BMP_TORASTER_OFFSET, SEEK_SET) == -1) return 0;
258         read(fd, buff, 4);
259         int raster = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
260         if (lseek(fd, BMP_BPP_OFFSET, SEEK_SET) == -1) return 0;
261         read(fd, buff, 2);
262         int bpp = buff[0] + (buff[1] << 8);
263
264         pic_buffer = new unsigned char[(*x) * (*y) * 3];
265         unsigned char *wr_buffer = pic_buffer + (*x) * ((*y) - 1) * 3;
266         
267         switch (bpp)
268         {
269                 case 4:
270                 {
271                         int skip = fill4B((*x) / 2 + (*x) % 2);
272                         fetch_pallete(fd, pallete, 16);
273                         lseek(fd, raster, SEEK_SET);
274                         unsigned char * tbuffer = new unsigned char[*x / 2 + 1];
275                         if (tbuffer == NULL)
276                                 return 0;
277                         for (int i = 0; i < *y; i++) 
278                         {
279                                 read(fd, tbuffer, (*x) / 2 + *x % 2);
280                                 int j;
281                                 for (j = 0; j < (*x) / 2; j++)
282                                 {
283                                         unsigned char c1 = tbuffer[j] >> 4;
284                                         unsigned char c2 = tbuffer[j] & 0x0f;
285                                         *wr_buffer++ = pallete[c1].red;
286                                         *wr_buffer++ = pallete[c1].green;
287                                         *wr_buffer++ = pallete[c1].blue;
288                                         *wr_buffer++ = pallete[c2].red;
289                                         *wr_buffer++ = pallete[c2].green;
290                                         *wr_buffer++ = pallete[c2].blue;
291                                 }
292                                 if ((*x) % 2)
293                                 {
294                                         unsigned char c1 = tbuffer[j] >> 4;
295                                         *wr_buffer++ = pallete[c1].red;
296                                         *wr_buffer++ = pallete[c1].green;
297                                         *wr_buffer++ = pallete[c1].blue;
298                                 }
299                                 if (skip)
300                                         read(fd, buff, skip);
301                                 wr_buffer -= (*x) * 6;
302                         }
303                         break;
304                 }
305                 case 8:
306                 {
307                         int skip = fill4B(*x);
308                         fetch_pallete(fd, pallete, 256);
309                         lseek(fd, raster, SEEK_SET);
310                         unsigned char * tbuffer = new unsigned char[*x];
311                         if (tbuffer == NULL)
312                                 return 0;
313                         for (int i = 0; i < *y; i++)
314                         {
315                                 read(fd, tbuffer, *x);
316                                 for (int j = 0; j < *x; j++)
317                                 {
318                                         wr_buffer[j * 3] = pallete[tbuffer[j]].red;
319                                         wr_buffer[j * 3 + 1] = pallete[tbuffer[j]].green;
320                                         wr_buffer[j * 3 + 2] = pallete[tbuffer[j]].blue;
321                                 }
322                                 if (skip)
323                                         read(fd, buff, skip);
324                                 wr_buffer -= (*x) * 3;
325                         }
326                         break;
327                 }
328                 case 24:
329                 {
330                         int skip = fill4B((*x) * 3);
331                         lseek(fd, raster, SEEK_SET);
332                         for (int i = 0; i < (*y); i++)
333                         {
334                                 read(fd, wr_buffer, (*x) * 3);
335                                 for (int j = 0; j < (*x) * 3 ; j = j + 3)
336                                 {
337                                         unsigned char c = wr_buffer[j];
338                                         wr_buffer[j] = wr_buffer[j + 2];
339                                         wr_buffer[j + 2] = c;
340                                 }
341                                 if (skip)
342                                         read(fd, buff, skip);
343                                 wr_buffer -= (*x) * 3;
344                         }
345                         break;
346                 }
347                 default:
348                         return 0;
349         }
350
351         close(fd);
352         return 1;
353 }
354
355 //---------------------------------------------------------------------------------------------
356 static int png_load(const char *filename,  int *x, int *y)
357 {
358         static const png_color_16 my_background = {0, 0, 0, 0, 0};
359
360         png_structp png_ptr;
361         png_infop info_ptr;
362         png_uint_32 width, height;
363         unsigned int i;
364         int bit_depth, color_type, interlace_type;
365         int number_passes, pass;
366         png_byte * fbptr;
367         FILE * fh;
368
369         if (!(fh = fopen(filename, "rb"))) return 0;
370
371         png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
372         if (png_ptr == NULL)
373                 return 0;
374         info_ptr = png_create_info_struct(png_ptr);
375         if (info_ptr == NULL)
376         {
377                 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
378                 fclose(fh); 
379                 return 0;
380         }
381
382         if (setjmp(png_ptr->jmpbuf))
383         {
384                 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
385                 fclose(fh); 
386                 return 0;
387         }
388
389         png_init_io(png_ptr, fh);
390
391         png_read_info(png_ptr, info_ptr);
392         png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
393
394         if ((color_type == PNG_COLOR_TYPE_PALETTE)||(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)||(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
395                 png_set_expand(png_ptr);
396         if (bit_depth == 16)
397                 png_set_strip_16(png_ptr);
398         if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
399                 png_set_gray_to_rgb(png_ptr);
400
401         number_passes = png_set_interlace_handling(png_ptr);
402         png_read_update_info(png_ptr, info_ptr);
403
404         int bpp =  png_get_rowbytes(png_ptr, info_ptr)/width;
405         if ((bpp !=4) && (bpp !=3))
406         {
407                 eDebug("[PNG] Error processing");
408                 return 0;
409         }
410
411         if (width * height > 1000000) // 1000x1000 or equiv.
412         {
413                 eDebug("[png_load] image size is %d x %d, which is \"too large\".", width, height);
414                 png_read_end(png_ptr, info_ptr);
415                 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
416                 fclose(fh);
417                 return 0;
418         }
419
420         pic_buffer = new unsigned char[width * height * bpp];
421         *x=width;
422         *y=height;
423
424         for(pass = 0; pass < number_passes; pass++)
425         {
426                 fbptr = (png_byte *)pic_buffer;
427                 for (i = 0; i < height; i++, fbptr += width * bpp)
428                         png_read_row(png_ptr, fbptr, NULL);
429         }
430         png_read_end(png_ptr, info_ptr);
431         png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
432         fclose(fh);
433         if (bpp == 3)
434                 pic_buffer = conv24to32(pic_buffer, width * height, 1);
435         return 1;
436 }
437
438 //-------------------------------------------------------------------
439
440 inline void m_rend_gif_decodecolormap(unsigned char *cmb, unsigned char *rgbb, ColorMapObject *cm, int s, int l)
441 {
442         GifColorType *cmentry;
443         int i;
444         for (i = 0; i < l; i++)
445         {
446                 cmentry = &cm->Colors[cmb[i]];
447                 *(rgbb++) = cmentry->Red;
448                 *(rgbb++) = cmentry->Green;
449                 *(rgbb++) = cmentry->Blue;
450         }
451 }
452
453 static int gif_load(const char *filename, int *x, int *y)
454 {
455         int px, py, i, j, ibxs;
456         unsigned char *fbptr;
457         unsigned char *lb=NULL;
458         unsigned char *slb=NULL;
459         GifFileType *gft;
460         GifRecordType rt;
461         GifByteType *extension;
462         ColorMapObject *cmap;
463         int cmaps;
464         int extcode;
465         
466         gft = DGifOpenFileName(filename);
467         if (gft == NULL) 
468                 return 0;
469         do
470         {
471                 if (DGifGetRecordType(gft, &rt) == GIF_ERROR)
472                         goto ERROR_R;
473                 switch(rt)
474                 {
475                         case IMAGE_DESC_RECORD_TYPE:
476                                 if (DGifGetImageDesc(gft) == GIF_ERROR)
477                                         goto ERROR_R;
478                                 *x = px = gft->Image.Width;
479                                 *y = py = gft->Image.Height;
480                                 pic_buffer = new unsigned char[px * py * 3];
481                                 lb = (unsigned char *)malloc(px * 3);
482                                 slb = (unsigned char *) malloc(px);
483
484                                 if (lb != NULL && slb != NULL)
485                                 {
486                                         cmap = (gft->Image.ColorMap ? gft->Image.ColorMap : gft->SColorMap);
487                                         cmaps = cmap->ColorCount;
488
489                                         ibxs = ibxs * 3;
490                                         fbptr = pic_buffer;
491                                         if (!(gft->Image.Interlace))
492                                         {
493                                                 for (i = 0; i < py; i++, fbptr += px * 3)
494                                                 {
495                                                         if (DGifGetLine(gft, slb, px) == GIF_ERROR)
496                                                                 goto ERROR_R;
497                                                         m_rend_gif_decodecolormap(slb, lb, cmap, cmaps, px);
498                                                         memcpy(fbptr, lb, px * 3);
499                                                 }
500                                         }
501                                         else
502                                         {
503                                                 for (j = 0; j < 4; j++)
504                                                 {
505                                                         fbptr = pic_buffer;
506                                                         for (i = 0; i < py; i++, fbptr += px * 3)
507                                                         {
508                                                                 if (DGifGetLine(gft, slb, px) == GIF_ERROR)
509                                                                         goto ERROR_R;
510                                                                 m_rend_gif_decodecolormap(slb, lb, cmap, cmaps, px);
511                                                                 memcpy(fbptr, lb, px * 3);
512                                                         }
513                                                 }
514                                         }
515                                 }
516                                 if (lb)
517                                 {
518                                         free(lb);
519                                         lb=NULL;
520                                 }
521                                 if (slb)
522                                 {
523                                         free(slb);
524                                         slb=NULL;
525                                 }
526                                 break;
527                         case EXTENSION_RECORD_TYPE:
528                                 if (DGifGetExtension(gft, &extcode, &extension) == GIF_ERROR)
529                                         goto ERROR_R;
530                                 while (extension != NULL)
531                                         if (DGifGetExtensionNext(gft, &extension) == GIF_ERROR)
532                                                 goto ERROR_R;
533                                 break;
534                         default:
535                                 break;
536                 }
537         }
538         while (rt != TERMINATE_RECORD_TYPE);
539
540         DGifCloseFile(gft);
541         return 1;
542 ERROR_R:
543         eDebug("[GIF] Error");
544         if (lb)         free(lb);
545         if (slb)        free(slb);
546         DGifCloseFile(gft);
547         return 0;
548 }
549
550 //---------------------------------------------------------------------------------------------
551
552 PyObject *getExif(const char *filename)
553 {
554         ePyObject list;
555         Cexif exif;
556         if(exif.DecodeExif(filename))
557         {
558                 if(exif.m_exifinfo->IsExif)
559                 {
560                         int pos=0;
561                         char tmp[256];
562                         list = PyList_New(22);
563                         PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->Version));
564                         PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->CameraMake));
565                         PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->CameraModel));
566                         PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->DateTime));
567                         PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->Comments));
568                         PyList_SET_ITEM(list, pos++,  PyString_FromFormat("%d x %d", exif.m_exifinfo->Width, exif.m_exifinfo->Height));
569                         PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->Orientation));
570                         PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->MeteringMode));
571                         PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->ExposureProgram));
572                         PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->LightSource));
573                         PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->FlashUsed));
574                         PyList_SET_ITEM(list, pos++,  PyString_FromFormat("%d", exif.m_exifinfo->CompressionLevel));
575                         PyList_SET_ITEM(list, pos++,  PyString_FromFormat("%d", exif.m_exifinfo->ISOequivalent));
576                         sprintf(tmp, "%.2f", exif.m_exifinfo->Xresolution);
577                         PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
578                         sprintf(tmp, "%.2f", exif.m_exifinfo->Yresolution);
579                         PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
580                         PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->ResolutionUnit));
581                         sprintf(tmp, "%.2f", exif.m_exifinfo->Brightness);
582                         PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
583                         sprintf(tmp, "%.5f sec.", exif.m_exifinfo->ExposureTime);
584                         PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
585                         sprintf(tmp, "%.5f", exif.m_exifinfo->ExposureBias);
586                         PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
587                         sprintf(tmp, "%.5f", exif.m_exifinfo->Distance);
588                         PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
589                         sprintf(tmp, "%.5f", exif.m_exifinfo->CCDWidth);
590                         PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
591                         sprintf(tmp, "%.2f", exif.m_exifinfo->ApertureFNumber);
592                         PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
593                 }
594                 else
595                 {
596                         list = PyList_New(1);
597                         PyList_SET_ITEM(list, 0, PyString_FromString(exif.m_szLastError));
598                 }
599                 exif.ClearExif();
600         }
601         else
602         {
603                 list = PyList_New(1);
604                 PyList_SET_ITEM(list, 0, PyString_FromString(exif.m_szLastError));
605         }
606
607         return list ? (PyObject*)list : (PyObject*)PyList_New(0);
608 }
609
610 //---------------------------------------------------------------------------------------------
611 enum {F_NONE, F_PNG, F_JPEG, F_BMP, F_GIF};
612
613 static int pic_id(const char *name)
614 {
615         unsigned char id[10];
616         int fd = open(name, O_RDONLY); 
617         if (fd == -1) 
618                 return F_NONE;
619         read(fd, id, 10);
620         close(fd);
621
622         if(id[1] == 'P' && id[2] == 'N' && id[3] == 'G')
623                 return F_PNG;
624         else if(id[6] == 'J' && id[7] == 'F' && id[8] == 'I' && id[9] == 'F')
625                 return F_JPEG;
626         else if(id[0] == 0xff && id[1] == 0xd8 && id[2] == 0xff) 
627                 return F_JPEG;
628         else if(id[0] == 'B' && id[1] == 'M' )
629                 return F_BMP;
630         else if(id[0] == 'G' && id[1] == 'I' && id[2] == 'F')
631                 return F_GIF;
632         return F_NONE;
633 }
634
635 int loadPic(ePtr<gPixmap> &result, std::string filename, int w, int h, int aspect, int resize_mode, int rotate, int background, std::string cachefile)
636 {
637         result = 0;
638         int ox=0, oy=0, imx, imy;
639         pic_buffer=NULL;
640         bool cache=false;
641
642         if(cachefile.length())
643         {
644                 if(png_load(cachefile.c_str(), &ox, &oy))
645                         eDebug("[CACHEPIC] x-size=%d, y-size=%d", ox, oy);
646         }
647
648         if(pic_buffer==NULL)
649         {
650                 switch(pic_id(filename.c_str()))
651                 {
652                         case F_PNG:     png_load(filename.c_str(), &ox, &oy);break;
653                         case F_JPEG:    jpeg_load(filename.c_str(), &ox, &oy);pic_buffer = conv24to32(pic_buffer, ox*oy, 1); break;
654                         case F_BMP:     bmp_load(filename.c_str(), &ox, &oy);pic_buffer = conv24to32(pic_buffer, ox*oy, 1); break;
655                         case F_GIF:     gif_load(filename.c_str(), &ox, &oy);pic_buffer = conv24to32(pic_buffer, ox*oy, 1); break;
656                         default:
657                                 eDebug("[PIC] <format not supportet>");
658                                 return 0;
659                 }
660         
661                 if(pic_buffer==NULL)
662                         return 0;
663
664                 double aspect_ratio;
665                 switch(aspect)
666                 {
667                         case 1:         aspect_ratio = 1.778 / ((double)720/576); break; //16:9
668                         case 2:         aspect_ratio = 1.600 / ((double)720/576); break; //16:10
669                         case 3:         aspect_ratio = 1.250 / ((double)720/576); break; //5:4
670                         default:        aspect_ratio = 1.333 / ((double)720/576); //4:3
671                 }
672
673                 if((aspect_ratio * oy * w / ox) <= h)
674                 {
675                         imx = w;
676                         imy = (int)(aspect_ratio*oy*w/ox);
677                 }
678                 else
679                 {
680                         imx = (int)((1.0/aspect_ratio)*ox*h/oy);
681                         imy = h;
682                 }
683
684                 if(resize_mode) pic_buffer = color_resize(pic_buffer, ox, oy, imx, imy);
685                 else            pic_buffer = simple_resize(pic_buffer, ox, oy, imx, imy);
686
687                 ox = imx;
688                 oy = imy;
689         }
690         else cache = true;
691         
692         result=new gPixmap(eSize(w, h), 32);
693         gSurface *surface = result->surface;
694         int a=0, b=0;
695         int nc=0, oc=0;
696         int o_y=0, u_y=0, v_x=0, h_x=0;
697         unsigned char clear[4] = {0x00,0x00,0x00,0x00};
698         if(background)  clear[3]=0xFF;
699         unsigned char *tmp_buffer=((unsigned char *)(surface->data));
700
701         if(oy < h)
702         {
703                 o_y=(h-oy)/2;
704                 u_y=h-oy-o_y;
705         }
706         if(ox < w)
707         {
708                 v_x=(w-ox)/2;
709                 h_x=w-ox-v_x;
710         }
711         
712         //eDebug("o_y=%d u_y=%d v_x=%d h_x=%d", o_y, u_y, v_x, h_x);
713
714         if(oy < h)
715                 for(a=0; a<(o_y*ox); a++, nc+=4)
716                 {
717                         tmp_buffer=((unsigned char *)(surface->data)) + nc;
718                         memcpy(tmp_buffer, clear, sizeof(clear));
719                 }
720
721         for(a=0; a<oy; a++)
722         {
723                 if(ox < w)
724                         for(b=0; b<v_x; b++, nc+=4)
725                         {
726                                 tmp_buffer=((unsigned char *)(surface->data)) + nc;
727                                 memcpy(tmp_buffer, clear, sizeof(clear));
728                         }
729
730                 for(b=0; b<(ox*4); b+=4, nc+=4)
731                 {
732                         tmp_buffer=((unsigned char *)(surface->data)) + nc;
733                         tmp_buffer[2]=pic_buffer[oc++];
734                         tmp_buffer[1]=pic_buffer[oc++];
735                         tmp_buffer[0]=pic_buffer[oc++];
736                         tmp_buffer[3]=pic_buffer[oc++];
737
738                 }
739                 
740                 if(ox < w)
741                         for(b=0; b<h_x; b++, nc+=4)
742                         {
743                                 tmp_buffer=((unsigned char *)(surface->data)) + nc;
744                                 memcpy(tmp_buffer, clear, sizeof(clear));
745                         }
746         }
747
748         if(oy < h)
749                 for(a=0; a<(u_y*ox); a++, nc+=4)
750                 {
751                         tmp_buffer=((unsigned char *)(surface->data)) + nc;
752                         memcpy(tmp_buffer, clear, sizeof(clear));
753                 }
754         
755         //eDebug("[PIC] buffer=%d, nc=%d oc=%d ox=%d, oy=%d",w*h*4, nc, oc, ox, oy);
756         
757         surface->clut.data=0;
758         surface->clut.colors=0;
759         surface->clut.start=0;
760         
761         delete [] pic_buffer;
762
763         if(cachefile.length() && !cache)
764         {
765                 savePNG( cachefile.c_str(), result);
766                 eDebug("[SAVEPIC] x-size=%d, y-size=%d", ox, oy);
767         }
768
769         return 0;
770 }