EAPI void evas_common_image_premul(Image_Entry *ie) { DATA32 nas = 0; if (!ie) return ; if (!evas_cache_image_pixels(ie)) return ; if (!ie->flags.alpha) return; nas = evas_common_convert_argb_premul(evas_cache_image_pixels(ie), ie->w * ie->h); if ((ALPHA_SPARSE_INV_FRACTION * nas) >= (ie->w * ie->h)) ie->flags.alpha_sparse = 1; }
static Eina_Bool evas_image_load_file_data_generic(Image_Entry *ie, const char *file, const char *key, int *error) { DATA32 *body; body = evas_cache_image_pixels(ie); if (!body) return _load(ie, file, key, error, EINA_TRUE); *error = EVAS_LOAD_ERROR_NONE; return EINA_TRUE; }
EAPI void evas_common_image_set_alpha_sparse(Image_Entry *ie) { DATA32 *s, *se; DATA32 nas = 0; if (!ie) return; if (!evas_cache_image_pixels(ie)) return ; if (!ie->flags.alpha) return; s = evas_cache_image_pixels(ie); se = s + (ie->w * ie->h); while (s < se) { DATA32 p = *s & 0xff000000; if (!p || (p == 0xff000000)) nas++; s++; } if ((ALPHA_SPARSE_INV_FRACTION * nas) >= (ie->w * ie->h)) ie->flags.alpha_sparse = 1; }
static void raster(TIFFRGBAImage_Extra * img, uint32 * rast, uint32 x, uint32 y, uint32 w, uint32 h) { int image_width, image_height; uint32 *pixel, pixel_value; int i, j, dy, rast_offset; DATA32 *buffer_pixel, *buffer = evas_cache_image_pixels(img->image); int alpha_premult = 0; image_width = img->image->w; image_height = img->image->h; dy = h > y ? -1 : y - h; /* rast seems to point to the beginning of the last strip processed */ /* so you need use negative offsets. Bizzare. Someone please check this */ /* I don't understand why, but that seems to be what's going on. */ /* libtiff needs better docs! */ if (img->rgba.alpha == EXTRASAMPLE_UNASSALPHA) alpha_premult = 1; for (i = y, rast_offset = 0; i > dy; i--, rast_offset--) { pixel = rast + (rast_offset * image_width); buffer_pixel = buffer + ((((image_height - 1) - i) * image_width) + x); for (j = 0; j < w; j++) { int a, r, g, b; pixel_value = (*(pixel++)); a = TIFFGetA(pixel_value); r = TIFFGetR(pixel_value); g = TIFFGetG(pixel_value); b = TIFFGetB(pixel_value); if (!alpha_premult && (a < 255)) { r = (r * (a + 1)) >> 8; g = (g * (a + 1)) >> 8; b = (b * (a + 1)) >> 8; } (*(buffer_pixel++)) = ARGB_JOIN(a, r, g, b); } }
Eina_Bool evas_image_load_file_data_eet(Image_Entry *ie, const char *file, const char *key, int *error) { unsigned int w, h; int alpha, compression, quality, lossy, ok; Eet_File *ef; DATA32 *body, *p, *end; DATA32 nas = 0; Eina_Bool res = EINA_FALSE; if (!key) { *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; return EINA_FALSE; } if (ie->flags.loaded) { *error = EVAS_LOAD_ERROR_NONE; return EINA_TRUE; } ef = eet_open(file, EET_FILE_MODE_READ); if (!ef) { *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; return EINA_FALSE; } ok = eet_data_image_header_read(ef, key, &w, &h, &alpha, &compression, &quality, &lossy); if (IMG_TOO_BIG(w, h)) { *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; goto on_error; } if (!ok) { *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; goto on_error; } evas_cache_image_surface_alloc(ie, w, h); ok = eet_data_image_read_to_surface(ef, key, 0, 0, evas_cache_image_pixels(ie), w, h, w * 4, &alpha, &compression, &quality, &lossy); if (!ok) { *error = EVAS_LOAD_ERROR_GENERIC; goto on_error; } if (alpha) { ie->flags.alpha = 1; body = evas_cache_image_pixels(ie); end = body +(w * h); for (p = body; p < end; p++) { DATA32 r, g, b, a; a = A_VAL(p); r = R_VAL(p); g = G_VAL(p); b = B_VAL(p); if ((a == 0) || (a == 255)) nas++; if (r > a) r = a; if (g > a) g = a; if (b > a) b = a; *p = ARGB_JOIN(a, r, g, b); } if ((ALPHA_SPARSE_INV_FRACTION * nas) >= (ie->w * ie->h)) ie->flags.alpha_sparse = 1; } // result is already premultiplied now if u compile with edje // evas_common_image_premul(im); *error = EVAS_LOAD_ERROR_NONE; res = EINA_TRUE; on_error: eet_close(ef); return res; }
static Eina_Bool _load(Image_Entry *ie, const char *file, const char *key, int *error, Eina_Bool get_data) { Eina_Bool res = EINA_FALSE; int w = 0, h = 0, alpha = 0; const char *dot1 = NULL, *dot2 = NULL, *end, *p; char *cmd = NULL, decoders[3][128], buf[4096]; char *loader = "/evas/utils/evas_image_loader"; char *img_loader = NULL; const char *libdir; // eg $libdir/evas/generic_loaders int cmd_len, len, decoders_num = 0, try_count = 0; int read_data = 0; char *tmpfname = NULL, *shmfname = NULL; DATA32 *body; FILE *f = NULL; libdir = _evas_module_libdir_get(); cmd_len = strlen(libdir); cmd_len += strlen(loader); img_loader = alloca(cmd_len + 1); strcpy(img_loader, libdir); strcat(img_loader, loader); // params excluding file, key and loadopts cmd_len += 1024; cmd_len += strlen(file) * 2; if (key) cmd_len += strlen(key) * 2; cmd = alloca(cmd_len + 1); len = strlen(file); if (len < 1) { *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; return EINA_FALSE; } end = file + len; for (p = end - 1; p >= file; p--) { if ((!dot1) && (*p == '.')) dot1 = p; else if ((!dot2) && (*p == '.')) dot2 = p; else if ((dot1) && (dot2)) break; } if (dot2) { // double extn not too long if (((end - dot2) <= 10) && (!illegal_char(dot2))) { strcpy(&(decoders[decoders_num][0]), img_loader); dotcat(&(decoders[decoders_num][0]), dot2); decoders_num++; } // single extn not too long if (((end - dot1) <= 5) && (!illegal_char(dot1))) { strcpy(&(decoders[decoders_num][0]), img_loader); dotcat(&(decoders[decoders_num][0]), dot1); decoders_num++; } strcpy(decoders[decoders_num], img_loader); decoders_num++; } else if (dot1) { // single extn not too long if (((end - dot1) <= 5) && (!illegal_char(dot1))) { strcpy(&(decoders[decoders_num][0]), img_loader); dotcat(&(decoders[decoders_num][0]), dot1); decoders_num++; } strcpy(decoders[decoders_num], img_loader); decoders_num++; } else { strcpy(decoders[decoders_num], img_loader); decoders_num++; } for (try_count = 0; try_count < decoders_num; try_count++) { // FIXME: strcats could be more efficient, not that it matters much // here as we are about to build a cmd to exec via a shell that // will interpret shell stuff and path hunt that will then exec the // program itself that will dynamically link that will again // parse the arguments and finally do something... if (access(decoders[try_count], X_OK)) continue; strcpy(cmd, decoders[try_count]); strcat(cmd, " "); // filename first arg len = strlen(cmd); escape_copy(file, cmd + len); if (!get_data) { strcat(cmd, " -head "); } if (key) { strcat(cmd, " -key "); len = strlen(cmd); escape_copy(key, cmd + len); } if (ie->load_opts.scale_down_by > 1) { strcat(cmd, " -opt-scale-down-by "); snprintf(buf, sizeof(buf), "%i", ie->load_opts.scale_down_by); strcat(cmd, buf); } if (ie->load_opts.dpi > 0.0) { strcat(cmd, " -opt-dpi "); snprintf(buf, sizeof(buf), "%i", (int)(ie->load_opts.dpi * 1000.0)); strcat(cmd, buf); } if ((ie->load_opts.w > 0) && (ie->load_opts.h > 0)) { strcat(cmd, " -opt-size "); snprintf(buf, sizeof(buf), "%i %i", ie->load_opts.w, ie->load_opts.h); strcat(cmd, buf); } f = popen(cmd, "r"); if (f) break; } if (!f) { *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; return EINA_FALSE; } while (fgets(buf, sizeof(buf), f)) { len = strlen(buf); if (len > 0) { if (buf[len - 1] == '\n') buf[len - 1] = 0; if (!strncmp(buf, "size ", 5)) { int tw = 0, th = 0; len = sscanf(buf, "%*s %i %i", &tw, &th); if (len == 2) { if ((tw > 0) && (th > 0)) { w = tw; h = th; } } } else if (!strncmp(buf, "alpha ", 6)) { int ta; len = sscanf(buf, "%*s %i", &ta); if (len == 1) { alpha = ta; } } else if (!strncmp(buf, "tmpfile ", 8)) { tmpfname = buf + 8; goto getdata; } #ifdef HAVE_SHM_OPEN else if (!strncmp(buf, "shmfile ", 8)) { shmfname = buf + 8; goto getdata; } #endif else if (!strncmp(buf, "data", 4)) { read_data = 1; goto getdata; } else if (!strncmp(buf, "done", 4)) { read_data = 2; goto getdata; } } } getdata: if ((!read_data) && (!tmpfname) && (!shmfname)) { *error = EVAS_LOAD_ERROR_CORRUPT_FILE; goto on_error; } if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) || IMG_TOO_BIG(w, h)) { *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; goto on_error; } body = evas_cache_image_pixels(ie); if (body) { if ((w != (int)ie->w) || (h != (int)ie->h)) { *error = EVAS_LOAD_ERROR_CORRUPT_FILE; goto on_error; } } if (alpha) ie->flags.alpha = 1; ie->w = w; ie->h = h; if (get_data) { if (!body) evas_cache_image_surface_alloc(ie, ie->w, ie->h); body = evas_cache_image_pixels(ie); if (!body) { *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; goto on_error; } if ((tmpfname) || (shmfname)) { int fd = -1; // open if (tmpfname) fd = open(tmpfname, O_RDONLY, S_IRUSR); #ifdef HAVE_SHM_OPEN else if (shmfname) fd = shm_open(shmfname, O_RDONLY, S_IRUSR); #endif if (fd >= 0) { void *addr; eina_mmap_safety_enabled_set(EINA_TRUE); // mmap addr = mmap(NULL, w * h * sizeof(DATA32), PROT_READ, MAP_SHARED, fd, 0); if (addr != MAP_FAILED) { memcpy(body, addr, w * h * sizeof(DATA32)); munmap(addr, w * h * sizeof(DATA32)); } // close if (tmpfname) { close(fd); unlink(tmpfname); } #ifdef HAVE_SHM_OPEN else if (shmfname) { close(fd); shm_unlink(shmfname); } #endif } else { *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; goto on_error; } } else if (read_data) { if (fread(body, w * h * sizeof(DATA32), 1, f) != 1) { *error = EVAS_LOAD_ERROR_CORRUPT_FILE; goto on_error; } } } res = EINA_TRUE; *error = EVAS_LOAD_ERROR_NONE; on_error: if (f) pclose(f); return res; }