X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/a0f23d0986f3af9d66367c617677f8a275b72737..2a7b743b84bd9ef380af30b0f9f260bf386eed9a:/lib/gdi/picload.cpp diff --git a/lib/gdi/picload.cpp b/lib/gdi/picload.cpp index d724bfcf..1f9bed48 100644 --- a/lib/gdi/picload.cpp +++ b/lib/gdi/picload.cpp @@ -1,26 +1,54 @@ -#include "picload.h" +#include // must be included before Python.h because of setjmp +#include #include "picexif.h" - -#include +#include #include #include #include #include +#include // savePNG need it + +#define JDCT_DEFAULT JDCT_IFAST + extern "C" { #include +#include //#include "transupp.h" } -#include unsigned char *pic_buffer=NULL; +static unsigned char *conv24to32(unsigned char * orgin, int size, int background = 0) +{ + int s, d; + unsigned char *cr = new unsigned char[size * 4]; + if (cr == NULL) + { + printf("[CONV32] Error: malloc\n"); + 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]; + 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 * 4]; if (cr == NULL) { printf("[RESIZE] Error: malloc\n"); @@ -28,15 +56,16 @@ static unsigned char *simple_resize(unsigned char * orgin, int ox, int oy, int d } l = cr; - for (j = 0; j < dy; j++,l += dx * 3) + for (j = 0; j < dy; j++,l += dx * 4) { - p = orgin + (j * oy / dy * ox * 3); - for (i = 0, k = 0; i < dx; i++, k += 3) + p = orgin + (j * oy / dy * ox * 4); + for (i = 0, k = 0; i < dx; i++, k += 4) { - ip = i * ox / dx * 3; + ip = i * ox / dx * 4; l[k] = p[ip]; l[k+1] = p[ip + 1]; l[k+2] = p[ip + 2]; + l[k+3] = p[ip + 3]; } } delete [] orgin; @@ -47,8 +76,8 @@ 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; - cr = new unsigned char[dx * dy * 3]; + int sq, r, g, b, a; + cr = new unsigned char[dx * dy * 4]; if (cr == NULL) { printf("[RESIZE] Error: malloc\n"); @@ -58,7 +87,7 @@ static unsigned char *color_resize(unsigned char * orgin, int ox, int oy, int dx for (j = 0; j < dy; j++) { - for (i = 0; i < dx; i++, p += 3) + for (i = 0; i < dx; i++, p += 4) { xa = i * ox / dx; ya = j * oy / dy; @@ -68,15 +97,15 @@ 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, sq = 0; l <= yb; l++) + for (l = ya, r = 0, g = 0, b = 0, a = 0, sq = 0; l <= yb; l++) { - q = orgin + ((l * ox + xa) * 3); - for (k = xa; k <= xb; k++, q += 3, sq++) + q = orgin + ((l * ox + xa) * 4); + for (k = xa; k <= xb; k++, q += 4, sq++) { - r += q[0]; g += q[1]; b += q[2]; + r += q[0]; g += q[1]; b += q[2]; a += q[3]; } } - p[0] = r / sq; p[1] = g / sq; p[2] = b / sq; + p[0] = r / sq; p[1] = g / sq; p[2] = b / sq; p[3] = a / sq; } } delete [] orgin; @@ -136,6 +165,151 @@ static int jpeg_save(unsigned char *image_buffer, const char * filename, int qua 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) { @@ -196,9 +370,29 @@ static int jpeg_load(const char *filename, int *x, int *y) #define fill4B(a) ((4 - ((a) % 4 )) & 0x03) +struct color { + unsigned char red; + unsigned char green; + unsigned char blue; +}; + +static void fetch_pallete(int fd, struct color pallete[], int count) +{ + unsigned char buff[4]; + lseek(fd, BMP_COLOR_OFFSET, SEEK_SET); + for (int i = 0; i < count; i++) + { + read(fd, buff, 4); + pallete[i].red = buff[2]; + pallete[i].green = buff[1]; + pallete[i].blue = buff[0]; + } +} + static int bmp_load(const char *filename, int *x, int *y) { unsigned char buff[4]; + struct color pallete[256]; int fd = open(filename, O_RDONLY); if (fd == -1) return 0; @@ -214,23 +408,80 @@ static int bmp_load(const char *filename, int *x, int *y) read(fd, buff, 2); int bpp = buff[0] + (buff[1] << 8); - //printf("x=%d, y=%d,bpp=%d\n",*x, *y, bpp); pic_buffer = new unsigned char[(*x) * (*y) * 3]; unsigned char *wr_buffer = pic_buffer + (*x) * ((*y) - 1) * 3; switch (bpp) { + case 4: + { + int skip = fill4B((*x) / 2 + (*x) % 2); + fetch_pallete(fd, pallete, 16); + lseek(fd, raster, SEEK_SET); + unsigned char * tbuffer = new unsigned char[*x / 2 + 1]; + if (tbuffer == NULL) + return 0; + for (int i = 0; i < *y; i++) + { + read(fd, tbuffer, (*x) / 2 + *x % 2); + int j; + for (j = 0; j < (*x) / 2; j++) + { + unsigned char c1 = tbuffer[j] >> 4; + unsigned char c2 = tbuffer[j] & 0x0f; + *wr_buffer++ = pallete[c1].red; + *wr_buffer++ = pallete[c1].green; + *wr_buffer++ = pallete[c1].blue; + *wr_buffer++ = pallete[c2].red; + *wr_buffer++ = pallete[c2].green; + *wr_buffer++ = pallete[c2].blue; + } + if ((*x) % 2) + { + unsigned char c1 = tbuffer[j] >> 4; + *wr_buffer++ = pallete[c1].red; + *wr_buffer++ = pallete[c1].green; + *wr_buffer++ = pallete[c1].blue; + } + if (skip) + read(fd, buff, skip); + wr_buffer -= (*x) * 6; + } + break; + } + case 8: + { + int skip = fill4B(*x); + fetch_pallete(fd, pallete, 256); + lseek(fd, raster, SEEK_SET); + unsigned char * tbuffer = new unsigned char[*x]; + if (tbuffer == NULL) + return 0; + for (int i = 0; i < *y; i++) + { + read(fd, tbuffer, *x); + for (int j = 0; j < *x; j++) + { + wr_buffer[j * 3] = pallete[tbuffer[j]].red; + wr_buffer[j * 3 + 1] = pallete[tbuffer[j]].green; + wr_buffer[j * 3 + 2] = pallete[tbuffer[j]].blue; + } + if (skip) + read(fd, buff, skip); + wr_buffer -= (*x) * 3; + } + break; + } case 24: { int skip = fill4B((*x) * 3); lseek(fd, raster, SEEK_SET); - unsigned char c; - for (int i = 0; i < (*y); i++) + for (int i = 0; i < (*y); i++) { read(fd, wr_buffer, (*x) * 3); for (int j = 0; j < (*x) * 3 ; j = j + 3) { - c = wr_buffer[j]; + unsigned char c = wr_buffer[j]; wr_buffer[j] = wr_buffer[j + 2]; wr_buffer[j + 2] = c; } @@ -249,7 +500,6 @@ static int bmp_load(const char *filename, int *x, int *y) } //--------------------------------------------------------------------------------------------- - static int png_load(const char *filename, int *x, int *y) { static const png_color_16 my_background = {0, 0, 0, 0, 0}; @@ -288,114 +538,248 @@ 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; } - - pic_buffer = new unsigned char[width * height * 3]; + + if (width * height > 1000000) // 1000x1000 or equiv. + { + 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 * bpp]; *x=width; *y=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); + if (bpp == 3) + pic_buffer = conv24to32(pic_buffer, width * height, 1); return 1; } +//------------------------------------------------------------------- + +inline void m_rend_gif_decodecolormap(unsigned char *cmb, unsigned char *rgbb, ColorMapObject *cm, int s, int l) +{ + GifColorType *cmentry; + int i; + for (i = 0; i < l; i++) + { + cmentry = &cm->Colors[cmb[i]]; + *(rgbb++) = cmentry->Red; + *(rgbb++) = cmentry->Green; + *(rgbb++) = cmentry->Blue; + } +} + +static int gif_load(const char *filename, int *x, int *y) +{ + int px, py, i, j, ibxs; + unsigned char *fbptr; + unsigned char *lb=NULL; + unsigned char *slb=NULL; + GifFileType *gft; + GifRecordType rt; + GifByteType *extension; + ColorMapObject *cmap; + int cmaps; + int extcode; + + gft = DGifOpenFileName(filename); + if (gft == NULL) + return 0; + do + { + if (DGifGetRecordType(gft, &rt) == GIF_ERROR) + goto ERROR_R; + switch(rt) + { + case IMAGE_DESC_RECORD_TYPE: + if (DGifGetImageDesc(gft) == GIF_ERROR) + goto ERROR_R; + *x = px = gft->Image.Width; + *y = py = gft->Image.Height; + pic_buffer = new unsigned char[px * py * 3]; + lb = (unsigned char *)malloc(px * 3); + slb = (unsigned char *) malloc(px); + + if (lb != NULL && slb != NULL) + { + cmap = (gft->Image.ColorMap ? gft->Image.ColorMap : gft->SColorMap); + cmaps = cmap->ColorCount; + + ibxs = ibxs * 3; + fbptr = pic_buffer; + if (!(gft->Image.Interlace)) + { + for (i = 0; i < py; i++, fbptr += px * 3) + { + if (DGifGetLine(gft, slb, px) == GIF_ERROR) + goto ERROR_R; + m_rend_gif_decodecolormap(slb, lb, cmap, cmaps, px); + memcpy(fbptr, lb, px * 3); + } + } + else + { + for (j = 0; j < 4; j++) + { + fbptr = pic_buffer; + for (i = 0; i < py; i++, fbptr += px * 3) + { + if (DGifGetLine(gft, slb, px) == GIF_ERROR) + goto ERROR_R; + m_rend_gif_decodecolormap(slb, lb, cmap, cmaps, px); + memcpy(fbptr, lb, px * 3); + } + } + } + } + if (lb) + { + free(lb); + lb=NULL; + } + if (slb) + { + free(slb); + slb=NULL; + } + break; + case EXTENSION_RECORD_TYPE: + if (DGifGetExtension(gft, &extcode, &extension) == GIF_ERROR) + goto ERROR_R; + while (extension != NULL) + if (DGifGetExtensionNext(gft, &extension) == GIF_ERROR) + goto ERROR_R; + break; + default: + break; + } + } + while (rt != TERMINATE_RECORD_TYPE); + + DGifCloseFile(gft); + return 1; +ERROR_R: + eDebug("[GIF] Error"); + if (lb) free(lb); + if (slb) free(slb); + DGifCloseFile(gft); + return 0; +} + //--------------------------------------------------------------------------------------------- PyObject *getExif(const char *filename) { - PyObject *list = 0; - Cexif *m_exif = new Cexif(); - if(m_exif->DecodeExif(filename)) + ePyObject list; + Cexif exif; + if(exif.DecodeExif(filename)) { - if(m_exif->m_exifinfo->IsExif) + if(exif.m_exifinfo->IsExif) { int pos=0; char tmp[256]; list = PyList_New(22); - PyList_SET_ITEM(list, pos++, PyString_FromString(m_exif->m_exifinfo->Version)); - PyList_SET_ITEM(list, pos++, PyString_FromString(m_exif->m_exifinfo->CameraMake)); - PyList_SET_ITEM(list, pos++, PyString_FromString(m_exif->m_exifinfo->CameraModel)); - PyList_SET_ITEM(list, pos++, PyString_FromString(m_exif->m_exifinfo->DateTime)); - PyList_SET_ITEM(list, pos++, PyString_FromString(m_exif->m_exifinfo->Comments)); - PyList_SET_ITEM(list, pos++, PyString_FromFormat("%d x %d", m_exif->m_exifinfo->Width, m_exif->m_exifinfo->Height)); - PyList_SET_ITEM(list, pos++, PyString_FromString(m_exif->m_exifinfo->Orientation)); - PyList_SET_ITEM(list, pos++, PyString_FromString(m_exif->m_exifinfo->MeteringMode)); - PyList_SET_ITEM(list, pos++, PyString_FromString(m_exif->m_exifinfo->ExposureProgram)); - PyList_SET_ITEM(list, pos++, PyString_FromString(m_exif->m_exifinfo->LightSource)); - PyList_SET_ITEM(list, pos++, PyString_FromString(m_exif->m_exifinfo->FlashUsed)); - PyList_SET_ITEM(list, pos++, PyString_FromFormat("%d", m_exif->m_exifinfo->CompressionLevel)); - PyList_SET_ITEM(list, pos++, PyString_FromFormat("%d", m_exif->m_exifinfo->ISOequivalent)); - sprintf(tmp, "%.2f", m_exif->m_exifinfo->Xresolution); + 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", m_exif->m_exifinfo->Yresolution); + sprintf(tmp, "%.2f", exif.m_exifinfo->Yresolution); PyList_SET_ITEM(list, pos++, PyString_FromString(tmp)); - PyList_SET_ITEM(list, pos++, PyString_FromString(m_exif->m_exifinfo->ResolutionUnit)); - sprintf(tmp, "%.2f", m_exif->m_exifinfo->Brightness); + 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.", m_exif->m_exifinfo->ExposureTime); + sprintf(tmp, "%.5f sec.", exif.m_exifinfo->ExposureTime); PyList_SET_ITEM(list, pos++, PyString_FromString(tmp)); - sprintf(tmp, "%.5f", m_exif->m_exifinfo->ExposureBias); + sprintf(tmp, "%.5f", exif.m_exifinfo->ExposureBias); PyList_SET_ITEM(list, pos++, PyString_FromString(tmp)); - sprintf(tmp, "%.5f", m_exif->m_exifinfo->Distance); + sprintf(tmp, "%.5f", exif.m_exifinfo->Distance); PyList_SET_ITEM(list, pos++, PyString_FromString(tmp)); - sprintf(tmp, "%.5f", m_exif->m_exifinfo->CCDWidth); + sprintf(tmp, "%.5f", exif.m_exifinfo->CCDWidth); PyList_SET_ITEM(list, pos++, PyString_FromString(tmp)); - sprintf(tmp, "%.2f", m_exif->m_exifinfo->ApertureFNumber); + sprintf(tmp, "%.2f", exif.m_exifinfo->ApertureFNumber); PyList_SET_ITEM(list, pos++, PyString_FromString(tmp)); } else { list = PyList_New(1); - PyList_SET_ITEM(list, 0, PyString_FromString(m_exif->m_szLastError)); + PyList_SET_ITEM(list, 0, PyString_FromString(exif.m_szLastError)); } - m_exif->ClearExif(); + exif.ClearExif(); } else { list = PyList_New(1); - PyList_SET_ITEM(list, 0, PyString_FromString(m_exif->m_szLastError)); + PyList_SET_ITEM(list, 0, PyString_FromString(exif.m_szLastError)); } - delete m_exif; - - return list ? list : PyList_New(0); + return list ? (PyObject*)list : (PyObject*)PyList_New(0); } //--------------------------------------------------------------------------------------------- +enum {F_NONE, F_PNG, F_JPEG, F_BMP, F_GIF}; + +static int pic_id(const char *name) +{ + unsigned char id[10]; + int fd = open(name, O_RDONLY); + if (fd == -1) + return F_NONE; + read(fd, id, 10); + close(fd); -int loadPic(ePtr &result, std::string filename, int w, int h, int aspect, int resize_mode, int rotate, int background, std::string cachefile) + 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; +} + +int loadPic(ePtr &result, std::string filename, int w, int h, int aspect, int resize_mode, int rotate, int background, std::string cachefile, int thumbnail) { result = 0; int ox=0, oy=0, imx, imy; @@ -404,41 +788,38 @@ int loadPic(ePtr &result, std::string filename, int w, int h, int aspec if(cachefile.length()) { - cache = true; - if(jpeg_load(cachefile.c_str(), &ox, &oy)) + if(png_load(cachefile.c_str(), &ox, &oy)) eDebug("[CACHEPIC] x-size=%d, y-size=%d", ox, oy); } if(pic_buffer==NULL) { - unsigned int pos = filename.find_last_of("."); - if (pos == std::string::npos) - pos = filename.length() - 1; - std::string ext = filename.substr(pos); - std::transform(ext.begin(), ext.end(), ext.begin(), (int(*)(int)) toupper); - if(ext == ".JPEG" || ext == ".JPG") - jpeg_load(filename.c_str(), &ox, &oy); - else if(ext == ".BMP") - bmp_load(filename.c_str(), &ox, &oy); - else if(ext == ".PNG") - png_load(filename.c_str(), &ox, &oy); - else + switch(pic_id(filename.c_str())) { - eDebug("[PIC] "); - return 0; + 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] "); + return 0; } - eDebug("[FULLPIC] x-size=%d, y-size=%d", ox, oy); - if(pic_buffer==NULL) return 0; double aspect_ratio; switch(aspect) { - case 1: aspect_ratio = 1.777 / ((double)720/576); break; //16:9 + 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 + case 3: aspect_ratio = 1.250 / ((double)720/576); break; //5:4 default: aspect_ratio = 1.333 / ((double)720/576); //4:3 } @@ -458,15 +839,8 @@ int loadPic(ePtr &result, std::string filename, int w, int h, int aspec 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); - } - } - + else cache = true; result=new gPixmap(eSize(w, h), 32); gSurface *surface = result->surface; @@ -475,7 +849,7 @@ int loadPic(ePtr &result, std::string filename, int w, int h, int aspec 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]; + unsigned char *tmp_buffer=((unsigned char *)(surface->data)); if(oy < h) { @@ -491,44 +865,44 @@ int loadPic(ePtr &result, std::string filename, int w, int h, int aspec //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) + for(a=0; a<(o_y*ox); a++, nc+=4) { - memcpy(tmp_buffer, clear, sizeof(clear)); tmp_buffer=((unsigned char *)(surface->data)) + nc; + memcpy(tmp_buffer, clear, sizeof(clear)); } - + for(a=0; adata)) + nc; + memcpy(tmp_buffer, clear, sizeof(clear)); } - for(b=0; b<(ox*3); b+=3, nc+=4) + for(b=0; b<(ox*4); b+=4, nc+=4) { - tmp_buffer[3]=0xFF; + 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=((unsigned char *)(surface->data)) + nc; } if(ox < w) for(b=0; bdata)) + nc; + memcpy(tmp_buffer, clear, sizeof(clear)); } } if(oy < h) - for(a=0; a<(u_y*ox)+1; a++, nc+=4) + for(a=0; a<(u_y*ox); a++, nc+=4) { - memcpy(tmp_buffer, clear, sizeof(clear)); tmp_buffer=((unsigned char *)(surface->data)) + nc; + memcpy(tmp_buffer, clear, sizeof(clear)); } //eDebug("[PIC] buffer=%d, nc=%d oc=%d ox=%d, oy=%d",w*h*4, nc, oc, ox, oy); @@ -539,5 +913,11 @@ int loadPic(ePtr &result, std::string filename, int w, int h, int aspec delete [] pic_buffer; + if(cachefile.length() && !cache) + { + savePNG( cachefile.c_str(), result); + eDebug("[SAVEPIC] x-size=%d, y-size=%d", ox, oy); + } + return 0; }