comparison src/http/modules/ngx_http_image_filter_module.c @ 502:89dc5654117c NGINX_0_7_63

nginx 0.7.63 *) Security: now "/../" are disabled in "Destination" request header line. *) Change: minimum supported OpenSSL version is 0.9.7. *) Change: the "ask" parameter of the "ssl_verify_client" directive was changed to the "optional" parameter and now it checks a client certificate if it was offered. Thanks to Brice Figureau. *) Feature: now the "-V" switch shows TLS SNI support. *) Feature: the $ssl_client_verify variable. Thanks to Brice Figureau. *) Feature: the "ssl_crl" directive. Thanks to Brice Figureau. *) Bugfix: the $ssl_client_cert variable usage corrupted memory; the bug had appeared in 0.7.7. Thanks to Sergey Zhuravlev. *) Feature: now the start cache loader runs in a separate process; this should improve large caches handling. *) Feature: now temporary files and permanent storage area may reside at different file systems. *) Bugfix: nginx counted incorrectly disk cache size. *) Change: now directive "gzip_disable msie6" does not disable gzipping for MSIE 6.0 SV1. *) Bugfix: nginx always added "Vary: Accept-Encoding" response header line, if both "gzip_static" and "gzip_vary" were on. *) Feature: the "proxy" parameter of the "geo" directive. *) Feature: the ngx_http_geoip_module. *) Feature: the "limit_rate_after" directive. Thanks to Ivan Debnar. *) Feature: the "limit_req_log_level" and "limit_conn_log_level" directives. *) Bugfix: now "limit_req" directive conforms to the leaky bucket algorithm. Thanks to Maxim Dounin. *) Bugfix: in ngx_http_limit_req_module. Thanks to Maxim Dounin. *) Bugfix: now nginx allows underscores in a request method. *) Bugfix: "proxy_pass_header" and "fastcgi_pass_header" directives did not pass to a client the "X-Accel-Redirect", "X-Accel-Limit-Rate", "X-Accel-Buffering", and "X-Accel-Charset" lines from backend response header. Thanks to Maxim Dounin. *) Bugfix: in handling "Last-Modified" and "Accept-Ranges" backend response header lines; the bug had appeared in 0.7.44. Thanks to Maxim Dounin. *) Feature: the "image_filter_transparency" directive. *) Feature: the "image_filter" directive supports variables for setting size. *) Bugfix: in PNG alpha-channel support in the ngx_http_image_filter_module. *) Bugfix: in transparency support in the ngx_http_image_filter_module. *) Feature: now several "perl_modules" directives may be used. *) Bugfix: ngx_http_perl_module responses did not work in subrequests. *) Bugfix: nginx sent '\0' in a "Location" response header line on MKCOL request. Thanks to Xie Zhenye. *) Bugfix: an "error_page" directive did not redirect a 413 error; the bug had appeared in 0.6.10. *) Bugfix: in memory allocation error handling. Thanks to Maxim Dounin and Kirill A. Korinskiy.
author Igor Sysoev <http://sysoev.ru>
date Mon, 26 Oct 2009 00:00:00 +0300
parents 116d5de7cbb6
children 68c0ae0a4959
comparison
equal deleted inserted replaced
501:dc87c92181c7 502:89dc5654117c
38 ngx_uint_t filter; 38 ngx_uint_t filter;
39 ngx_uint_t width; 39 ngx_uint_t width;
40 ngx_uint_t height; 40 ngx_uint_t height;
41 ngx_int_t jpeg_quality; 41 ngx_int_t jpeg_quality;
42 42
43 ngx_flag_t transparency;
44
45 ngx_http_complex_value_t *wcv;
46 ngx_http_complex_value_t *hcv;
47
43 size_t buffer_size; 48 size_t buffer_size;
44 } ngx_http_image_filter_conf_t; 49 } ngx_http_image_filter_conf_t;
45 50
46 51
47 typedef struct { 52 typedef struct {
50 55
51 size_t length; 56 size_t length;
52 57
53 ngx_uint_t width; 58 ngx_uint_t width;
54 ngx_uint_t height; 59 ngx_uint_t height;
60
61 ngx_uint_t max_width;
62 ngx_uint_t max_height;
55 63
56 ngx_uint_t phase; 64 ngx_uint_t phase;
57 ngx_uint_t type; 65 ngx_uint_t type;
58 } ngx_http_image_filter_ctx_t; 66 } ngx_http_image_filter_ctx_t;
59 67
78 static gdImagePtr ngx_http_image_new(ngx_http_request_t *r, int w, int h, 86 static gdImagePtr ngx_http_image_new(ngx_http_request_t *r, int w, int h,
79 int colors); 87 int colors);
80 static u_char *ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, 88 static u_char *ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type,
81 gdImagePtr img, int *size); 89 gdImagePtr img, int *size);
82 static void ngx_http_image_cleanup(void *data); 90 static void ngx_http_image_cleanup(void *data);
91 static ngx_uint_t ngx_http_image_filter_get_value(ngx_http_request_t *r,
92 ngx_http_complex_value_t *cv, ngx_uint_t v);
93 static ngx_uint_t ngx_http_image_filter_value(ngx_str_t *value);
83 94
84 95
85 static void *ngx_http_image_filter_create_conf(ngx_conf_t *cf); 96 static void *ngx_http_image_filter_create_conf(ngx_conf_t *cf);
86 static char *ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, 97 static char *ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent,
87 void *child); 98 void *child);
102 { ngx_string("image_filter_jpeg_quality"), 113 { ngx_string("image_filter_jpeg_quality"),
103 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 114 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
104 ngx_conf_set_num_slot, 115 ngx_conf_set_num_slot,
105 NGX_HTTP_LOC_CONF_OFFSET, 116 NGX_HTTP_LOC_CONF_OFFSET,
106 offsetof(ngx_http_image_filter_conf_t, jpeg_quality), 117 offsetof(ngx_http_image_filter_conf_t, jpeg_quality),
118 NULL },
119
120 { ngx_string("image_filter_transparency"),
121 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
122 ngx_conf_set_flag_slot,
123 NGX_HTTP_LOC_CONF_OFFSET,
124 offsetof(ngx_http_image_filter_conf_t, transparency),
107 NULL }, 125 NULL },
108 126
109 { ngx_string("image_filter_buffer"), 127 { ngx_string("image_filter_buffer"),
110 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 128 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
111 ngx_conf_set_size_slot, 129 ngx_conf_set_size_slot,
452 470
453 471
454 static ngx_buf_t * 472 static ngx_buf_t *
455 ngx_http_image_process(ngx_http_request_t *r) 473 ngx_http_image_process(ngx_http_request_t *r)
456 { 474 {
457 ngx_buf_t *b;
458 ngx_int_t rc; 475 ngx_int_t rc;
459 ngx_http_image_filter_ctx_t *ctx; 476 ngx_http_image_filter_ctx_t *ctx;
460 ngx_http_image_filter_conf_t *conf; 477 ngx_http_image_filter_conf_t *conf;
461 478
462 r->connection->buffered &= ~NGX_HTTP_IMAGE_BUFFERED; 479 r->connection->buffered &= ~NGX_HTTP_IMAGE_BUFFERED;
466 rc = ngx_http_image_size(r, ctx); 483 rc = ngx_http_image_size(r, ctx);
467 484
468 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); 485 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
469 486
470 if (conf->filter == NGX_HTTP_IMAGE_SIZE) { 487 if (conf->filter == NGX_HTTP_IMAGE_SIZE) {
471 488 return ngx_http_image_json(r, rc == NGX_OK ? ctx : NULL);
472 b = ngx_http_image_json(r, rc == NGX_OK ? ctx : NULL); 489 }
473 490
474 } else if (rc == NGX_OK 491 ctx->max_width = ngx_http_image_filter_get_value(r, conf->wcv, conf->width);
475 && ctx->width <= conf->width 492 if (ctx->max_width == 0) {
476 && ctx->height <= conf->height) 493 return NULL;
494 }
495
496 ctx->max_height = ngx_http_image_filter_get_value(r, conf->hcv,
497 conf->height);
498 if (ctx->max_height == 0) {
499 return NULL;
500 }
501
502 if (rc == NGX_OK
503 && ctx->width <= ctx->max_width
504 && ctx->height <= ctx->max_height)
477 { 505 {
478 b = ngx_http_image_asis(r, ctx); 506 return ngx_http_image_asis(r, ctx);
479 507 }
480 } else { 508
481 b = ngx_http_image_resize(r, ctx); 509 return ngx_http_image_resize(r, ctx);
482 }
483
484 return b;
485 } 510 }
486 511
487 512
488 static ngx_buf_t * 513 static ngx_buf_t *
489 ngx_http_image_json(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) 514 ngx_http_image_json(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
660 685
661 686
662 static ngx_buf_t * 687 static ngx_buf_t *
663 ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) 688 ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
664 { 689 {
665 int sx, sy, dx, dy, ox, oy, 690 int sx, sy, dx, dy, ox, oy, size,
666 colors, transparent, size; 691 colors, palette, transparent,
692 red, green, blue;
667 u_char *out; 693 u_char *out;
668 ngx_buf_t *b; 694 ngx_buf_t *b;
669 ngx_uint_t resize; 695 ngx_uint_t resize;
670 gdImagePtr src, dst; 696 gdImagePtr src, dst;
671 ngx_pool_cleanup_t *cln; 697 ngx_pool_cleanup_t *cln;
680 sx = gdImageSX(src); 706 sx = gdImageSX(src);
681 sy = gdImageSY(src); 707 sy = gdImageSY(src);
682 708
683 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); 709 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
684 710
685 if ((ngx_uint_t) sx <= conf->width && (ngx_uint_t) sy <= conf->height) { 711 if ((ngx_uint_t) sx <= ctx->max_width
712 && (ngx_uint_t) sy <= ctx->max_height)
713 {
686 gdImageDestroy(src); 714 gdImageDestroy(src);
687 return ngx_http_image_asis(r, ctx); 715 return ngx_http_image_asis(r, ctx);
688 } 716 }
689 717
690 colors = gdImageColorsTotal(src); 718 colors = gdImageColorsTotal(src);
691 transparent = gdImageGetTransparent(src); 719
720 if (colors && conf->transparency) {
721 transparent = gdImageGetTransparent(src);
722
723 if (transparent != -1) {
724 palette = colors;
725 red = gdImageRed(src, transparent);
726 green = gdImageGreen(src, transparent);
727 blue = gdImageBlue(src, transparent);
728
729 goto transparent;
730 }
731 }
732
733 palette = 0;
734 transparent = -1;
735 red = 0;
736 green = 0;
737 blue = 0;
738
739 transparent:
740
741 gdImageColorTransparent(src, -1);
692 742
693 dx = sx; 743 dx = sx;
694 dy = sy; 744 dy = sy;
695 745
696 if (conf->filter == NGX_HTTP_IMAGE_RESIZE) { 746 if (conf->filter == NGX_HTTP_IMAGE_RESIZE) {
697 747
698 if ((ngx_uint_t) dx > conf->width) { 748 if ((ngx_uint_t) dx > ctx->max_width) {
699 dy = dy * conf->width / dx; 749 dy = dy * ctx->max_width / dx;
700 dy = dy ? dy : 1; 750 dy = dy ? dy : 1;
701 dx = conf->width; 751 dx = ctx->max_width;
702 } 752 }
703 753
704 if ((ngx_uint_t) dy > conf->height) { 754 if ((ngx_uint_t) dy > ctx->max_height) {
705 dx = dx * conf->height / dy; 755 dx = dx * ctx->max_height / dy;
706 dx = dx ? dx : 1; 756 dx = dx ? dx : 1;
707 dy = conf->height; 757 dy = ctx->max_height;
708 } 758 }
709 759
710 resize = 1; 760 resize = 1;
711 761
712 } else { /* NGX_HTTP_IMAGE_CROP */ 762 } else { /* NGX_HTTP_IMAGE_CROP */
713 763
714 resize = 0; 764 resize = 0;
715 765
716 if ((ngx_uint_t) (dx * 100 / dy) < conf->width * 100 / conf->height) { 766 if ((ngx_uint_t) (dx * 100 / dy)
717 767 < ctx->max_width * 100 / ctx->max_height)
718 if ((ngx_uint_t) dx > conf->width) { 768 {
719 dy = dy * conf->width / dx; 769 if ((ngx_uint_t) dx > ctx->max_width) {
770 dy = dy * ctx->max_width / dx;
720 dy = dy ? dy : 1; 771 dy = dy ? dy : 1;
721 dx = conf->width; 772 dx = ctx->max_width;
722 resize = 1; 773 resize = 1;
723 } 774 }
724 775
725 } else { 776 } else {
726 if ((ngx_uint_t) dy > conf->height) { 777 if ((ngx_uint_t) dy > ctx->max_height) {
727 dx = dx * conf->height / dy; 778 dx = dx * ctx->max_height / dy;
728 dx = dx ? dx : 1; 779 dx = dx ? dx : 1;
729 dy = conf->height; 780 dy = ctx->max_height;
730 resize = 1; 781 resize = 1;
731 } 782 }
732 } 783 }
733 } 784 }
734 785
735 if (resize) { 786 if (resize) {
736 dst = ngx_http_image_new(r, dx, dy, colors); 787 dst = ngx_http_image_new(r, dx, dy, palette);
737 if (dst == NULL) { 788 if (dst == NULL) {
738 gdImageDestroy(src); 789 gdImageDestroy(src);
739 return NULL; 790 return NULL;
740 } 791 }
741 792
793 if (colors == 0) {
794 gdImageSaveAlpha(dst, 1);
795 gdImageAlphaBlending(dst, 0);
796 }
797
742 gdImageCopyResampled(dst, src, 0, 0, 0, 0, dx, dy, sx, sy); 798 gdImageCopyResampled(dst, src, 0, 0, 0, 0, dx, dy, sx, sy);
799
800 if (colors) {
801 gdImageTrueColorToPalette(dst, 1, 256);
802 }
743 803
744 gdImageDestroy(src); 804 gdImageDestroy(src);
745 805
746 } else { 806 } else {
747 dst = src; 807 dst = src;
749 809
750 if (conf->filter == NGX_HTTP_IMAGE_CROP) { 810 if (conf->filter == NGX_HTTP_IMAGE_CROP) {
751 811
752 src = dst; 812 src = dst;
753 813
754 if ((ngx_uint_t) dx > conf->width) { 814 if ((ngx_uint_t) dx > ctx->max_width) {
755 ox = dx - conf->width; 815 ox = dx - ctx->max_width;
756 816
757 } else { 817 } else {
758 ox = 0; 818 ox = 0;
759 } 819 }
760 820
761 if ((ngx_uint_t) dy > conf->height) { 821 if ((ngx_uint_t) dy > ctx->max_height) {
762 oy = dy - conf->height; 822 oy = dy - ctx->max_height;
763 823
764 } else { 824 } else {
765 oy = 0; 825 oy = 0;
766 } 826 }
767 827
779 839
780 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 840 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
781 "image crop: %d x %d @ %d x %d", 841 "image crop: %d x %d @ %d x %d",
782 dx, dy, ox, oy); 842 dx, dy, ox, oy);
783 843
844 if (colors == 0) {
845 gdImageSaveAlpha(dst, 1);
846 gdImageAlphaBlending(dst, 0);
847 }
848
784 gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, dy - oy); 849 gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, dy - oy);
785 850
851 if (colors) {
852 gdImageTrueColorToPalette(dst, 1, 256);
853 }
854
786 gdImageDestroy(src); 855 gdImageDestroy(src);
787 } 856 }
788 } 857 }
789 858
790 gdImageColorTransparent(dst, transparent); 859 if (transparent != -1 && colors) {
860 gdImageColorTransparent(dst, gdImageColorExact(dst, red, green, blue));
861 }
791 862
792 out = ngx_http_image_out(r, ctx->type, dst, &size); 863 out = ngx_http_image_out(r, ctx->type, dst, &size);
793 864
794 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 865 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
795 "image: %d x %d %d", sx, sy, colors); 866 "image: %d x %d %d", sx, sy, colors);
939 { 1010 {
940 gdFree(data); 1011 gdFree(data);
941 } 1012 }
942 1013
943 1014
1015 static ngx_uint_t
1016 ngx_http_image_filter_get_value(ngx_http_request_t *r,
1017 ngx_http_complex_value_t *cv, ngx_uint_t v)
1018 {
1019 ngx_str_t val;
1020
1021 if (cv == NULL) {
1022 return v;
1023 }
1024
1025 if (ngx_http_complex_value(r, cv, &val) != NGX_OK) {
1026 return 0;
1027 }
1028
1029 return ngx_http_image_filter_value(&val);
1030 }
1031
1032
1033 static ngx_uint_t
1034 ngx_http_image_filter_value(ngx_str_t *value)
1035 {
1036 ngx_int_t n;
1037
1038 if (value->len == 1 && value->data[0] == '-') {
1039 return (ngx_uint_t) -1;
1040 }
1041
1042 n = ngx_atoi(value->data, value->len);
1043
1044 if (n > 0) {
1045 return (ngx_uint_t) n;
1046 }
1047
1048 return 0;
1049 }
1050
1051
944 static void * 1052 static void *
945 ngx_http_image_filter_create_conf(ngx_conf_t *cf) 1053 ngx_http_image_filter_create_conf(ngx_conf_t *cf)
946 { 1054 {
947 ngx_http_image_filter_conf_t *conf; 1055 ngx_http_image_filter_conf_t *conf;
948 1056
949 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_image_filter_conf_t)); 1057 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_image_filter_conf_t));
950 if (conf == NULL) { 1058 if (conf == NULL) {
951 return NGX_CONF_ERROR; 1059 return NULL;
952 } 1060 }
953 1061
954 conf->filter = NGX_CONF_UNSET_UINT; 1062 conf->filter = NGX_CONF_UNSET_UINT;
955 conf->jpeg_quality = NGX_CONF_UNSET; 1063 conf->jpeg_quality = NGX_CONF_UNSET;
1064 conf->transparency = NGX_CONF_UNSET;
956 conf->buffer_size = NGX_CONF_UNSET_SIZE; 1065 conf->buffer_size = NGX_CONF_UNSET_SIZE;
957 1066
958 return conf; 1067 return conf;
959 } 1068 }
960 1069
972 1081
973 } else { 1082 } else {
974 conf->filter = prev->filter; 1083 conf->filter = prev->filter;
975 conf->width = prev->width; 1084 conf->width = prev->width;
976 conf->height = prev->height; 1085 conf->height = prev->height;
1086 conf->wcv = prev->wcv;
1087 conf->hcv = prev->hcv;
977 } 1088 }
978 } 1089 }
979 1090
980 /* 75 is libjpeg default quality */ 1091 /* 75 is libjpeg default quality */
981 ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75); 1092 ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75);
982 1093
1094 ngx_conf_merge_value(conf->transparency, prev->transparency, 1);
1095
983 ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 1096 ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
984 1 * 1024 * 1024); 1097 1 * 1024 * 1024);
985 1098
986 return NGX_CONF_OK; 1099 return NGX_CONF_OK;
987 } 1100 }
990 static char * 1103 static char *
991 ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 1104 ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
992 { 1105 {
993 ngx_http_image_filter_conf_t *imcf = conf; 1106 ngx_http_image_filter_conf_t *imcf = conf;
994 1107
995 ngx_str_t *value; 1108 ngx_str_t *value;
996 ngx_int_t n; 1109 ngx_int_t n;
997 ngx_uint_t i; 1110 ngx_uint_t i;
1111 ngx_http_complex_value_t cv;
1112 ngx_http_compile_complex_value_t ccv;
998 1113
999 value = cf->args->elts; 1114 value = cf->args->elts;
1000 1115
1001 i = 1; 1116 i = 1;
1002 1117
1025 1140
1026 } else { 1141 } else {
1027 goto failed; 1142 goto failed;
1028 } 1143 }
1029 1144
1030 i++; 1145 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
1031 1146
1032 if (value[i].len == 1 && value[i].data[0] == '-') { 1147 ccv.cf = cf;
1033 imcf->width = (ngx_uint_t) -1; 1148 ccv.value = &value[++i];
1149 ccv.complex_value = &cv;
1150
1151 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
1152 return NGX_CONF_ERROR;
1153 }
1154
1155 if (cv.lengths == NULL) {
1156 n = ngx_http_image_filter_value(&value[i]);
1157
1158 if (n == 0) {
1159 goto failed;
1160 }
1161
1162 imcf->width = (ngx_uint_t) n;
1034 1163
1035 } else { 1164 } else {
1036 n = ngx_atoi(value[i].data, value[i].len); 1165 imcf->wcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
1037 if (n == NGX_ERROR) { 1166 if (imcf->wcv == NULL) {
1167 return NGX_CONF_ERROR;
1168 }
1169
1170 *imcf->wcv = cv;
1171 }
1172
1173 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
1174
1175 ccv.cf = cf;
1176 ccv.value = &value[++i];
1177 ccv.complex_value = &cv;
1178
1179 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
1180 return NGX_CONF_ERROR;
1181 }
1182
1183 if (cv.lengths == NULL) {
1184 n = ngx_http_image_filter_value(&value[i]);
1185
1186 if (n == 0) {
1038 goto failed; 1187 goto failed;
1039 } 1188 }
1040 1189
1041 imcf->width = (ngx_uint_t) n; 1190 imcf->height = (ngx_uint_t) n;
1042 }
1043
1044 i++;
1045
1046 if (value[i].len == 1 && value[i].data[0] == '-') {
1047 imcf->height = (ngx_uint_t) -1;
1048 1191
1049 } else { 1192 } else {
1050 n = ngx_atoi(value[i].data, value[i].len); 1193 imcf->hcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
1051 if (n == NGX_ERROR) { 1194 if (imcf->hcv == NULL) {
1052 goto failed; 1195 return NGX_CONF_ERROR;
1053 } 1196 }
1054 1197
1055 imcf->height = (ngx_uint_t) n; 1198 *imcf->hcv = cv;
1056 } 1199 }
1057 1200
1058 return NGX_CONF_OK; 1201 return NGX_CONF_OK;
1059 1202
1060 failed: 1203 failed: