work on asynchron pic loading... to get rid of spinning wheels
authorghost <andreas.monzner@multimedia-labs.de>
Sun, 16 Nov 2008 12:12:56 +0000 (13:12 +0100)
committerghost <andreas.monzner@multimedia-labs.de>
Sun, 16 Nov 2008 12:12:56 +0000 (13:12 +0100)
lib/gdi/picexif.cpp
lib/gdi/picexif.h
lib/gdi/picload.cpp
lib/gdi/picload.h
lib/python/Components/AVSwitch.py
lib/python/enigma_python.i

index 844673c..f9e8055 100644 (file)
@@ -75,7 +75,6 @@ Cexif::Cexif()
 
 Cexif::~Cexif()
 {
-       //ClearExif();
 }
 
 void Cexif::ClearExif()
@@ -89,7 +88,7 @@ void Cexif::ClearExif()
        }
 }
 
-bool Cexif::DecodeExif(const char *filename)
+bool Cexif::DecodeExif(const char *filename, int Thumb)
 {
        FILE * hFile = fopen(filename, "r");
        if(!hFile) return false;
@@ -98,6 +97,7 @@ bool Cexif::DecodeExif(const char *filename)
        m_exifinfo = new EXIFINFO;
        memset(m_exifinfo,0,sizeof(EXIFINFO));
        freeinfo = true;
+       m_exifinfo->Thumnailstate = Thumb;
 
        m_szLastError[0]='\0';
        ExifImageWidth = MotorolaOrder = SectionsRead=0;
@@ -555,12 +555,16 @@ bool Cexif::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase,
                ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP);
         }
 
-       if (ThumbnailSize && ThumbnailOffset)
+       if (ThumbnailSize && ThumbnailOffset && m_exifinfo->Thumnailstate)
        {
                if (ThumbnailSize + ThumbnailOffset <= ExifLength)
                {
-                       m_exifinfo->ThumbnailPointer = OffsetBase + ThumbnailOffset;
-                       m_exifinfo->ThumbnailSize = ThumbnailSize;
+                       if(FILE *tf = fopen(THUMBNAILTMPFILE, "w"))
+                       {
+                               fwrite( OffsetBase + ThumbnailOffset, ThumbnailSize, 1, tf);
+                               fclose(tf);
+                               m_exifinfo->Thumnailstate = 2;
+                       }
                }
        }
 
index cd321d7..bdd64b2 100644 (file)
@@ -8,7 +8,7 @@
 
 #define MAX_COMMENT 1000
 #define MAX_SECTIONS 20
-
+#define THUMBNAILTMPFILE "/tmp/.thumbcache"
 
 typedef struct tag_ExifInfo {
        char  Version        [5];
@@ -29,7 +29,7 @@ typedef struct tag_ExifInfo {
        float ExposureTime;
        float ExposureBias;
        float Distance;
-       float CCDWidth;                 //in milimeters
+       float CCDWidth;
        float FocalplaneXRes;
        float FocalplaneYRes;
        float FocalplaneUnits;
@@ -40,9 +40,10 @@ typedef struct tag_ExifInfo {
        int   ISOequivalent;
        int   Process;
        int   Orient;
-       unsigned char * ThumbnailPointer;
-       unsigned ThumbnailSize;
+       //unsigned char *ThumbnailPointer;
+       //unsigned ThumbnailSize;
        bool  IsExif;
+       int Thumnailstate;
 } EXIFINFO;
 
 static const int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
@@ -59,7 +60,7 @@ public:
        char m_szLastError[256];
        Cexif();
        ~Cexif();
-       bool DecodeExif(const char *filename);
+       bool DecodeExif(const char *filename, int Thumb=0);
        void ClearExif();
 protected:
        bool process_EXIF(unsigned char * CharBuf, unsigned int length);
index 1f9bed4..2ef901f 100644 (file)
@@ -1,38 +1,38 @@
 #include <png.h>       // must be included before Python.h because of setjmp
-#include <lib/gdi/picload.h>
-#include "picexif.h"
-#include <lib/python/python.h>
-
 #include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
 
-#include <epng.h>      // savePNG need it
-
-#define JDCT_DEFAULT JDCT_IFAST
+#include <lib/gdi/picload.h>
+#include <lib/gdi/picexif.h>
 
 extern "C" {
 #include <jpeglib.h>
 #include <gif_lib.h>
-//#include "transupp.h"
 }
 
-unsigned char *pic_buffer=NULL;
+extern const uint32_t crc32_table[256];
+
+DEFINE_REF(ePicLoad);
+
+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, int background = 0)
+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)
        {
-               printf("[CONV32] Error: malloc\n");
+               eDebug("[Picload] Error malloc");
                return(orgin);
        }
 
-       unsigned char alpha = 0x00;
-       if(background)  alpha = 0xFF;
-
        for (s = 0, d = 0 ; s < (size * 3); s += 3, d += 4 )
        {
                cr[d] = orgin[s];
@@ -44,28 +44,27 @@ static unsigned char *conv24to32(unsigned char * orgin, int size, int background
        return(cr);
 }
 
-static unsigned char *simple_resize(unsigned char * orgin, int ox, int oy, int dx, int dy)
+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 * 4]; 
+       cr = new unsigned char[dx * dy * 3];
        if (cr == NULL)
        {
-               printf("[RESIZE] Error: malloc\n");
+               eDebug("[Picload] Error malloc");
                return(orgin);
        }
        l = cr;
 
-       for (j = 0; j < dy; j++,l += dx * 4)
+       for (j = 0; j < dy; j++,l += dx * 3)
        {
-               p = orgin + (j * oy / dy * ox * 4);
-               for (i = 0, k = 0; i < dx; i++, k += 4)
+               p = orgin + (j * oy / dy * ox * 3);
+               for (i = 0, k = 0; i < dx; i++, k += 3)
                {
-                       ip = i * ox / dx * 4;
+                       ip = i * ox / dx * 3;
                        l[k] = p[ip];
                        l[k+1] = p[ip + 1];
                        l[k+2] = p[ip + 2];
-                       l[k+3] = p[ip + 3];
                }
        }
        delete [] orgin;
@@ -76,18 +75,18 @@ static unsigned char *color_resize(unsigned char * orgin, int ox, int oy, int dx
 {
        unsigned char *cr, *p, *q;
        int i, j, k, l, xa, xb, ya, yb;
-       int sq, r, g, b, a;
-       cr = new unsigned char[dx * dy * 4];
+       int sq, r, g, b;
+       cr = new unsigned char[dx * dy * 3];
        if (cr == NULL)
        {
-               printf("[RESIZE] Error: malloc\n");
+               eDebug("[Picload] Error malloc");
                return(orgin);
        }
        p = cr;
 
        for (j = 0; j < dy; j++)
        {
-               for (i = 0; i < dx; i++, p += 4)
+               for (i = 0; i < dx; i++, p += 3)
                {
                        xa = i * ox / dx;
                        ya = j * oy / dy;
@@ -97,269 +96,21 @@ static unsigned char *color_resize(unsigned char * orgin, int ox, int oy, int dx
                        yb = (j + 1) * oy / dy; 
                        if (yb >= oy)
                                yb = oy - 1;
-                       for (l = ya, r = 0, g = 0, b = 0, a = 0, sq = 0; l <= yb; l++)
+                       for (l = ya, r = 0, g = 0, b = 0, sq = 0; l <= yb; l++)
                        {
-                               q = orgin + ((l * ox + xa) * 4);
-                               for (k = xa; k <= xb; k++, q += 4, sq++)
+                               q = orgin + ((l * ox + xa) * 3);
+                               for (k = xa; k <= xb; k++, q += 3, sq++)
                                {
-                                       r += q[0]; g += q[1]; b += q[2]; a += q[3];
+                                       r += q[0]; g += q[1]; b += q[2];
                                }
                        }
-                       p[0] = r / sq; p[1] = g / sq; p[2] = b / sq; p[3] = a / sq;
+                       p[0] = r / sq; p[1] = g / sq; p[2] = b / sq;
                }
        }
        delete [] orgin;
        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;
-}
-
-/* Expanded data source object for memory buffer input */
-typedef struct
-{
-       struct jpeg_source_mgr pub;     /* public fields */
-       FILE *infile;                   /* source stream */
-       JOCTET *buffer;         /* start of buffer */
-       boolean start_of_file;  /* have we gotten any data yet? */
-} mem_source_mgr;
-
-typedef mem_source_mgr *mem_src_ptr;
-
-static void init_source (j_decompress_ptr cinfo)
-{
-       mem_src_ptr src = (mem_src_ptr) cinfo->src;
-       src->start_of_file = TRUE;
-}
-
-static boolean fill_input_buffer (j_decompress_ptr cinfo)
-{
-       /* no-op */ (void)cinfo;
-       return TRUE;
- }
-
-static void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
-{
-       mem_src_ptr src = (mem_src_ptr) cinfo->src;
-       
-       if (num_bytes > 0)
-       {
-               src->pub.next_input_byte += (size_t) num_bytes;
-               src->pub.bytes_in_buffer -= (size_t) num_bytes;
-       }
-}
-
-static void term_source (j_decompress_ptr cinfo)
-{
-       /* no-op */ (void)cinfo;
-}
-
-static void jpeg_memory_src (j_decompress_ptr cinfo, unsigned char *inbfr, int len)
-{
-       mem_src_ptr src;
-       if (cinfo->src == NULL)
-       {
-               cinfo->src = (struct jpeg_source_mgr *)
-               (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, (size_t)sizeof(mem_source_mgr));
-               src = (mem_src_ptr) cinfo->src;
-               src->buffer = (JOCTET *) inbfr;
-       }
-       src = (mem_src_ptr) cinfo->src;
-       src->pub.init_source = init_source;
-       src->pub.fill_input_buffer = fill_input_buffer;
-       src->pub.skip_input_data = skip_input_data;
-       src->pub.resync_to_restart = jpeg_resync_to_restart;    /* use default method */
-       src->pub.term_source = term_source;
-       src->infile = 0L;
-       src->pub.bytes_in_buffer = len;                         /* sets to entire file len */
-       src->pub.next_input_byte = (JOCTET *)inbfr;             /* at start of buffer */
-}
-
-static int jpeg_load_thumb(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_save_markers (ciptr, JPEG_APP0 + 1, 0xffff);
-
-       jpeg_read_header(ciptr, TRUE);
-
-       struct jpeg_marker_struct *m = cinfo.marker_list;
-
-       unsigned char *thumb_buf = NULL;
-       size_t bufsize;
-       
-       if ( m )
-       {
-               unsigned char *p_data = m->data;
-               while ( p_data < m->data+m->data_length )
-               {
-                       if ( p_data[0] == 0xFF && p_data[1] == 0xD8 )
-                       {
-                               bufsize = (size_t) m->data_length - (size_t) (p_data-m->data);
-                               thumb_buf = new unsigned char[bufsize];
-                               bufsize = 0;
-                               do {
-                                       thumb_buf[bufsize++] = *p_data;
-                               } while ( !(*p_data++ == 0xFF && *p_data == 0xD9) && p_data < m->data+m->data_length );
-                               thumb_buf[bufsize++] = *p_data;
-                       }
-                       p_data++;
-               }
-       }
-
-       if ( thumb_buf != NULL )
-       {
-               jpeg_create_decompress(ciptr);
-               jpeg_memory_src(ciptr, thumb_buf, bufsize-2);
-               jpeg_read_header(ciptr, TRUE);
-       }
-       else
-               eDebug("no exif thumbnail found! loading actual image instead");
-
-       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;
-}
-
-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
@@ -389,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)
@@ -420,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);
@@ -456,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);
@@ -492,18 +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 const png_color_16 my_background = {0, 0, 0, 0, 0};
+//---------------------------------------------------------------------
 
+static unsigned char *png_load(const char *file, int *ox, int *oy)
+{
+       //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;
@@ -513,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))
@@ -564,9 +315,9 @@ static int png_load(const char *filename,  int *x, int *y)
                return 0;
        }
 
-       pic_buffer = new unsigned char[width * height * bpp];
-       *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++)
        {
@@ -577,9 +328,113 @@ static int png_load(const char *filename,  int *x, int *y)
        png_read_end(png_ptr, info_ptr);
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
        fclose(fh);
-       if (bpp == 3)
-               pic_buffer = conv24to32(pic_buffer, width * height, 1);
-       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;
 }
 
 //-------------------------------------------------------------------
@@ -597,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;
@@ -610,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)
@@ -622,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);
@@ -685,239 +541,477 @@ 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;
+}
+
+ePicLoad::~ePicLoad()
+{
+       msg_thread.send(Message(Message::quit));
+       kill();
+
+       if(m_filepara != NULL)
+               delete m_filepara;
+}
+
+
+void ePicLoad::thread()
+{
+       hasStarted();
+       nice(4);
+       runLoop();
+}
+
+void ePicLoad::decodePic()
+{
+       eDebug("[Picload] decode picture... %s",m_filepara->file);
+       
+       switch(m_filepara->id)
+       {
+               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)
        {
-               if(exif.m_exifinfo->IsExif)
+               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");
+               }
 
-static int pic_id(const char *name)
+               resizePic();
+       }
+}
+
+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((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);
 
-       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;
+       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, int thumbnail)
+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);
+                       threadrunning=false;
+                       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)
+       {
+               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)
        {
-               if(png_load(cachefile.c_str(), &ox, &oy))
-                       eDebug("[CACHEPIC] x-size=%d, y-size=%d", ox, oy);
+               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:    {
-                                       if (thumbnail)
-                                               jpeg_load_thumb(filename.c_str(), &ox, &oy);
-                                       else
-                                               jpeg_load(filename.c_str(), &ox, &oy);
-                                       pic_buffer = conv24to32(pic_buffer, ox*oy, 1);
-                                       break; }
-                       case F_BMP:     bmp_load(filename.c_str(), &ox, &oy);pic_buffer = conv24to32(pic_buffer, ox*oy, 1); break;
-                       case F_GIF:     gif_load(filename.c_str(), &ox, &oy);pic_buffer = conv24to32(pic_buffer, ox*oy, 1); break;
-                       default:
-                               eDebug("[PIC] <format not supportet>");
-                               return 0;
-               }
+               delete m_filepara;
+               m_filepara = NULL;
+               eDebug("[Picload] <error in Para>");
+               return 1;
+       }
        
-               if(pic_buffer==NULL)
-                       return 0;
+       threadrunning=true;
+       if(what==1)
+               msg_thread.send(Message(Message::decode_Pic));
+       else
+               msg_thread.send(Message(Message::decode_Thumb));
+       run();
+       return 0;
+}
 
-               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
-               }
+RESULT ePicLoad::startDecode(const char *file, int x, int y)
+{
+       return startThread(1, file, x, y);
+}
+
+RESULT ePicLoad::getThumbnail(const char *file, int x, int y)
+{
+       return startThread(0, file, x, y);
+}
 
-               if((aspect_ratio * oy * w / ox) <= h)
+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));
+       
+       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;
+}
+
+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));
                }
+               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;
 
-               if(resize_mode) pic_buffer = color_resize(pic_buffer, ox, oy, imx, imy);
-               else            pic_buffer = simple_resize(pic_buffer, ox, oy, imx, imy);
+       return list ? (PyObject*)list : (PyObject*)PyList_New(0);
+}
 
-               ox = imx;
-               oy = imy;
-       }
-       else cache = true;
+int ePicLoad::getData(ePtr<gPixmap> &result)
+{
+       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=((unsigned char *)(surface->data));
 
-       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); a++, nc+=4)
+       if(m_filepara->oy < m_filepara->max_y)
+       {
+               for(a=0; a<(o_y*m_filepara->ox); a++, nc+=4)
                {
                        tmp_buffer=((unsigned char *)(surface->data)) + nc;
-                       memcpy(tmp_buffer, clear, sizeof(clear));
+                       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)
                        {
                                tmp_buffer=((unsigned char *)(surface->data)) + nc;
-                               memcpy(tmp_buffer, clear, sizeof(clear));
+                               memcpy(tmp_buffer, m_conf.background, sizeof(m_conf.background));
                        }
+               }
 
-               for(b=0; b<(ox*4); b+=4, nc+=4)
+               for(b=0; b<(m_filepara->ox*4); b+=4, nc+=4)
                {
                        tmp_buffer=((unsigned char *)(surface->data)) + nc;
-                       tmp_buffer[2]=pic_buffer[oc++];
-                       tmp_buffer[1]=pic_buffer[oc++];
-                       tmp_buffer[0]=pic_buffer[oc++];
-                       tmp_buffer[3]=pic_buffer[oc++];
-
+                       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)
                        {
                                tmp_buffer=((unsigned char *)(surface->data)) + nc;
-                               memcpy(tmp_buffer, clear, sizeof(clear));
+                               memcpy(tmp_buffer, m_conf.background, sizeof(m_conf.background));
                        }
+               }
        }
-
-       if(oy < h)
-               for(a=0; a<(u_y*ox); a++, nc+=4)
+       
+       if(m_filepara->oy < m_filepara->max_y)
+       {
+               for(a=0; a<(u_y*m_filepara->ox); a++, nc+=4)
                {
                        tmp_buffer=((unsigned char *)(surface->data)) + nc;
-                       memcpy(tmp_buffer, clear, sizeof(clear));
+                       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 [] pic_buffer;
 
-       if(cachefile.length() && !cache)
-       {
-               savePNG( cachefile.c_str(), result);
-               eDebug("[SAVEPIC] x-size=%d, y-size=%d", ox, oy);
-       }
+       delete m_filepara;
+       m_filepara = NULL;
 
        return 0;
 }
index 7bb9adf..a85567c 100644 (file)
 #ifndef __picload_h__
 #define __picload_h__
 
-#include "Python.h"
 #include <lib/gdi/gpixmap.h>
-#include <lib/gdi/epng.h>
+#include <lib/base/thread.h>
+#include <lib/python/python.h>
+#include <lib/base/message.h>
+#include <lib/base/ebase.h>
 
-SWIG_VOID(int) loadPic(ePtr<gPixmap> &SWIG_OUTPUT, std::string filename, int x, int y, int aspect, int resize_mode=0, int rotate=0, int background=0, std::string cachefile="", int thumbnail=0);
-PyObject *getExif(const char *filename);
+#ifndef SWIG
+class Cfilepara
+{
+public:
+       int max_x;
+       int max_y;
+       bool callback;
+       
+       const char *file;
+       int id;
+       int ox;
+       int oy;
+       unsigned char *pic_buffer;
+       std::string picinfo;
+       int test;
+       
+       Cfilepara(const char *mfile, int mid, std::string size)
+       {
+               file = strdup(mfile);
+               id = mid;
+               pic_buffer = NULL;
+               callback = true;
+               picinfo = mfile;
+               picinfo += + "\n" + size + "\n";
+       }
+       
+       ~Cfilepara()
+       {
+               if(pic_buffer != NULL)  delete pic_buffer;
+               picinfo.clear();
+       }
+       
+       void addExifInfo(std::string val) { picinfo += val + "\n"; }
+};
+#endif
+
+class ePicLoad: public eMainloop, public eThread, public Object, public iObject
+{
+       DECLARE_REF(ePicLoad);
+
+       enum{ F_PNG, F_JPEG, F_BMP, F_GIF};
+       
+       void decodePic();
+       void decodeThumb();
+       void resizePic();
+
+       Cfilepara *m_filepara;
+       bool threadrunning;
+       
+       struct PConf
+       {
+               int max_x;
+               int max_y;
+               double aspect_ratio;
+               unsigned char background[4];
+               bool resizetype;
+               bool usecache;
+               int thumbnailsize;
+               int test;
+       } m_conf;
+       
+       struct Message
+       {
+               int type;
+               enum
+               {
+                       decode_Pic,
+                       decode_Thumb,
+                       decode_finished,
+                       quit
+               };
+               Message(int type=0)
+                       :type(type) {}
+       };
+       eFixedMessagePump<Message> msg_thread, msg_main;
+
+       void gotMessage(const Message &message);
+       void thread();
+       int startThread(int what, const char *file, int x, int y);
+public:
+       PSignal1<void, const char*> PictureData;
+
+       ePicLoad();
+       ~ePicLoad();
+       
+       RESULT startDecode(const char *filename, int x=0, int y=0);
+       RESULT getThumbnail(const char *filename, int x=0, int y=0);
+       RESULT setPara(PyObject *val);
+       PyObject *getInfo(const char *filename);
+       SWIG_VOID(int) getData(ePtr<gPixmap> &SWIG_OUTPUT);
+};
 
 #endif // __picload_h__
index 8f99b98..7ac2bb9 100644 (file)
@@ -28,6 +28,21 @@ class AVSwitch:
        def setSystem(self, value):
                eAVSwitch.getInstance().setVideomode(value)
 
+       def getOutputAspect(self):
+               if valstr in ("4_3_letterbox", "4_3_panscan"): # 4:3
+                       return 1.333333333
+               elif valstr == "16_9": # auto ... 4:3 or 16:9
+                       # TODO: here we must retrieve the current video aspect ratio...
+                       # because the TV can run in 4:3 or in 16:9 mode.. (switched by wss or scart pin8)
+                       # until we have done this we always return the scale value for 16:9!!
+                       return 1.777777778
+               elif valstr in ("16_9_always", "16_9_letterbox"): # 16:9
+                       return 1.777777778
+               elif valstr in ("16_10_letterbox", "16_10_panscan"): # 16:10
+                       return 1.6
+               print "unknown output aspect!"
+               return 1.0000
+
        def getAspectRatioSetting(self):
                valstr = config.av.aspectratio.value
                if valstr == "4_3_letterbox":
index 7de05d2..8493637 100644 (file)
@@ -141,6 +141,7 @@ typedef long time_t;
 %include <lib/service/service.h>
 
 // TODO: embed these...
+%immutable ePicLoad::PictureData;
 %immutable eButton::selected;
 %immutable eInput::changed;
 %immutable eComponentScan::statusChanged;