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