char load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity, char immediate_load) { uint8_t *data; size_t size; int w,h; int has_alpha; #if (WEBP_DECODER_ABI_VERSION >= 0x200) WebPBitstreamFeatures features; #endif char ret = 0; if(im->data) return 0; if(!(data = read_file(im->real_file, &size, progress))) return 0; #if (WEBP_DECODER_ABI_VERSION >= 0x200) if(WebPGetFeatures(data, size, &features) != VP8_STATUS_OK) goto EXIT; w = features.width; h = features.height; has_alpha = features.has_alpha; #else /* compatibility with versions <= 0.1.3 */ if (!WebPGetInfo(data, size, &w, &h)) goto EXIT; has_alpha = 0; #endif if(!im->loader && !im->data) { im->w = w; im->h = h; if(!IMAGE_DIMENSIONS_OK(w, h)) goto EXIT; if(!has_alpha) UNSET_FLAGS(im->flags, F_HAS_ALPHA); else SET_FLAGS(im->flags, F_HAS_ALPHA); im->format = strdup("webp"); } if((!im->data && im->loader) || immediate_load || progress) im->data = (DATA32*)WebPDecodeBGRA(data, size, &w, &h); if(progress) progress(im, 100, 0, 0, 0, 0); ret = 1; EXIT: free(data); return ret; }
char load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity, char immediate_load) { int w = 0, h = 0, alpha = 0; FILE *f; if (im->data) return 0; f = fopen(im->real_file, "rb"); if (!f) return 0; /* header */ { char buf[256], buf2[256]; buf[0] = '\0'; if (!fgets(buf, 255, f)) { fclose(f); return 0; } buf2[0] = '\0'; sscanf(buf, "%s %i %i %i", buf2, &w, &h, &alpha); if (strcmp(buf2, "ARGB")) { fclose(f); return 0; } if (!IMAGE_DIMENSIONS_OK(w, h)) { fclose(f); return 0; } im->w = w; im->h = h; if (!im->format) { if (alpha) SET_FLAG(im->flags, F_HAS_ALPHA); else UNSET_FLAG(im->flags, F_HAS_ALPHA); im->format = strdup("argb"); } } if (((!im->data) && (im->loader)) || (immediate_load) || (progress)) { DATA32 *ptr; int y, pl = 0; char pper = 0; /* must set the im->data member before callign progress function */ ptr = im->data = malloc(w * h * sizeof(DATA32)); if (!im->data) { fclose(f); return 0; } for (y = 0; y < h; y++) { #ifdef WORDS_BIGENDIAN { int x; if (fread(ptr, im->w, 4, f) != 4) { free(ptr); fclose(f); return 0; } for (x = 0; x < im->w; x++) SWAP32(ptr[x]); } #else if (fread(ptr, im->w, 4, f) != 4) { free(ptr); fclose(f); return 0; } #endif ptr += im->w; if (progress) { char per; int l; per = (char)((100 * y) / im->h); if (((per - pper) >= progress_granularity) || (y == (im->h - 1))) { l = y - pl; if (!progress(im, per, 0, (y - l), im->w, l)) { fclose(f); return 2; } pper = per; pl = y; } } } } fclose(f); return 1; }
/* The load_jpeg function is based on Imlib2 loader. */ ngx_int_t ngx_http_small_light_load_jpeg( void **dest_data, int *width, int *height, const ngx_http_request_t *r, const char *filename, int hint_w, int hint_h) { int w, h; struct jpeg_decompress_struct cinfo; struct ImLib_JPEG_error_mgr jerr; FILE *f; ngx_int_t fd; int denom; DATA8 *ptr, *line[16], *data; DATA32 *ptr2, *dest; int x, y, l, i, scans; *dest_data = NULL; *width = *height = 0; fd = ngx_open_file(filename, NGX_FILE_RDONLY, NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS); if (fd == NGX_INVALID_FILE) { return NGX_ERROR; } f = fdopen(fd, "rb"); cinfo.err = jpeg_std_error(&(jerr.pub)); jerr.pub.error_exit = _JPEGFatalErrorHandler; jerr.pub.emit_message = _JPEGErrorHandler2; jerr.pub.output_message = _JPEGErrorHandler; if (sigsetjmp(jerr.setjmp_buffer, 1)) { jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); return NGX_ERROR; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, f); jpeg_read_header(&cinfo, TRUE); cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; jpeg_start_decompress(&cinfo); w = cinfo.output_width; h = cinfo.output_height; denom = w / hint_w; if (denom > h / hint_h) { denom = h / hint_h; } denom = denom >= 1 ? denom : 1; denom = denom <= 8 ? denom : 8; jpeg_destroy_decompress(&cinfo); fseek(f, 0, SEEK_SET); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, f); jpeg_read_header(&cinfo, TRUE); cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; cinfo.scale_denom = denom; jpeg_start_decompress(&cinfo); w = cinfo.output_width; h = cinfo.output_height; if ((cinfo.rec_outbuf_height > 16) || (cinfo.output_components <= 0) || !IMAGE_DIMENSIONS_OK(w, h)) { jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); return NGX_ERROR; } data = ngx_palloc(r->pool, w * 16 * cinfo.output_components); if (!data) { jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); return NGX_ERROR; } /* must set the im->data member before callign progress function */ ptr2 = dest = ngx_palloc(r->pool, w * h * sizeof(DATA32)); if (!dest) { jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); return NGX_ERROR; } if (cinfo.output_components > 1) { for (i = 0; i < cinfo.rec_outbuf_height; i++) { line[i] = data + (i * w * cinfo.output_components); } for (l = 0; l < h; l += cinfo.rec_outbuf_height) { jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); scans = cinfo.rec_outbuf_height; if ((h - l) < scans) { scans = h - l; } ptr = data; for (y = 0; y < scans; y++) { for (x = 0; x < w; x++) { *ptr2 = (0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]); ptr += cinfo.output_components; ptr2++; } } } } else if (cinfo.output_components == 1) { for (i = 0; i < cinfo.rec_outbuf_height; i++) { line[i] = data + (i * w); } for (l = 0; l < h; l += cinfo.rec_outbuf_height) { jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); scans = cinfo.rec_outbuf_height; if ((h - l) < scans) { scans = h - l; } ptr = data; for (y = 0; y < scans; y++) { for (x = 0; x < w; x++) { *ptr2 = (0xff000000) | ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]); ptr++; ptr2++; } } } } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); *dest_data = dest; *width = w; *height = h; return NGX_OK; }
/* \brief import TGA images */ int _glhckImportTGA(const char *file, _glhckImportImageStruct *import) { FILE *f; void *seg = NULL, *data; int bpp, vinverted = 0; int rle = 0, footer_present = 0; size_t datasize, size; unsigned short i, w, h; tga_header *header; tga_footer *footer; unsigned char *bufptr, *bufend, *importData = NULL; CALL(0, "%s, %p", file, import); if (!(f = fopen(file, "rb"))) goto read_fail; fseek(f, 0L, SEEK_END); if ((size = ftell(f)) < sizeof(tga_header) + sizeof(tga_footer)) goto not_possible; if (!(seg = _glhckMalloc(size))) goto out_of_memory; fseek(f, 0L, SEEK_SET); if (fread(seg, 1, size, f) != size) goto fail; /* we don't need the file anymore */ NULLDO(fclose, f); data = seg; header = (tga_header*)data; footer = (tga_footer*)((char*)data+size-sizeof(tga_footer)); /* is TGA v2.0? (stop storing the headers at EOF please) */ if (!memcmp(footer->signature, TGA_SIGNATURE, sizeof(footer->signature))) footer_present = 1; /* skip over header */ data = (char*)data+sizeof(tga_header); /* skip over ID filed */ if (header->idLength) data = (char*)data+header->idLength; /* inverted TGA? */ vinverted = !(header->descriptor & TGA_DESC_VERTICAL); switch (header->imageType) { case TGA_TYPE_COLOR_RLE: case TGA_TYPE_GRAY_RLE: rle = 1; break; case TGA_TYPE_COLOR: case TGA_TYPE_GRAY: rle = 0; break; default: goto unknown_type; } bpp = header->bpp; if (!((bpp == 32) || (bpp == 24) || (bpp == 8))) goto invalid_bpp; /* endian safe for 16-bit dimensions */ w = (header->widthHi << 8) | header->widthLo; h = (header->heightHi << 8) | header->heightLo; if (!IMAGE_DIMENSIONS_OK(w, h)) goto bad_dimensions; /* allocate destination buffer */ if (!(importData = _glhckMalloc(w*h*4))) goto out_of_memory; /* find out how much data to be read from file * (this is NOT simply width*height*4, due to compression) */ datasize = size - sizeof(tga_header) - header->idLength - (footer_present ? sizeof(tga_footer) : 0); /* bufptr is the next byte to be read from the buffer */ bufptr = data; bufend = data + datasize; /* non RLE compressed data */ if (!rle) { for (i = 0; i < h*w && bufptr+bpp/8 <= bufend; ++i) { switch (bpp) { /* 32-bit BGRA */ case 32: importData[i*4+0] = bufptr[2]; importData[i*4+1] = bufptr[1]; importData[i*4+2] = bufptr[0]; importData[i*4+3] = bufptr[3]; bufptr += 4; break; /* 24-bit BGR */ case 24: importData[i*4+0] = bufptr[2]; importData[i*4+1] = bufptr[1]; importData[i*4+2] = bufptr[0]; importData[i*4+3] = 255; bufptr += 3; break; /* 8-bit grayscale */ case 8: importData[i*4+0] = bufptr[0]; importData[i*4+1] = bufptr[0]; importData[i*4+2] = bufptr[0]; importData[i*4+3] = 255; bufptr += 1; break; } } } /* RLE compressed data */ if (rle) { DEBUG(GLHCK_DBG_ERROR, "RLE compressed import not yet implemented."); goto fail; } /* some TGA's are upside-down */ if (vinverted) _glhckInvertPixels(importData, w, h, 4); /* free */ NULLDO(_glhckFree, seg); /* fill import struct */ import->width = w; import->height = h; import->data = importData; import->format = GLHCK_RGBA; import->type = GLHCK_UNSIGNED_BYTE; import->flags |= (bpp==32?GLHCK_TEXTURE_IMPORT_ALPHA:0); RET(0, "%d", RETURN_OK); return RETURN_OK; read_fail: DEBUG(GLHCK_DBG_ERROR, "Failed to open: %s", file); goto fail; not_possible: DEBUG(GLHCK_DBG_ERROR, "Assumed TGA file '%s' has too small filesize", file); goto fail; out_of_memory: DEBUG(GLHCK_DBG_ERROR, "Out of memory, won't load file: %s", file); goto fail; unknown_type: DEBUG(GLHCK_DBG_ERROR, "Unknown TGA image type"); goto fail; invalid_bpp: DEBUG(GLHCK_DBG_ERROR, "TGA image is not either 32, 24 or 8 bpp"); goto fail; bad_dimensions: DEBUG(GLHCK_DBG_ERROR, "TGA image has invalid dimension %dx%d", w, h); fail: IFDO(fclose, f); IFDO(_glhckFree, importData); IFDO(_glhckFree, seg); RET(0, "%d", RETURN_FAIL); return RETURN_FAIL; }
char load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity, char immediate_load) { DATA32 *ptr; GifFileType *gif; GifRowType *rows; GifRecordType rec; ColorMapObject *cmap; int i, j, done, bg, r, g, b, w = 0, h = 0; float per = 0.0, per_inc; int last_per = 0, last_y = 0; int intoffset[] = { 0, 4, 2, 1 }; int intjump[] = { 8, 8, 4, 2 }; int transp; int fd; done = 0; rows = NULL; transp = -1; /* if immediate_load is 1, then dont delay image laoding as below, or */ /* already data in this image - dont load it again */ if (im->data) return 0; #ifndef __EMX__ fd = open(im->real_file, O_RDONLY); #else fd = open(im->real_file, O_RDONLY | O_BINARY); #endif if (fd < 0) return 0; gif = DGifOpenFileHandle(fd); if (!gif) { close(fd); return 0; } do { if (DGifGetRecordType(gif, &rec) == GIF_ERROR) { /* PrintGifError(); */ rec = TERMINATE_RECORD_TYPE; } if ((rec == IMAGE_DESC_RECORD_TYPE) && (!done)) { if (DGifGetImageDesc(gif) == GIF_ERROR) { /* PrintGifError(); */ rec = TERMINATE_RECORD_TYPE; } w = gif->Image.Width; h = gif->Image.Height; if (!IMAGE_DIMENSIONS_OK(w, h)) { DGifCloseFile(gif); return 0; } rows = malloc(h * sizeof(GifRowType *)); if (!rows) { DGifCloseFile(gif); return 0; } for (i = 0; i < h; i++) { rows[i] = NULL; } for (i = 0; i < h; i++) { rows[i] = malloc(w * sizeof(GifPixelType)); if (!rows[i]) { DGifCloseFile(gif); for (i = 0; i < h; i++) { if (rows[i]) { free(rows[i]); } } free(rows); return 0; } } if (gif->Image.Interlace) { for (i = 0; i < 4; i++) { for (j = intoffset[i]; j < h; j += intjump[i]) { DGifGetLine(gif, rows[j], w); } } } else { for (i = 0; i < h; i++) { DGifGetLine(gif, rows[i], w); } } done = 1; } else if (rec == EXTENSION_RECORD_TYPE) { int ext_code; GifByteType *ext; ext = NULL; DGifGetExtension(gif, &ext_code, &ext); while (ext) { if ((ext_code == 0xf9) && (ext[1] & 1) && (transp < 0)) { transp = (int)ext[4]; } ext = NULL; DGifGetExtensionNext(gif, &ext); } } } while (rec != TERMINATE_RECORD_TYPE); if (transp >= 0) { SET_FLAG(im->flags, F_HAS_ALPHA); } else { UNSET_FLAG(im->flags, F_HAS_ALPHA); } /* set the format string member to the lower-case full extension */ /* name for the format - so example names would be: */ /* "png", "jpeg", "tiff", "ppm", "pgm", "pbm", "gif", "xpm" ... */ im->w = w; im->h = h; if (!im->format) im->format = strdup("gif"); if (im->loader || immediate_load || progress) { bg = gif->SBackGroundColor; cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap); im->data = (DATA32 *) malloc(sizeof(DATA32) * w * h); if (!im->data) { DGifCloseFile(gif); free(rows); return 0; } ptr = im->data; per_inc = 100.0 / (((float)w) * h); for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { if (rows[i][j] == transp) { r = cmap->Colors[bg].Red; g = cmap->Colors[bg].Green; b = cmap->Colors[bg].Blue; *ptr++ = 0x00ffffff & ((r << 16) | (g << 8) | b); } else { r = cmap->Colors[rows[i][j]].Red; g = cmap->Colors[rows[i][j]].Green; b = cmap->Colors[rows[i][j]].Blue; *ptr++ = (0xff << 24) | (r << 16) | (g << 8) | b; } per += per_inc; if (progress && (((int)per) != last_per) && (((int)per) % progress_granularity == 0)) { last_per = (int)per; if (!(progress(im, (int)per, 0, last_y, w, i))) { DGifCloseFile(gif); for (i = 0; i < h; i++) { free(rows[i]); } free(rows); return 2; } last_y = i; } } } } if (progress) { progress(im, 100, 0, last_y, w, h); } DGifCloseFile(gif); for (i = 0; i < h; i++) { free(rows[i]); } free(rows); return 1; }