Mercurial > hg > nginx-ranges
diff src/http/modules/ngx_http_image_filter_module.c @ 578:f3a9e57d2e17
Merge with current.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 11 Mar 2010 21:27:17 +0300 |
parents | 2da4537168f8 |
children | 8246d8a2c2be |
line wrap: on
line diff
--- a/src/http/modules/ngx_http_image_filter_module.c +++ b/src/http/modules/ngx_http_image_filter_module.c @@ -40,6 +40,8 @@ typedef struct { ngx_uint_t height; ngx_int_t jpeg_quality; + ngx_flag_t transparency; + ngx_http_complex_value_t *wcv; ngx_http_complex_value_t *hcv; @@ -61,6 +63,7 @@ typedef struct { ngx_uint_t phase; ngx_uint_t type; + ngx_uint_t force; } ngx_http_image_filter_ctx_t; @@ -115,6 +118,13 @@ static ngx_command_t ngx_http_image_fil offsetof(ngx_http_image_filter_conf_t, jpeg_quality), NULL }, + { ngx_string("image_filter_transparency"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_image_filter_conf_t, transparency), + NULL }, + { ngx_string("image_filter_buffer"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, @@ -492,7 +502,8 @@ ngx_http_image_process(ngx_http_request_ if (rc == NGX_OK && ctx->width <= ctx->max_width - && ctx->height <= ctx->max_height) + && ctx->height <= ctx->max_height + && !ctx->force) { return ngx_http_image_asis(r, ctx); } @@ -592,6 +603,7 @@ static ngx_int_t ngx_http_image_size(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) { u_char *p, *last; + size_t len, app; ngx_uint_t width, height; p = ctx->image; @@ -602,26 +614,38 @@ ngx_http_image_size(ngx_http_request_t * p += 2; last = ctx->image + ctx->length - 10; + width = 0; + height = 0; + app = 0; while (p < last) { if (p[0] == 0xff && p[1] != 0xff) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "JPEG: %02xd %02xd", *p, *(p + 1)); + "JPEG: %02xd %02xd", p[0], p[1]); p++; - if (*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3 - || *p == 0xc9 || *p == 0xca || *p == 0xcb) + if ((*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3 + || *p == 0xc9 || *p == 0xca || *p == 0xcb) + && (width == 0 || height == 0)) { - goto found; + width = p[6] * 256 + p[7]; + height = p[4] * 256 + p[5]; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "JPEG: %02xd %02xd", p[1], p[2]); - p += p[1] * 256 + p[2]; + len = p[1] * 256 + p[2]; + + if (*p >= 0xe1 && *p <= 0xef) { + /* application data, e.g., EXIF, Adobe XMP, etc. */ + app += len; + } + + p += len; continue; } @@ -629,12 +653,16 @@ ngx_http_image_size(ngx_http_request_t * p++; } - return NGX_DECLINED; + if (width == 0 || height == 0) { + return NGX_DECLINED; + } - found: - - width = p[6] * 256 + p[7]; - height = p[4] * 256 + p[5]; + if (ctx->length / 20 < app) { + /* force conversion if application data consume more than 5% */ + ctx->force = 1; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "app data size: %uz", app); + } break; @@ -678,8 +706,9 @@ ngx_http_image_size(ngx_http_request_t * 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, - colors, transparent, red, green, blue, size; + int sx, sy, dx, dy, ox, oy, size, + colors, palette, transparent, + red, green, blue; u_char *out; ngx_buf_t *b; ngx_uint_t resize; @@ -698,7 +727,8 @@ ngx_http_image_resize(ngx_http_request_t conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); - if ((ngx_uint_t) sx <= ctx->max_width + if (!ctx->force + && (ngx_uint_t) sx <= ctx->max_width && (ngx_uint_t) sy <= ctx->max_height) { gdImageDestroy(src); @@ -706,17 +736,29 @@ ngx_http_image_resize(ngx_http_request_t } colors = gdImageColorsTotal(src); - transparent = gdImageGetTransparent(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); - if (transparent != -1 && colors) { - red = gdImageRed(src, transparent); - green = gdImageGreen(src, transparent); - blue = gdImageBlue(src, transparent); - gdImageColorTransparent(src, -1); + goto transparent; + } + } - } else { - red = 0; green = 0; blue = 0; - } + palette = 0; + transparent = -1; + red = 0; + green = 0; + blue = 0; + +transparent: + + gdImageColorTransparent(src, -1); dx = sx; dy = sy; @@ -762,14 +804,23 @@ ngx_http_image_resize(ngx_http_request_t } if (resize) { - dst = ngx_http_image_new(r, dx, dy, colors); + 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 { @@ -810,8 +861,17 @@ ngx_http_image_resize(ngx_http_request_t "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); } } @@ -1021,6 +1081,7 @@ ngx_http_image_filter_create_conf(ngx_co conf->filter = NGX_CONF_UNSET_UINT; conf->jpeg_quality = NGX_CONF_UNSET; + conf->transparency = NGX_CONF_UNSET; conf->buffer_size = NGX_CONF_UNSET_SIZE; return conf; @@ -1050,6 +1111,8 @@ ngx_http_image_filter_merge_conf(ngx_con /* 75 is libjpeg default quality */ ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75); + ngx_conf_merge_value(conf->transparency, prev->transparency, 1); + ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 1 * 1024 * 1024);