static ngx_buf_t * ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) { int sx, sy, dx, dy, ox, oy, ax, ay, size, colors, palette, transparent, sharpen, red, green, blue, t, offset_x, offset_y; u_char *out; ngx_buf_t *b; ngx_uint_t resize; gdImagePtr src, dst; ngx_pool_cleanup_t *cln; ngx_http_image_filter_conf_t *conf; src = ngx_http_image_source(r, ctx); if (src == NULL) { return NULL; } sx = gdImageSX(src); sy = gdImageSY(src); conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); if (!ctx->force && ctx->angle == 0 && (ngx_uint_t) sx <= ctx->max_width && (ngx_uint_t) sy <= ctx->max_height) { gdImageDestroy(src); return ngx_http_image_asis(r, ctx); } colors = gdImageColorsTotal(src); if (colors && conf->transparency) { transparent = gdImageGetTransparent(src); if (transparent != -1) { palette = colors; red = gdImageRed(src, transparent); green = gdImageGreen(src, transparent); blue = gdImageBlue(src, transparent); goto transparent; } } palette = 0; transparent = -1; red = 0; green = 0; blue = 0; transparent: gdImageColorTransparent(src, -1); dx = sx; dy = sy; if (conf->filter == NGX_HTTP_IMAGE_RESIZE) { if ((ngx_uint_t) dx > ctx->max_width) { dy = dy * ctx->max_width / dx; dy = dy ? dy : 1; dx = ctx->max_width; } if ((ngx_uint_t) dy > ctx->max_height) { dx = dx * ctx->max_height / dy; dx = dx ? dx : 1; dy = ctx->max_height; } resize = 1; } else if (conf->filter == NGX_HTTP_IMAGE_ROTATE) { resize = 0; } else { /* NGX_HTTP_IMAGE_CROP */ resize = 0; if ((double) dx / dy < (double) ctx->max_width / ctx->max_height) { if ((ngx_uint_t) dx > ctx->max_width) { dy = dy * ctx->max_width / dx; dy = dy ? dy : 1; dx = ctx->max_width; resize = 1; } } else { if ((ngx_uint_t) dy > ctx->max_height) { dx = dx * ctx->max_height / dy; dx = dx ? dx : 1; dy = ctx->max_height; resize = 1; } } } if (resize) { dst = ngx_http_image_new(r, dx, dy, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } if (colors == 0) { gdImageSaveAlpha(dst, 1); gdImageAlphaBlending(dst, 0); } gdImageCopyResampled(dst, src, 0, 0, 0, 0, dx, dy, sx, sy); if (colors) { gdImageTrueColorToPalette(dst, 1, 256); } gdImageDestroy(src); } else { dst = src; } if (ctx->angle) { src = dst; ax = (dx % 2 == 0) ? 1 : 0; ay = (dy % 2 == 0) ? 1 : 0; switch (ctx->angle) { case 90: case 270: dst = ngx_http_image_new(r, dy, dx, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } if (ctx->angle == 90) { ox = dy / 2 + ay; oy = dx / 2 - ax; } else { ox = dy / 2 - ay; oy = dx / 2 + ax; } gdImageCopyRotated(dst, src, ox, oy, 0, 0, dx + ax, dy + ay, ctx->angle); gdImageDestroy(src); t = dx; dx = dy; dy = t; break; case 180: dst = ngx_http_image_new(r, dx, dy, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } gdImageCopyRotated(dst, src, dx / 2 - ax, dy / 2 - ay, 0, 0, dx + ax, dy + ay, ctx->angle); gdImageDestroy(src); break; } } if (conf->filter == NGX_HTTP_IMAGE_CROP) { src = dst; if ((ngx_uint_t) dx > ctx->max_width) { ox = dx - ctx->max_width; } else { ox = 0; } if ((ngx_uint_t) dy > ctx->max_height) { oy = dy - ctx->max_height; } else { oy = 0; } if (ox || oy) { dst = ngx_http_image_new(r, dx - ox, dy - oy, colors); if (dst == NULL) { gdImageDestroy(src); return NULL; } offset_x = ngx_http_image_filter_get_value(r, conf->oxcv, conf->offset_x); offset_y = ngx_http_image_filter_get_value(r, conf->oycv, conf->offset_y); if (offset_x == NGX_HTTP_IMAGE_OFFSET_LEFT) { ox = 0; } else if (offset_x == NGX_HTTP_IMAGE_OFFSET_CENTER) { ox /= 2; } if (offset_y == NGX_HTTP_IMAGE_OFFSET_TOP) { oy = 0; } else if (offset_y == NGX_HTTP_IMAGE_OFFSET_CENTER) { oy /= 2; } ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image crop: %d x %d @ %d x %d", dx, dy, ox, oy); if (colors == 0) { gdImageSaveAlpha(dst, 1); gdImageAlphaBlending(dst, 0); } gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, dy - oy); if (colors) { gdImageTrueColorToPalette(dst, 1, 256); } gdImageDestroy(src); } } if (transparent != -1 && colors) { gdImageColorTransparent(dst, gdImageColorExact(dst, red, green, blue)); } sharpen = ngx_http_image_filter_get_value(r, conf->shcv, conf->sharpen); if (sharpen > 0) { gdImageSharpen(dst, sharpen); } out = ngx_http_image_out(r, ctx->type, dst, &size); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image: %d x %d %d", sx, sy, colors); gdImageDestroy(dst); ngx_pfree(r->pool, ctx->image); if (out == NULL) { return NULL; } cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { gdFree(out); return NULL; } b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { gdFree(out); return NULL; } cln->handler = ngx_http_image_cleanup; cln->data = out; b->pos = out; b->last = out + size; b->memory = 1; b->last_buf = 1; ngx_http_image_length(r, b); return b; }
static int put_file_func (CameraFilesystem *fs, const char *folder, const char *name, CameraFileType type, CameraFile *file, void *data, GPContext *context) { #ifdef HAVE_GD Camera *camera = data; char *c, *in_name, *out_name, *filedata = NULL; int ret, in_width, in_height, in_x, in_y; size_t inc, outc; double aspect_in, aspect_out; #ifdef HAVE_ICONV char *in, *out; #endif unsigned long filesize = 0; gdImagePtr rotated, im_out, im_in = NULL; if (strcmp (folder, "/")) return GP_ERROR_DIRECTORY_NOT_FOUND; inc = strlen (name); in_name = strdup (name); outc = inc; out_name = malloc (outc + 1); if (!in_name || !out_name) { free (in_name); free (out_name); return GP_ERROR_NO_MEMORY; } /* Convert name to ASCII */ #ifdef HAVE_ICONV in = in_name; out = out_name; if (iconv (camera->pl->cd, &in, &inc, &out, &outc) == -1) { free (in_name); free (out_name); gp_log (GP_LOG_ERROR, "iconv", "Failed to convert filename to ASCII"); return GP_ERROR_OS_FAILURE; } outc = out - out_name; out_name[outc] = 0; #else for (i = 0; i < inc; i++) { if ((uint8_t)in_name[i] < 0x20 || (uint8_t)in_name[i] > 0x7E) out_name[i] = '?'; else out_name[i] = in_name[i]; } out_name[i] = 0; #endif free (in_name); /* Remove file extension, and if necessary truncate the name */ c = strrchr (out_name, '.'); if (c) *c = 0; if (outc > ST2205_FILENAME_LENGTH) out_name[ST2205_FILENAME_LENGTH] = 0; ret = gp_file_get_data_and_size (file, (const char **)&filedata, &filesize); if (ret < 0) { free (out_name); return ret; } /* Try loading the file using gd, starting with the most often used types first */ /* gdImageCreateFromJpegPtr is chatty on error, don't call it on non JPEG files */ if (filesize > 2 && (uint8_t)filedata[0] == 0xff && (uint8_t)filedata[1] == 0xd8) im_in = gdImageCreateFromJpegPtr(filesize, filedata); if (im_in == NULL) im_in = gdImageCreateFromPngPtr(filesize, filedata); if (im_in == NULL) im_in = gdImageCreateFromGifPtr(filesize, filedata); if (im_in == NULL) im_in = gdImageCreateFromWBMPPtr(filesize, filedata); if (im_in == NULL) { gp_log (GP_LOG_ERROR, "st2205", "Unrecognized file format for file: %s%s", folder, name); free (out_name); return GP_ERROR_BAD_PARAMETERS; } if (needs_rotation (camera)) { rotated = gdImageCreateTrueColor (im_in->sy, im_in->sx); if (rotated == NULL) { gdImageDestroy (im_in); free (out_name); return GP_ERROR_NO_MEMORY; } rotate90 (im_in, rotated); gdImageDestroy (im_in); im_in = rotated; } im_out = gdImageCreateTrueColor(camera->pl->width, camera->pl->height); if (im_out == NULL) { gdImageDestroy (im_in); free (out_name); return GP_ERROR_NO_MEMORY; } /* Keep aspect */ aspect_in = (double)im_in->sx / im_in->sy; aspect_out = (double)im_out->sx / im_out->sy; if (aspect_in > aspect_out) { /* Reduce in width (crop left and right) */ in_width = (im_in->sx / aspect_in) * aspect_out; in_x = (im_in->sx - in_width) / 2; in_height = im_in->sy; in_y = 0; } else { /* Reduce in height (crop top and bottom) */ in_width = im_in->sx; in_x = 0; in_height = (im_in->sy * aspect_in) / aspect_out; in_y = (im_in->sy - in_height) / 2; } gdImageCopyResampled (im_out, im_in, 0, 0, in_x, in_y, im_out->sx, im_out->sy, in_width, in_height); if (im_in->sx != im_out->sx || im_in->sy != im_out->sy) gdImageSharpen(im_out, 100); ret = st2205_write_file (camera, out_name, im_out->tpixels); if (ret >= 0) { /* Add to our filenames list */ ST2205_SET_FILENAME(camera->pl->filenames[ret], out_name, ret); /* And commit the changes to the device */ ret = st2205_commit(camera); } gdImageDestroy (im_in); gdImageDestroy (im_out); free (out_name); return ret; #else gp_log(GP_LOG_ERROR,"st2205", "GD compression not supported - no libGD present during build"); return GP_ERROR_NOT_SUPPORTED; #endif }
static ngx_buf_t * ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) { int sx, sy, dx, dy, ox, oy, ax, ay, size, colors, palette, transparent, sharpen, red, green, blue, t; u_char *out; ngx_buf_t *b; ngx_uint_t resize; gdImagePtr src, dst; ngx_pool_cleanup_t *cln; ngx_http_image_filter_conf_t *conf; src = ngx_http_image_source(r, ctx); if (src == NULL) { return NULL; } sx = gdImageSX(src); sy = gdImageSY(src); conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); if (!ctx->force && ctx->angle == 0 && (ngx_uint_t) sx <= ctx->max_width && (ngx_uint_t) sy <= ctx->max_height) { gdImageDestroy(src); return ngx_http_image_asis(r, ctx); } colors = gdImageColorsTotal(src); if (colors && conf->transparency) { transparent = gdImageGetTransparent(src); if (transparent != -1) { palette = colors; red = gdImageRed(src, transparent); green = gdImageGreen(src, transparent); blue = gdImageBlue(src, transparent); goto transparent; } } palette = 0; transparent = -1; red = 0; green = 0; blue = 0; transparent: gdImageColorTransparent(src, -1); dx = sx; dy = sy; if (conf->filter == NGX_HTTP_IMAGE_RESIZE) { if ((ngx_uint_t) dx > ctx->max_width) { dy = dy * ctx->max_width / dx; dy = dy ? dy : 1; dx = ctx->max_width; } if ((ngx_uint_t) dy > ctx->max_height) { dx = dx * ctx->max_height / dy; dx = dx ? dx : 1; dy = ctx->max_height; } resize = 1; } else if (conf->filter == NGX_HTTP_IMAGE_ROTATE) { resize = 0; } else if (conf->filter == NGX_HTTP_IMAGE_WATERMARK) { resize = 0; } else { /* NGX_HTTP_IMAGE_CROP */ resize = 0; if ((double) dx / dy < (double) ctx->max_width / ctx->max_height) { if ((ngx_uint_t) dx > ctx->max_width) { dy = dy * ctx->max_width / dx; dy = dy ? dy : 1; dx = ctx->max_width; resize = 1; } } else { if ((ngx_uint_t) dy > ctx->max_height) { dx = dx * ctx->max_height / dy; dx = dx ? dx : 1; dy = ctx->max_height; resize = 1; } } } if (resize) { dst = ngx_http_image_new(r, dx, dy, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } if (colors == 0) { gdImageSaveAlpha(dst, 1); gdImageAlphaBlending(dst, 0); } gdImageCopyResampled(dst, src, 0, 0, 0, 0, dx, dy, sx, sy); if (colors) { gdImageTrueColorToPalette(dst, 1, 256); } gdImageDestroy(src); } else { dst = src; } if (ctx->angle) { src = dst; ax = (dx % 2 == 0) ? 1 : 0; ay = (dy % 2 == 0) ? 1 : 0; switch (ctx->angle) { case 90: case 270: dst = ngx_http_image_new(r, dy, dx, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } if (ctx->angle == 90) { ox = dy / 2 + ay; oy = dx / 2 - ax; } else { ox = dy / 2 - ay; oy = dx / 2 + ax; } gdImageCopyRotated(dst, src, ox, oy, 0, 0, dx + ax, dy + ay, ctx->angle); gdImageDestroy(src); t = dx; dx = dy; dy = t; break; case 180: dst = ngx_http_image_new(r, dx, dy, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } gdImageCopyRotated(dst, src, dx / 2 - ax, dy / 2 - ay, 0, 0, dx + ax, dy + ay, ctx->angle); gdImageDestroy(src); break; } } if (conf->filter == NGX_HTTP_IMAGE_CROP) { src = dst; if ((ngx_uint_t) dx > ctx->max_width) { ox = dx - ctx->max_width; } else { ox = 0; } if ((ngx_uint_t) dy > ctx->max_height) { oy = dy - ctx->max_height; } else { oy = 0; } if (ox || oy) { dst = ngx_http_image_new(r, dx - ox, dy - oy, colors); if (dst == NULL) { gdImageDestroy(src); return NULL; } ox /= 2; oy /= 2; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image crop: %d x %d @ %d x %d", dx, dy, ox, oy); if (colors == 0) { gdImageSaveAlpha(dst, 1); gdImageAlphaBlending(dst, 0); } gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, dy - oy); if (colors) { gdImageTrueColorToPalette(dst, 1, 256); } gdImageDestroy(src); } } if (transparent != -1 && colors) { gdImageColorTransparent(dst, gdImageColorExact(dst, red, green, blue)); } if (conf->filter == NGX_HTTP_IMAGE_WATERMARK && conf->watermark.data) { FILE *watermark_file = fopen((const char *)conf->watermark.data, "r"); if (watermark_file) { gdImagePtr watermark, watermark_mix; ngx_int_t wdx = 0, wdy = 0; watermark = gdImageCreateFromPng(watermark_file); if(watermark != NULL) { watermark_mix = gdImageCreateTrueColor(watermark->sx, watermark->sy); if (ngx_strcmp(conf->watermark_position.data, "bottom-right") == 0) { wdx = dx - watermark->sx - 10; wdy = dy - watermark->sy - 10; } else if (ngx_strcmp(conf->watermark_position.data, "top-left") == 0) { wdx = wdy = 10; } else if (ngx_strcmp(conf->watermark_position.data, "top-right") == 0) { wdx = dx - watermark->sx - 10; wdy = 10; } else if (ngx_strcmp(conf->watermark_position.data, "bottom-left") == 0) { wdx = 10; wdy = dy - watermark->sy - 10; } else if (ngx_strcmp(conf->watermark_position.data, "center") == 0) { wdx = dx / 2 - watermark->sx / 2; wdy = dy / 2 - watermark->sy / 2; } gdImageCopy(watermark_mix, dst, 0, 0, wdx, wdy, watermark->sx, watermark->sy); gdImageCopy(watermark_mix, watermark, 0, 0, 0, 0, watermark->sx, watermark->sy); gdImageCopyMerge(dst, watermark_mix, wdx, wdy, 0, 0, watermark->sx, watermark->sy, 75); gdFree(watermark); gdFree(watermark_mix); } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "watermark file '%s' is not PNG", conf->watermark.data);} } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "watermark file '%s' not found", conf->watermark.data); } } sharpen = ngx_http_image_filter_get_value(r, conf->shcv, conf->sharpen); if (sharpen > 0) { gdImageSharpen(dst, sharpen); } gdImageInterlace(dst, (int) conf->interlace); out = ngx_http_image_out(r, ctx->type, dst, &size); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image: %d x %d %d", sx, sy, colors); gdImageDestroy(dst); ngx_pfree(r->pool, ctx->image); if (out == NULL) { return NULL; } cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { gdFree(out); return NULL; } b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { gdFree(out); return NULL; } cln->handler = ngx_http_image_cleanup; cln->data = out; b->pos = out; b->last = out + size; b->memory = 1; b->last_buf = 1; ngx_http_image_length(r, b); return b; }
static int put_file_func (CameraFilesystem *fs, const char *folder, CameraFile *file, void *data, GPContext *context) { #ifdef HAVE_GD Camera *camera = data; char *filedata = NULL; const char *name; int ret, in_width, in_height, in_x, in_y; double aspect_in, aspect_out; unsigned long filesize = 0; gdImagePtr im_out, im_in = NULL; if (strcmp (folder, "/")) return GP_ERROR_DIRECTORY_NOT_FOUND; CHECK (gp_file_get_name (file, &name)) CHECK (gp_file_get_data_and_size (file, (const char **)&filedata, &filesize)) /* Try loading the file using gd, starting with the most often used types first */ /* gdImageCreateFromJpegPtr is chatty on error, don't call it on non JPEG files */ if (filesize > 2 && (uint8_t)filedata[0] == 0xff && (uint8_t)filedata[1] == 0xd8) im_in = gdImageCreateFromJpegPtr(filesize, filedata); if (im_in == NULL) im_in = gdImageCreateFromPngPtr(filesize, filedata); if (im_in == NULL) im_in = gdImageCreateFromGifPtr(filesize, filedata); if (im_in == NULL) im_in = gdImageCreateFromWBMPPtr(filesize, filedata); if (im_in == NULL) { gp_log (GP_LOG_ERROR, "tp6801", "Unrecognized file format for file: %s%s", folder, name); return GP_ERROR_BAD_PARAMETERS; } im_out = gdImageCreateTrueColor(camera->pl->width, camera->pl->height); if (im_out == NULL) { gdImageDestroy (im_in); return GP_ERROR_NO_MEMORY; } /* Keep aspect */ aspect_in = (double)im_in->sx / im_in->sy; aspect_out = (double)im_out->sx / im_out->sy; if (aspect_in > aspect_out) { /* Reduce in width (crop left and right) */ in_width = (im_in->sx / aspect_in) * aspect_out; in_x = (im_in->sx - in_width) / 2; in_height = im_in->sy; in_y = 0; } else { /* Reduce in height (crop top and bottom) */ in_width = im_in->sx; in_x = 0; in_height = (im_in->sy * aspect_in) / aspect_out; in_y = (im_in->sy - in_height) / 2; } gdImageCopyResampled (im_out, im_in, 0, 0, in_x, in_y, im_out->sx, im_out->sy, in_width, in_height); if (im_in->sx != im_out->sx || im_in->sy != im_out->sy) gdImageSharpen(im_out, 100); ret = tp6801_write_file (camera, im_out->tpixels); if (ret >= 0) { /* Commit the changes to the device */ ret = tp6801_commit(camera); } gdImageDestroy (im_in); gdImageDestroy (im_out); return ret; #else gp_log(GP_LOG_ERROR,"tp6801", "GD compression not supported - no libGD present during build"); return GP_ERROR_NOT_SUPPORTED; #endif }
ngx_int_t ngx_http_small_light_gd_process(ngx_http_request_t *r, ngx_http_small_light_ctx_t *ctx) { ngx_http_small_light_gd_ctx_t *ictx; ngx_http_small_light_image_size_t sz; gdImagePtr src, dst, canvas; ngx_int_t colors, transparent, palette, red, green, blue; ngx_int_t ax, ay, ox, oy, type; int iw, ih, radius, ccolor, bcolor; char *sharpen, *of; u_char *out; int size; double q; ictx = (ngx_http_small_light_gd_ctx_t *)ctx->ictx; src = ngx_http_small_light_gd_src(ictx); if (src == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to get image source %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } /* adjust image size */ iw = gdImageSX(src); ih = gdImageSY(src); ngx_http_small_light_calc_image_size(r, ctx, &sz, iw, ih); colors = gdImageColorsTotal(src); palette = 0; transparent = -1; red = 0; green = 0; blue = 0; if (colors) { transparent = gdImageGetTransparent(src); if (transparent != -1) { palette = colors; red = gdImageRed(src, transparent); green = gdImageGreen(src, transparent); blue = gdImageBlue(src, transparent); } } gdImageColorTransparent(src, -1); /* rotate. */ if (sz.angle) { dst = src; ax = (iw % 2 == 0) ? 1 : 0; ay = (ih % 2 == 0) ? 1 : 0; switch (sz.angle) { case 90: case 270: dst = ngx_http_small_light_gd_new(ih, iw, palette); if (dst == NULL) { gdImageDestroy(src); return NGX_ERROR; } if (sz.angle == 90) { ox = ih / 2 - ay; oy = iw / 2 + ax; } else { ox = ih / 2 + ay; oy = iw / 2 - ax; } gdImageCopyRotated(dst, src, ox, oy, 0, 0, iw, ih, -sz.angle); gdImageDestroy(src); break; case 180: dst = ngx_http_small_light_gd_new(iw, ih, palette); if (dst == NULL) { gdImageDestroy(src); return NGX_ERROR; } gdImageCopyRotated(dst, src, iw / 2 - ax, ih / 2 - ay, 0, 0, iw + ax, ih + ay, sz.angle); gdImageDestroy(src); break; default: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "image not rotated. 'angle'(%ui) must be 90 or 180 or 270. %s:%d", sz.angle, __FUNCTION__, __LINE__); break; } src = dst; } /* calc size. */ iw = gdImageSX(src); ih = gdImageSY(src); ngx_http_small_light_calc_image_size(r, ctx, &sz, iw, ih); /* pass through. */ if (sz.pt_flg != 0) { gdImageDestroy(src); ctx->of = ctx->inf; return NGX_OK; } /* crop, scale. */ if (sz.scale_flg != 0) { dst = ngx_http_small_light_gd_new(sz.dw, sz.dh, palette); if (dst == NULL) { gdImageDestroy(src); return NGX_ERROR; } if (colors == 0) { gdImageSaveAlpha(dst, 1); gdImageAlphaBlending(dst, 0); } gdImageCopyResampled(dst, src, 0, 0, sz.sx, sz.sy, sz.dw, sz.dh, sz.sw, sz.sh); if (colors) { gdImageTrueColorToPalette(dst, 1, 256); } gdImageDestroy(src); } else { dst = src; } if (transparent != -1 && colors) { gdImageColorTransparent(dst, gdImageColorExact(dst, red, green, blue)); } /* effects. */ sharpen = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "sharpen"); if (sharpen != NULL) { radius = ngx_http_small_light_parse_int(sharpen); if (radius > 0) { gdImageSharpen(dst, radius); } } /* interlace */ gdImageInterlace(dst, 1); /* create canvas then draw image to the canvas. */ if (sz.cw > 0.0 && sz.ch > 0.0) { canvas = gdImageCreateTrueColor(sz.cw, sz.ch); if (canvas == NULL) { gdImageDestroy(dst); return NGX_ERROR; } ccolor = gdImageColorAllocateAlpha(canvas, sz.cc.r, sz.cc.g, sz.cc.b, sz.cc.a); gdImageFilledRectangle(canvas, 0, 0, sz.cw, sz.ch, ccolor); gdImageCopy(canvas, dst, sz.dx, sz.dy, 0, 0, sz.dw, sz.dh); gdImageDestroy(dst); dst = canvas; } /* border. */ if (sz.bw > 0.0 || sz.bh > 0.0) { bcolor = gdImageColorAllocateAlpha(dst, sz.bc.r, sz.bc.g, sz.bc.b, sz.bc.a); if (sz.cw > 0.0 && sz.ch > 0.0) { gdImageFilledRectangle(dst, 0, 0, sz.cw, sz.bh, bcolor); gdImageFilledRectangle(dst, 0, 0, sz.bw, sz.ch, bcolor); gdImageFilledRectangle(dst, 0, sz.ch - sz.bh, sz.cw - 1, sz.ch - 1, bcolor); gdImageFilledRectangle(dst, sz.cw - sz.bw, 0, sz.cw - 1, sz.ch - 1, bcolor); } else { gdImageFilledRectangle(dst, 0, 0, sz.dw, sz.bh, bcolor); gdImageFilledRectangle(dst, 0, 0, sz.bw, sz.dh, bcolor); gdImageFilledRectangle(dst, 0, sz.dh - sz.bh, sz.dw - 1, sz.dh - 1, bcolor); gdImageFilledRectangle(dst, sz.dw - sz.bw, 0, sz.dw - 1, sz.dh - 1, bcolor); } } 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__); } else if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_WEBP) { #ifdef NGX_HTTP_SMALL_LIGHT_GD_WEBP_ENABLED ictx->type = type; #else ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "WebP is not supported %s:%d", __FUNCTION__, __LINE__); #endif } else { ictx->type = type; } } ctx->of = ngx_http_small_light_image_types[ictx->type - 1]; q = ngx_http_small_light_parse_double(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "q")); if (q == 0) { q = 100; } out = ngx_http_small_light_gd_out(dst, ictx->type, (int *)&size, q); gdImageDestroy(dst); if (out == NULL) { return NGX_ERROR; } /* get small_lighted image as binary. */ ctx->content = out; ctx->content_length = size; ngx_pfree(r->pool, ctx->content_orig); ictx->complete = 1; return NGX_OK; }
int main(int argc, char *argv[]) { FILE *fin = NULL; FILE *fout = NULL; gdImagePtr im_in = NULL, im = NULL; char *buf = NULL; int bufsize, ret = 0; /* FIXME get these from the cmdline */ int width = 128, height = 128; if (argc != 4) { fprintf (stderr, "Usage: %s <-d|-c> <inputfile> <outputfile>\n", argv[0]); ret = 1; goto exit; } fin = fopen(argv[2], "r"); if (!fin) { fprintf (stderr, "Error opening: %s: %s\n", argv[2], strerror(errno)); ret = 1; goto exit; } fout = fopen(argv[3], "w"); if (!fout) { fprintf (stderr, "Error opening: %s: %s\n", argv[3], strerror(errno)); ret = 1; goto exit; } bufsize = width * height; buf = malloc(bufsize); if (!buf) { fprintf (stderr, "Error allocating memory\n"); ret = 1; goto exit; } im = gdImageCreateTrueColor(width, height); if (!im) { fprintf (stderr, "Error allocating memory\n"); ret = 1; goto exit; } if (!strcmp(argv[1], "-d")) { if (fread(buf, 1, bufsize, fin) != bufsize) { fprintf (stderr, "Error reading: %s: %s\n", argv[2], strerror(errno)); ret = 1; goto exit; } ax203_decode2(buf, im->tpixels, width, height); gdImagePng (im, fout); } else if (!strcmp(argv[1], "-c")) { im_in = gdImageCreateFromPng(fin); if (im_in == NULL) { rewind(fin); im_in = gdImageCreateFromGif(fin); } if (im_in == NULL) { rewind(fin); im_in = gdImageCreateFromWBMP(fin); } /* gdImageCreateFromJpegPtr is chatty on error, so call it last */ if (im_in == NULL) { rewind(fin); im_in = gdImageCreateFromJpeg(fin); } if (im_in == NULL) { fprintf (stderr, "Error unrecognized file format for file: %s\n", argv[2]); ret = 1; goto exit; } gdImageCopyResampled (im, im_in, 0, 0, 0, 0, im->sx, im->sy, im_in->sx, im_in->sy); gdImageSharpen(im, 100); ax203_encode2(im->tpixels, buf, width, height); if (fwrite (buf, 1, bufsize, fout) != bufsize) { fprintf (stderr, "Error writing: %s: %s\n", argv[3], strerror(errno)); ret = 1; goto exit; } } else { fprintf (stderr, "%s: unkown option: %s\n", argv[0], argv[1]); ret = 1; goto exit; } exit: if (fin) fclose (fin); if (fout) fclose (fout); if (buf) free (buf); if (im) gdImageDestroy (im); if (im_in) gdImageDestroy (im_in); return ret; }