#include "picload.h" #include "picexif.h" #include #include #include #include #include extern "C" { #include //#include "transupp.h" } #include unsigned char *pic_buffer=NULL; 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]; if (cr == NULL) { printf("[RESIZE] Error: malloc\n"); return(orgin); } l = cr; for (j = 0; j < dy; j++,l += dx * 3) { p = orgin + (j * oy / dy * ox * 3); for (i = 0, k = 0; i < dx; i++, k += 3) { ip = i * ox / dx * 3; l[k] = p[ip]; l[k+1] = p[ip + 1]; l[k+2] = p[ip + 2]; } } delete [] orgin; return(cr); } static unsigned char *color_resize(unsigned char * orgin, int ox, int oy, int dx, int dy) { 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]; if (cr == NULL) { printf("[RESIZE] Error: malloc\n"); return(orgin); } p = cr; for (j = 0; j < dy; j++) { for (i = 0; i < dx; i++, p += 3) { xa = i * ox / dx; ya = j * oy / dy; xb = (i + 1) * ox / dx; if (xb >= ox) xb = ox - 1; 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++) { q = orgin + ((l * ox + xa) * 3); for (k = xa; k <= xb; k++, q += 3, sq++) { r += q[0]; g += q[1]; b += q[2]; } } 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; } 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 #define BMP_SIZE_OFFSET 18 #define BMP_BPP_OFFSET 28 #define BMP_RLE_OFFSET 30 #define BMP_COLOR_OFFSET 54 #define fill4B(a) ((4 - ((a) % 4 )) & 0x03) static int bmp_load(const char *filename, int *x, int *y) { unsigned char buff[4]; int fd = open(filename, O_RDONLY); if (fd == -1) return 0; if (lseek(fd, BMP_SIZE_OFFSET, SEEK_SET) == -1) return 0; 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; 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; 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 24: { int skip = fill4B((*x) * 3); lseek(fd, raster, SEEK_SET); unsigned char c; 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]; wr_buffer[j] = wr_buffer[j + 2]; wr_buffer[j + 2] = c; } if (skip) read(fd, buff, skip); wr_buffer -= (*x) * 3; } break; } default: return 0; } close(fd); return 1; } //--------------------------------------------------------------------------------------------- static int png_load(const char *filename, int *x, int *y) { 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; unsigned int i; int bit_depth, color_type, interlace_type; int number_passes, pass; png_byte * fbptr; FILE * fh; if (!(fh = fopen(filename, "rb"))) return 0; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) return 0; 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; } if (setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); return 0; } png_init_io(png_ptr, fh); 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_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)) { eDebug("[PNG] Error processing"); return 0; } pic_buffer = new unsigned char[width * height * 3]; *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) png_read_row(png_ptr, fbptr, NULL); } png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); return 1; } //--------------------------------------------------------------------------------------------- PyObject *getExif(const char *filename) { PyObject *list = PyList_New(0); Cexif *m_exif = new Cexif(); if(m_exif->DecodeExif(filename)) { if(m_exif->m_exifinfo->IsExif) { char tmp[256]; PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->Version)); PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->CameraMake)); PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->CameraModel)); PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->DateTime)); PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->Comments)); PyList_Append(list, PyString_FromFormat("%d x %d", m_exif->m_exifinfo->Width, m_exif->m_exifinfo->Height)); PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->Orientation)); PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->MeteringMode)); PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->ExposureProgram)); PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->LightSource)); PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->FlashUsed)); PyList_Append(list, PyString_FromFormat("%d", m_exif->m_exifinfo->CompressionLevel)); PyList_Append(list, PyString_FromFormat("%d", m_exif->m_exifinfo->ISOequivalent)); sprintf(tmp, "%.2f", m_exif->m_exifinfo->Xresolution); PyList_Append(list, PyString_FromString(tmp)); sprintf(tmp, "%.2f", m_exif->m_exifinfo->Yresolution); PyList_Append(list, PyString_FromString(tmp)); PyList_Append(list, PyString_FromString(m_exif->m_exifinfo->ResolutionUnit)); sprintf(tmp, "%.2f", m_exif->m_exifinfo->Brightness); PyList_Append(list, PyString_FromString(tmp)); sprintf(tmp, "%.5f sec.", m_exif->m_exifinfo->ExposureTime); PyList_Append(list, PyString_FromString(tmp)); sprintf(tmp, "%.5f", m_exif->m_exifinfo->ExposureBias); PyList_Append(list, PyString_FromString(tmp)); sprintf(tmp, "%.5f", m_exif->m_exifinfo->Distance); PyList_Append(list, PyString_FromString(tmp)); sprintf(tmp, "%.5f", m_exif->m_exifinfo->CCDWidth); PyList_Append(list, PyString_FromString(tmp)); sprintf(tmp, "%.2f", m_exif->m_exifinfo->ApertureFNumber); PyList_Append(list, PyString_FromString(tmp)); } else PyList_Append(list, PyString_FromString(m_exif->m_szLastError)); m_exif->ClearExif(); } else PyList_Append(list, PyString_FromString(m_exif->m_szLastError)); delete m_exif; return list; } //--------------------------------------------------------------------------------------------- int loadPic(ePtr &result, std::string filename, int w, int h, int aspect, int resize_mode, int rotate, int background, std::string cachefile) { result = 0; int ox=0, oy=0, imx, imy; pic_buffer=NULL; bool cache=false; if(cachefile.length()) { cache = true; if(jpeg_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 { 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 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 } if((aspect_ratio * oy * w / ox) <= h) { imx = w; imy = (int)(aspect_ratio*oy*w/ox); } else { imx = (int)((1.0/aspect_ratio)*ox*h/oy); imy = h; } if(resize_mode) pic_buffer = color_resize(pic_buffer, ox, oy, imx, imy); else pic_buffer = simple_resize(pic_buffer, ox, oy, imx, imy); ox = imx; oy = imy; if(cache) { jpeg_save(pic_buffer, cachefile.c_str(), 50, oy, ox); eDebug("[SAVEPIC] x-size=%d, y-size=%d", ox, oy); } } result=new gPixmap(eSize(w, h), 32); gSurface *surface = result->surface; int a=0, b=0; int nc=0, oc=0; int o_y=0, u_y=0, v_x=0, h_x=0; unsigned char clear[4] = {0x00,0x00,0x00,0x00}; if(background) clear[3]=0xFF; unsigned char *tmp_buffer = new unsigned char[4]; if(oy < h) { o_y=(h-oy)/2; u_y=h-oy-o_y; } if(ox < w) { v_x=(w-ox)/2; h_x=w-ox-v_x; } //eDebug("o_y=%d u_y=%d v_x=%d h_x=%d", o_y, u_y, v_x, h_x); if(oy < h) for(a=0; a<(o_y*ox)+1; a++, nc+=4) { memcpy(tmp_buffer, clear, sizeof(clear)); tmp_buffer=((unsigned char *)(surface->data)) + nc; } for(a=0; adata)) + nc; } for(b=0; b<(ox*3); b+=3, nc+=4) { tmp_buffer[3]=0xFF; tmp_buffer[2]=pic_buffer[oc++]; tmp_buffer[1]=pic_buffer[oc++]; tmp_buffer[0]=pic_buffer[oc++]; tmp_buffer=((unsigned char *)(surface->data)) + nc; } if(ox < w) for(b=0; bdata)) + nc; } } if(oy < h) for(a=0; a<(u_y*ox)+1; a++, nc+=4) { memcpy(tmp_buffer, clear, sizeof(clear)); tmp_buffer=((unsigned char *)(surface->data)) + nc; } //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; return 0; }