comparison src/http/modules/ngx_http_image_filter_module.c @ 665:0b460e61bdcd default tip

Merge with nginx 1.0.0.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 25 Apr 2011 04:22:17 +0400
parents b4dcae568a2a
children
comparison
equal deleted inserted replaced
572:06419a2298a9 665:0b460e61bdcd
14 #define NGX_HTTP_IMAGE_OFF 0 14 #define NGX_HTTP_IMAGE_OFF 0
15 #define NGX_HTTP_IMAGE_TEST 1 15 #define NGX_HTTP_IMAGE_TEST 1
16 #define NGX_HTTP_IMAGE_SIZE 2 16 #define NGX_HTTP_IMAGE_SIZE 2
17 #define NGX_HTTP_IMAGE_RESIZE 3 17 #define NGX_HTTP_IMAGE_RESIZE 3
18 #define NGX_HTTP_IMAGE_CROP 4 18 #define NGX_HTTP_IMAGE_CROP 4
19 #define NGX_HTTP_IMAGE_ROTATE 5
19 20
20 21
21 #define NGX_HTTP_IMAGE_START 0 22 #define NGX_HTTP_IMAGE_START 0
22 #define NGX_HTTP_IMAGE_READ 1 23 #define NGX_HTTP_IMAGE_READ 1
23 #define NGX_HTTP_IMAGE_PROCESS 2 24 #define NGX_HTTP_IMAGE_PROCESS 2
36 37
37 typedef struct { 38 typedef struct {
38 ngx_uint_t filter; 39 ngx_uint_t filter;
39 ngx_uint_t width; 40 ngx_uint_t width;
40 ngx_uint_t height; 41 ngx_uint_t height;
41 ngx_int_t jpeg_quality; 42 ngx_uint_t angle;
43 ngx_uint_t jpeg_quality;
42 44
43 ngx_flag_t transparency; 45 ngx_flag_t transparency;
44 46
45 ngx_http_complex_value_t *wcv; 47 ngx_http_complex_value_t *wcv;
46 ngx_http_complex_value_t *hcv; 48 ngx_http_complex_value_t *hcv;
49 ngx_http_complex_value_t *acv;
50 ngx_http_complex_value_t *jqcv;
47 51
48 size_t buffer_size; 52 size_t buffer_size;
49 } ngx_http_image_filter_conf_t; 53 } ngx_http_image_filter_conf_t;
50 54
51 55
55 59
56 size_t length; 60 size_t length;
57 61
58 ngx_uint_t width; 62 ngx_uint_t width;
59 ngx_uint_t height; 63 ngx_uint_t height;
60
61 ngx_uint_t max_width; 64 ngx_uint_t max_width;
62 ngx_uint_t max_height; 65 ngx_uint_t max_height;
66 ngx_uint_t angle;
63 67
64 ngx_uint_t phase; 68 ngx_uint_t phase;
65 ngx_uint_t type; 69 ngx_uint_t type;
70 ngx_uint_t force;
66 } ngx_http_image_filter_ctx_t; 71 } ngx_http_image_filter_ctx_t;
67 72
68 73
69 static ngx_int_t ngx_http_image_send(ngx_http_request_t *r, 74 static ngx_int_t ngx_http_image_send(ngx_http_request_t *r,
70 ngx_http_image_filter_ctx_t *ctx, ngx_chain_t *in); 75 ngx_http_image_filter_ctx_t *ctx, ngx_chain_t *in);
96 static void *ngx_http_image_filter_create_conf(ngx_conf_t *cf); 101 static void *ngx_http_image_filter_create_conf(ngx_conf_t *cf);
97 static char *ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, 102 static char *ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent,
98 void *child); 103 void *child);
99 static char *ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd, 104 static char *ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd,
100 void *conf); 105 void *conf);
106 static char *ngx_http_image_filter_jpeg_quality(ngx_conf_t *cf,
107 ngx_command_t *cmd, void *conf);
101 static ngx_int_t ngx_http_image_filter_init(ngx_conf_t *cf); 108 static ngx_int_t ngx_http_image_filter_init(ngx_conf_t *cf);
102 109
103 110
104 static ngx_command_t ngx_http_image_filter_commands[] = { 111 static ngx_command_t ngx_http_image_filter_commands[] = {
105 112
106 { ngx_string("image_filter"), 113 { ngx_string("image_filter"),
107 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13, 114 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13|NGX_CONF_TAKE2,
108 ngx_http_image_filter, 115 ngx_http_image_filter,
109 NGX_HTTP_LOC_CONF_OFFSET, 116 NGX_HTTP_LOC_CONF_OFFSET,
110 0, 117 0,
111 NULL }, 118 NULL },
112 119
113 { ngx_string("image_filter_jpeg_quality"), 120 { ngx_string("image_filter_jpeg_quality"),
114 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 121 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
115 ngx_conf_set_num_slot, 122 ngx_http_image_filter_jpeg_quality,
116 NGX_HTTP_LOC_CONF_OFFSET, 123 NGX_HTTP_LOC_CONF_OFFSET,
117 offsetof(ngx_http_image_filter_conf_t, jpeg_quality), 124 0,
118 NULL }, 125 NULL },
119 126
120 { ngx_string("image_filter_transparency"), 127 { ngx_string("image_filter_transparency"),
121 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 128 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
122 ngx_conf_set_flag_slot, 129 ngx_conf_set_flag_slot,
225 232
226 if (len != -1 && len > (off_t) conf->buffer_size) { 233 if (len != -1 && len > (off_t) conf->buffer_size) {
227 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 234 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
228 "image filter: too big response: %O", len); 235 "image filter: too big response: %O", len);
229 236
230 return NGX_ERROR; 237 return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
231 } 238 }
232 239
233 if (len == -1) { 240 if (len == -1) {
234 ctx->length = conf->buffer_size; 241 ctx->length = conf->buffer_size;
235 242
486 493
487 if (conf->filter == NGX_HTTP_IMAGE_SIZE) { 494 if (conf->filter == NGX_HTTP_IMAGE_SIZE) {
488 return ngx_http_image_json(r, rc == NGX_OK ? ctx : NULL); 495 return ngx_http_image_json(r, rc == NGX_OK ? ctx : NULL);
489 } 496 }
490 497
498 ctx->angle = ngx_http_image_filter_get_value(r, conf->acv, conf->angle);
499
500 if (conf->filter == NGX_HTTP_IMAGE_ROTATE) {
501
502 if (ctx->angle != 90 && ctx->angle != 180 && ctx->angle != 270) {
503 return NULL;
504 }
505
506 return ngx_http_image_resize(r, ctx);
507 }
508
491 ctx->max_width = ngx_http_image_filter_get_value(r, conf->wcv, conf->width); 509 ctx->max_width = ngx_http_image_filter_get_value(r, conf->wcv, conf->width);
492 if (ctx->max_width == 0) { 510 if (ctx->max_width == 0) {
493 return NULL; 511 return NULL;
494 } 512 }
495 513
499 return NULL; 517 return NULL;
500 } 518 }
501 519
502 if (rc == NGX_OK 520 if (rc == NGX_OK
503 && ctx->width <= ctx->max_width 521 && ctx->width <= ctx->max_width
504 && ctx->height <= ctx->max_height) 522 && ctx->height <= ctx->max_height
523 && ctx->angle == 0
524 && !ctx->force)
505 { 525 {
506 return ngx_http_image_asis(r, ctx); 526 return ngx_http_image_asis(r, ctx);
507 } 527 }
508 528
509 return ngx_http_image_resize(r, ctx); 529 return ngx_http_image_resize(r, ctx);
525 b->last_buf = 1; 545 b->last_buf = 1;
526 546
527 ngx_http_clean_header(r); 547 ngx_http_clean_header(r);
528 548
529 r->headers_out.status = NGX_HTTP_OK; 549 r->headers_out.status = NGX_HTTP_OK;
530 r->headers_out.content_type.len = sizeof("text/plain") - 1; 550 ngx_str_set(&r->headers_out.content_type, "text/plain");
531 r->headers_out.content_type.data = (u_char *) "text/plain";
532 r->headers_out.content_type_lowcase = NULL; 551 r->headers_out.content_type_lowcase = NULL;
533 552
534 if (ctx == NULL) { 553 if (ctx == NULL) {
535 b->pos = (u_char *) "{}" CRLF; 554 b->pos = (u_char *) "{}" CRLF;
536 b->last = b->pos + sizeof("{}" CRLF) - 1; 555 b->last = b->pos + sizeof("{}" CRLF) - 1;
599 618
600 static ngx_int_t 619 static ngx_int_t
601 ngx_http_image_size(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) 620 ngx_http_image_size(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
602 { 621 {
603 u_char *p, *last; 622 u_char *p, *last;
623 size_t len, app;
604 ngx_uint_t width, height; 624 ngx_uint_t width, height;
605 625
606 p = ctx->image; 626 p = ctx->image;
607 627
608 switch (ctx->type) { 628 switch (ctx->type) {
609 629
610 case NGX_HTTP_IMAGE_JPEG: 630 case NGX_HTTP_IMAGE_JPEG:
611 631
612 p += 2; 632 p += 2;
613 last = ctx->image + ctx->length - 10; 633 last = ctx->image + ctx->length - 10;
634 width = 0;
635 height = 0;
636 app = 0;
614 637
615 while (p < last) { 638 while (p < last) {
616 639
617 if (p[0] == 0xff && p[1] != 0xff) { 640 if (p[0] == 0xff && p[1] != 0xff) {
618 641
619 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 642 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
620 "JPEG: %02xd %02xd", *p, *(p + 1)); 643 "JPEG: %02xd %02xd", p[0], p[1]);
621 644
622 p++; 645 p++;
623 646
624 if (*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3 647 if ((*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3
625 || *p == 0xc9 || *p == 0xca || *p == 0xcb) 648 || *p == 0xc9 || *p == 0xca || *p == 0xcb)
649 && (width == 0 || height == 0))
626 { 650 {
627 goto found; 651 width = p[6] * 256 + p[7];
652 height = p[4] * 256 + p[5];
628 } 653 }
629 654
630 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 655 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
631 "JPEG: %02xd %02xd", p[1], p[2]); 656 "JPEG: %02xd %02xd", p[1], p[2]);
632 657
633 p += p[1] * 256 + p[2]; 658 len = p[1] * 256 + p[2];
659
660 if (*p >= 0xe1 && *p <= 0xef) {
661 /* application data, e.g., EXIF, Adobe XMP, etc. */
662 app += len;
663 }
664
665 p += len;
634 666
635 continue; 667 continue;
636 } 668 }
637 669
638 p++; 670 p++;
639 } 671 }
640 672
641 return NGX_DECLINED; 673 if (width == 0 || height == 0) {
642 674 return NGX_DECLINED;
643 found: 675 }
644 676
645 width = p[6] * 256 + p[7]; 677 if (ctx->length / 20 < app) {
646 height = p[4] * 256 + p[5]; 678 /* force conversion if application data consume more than 5% */
679 ctx->force = 1;
680 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
681 "app data size: %uz", app);
682 }
647 683
648 break; 684 break;
649 685
650 case NGX_HTTP_IMAGE_GIF: 686 case NGX_HTTP_IMAGE_GIF:
651 687
687 static ngx_buf_t * 723 static ngx_buf_t *
688 ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) 724 ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
689 { 725 {
690 int sx, sy, dx, dy, ox, oy, size, 726 int sx, sy, dx, dy, ox, oy, size,
691 colors, palette, transparent, 727 colors, palette, transparent,
692 red, green, blue; 728 red, green, blue, t;
693 u_char *out; 729 u_char *out;
694 ngx_buf_t *b; 730 ngx_buf_t *b;
695 ngx_uint_t resize; 731 ngx_uint_t resize;
696 gdImagePtr src, dst; 732 gdImagePtr src, dst;
697 ngx_pool_cleanup_t *cln; 733 ngx_pool_cleanup_t *cln;
706 sx = gdImageSX(src); 742 sx = gdImageSX(src);
707 sy = gdImageSY(src); 743 sy = gdImageSY(src);
708 744
709 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); 745 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
710 746
711 if ((ngx_uint_t) sx <= ctx->max_width 747 if (!ctx->force
748 && ctx->angle == 0
749 && (ngx_uint_t) sx <= ctx->max_width
712 && (ngx_uint_t) sy <= ctx->max_height) 750 && (ngx_uint_t) sy <= ctx->max_height)
713 { 751 {
714 gdImageDestroy(src); 752 gdImageDestroy(src);
715 return ngx_http_image_asis(r, ctx); 753 return ngx_http_image_asis(r, ctx);
716 } 754 }
756 dx = dx ? dx : 1; 794 dx = dx ? dx : 1;
757 dy = ctx->max_height; 795 dy = ctx->max_height;
758 } 796 }
759 797
760 resize = 1; 798 resize = 1;
799
800 } else if (conf->filter == NGX_HTTP_IMAGE_ROTATE) {
801
802 resize = 0;
761 803
762 } else { /* NGX_HTTP_IMAGE_CROP */ 804 } else { /* NGX_HTTP_IMAGE_CROP */
763 805
764 resize = 0; 806 resize = 0;
765 807
805 847
806 } else { 848 } else {
807 dst = src; 849 dst = src;
808 } 850 }
809 851
810 if (conf->filter == NGX_HTTP_IMAGE_CROP) { 852 if (ctx->angle) {
811
812 src = dst; 853 src = dst;
813 854
814 if ((ngx_uint_t) dx > ctx->max_width) { 855 switch (ctx->angle) {
815 ox = dx - ctx->max_width; 856
816 857 case 90:
817 } else { 858 case 270:
818 ox = 0; 859 dst = ngx_http_image_new(r, dy, dx, palette);
819 }
820
821 if ((ngx_uint_t) dy > ctx->max_height) {
822 oy = dy - ctx->max_height;
823
824 } else {
825 oy = 0;
826 }
827
828 if (ox || oy) {
829
830 dst = ngx_http_image_new(r, dx - ox, dy - oy, colors);
831
832 if (dst == NULL) { 860 if (dst == NULL) {
833 gdImageDestroy(src); 861 gdImageDestroy(src);
834 return NULL; 862 return NULL;
835 } 863 }
864 gdImageCopyRotated(dst, src, dy/2, dx/2, 0, 0, dx, dy, ctx->angle);
865 gdImageDestroy(src);
866
867 t = dx;
868 dx = dy;
869 dy = t;
870 break;
871
872 case 180:
873 dst = ngx_http_image_new(r, dx, dy, palette);
874 if (dst == NULL) {
875 gdImageDestroy(src);
876 return NULL;
877 }
878 gdImageCopyRotated(dst, src, dx/2, dy/2, 0, 0, dx, dy, ctx->angle);
879 gdImageDestroy(src);
880 break;
881 }
882 }
883
884 if (conf->filter == NGX_HTTP_IMAGE_CROP) {
885
886 src = dst;
887
888 if ((ngx_uint_t) dx > ctx->max_width) {
889 ox = dx - ctx->max_width;
890
891 } else {
892 ox = 0;
893 }
894
895 if ((ngx_uint_t) dy > ctx->max_height) {
896 oy = dy - ctx->max_height;
897
898 } else {
899 oy = 0;
900 }
901
902 if (ox || oy) {
903
904 dst = ngx_http_image_new(r, dx - ox, dy - oy, colors);
905
906 if (dst == NULL) {
907 gdImageDestroy(src);
908 return NULL;
909 }
836 910
837 ox /= 2; 911 ox /= 2;
838 oy /= 2; 912 oy /= 2;
839 913
840 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 914 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
968 ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, gdImagePtr img, 1042 ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, gdImagePtr img,
969 int *size) 1043 int *size)
970 { 1044 {
971 char *failed; 1045 char *failed;
972 u_char *out; 1046 u_char *out;
1047 ngx_int_t jq;
973 ngx_http_image_filter_conf_t *conf; 1048 ngx_http_image_filter_conf_t *conf;
974 1049
975 out = NULL; 1050 out = NULL;
976 1051
977 switch (type) { 1052 switch (type) {
978 1053
979 case NGX_HTTP_IMAGE_JPEG: 1054 case NGX_HTTP_IMAGE_JPEG:
980 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); 1055 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
981 out = gdImageJpegPtr(img, size, conf->jpeg_quality); 1056
1057 jq = ngx_http_image_filter_get_value(r, conf->jqcv, conf->jpeg_quality);
1058 if (jq <= 0) {
1059 return NULL;
1060 }
1061
1062 out = gdImageJpegPtr(img, size, jq);
982 failed = "gdImageJpegPtr() failed"; 1063 failed = "gdImageJpegPtr() failed";
983 break; 1064 break;
984 1065
985 case NGX_HTTP_IMAGE_GIF: 1066 case NGX_HTTP_IMAGE_GIF:
986 out = gdImageGifPtr(img, size); 1067 out = gdImageGifPtr(img, size);
1058 if (conf == NULL) { 1139 if (conf == NULL) {
1059 return NULL; 1140 return NULL;
1060 } 1141 }
1061 1142
1062 conf->filter = NGX_CONF_UNSET_UINT; 1143 conf->filter = NGX_CONF_UNSET_UINT;
1063 conf->jpeg_quality = NGX_CONF_UNSET; 1144 conf->jpeg_quality = NGX_CONF_UNSET_UINT;
1145 conf->angle = NGX_CONF_UNSET_UINT;
1064 conf->transparency = NGX_CONF_UNSET; 1146 conf->transparency = NGX_CONF_UNSET;
1065 conf->buffer_size = NGX_CONF_UNSET_SIZE; 1147 conf->buffer_size = NGX_CONF_UNSET_SIZE;
1066 1148
1067 return conf; 1149 return conf;
1068 } 1150 }
1087 conf->hcv = prev->hcv; 1169 conf->hcv = prev->hcv;
1088 } 1170 }
1089 } 1171 }
1090 1172
1091 /* 75 is libjpeg default quality */ 1173 /* 75 is libjpeg default quality */
1092 ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75); 1174 ngx_conf_merge_uint_value(conf->jpeg_quality, prev->jpeg_quality, 75);
1175
1176 if (conf->jqcv == NULL) {
1177 conf->jqcv = prev->jqcv;
1178 }
1179
1180 ngx_conf_merge_uint_value(conf->angle, prev->angle, 0);
1181 if (conf->acv == NULL) {
1182 conf->acv = prev->acv;
1183 }
1093 1184
1094 ngx_conf_merge_value(conf->transparency, prev->transparency, 1); 1185 ngx_conf_merge_value(conf->transparency, prev->transparency, 1);
1095 1186
1096 ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 1187 ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
1097 1 * 1024 * 1024); 1188 1 * 1024 * 1024);
1128 } else { 1219 } else {
1129 goto failed; 1220 goto failed;
1130 } 1221 }
1131 1222
1132 return NGX_CONF_OK; 1223 return NGX_CONF_OK;
1224
1225 } else if (cf->args->nelts == 3) {
1226
1227 if (ngx_strcmp(value[i].data, "rotate") == 0) {
1228 imcf->filter = NGX_HTTP_IMAGE_ROTATE;
1229
1230 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
1231
1232 ccv.cf = cf;
1233 ccv.value = &value[++i];
1234 ccv.complex_value = &cv;
1235
1236 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
1237 return NGX_CONF_ERROR;
1238 }
1239
1240 if (cv.lengths == NULL) {
1241 n = ngx_http_image_filter_value(&value[i]);
1242
1243 if (n != 90 && n != 180 && n != 270) {
1244 goto failed;
1245 }
1246
1247 imcf->angle = (ngx_uint_t) n;
1248
1249 } else {
1250 imcf->acv = ngx_palloc(cf->pool,
1251 sizeof(ngx_http_complex_value_t));
1252 if (imcf->acv == NULL) {
1253 return NGX_CONF_ERROR;
1254 }
1255
1256 *imcf->acv = cv;
1257 }
1258
1259 return NGX_CONF_OK;
1260
1261 } else {
1262 goto failed;
1263 }
1133 } 1264 }
1134 1265
1135 if (ngx_strcmp(value[i].data, "resize") == 0) { 1266 if (ngx_strcmp(value[i].data, "resize") == 0) {
1136 imcf->filter = NGX_HTTP_IMAGE_RESIZE; 1267 imcf->filter = NGX_HTTP_IMAGE_RESIZE;
1137 1268
1207 1338
1208 return NGX_CONF_ERROR; 1339 return NGX_CONF_ERROR;
1209 } 1340 }
1210 1341
1211 1342
1343 static char *
1344 ngx_http_image_filter_jpeg_quality(ngx_conf_t *cf, ngx_command_t *cmd,
1345 void *conf)
1346 {
1347 ngx_http_image_filter_conf_t *imcf = conf;
1348
1349 ngx_str_t *value;
1350 ngx_int_t n;
1351 ngx_http_complex_value_t cv;
1352 ngx_http_compile_complex_value_t ccv;
1353
1354 value = cf->args->elts;
1355
1356 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
1357
1358 ccv.cf = cf;
1359 ccv.value = &value[1];
1360 ccv.complex_value = &cv;
1361
1362 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
1363 return NGX_CONF_ERROR;
1364 }
1365
1366 if (cv.lengths == NULL) {
1367 n = ngx_http_image_filter_value(&value[1]);
1368
1369 if (n <= 0) {
1370 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1371 "invalid parameter \"%V\"", &value[1]);
1372 return NGX_CONF_ERROR;
1373 }
1374
1375 imcf->jpeg_quality = (ngx_uint_t) n;
1376
1377 } else {
1378 imcf->jqcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
1379 if (imcf->jqcv == NULL) {
1380 return NGX_CONF_ERROR;
1381 }
1382
1383 *imcf->jqcv = cv;
1384 }
1385
1386 return NGX_CONF_OK;
1387 }
1388
1389
1212 static ngx_int_t 1390 static ngx_int_t
1213 ngx_http_image_filter_init(ngx_conf_t *cf) 1391 ngx_http_image_filter_init(ngx_conf_t *cf)
1214 { 1392 {
1215 ngx_http_next_header_filter = ngx_http_top_header_filter; 1393 ngx_http_next_header_filter = ngx_http_top_header_filter;
1216 ngx_http_top_header_filter = ngx_http_image_header_filter; 1394 ngx_http_top_header_filter = ngx_http_image_header_filter;