more changes for async picture decode support
[vuplus_dvbapp] / lib / gdi / picload.cpp
index 6a79d55..b1dfd1a 100644 (file)
@@ -1,31 +1,57 @@
-#include <lib/gdi/picload.h>
-#include "picexif.h"
-#include <lib/python/python.h>
-
-#include <png.h>
-
+#include <png.h>       // must be included before Python.h because of setjmp
 #include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
+
+#include <lib/gdi/picload.h>
+#include <lib/gdi/picexif.h>
 
 extern "C" {
 #include <jpeglib.h>
 #include <gif_lib.h>
-//#include "transupp.h"
 }
-#include <setjmp.h>
 
-unsigned char *pic_buffer=NULL;
+extern const uint32_t crc32_table[256];
+
+DEFINE_REF(ePicLoad);
 
-static unsigned char *simple_resize(unsigned char * orgin, int ox, int oy, int dx, int dy)
+static std::string getSize(const char* file)
+{
+       struct stat64 s;
+       if (stat64(file, &s) < 0)
+               return "";
+       char tmp[20];
+       snprintf(tmp, 20, "%ld kB",(long)s.st_size / 1024);
+       return tmp;
+}
+
+static unsigned char *conv24to32(unsigned char *orgin, int size, unsigned char alpha = 0xFF)
+{
+       int s, d;
+       unsigned char *cr = new unsigned char[size * 4];
+       if (cr == NULL)
+       {
+               eDebug("[Picload] Error malloc");
+               return(orgin);
+       }
+
+       for (s = 0, d = 0 ; s < (size * 3); s += 3, d += 4 )
+       {
+               cr[d] = orgin[s];
+               cr[d+1] = orgin[s + 1];
+               cr[d+2] = orgin[s + 2];
+               cr[d+3] = alpha;
+       }
+       delete [] orgin;
+       return(cr);
+}
+
+static unsigned char *simple_resize(unsigned char *orgin, int ox, int oy, int dx, int dy)
 {
        unsigned char *cr, *p, *l;
        int i, j, k, ip;
-       cr = new unsigned char[dx * dy * 3]; 
+       cr = new unsigned char[dx * dy * 3];
        if (cr == NULL)
        {
-               printf("[RESIZE] Error: malloc\n");
+               eDebug("[Picload] Error malloc");
                return(orgin);
        }
        l = cr;
@@ -53,7 +79,7 @@ static unsigned char *color_resize(unsigned char * orgin, int ox, int oy, int dx
        cr = new unsigned char[dx * dy * 3];
        if (cr == NULL)
        {
-               printf("[RESIZE] Error: malloc\n");
+               eDebug("[Picload] Error malloc");
                return(orgin);
        }
        p = cr;
@@ -85,109 +111,6 @@ static unsigned char *color_resize(unsigned char * orgin, int ox, int oy, int dx
        return(cr);
 }
 
-//-------------------------------------------------------------------
-
-struct r_jpeg_error_mgr
-{
-       struct jpeg_error_mgr pub;
-       jmp_buf envbuffer;
-};
-
-void jpeg_cb_error_exit(j_common_ptr cinfo)
-{
-       struct r_jpeg_error_mgr *mptr;
-       mptr = (struct r_jpeg_error_mgr *) cinfo->err;
-       (*cinfo->err->output_message) (cinfo);
-       longjmp(mptr->envbuffer, 1);
-}
-
-static int jpeg_save(unsigned char *image_buffer, const char * filename, int quality, int image_height, int image_width)
-{
-       struct jpeg_compress_struct cinfo;
-       struct jpeg_error_mgr jerr;
-       FILE * outfile;         /* target file */
-       JSAMPROW row_pointer[1];/* pointer to JSAMPLE row[s] */
-       int row_stride;         /* physical row width in image buffer */
-       cinfo.err = jpeg_std_error(&jerr);
-       jpeg_create_compress(&cinfo);
-       if ((outfile = fopen(filename, "wb")) == NULL) 
-       {
-               eDebug("[JPEG] can't open %s", filename);
-               return -1;
-       }
-       jpeg_stdio_dest(&cinfo, outfile);
-       cinfo.image_width = image_width;
-       cinfo.image_height = image_height;
-       cinfo.input_components = 3;
-       cinfo.in_color_space = JCS_RGB;
-       jpeg_set_defaults(&cinfo);
-       jpeg_set_quality(&cinfo, quality, TRUE );
-       jpeg_start_compress(&cinfo, TRUE);
-       row_stride = image_width * 3;
-       while (cinfo.next_scanline < cinfo.image_height) 
-       {
-               row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
-               (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
-       }
-       jpeg_finish_compress(&cinfo);
-       fclose(outfile);
-       jpeg_destroy_compress(&cinfo);
-       return 0;
-}
-
-
-static int jpeg_load(const char *filename, int *x, int *y)
-{
-       struct jpeg_decompress_struct cinfo;
-       struct jpeg_decompress_struct *ciptr = &cinfo;
-       struct r_jpeg_error_mgr emgr;
-       FILE *fh;
-
-       if (!(fh = fopen(filename, "rb")))
-               return 0;
-
-       ciptr->err = jpeg_std_error(&emgr.pub);
-       emgr.pub.error_exit = jpeg_cb_error_exit;
-       if (setjmp(emgr.envbuffer) == 1)
-       {
-               jpeg_destroy_decompress(ciptr);
-               fclose(fh);
-               return 0;
-       }
-
-       jpeg_create_decompress(ciptr);
-       jpeg_stdio_src(ciptr, fh);
-       jpeg_read_header(ciptr, TRUE);
-       ciptr->out_color_space = JCS_RGB;
-       ciptr->scale_denom = 1;
-
-       jpeg_start_decompress(ciptr);
-       
-       *x=ciptr->output_width;
-       *y=ciptr->output_height;
-
-       if(ciptr->output_components == 3)
-       {
-               JSAMPLE *lb = (JSAMPLE *)(*ciptr->mem->alloc_small)((j_common_ptr) ciptr, JPOOL_PERMANENT, ciptr->output_width * ciptr->output_components);
-               pic_buffer = new unsigned char[ciptr->output_height * ciptr->output_width * ciptr->output_components];
-               unsigned char *bp = pic_buffer;
-
-               while (ciptr->output_scanline < ciptr->output_height)
-               {
-                       jpeg_read_scanlines(ciptr, &lb, 1);
-                       memcpy(bp, lb, ciptr->output_width * ciptr->output_components);
-                       bp += ciptr->output_width * ciptr->output_components;
-               }
-       }
-       jpeg_finish_decompress(ciptr);
-       jpeg_destroy_decompress(ciptr);
-       fclose(fh);
-       return 1;
-}
-
 //---------------------------------------------------------------------------------------------
 
 #define BMP_TORASTER_OFFSET 10
@@ -217,26 +140,26 @@ static void fetch_pallete(int fd, struct color pallete[], int count)
        }
 }
 
-static int bmp_load(const char *filename,  int *x, int *y)
+static unsigned char *bmp_load(const char *file,  int *x, int *y)
 {
        unsigned char buff[4];
        struct color pallete[256];
 
-       int fd = open(filename, O_RDONLY);
-       if (fd == -1) return 0;
-       if (lseek(fd, BMP_SIZE_OFFSET, SEEK_SET) == -1) return 0;
+       int fd = open(file, O_RDONLY);
+       if (fd == -1) return NULL;
+       if (lseek(fd, BMP_SIZE_OFFSET, SEEK_SET) == -1) return NULL;
        read(fd, buff, 4);
        *x = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
        read(fd, buff, 4);
        *y = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
-       if (lseek(fd, BMP_TORASTER_OFFSET, SEEK_SET) == -1) return 0;
+       if (lseek(fd, BMP_TORASTER_OFFSET, SEEK_SET) == -1) return NULL;
        read(fd, buff, 4);
        int raster = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
-       if (lseek(fd, BMP_BPP_OFFSET, SEEK_SET) == -1) return 0;
+       if (lseek(fd, BMP_BPP_OFFSET, SEEK_SET) == -1) return NULL;
        read(fd, buff, 2);
        int bpp = buff[0] + (buff[1] << 8);
 
-       pic_buffer = new unsigned char[(*x) * (*y) * 3];
+       unsigned char *pic_buffer = new unsigned char[(*x) * (*y) * 3];
        unsigned char *wr_buffer = pic_buffer + (*x) * ((*y) - 1) * 3;
        
        switch (bpp)
@@ -248,7 +171,7 @@ static int bmp_load(const char *filename,  int *x, int *y)
                        lseek(fd, raster, SEEK_SET);
                        unsigned char * tbuffer = new unsigned char[*x / 2 + 1];
                        if (tbuffer == NULL)
-                               return 0;
+                               return NULL;
                        for (int i = 0; i < *y; i++) 
                        {
                                read(fd, tbuffer, (*x) / 2 + *x % 2);
@@ -284,7 +207,7 @@ static int bmp_load(const char *filename,  int *x, int *y)
                        lseek(fd, raster, SEEK_SET);
                        unsigned char * tbuffer = new unsigned char[*x];
                        if (tbuffer == NULL)
-                               return 0;
+                               return NULL;
                        for (int i = 0; i < *y; i++)
                        {
                                read(fd, tbuffer, *x);
@@ -320,19 +243,18 @@ static int bmp_load(const char *filename,  int *x, int *y)
                        break;
                }
                default:
-                       return 0;
+                       return NULL;
        }
 
        close(fd);
-       return 1;
+       return(pic_buffer);
 }
 
-//---------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------
 
-static int png_load(const char *filename,  int *x, int *y)
+static unsigned char *png_load(const char *file, int *ox, int *oy)
 {
-       static const png_color_16 my_background = {0, 0, 0, 0, 0};
-
+       //static const png_color_16 my_background = {0, 0, 0, 0, 0};
        png_structp png_ptr;
        png_infop info_ptr;
        png_uint_32 width, height;
@@ -342,17 +264,17 @@ static int png_load(const char *filename,  int *x, int *y)
        png_byte * fbptr;
        FILE * fh;
 
-       if (!(fh = fopen(filename, "rb"))) return 0;
+       if (!(fh = fopen(file, "rb"))) return NULL;
 
        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
        if (png_ptr == NULL)
-               return 0;
+               return NULL;
        info_ptr = png_create_info_struct(png_ptr);
        if (info_ptr == NULL)
        {
                png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
                fclose(fh); 
-               return 0;
+               return NULL;
        }
 
        if (setjmp(png_ptr->jmpbuf))
@@ -367,28 +289,18 @@ static int png_load(const char *filename,  int *x, int *y)
        png_read_info(png_ptr, info_ptr);
        png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
 
-       if (color_type == PNG_COLOR_TYPE_PALETTE)
-       {
-               png_set_palette_to_rgb(png_ptr);
-               png_set_background(png_ptr, (png_color_16 *)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
-       }
-
+       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)))
+               png_set_expand(png_ptr);
+       if (bit_depth == 16)
+               png_set_strip_16(png_ptr);
        if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-       {
                png_set_gray_to_rgb(png_ptr);
-               png_set_background(png_ptr, (png_color_16 *)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
-       }
-
-       if (color_type & PNG_COLOR_MASK_ALPHA)
-               png_set_strip_alpha(png_ptr);
-
-       if (bit_depth < 8)      png_set_packing(png_ptr);
-       if (bit_depth == 16)    png_set_strip_16(png_ptr);
 
        number_passes = png_set_interlace_handling(png_ptr);
        png_read_update_info(png_ptr, info_ptr);
 
-       if (width * 3 != png_get_rowbytes(png_ptr, info_ptr))
+       int bpp =  png_get_rowbytes(png_ptr, info_ptr)/width;
+       if ((bpp !=4) && (bpp !=3))
        {
                eDebug("[PNG] Error processing");
                return 0;
@@ -396,27 +308,133 @@ static int png_load(const char *filename,  int *x, int *y)
 
        if (width * height > 1000000) // 1000x1000 or equiv.
        {
-               eDebug("[png_load] image size is %d x %d, which is \"too large\".", width, height);
+               eDebug("[png_load] image size is %d x %d, which is \"too large\".", (int)width, (int)height);
                png_read_end(png_ptr, info_ptr);
                png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
                fclose(fh);
                return 0;
        }
 
-       pic_buffer = new unsigned char[width * height * 3];
-       *x=width;
-       *y=height;
+       unsigned char *pic_buffer = new unsigned char[width * height * bpp];
+       *ox=width;
+       *oy=height;
 
        for(pass = 0; pass < number_passes; pass++)
        {
                fbptr = (png_byte *)pic_buffer;
-               for (i = 0; i < height; i++, fbptr += width * 3)
+               for (i = 0; i < height; i++, fbptr += width * bpp)
                        png_read_row(png_ptr, fbptr, NULL);
        }
        png_read_end(png_ptr, info_ptr);
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
        fclose(fh);
-       return 1;
+       return(pic_buffer);
+}
+
+//-------------------------------------------------------------------
+
+struct r_jpeg_error_mgr
+{
+       struct jpeg_error_mgr pub;
+       jmp_buf envbuffer;
+};
+
+void jpeg_cb_error_exit(j_common_ptr cinfo)
+{
+       struct r_jpeg_error_mgr *mptr;
+       mptr = (struct r_jpeg_error_mgr *) cinfo->err;
+       (*cinfo->err->output_message) (cinfo);
+       longjmp(mptr->envbuffer, 1);
+}
+
+static unsigned char *jpeg_load(const char *file, int *ox, int *oy)
+{
+       struct jpeg_decompress_struct cinfo;
+       struct jpeg_decompress_struct *ciptr = &cinfo;
+       struct r_jpeg_error_mgr emgr;
+       FILE *fh;
+       unsigned char *pic_buffer=NULL;
+
+       if (!(fh = fopen(file, "rb")))
+               return NULL;
+
+       ciptr->err = jpeg_std_error(&emgr.pub);
+       emgr.pub.error_exit = jpeg_cb_error_exit;
+       if (setjmp(emgr.envbuffer) == 1)
+       {
+               jpeg_destroy_decompress(ciptr);
+               fclose(fh);
+               return NULL;
+       }
+
+       jpeg_create_decompress(ciptr);
+       jpeg_stdio_src(ciptr, fh);
+       jpeg_read_header(ciptr, TRUE);
+       ciptr->out_color_space = JCS_RGB;
+       ciptr->scale_denom = 1;
+
+       jpeg_start_decompress(ciptr);
+       
+       *ox=ciptr->output_width;
+       *oy=ciptr->output_height;
+
+       if(ciptr->output_components == 3)
+       {
+               JSAMPLE *lb = (JSAMPLE *)(*ciptr->mem->alloc_small)((j_common_ptr) ciptr, JPOOL_PERMANENT, ciptr->output_width * ciptr->output_components);
+               pic_buffer = new unsigned char[ciptr->output_height * ciptr->output_width * ciptr->output_components];
+               unsigned char *bp = pic_buffer;
+
+               while (ciptr->output_scanline < ciptr->output_height)
+               {
+                       jpeg_read_scanlines(ciptr, &lb, 1);
+                       memcpy(bp, lb, ciptr->output_width * ciptr->output_components);
+                       bp += ciptr->output_width * ciptr->output_components;
+               }
+       }
+       jpeg_finish_decompress(ciptr);
+       jpeg_destroy_decompress(ciptr);
+       fclose(fh);
+       return(pic_buffer);
+}
+
+
+static int jpeg_save(const char * filename, int ox, int oy, unsigned char *pic_buffer)
+{
+       struct jpeg_compress_struct cinfo;
+       struct jpeg_error_mgr jerr;
+       FILE * outfile;         
+       JSAMPROW row_pointer[1];
+       int row_stride;         
+       cinfo.err = jpeg_std_error(&jerr);
+       jpeg_create_compress(&cinfo);
+       if ((outfile = fopen(filename, "wb")) == NULL) 
+       {
+               eDebug("[Picload] jpeg can't open %s", filename);
+               return 1;
+       }
+       eDebug("[Picload] save Thumbnail... %s",filename);
+
+       jpeg_stdio_dest(&cinfo, outfile);
+       cinfo.image_width = ox;
+       cinfo.image_height = oy;
+       cinfo.input_components = 3;
+       cinfo.in_color_space = JCS_RGB;
+       jpeg_set_defaults(&cinfo);
+       jpeg_set_quality(&cinfo, 70, TRUE );
+       jpeg_start_compress(&cinfo, TRUE);
+       row_stride = ox * 3;
+       while (cinfo.next_scanline < cinfo.image_height) 
+       {
+               row_pointer[0] = & pic_buffer[cinfo.next_scanline * row_stride];
+               (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+       }
+       jpeg_finish_compress(&cinfo);
+       fclose(outfile);
+       jpeg_destroy_compress(&cinfo);
+       return 0;
 }
 
 //-------------------------------------------------------------------
@@ -434,8 +452,9 @@ inline void m_rend_gif_decodecolormap(unsigned char *cmb, unsigned char *rgbb, C
        }
 }
 
-static int gif_load(const char *filename, int *x, int *y)
+static unsigned char *gif_load(const char *file, int *ox, int *oy)
 {
+       unsigned char *pic_buffer = NULL;
        int px, py, i, j, ibxs;
        unsigned char *fbptr;
        unsigned char *lb=NULL;
@@ -447,9 +466,9 @@ static int gif_load(const char *filename, int *x, int *y)
        int cmaps;
        int extcode;
        
-       gft = DGifOpenFileName(filename);
+       gft = DGifOpenFileName(file);
        if (gft == NULL) 
-               return 0;
+               return NULL;
        do
        {
                if (DGifGetRecordType(gft, &rt) == GIF_ERROR)
@@ -459,8 +478,8 @@ static int gif_load(const char *filename, int *x, int *y)
                        case IMAGE_DESC_RECORD_TYPE:
                                if (DGifGetImageDesc(gft) == GIF_ERROR)
                                        goto ERROR_R;
-                               *x = px = gft->Image.Width;
-                               *y = py = gft->Image.Height;
+                               *ox = px = gft->Image.Width;
+                               *oy = py = gft->Image.Height;
                                pic_buffer = new unsigned char[px * py * 3];
                                lb = (unsigned char *)malloc(px * 3);
                                slb = (unsigned char *) malloc(px);
@@ -522,237 +541,526 @@ static int gif_load(const char *filename, int *x, int *y)
        while (rt != TERMINATE_RECORD_TYPE);
 
        DGifCloseFile(gft);
-       return 1;
+       return(pic_buffer);
 ERROR_R:
-       eDebug("[GIF] Error");
+       eDebug("[Picload] <Error gif>");
        if (lb)         free(lb);
        if (slb)        free(slb);
        DGifCloseFile(gft);
-       return 0;
+       return NULL;
 }
 
 //---------------------------------------------------------------------------------------------
 
-PyObject *getExif(const char *filename)
+ePicLoad::ePicLoad()
+       :msg_thread(this,1), msg_main(eApp,1)
 {
-       ePyObject list;
-       Cexif exif;
-       if(exif.DecodeExif(filename))
+       CONNECT(msg_thread.recv_msg, ePicLoad::gotMessage);
+       CONNECT(msg_main.recv_msg, ePicLoad::gotMessage);
+       
+       threadrunning = false;
+       m_filepara = NULL;
+       m_conf.max_x = 0;
+       m_conf.max_y = 0;
+       m_conf.aspect_ratio = 1.066400; //4:3
+       m_conf.usecache = false;
+       m_conf.resizetype = 1;
+       memset(m_conf.background,0x00,sizeof(m_conf.background));
+       m_conf.thumbnailsize = 180;
+}
+
+void ePicLoad::waitFinished()
+{
+       msg_thread.send(Message(Message::quit));
+       kill();
+}
+
+ePicLoad::~ePicLoad()
+{
+       if (threadrunning)
+               waitFinished();
+       if(m_filepara != NULL)
+               delete m_filepara;
+}
+
+void ePicLoad::thread_finished()
+{
+       threadrunning=false;
+}
+
+void ePicLoad::thread()
+{
+       hasStarted();
+       threadrunning=true;
+       nice(4);
+       runLoop();
+}
+
+void ePicLoad::decodePic()
+{
+       eDebug("[Picload] decode picture... %s",m_filepara->file);
+       
+       switch(m_filepara->id)
        {
-               if(exif.m_exifinfo->IsExif)
+               case F_PNG:     m_filepara->pic_buffer = png_load(m_filepara->file, &m_filepara->ox, &m_filepara->oy);  break;
+               case F_JPEG:    m_filepara->pic_buffer = jpeg_load(m_filepara->file, &m_filepara->ox, &m_filepara->oy); break;
+               case F_BMP:     m_filepara->pic_buffer = bmp_load(m_filepara->file, &m_filepara->ox, &m_filepara->oy);  break;
+               case F_GIF:     m_filepara->pic_buffer = gif_load(m_filepara->file, &m_filepara->ox, &m_filepara->oy);  break;
+       }
+       
+       if(m_filepara->pic_buffer != NULL)
+       {
+               resizePic();
+       }
+}
+
+void ePicLoad::decodeThumb()
+{
+       eDebug("[Picload] get Thumbnail... %s",m_filepara->file);
+
+       bool exif_thumbnail = false;
+       bool cachefile_found = false;
+       std::string cachefile = "";
+       std::string cachedir = "/.Thumbnails";
+       
+       if(m_filepara->id == F_JPEG)
+       {
+               Cexif *exif = new Cexif;
+               if(exif->DecodeExif(m_filepara->file, 1))
                {
-                       int pos=0;
-                       char tmp[256];
-                       list = PyList_New(22);
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->Version));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->CameraMake));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->CameraModel));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->DateTime));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->Comments));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromFormat("%d x %d", exif.m_exifinfo->Width, exif.m_exifinfo->Height));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->Orientation));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->MeteringMode));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->ExposureProgram));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->LightSource));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->FlashUsed));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromFormat("%d", exif.m_exifinfo->CompressionLevel));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromFormat("%d", exif.m_exifinfo->ISOequivalent));
-                       sprintf(tmp, "%.2f", exif.m_exifinfo->Xresolution);
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
-                       sprintf(tmp, "%.2f", exif.m_exifinfo->Yresolution);
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif.m_exifinfo->ResolutionUnit));
-                       sprintf(tmp, "%.2f", exif.m_exifinfo->Brightness);
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
-                       sprintf(tmp, "%.5f sec.", exif.m_exifinfo->ExposureTime);
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
-                       sprintf(tmp, "%.5f", exif.m_exifinfo->ExposureBias);
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
-                       sprintf(tmp, "%.5f", exif.m_exifinfo->Distance);
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
-                       sprintf(tmp, "%.5f", exif.m_exifinfo->CCDWidth);
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
-                       sprintf(tmp, "%.2f", exif.m_exifinfo->ApertureFNumber);
-                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
+                       if(exif->m_exifinfo->IsExif)
+                       {
+                               if(exif->m_exifinfo->Thumnailstate==2)
+                               {
+                                       m_filepara->file = strdup(THUMBNAILTMPFILE);
+                                       exif_thumbnail = true;
+                                       eDebug("[Picload] Exif Thumbnail found");
+                               }
+                               m_filepara->addExifInfo(exif->m_exifinfo->CameraMake);
+                               m_filepara->addExifInfo(exif->m_exifinfo->CameraModel);
+                               m_filepara->addExifInfo(exif->m_exifinfo->DateTime);
+                               char buf[20];
+                               snprintf(buf, 20, "%d x %d", exif->m_exifinfo->Width, exif->m_exifinfo->Height);
+                               m_filepara->addExifInfo(buf);
+                       }
+                       exif->ClearExif();
                }
-               else
+               delete exif;
+       }
+       
+       if((! exif_thumbnail) && m_conf.usecache)
+       {
+               if(FILE *f=fopen(m_filepara->file, "rb"))
                {
-                       list = PyList_New(1);
-                       PyList_SET_ITEM(list, 0, PyString_FromString(exif.m_szLastError));
+                       int c;
+                       int count = 1024*100;
+                       unsigned long crc32 = 0;
+                       char crcstr[9];*crcstr=0;
+
+                       while ((c=getc(f))!=EOF)
+                       {
+                               crc32 = crc32_table[((crc32) ^ (c)) & 0xFF] ^ ((crc32) >> 8);
+                               if(--count < 0) break;
+                       }
+       
+                       fclose(f);
+                       crc32 = ~crc32;
+                       sprintf(crcstr, "%08lX", crc32);
+               
+                       cachedir = m_filepara->file;
+                       unsigned int pos = cachedir.find_last_of("/");
+                       if (pos != std::string::npos)
+                               cachedir = cachedir.substr(0, pos) + "/.Thumbnails";
+                       
+                       cachefile = cachedir + std::string("/pc_") + crcstr;
+                       if(!access(cachefile.c_str(), R_OK))
+                       {
+                               cachefile_found = true;
+                               m_filepara->file = strdup(cachefile.c_str());
+                               m_filepara->id = F_JPEG;
+                               eDebug("[Picload] Cache File found");
+                       }
                }
-               exif.ClearExif();
        }
-       else
+
+       switch(m_filepara->id)
        {
-               list = PyList_New(1);
-               PyList_SET_ITEM(list, 0, PyString_FromString(exif.m_szLastError));
+               case F_PNG:     m_filepara->pic_buffer = png_load(m_filepara->file, &m_filepara->ox, &m_filepara->oy);  break;
+               case F_JPEG:    m_filepara->pic_buffer = jpeg_load(m_filepara->file, &m_filepara->ox, &m_filepara->oy); break;
+               case F_BMP:     m_filepara->pic_buffer = bmp_load(m_filepara->file, &m_filepara->ox, &m_filepara->oy);  break;
+               case F_GIF:     m_filepara->pic_buffer = gif_load(m_filepara->file, &m_filepara->ox, &m_filepara->oy);  break;
        }
+       
+       if(exif_thumbnail)
+               ::unlink(THUMBNAILTMPFILE);
+       
+       if(m_filepara->pic_buffer != NULL)
+       {
+               //save cachefile
+               if(m_conf.usecache && (! exif_thumbnail) && (! cachefile_found))
+               {
+                       if(access(cachedir.c_str(), R_OK))
+                               ::mkdir(cachedir.c_str(), 0755);
+                       
+                       //resize for Thumbnail
+                       int imx, imy;
+                       if (m_filepara->ox <= m_filepara->oy)
+                       {
+                               imy = m_conf.thumbnailsize;
+                               imx = (int)( (m_conf.thumbnailsize * ((double)m_filepara->ox)) / ((double)m_filepara->oy) );
+                       }
+                       else
+                       {
+                               imx = m_conf.thumbnailsize;
+                               imy = (int)( (m_conf.thumbnailsize * ((double)m_filepara->oy)) / ((double)m_filepara->ox) );
+                       }
 
-       return list ? (PyObject*)list : (PyObject*)PyList_New(0);
-}
+                       m_filepara->pic_buffer = color_resize(m_filepara->pic_buffer, m_filepara->ox, m_filepara->oy, imx, imy);
+                       m_filepara->ox = imx;
+                       m_filepara->oy = imy;
 
-//---------------------------------------------------------------------------------------------
-enum {F_NONE, F_PNG, F_JPEG, F_BMP, F_GIF};
+                       if(jpeg_save(cachefile.c_str(), m_filepara->ox, m_filepara->oy, m_filepara->pic_buffer))
+                               eDebug("[Picload] error saving cachefile");
+               }
+
+               resizePic();
+       }
+}
 
-static int pic_id(const char *name)
+void ePicLoad::resizePic()
 {
-       unsigned char id[10];
-       int fd = open(name, O_RDONLY); 
-       if (fd == -1) 
-               return F_NONE;
-       read(fd, id, 10);
-       close(fd);
+       int imx, imy;
 
-       if(id[1] == 'P' && id[2] == 'N' && id[3] == 'G')
-               return F_PNG;
-       else if(id[6] == 'J' && id[7] == 'F' && id[8] == 'I' && id[9] == 'F')
-               return F_JPEG;
-       else if(id[0] == 0xff && id[1] == 0xd8 && id[2] == 0xff) 
-               return F_JPEG;
-       else if(id[0] == 'B' && id[1] == 'M' )
-               return F_BMP;
-       else if(id[0] == 'G' && id[1] == 'I' && id[2] == 'F')
-               return F_GIF;
-       return F_NONE;
+       if((m_conf.aspect_ratio * m_filepara->oy * m_filepara->max_x / m_filepara->ox) <= m_filepara->max_y)
+       {
+               imx = m_filepara->max_x;
+               imy = (int)(m_conf.aspect_ratio * m_filepara->oy * m_filepara->max_x / m_filepara->ox);
+       }
+       else
+       {
+               imx = (int)((1.0/m_conf.aspect_ratio) * m_filepara->ox * m_filepara->max_y / m_filepara->oy);
+               imy = m_filepara->max_y;
+       }
+               
+       if(m_conf.resizetype)
+               m_filepara->pic_buffer = color_resize(m_filepara->pic_buffer, m_filepara->ox, m_filepara->oy, imx, imy);
+       else
+               m_filepara->pic_buffer = simple_resize(m_filepara->pic_buffer, m_filepara->ox, m_filepara->oy, imx, imy);
+
+       m_filepara->ox = imx;
+       m_filepara->oy = imy;
 }
 
-int loadPic(ePtr<gPixmap> &result, std::string filename, int w, int h, int aspect, int resize_mode, int rotate, int background, std::string cachefile)
+void ePicLoad::gotMessage(const Message &msg)
 {
-       result = 0;
-       int ox=0, oy=0, imx, imy;
-       pic_buffer=NULL;
-       bool cache=false;
+       switch (msg.type)
+       {
+               case Message::decode_Pic:
+                       decodePic();
+                       msg_main.send(Message(Message::decode_finished));
+                       break;
+               case Message::decode_Thumb:
+                       decodeThumb();
+                       msg_main.send(Message(Message::decode_finished));
+                       break;
+               case Message::quit: // called from decode thread
+                       eDebug("[Picload] decode thread ... got quit msg");
+                       quit(0);
+                       break;
+               case Message::decode_finished: // called from main thread
+                       //eDebug("[Picload] decode finished... %s", m_filepara->file);
+                       if(m_filepara->callback)
+                       {
+                               PictureData(m_filepara->picinfo.c_str());
+                       }
+                       else
+                       {
+                               if(m_filepara != NULL)
+                               {
+                                       delete m_filepara;
+                                       m_filepara = NULL;
+                               }
+                       }
+                       break;
+               default:
+                       eDebug("unhandled thread message");
+       }
+}
 
-       if(cachefile.length())
+int ePicLoad::startThread(int what, const char *file, int x, int y)
+{
+       if(threadrunning && m_filepara != NULL)
+       {
+               eDebug("[Picload] thread running");
+               m_filepara->callback = false;
+               return 1;
+       }
+       
+       if(m_filepara != NULL)
        {
-               cache = true;
-               if(jpeg_load(cachefile.c_str(), &ox, &oy))
-                       eDebug("[CACHEPIC] x-size=%d, y-size=%d", ox, oy);
+               delete m_filepara;
+               m_filepara = NULL;
+       }
+       
+       int file_id = -1;
+       unsigned char id[10];
+       int fd = ::open(file, O_RDONLY);
+       if (fd == -1) return 1;
+       ::read(fd, id, 10);
+       ::close(fd);
+
+       if(id[1] == 'P' && id[2] == 'N' && id[3] == 'G')                        file_id = F_PNG;
+       else if(id[6] == 'J' && id[7] == 'F' && id[8] == 'I' && id[9] == 'F')   file_id = F_JPEG;
+       else if(id[0] == 0xff && id[1] == 0xd8 && id[2] == 0xff)                file_id = F_JPEG;
+       else if(id[0] == 'B' && id[1] == 'M' )                                  file_id = F_BMP;
+       else if(id[0] == 'G' && id[1] == 'I' && id[2] == 'F')                   file_id = F_GIF;
+       
+       if(file_id < 0)
+       {
+               eDebug("[Picload] <format not supportet>");
+               return 1;
        }
 
-       if(pic_buffer==NULL)
+       m_filepara = new Cfilepara(file, file_id, getSize(file));
+       x > 0 ? m_filepara->max_x = x : m_filepara->max_x = m_conf.max_x;
+       y > 0 ? m_filepara->max_y = y : m_filepara->max_y = m_conf.max_y;
+       
+       if(m_filepara->max_x <= 0 || m_filepara->max_y <= 0)
        {
-               switch(pic_id(filename.c_str()))
-               {
-                       case F_PNG:     png_load(filename.c_str(), &ox, &oy); break;
-                       case F_JPEG:    jpeg_load(filename.c_str(), &ox, &oy); break;
-                       case F_BMP:     bmp_load(filename.c_str(), &ox, &oy); break;
-                       case F_GIF:     gif_load(filename.c_str(), &ox, &oy); break;
-                       default:
-                               eDebug("[PIC] <format not supportet>");
-                               return 0;
-               }
+               delete m_filepara;
+               m_filepara = NULL;
+               eDebug("[Picload] <error in Para>");
+               return 1;
+       }
        
-               eDebug("[FULLPIC] x-size=%d, y-size=%d", ox, oy);
+       if(what==1)
+               msg_thread.send(Message(Message::decode_Pic));
+       else
+               msg_thread.send(Message(Message::decode_Thumb));
+       run();
+       return 0;
+}
 
-               if(pic_buffer==NULL)
-                       return 0;
+RESULT ePicLoad::startDecode(const char *file, int x, int y)
+{
+       return startThread(1, file, x, y);
+}
 
-               double aspect_ratio;
-               switch(aspect)
-               {
-                       case 1:         aspect_ratio = 1.777 / ((double)720/576); break; //16:9
-                       case 2:         aspect_ratio = 1.600 / ((double)720/576); break; //16:10
-                       //case 3:       aspect_ratio = 1.250 / ((double)720/576); break; //5:4
-                       default:        aspect_ratio = 1.333 / ((double)720/576); //4:3
-               }
+RESULT ePicLoad::getThumbnail(const char *file, int x, int y)
+{
+       return startThread(0, file, x, y);
+}
 
-               if((aspect_ratio * oy * w / ox) <= h)
+PyObject *ePicLoad::getInfo(const char *filename)
+{
+       ePyObject list;
+       
+       Cexif *exif = new Cexif;
+       if(exif->DecodeExif(filename))
+       {
+               if(exif->m_exifinfo->IsExif)
                {
-                       imx = w;
-                       imy = (int)(aspect_ratio*oy*w/ox);
+                       char tmp[256];
+                       int pos=0;
+                       list = PyList_New(23);
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(filename));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif->m_exifinfo->Version));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif->m_exifinfo->CameraMake));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif->m_exifinfo->CameraModel));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif->m_exifinfo->DateTime));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromFormat("%d x %d", exif->m_exifinfo->Width, exif->m_exifinfo->Height));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif->m_exifinfo->FlashUsed));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif->m_exifinfo->Orientation));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif->m_exifinfo->Comments));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif->m_exifinfo->MeteringMode));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif->m_exifinfo->ExposureProgram));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif->m_exifinfo->LightSource));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromFormat("%d", exif->m_exifinfo->CompressionLevel));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromFormat("%d", exif->m_exifinfo->ISOequivalent));
+                       sprintf(tmp, "%.2f", exif->m_exifinfo->Xresolution);
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
+                       sprintf(tmp, "%.2f", exif->m_exifinfo->Yresolution);
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(exif->m_exifinfo->ResolutionUnit));
+                       sprintf(tmp, "%.2f", exif->m_exifinfo->Brightness);
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
+                       sprintf(tmp, "%.5f sec.", exif->m_exifinfo->ExposureTime);
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
+                       sprintf(tmp, "%.5f", exif->m_exifinfo->ExposureBias);
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
+                       sprintf(tmp, "%.5f", exif->m_exifinfo->Distance);
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
+                       sprintf(tmp, "%.5f", exif->m_exifinfo->CCDWidth);
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
+                       sprintf(tmp, "%.2f", exif->m_exifinfo->ApertureFNumber);
+                       PyList_SET_ITEM(list, pos++,  PyString_FromString(tmp));
                }
                else
                {
-                       imx = (int)((1.0/aspect_ratio)*ox*h/oy);
-                       imy = h;
+                       list = PyList_New(2);
+                       PyList_SET_ITEM(list, 0, PyString_FromString(filename));
+                       PyList_SET_ITEM(list, 1, PyString_FromString(exif->m_szLastError));
                }
-
-               if(resize_mode) pic_buffer = color_resize(pic_buffer, ox, oy, imx, imy);
-               else            pic_buffer = simple_resize(pic_buffer, ox, oy, imx, imy);
-
-               ox = imx;
-               oy = imy;
-               
-               if(cache)
-               {
-                       jpeg_save(pic_buffer, cachefile.c_str(), 50, oy, ox);
-                       eDebug("[SAVEPIC] x-size=%d, y-size=%d", ox, oy);
-               }
-               
+               exif->ClearExif();
        }
+       else
+       {
+               list = PyList_New(2);
+               PyList_SET_ITEM(list, 0, PyString_FromString(filename));
+               PyList_SET_ITEM(list, 1, PyString_FromString(exif->m_szLastError));
+       }
+       delete exif;
 
+       return list ? (PyObject*)list : (PyObject*)PyList_New(0);
+}
+
+int ePicLoad::getData(ePtr<gPixmap> &result)
+{
+       result = 0;
+       if(m_filepara->pic_buffer == NULL) return 0;
+       
+       m_filepara->pic_buffer = conv24to32(m_filepara->pic_buffer, m_filepara->ox * m_filepara->oy);
        
-       result=new gPixmap(eSize(w, h), 32);
+       result=new gPixmap(eSize(m_filepara->max_x, m_filepara->max_y), 32);
        gSurface *surface = result->surface;
        int a=0, b=0;
        int nc=0, oc=0;
        int o_y=0, u_y=0, v_x=0, h_x=0;
-       unsigned char clear[4] = {0x00,0x00,0x00,0x00};
-       if(background)  clear[3]=0xFF;
-       unsigned char *tmp_buffer = new unsigned char[4];
 
-       if(oy < h)
+       unsigned char *tmp_buffer=((unsigned char *)(surface->data));
+       
+       if(m_filepara->oy < m_filepara->max_y)
        {
-               o_y=(h-oy)/2;
-               u_y=h-oy-o_y;
+               o_y = (m_filepara->max_y - m_filepara->oy) / 2;
+               u_y = m_filepara->max_y - m_filepara->oy - o_y;
        }
-       if(ox < w)
+       if(m_filepara->ox < m_filepara->max_x)
        {
-               v_x=(w-ox)/2;
-               h_x=w-ox-v_x;
+               v_x = (m_filepara->max_x - m_filepara->ox) / 2;
+               h_x = m_filepara->max_x - m_filepara->ox - v_x;
        }
        
-       //eDebug("o_y=%d u_y=%d v_x=%d h_x=%d", o_y, u_y, v_x, h_x);
-
-       if(oy < h)
-               for(a=0; a<(o_y*ox)+1; a++, nc+=4)
+       if(m_filepara->oy < m_filepara->max_y)
+       {
+               for(a=0; a<(o_y*m_filepara->ox); a++, nc+=4)
                {
-                       memcpy(tmp_buffer, clear, sizeof(clear));
                        tmp_buffer=((unsigned char *)(surface->data)) + nc;
+                       memcpy(tmp_buffer, m_conf.background, sizeof(m_conf.background));
                }
+       }
        
-       for(a=0; a<oy; a++)
+       for(a=0; a<m_filepara->oy; a++)
        {
-               if(ox < w)
+               if(m_filepara->ox < m_filepara->max_x)
+               {
                        for(b=0; b<v_x; b++, nc+=4)
                        {
-                               memcpy(tmp_buffer, clear, sizeof(clear));
                                tmp_buffer=((unsigned char *)(surface->data)) + nc;
+                               memcpy(tmp_buffer, m_conf.background, sizeof(m_conf.background));
                        }
+               }
 
-               for(b=0; b<(ox*3); b+=3, nc+=4)
+               for(b=0; b<(m_filepara->ox*4); b+=4, nc+=4)
                {
-                       tmp_buffer[3]=0xFF;
-                       tmp_buffer[2]=pic_buffer[oc++];
-                       tmp_buffer[1]=pic_buffer[oc++];
-                       tmp_buffer[0]=pic_buffer[oc++];
-
                        tmp_buffer=((unsigned char *)(surface->data)) + nc;
+                       tmp_buffer[2] = m_filepara->pic_buffer[oc++];
+                       tmp_buffer[1] = m_filepara->pic_buffer[oc++];
+                       tmp_buffer[0] = m_filepara->pic_buffer[oc++];
+                       tmp_buffer[3] = m_filepara->pic_buffer[oc++];
                }
                
-               if(ox < w)
+               if(m_filepara->ox < m_filepara->max_x)
+               {
                        for(b=0; b<h_x; b++, nc+=4)
                        {
-                               memcpy(tmp_buffer, clear, sizeof(clear));
                                tmp_buffer=((unsigned char *)(surface->data)) + nc;
+                               memcpy(tmp_buffer, m_conf.background, sizeof(m_conf.background));
                        }
+               }
        }
-
-       if(oy < h)
-               for(a=0; a<(u_y*ox)+1; a++, nc+=4)
+       
+       if(m_filepara->oy < m_filepara->max_y)
+       {
+               for(a=0; a<(u_y*m_filepara->ox); a++, nc+=4)
                {
-                       memcpy(tmp_buffer, clear, sizeof(clear));
                        tmp_buffer=((unsigned char *)(surface->data)) + nc;
+                       memcpy(tmp_buffer, m_conf.background, sizeof(m_conf.background));
                }
-       
-       //eDebug("[PIC] buffer=%d, nc=%d oc=%d ox=%d, oy=%d",w*h*4, nc, oc, ox, oy);
+       }
        
        surface->clut.data=0;
        surface->clut.colors=0;
        surface->clut.start=0;
+
+       delete m_filepara;
+       m_filepara = NULL;
+
+       return 0;
+}
+
+RESULT ePicLoad::setPara(PyObject *val)
+{
+       if (!PyList_Check(val))
+               return 0;
+       if (PyList_Size(val) < 6)
+               return 0;
+
+       m_conf.max_x            = PyInt_AsLong( PyList_GET_ITEM(val, 0));
+       m_conf.max_y            = PyInt_AsLong( PyList_GET_ITEM(val, 1));
+       m_conf.aspect_ratio     = PyFloat_AsDouble( PyList_GET_ITEM(val, 2));
+       m_conf.usecache         = PyInt_AsLong( PyList_GET_ITEM(val, 3));
+       m_conf.resizetype       = PyInt_AsLong( PyList_GET_ITEM(val, 4));
+       const char *bg_str      = PyString_AsString( PyList_GET_ITEM(val, 5));
        
-       delete [] pic_buffer;
+       if(bg_str[0] == '#' && strlen(bg_str)==9)
+       {
+               int bg = strtoul(bg_str+1, NULL, 16);
+               m_conf.background[0] = bg&0xFF;         //BB
+               m_conf.background[1] = (bg>>8)&0xFF;    //GG
+               m_conf.background[2] = (bg>>16)&0xFF;   //RR
+               m_conf.background[3] = bg>>24;          //AA
+       }
+       
+       eDebug("[Picload] setPara max-X=%d max-Y=%d aspect_ratio=%lf cache=%d resize=%d bg=#%02X%02X%02X%02X", m_conf.max_x, m_conf.max_y, m_conf.aspect_ratio, (int)m_conf.usecache, (int)m_conf.resizetype, m_conf.background[3], m_conf.background[2], m_conf.background[1], m_conf.background[0]);
+       return 1;
+}
+
+//------------------------------------------------------------------------------------
+
+//for old plugins
+SWIG_VOID(int) loadPic(ePtr<gPixmap> &result, std::string filename, int x, int y, int aspect, int resize_mode, int rotate, int background, std::string cachefile)
+{
+       result = 0;
+       eDebug("deprecated loadPic function used!!! please use the non blocking version! you can see demo code in Pictureplayer plugin... this function is removed in the near future!");
+       ePicLoad mPL;
+
+       double  aspect_ratio;
+       switch(aspect)
+       {
+               case 1:         aspect_ratio = 1.778 / ((double)720/576); break; //16:9
+               case 2:         aspect_ratio = 1.600 / ((double)720/576); break; //16:10
+               case 3:         aspect_ratio = 1.250 / ((double)720/576); break; //5:4
+               default:        aspect_ratio = 1.333 / ((double)720/576); //4:3
+       }
+       
+       ePyObject list = PyList_New(6);
+       PyList_SET_ITEM(list, 0,  PyLong_FromLong(x));
+       PyList_SET_ITEM(list, 1,  PyLong_FromLong(y));
+       PyList_SET_ITEM(list, 2,  PyFloat_FromDouble(aspect_ratio));
+       PyList_SET_ITEM(list, 3,  PyLong_FromLong(0));
+       PyList_SET_ITEM(list, 4,  PyLong_FromLong(resize_mode));
+       if(background)
+               PyList_SET_ITEM(list, 5,  PyString_FromString("#ff000000"));
+       else
+               PyList_SET_ITEM(list, 5,  PyString_FromString("#00000000"));
+
+       mPL.setPara(list);
+
+       if(!mPL.startDecode(filename.c_str()))
+       {
+               mPL.waitFinished(); // this blocks until the thread is finished
+               mPL.getData(result);
+       }
 
        return 0;
 }