3434#define NGX_HTTP_IMAGE_GIF 2
3535#define NGX_HTTP_IMAGE_PNG 3
3636#define NGX_HTTP_IMAGE_WEBP 4
37+ #define NGX_HTTP_IMAGE_BMP 5
3738
3839
3940#define NGX_HTTP_IMAGE_OFFSET_CENTER 0
@@ -58,15 +59,16 @@ typedef struct {
5859
5960 ngx_flag_t transparency ;
6061 ngx_flag_t interlace ;
62+ ngx_str_t output ;
6163
62- ngx_http_complex_value_t * wcv ;
63- ngx_http_complex_value_t * hcv ;
64- ngx_http_complex_value_t * oxcv ;
65- ngx_http_complex_value_t * oycv ;
66- ngx_http_complex_value_t * acv ;
67- ngx_http_complex_value_t * jqcv ;
68- ngx_http_complex_value_t * wqcv ;
69- ngx_http_complex_value_t * shcv ;
64+ ngx_http_complex_value_t * wcv ;
65+ ngx_http_complex_value_t * hcv ;
66+ ngx_http_complex_value_t * oxcv ;
67+ ngx_http_complex_value_t * oycv ;
68+ ngx_http_complex_value_t * acv ;
69+ ngx_http_complex_value_t * jqcv ;
70+ ngx_http_complex_value_t * wqcv ;
71+ ngx_http_complex_value_t * shcv ;
7072
7173 size_t buffer_size ;
7274} ngx_http_image_filter_conf_t ;
@@ -193,6 +195,13 @@ static ngx_command_t ngx_http_image_filter_commands[] = {
193195 0 ,
194196 NULL },
195197
198+ { ngx_string ("image_filter_output" ),
199+ NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_LOC_CONF |NGX_CONF_TAKE1 ,
200+ ngx_conf_set_str_slot ,
201+ NGX_HTTP_LOC_CONF_OFFSET ,
202+ offsetof(ngx_http_image_filter_conf_t , output ),
203+ NULL },
204+
196205 ngx_null_command
197206};
198207
@@ -236,7 +245,8 @@ static ngx_str_t ngx_http_image_types[] = {
236245 ngx_string ("image/jpeg" ),
237246 ngx_string ("image/gif" ),
238247 ngx_string ("image/png" ),
239- ngx_string ("image/webp" )
248+ ngx_string ("image/webp" ),
249+ ngx_string ("image/bmp" )
240250};
241251
242252
@@ -366,7 +376,19 @@ ngx_http_image_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
366376 } else {
367377 ct = & ngx_http_image_types [ctx -> type - 1 ];
368378 }
369-
379+
380+ if (ngx_strncmp (conf -> output .data , "jpg" , 3 ) == 0 || ngx_strncmp (conf -> output .data , "jpeg" , 4 ) == 0 ) {
381+ ct = & ngx_http_image_types [NGX_HTTP_IMAGE_JPEG - 1 ];
382+ } else if (ngx_strncmp (conf -> output .data , "gif" , 3 ) == 0 ){
383+ ct = & ngx_http_image_types [NGX_HTTP_IMAGE_GIF - 1 ];
384+ } else if (ngx_strncmp (conf -> output .data , "png" , 3 ) == 0 ){
385+ ct = & ngx_http_image_types [NGX_HTTP_IMAGE_PNG - 1 ];
386+ } else if (ngx_strncmp (conf -> output .data , "webp" , 4 ) == 0 ){
387+ ct = & ngx_http_image_types [NGX_HTTP_IMAGE_WEBP - 1 ];
388+ } else if (ngx_strncmp (conf -> output .data , "bmp" , 3 ) == 0 ){
389+ ct = & ngx_http_image_types [NGX_HTTP_IMAGE_BMP - 1 ];
390+ }
391+
370392 r -> headers_out .content_type_len = ct -> len ;
371393 r -> headers_out .content_type = * ct ;
372394 r -> headers_out .content_type_lowcase = NULL ;
@@ -490,6 +512,10 @@ ngx_http_image_test(ngx_http_request_t *r, ngx_chain_t *in)
490512 /* WebP */
491513
492514 return NGX_HTTP_IMAGE_WEBP ;
515+ } else if (p [0 ] == 'B' && p [1 ] == 'M' ) {
516+ /* BMP */
517+
518+ return NGX_HTTP_IMAGE_BMP ;
493519 }
494520
495521 return NGX_HTTP_IMAGE_NONE ;
@@ -829,6 +855,16 @@ ngx_http_image_size(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
829855
830856 break ;
831857
858+ case NGX_HTTP_IMAGE_BMP :
859+ if (ctx -> length < 24 ) {
860+ return NGX_DECLINED ;
861+ }
862+
863+ width = p [18 ] * 256 + p [19 ];
864+ height = p [22 ] * 256 + p [23 ];
865+
866+ break ;
867+
832868 default :
833869
834870 return NGX_DECLINED ;
@@ -1185,6 +1221,11 @@ ngx_http_image_source(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
11851221#endif
11861222 break ;
11871223
1224+ case NGX_HTTP_IMAGE_BMP :
1225+ img = gdImageCreateFromBmpPtr (ctx -> length , ctx -> image );
1226+ failed = "gdImageCreateFromBmpPtr() failed" ;
1227+ break ;
1228+
11881229 default :
11891230 failed = "unknown image type" ;
11901231 break ;
@@ -1237,11 +1278,23 @@ ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, gdImagePtr img,
12371278
12381279 out = NULL ;
12391280
1281+ conf = ngx_http_get_module_loc_conf (r , ngx_http_image_filter_module );
1282+
1283+ if (ngx_strncmp (conf -> output .data , "jpg" , 3 ) == 0 || ngx_strncmp (conf -> output .data , "jpeg" , 4 ) == 0 ){
1284+ type = NGX_HTTP_IMAGE_JPEG ;
1285+ } else if (ngx_strncmp (conf -> output .data , "gif" , 3 ) == 0 ){
1286+ type = NGX_HTTP_IMAGE_GIF ;
1287+ } else if (ngx_strncmp (conf -> output .data , "png" , 3 ) == 0 ){
1288+ type = NGX_HTTP_IMAGE_PNG ;
1289+ } else if (ngx_strncmp (conf -> output .data , "webp" , 4 ) == 0 ){
1290+ type = NGX_HTTP_IMAGE_WEBP ;
1291+ } else if (ngx_strncmp (conf -> output .data , "bmp" , 3 ) == 0 ){
1292+ type = NGX_HTTP_IMAGE_BMP ;
1293+ }
1294+
12401295 switch (type ) {
12411296
12421297 case NGX_HTTP_IMAGE_JPEG :
1243- conf = ngx_http_get_module_loc_conf (r , ngx_http_image_filter_module );
1244-
12451298 q = ngx_http_image_filter_get_value (r , conf -> jqcv , conf -> jpeg_quality );
12461299 if (q <= 0 ) {
12471300 return NULL ;
@@ -1257,8 +1310,6 @@ ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, gdImagePtr img,
12571310 break ;
12581311
12591312 case NGX_HTTP_IMAGE_PNG :
1260- conf = ngx_http_get_module_loc_conf (r , ngx_http_image_filter_module );
1261-
12621313 if (conf -> jpeg_quality >= 96 ) {
12631314 out = gdImagePngPtr (img , size );
12641315 failed = "gdImagePngPtr() failed" ;
@@ -1275,8 +1326,6 @@ ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, gdImagePtr img,
12751326
12761327 case NGX_HTTP_IMAGE_WEBP :
12771328#if (NGX_HAVE_GD_WEBP )
1278- conf = ngx_http_get_module_loc_conf (r , ngx_http_image_filter_module );
1279-
12801329 q = ngx_http_image_filter_get_value (r , conf -> wqcv , conf -> webp_quality );
12811330 if (q <= 0 ) {
12821331 return NULL ;
@@ -1289,6 +1338,11 @@ ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, gdImagePtr img,
12891338#endif
12901339 break ;
12911340
1341+ case NGX_HTTP_IMAGE_BMP :
1342+ out = gdImageBmpPtr (img , size , 0 );
1343+ failed = "gdImageBmpPtr() failed" ;
1344+ break ;
1345+
12921346 default :
12931347 failed = "unknown image type" ;
12941348 break ;
@@ -1459,6 +1513,8 @@ ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
14591513
14601514 ngx_conf_merge_value (conf -> interlace , prev -> interlace , 0 );
14611515
1516+ ngx_conf_merge_str_value (conf -> output , prev -> output , "" );
1517+
14621518 ngx_conf_merge_size_value (conf -> buffer_size , prev -> buffer_size ,
14631519 1 * 1024 * 1024 );
14641520
0 commit comments