static MagickBooleanType ScribbleImage (MagickWand *canvas) { DrawingWand *picasso; PixelWand *color; picasso=NewDrawingWand(); color=NewPixelWand(); (void) PushDrawingWand(picasso); { DrawSetViewbox(picasso,0,0,(ssize_t) MagickGetImageWidth(canvas), (ssize_t) MagickGetImageHeight(canvas)); DrawScale(picasso,1.101,1.08); DrawTranslate(picasso,-23.69,-22.97); DrawRotate(picasso,0); (void) PixelSetColor(color,"#ffffff"); DrawSetFillColor(picasso,color); DrawRectangle(picasso,23.69,22.97,564.6,802.2); DrawSetFillOpacity(picasso,1.0); (void) PixelSetColor(color,"none"); DrawSetFillColor(picasso,color); DrawSetStrokeColor(picasso,color); DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); DrawPushDefs(picasso); { DrawPushClipPath(picasso,"clip_1"); { (void) PushDrawingWand(picasso); { DrawRectangle(picasso,0,0,595.3,841.9); } (void) PopDrawingWand(picasso); } DrawPopClipPath(picasso); } DrawPopDefs(picasso); (void) PushDrawingWand(picasso); { (void) DrawSetClipPath(picasso, "url(#clip_1)"); (void) PushDrawingWand(picasso); { DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeWidth(picasso,4.032); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); (void) DrawSetStrokeDashArray(picasso,0,(const double *)NULL); (void) PixelSetColor(color,"#ff0000"); DrawSetStrokeColor(picasso,color); DrawSetFillRule(picasso,EvenOddRule); (void) PixelSetColor(color,"#ff00ff"); DrawSetFillColor(picasso,color); DrawRectangle(picasso,72,72,144,144); } (void) PopDrawingWand(picasso); (void) PushDrawingWand(picasso); { DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeWidth(picasso,9); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); (void) DrawSetStrokeDashArray(picasso,0,(const double *)NULL); (void) PixelSetColor(color,"#00ff00"); DrawSetStrokeColor(picasso,color); DrawSetFillRule(picasso,EvenOddRule); (void) PixelSetColor(color,"#0080ff"); DrawSetFillColor(picasso,color); DrawRoundRectangle(picasso,72,216,360,432,9,9); } (void) PopDrawingWand(picasso); (void) PushDrawingWand(picasso); { const PointInfo points[37] = { { 378.1,81.72 }, { 381.1,79.56 }, { 384.3,78.12 }, { 387.6,77.33 }, { 391.1,77.11 }, { 394.6,77.62 }, { 397.8,78.77 }, { 400.9,80.57 }, { 403.6,83.02 }, { 523.9,216.8 }, { 526.2,219.7 }, { 527.6,223 }, { 528.4,226.4 }, { 528.6,229.8 }, { 528,233.3 }, { 526.9,236.5 }, { 525.1,239.5 }, { 522.6,242.2 }, { 495.9,266.3 }, { 493,268.5 }, { 489.7,269.9 }, { 486.4,270.8 }, { 482.9,270.9 }, { 479.5,270.4 }, { 476.2,269.3 }, { 473.2,267.5 }, { 470.4,265 }, { 350,131.2 }, { 347.8,128.3 }, { 346.4,125.1 }, { 345.6,121.7 }, {345.4,118.2 }, { 346,114.8 }, { 347.1,111.5 }, { 348.9,108.5 }, { 351.4,105.8 }, { 378.1,81.72 } }; DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeWidth(picasso,2.016); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); (void) DrawSetStrokeDashArray(picasso,0,(const double *)NULL); (void) PixelSetColor(color,"#000080"); DrawSetStrokeColor(picasso,color); DrawSetFillRule(picasso,EvenOddRule); (void) PixelSetColor(color,"#c2c280"); DrawSetFillColor(picasso,color); DrawPolygon(picasso,37,points); } (void) PopDrawingWand(picasso); (void) PushDrawingWand(picasso); { DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeWidth(picasso,3.024); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); (void) DrawSetStrokeDashArray(picasso,0,(const double *)NULL); (void) PixelSetColor(color,"#000080"); DrawSetStrokeColor(picasso,color); DrawSetFillRule(picasso,EvenOddRule); (void) PixelSetColor(color,"#000080"); DrawSetFillColor(picasso,color); DrawEllipse(picasso,489.6,424.8,72,129.6,0,360); } (void) PopDrawingWand(picasso); (void) PushDrawingWand(picasso); { const PointInfo points[48] = { { 213.8,25.13}, { 216.7,24.48 }, {219.8,24.55 }, { 223.1,25.42 }, { 226.7,27 }, { 230.3,29.3 }, { 234.1,32.26 }, { 237.9,35.86 }, { 241.8,40.03 }, { 249.7,50.11 }, { 257.4,62.14 }, { 264.8,75.89 }, { 271.6,91.15 }, { 277.3,106.8 }, { 281.6,121.8 }, { 284.4,135.9 }, { 285.7,148.5 }, { 285.6,159.6 }, { 284.9,164.3 }, { 283.8,168.5 }, { 282.5,172.1 }, { 280.7,175 }, { 278.5,177.3 }, { 275.9,178.7 }, { 273,179.4 }, { 269.9,179.3 }, { 266.6,178.4 }, { 263.1,176.8 }, { 259.5,174.5}, { 255.7,171.6 }, { 251.9,168 }, { 248,163.8 }, { 244.1,159 }, { 240.1,153.7 }, { 232.3,141.7 }, { 225,127.9 }, { 218.2,112.7 }, { 212.5,97.06 }, { 208.2,82.01 }, { 205.4,67.97 }, { 204,55.3 }, { 204.3,44.35 }, { 204.9,39.6 }, { 205.9,35.42 }, { 207.4,31.82 }, { 209.2,28.87 }, { 211.3,26.64}, { 213.8,25.13 } }; DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeWidth(picasso,3.024); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); (void) DrawSetStrokeDashArray(picasso,0,(const double *)NULL); (void) PixelSetColor(color,"#ff8000"); DrawSetStrokeColor(picasso,color); DrawSetFillRule(picasso,EvenOddRule); (void) PixelSetColor(color,"#00ffff"); DrawSetFillColor(picasso,color); DrawPolygon(picasso,48,points); } (void) PopDrawingWand(picasso); (void) PushDrawingWand(picasso); { DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeWidth(picasso,12.02); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); (void) DrawSetStrokeDashArray(picasso,0,(const double *)NULL); (void) PixelSetColor(color,"#4000c2"); DrawSetStrokeColor(picasso,color); (void) PixelSetColor(color,"none"); DrawSetFillColor(picasso,color); DrawArc(picasso,360,554.4,187.2,237.6,0,90); } (void) PopDrawingWand(picasso); (void) PushDrawingWand(picasso); { DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeWidth(picasso,9); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); (void) DrawSetStrokeDashArray(picasso,0,(const double *)NULL); (void) PixelSetColor(color,"#4000c2"); DrawSetStrokeColor(picasso,color); DrawSetFillRule(picasso,EvenOddRule); (void) PixelSetColor(color,"#4000c2"); DrawSetFillColor(picasso,color); DrawEllipse(picasso,388.8,626.4,100.8,122.4,0,90); } (void) PopDrawingWand(picasso); (void) PushDrawingWand(picasso); { const PointInfo points[6] = { { 180,504 }, { 282.7,578.6 }, { 243.5,699.4 }, { 116.5,699.4 }, { 77.26,578.6 }, { 180,504 } }; DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeWidth(picasso,9); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); (void) DrawSetStrokeDashArray(picasso,0,(const double *)NULL); (void) PixelSetColor(color,"#4000c2"); DrawSetStrokeColor(picasso,color); DrawSetFillRule(picasso,EvenOddRule); (void) PixelSetColor(color,"#800000"); DrawSetFillColor(picasso,color); DrawPolygon(picasso,6,points); } (void) PopDrawingWand(picasso); (void) PushDrawingWand(picasso); { const PointInfo points[11] = { { 180,504 }, { 211.8,568.3 }, { 282.7,578.6 }, { 231.3,628.7 }, { 243.5,699.4 }, { 180,666 }, { 116.5,699.4 }, { 128.7,628.7 }, { 77.26,578.6 }, { 148.2,568.3 }, { 180,504 } }; DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeWidth(picasso,9); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); (void) DrawSetStrokeDashArray(picasso,0,(const double *)NULL); (void) PixelSetColor(color,"#4000c2"); DrawSetStrokeColor(picasso,color); DrawSetFillRule(picasso,EvenOddRule); (void) PixelSetColor(color,"#800000"); DrawSetFillColor(picasso,color); DrawPolygon(picasso,11,points); } (void) PopDrawingWand(picasso); (void) PushDrawingWand(picasso); { const PointInfo points[15] = { { 540,288 }, { 561.6,216 }, { 547.2,43.2 }, { 280.8,36 }, { 302.4,194.4 }, { 331.2,64.8 }, { 504,64.8 }, { 475.2,115.2 }, { 525.6,93.6 }, { 496.8,158.4 }, { 532.8,136.8 }, { 518.4,180 }, { 540,172.8 }, { 540,223.2 }, { 540,288 } }; DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeWidth(picasso,5.976); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); (void) DrawSetStrokeDashArray(picasso,0,(const double *)NULL); (void) PixelSetColor(color,"#4000c2"); DrawSetStrokeColor(picasso,color); DrawSetFillRule(picasso,EvenOddRule); (void) PixelSetColor(color,"#ffff00"); DrawSetFillColor(picasso,color); DrawPolygon(picasso,15,points); } (void) PopDrawingWand(picasso); (void) PushDrawingWand(picasso); { const PointInfo points[7] = { { 57.6,640.8 }, { 57.6,784.8 }, { 194.4,799.2 }, { 259.2,777.6 }, { 151.2,756 }, { 86.4,748.8 }, { 57.6,640.8 } }; DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeWidth(picasso,5.976); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); (void) DrawSetStrokeDashArray(picasso,0,(const double *)NULL); (void) PixelSetColor(color,"#4000c2"); DrawSetStrokeColor(picasso,color); DrawSetFillRule(picasso,EvenOddRule); (void) PixelSetColor(color,"#ffff00"); DrawSetFillColor(picasso,color); DrawPolygon(picasso,7,points); } (void) PopDrawingWand(picasso); (void) PushDrawingWand(picasso); { const PointInfo points[193] = { { 27.86,565.3 }, { 29.66,550.8 }, { 31.97,538.1 }, { 34.85,527.1 }, { 38.09,517.7 }, { 41.83,509.8 }, { 45.86,503.1 }, { 50.33,497.6 }, { 55.08,493.2 }, { 60.19,489.8 }, { 65.45,487.3 }, { 70.92,485.4 }, { 76.61,484.2 }, { 88.42,483 }, { 100.4,482.9 }, { 108.4,482.2 }, { 119.8,480.3 }, { 150.8,474.1 }, { 189.4,466.6 }, { 210.3,463 }, { 231.5,459.9 }, { 252.4,457.8 }, { 272.7,456.6 }, { 291.8,456.9 }, { 300.7,457.7 }, { 309.1,458.9 }, { 316.9,460.6 }, { 324.1,462.8 }, { 330.7,465.6 }, { 336.4,469 }, { 341.3,473 }, { 345.3,477.7 }, { 348.4,483.1 }, { 350.4,489.2}, { 352.4,495.4 }, { 355.2,500.9 }, { 358.8,505.8 }, { 363,510 }, { 367.8,513.6 }, { 373,516.8 }, { 378.6,519.6 }, { 384.3,521.8 }, { 396.4,525.4 }, { 408.2,527.9 }, { 428,531.2 }, { 434.6,532.9 }, { 436.7,533.8 }, { 437.8,534.9 }, { 437.8,536.2 }, { 436.8,537.8 }, { 434.5,539.6 }, { 430.9,541.8 }, { 419.3,547.6 }, { 401.3,555.2 }, { 342.4,577.9 }, {325.2,584.9 }, { 311,591.3 }, { 300,597.3 }, { 291.6,602.8 }, { 285.8,607.8 }, { 282.3,612.3 }, { 281.4,614.4 }, { 280.9,616.2 }, { 281.2,619.6 }, { 282.1,621.2 }, { 283.3,622.6 }, { 286.8,624.9 }, { 291.5,626.6 }, { 297.1,627.8 }, { 303.6,628.3 }, { 310.5,628.3 }, { 317.9,627.6 }, { 325.2,626.3 }, { 332.6,624.3 }, { 339.5,621.7 }, { 345.9,618.4 }, { 351.4,614.4 }, { 353.9,612.2 }, { 356,609.8 }, { 357.9,607.1 }, { 359.4,604.3 }, { 360.6,601.3 }, { 361.4,598.2 }, { 361.7,594.9 }, { 361.7,591.3 }, { 361.2,587.7 }, { 360.1,583.7 }, { 358.6,579.7 }, { 356.4,575.4 }, { 353.7,570.9 }, { 350.4,566.2 }, { 346.4,561.3 }, { 341.8,556.2 }, { 336.5,550.9 }, { 330.6,545.5 }, { 323.8,539.8 }, { 316.2,533.9 }, { 298.7,521.5 }, { 277.8,508.2 }, { 256.1,495.5 }, { 236,484.5 }, { 217.7,475.1 }, { 200.8,467.1 }, { 185.6,460.7 }, { 171.9,455.5 }, { 159.6,451.6 }, { 148.6,448.8 }, { 139,447 }, { 130.5,446.2 }, { 123.3,446.2 }, { 117.1,446.9 }, { 112,448.3 }, { 107.9,450.2 }, { 104.8,452.5 }, { 102.5,455.2 }, { 101,458.1 }, { 100.2,461.2 }, { 100.2,464.3 }, { 100.7,467.4 }, { 101.8,470.3 }, { 103.4,473 }, { 105.4,475.3 }, { 107.8,477.1 }, { 110.5,478.4 }, { 113.4,479.1 }, { 116.5,478.9 }, { 119.7,478 }, { 123,476.2 }, { 126.4,473.3 }, { 129.6,469.2 }, { 132.7,463.9 }, { 135.2,458.4 }, { 136.6,453.7 }, { 137,449.9 }, { 136.6,446.8 }, { 135.4,444.5 }, { 133.3,442.9 }, { 130.8,441.9 }, { 127.5,441.4 }, { 123.9,441.6 }, { 119.8,442.3 }, { 110.7,445.1 }, { 101.1,449.5 }, { 91.37,455.2 }, { 82.37,461.9 }, { 74.66,469.2 }, { 71.57,473 }, { 68.98,476.8 }, { 67.03,480.7 }, { 65.81,484.4 }, { 65.45,488.2 }, { 65.95,491.7 }, { 67.46,495.1 }, { 69.98,498.3 }, { 73.66,501.3 }, { 78.55,503.9 }, { 84.82,506.3 }, { 92.38,508.2 }, { 107.1,511.6 }, { 118.2,514.8 }, { 125.9,517.8 }, { 130.7,520.4 }, { 132.1,521.7 }, { 132.8,522.9 }, { 133,524.2 }, { 132.6,525.3 }, { 131.8,526.5 }, { 130.5,527.5 }, { 126.6,529.6 }, { 121.5,531.7 }, { 115.3,533.7 }, { 101.4,537.6 }, { 87.55,541.8 }, { 81.36,544 }, { 76.25,546.3 }, { 71.64,549.5 }, { 66.89,554.1 }, { 62.14,559.8 }, { 57.38,566.1 }, { 48.17,579.6 }, { 39.96,591.4 }, { 36.43,595.9 }, { 34.78,597.6 }, { 33.26,598.8 }, { 31.9,599.6 }, { 30.67,599.9 }, { 29.59,599.7 }, { 28.66,598.8 }, { 27.86,597.4 }, { 27.29,595.2 }, { 26.64,588.7 }, { 26.86,578.8 }, { 27.86,565.3 } }; DrawSetStrokeAntialias(picasso,MagickTrue); DrawSetStrokeWidth(picasso,5.904); DrawSetStrokeLineCap(picasso,RoundCap); DrawSetStrokeLineJoin(picasso,RoundJoin); (void) DrawSetStrokeDashArray(picasso,0,(const double *)NULL); (void) PixelSetColor(color,"#4000c2"); DrawSetStrokeColor(picasso,color); DrawSetFillRule(picasso,EvenOddRule); (void) PixelSetColor(color,"#ffff00"); DrawSetFillColor(picasso,color); DrawPolygon(picasso,193,points); } (void) PopDrawingWand(picasso); } (void) PopDrawingWand(picasso); } (void) PopDrawingWand(picasso); (void) MagickDrawImage(canvas,picasso); color=DestroyPixelWand(color); picasso=DestroyDrawingWand(picasso); return(MagickTrue); }
ngx_int_t ngx_http_small_light_imagemagick_process(ngx_http_request_t *r, ngx_http_small_light_ctx_t *ctx) { ngx_http_small_light_imagemagick_ctx_t *ictx; ngx_http_small_light_image_size_t sz; MagickBooleanType status; int rmprof_flg, progressive_flg, cmyk2rgb_flg; double iw, ih, q; char *unsharp, *sharpen, *blur, *of, *of_orig; MagickWand *trans_wand, *canvas_wand; DrawingWand *border_wand; PixelWand *bg_color, *canvas_color, *border_color; GeometryInfo geo; ngx_fd_t fd; MagickWand *icon_wand; u_char *p, *embedicon; size_t embedicon_path_len, embedicon_len, sled_image_size; ngx_int_t type; u_char jpeg_size_opt[32], crop_geo[128], size_geo[128], embedicon_path[256]; ColorspaceType color_space; #if MagickLibVersion >= 0x690 int autoorient_flg; #endif status = MagickFalse; ictx = (ngx_http_small_light_imagemagick_ctx_t *)ctx->ictx; /* adjust image size */ ngx_http_small_light_calc_image_size(r, ctx, &sz, 10000.0, 10000.0); /* prepare */ if (sz.jpeghint_flg != 0) { p = ngx_snprintf((u_char *)jpeg_size_opt, sizeof(jpeg_size_opt) - 1, "%dx%d", (ngx_int_t)sz.dw, (ngx_int_t)sz.dh); *p = '\0'; ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "jpeg_size_opt:%s", jpeg_size_opt); MagickSetOption(ictx->wand, "jpeg:size", (char *)jpeg_size_opt); } /* load image. */ status = MagickReadImageBlob(ictx->wand, (void *)ictx->image, ictx->image_len); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "couldn't read image %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } MagickSetFirstIterator(ictx->wand); color_space = MagickGetImageColorspace(ictx->wand); /* remove all profiles */ rmprof_flg = ngx_http_small_light_parse_flag(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "rmprof")); if (rmprof_flg != 0) { status = MagickProfileImage(ictx->wand, "*", NULL, 0); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "couldn't profiling image %s:%d", __FUNCTION__, __LINE__); } } of_orig = MagickGetImageFormat(ictx->wand); status = MagickTrue; #if MagickLibVersion >= 0x690 /* auto-orient */ autoorient_flg = ngx_http_small_light_parse_flag(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "autoorient")); if (autoorient_flg != 0) { status = MagickAutoOrientImage(ictx->wand); if (status == MagickFalse) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; DestroyString(of_orig); return NGX_ERROR; } } #endif /* rotate. */ if (sz.angle) { bg_color = NewPixelWand(); PixelSetRed(bg_color, sz.cc.r / 255.0); PixelSetGreen(bg_color, sz.cc.g / 255.0); PixelSetBlue(bg_color, sz.cc.b / 255.0); PixelSetAlpha(bg_color, sz.cc.a / 255.0); switch (sz.angle) { case 90: case 180: case 270: MagickRotateImage(ictx->wand, bg_color, sz.angle); break; default: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "image not rotated. 'angle'(%ui) must be 90 or 180 or 270. %s:%d", sz.angle, __FUNCTION__, __LINE__); break; } DestroyPixelWand(bg_color); } /* calc size. */ iw = (double)MagickGetImageWidth(ictx->wand); ih = (double)MagickGetImageHeight(ictx->wand); ngx_http_small_light_calc_image_size(r, ctx, &sz, iw, ih); /* pass through. */ if (sz.pt_flg != 0) { ctx->of = ctx->inf; DestroyString(of_orig); return NGX_OK; } /* crop, scale. */ if (sz.scale_flg != 0) { p = ngx_snprintf(crop_geo, sizeof(crop_geo) - 1, "%f!x%f!+%f+%f", sz.sw, sz.sh, sz.sx, sz.sy); *p = '\0'; p = ngx_snprintf(size_geo, sizeof(size_geo) - 1, "%f!x%f!", sz.dw, sz.dh); *p = '\0'; ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "crop_geo:%s", crop_geo); ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "size_geo:%s", size_geo); MagickResetImagePage(ictx->wand, "+0+0"); trans_wand = MagickTransformImage(ictx->wand, (char *)crop_geo, (char *)size_geo); if (trans_wand == NULL || trans_wand == ictx->wand) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; DestroyString(of_orig); return NGX_ERROR; } DestroyMagickWand(ictx->wand); ictx->wand = trans_wand; } /* create canvas then draw image to the canvas. */ if (sz.cw > 0.0 && sz.ch > 0.0) { canvas_wand = NewMagickWand(); canvas_color = NewPixelWand(); PixelSetRed(canvas_color, sz.cc.r / 255.0); PixelSetGreen(canvas_color, sz.cc.g / 255.0); PixelSetBlue(canvas_color, sz.cc.b / 255.0); PixelSetAlpha(canvas_color, sz.cc.a / 255.0); status = MagickNewImage(canvas_wand, sz.cw, sz.ch, canvas_color); DestroyPixelWand(canvas_color); if (status == MagickFalse) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; DestroyMagickWand(canvas_wand); DestroyString(of_orig); return NGX_ERROR; } status = MagickTransformImageColorspace(canvas_wand, color_space); if (status == MagickFalse) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; DestroyMagickWand(canvas_wand); DestroyString(of_orig); return NGX_ERROR; } status = MagickCompositeImage(canvas_wand, ictx->wand, AtopCompositeOp, sz.dx, sz.dy); if (status == MagickFalse) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; DestroyMagickWand(canvas_wand); DestroyString(of_orig); return NGX_ERROR; } DestroyMagickWand(ictx->wand); ictx->wand = canvas_wand; } /* CMYK to sRGB */ cmyk2rgb_flg = ngx_http_small_light_parse_flag(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "cmyk2rgb")); if (cmyk2rgb_flg != 0 && color_space == CMYKColorspace) { status = MagickTransformImageColorspace(ictx->wand, sRGBColorspace); if (status == MagickFalse) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; DestroyString(of_orig); return NGX_ERROR; } } /* effects. */ unsharp = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "unsharp"); if (ngx_strlen(unsharp) > 0) { ParseGeometry(unsharp, &geo); if (geo.rho > ctx->radius_max || geo.sigma > ctx->sigma_max) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "As unsharp geometry is too large, ignored. %s:%d", __FUNCTION__, __LINE__); } else { status = MagickUnsharpMaskImage(ictx->wand, geo.rho, geo.sigma, geo.xi, geo.psi); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "unsharp failed %s:%d", __FUNCTION__, __LINE__); } } } sharpen = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "sharpen"); if (ngx_strlen(sharpen) > 0) { ParseGeometry(sharpen, &geo); if (geo.rho > ctx->radius_max || geo.sigma > ctx->sigma_max) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "As sharpen geometry is too large, ignored. %s:%d", __FUNCTION__, __LINE__); } else { status = MagickSharpenImage(ictx->wand, geo.rho, geo.sigma); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "sharpen failed %s:%d", __FUNCTION__, __LINE__); } } } blur = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "blur"); if (ngx_strlen(blur) > 0) { ParseGeometry(blur, &geo); if (geo.rho > ctx->radius_max || geo.sigma > ctx->sigma_max) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "As blur geometry is too large, ignored. %s:%d", __FUNCTION__, __LINE__); } else { status = MagickBlurImage(ictx->wand, geo.rho, geo.sigma); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "blur failed %s:%d", __FUNCTION__, __LINE__); } } } /* border. */ if (sz.bw > 0.0 || sz.bh > 0.0) { border_wand = NewDrawingWand(); border_color = NewPixelWand(); PixelSetRed(border_color, sz.bc.r / 255.0); PixelSetGreen(border_color, sz.bc.g / 255.0); PixelSetBlue(border_color, sz.bc.b / 255.0); PixelSetAlpha(border_color, sz.bc.a / 255.0); DrawSetFillColor(border_wand, border_color); DrawSetStrokeColor(border_wand, border_color); DrawSetStrokeWidth(border_wand, 1); if (sz.cw > 0.0 && sz.ch > 0.0) { DrawRectangle(border_wand, 0, 0, sz.cw - 1, sz.bh - 1); DrawRectangle(border_wand, 0, 0, sz.bw - 1, sz.ch - 1); DrawRectangle(border_wand, 0, sz.ch - sz.bh, sz.cw - 1, sz.ch - 1); DrawRectangle(border_wand, sz.cw - sz.bw, 0, sz.cw - 1, sz.ch - 1); } else { DrawRectangle(border_wand, 0, 0, sz.dw - 1, sz.bh - 1); DrawRectangle(border_wand, 0, 0, sz.bw - 1, sz.dh - 1); DrawRectangle(border_wand, 0, sz.dh - sz.bh, sz.dw - 1, sz.dh - 1); DrawRectangle(border_wand, sz.dw - sz.bw, 0, sz.dw - 1, sz.dh - 1); } MagickDrawImage(ictx->wand, border_wand); DestroyPixelWand(border_color); DestroyDrawingWand(border_wand); } /* embed icon */ embedicon = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "embedicon"); if (ctx->material_dir->len > 0 && ngx_strlen(embedicon) > 0) { if (ngx_strstrn((u_char *)embedicon, "/", 1 - 1)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid parameter 'embedicon':%s %s:%d", embedicon, __FUNCTION__, __LINE__); DestroyString(of_orig); return NGX_ERROR; } embedicon_len = ngx_strlen(embedicon); embedicon_path_len = ctx->material_dir->len + ngx_strlen("/") + embedicon_len; if (embedicon_path_len > sizeof(embedicon_path) - 1) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "embedicon path is too long. maximun value is %z %s:%d", sizeof(embedicon_path) - 1, __FUNCTION__, __LINE__); DestroyString(of_orig); return NGX_ERROR; } p = embedicon_path; p = ngx_cpystrn(p, ctx->material_dir->data, ctx->material_dir->len + 1); p = ngx_cpystrn(p, (u_char *)"/", 1 + 1); p = ngx_cpystrn(p, embedicon, embedicon_len + 1); if ((fd = ngx_open_file(embedicon_path, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0)) == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to open embeddedicon file:%s %s:%d", embedicon_path, __FUNCTION__, __LINE__); DestroyString(of_orig); return NGX_ERROR; } if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to close:%s %s:%d", embedicon_path, __FUNCTION__, __LINE__); DestroyString(of_orig); return NGX_ERROR; } if (ngx_strstrn(embedicon_path, "..", 2 - 1)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid embeddedicon_path:%s %s:%d", embedicon_path, __FUNCTION__, __LINE__); DestroyString(of_orig); return NGX_ERROR; } icon_wand = NewMagickWand(); if (MagickReadImage(icon_wand, (char *)embedicon_path) == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to read embed icon image file:%s %s:%d", embedicon_path, __FUNCTION__, __LINE__); DestroyMagickWand(icon_wand); DestroyString(of_orig); return NGX_ERROR; } MagickCompositeImageChannel(ictx->wand, AllChannels, icon_wand, OverCompositeOp, sz.ix, sz.iy); DestroyMagickWand(icon_wand); } /* set params. */ q = ngx_http_small_light_parse_double(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "q")); if (q > 0.0) { MagickSetImageCompressionQuality(ictx->wand, q); } progressive_flg = ngx_http_small_light_parse_flag(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "progressive")); if (progressive_flg != 0) { MagickSetInterlaceScheme(ictx->wand, LineInterlace); } of = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "of"); if (ngx_strlen(of) > 0) { type = ngx_http_small_light_type(of); if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_NONE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "of is invalid(%s) %s:%d", of, __FUNCTION__, __LINE__); of = (char *)ngx_http_small_light_image_exts[ictx->type - 1]; } else if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_WEBP) { #if defined(MAGICKCORE_WEBP_DELEGATE) ictx->type = type; #else ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "WebP is not supported %s:%d", __FUNCTION__, __LINE__); of = (char *)ngx_http_small_light_image_exts[ictx->type - 1]; #endif } else { ictx->type = type; } MagickSetFormat(ictx->wand, of); ctx->of = ngx_http_small_light_image_types[ictx->type - 1]; } else { MagickSetFormat(ictx->wand, of_orig); ctx->of = ctx->inf; } DestroyString(of_orig); ctx->content = MagickGetImageBlob(ictx->wand, &sled_image_size); ctx->content_length = sled_image_size; ngx_pfree(r->pool, ctx->content_orig); ictx->complete = 1; return NGX_OK; }
static bool HHVM_METHOD(ImagickDraw, setStrokeWidth, double stroke_width) { auto wand = getDrawingWandResource(this_); DrawSetStrokeWidth(wand->getWand(), stroke_width); return true; }
ngx_int_t ngx_http_small_light_imagemagick_process(ngx_http_request_t *r, ngx_http_small_light_ctx_t *ctx) { ngx_http_small_light_imagemagick_ctx_t *ictx; ngx_http_small_light_image_size_t sz; MagickBooleanType status; int rmprof_flg, progressive_flg; double iw, ih, q; char *jpeg_size_opt, *of_orig, *crop_geo, *size_geo; char *unsharp, *sharpen, *blur, *dealpha, *of; MagickWand *trans_wand, *canvas_wand; DrawingWand *border_wand; PixelWand *bg_color, *canvas_color, *border_color; GeometryInfo geo; ngx_fd_t fd; MagickWand *icon_wand; u_char *p, *embedicon, *embedicon_path; size_t embedicon_path_len, embedicon_len, sled_image_size; ngx_int_t type; status = MagickFalse; ictx = (ngx_http_small_light_imagemagick_ctx_t *)ctx->ictx; /* adjust image size */ ngx_http_small_light_calc_image_size(r, ctx, &sz, 10000.0, 10000.0); /* init */ ictx->wand = NewMagickWand(); /* prepare */ if (sz.jpeghint_flg != 0) { jpeg_size_opt = ngx_pcalloc(r->pool, 32 + 1); if (jpeg_size_opt == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ngx_snprintf((u_char *)jpeg_size_opt, 32 + 1, "%dx%d", (ngx_int_t)sz.dw, (ngx_int_t)sz.dh); MagickSetOption(ictx->wand, "jpeg:size", jpeg_size_opt); } /* load image. */ status = MagickReadImageBlob(ictx->wand, (void *)ictx->image, ictx->image_len); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "couldn't read image %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } /* remove all profiles */ rmprof_flg = ngx_http_small_light_parse_flag(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "rmprof")); if (rmprof_flg != 0) { status = MagickProfileImage(ictx->wand, "*", NULL, 0); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "couldn't profiling image %s:%d", __FUNCTION__, __LINE__); } } /* calc size. */ iw = (double)MagickGetImageWidth(ictx->wand); ih = (double)MagickGetImageHeight(ictx->wand); ngx_http_small_light_calc_image_size(r, ctx, &sz, iw, ih); /* pass through. */ if (sz.pt_flg != 0) { return NGX_OK; } of_orig = MagickGetImageFormat(ictx->wand); /* crop, scale. */ status = MagickTrue; if (sz.scale_flg != 0) { crop_geo = ngx_pcalloc(r->pool, 128 + 1); if (crop_geo == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } size_geo = ngx_pcalloc(r->pool, 128 + 1); if (size_geo == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ngx_snprintf((u_char *)crop_geo, 128 + 1, "%f!x%f!+%f+%f", sz.sw, sz.sh, sz.sx, sz.sy); ngx_snprintf((u_char *)size_geo, 128 + 1, "%f!x%f!", sz.dw, sz.dh); trans_wand = MagickTransformImage(ictx->wand, crop_geo, size_geo); if (trans_wand == NULL || trans_wand == ictx->wand) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_ERROR; } DestroyMagickWand(ictx->wand); ictx->wand = trans_wand; } /* rotate */ if (sz.angle) { bg_color = NewPixelWand(); PixelSetRed(bg_color, sz.cc.r / 255.0); PixelSetGreen(bg_color, sz.cc.g / 255.0); PixelSetBlue(bg_color, sz.cc.b / 255.0); PixelSetAlpha(bg_color, sz.cc.a / 255.0); switch (sz.angle) { case 90: case 180: case 270: MagickRotateImage(ictx->wand, bg_color, sz.angle); break; } DestroyPixelWand(bg_color); } /* create canvas then draw image to the canvas. */ if (sz.cw > 0.0 && sz.ch > 0.0) { canvas_wand = NewMagickWand(); canvas_color = NewPixelWand(); PixelSetRed(canvas_color, sz.cc.r / 255.0); PixelSetGreen(canvas_color, sz.cc.g / 255.0); PixelSetBlue(canvas_color, sz.cc.b / 255.0); PixelSetAlpha(canvas_color, sz.cc.a / 255.0); status = MagickNewImage(canvas_wand, sz.cw, sz.ch, canvas_color); DestroyPixelWand(canvas_color); if (status == MagickFalse) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_ERROR; } status = MagickCompositeImage(canvas_wand, ictx->wand, AtopCompositeOp, sz.dx, sz.dy); if (status == MagickFalse) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_ERROR; } DestroyMagickWand(ictx->wand); ictx->wand = canvas_wand; } /* effects. */ unsharp = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "unsharp"); if (unsharp != NULL) { ParseGeometry(unsharp, &geo); status = MagickUnsharpMaskImage(ictx->wand, geo.rho, geo.sigma, geo.xi, geo.psi); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "unsharp failed %s:%d", __FUNCTION__, __LINE__); } } sharpen = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "sharpen"); if (sharpen != NULL) { ParseGeometry(sharpen, &geo); status = MagickSharpenImage(ictx->wand, geo.rho, geo.sigma); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "sharpen failed %s:%d", __FUNCTION__, __LINE__); } } blur = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "blur"); if (blur) { ParseGeometry(blur, &geo); status = MagickBlurImage(ictx->wand, geo.rho, geo.sigma); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "blur failed %s:%d", __FUNCTION__, __LINE__); } } dealpha = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "dealpha"); if (dealpha != NULL) { status = MagickSetImageAlphaChannel(ictx->wand, DeactivateAlphaChannel); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "dealpha failed %s:%d", __FUNCTION__, __LINE__); } } /* border. */ if (sz.bw > 0.0 || sz.bh > 0.0) { border_wand = NewDrawingWand(); border_color = NewPixelWand(); PixelSetRed(border_color, sz.bc.r / 255.0); PixelSetGreen(border_color, sz.bc.g / 255.0); PixelSetBlue(border_color, sz.bc.b / 255.0); PixelSetAlpha(border_color, sz.bc.a / 255.0); DrawSetFillColor(border_wand, border_color); DrawSetStrokeColor(border_wand, border_color); DrawSetStrokeWidth(border_wand, 1); if (sz.cw > 0.0 && sz.ch > 0.0) { DrawRectangle(border_wand, 0, 0, sz.cw - 1, sz.bh - 1); DrawRectangle(border_wand, 0, 0, sz.bw - 1, sz.ch - 1); DrawRectangle(border_wand, 0, sz.ch - sz.bh, sz.cw - 1, sz.ch - 1); DrawRectangle(border_wand, sz.cw - sz.bw, 0, sz.cw - 1, sz.ch - 1); } else { DrawRectangle(border_wand, 0, 0, sz.dw - 1, sz.bh - 1); DrawRectangle(border_wand, 0, 0, sz.bw - 1, sz.dh - 1); DrawRectangle(border_wand, 0, sz.dh - sz.bh, sz.dw - 1, sz.dh - 1); DrawRectangle(border_wand, sz.dw - sz.bw, 0, sz.dw - 1, sz.dh - 1); } MagickDrawImage(ictx->wand, border_wand); DestroyPixelWand(border_color); DestroyDrawingWand(border_wand); } /* embed icon */ embedicon = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "embedicon"); if (ngx_strlen(ctx->material_dir) > 0 && ngx_strlen(embedicon) > 0) { if (ngx_strstrn((u_char *)embedicon, "/", 1 - 1)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid parameter 'embedicon':%s %s:%d", embedicon, __FUNCTION__, __LINE__); return NGX_ERROR; } icon_wand = NewMagickWand(); embedicon_len = ngx_strlen(embedicon); embedicon_path_len = ctx->material_dir->len + ngx_strlen("/") + embedicon_len; embedicon_path = ngx_palloc(r->pool, embedicon_path_len + 1); if (embedicon_path == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } p = embedicon_path; p = ngx_cpystrn(p, ctx->material_dir->data, ctx->material_dir->len + 1); p = ngx_cpystrn(p, (u_char *)"/", 1 + 1); p = ngx_cpystrn(p, embedicon, embedicon_len + 1); if ((fd = ngx_open_file(embedicon_path, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0)) == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to open embeddedicon file:%s %s:%d", embedicon_path, __FUNCTION__, __LINE__); return NGX_ERROR; } if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to close:%s %s:%d", embedicon_path, __FUNCTION__, __LINE__); return NGX_ERROR; } if (ngx_strstrn(embedicon_path, "..", 2 - 1)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid embeddedicon_path:%s %s:%d", embedicon_path, __FUNCTION__, __LINE__); return NGX_ERROR; } if (MagickReadImage(icon_wand, (char *)embedicon_path) == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to read embed icon image file:%s %s:%d", embedicon_path, __FUNCTION__, __LINE__); return NGX_ERROR; } MagickCompositeImageChannel(ictx->wand, AllChannels, icon_wand, OverCompositeOp, sz.ix, sz.iy); ClearMagickWand(icon_wand); } /* set params. */ q = ngx_http_small_light_parse_double(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "q")); if (q > 0.0) { MagickSetImageCompressionQuality(ictx->wand, q); } progressive_flg = ngx_http_small_light_parse_flag(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "progressive")); if (progressive_flg != 0) { MagickSetInterlaceScheme(ictx->wand, LineInterlace); } of = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "of"); if (ngx_strlen(of) > 0) { type = ngx_http_small_light_type(of); if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_NONE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "of is invalid(%s) %s:%d", of, __FUNCTION__, __LINE__); of = (char *)ngx_http_small_light_image_exts[ictx->type - 1]; } else if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_WEBP) { #if defined(MAGICKCORE_WEBP_DELEGATE) ictx->type = type; #else ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "WebP is not supported %s:%d", __FUNCTION__, __LINE__); of = (char *)ngx_http_small_light_image_exts[ictx->type - 1]; #endif } else { ictx->type = type; } MagickSetFormat(ictx->wand, of); ctx->of = ngx_http_small_light_image_types[ictx->type - 1]; } else { MagickSetFormat(ictx->wand, of_orig); ctx->of = ctx->inf; } ctx->content = MagickGetImageBlob(ictx->wand, &sled_image_size); ctx->content_length = sled_image_size; ictx->complete = 1; return NGX_OK; }
MAGICK_NET_EXPORT void DrawingWand_StrokeWidth(DrawingWand *instance, const double value, ExceptionInfo **exception) { DrawSetStrokeWidth(instance, value); MAGICK_NET_SET_DRAW_EXCEPTION; }