int main(int argc, char **argv) { char *dot, *colon, *n, *oldn; Imlib_Image im; /* I'm just plain being lazy here.. get our basename. */ for (oldn = n = argv[0]; n; oldn = n) n = strchr(++oldn, '/'); if (argc < 3 || !strcmp(argv[1], "-h")) usage(-1); if (!(im = imlib_load_image(argv[1]))) { fprintf(stderr, PROG_NAME ": Error loading image: %s\n", argv[1]); exit(-1); } /* we only care what format the export format is. */ imlib_context_set_image(im); /* hopefully the last one will be the one we want.. */ dot = strrchr(argv[2], '.'); /* if there's a format, snarf it and set the format. */ if (dot && *(dot + 1)) { colon = strrchr(++dot, ':'); /* if a db file with a key, export it to a db. */ if (colon && *(colon + 1)) { *colon = 0; /* beats having to look for strcasecmp() */ if (!strncmp(dot, "db", 2) || !strncmp(dot, "dB", 2) || !strncmp(dot, "DB", 2) || !strncmp(dot, "Db", 2)) { imlib_image_set_format("db"); } *colon = ':'; } else { char *p, *q; /* max length of 8 for format name. seems reasonable. */ q = p = malloc(9); memset(p, 0, 8); strncpy(p, dot, (strlen(dot) < 9) ? strlen(dot) : 8); /* Imlib2 only recognizes lowercase formats. convert it. */ for (q[8] = 0; *q; q++) *q = tolower(*q); imlib_image_set_format(p); free(p); } dot--; } else imlib_image_set_format("jpg"); imlib_save_image(argv[2]); return 0; }
static void save_image(char *filename) { Imlib_Image img; int width = image.width; int height = image.height; DATA32 *data; char *suffix; if (filename == NULL) { return; } suffix = strrchr(filename, '.'); if (suffix) { data = (DATA32 *)image.pixels; img = imlib_create_image_using_data(width, height, data); if (img) { imlib_context_set_image(img); imlib_image_set_format(suffix + 1); imlib_save_image(filename); imlib_free_image(); } } else { fprintf(stderr, "wrong file name: %s\n", filename); exit(EXIT_FAILURE); } }
static inline void save2path( img_t *img, const char *path, ImlibLoadError *err ) { // set quality imlib_image_attach_data_value( "quality", NULL, img->quality, NULL ); imlib_image_set_format( img->format ); imlib_save_image_with_error_return( path, err ); imlib_free_image_and_decache(); }
/* save image to file */ void save_image(const char *image_type, Imlib_Image *image, const char *fmt, const char *filename, int flags) { const char *tmp; Imlib_Image *current_image; Imlib_Load_Error save_error=0; const char *const stdout_file = "/proc/self/fd/1"; current_image = imlib_context_get_image(); imlib_context_set_image(image); /* interpret - as STDOUT */ if(strcmp("-", filename) == 0) filename = stdout_file; /* get file format for image */ if(fmt) { /* use provided format string */ tmp = fmt; } else { /* use file name extension */ tmp = strrchr(filename, '.'); if(tmp) tmp++; } if(tmp) { if(flags & VERBOSE) fprintf(stderr, "using %s format for %s image\n", tmp, image_type); imlib_image_set_format(tmp); } else { /* use png as default */ if(flags & VERBOSE) fprintf(stderr, "using png format for %s image\n", image_type); imlib_image_set_format("png"); } /* write image to disk */ if(flags & VERBOSE) fprintf(stderr, "writing %s image to file %s\n", image_type, filename); imlib_save_image_with_error_return(filename, &save_error); if(save_error && save_error != IMLIB_LOAD_ERROR_NONE) { fprintf(stderr, "error saving image file %s\n", filename); report_imlib_error(save_error); } imlib_context_set_image(current_image); }
void gib_imlib_save_image_with_error_return(Imlib_Image im, char *file, Imlib_Load_Error * error_return) { char *tmp; imlib_context_set_image(im); tmp = strrchr(file, '.'); if (tmp) imlib_image_set_format(tmp + 1); imlib_save_image_with_error_return(file, error_return); }
/* * XXX gib_imlib_save_image_with_error_return breaks with *.END and * similar because it tries to set the image format, which only works * with .end . * So we leave that part out. */ void ungib_imlib_save_image_with_error_return(Imlib_Image im, char *file, Imlib_Load_Error * error_return) { char *tmp; imlib_context_set_image(im); tmp = strrchr(file, '.'); if (tmp) { char *p, *pp; p = gib_estrdup(tmp + 1); pp = p; while(*pp) { *pp = tolower(*pp); pp++; } imlib_image_set_format(p); gib_efree(p); } imlib_save_image_with_error_return(file, error_return); }
static inline PyObject * ImageObject_save(PyObject* self, PyObject *args) { char *filename, *ext; Imlib_Load_Error error = IMLIB_LOAD_ERROR_NONE; if (!PyArg_ParseTuple(args, "ss:save", &filename, &ext)){ return NULL; } imlib_context_set_image(((ImageObject *)self)->image); imlib_image_set_format(ext); imlib_save_image_with_error_return(filename, &error); CHECK_LOAD_ERROR(error); Py_RETURN_NONE; }
void gib_imlib_save_image(Imlib_Image im, char *file) { char *tmp; imlib_context_set_image(im); tmp = strrchr(file, '.'); if (tmp) { char *p, *pp; p = gib_estrdup(tmp + 1); pp = p; while(*pp) { *pp = tolower(*pp); pp++; } imlib_image_set_format(p); gib_efree(p); } imlib_save_image(file); }
/* main program */ int main(int argc, char **argv) { /* an image handle */ Imlib_Image image; /* if we provided < 2 arguments after the command - exit */ if (argc != 3) exit(1); /* load the image */ image = imlib_load_image(argv[1]); /* if the load was successful */ if (image) { char *tmp; /* set the image we loaded as the current context image to work on */ imlib_context_set_image(image); /* set the image format to be the format of the extension of our last */ /* argument - i.e. .png = png, .tif = tiff etc. */ tmp = strrchr(argv[2], '.'); if(tmp) imlib_image_set_format(tmp + 1); /* save the image */ imlib_save_image(argv[2]); } }
bool img_load_gif(img_t *img, const fileinfo_t *file) { GifFileType *gif; GifRowType *rows = NULL; GifRecordType rec; ColorMapObject *cmap; DATA32 bgpixel, *data, *ptr; DATA32 *prev_frame = NULL; Imlib_Image im; int i, j, bg, r, g, b; int x, y, w, h, sw, sh; int px, py, pw, ph; int intoffset[] = { 0, 4, 2, 1 }; int intjump[] = { 8, 8, 4, 2 }; int transp = -1; unsigned int disposal = 0, prev_disposal = 0; unsigned int delay = 0; bool err = false; if (img->multi.cap == 0) { img->multi.cap = 8; img->multi.frames = (img_frame_t*) s_malloc(sizeof(img_frame_t) * img->multi.cap); } img->multi.cnt = img->multi.sel = 0; img->multi.length = 0; #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 gif = DGifOpenFileName(file->path, NULL); #else gif = DGifOpenFileName(file->path); #endif if (gif == NULL) { warn("could not open gif file: %s", file->name); return false; } bg = gif->SBackGroundColor; sw = gif->SWidth; sh = gif->SHeight; px = py = pw = ph = 0; do { if (DGifGetRecordType(gif, &rec) == GIF_ERROR) { err = true; break; } if (rec == EXTENSION_RECORD_TYPE) { int ext_code; GifByteType *ext = NULL; DGifGetExtension(gif, &ext_code, &ext); while (ext) { if (ext_code == GRAPHICS_EXT_FUNC_CODE) { if (ext[1] & 1) transp = (int) ext[4]; else transp = -1; delay = 10 * ((unsigned int) ext[3] << 8 | (unsigned int) ext[2]); disposal = (unsigned int) ext[1] >> 2 & 0x7; } ext = NULL; DGifGetExtensionNext(gif, &ext); } } else if (rec == IMAGE_DESC_RECORD_TYPE) { if (DGifGetImageDesc(gif) == GIF_ERROR) { err = true; break; } x = gif->Image.Left; y = gif->Image.Top; w = gif->Image.Width; h = gif->Image.Height; rows = (GifRowType*) s_malloc(h * sizeof(GifRowType)); for (i = 0; i < h; i++) rows[i] = (GifRowType) s_malloc(w * sizeof(GifPixelType)); 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); } ptr = data = (DATA32*) s_malloc(sizeof(DATA32) * sw * sh); cmap = gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap; r = cmap->Colors[bg].Red; g = cmap->Colors[bg].Green; b = cmap->Colors[bg].Blue; bgpixel = 0x00ffffff & (r << 16 | g << 8 | b); for (i = 0; i < sh; i++) { for (j = 0; j < sw; j++) { if (i < y || i >= y + h || j < x || j >= x + w || rows[i-y][j-x] == transp) { if (prev_frame != NULL && (prev_disposal != 2 || i < py || i >= py + ph || j < px || j >= px + pw)) { *ptr = prev_frame[i * sw + j]; } else { *ptr = bgpixel; } } else { r = cmap->Colors[rows[i-y][j-x]].Red; g = cmap->Colors[rows[i-y][j-x]].Green; b = cmap->Colors[rows[i-y][j-x]].Blue; *ptr = 0xff << 24 | r << 16 | g << 8 | b; } ptr++; } } im = imlib_create_image_using_copied_data(sw, sh, data); for (i = 0; i < h; i++) free(rows[i]); free(rows); free(data); if (im == NULL) { err = true; break; } imlib_context_set_image(im); imlib_image_set_format("gif"); if (transp >= 0) imlib_image_set_has_alpha(1); if (disposal != 3) prev_frame = imlib_image_get_data_for_reading_only(); prev_disposal = disposal; px = x, py = y, pw = w, ph = h; if (img->multi.cnt == img->multi.cap) { img->multi.cap *= 2; img->multi.frames = (img_frame_t*) s_realloc(img->multi.frames, img->multi.cap * sizeof(img_frame_t)); } img->multi.frames[img->multi.cnt].im = im; img->multi.frames[img->multi.cnt].delay = delay > 0 ? delay : DEF_GIF_DELAY; img->multi.length += img->multi.frames[img->multi.cnt].delay; img->multi.cnt++; } } while (rec != TERMINATE_RECORD_TYPE);
ngx_int_t ngx_http_small_light_imlib2_process(ngx_http_request_t *r, ngx_http_small_light_ctx_t *ctx) { ngx_http_small_light_imlib2_ctx_t *ictx; ngx_http_small_light_image_size_t sz; Imlib_Image image_org, image_dst, image_tmp; Imlib_Load_Error err; ngx_file_info_t fi; ngx_fd_t fd; char *filename, *sharpen, *blur, *of, *buf; void *data; int w, h, radius, orientation; double iw, ih, q; ngx_int_t type; const char *ext; ssize_t size; ictx = (ngx_http_small_light_imlib2_ctx_t *)ctx->ictx; filename = (char *)ictx->tf->file.name.data; /* adjust image size */ ngx_http_small_light_calc_image_size(r, ctx, &sz, 10000.0, 10000.0); if (sz.jpeghint_flg != 0) { if (ngx_http_small_light_load_jpeg((void**)&data, &w, &h, r, filename, sz.dw, sz.dh) != NGX_OK) { image_org = imlib_load_image_immediately_without_cache(filename); if (image_org == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to load image %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } } else { image_org = imlib_create_image_using_data(w, h, data); } } else { image_org = imlib_load_image_immediately_without_cache(filename); if (image_org == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to load image %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } } /* rotate. */ if (sz.angle) { orientation = 0; switch (sz.angle) { case 90: orientation = 1; break; case 180: orientation = 2; break; case 270: orientation = 3; break; default: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "image not rotated. 'angle'(%d) must be 90 or 180 or 270. %s:%d", sz.angle, __FUNCTION__, __LINE__); break; } imlib_context_set_image(image_org); imlib_image_orientate(orientation); } /* calc size. */ imlib_context_set_image(image_org); iw = (double)imlib_image_get_width(); ih = (double)imlib_image_get_height(); ngx_http_small_light_calc_image_size(r, ctx, &sz, iw, ih); /* pass through. */ if (sz.pt_flg != 0) { ctx->of = ctx->inf; return NGX_OK; } /* crop, scale. */ if (sz.scale_flg != 0) { image_dst = imlib_create_cropped_scaled_image((int)sz.sx, (int)sz.sy, (int)sz.sw, (int)sz.sh, (int)sz.dw, (int)sz.dh); imlib_context_set_image(image_org); imlib_free_image(); } else { image_dst = image_org; } if (image_dst == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "imlib_create_cropped_scaled_image failed. %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } /* create canvas then draw image to the canvas. */ if (sz.cw > 0.0 && sz.ch > 0.0) { image_tmp = imlib_create_image(sz.cw, sz.ch); if (image_tmp == NULL) { imlib_context_set_image(image_dst); imlib_free_image(); return NGX_ERROR; } imlib_context_set_image(image_tmp); imlib_context_set_color(sz.cc.r, sz.cc.g, sz.cc.b, sz.cc.a); imlib_image_fill_rectangle(0, 0, sz.cw, sz.ch); imlib_blend_image_onto_image(image_dst, 255, 0, 0, (int)sz.dw, (int)sz.dh, (int)sz.dx, (int)sz.dy, (int)sz.dw, (int)sz.dh); imlib_context_set_image(image_dst); imlib_free_image(); image_dst = image_tmp; } /* effects. */ sharpen = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "sharpen"); if (sharpen) { radius = ngx_http_small_light_parse_int(sharpen); if (radius > 0) { imlib_context_set_image(image_dst); imlib_image_sharpen(radius); } } blur = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "blur"); if (blur) { radius = ngx_http_small_light_parse_int(blur); if (radius > 0) { imlib_context_set_image(image_dst); imlib_image_blur(radius); } } /* border. */ if (sz.bw > 0.0 || sz.bh > 0.0) { imlib_context_set_color(sz.bc.r, sz.bc.g, sz.bc.b, sz.bc.a); imlib_context_set_image(image_dst); if (sz.cw > 0.0 && sz.ch > 0.0) { imlib_image_fill_rectangle(0, 0, sz.cw, sz.bh); imlib_image_fill_rectangle(0, 0, sz.bw, sz.ch); imlib_image_fill_rectangle(0, sz.ch - sz.bh, sz.cw, sz.bh); imlib_image_fill_rectangle(sz.cw - sz.bw, 0, sz.bw, sz.ch); } else { imlib_image_fill_rectangle(0, 0, sz.dw, sz.bh); imlib_image_fill_rectangle(0, 0, sz.bw, sz.ch); imlib_image_fill_rectangle(0, sz.dh - sz.bh, sz.dw, sz.bh); imlib_image_fill_rectangle(sz.dw - sz.bw, 0, sz.bw, sz.dh); } } /* set params. */ imlib_context_set_image(image_dst); q = ngx_http_small_light_parse_double(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "q")); if (q > 0.0) { imlib_image_attach_data_value("quality", NULL, q, NULL); } of = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "of"); if (ngx_strlen(of) > 0) { type = ngx_http_small_light_type(of); if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_NONE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "of is invalid(%s) %s:%d", of, __FUNCTION__, __LINE__); of = (char *)ngx_http_small_light_image_exts[ictx->type - 1]; } else if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_WEBP) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "WebP is not supported %s:%d", __FUNCTION__, __LINE__); of = (char *)ngx_http_small_light_image_exts[ictx->type - 1]; } else { ictx->type = type; } imlib_image_set_format(of); ctx->of = ngx_http_small_light_image_types[ictx->type - 1]; } else { ext = ngx_http_small_light_image_exts[ictx->type - 1]; imlib_image_set_format(ext); ctx->of = ctx->inf; } /* save image. */ imlib_save_image_with_error_return(filename, &err); imlib_free_image(); /* check error. */ if (err != IMLIB_LOAD_ERROR_NONE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to imlib_save_error %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } if (ngx_file_info(filename, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to ngx_file_info %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } fd = ngx_open_file(filename, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to open fd %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to ngx_fd_info %s:%d", __FUNCTION__, __LINE__); ngx_close_file(fd); return NGX_ERROR; } buf = ngx_palloc(r->pool, ngx_file_size(&fi)); if (buf == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); ngx_close_file(fd); return NGX_ERROR; } size = ngx_read_fd(fd, buf, ngx_file_size(&fi)); if (size == -1) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to ngx_read_fd %s:%d", __FUNCTION__, __LINE__); ngx_close_file(fd); return NGX_ERROR; } if ((size_t)size > ctx->content_length) { ctx->content = ngx_palloc(r->pool, size); if (ctx->content == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); ngx_close_file(fd); return NGX_ERROR; } } ngx_memcpy(ctx->content, buf, size); ngx_close_file(fd); ctx->content_length = size; return NGX_OK; }
/* Originally based on, but in its current form merely inspired by Imlib2's * src/modules/loaders/loader_gif.c:load(), written by Carsten Haitzler. */ bool img_load_gif(img_t *img, const fileinfo_t *file) { GifFileType *gif; GifRowType *rows = NULL; GifRecordType rec; ColorMapObject *cmap; DATA32 bgpixel, *data, *ptr; DATA32 *prev_frame = NULL; Imlib_Image *im; int i, j, bg, r, g, b; int x, y, w, h, sw, sh; int intoffset[] = { 0, 4, 2, 1 }; int intjump[] = { 8, 8, 4, 2 }; int transp = -1; unsigned int delay = 0; bool err = false; if (img->multi.cap == 0) { img->multi.cap = 8; img->multi.frames = (img_frame_t*) s_malloc(sizeof(img_frame_t) * img->multi.cap); } img->multi.cnt = 0; img->multi.sel = 0; gif = DGifOpenFileName(file->path); if (gif == NULL) { warn("could not open gif file: %s", file->name); return false; } bg = gif->SBackGroundColor; sw = gif->SWidth; sh = gif->SHeight; do { if (DGifGetRecordType(gif, &rec) == GIF_ERROR) { err = true; break; } if (rec == EXTENSION_RECORD_TYPE) { int ext_code; GifByteType *ext = NULL; DGifGetExtension(gif, &ext_code, &ext); while (ext) { if (ext_code == 0xf9) { if (ext[1] & 1) transp = (int) ext[4]; else transp = -1; delay = 10 * ((unsigned int) ext[3] << 8 | (unsigned int) ext[2]); if (delay) delay = MAX(delay, MIN_GIF_DELAY); /* TODO: handle disposal method, section 23.c.iv of http://www.w3.org/Graphics/GIF/spec-gif89a.txt */ } ext = NULL; DGifGetExtensionNext(gif, &ext); } } else if (rec == IMAGE_DESC_RECORD_TYPE) { if (DGifGetImageDesc(gif) == GIF_ERROR) { err = true; break; } x = gif->Image.Left; y = gif->Image.Top; w = gif->Image.Width; h = gif->Image.Height; rows = (GifRowType*) s_malloc(h * sizeof(GifRowType)); for (i = 0; i < h; i++) rows[i] = (GifRowType) s_malloc(w * sizeof(GifPixelType)); 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); } ptr = data = (DATA32*) s_malloc(sizeof(DATA32) * sw * sh); cmap = gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap; r = cmap->Colors[bg].Red; g = cmap->Colors[bg].Green; b = cmap->Colors[bg].Blue; bgpixel = 0x00ffffff & (r << 16 | g << 8 | b); for (i = 0; i < sh; i++) { for (j = 0; j < sw; j++) { if (i < y || i >= y + h || j < x || j >= x + w || rows[i-y][j-x] == transp) { if (prev_frame != NULL) *ptr = prev_frame[i * sw + j]; else *ptr = bgpixel; } else { r = cmap->Colors[rows[i-y][j-x]].Red; g = cmap->Colors[rows[i-y][j-x]].Green; b = cmap->Colors[rows[i-y][j-x]].Blue; *ptr = 0xff << 24 | r << 16 | g << 8 | b; } ptr++; } } im = imlib_create_image_using_copied_data(sw, sh, data); for (i = 0; i < h; i++) free(rows[i]); free(rows); free(data); if (im == NULL) { err = true; break; } imlib_context_set_image(im); prev_frame = imlib_image_get_data_for_reading_only(); imlib_image_set_format("gif"); if (transp >= 0) imlib_image_set_has_alpha(1); if (img->multi.cnt == img->multi.cap) { img->multi.cap *= 2; img->multi.frames = (img_frame_t*) s_realloc(img->multi.frames, img->multi.cap * sizeof(img_frame_t)); } img->multi.frames[img->multi.cnt].im = im; img->multi.frames[img->multi.cnt].delay = delay ? delay : GIF_DELAY; img->multi.cnt++; } } while (rec != TERMINATE_RECORD_TYPE); DGifCloseFile(gif); if (err && !file->loaded) warn("corrupted gif file: %s", file->name); if (img->multi.cnt > 1) { imlib_context_set_image(img->im); imlib_free_image(); img->im = img->multi.frames[0].im; img->multi.animate = GIF_AUTOPLAY; } else if (img->multi.cnt == 1) { imlib_context_set_image(img->multi.frames[0].im); imlib_free_image(); img->multi.cnt = 0; img->multi.animate = false; } imlib_context_set_image(img->im); return !err; }