Mercurial > hg > nginx-mail
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; |