1 #include <lib/gdi/picload.h>
3 #include <lib/python/python.h>
15 //#include "transupp.h"
19 unsigned char *pic_buffer=NULL;
21 static unsigned char *simple_resize(unsigned char * orgin, int ox, int oy, int dx, int dy)
23 unsigned char *cr, *p, *l;
25 cr = new unsigned char[dx * dy * 3];
28 printf("[RESIZE] Error: malloc\n");
33 for (j = 0; j < dy; j++,l += dx * 3)
35 p = orgin + (j * oy / dy * ox * 3);
36 for (i = 0, k = 0; i < dx; i++, k += 3)
48 static unsigned char *color_resize(unsigned char * orgin, int ox, int oy, int dx, int dy)
50 unsigned char *cr, *p, *q;
51 int i, j, k, l, xa, xb, ya, yb;
53 cr = new unsigned char[dx * dy * 3];
56 printf("[RESIZE] Error: malloc\n");
61 for (j = 0; j < dy; j++)
63 for (i = 0; i < dx; i++, p += 3)
67 xb = (i + 1) * ox / dx;
70 yb = (j + 1) * oy / dy;
73 for (l = ya, r = 0, g = 0, b = 0, sq = 0; l <= yb; l++)
75 q = orgin + ((l * ox + xa) * 3);
76 for (k = xa; k <= xb; k++, q += 3, sq++)
78 r += q[0]; g += q[1]; b += q[2];
81 p[0] = r / sq; p[1] = g / sq; p[2] = b / sq;
88 //-------------------------------------------------------------------
90 struct r_jpeg_error_mgr
92 struct jpeg_error_mgr pub;
96 void jpeg_cb_error_exit(j_common_ptr cinfo)
98 struct r_jpeg_error_mgr *mptr;
99 mptr = (struct r_jpeg_error_mgr *) cinfo->err;
100 (*cinfo->err->output_message) (cinfo);
101 longjmp(mptr->envbuffer, 1);
104 static int jpeg_save(unsigned char *image_buffer, const char * filename, int quality, int image_height, int image_width)
106 struct jpeg_compress_struct cinfo;
107 struct jpeg_error_mgr jerr;
108 FILE * outfile; /* target file */
109 JSAMPROW row_pointer[1];/* pointer to JSAMPLE row[s] */
110 int row_stride; /* physical row width in image buffer */
112 cinfo.err = jpeg_std_error(&jerr);
113 jpeg_create_compress(&cinfo);
115 if ((outfile = fopen(filename, "wb")) == NULL)
117 eDebug("[JPEG] can't open %s", filename);
120 jpeg_stdio_dest(&cinfo, outfile);
122 cinfo.image_width = image_width;
123 cinfo.image_height = image_height;
124 cinfo.input_components = 3;
125 cinfo.in_color_space = JCS_RGB;
126 jpeg_set_defaults(&cinfo);
127 jpeg_set_quality(&cinfo, quality, TRUE );
128 jpeg_start_compress(&cinfo, TRUE);
129 row_stride = image_width * 3;
130 while (cinfo.next_scanline < cinfo.image_height)
132 row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
133 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
135 jpeg_finish_compress(&cinfo);
137 jpeg_destroy_compress(&cinfo);
142 static int jpeg_load(const char *filename, int *x, int *y)
144 struct jpeg_decompress_struct cinfo;
145 struct jpeg_decompress_struct *ciptr = &cinfo;
146 struct r_jpeg_error_mgr emgr;
149 if (!(fh = fopen(filename, "rb")))
152 ciptr->err = jpeg_std_error(&emgr.pub);
153 emgr.pub.error_exit = jpeg_cb_error_exit;
154 if (setjmp(emgr.envbuffer) == 1)
156 jpeg_destroy_decompress(ciptr);
161 jpeg_create_decompress(ciptr);
162 jpeg_stdio_src(ciptr, fh);
163 jpeg_read_header(ciptr, TRUE);
164 ciptr->out_color_space = JCS_RGB;
165 ciptr->scale_denom = 1;
167 jpeg_start_decompress(ciptr);
169 *x=ciptr->output_width;
170 *y=ciptr->output_height;
172 if(ciptr->output_components == 3)
174 JSAMPLE *lb = (JSAMPLE *)(*ciptr->mem->alloc_small)((j_common_ptr) ciptr, JPOOL_PERMANENT, ciptr->output_width * ciptr->output_components);
175 pic_buffer = new unsigned char[ciptr->output_height * ciptr->output_width * ciptr->output_components];
176 unsigned char *bp = pic_buffer;
178 while (ciptr->output_scanline < ciptr->output_height)
180 jpeg_read_scanlines(ciptr, &lb, 1);
181 memcpy(bp, lb, ciptr->output_width * ciptr->output_components);
182 bp += ciptr->output_width * ciptr->output_components;
185 jpeg_finish_decompress(ciptr);
186 jpeg_destroy_decompress(ciptr);
191 //---------------------------------------------------------------------------------------------
193 #define BMP_TORASTER_OFFSET 10
194 #define BMP_SIZE_OFFSET 18
195 #define BMP_BPP_OFFSET 28
196 #define BMP_RLE_OFFSET 30
197 #define BMP_COLOR_OFFSET 54
199 #define fill4B(a) ((4 - ((a) % 4 )) & 0x03)
207 static void fetch_pallete(int fd, struct color pallete[], int count)
209 unsigned char buff[4];
210 lseek(fd, BMP_COLOR_OFFSET, SEEK_SET);
211 for (int i = 0; i < count; i++)
214 pallete[i].red = buff[2];
215 pallete[i].green = buff[1];
216 pallete[i].blue = buff[0];
220 static int bmp_load(const char *filename, int *x, int *y)
222 unsigned char buff[4];
223 struct color pallete[256];
225 int fd = open(filename, O_RDONLY);
226 if (fd == -1) return 0;
227 if (lseek(fd, BMP_SIZE_OFFSET, SEEK_SET) == -1) return 0;
229 *x = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
231 *y = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
232 if (lseek(fd, BMP_TORASTER_OFFSET, SEEK_SET) == -1) return 0;
234 int raster = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
235 if (lseek(fd, BMP_BPP_OFFSET, SEEK_SET) == -1) return 0;
237 int bpp = buff[0] + (buff[1] << 8);
239 pic_buffer = new unsigned char[(*x) * (*y) * 3];
240 unsigned char *wr_buffer = pic_buffer + (*x) * ((*y) - 1) * 3;
246 int skip = fill4B((*x) / 2 + (*x) % 2);
247 fetch_pallete(fd, pallete, 16);
248 lseek(fd, raster, SEEK_SET);
249 unsigned char * tbuffer = new unsigned char[*x / 2 + 1];
252 for (int i = 0; i < *y; i++)
254 read(fd, tbuffer, (*x) / 2 + *x % 2);
256 for (j = 0; j < (*x) / 2; j++)
258 unsigned char c1 = tbuffer[j] >> 4;
259 unsigned char c2 = tbuffer[j] & 0x0f;
260 *wr_buffer++ = pallete[c1].red;
261 *wr_buffer++ = pallete[c1].green;
262 *wr_buffer++ = pallete[c1].blue;
263 *wr_buffer++ = pallete[c2].red;
264 *wr_buffer++ = pallete[c2].green;
265 *wr_buffer++ = pallete[c2].blue;
269 unsigned char c1 = tbuffer[j] >> 4;
270 *wr_buffer++ = pallete[c1].red;
271 *wr_buffer++ = pallete[c1].green;
272 *wr_buffer++ = pallete[c1].blue;
275 read(fd, buff, skip);
276 wr_buffer -= (*x) * 6;
282 int skip = fill4B(*x);
283 fetch_pallete(fd, pallete, 256);
284 lseek(fd, raster, SEEK_SET);
285 unsigned char * tbuffer = new unsigned char[*x];
288 for (int i = 0; i < *y; i++)
290 read(fd, tbuffer, *x);
291 for (int j = 0; j < *x; j++)
293 wr_buffer[j * 3] = pallete[tbuffer[j]].red;
294 wr_buffer[j * 3 + 1] = pallete[tbuffer[j]].green;
295 wr_buffer[j * 3 + 2] = pallete[tbuffer[j]].blue;
298 read(fd, buff, skip);
299 wr_buffer -= (*x) * 3;
305 int skip = fill4B((*x) * 3);
306 lseek(fd, raster, SEEK_SET);
307 for (int i = 0; i < (*y); i++)
309 read(fd, wr_buffer, (*x) * 3);
310 for (int j = 0; j < (*x) * 3 ; j = j + 3)
312 unsigned char c = wr_buffer[j];
313 wr_buffer[j] = wr_buffer[j + 2];
314 wr_buffer[j + 2] = c;
317 read(fd, buff, skip);
318 wr_buffer -= (*x) * 3;
330 //---------------------------------------------------------------------------------------------
332 static int png_load(const char *filename, int *x, int *y)
334 static const png_color_16 my_background = {0, 0, 0, 0, 0};
338 png_uint_32 width, height;
340 int bit_depth, color_type, interlace_type;
341 int number_passes, pass;
345 if (!(fh = fopen(filename, "rb"))) return 0;
347 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
350 info_ptr = png_create_info_struct(png_ptr);
351 if (info_ptr == NULL)
353 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
358 if (setjmp(png_ptr->jmpbuf))
360 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
365 png_init_io(png_ptr, fh);
367 png_read_info(png_ptr, info_ptr);
368 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
370 if (color_type == PNG_COLOR_TYPE_PALETTE)
372 png_set_palette_to_rgb(png_ptr);
373 png_set_background(png_ptr, (png_color_16 *)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
376 if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
378 png_set_gray_to_rgb(png_ptr);
379 png_set_background(png_ptr, (png_color_16 *)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
382 if (color_type & PNG_COLOR_MASK_ALPHA)
383 png_set_strip_alpha(png_ptr);
385 if (bit_depth < 8) png_set_packing(png_ptr);
386 if (bit_depth == 16) png_set_strip_16(png_ptr);
388 number_passes = png_set_interlace_handling(png_ptr);
389 png_read_update_info(png_ptr, info_ptr);
391 if (width * 3 != png_get_rowbytes(png_ptr, info_ptr))
393 eDebug("[PNG] Error processing");
397 pic_buffer = new unsigned char[width * height * 3];
401 for(pass = 0; pass < number_passes; pass++)
403 fbptr = (png_byte *)pic_buffer;
404 for (i = 0; i < height; i++, fbptr += width * 3)
405 png_read_row(png_ptr, fbptr, NULL);
407 png_read_end(png_ptr, info_ptr);
408 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
413 //-------------------------------------------------------------------
415 inline void m_rend_gif_decodecolormap(unsigned char *cmb, unsigned char *rgbb, ColorMapObject *cm, int s, int l)
417 GifColorType *cmentry;
419 for (i = 0; i < l; i++)
421 cmentry = &cm->Colors[cmb[i]];
422 *(rgbb++) = cmentry->Red;
423 *(rgbb++) = cmentry->Green;
424 *(rgbb++) = cmentry->Blue;
428 static int gif_load(const char *filename, int *x, int *y)
430 int px, py, i, j, ibxs;
431 unsigned char *fbptr;
432 unsigned char *lb=NULL;
433 unsigned char *slb=NULL;
436 GifByteType *extension;
437 ColorMapObject *cmap;
441 gft = DGifOpenFileName(filename);
446 if (DGifGetRecordType(gft, &rt) == GIF_ERROR)
450 case IMAGE_DESC_RECORD_TYPE:
451 if (DGifGetImageDesc(gft) == GIF_ERROR)
453 *x = px = gft->Image.Width;
454 *y = py = gft->Image.Height;
455 pic_buffer = new unsigned char[px * py * 3];
456 lb = (unsigned char *)malloc(px * 3);
457 slb = (unsigned char *) malloc(px);
459 if (lb != NULL && slb != NULL)
461 cmap = (gft->Image.ColorMap ? gft->Image.ColorMap : gft->SColorMap);
462 cmaps = cmap->ColorCount;
466 if (!(gft->Image.Interlace))
468 for (i = 0; i < py; i++, fbptr += px * 3)
470 if (DGifGetLine(gft, slb, px) == GIF_ERROR)
472 m_rend_gif_decodecolormap(slb, lb, cmap, cmaps, px);
473 memcpy(fbptr, lb, px * 3);
478 for (j = 0; j < 4; j++)
481 for (i = 0; i < py; i++, fbptr += px * 3)
483 if (DGifGetLine(gft, slb, px) == GIF_ERROR)
485 m_rend_gif_decodecolormap(slb, lb, cmap, cmaps, px);
486 memcpy(fbptr, lb, px * 3);
502 case EXTENSION_RECORD_TYPE:
503 if (DGifGetExtension(gft, &extcode, &extension) == GIF_ERROR)
505 while (extension != NULL)
506 if (DGifGetExtensionNext(gft, &extension) == GIF_ERROR)
513 while (rt != TERMINATE_RECORD_TYPE);
518 eDebug("[GIF] Error");
525 //---------------------------------------------------------------------------------------------
527 PyObject *getExif(const char *filename)
531 if(exif.DecodeExif(filename))
533 if(exif.m_exifinfo->IsExif)
537 list = PyList_New(22);
538 PyList_SET_ITEM(list, pos++, PyString_FromString(exif.m_exifinfo->Version));
539 PyList_SET_ITEM(list, pos++, PyString_FromString(exif.m_exifinfo->CameraMake));
540 PyList_SET_ITEM(list, pos++, PyString_FromString(exif.m_exifinfo->CameraModel));
541 PyList_SET_ITEM(list, pos++, PyString_FromString(exif.m_exifinfo->DateTime));
542 PyList_SET_ITEM(list, pos++, PyString_FromString(exif.m_exifinfo->Comments));
543 PyList_SET_ITEM(list, pos++, PyString_FromFormat("%d x %d", exif.m_exifinfo->Width, exif.m_exifinfo->Height));
544 PyList_SET_ITEM(list, pos++, PyString_FromString(exif.m_exifinfo->Orientation));
545 PyList_SET_ITEM(list, pos++, PyString_FromString(exif.m_exifinfo->MeteringMode));
546 PyList_SET_ITEM(list, pos++, PyString_FromString(exif.m_exifinfo->ExposureProgram));
547 PyList_SET_ITEM(list, pos++, PyString_FromString(exif.m_exifinfo->LightSource));
548 PyList_SET_ITEM(list, pos++, PyString_FromString(exif.m_exifinfo->FlashUsed));
549 PyList_SET_ITEM(list, pos++, PyString_FromFormat("%d", exif.m_exifinfo->CompressionLevel));
550 PyList_SET_ITEM(list, pos++, PyString_FromFormat("%d", exif.m_exifinfo->ISOequivalent));
551 sprintf(tmp, "%.2f", exif.m_exifinfo->Xresolution);
552 PyList_SET_ITEM(list, pos++, PyString_FromString(tmp));
553 sprintf(tmp, "%.2f", exif.m_exifinfo->Yresolution);
554 PyList_SET_ITEM(list, pos++, PyString_FromString(tmp));
555 PyList_SET_ITEM(list, pos++, PyString_FromString(exif.m_exifinfo->ResolutionUnit));
556 sprintf(tmp, "%.2f", exif.m_exifinfo->Brightness);
557 PyList_SET_ITEM(list, pos++, PyString_FromString(tmp));
558 sprintf(tmp, "%.5f sec.", exif.m_exifinfo->ExposureTime);
559 PyList_SET_ITEM(list, pos++, PyString_FromString(tmp));
560 sprintf(tmp, "%.5f", exif.m_exifinfo->ExposureBias);
561 PyList_SET_ITEM(list, pos++, PyString_FromString(tmp));
562 sprintf(tmp, "%.5f", exif.m_exifinfo->Distance);
563 PyList_SET_ITEM(list, pos++, PyString_FromString(tmp));
564 sprintf(tmp, "%.5f", exif.m_exifinfo->CCDWidth);
565 PyList_SET_ITEM(list, pos++, PyString_FromString(tmp));
566 sprintf(tmp, "%.2f", exif.m_exifinfo->ApertureFNumber);
567 PyList_SET_ITEM(list, pos++, PyString_FromString(tmp));
571 list = PyList_New(1);
572 PyList_SET_ITEM(list, 0, PyString_FromString(exif.m_szLastError));
578 list = PyList_New(1);
579 PyList_SET_ITEM(list, 0, PyString_FromString(exif.m_szLastError));
582 return list ? (PyObject*)list : (PyObject*)PyList_New(0);
585 //---------------------------------------------------------------------------------------------
586 enum {F_NONE, F_PNG, F_JPEG, F_BMP, F_GIF};
588 static int pic_id(const char *name)
590 unsigned char id[10];
591 int fd = open(name, O_RDONLY);
597 if(id[1] == 'P' && id[2] == 'N' && id[3] == 'G')
599 else if(id[6] == 'J' && id[7] == 'F' && id[8] == 'I' && id[9] == 'F')
601 else if(id[0] == 0xff && id[1] == 0xd8 && id[2] == 0xff)
603 else if(id[0] == 'B' && id[1] == 'M' )
605 else if(id[0] == 'G' && id[1] == 'I' && id[2] == 'F')
610 int loadPic(ePtr<gPixmap> &result, std::string filename, int w, int h, int aspect, int resize_mode, int rotate, int background, std::string cachefile)
613 int ox=0, oy=0, imx, imy;
617 if(cachefile.length())
620 if(jpeg_load(cachefile.c_str(), &ox, &oy))
621 eDebug("[CACHEPIC] x-size=%d, y-size=%d", ox, oy);
626 switch(pic_id(filename.c_str()))
628 case F_PNG: png_load(filename.c_str(), &ox, &oy); break;
629 case F_JPEG: jpeg_load(filename.c_str(), &ox, &oy); break;
630 case F_BMP: bmp_load(filename.c_str(), &ox, &oy); break;
631 case F_GIF: gif_load(filename.c_str(), &ox, &oy); break;
633 eDebug("[PIC] <format not supportet>");
637 eDebug("[FULLPIC] x-size=%d, y-size=%d", ox, oy);
645 case 1: aspect_ratio = 1.777 / ((double)720/576); break; //16:9
646 case 2: aspect_ratio = 1.600 / ((double)720/576); break; //16:10
647 //case 3: aspect_ratio = 1.250 / ((double)720/576); break; //5:4
648 default: aspect_ratio = 1.333 / ((double)720/576); //4:3
651 if((aspect_ratio * oy * w / ox) <= h)
654 imy = (int)(aspect_ratio*oy*w/ox);
658 imx = (int)((1.0/aspect_ratio)*ox*h/oy);
662 if(resize_mode) pic_buffer = color_resize(pic_buffer, ox, oy, imx, imy);
663 else pic_buffer = simple_resize(pic_buffer, ox, oy, imx, imy);
670 jpeg_save(pic_buffer, cachefile.c_str(), 50, oy, ox);
671 eDebug("[SAVEPIC] x-size=%d, y-size=%d", ox, oy);
677 result=new gPixmap(eSize(w, h), 32);
678 gSurface *surface = result->surface;
681 int o_y=0, u_y=0, v_x=0, h_x=0;
682 unsigned char clear[4] = {0x00,0x00,0x00,0x00};
683 if(background) clear[3]=0xFF;
684 unsigned char *tmp_buffer = new unsigned char[4];
697 //eDebug("o_y=%d u_y=%d v_x=%d h_x=%d", o_y, u_y, v_x, h_x);
700 for(a=0; a<(o_y*ox)+1; a++, nc+=4)
702 memcpy(tmp_buffer, clear, sizeof(clear));
703 tmp_buffer=((unsigned char *)(surface->data)) + nc;
709 for(b=0; b<v_x; b++, nc+=4)
711 memcpy(tmp_buffer, clear, sizeof(clear));
712 tmp_buffer=((unsigned char *)(surface->data)) + nc;
715 for(b=0; b<(ox*3); b+=3, nc+=4)
718 tmp_buffer[2]=pic_buffer[oc++];
719 tmp_buffer[1]=pic_buffer[oc++];
720 tmp_buffer[0]=pic_buffer[oc++];
722 tmp_buffer=((unsigned char *)(surface->data)) + nc;
726 for(b=0; b<h_x; b++, nc+=4)
728 memcpy(tmp_buffer, clear, sizeof(clear));
729 tmp_buffer=((unsigned char *)(surface->data)) + nc;
734 for(a=0; a<(u_y*ox)+1; a++, nc+=4)
736 memcpy(tmp_buffer, clear, sizeof(clear));
737 tmp_buffer=((unsigned char *)(surface->data)) + nc;
740 //eDebug("[PIC] buffer=%d, nc=%d oc=%d ox=%d, oy=%d",w*h*4, nc, oc, ox, oy);
742 surface->clut.data=0;
743 surface->clut.colors=0;
744 surface->clut.start=0;
746 delete [] pic_buffer;