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