|
20 | 20 | #define NGX_HTTP_IMAGE_ROTATE 5
|
21 | 21 | #define NGX_HTTP_IMAGE_CROP_KEEPX 6
|
22 | 22 | #define NGX_HTTP_IMAGE_CROP_KEEPY 7
|
| 23 | +#define NGX_HTTP_IMAGE_WATERMARK 8 |
23 | 24 |
|
24 | 25 |
|
25 | 26 | #define NGX_HTTP_IMAGE_START 0
|
@@ -60,6 +61,8 @@ typedef struct {
|
60 | 61 |
|
61 | 62 | ngx_flag_t transparency;
|
62 | 63 | ngx_flag_t interlace;
|
| 64 | + ngx_str_t watermark; |
| 65 | + ngx_str_t watermark_position; |
63 | 66 | ngx_http_complex_value_t *output;
|
64 | 67 |
|
65 | 68 | ngx_http_complex_value_t *wcv;
|
@@ -202,6 +205,20 @@ static ngx_command_t ngx_http_image_filter_commands[] = {
|
202 | 205 | 0,
|
203 | 206 | NULL },
|
204 | 207 |
|
| 208 | + { ngx_string("image_filter_watermark"), |
| 209 | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
| 210 | + ngx_conf_set_str_slot, |
| 211 | + NGX_HTTP_LOC_CONF_OFFSET, |
| 212 | + offsetof(ngx_http_image_filter_conf_t, watermark), |
| 213 | + NULL }, |
| 214 | + |
| 215 | + { ngx_string("image_filter_watermark_position"), |
| 216 | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
| 217 | + ngx_conf_set_str_slot, |
| 218 | + NGX_HTTP_LOC_CONF_OFFSET, |
| 219 | + offsetof(ngx_http_image_filter_conf_t, watermark_position), |
| 220 | + NULL }, |
| 221 | + |
205 | 222 | ngx_null_command
|
206 | 223 | };
|
207 | 224 |
|
@@ -626,6 +643,16 @@ ngx_http_image_process(ngx_http_request_t *r)
|
626 | 643 | return ngx_http_image_resize(r, ctx);
|
627 | 644 | }
|
628 | 645 |
|
| 646 | + if (conf->filter == NGX_HTTP_IMAGE_WATERMARK) { |
| 647 | + |
| 648 | + if (!conf->watermark.data) { |
| 649 | + return NULL; |
| 650 | + } |
| 651 | + |
| 652 | + return ngx_http_image_resize(r, ctx); |
| 653 | + } |
| 654 | + |
| 655 | + |
629 | 656 | ctx->max_width = ngx_http_image_filter_get_value(r, conf->wcv, conf->width);
|
630 | 657 | if (ctx->max_width == 0) {
|
631 | 658 | return NULL;
|
@@ -983,6 +1010,10 @@ ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
|
983 | 1010 |
|
984 | 1011 | resize = 0;
|
985 | 1012 |
|
| 1013 | + } else if (conf->filter == NGX_HTTP_IMAGE_WATERMARK) { |
| 1014 | + |
| 1015 | + resize = 0; |
| 1016 | + |
986 | 1017 | } else { /* NGX_HTTP_IMAGE_CROP */
|
987 | 1018 |
|
988 | 1019 | resize = 0;
|
@@ -1162,6 +1193,49 @@ ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
|
1162 | 1193 | gdImageColorTransparent(dst, gdImageColorExact(dst, red, green, blue));
|
1163 | 1194 | }
|
1164 | 1195 |
|
| 1196 | + if (conf->filter == NGX_HTTP_IMAGE_WATERMARK && conf->watermark.data) { |
| 1197 | + FILE *watermark_file = fopen((const char *)conf->watermark.data, "r"); |
| 1198 | + |
| 1199 | + if (watermark_file) { |
| 1200 | + gdImagePtr watermark, watermark_mix; |
| 1201 | + ngx_int_t wdx = 0, wdy = 0; |
| 1202 | + |
| 1203 | + watermark = gdImageCreateFromPng(watermark_file); |
| 1204 | + fclose(watermark_file); |
| 1205 | + |
| 1206 | + if(watermark != NULL) { |
| 1207 | + watermark_mix = gdImageCreateTrueColor(watermark->sx, watermark->sy); |
| 1208 | + |
| 1209 | + if (ngx_strcmp(conf->watermark_position.data, "bottom-right") == 0) { |
| 1210 | + wdx = dx - watermark->sx - 10; |
| 1211 | + wdy = dy - watermark->sy - 10; |
| 1212 | + } else if (ngx_strcmp(conf->watermark_position.data, "top-left") == 0) { |
| 1213 | + wdx = wdy = 10; |
| 1214 | + } else if (ngx_strcmp(conf->watermark_position.data, "top-right") == 0) { |
| 1215 | + wdx = dx - watermark->sx - 10; |
| 1216 | + wdy = 10; |
| 1217 | + } else if (ngx_strcmp(conf->watermark_position.data, "bottom-left") == 0) { |
| 1218 | + wdx = 10; |
| 1219 | + wdy = dy - watermark->sy - 10; |
| 1220 | + } else if (ngx_strcmp(conf->watermark_position.data, "center") == 0) { |
| 1221 | + wdx = dx / 2 - watermark->sx / 2; |
| 1222 | + wdy = dy / 2 - watermark->sy / 2; |
| 1223 | + } |
| 1224 | + |
| 1225 | + gdImageCopy(watermark_mix, dst, 0, 0, wdx, wdy, watermark->sx, watermark->sy); |
| 1226 | + gdImageCopy(watermark_mix, watermark, 0, 0, 0, 0, watermark->sx, watermark->sy); |
| 1227 | + gdImageCopyMerge(dst, watermark_mix, wdx, wdy, 0, 0, watermark->sx, watermark->sy, 75); |
| 1228 | + gdImageDestroy(watermark); |
| 1229 | + gdImageDestroy(watermark_mix); |
| 1230 | + |
| 1231 | + } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "watermark file '%s' is not PNG", conf->watermark.data);} |
| 1232 | + |
| 1233 | + } else { |
| 1234 | + |
| 1235 | + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "watermark file '%s' not found", conf->watermark.data); |
| 1236 | + } |
| 1237 | + } |
| 1238 | + |
1165 | 1239 | sharpen = ngx_http_image_filter_get_value(r, conf->shcv, conf->sharpen);
|
1166 | 1240 | if (sharpen > 0) {
|
1167 | 1241 | gdImageSharpen(dst, sharpen);
|
@@ -1558,6 +1632,10 @@ ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
1558 | 1632 | ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
|
1559 | 1633 | 1 * 1024 * 1024);
|
1560 | 1634 |
|
| 1635 | + ngx_conf_merge_str_value(conf->watermark, prev->watermark, ""); |
| 1636 | + |
| 1637 | + ngx_conf_merge_str_value(conf->watermark_position, prev->watermark_position, "bottom-right"); |
| 1638 | + |
1561 | 1639 | if (conf->offset_x == NGX_CONF_UNSET_UINT) {
|
1562 | 1640 | ngx_conf_merge_uint_value(conf->offset_x, prev->offset_x,
|
1563 | 1641 | NGX_HTTP_IMAGE_OFFSET_CENTER);
|
@@ -1655,11 +1733,23 @@ ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
1655 | 1733 |
|
1656 | 1734 | return NGX_CONF_OK;
|
1657 | 1735 |
|
| 1736 | + } else if (ngx_strcmp(value[i].data, "watermark") == 0) { |
| 1737 | + imcf->filter = NGX_HTTP_IMAGE_WATERMARK; |
| 1738 | + imcf->watermark = value[2]; |
| 1739 | + return NGX_CONF_OK; |
| 1740 | + |
1658 | 1741 | } else {
|
1659 | 1742 | goto failed;
|
1660 | 1743 | }
|
1661 | 1744 | }
|
1662 | 1745 |
|
| 1746 | + if ((ngx_strcmp(value[i].data, "watermark") == 0) && cf->args->nelts == 4) { |
| 1747 | + imcf->filter = NGX_HTTP_IMAGE_WATERMARK; |
| 1748 | + imcf->watermark = value[2]; |
| 1749 | + imcf->watermark_position = value[3]; |
| 1750 | + return NGX_CONF_OK; |
| 1751 | + } |
| 1752 | + |
1663 | 1753 | if (ngx_strcmp(value[i].data, "resize") == 0) {
|
1664 | 1754 | imcf->filter = NGX_HTTP_IMAGE_RESIZE;
|
1665 | 1755 |
|
|
0 commit comments