int main(int argc, char* argv[]) { MagickWand *mw = NULL; DrawingWand *dw = NULL; PixelWand *fill = NULL; int x,y; MagickWandGenesis(); mw = NewMagickWand(); MagickReadImage(mw,"logo:"); fill = NewPixelWand(); dw = NewDrawingWand(); PixelSetColor(fill,"green"); DrawSetFillColor(dw,fill); for (x=200;x<210;x++) for (y=100;y<110;y++) DrawPoint(dw,x,y); MagickDrawImage(mw,dw); MagickWriteImage(mw,"logo.jpg"); if (dw) dw = DestroyDrawingWand(dw); if (fill) fill = DestroyPixelWand(fill); if (mw) mw = DestroyMagickWand(mw); MagickWandTerminus(); }
static ngx_int_t ngx_http_circle_gif_init(ngx_http_circle_gif_loc_conf_t *cglcf) { u_int i; MagickWand *wand; PixelWand *bg_wand, *fg_wand; DrawingWand *dwand; wand = NewMagickWand(); bg_wand = NewPixelWand(); fg_wand = NewPixelWand(); dwand = NewDrawingWand(); if ((cglcf->circle_templates = malloc((1+radius2index(cglcf->max_radius, cglcf))*sizeof(unsigned char*))) == NULL || (cglcf->circle_sizes = malloc((1+radius2index(cglcf->max_radius, cglcf))*sizeof(size_t))) == NULL) { perror("malloc()"); return NGX_ERROR; } for (i=0;i<=radius2index(cglcf->max_radius, cglcf);i++) { cglcf->circle_templates[i] = ngx_http_circle_gif_template(cglcf->min_radius+i*cglcf->step_radius, &cglcf->circle_sizes[i], wand, bg_wand, fg_wand, dwand); } DestroyMagickWand( wand ); DestroyPixelWand( fg_wand ); DestroyPixelWand( bg_wand ); DestroyDrawingWand( dwand ); return i; }
static void HHVM_METHOD(ImagickDraw, __construct) { auto wand = NewDrawingWand(); if (wand == nullptr) { IMAGICKDRAW_THROW("Failed to create ImagickDraw object"); } else { setWandResource(s_ImagickDraw, Object{this_}, wand); } }
char* get_phone_img(const char *phone_str, size_t *img_size){ if(phone_str == NULL){ return NULL; } MagickWand *m_wand = NULL; PixelWand *p_wand = NULL; DrawingWand *d_wand = NULL; /* Create a wand */ m_wand = NewMagickWand(); p_wand = NewPixelWand(); d_wand = NewDrawingWand(); PixelSetColor(p_wand,"white"); int height = 18; int width = strlen(phone_str) * 130 / 12; MagickNewImage(m_wand, width,height ,p_wand); //draw number PixelSetColor(p_wand,"black"); DrawSetFillColor(d_wand,p_wand); DrawSetFont (d_wand, "Arial" ) ; DrawSetFontSize(d_wand,20); DrawSetStrokeColor(d_wand,p_wand); DrawAnnotation(d_wand,0,height -2,phone_str); MagickDrawImage(m_wand,d_wand); //MagickTrimImage(m_wand,0); //ImageFormat MUST be SET,otherwise,otherwise we will not MagickGetImageBlob properly MagickSetImageFormat(m_wand,"JPEG"); char *p = NULL; char *data = NULL; p = (char *)MagickGetImageBlob(m_wand,img_size); if(p != NULL){ data = (char *)malloc(*img_size); if(data != NULL){ memcpy(data,p,*img_size); }else{ LOG_PRINT(LOG_INFO, "malloc Failed!"); } }else{ LOG_PRINT(LOG_INFO, "MagickGetImageBlob Failed!"); } /* Tidy up */ MagickRelinquishMemory(p); DestroyMagickWand(m_wand); DestroyPixelWand(p_wand); return data; }
/* @description Returns a new pixel wand. */ value nMagick_draw_new() { value v; DrawingWand *draw; draw = NewDrawingWand(); v = alloc_abstract( k_draw, draw ); val_gc( v, nMagick_draw_close ); return v; }
/** * Prints count lines on output with background bg. Lines can be scaled by using factor. * NOTE: This performs some filtering removing lines passing through origin */ void print_lines(char* output, char* bg, LINE_TYPE* lines, sizep_t count, double factor) { MagickWand *mw = NULL; DrawingWand *dw = NULL; PixelWand *pmw = NULL; unsigned long width, semi_width, height, semi_height; MagickWandGenesis(); mw = NewMagickWand(); dw = NewDrawingWand(); pmw = NewPixelWand(); MagickReadImage(mw, bg); width = MagickGetImageWidth(mw); semi_width = ceil(width/2.0); height = MagickGetImageHeight(mw); semi_height = ceil(height/2.0); PixelSetColor(pmw,"red"); DrawSetStrokeColor(dw, pmw); DrawSetStrokeWidth(dw, .5*factor); DrawSetStrokeAntialias(dw, 0); sizep_t n; for(n=0; n<count; n++) { LINE_TYPE cline = lines[n]; double m = -cos(cline.t)/sin(cline.t); double b = cline.r/sin(cline.t); if ((-0.5 < m && m < 0.5) || (-1 < b && b < 1)) continue; // remove lines too horizontal double x0 = - ((long) semi_width); double y0 = x0*m+b; double x1 = ((long) semi_width); double y1 = x1*m+b; // Apply factor x0 *= factor; y0 *= factor; x1 *= factor; y1 *= factor; // Fix coordinates and plot over the image DrawLine(dw, x0+semi_width, height-y0-semi_height, x1+semi_width, height-y1-semi_height); } MagickDrawImage(mw,dw); MagickWriteImage(mw, output); pmw = DestroyPixelWand(pmw); mw = DestroyMagickWand(mw); dw = DestroyDrawingWand(dw); MagickWandTerminus(); }
static PyObject * magick_DrawingWand_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { magick_DrawingWand *self; self = (magick_DrawingWand *)type->tp_alloc(type, 0); if (self != NULL) { self->wand = NewDrawingWand(); if (self->wand == NULL || self->wand < 0) { PyErr_SetString(PyExc_Exception, "Failed to allocate wand."); self->wand = NULL; Py_DECREF(self); return NULL; } } return (PyObject *)self; }
caddr_t bif_im_AnnotateImageBlob (caddr_t * qst, caddr_t * err, state_slot_t ** args) { char * szMe = "IM AnnotateImageBlob"; caddr_t res; caddr_t blob = (caddr_t)bif_arg (qst, args, 0, szMe); long blob_size = box_length (blob) - 1; long x_pos = bif_long_arg (qst, args, 1, szMe); long y_pos = bif_long_arg (qst, args, 2, szMe); caddr_t text = bif_string_arg (qst, args, 3, szMe); int n_args = BOX_ELEMENTS(args); long angle = n_args > 4 ? bif_long_arg (qst, args, 4, szMe) : 0; long f_size = n_args > 5 ? bif_long_arg (qst, args, 5, szMe) : 12; char *text_color = n_args > 6 ? bif_string_arg (qst, args, 6, szMe) : "black" ; dtp_t dtp = DV_TYPE_OF (blob); im_env_t env; im_init (&env, qst, args, "IM AnnotateImageBlob"); if (IS_STRING_DTP (dtp)) blob_size = box_length (blob) - 1; else if (dtp == DV_BIN) blob_size = box_length (blob); else im_leave_with_error (&env, "22023", "IM001", "AnnotateImageBlob needs string or binary as 1-st argument"); im_env_set_blob_ext (&env, 7, -1); env.ime_drawing_wand = NewDrawingWand (); im_read (&env); im_set_background (&env, text_color); DrawSetFillColor (env.ime_drawing_wand, env.ime_background); DrawSetFontSize (env.ime_drawing_wand, f_size); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { env.ime_status = MagickAnnotateImage (env.ime_magick_wand, env.ime_drawing_wand, x_pos, y_pos, angle, text); if (env.ime_status == MagickFalse) im_leave_with_error (&env, "22023", "IM001", "Cannot annotate image"); } res = im_write (&env); im_leave (&env); return res; }
int main(int argc,char **argv) { #define ThrowAPIException(wand) \ { \ description=MagickGetException(wand,&severity); \ (void) FormatLocaleFile(stderr,"%s %s %lu %s\n",GetMagickModule(), \ description); \ description=(char *) MagickRelinquishMemory(description); \ exit(-1); \ } static char CustomOption[] = "custom option", CustomProperty[] = "custom profile"; static unsigned char sRGBProfile[] = { 0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, 0x02, 0x10, 0x00, 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20, 0x07, 0xce, 0x00, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00, 0x31, 0x00, 0x00, 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x48, 0x50, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x33, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x00, 0x6c, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14, 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x14, 0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70, 0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88, 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x86, 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xd4, 0x00, 0x00, 0x00, 0x24, 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x14, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x24, 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x65, 0x77, 0x6c, 0x65, 0x74, 0x74, 0x2d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x72, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa2, 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x99, 0x00, 0x00, 0xb7, 0x85, 0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xcf, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0xfe, 0x00, 0x14, 0x5f, 0x2e, 0x00, 0x10, 0xcf, 0x14, 0x00, 0x03, 0xed, 0xcc, 0x00, 0x04, 0x13, 0x0b, 0x00, 0x03, 0x5c, 0x9e, 0x00, 0x00, 0x00, 0x01, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x09, 0x56, 0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1f, 0xe7, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00, 0x43, 0x52, 0x54, 0x20, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37, 0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72, 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90, 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae, 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb, 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb, 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d, 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59, 0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83, 0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1, 0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1, 0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14, 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b, 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84, 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1, 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00, 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43, 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a, 0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3, 0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20, 0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71, 0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4, 0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c, 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77, 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5, 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37, 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d, 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07, 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74, 0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5, 0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a, 0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2, 0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f, 0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf, 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54, 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc, 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69, 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9, 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e, 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26, 0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3, 0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64, 0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09, 0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3, 0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61, 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13, 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9, 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84, 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43, 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06, 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce, 0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b, 0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c, 0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41, 0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b, 0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa, 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd, 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5, 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2, 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3, 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99, 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94, 0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94, 0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98, 0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1, 0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf, 0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2, 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda, 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7, 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18, 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f, 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b, 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b, 0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1, 0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c, 0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c, 0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91, 0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb, 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a, 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f, 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8, 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37, 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c, 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05, 0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74, 0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8, 0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61, 0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0, 0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64, 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee, 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d, 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12, 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab, 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b, 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0, 0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a, 0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a, 0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00, 0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb, 0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c, 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42, 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f, 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0, 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8, 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95, 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78, 0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61, 0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f, 0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43, 0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d, 0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d, 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43, 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f, 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60, 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78, 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95, 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8, 0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1, 0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11, 0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46, 0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81, 0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2, 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a, 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57, 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab, 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04, 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64, 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca, 0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36, 0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8, 0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20, 0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f, 0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24, 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf, 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40, 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8, 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76, 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a, 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4, 0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75, 0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d, 0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea, 0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae, 0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79, 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a, 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21, 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff, 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3, 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce, 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf, 0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7, 0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5, 0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba, 0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6, 0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8, 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1, 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10, 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36, 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63, 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96, 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0, 0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11, 0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58, 0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7, 0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb, 0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57, 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba, 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff }; char *description, **options, **profiles, **properties; const char *option, *property; DrawingWand *drawing_wand; ExceptionType severity; MagickWand *clone_wand, *magick_wand; PixelIterator *iterator; PixelWand *background, *border, *fill, **pixels; register ssize_t i; unsigned char *profile; unsigned int status; size_t columns, delay, length, number_options, number_profiles, number_properties, number_wands, rows; (void) argc; (void) argv; MagickWandGenesis(); magick_wand=NewMagickWand(); (void) MagickSetSize(magick_wand,640,480); (void) MagickGetSize(magick_wand,&columns,&rows); if ((columns != 640) || (rows != 480)) { (void) FormatLocaleFile(stderr,"Unexpected magick wand size\n"); exit(1); } (void) FormatLocaleFile(stdout,"Reading images...\n"); { char *p, path[MaxTextExtent]; path[0]=0; p=getenv("SRCDIR"); if (p != (char *) NULL) { (void) strcpy(path,p); if (path[strlen(path)-1] != '/') (void) strcat(path,"/"); } (void) strcat(path,"sequence.miff"); status=MagickReadImage(magick_wand,path); } if (status == MagickFalse) ThrowAPIException(magick_wand); if (MagickGetNumberImages(magick_wand) != 5) (void) FormatLocaleFile(stderr,"read %.20g images; expected 5\n", (double) MagickGetNumberImages(magick_wand)); (void) FormatLocaleFile(stdout,"Iterate forward...\n"); MagickResetIterator(magick_wand); while (MagickNextImage(magick_wand) != MagickFalse) (void) FormatLocaleFile(stdout,"index %.20g scene %.20g\n",(double) MagickGetIteratorIndex(magick_wand),(double) MagickGetImageScene(magick_wand)); (void) FormatLocaleFile(stdout,"Iterate reverse...\n"); while (MagickPreviousImage(magick_wand) != MagickFalse) (void) FormatLocaleFile(stdout,"index %.20g scene %.20g\n",(double) MagickGetIteratorIndex(magick_wand),(double) MagickGetImageScene(magick_wand)); (void) FormatLocaleFile(stdout,"Remove scene 1...\n"); (void) MagickSetIteratorIndex(magick_wand,1); clone_wand=MagickGetImage(magick_wand); status=MagickRemoveImage(magick_wand); if (status == MagickFalse) ThrowAPIException(magick_wand); MagickResetIterator(magick_wand); while (MagickNextImage(magick_wand) != MagickFalse) (void) FormatLocaleFile(stdout,"index %.20g scene %.20g\n",(double) MagickGetIteratorIndex(magick_wand),(double) MagickGetImageScene(magick_wand)); (void) FormatLocaleFile(stdout,"Insert scene 1 back in sequence...\n"); (void) MagickSetIteratorIndex(magick_wand,0); status=MagickAddImage(magick_wand,clone_wand); if (status == MagickFalse) ThrowAPIException(magick_wand); MagickResetIterator(magick_wand); while (MagickNextImage(magick_wand) != MagickFalse) (void) FormatLocaleFile(stdout,"index %.20g scene %.20g\n",(double) MagickGetIteratorIndex(magick_wand),(double) MagickGetImageScene(magick_wand)); (void) FormatLocaleFile(stdout,"Set scene 2 to scene 1...\n"); (void) MagickSetIteratorIndex(magick_wand,2); status=MagickSetImage(magick_wand,clone_wand); clone_wand=DestroyMagickWand(clone_wand); if (status == MagickFalse) ThrowAPIException(magick_wand); MagickResetIterator(magick_wand); while (MagickNextImage(magick_wand) != MagickFalse) (void) FormatLocaleFile(stdout,"index %.20g scene %.20g\n",(double) MagickGetIteratorIndex(magick_wand),(double) MagickGetImageScene(magick_wand)); (void) FormatLocaleFile(stdout,"Apply image processing options...\n"); status=MagickCropImage(magick_wand,60,60,10,10); if (status == MagickFalse) ThrowAPIException(magick_wand); MagickResetIterator(magick_wand); background=NewPixelWand(); status=PixelSetColor(background,"#000000"); if (status == MagickFalse) ThrowAPIException(magick_wand); status=MagickRotateImage(magick_wand,background,90.0); if (status == MagickFalse) ThrowAPIException(magick_wand); border=NewPixelWand(); (void) PixelSetColor(background,"green"); (void) PixelSetColor(border,"black"); status=MagickFloodfillPaintImage(magick_wand,CompositeChannels,background, 0.01*QuantumRange,border,0,0,MagickFalse); if (status == MagickFalse) ThrowAPIException(magick_wand); background=DestroyPixelWand(background); border=DestroyPixelWand(border); drawing_wand=NewDrawingWand(); (void) PushDrawingWand(drawing_wand); (void) DrawRotate(drawing_wand,45); (void) DrawSetFontSize(drawing_wand,18); fill=NewPixelWand(); (void) PixelSetColor(fill,"green"); (void) DrawSetFillColor(drawing_wand,fill); fill=DestroyPixelWand(fill); (void) DrawAnnotation(drawing_wand,15,5,(const unsigned char *) "Magick"); (void) PopDrawingWand(drawing_wand); (void) MagickSetIteratorIndex(magick_wand,1); status=MagickDrawImage(magick_wand,drawing_wand); if (status == MagickFalse) ThrowAPIException(magick_wand); status=MagickAnnotateImage(magick_wand,drawing_wand,70,5,90,"Image"); if (status == MagickFalse) ThrowAPIException(magick_wand); drawing_wand=DestroyDrawingWand(drawing_wand); { unsigned char pixels[27], primary_colors[27] = { 0, 0, 0, 0, 0, 255, 0, 255, 0, 0, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0, 255, 255, 255, 0, 128, 128, 128, }; (void) MagickSetIteratorIndex(magick_wand,2); status=MagickImportImagePixels(magick_wand,10,10,3,3,"RGB",CharPixel, primary_colors); if (status == MagickFalse) ThrowAPIException(magick_wand); status=MagickExportImagePixels(magick_wand,10,10,3,3,"RGB",CharPixel, pixels); if (status == MagickFalse) ThrowAPIException(magick_wand); for (i=0; i < 9; i++) if (pixels[i] != primary_colors[i]) { (void) FormatLocaleFile(stderr, "Get pixels does not match set pixels\n"); exit(1); } } (void) MagickSetIteratorIndex(magick_wand,3); status=MagickResizeImage(magick_wand,50,50,UndefinedFilter,1.0); if (status == MagickFalse) ThrowAPIException(magick_wand); MagickResetIterator(magick_wand); while (MagickNextImage(magick_wand) != MagickFalse) { (void) MagickSetImageDepth(magick_wand,8); (void) MagickSetImageCompression(magick_wand,RLECompression); } MagickResetIterator(magick_wand); (void) MagickSetIteratorIndex(magick_wand,4); (void) FormatLocaleFile(stdout, "Utilitize pixel iterator to draw diagonal...\n"); iterator=NewPixelIterator(magick_wand); if (iterator == (PixelIterator *) NULL) ThrowAPIException(magick_wand); pixels=PixelGetNextIteratorRow(iterator,&number_wands); for (i=0; pixels != (PixelWand **) NULL; i++) { (void) PixelSetColor(pixels[i],"#224466"); (void) PixelSyncIterator(iterator); pixels=PixelGetNextIteratorRow(iterator,&number_wands); } (void) PixelSyncIterator(iterator); iterator=DestroyPixelIterator(iterator); (void) FormatLocaleFile(stdout,"Write to wandtest_out.miff...\n"); status=MagickWriteImages(magick_wand,"wandtest_out.miff",MagickTrue); if (status == MagickFalse) ThrowAPIException(magick_wand); (void) FormatLocaleFile(stdout, "Change image format from \"MIFF\" to \"GIF\"...\n"); status=MagickSetImageFormat(magick_wand,"GIF"); if (status == MagickFalse) ThrowAPIException(magick_wand); (void) FormatLocaleFile(stdout,"Set delay between frames to %d seconds...\n", WandDelay); status=MagickSetImageDelay(magick_wand,100*WandDelay); if (status == MagickFalse) ThrowAPIException(magick_wand); delay=MagickGetImageDelay(magick_wand); if (delay != (100*WandDelay)) { (void) FormatLocaleFile(stderr,"Get delay does not match set delay\n"); exit(1); } (void) FormatLocaleFile(stdout,"Write to wandtest_out_0.gif...\n"); status=MagickWriteImages(magick_wand,"wandtest_out.gif",MagickTrue); if (status == MagickFalse) ThrowAPIException(magick_wand); (void) FormatLocaleFile(stdout,"Set, list, get, and delete wand option...\n"); status=MagickSetOption(magick_wand,"wand:custom-option",CustomOption); if (status == MagickFalse) ThrowAPIException(magick_wand); option=MagickGetOption(magick_wand,"wand:custom-option"); if ((option == (const char *) NULL) || (strlen(option) != strlen(CustomOption)) || (memcmp(option,CustomOption,strlen(option)) != 0)) { (void) FormatLocaleFile(stderr,"Option does not match\n"); exit(1); } options=MagickGetOptions(magick_wand,"*",&number_options); if (options != (char **) NULL) { for (i=0; i < (ssize_t) number_options; i++) { (void) FormatLocaleFile(stdout," %s\n",options[i]); options[i]=(char *) MagickRelinquishMemory(options[i]); } options=(char **) MagickRelinquishMemory(options); } status=MagickDeleteOption(magick_wand,"wand:custom-option"); if (status == MagickFalse) ThrowAPIException(magick_wand); (void) FormatLocaleFile(stdout, "Set, list, get, and delete wand property...\n"); status=MagickSetImageProperty(magick_wand,"wand:custom-property", CustomProperty); if (status == MagickFalse) ThrowAPIException(magick_wand); property=MagickGetImageProperty(magick_wand,"wand:custom-property"); if ((property == (const char *) NULL) || (strlen(property) != strlen(CustomProperty)) || (memcmp(property,CustomProperty,strlen(property)) != 0)) { (void) FormatLocaleFile(stderr,"Property does not match\n"); exit(1); } properties=MagickGetImageProperties(magick_wand,"*",&number_properties); if (properties != (char **) NULL) { for (i=0; i < (ssize_t) number_properties; i++) { (void) FormatLocaleFile(stdout," %s\n",properties[i]); properties[i]=(char *) MagickRelinquishMemory(properties[i]); } properties=(char **) MagickRelinquishMemory(properties); } status=MagickDeleteImageProperty(magick_wand,"wand:custom-property"); if (status == MagickFalse) ThrowAPIException(magick_wand); (void) FormatLocaleFile(stdout, "Set, list, get, and remove sRGB color profile...\n"); status=MagickSetImageProfile(magick_wand,"sRGB",sRGBProfile, sizeof(sRGBProfile)); if (status == MagickFalse) ThrowAPIException(magick_wand); profile=(unsigned char *) MagickGetImageProfile(magick_wand,"sRGB",&length); if ((profile == (unsigned char *) NULL) || (length != sizeof(sRGBProfile)) || (memcmp(profile,sRGBProfile,length) != 0)) { (void) FormatLocaleFile(stderr,"Profile does not match\n"); exit(1); } profile=(unsigned char *) MagickRelinquishMemory(profile); profiles=MagickGetImageProfiles(magick_wand,"*",&number_profiles); if (profiles != (char **) NULL) { for (i=0; i < (ssize_t) number_profiles; i++) { (void) FormatLocaleFile(stdout," %s\n",profiles[i]); profiles[i]=(char *) MagickRelinquishMemory(profiles[i]); } profiles=(char **) MagickRelinquishMemory(profiles); } profile=(unsigned char *) MagickRemoveImageProfile(magick_wand,"sRGB", &length); if ((profile == (unsigned char *) NULL) || (length != sizeof(sRGBProfile)) || (memcmp(profile,sRGBProfile,length) != 0)) { (void) FormatLocaleFile(stderr,"Profile does not match\n"); exit(1); } profile=(unsigned char *) MagickRelinquishMemory(profile); magick_wand=DestroyMagickWand(magick_wand); (void) FormatLocaleFile(stdout,"Wand tests pass.\n"); return(0); }
void test_wand(void) { MagickWand *magick_wand = NULL; MagickWand *c_wand = NULL; DrawingWand *d_wand = NULL; PixelWand *p_wand = NULL; // Used for text effect #3 double dargs[1] = {120.}; // Used for text effect #5 double d_args[8] = { -0.02,0.0, 0.0,1.02, 0.0,0.0, -0.5,1.9 }; MagickWandGenesis(); // Text effect 1 - shadow effect using MagickShadowImage // This is derived from Anthony's Soft Shadow effect // convert -size 300x100 xc:none -font Candice -pointsize 72 \ // -fill white -stroke black -annotate +25+65 'Anthony' \ // \( +clone -background navy -shadow 70x4+5+5 \) +swap \ // -background lightblue -flatten -trim +repage font_shadow_soft.jpg //NOTE - if an image has a transparent background, adding a border of any colour other // than "none" will remove all the transparency and replace it with the border's colour magick_wand = NewMagickWand(); d_wand = NewDrawingWand(); p_wand = NewPixelWand(); PixelSetColor(p_wand,"none"); // Create a new transparent image MagickNewImage(magick_wand,350,100,p_wand); // Set up a 72 point white font PixelSetColor(p_wand,"white"); DrawSetFillColor(d_wand,p_wand); DrawSetFont (d_wand, "Verdana-Bold-Italic" ) ; DrawSetFontSize(d_wand,72); // Add a black outline to the text PixelSetColor(p_wand,"black"); DrawSetStrokeColor(d_wand,p_wand); // Turn antialias on - not sure this makes a difference DrawSetTextAntialias(d_wand,MagickTrue); // Now draw the text DrawAnnotation(d_wand,25,65,(const unsigned char *)"Magick"); // Draw the image on to the magick_wand MagickDrawImage(magick_wand,d_wand); // Trim the image down to include only the text MagickTrimImage(magick_wand,0); // equivalent to the command line +repage MagickResetImagePage(magick_wand,""); // Make a copy of the text image c_wand = CloneMagickWand(magick_wand); // Set the background colour to blue for the shadow PixelSetColor(p_wand,"blue"); MagickSetImageBackgroundColor(magick_wand,p_wand); // Opacity is a real number indicating (apparently) percentage MagickShadowImage(magick_wand,70,4,5,5); // Composite the text on top of the shadow MagickCompositeImage(magick_wand,c_wand,OverCompositeOp,5,5); if(c_wand)c_wand = DestroyMagickWand(c_wand); c_wand = NewMagickWand(); // Create a new image the same size as the text image and put a solid colour // as its background PixelSetColor(p_wand,"rgb(125,215,255)"); MagickNewImage(c_wand,MagickGetImageWidth(magick_wand),MagickGetImageHeight(magick_wand),p_wand); // Now composite the shadowed text over the plain background MagickCompositeImage(c_wand,magick_wand,OverCompositeOp,0,0); // and write the result MagickWriteImage(c_wand,"text_shadow.png"); /* Clean up */ if(magick_wand)magick_wand = DestroyMagickWand(magick_wand); if(c_wand)c_wand = DestroyMagickWand(c_wand); if(d_wand)d_wand = DestroyDrawingWand(d_wand); if(p_wand)p_wand = DestroyPixelWand(p_wand); // Text effect 2 - tiled text using the builtin checkerboard pattern // Anthony's Tiled Font effect // convert -size 320x100 xc:lightblue -font Candice -pointsize 72 \ // -tile pattern:checkerboard -annotate +28+68 'Anthony' \ // font_tile.jpg magick_wand = NewMagickWand(); d_wand = NewDrawingWand(); p_wand = NewPixelWand(); set_tile_pattern(d_wand,"#check","pattern:checkerboard"); PixelSetColor(p_wand,"lightblue"); // Create a new transparent image MagickNewImage(magick_wand,320,100,p_wand); // Set up a 72 point font DrawSetFont (d_wand, "Verdana-Bold-Italic" ) ; DrawSetFontSize(d_wand,72); // Now draw the text DrawAnnotation(d_wand,28,68,(const unsigned char *)"Magick"); // Draw the image on to the magick_wand MagickDrawImage(magick_wand,d_wand); // Trim the image MagickTrimImage(magick_wand,0); // Add a transparent border PixelSetColor(p_wand,"lightblue"); MagickBorderImage(magick_wand,p_wand,5,5); // and write it MagickWriteImage(magick_wand,"text_pattern.png"); /* Clean up */ if(magick_wand)magick_wand = DestroyMagickWand(magick_wand); if(d_wand)d_wand = DestroyDrawingWand(d_wand); if(p_wand)p_wand = DestroyPixelWand(p_wand); // Text effect 3 - arc font (similar to http://www.imagemagick.org/Usage/fonts/#arc) //convert -size 320x100 xc:lightblue -font Candice -pointsize 72 \ // -annotate +25+65 'Anthony' -distort Arc 120 \ // -trim +repage -bordercolor lightblue -border 10 font_arc.jpg magick_wand = NewMagickWand(); d_wand = NewDrawingWand(); p_wand = NewPixelWand(); // Create a 320x100 lightblue canvas PixelSetColor(p_wand,"lightblue"); MagickNewImage(magick_wand,320,100,p_wand); // Set up a 72 point font DrawSetFont (d_wand, "Verdana-Bold-Italic" ) ; DrawSetFontSize(d_wand,72); // Now draw the text DrawAnnotation(d_wand,25,65,(const unsigned char *)"Magick"); // Draw the image on to the magick_wand MagickDrawImage(magick_wand,d_wand); MagickDistortImage(magick_wand,ArcDistortion,1,dargs,MagickFalse); // Trim the image MagickTrimImage(magick_wand,0); // Add the border PixelSetColor(p_wand,"lightblue"); MagickBorderImage(magick_wand,p_wand,10,10); // and write it MagickWriteImage(magick_wand,"text_arc.png"); /* Clean up */ if(magick_wand)magick_wand = DestroyMagickWand(magick_wand); if(d_wand)d_wand = DestroyDrawingWand(d_wand); if(p_wand)p_wand = DestroyPixelWand(p_wand); // Text effect 4 - bevelled font http://www.imagemagick.org/Usage/fonts/#bevel // convert -size 320x100 xc:black -font Candice -pointsize 72 \ // -fill white -annotate +25+65 'Anthony' \ // -shade 140x60 font_beveled.jpg magick_wand = NewMagickWand(); d_wand = NewDrawingWand(); p_wand = NewPixelWand(); // Create a 320x100 canvas PixelSetColor(p_wand,"gray"); MagickNewImage(magick_wand,320,100,p_wand); // Set up a 72 point font DrawSetFont (d_wand, "Verdana-Bold-Italic" ) ; DrawSetFontSize(d_wand,72); // Set up a 72 point white font PixelSetColor(p_wand,"white"); DrawSetFillColor(d_wand,p_wand); // Now draw the text DrawAnnotation(d_wand,25,65,(const unsigned char *)"Magick"); // Draw the image on to the magick_wand MagickDrawImage(magick_wand,d_wand); // the "gray" parameter must be true to get the effect shown on Anthony's page MagickShadeImage(magick_wand,MagickTrue,140,60); #ifdef COLORIZE PixelSetColor(p_wand,"yellow"); DrawSetFillColor(d_wand,p_wand); cp_wand = NewPixelWand(); PixelSetColor(cp_wand,"gold"); MagickColorizeImage(magick_wand,p_wand,cp_wand); #endif // and write it MagickWriteImage(magick_wand,"text_bevel.png"); /* Clean up */ if(magick_wand)magick_wand = DestroyMagickWand(magick_wand); if(d_wand)d_wand = DestroyDrawingWand(d_wand); if(p_wand)p_wand = DestroyPixelWand(p_wand); #ifdef COLORIZE if(cp_wand)cp_wand = DestroyPixelWand(cp_wand); #endif // Text effect 5 and 6 - Plain text and then Barrel distortion // This one uses d_args magick_wand = NewMagickWand(); d_wand = NewDrawingWand(); p_wand = NewPixelWand(); // Create a 320x100 transparent canvas PixelSetColor(p_wand,"none"); MagickNewImage(magick_wand,320,100,p_wand); // Set up a 72 point font DrawSetFont (d_wand, "Verdana-Bold-Italic" ) ; DrawSetFontSize(d_wand,72); // Now draw the text DrawAnnotation(d_wand,25,65,(const unsigned char *)"Magick"); // Draw the image on to the magick_wand MagickDrawImage(magick_wand,d_wand); MagickWriteImage(magick_wand,"text_plain.png"); // Trim the image MagickTrimImage(magick_wand,0); // Add the border PixelSetColor(p_wand,"none"); MagickBorderImage(magick_wand,p_wand,10,10); // MagickSetImageMatte(magick_wand,MagickTrue); // MagickSetImageVirtualPixelMethod(magick_wand,TransparentVirtualPixelMethod); // d_args[0] = 0.1;d_args[1] = -0.25;d_args[2] = -0.25; [3] += .1 // The first value should be positive. If it is negative the image is *really* distorted d_args[0] = 0.0; d_args[1] = 0.0; d_args[2] = 0.5; // d_args[3] should normally be chosen such the sum of all 4 values is 1 // so that the result is the same size as the original // You can override the sum with a different value // If the sum is greater than 1 the resulting image will be smaller than the original d_args[3] = 1 - (d_args[0] + d_args[1] + d_args[2]); // Make the result image smaller so that it isn't as likely // to overflow the edges // d_args[3] += 0.1; // 0.0,0.0,0.5,0.5,0.0,0.0,-0.5,1.9 d_args[3] = 0.5; d_args[4] = 0.0; d_args[5] = 0.0; d_args[6] = -0.5; d_args[7] = 1.9; // DON'T FORGET to set the correct number of arguments here MagickDistortImage(magick_wand,BarrelDistortion,8,d_args,MagickTrue); // MagickResetImagePage(magick_wand,""); // Trim the image again MagickTrimImage(magick_wand,0); // Add the border PixelSetColor(p_wand,"none"); MagickBorderImage(magick_wand,p_wand,10,10); // and write it MagickWriteImage(magick_wand,"text_barrel.png"); /* Clean up */ if(magick_wand)magick_wand = DestroyMagickWand(magick_wand); if(d_wand)d_wand = DestroyDrawingWand(d_wand); if(p_wand)p_wand = DestroyPixelWand(p_wand); // Text effect 7 - Polar distortion // This one uses d_args[0] magick_wand = NewMagickWand(); d_wand = NewDrawingWand(); p_wand = NewPixelWand(); // Create a 320x200 transparent canvas PixelSetColor(p_wand,"none"); MagickNewImage(magick_wand,320,200,p_wand); // Set up a 72 point font DrawSetFont (d_wand, "Verdana-Bold-Italic" ) ; DrawSetFontSize(d_wand,72); // Now draw the text DrawAnnotation(d_wand,25,65,(const unsigned char *)"Magick"); // Draw the image on to the magick_wand MagickDrawImage(magick_wand,d_wand); d_args[0] = 0.0; // DON'T FORGET to set the correct number of arguments here MagickDistortImage(magick_wand,PolarDistortion,1,d_args,MagickTrue); // MagickResetImagePage(magick_wand,""); // Trim the image again MagickTrimImage(magick_wand,0); // Add the border PixelSetColor(p_wand,"none"); MagickBorderImage(magick_wand,p_wand,10,10); // and write it MagickWriteImage(magick_wand,"text_polar.png"); /* Clean up */ if(magick_wand)magick_wand = DestroyMagickWand(magick_wand); if(d_wand)d_wand = DestroyDrawingWand(d_wand); if(p_wand)p_wand = DestroyPixelWand(p_wand); // Text effect 8 - Shepard's distortion // This one uses d_args[0] magick_wand = NewMagickWand(); d_wand = NewDrawingWand(); p_wand = NewPixelWand(); // Create a 320x200 transparent canvas PixelSetColor(p_wand,"none"); MagickNewImage(magick_wand,640,480,p_wand); // Set up a 72 point font DrawSetFont (d_wand, "Verdana-Bold-Italic" ) ; DrawSetFontSize(d_wand,72); // Now draw the text DrawAnnotation(d_wand,50,240,(const unsigned char *)"Magick Rocks"); // Draw the image on to the magick_wand MagickDrawImage(magick_wand,d_wand); d_args[0] = 150.0; d_args[1] = 190.0; d_args[2] = 100.0; d_args[3] = 290.0; d_args[4] = 500.0; d_args[5] = 200.0; d_args[6] = 430.0; d_args[7] = 130.0; // DON'T FORGET to set the correct number of arguments here MagickDistortImage(magick_wand,ShepardsDistortion,8,d_args,MagickTrue); // Trim the image MagickTrimImage(magick_wand,0); // Add the border PixelSetColor(p_wand,"none"); MagickBorderImage(magick_wand,p_wand,10,10); // and write it MagickWriteImage(magick_wand,"text_shepards.png"); /* Clean up */ if(magick_wand)magick_wand = DestroyMagickWand(magick_wand); if(d_wand)d_wand = DestroyDrawingWand(d_wand); if(p_wand)p_wand = DestroyPixelWand(p_wand); MagickWandTerminus(); }
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); DrawSetFillAlpha(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); }
// output_data apr_status_t small_light_filter_imagemagick_output_data( ap_filter_t *f, apr_bucket_brigade *bb, void *v_ctx, apr_bucket *e) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, "small_light_filter_imagemagick_output_data"); request_rec *r = f->r; small_light_module_ctx_t* ctx = (small_light_module_ctx_t*)v_ctx; small_light_module_imagemagick_ctx_t *lctx = ctx->lctx; struct timeval t2, t21, t22, t23, t3; MagickBooleanType status = MagickFalse; // check data received. if (lctx->image == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "no data received."); r->status = HTTP_INTERNAL_SERVER_ERROR; return APR_EGENERAL; } // start image modifing. gettimeofday(&t2, NULL); small_light_image_size_t sz; small_light_calc_image_size(&sz, r, ctx, 10000.0, 10000.0); // init wand small_light_filter_imagemagick_output_data_init(); lctx->wand = NewMagickWand(); // prepare. if (sz.jpeghint_flg != 0) { char *jpeg_size_opt = (char *)apr_psprintf(r->pool, "%dx%d", (int)sz.dw, (int)sz.dh); MagickSetOption(lctx->wand, "jpeg:size", jpeg_size_opt); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "MagickSetOption(jpeg:size, %s)", jpeg_size_opt); } // load image. gettimeofday(&t21, NULL); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "MagickReadImageBlob"); status = MagickReadImageBlob(lctx->wand, (void *)lctx->image, lctx->image_len); if (status == MagickFalse) { small_light_filter_imagemagick_output_data_fini(ctx); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "couldn't read image"); r->status = HTTP_INTERNAL_SERVER_ERROR; return APR_EGENERAL; } // calc size. gettimeofday(&t22, NULL); double iw = (double)MagickGetImageWidth(lctx->wand); double ih = (double)MagickGetImageHeight(lctx->wand); small_light_calc_image_size(&sz, r, ctx, iw, ih); // pass through. if (sz.pt_flg != 0) { small_light_filter_imagemagick_output_data_fini(ctx); apr_bucket *b = apr_bucket_pool_create(lctx->image, lctx->image_len, r->pool, ctx->bb->bucket_alloc); APR_BRIGADE_INSERT_TAIL(ctx->bb, b); APR_BRIGADE_INSERT_TAIL(ctx->bb, apr_bucket_eos_create(ctx->bb->bucket_alloc)); return ap_pass_brigade(f->next, ctx->bb); } // crop, scale. status = MagickTrue; if (sz.scale_flg != 0) { char *crop_geo = (char *)apr_psprintf(r->pool, "%f!x%f!+%f+%f", sz.sw, sz.sh, sz.sx, sz.sy); char *size_geo = (char *)apr_psprintf(r->pool, "%f!x%f!", sz.dw, sz.dh); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "MagickTransformImage(wand, ""%s"", ""%s"")", crop_geo, size_geo); MagickWand *trans_wand; trans_wand = MagickTransformImage(lctx->wand, crop_geo, size_geo); if (trans_wand == NULL || trans_wand == lctx->wand) { small_light_filter_imagemagick_output_data_fini(ctx); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "MagickTransformImage failed"); r->status = HTTP_INTERNAL_SERVER_ERROR; return APR_EGENERAL; } DestroyMagickWand(lctx->wand); lctx->wand = trans_wand; } else { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "no scale"); } // create canvas then draw image to the canvas. if (sz.cw > 0.0 && sz.ch > 0.0) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "NewMagickWand()"); MagickWand *canvas_wand = NewMagickWand(); PixelWand *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); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "MagickNewImage(canvas_wand, %f, %f, bgcolor)", sz.cw, sz.ch); status = MagickNewImage(canvas_wand, sz.cw, sz.ch, canvas_color); DestroyPixelWand(canvas_color); if (status == MagickFalse) { small_light_filter_imagemagick_output_data_fini(ctx); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "MagickNewImage(canvas_wand, %f, %f, bgcolor) failed", sz.cw, sz.ch); r->status = HTTP_INTERNAL_SERVER_ERROR; return APR_EGENERAL; } ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "MagickCompositeImage(canvas_wand, wand, AtopCompositeOp, %f, %f)", sz.dx, sz.dy); status = MagickCompositeImage(canvas_wand, lctx->wand, AtopCompositeOp, sz.dx, sz.dy); if (status == MagickFalse) { small_light_filter_imagemagick_output_data_fini(ctx); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "MagickCompositeImage(canvas_wand, wand, AtopCompositeOp, %f, %f) failed", sz.dx, sz.dy); r->status = HTTP_INTERNAL_SERVER_ERROR; return APR_EGENERAL; } DestroyMagickWand(lctx->wand); lctx->wand = canvas_wand; } // effects. char *unsharp = (char *)apr_table_get(ctx->prm, "unsharp"); if (unsharp) { GeometryInfo geo; ParseGeometry(unsharp, &geo); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "MagickUnsharpMaskImage(wand, %f, %f, %f, %f)", geo.rho, geo.sigma, geo.xi, geo.psi); status = MagickUnsharpMaskImage(lctx->wand, geo.rho, geo.sigma, geo.xi, geo.psi); if (status == MagickFalse) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unsharp failed"); } } char *sharpen = (char *)apr_table_get(ctx->prm, "sharpen"); if (sharpen) { GeometryInfo geo; ParseGeometry(sharpen, &geo); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "MagickSharpenImage(wand, %f, %f)", geo.rho, geo.sigma); status = MagickSharpenImage(lctx->wand, geo.rho, geo.sigma); if (status == MagickFalse) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "sharpen failed"); } } char *blur = (char *)apr_table_get(ctx->prm, "blur"); if (blur) { GeometryInfo geo; ParseGeometry(blur, &geo); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "MagickBlurImage(wand, %f, %f)", geo.rho, geo.sigma); status = MagickBlurImage(lctx->wand, geo.rho, geo.sigma); if (status == MagickFalse) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "blur failed"); } } // border. if (sz.bw > 0.0 || sz.bh > 0.0) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "draw border"); DrawingWand *border_wand = NewDrawingWand(); PixelWand *border_color; 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); 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); MagickDrawImage(lctx->wand, border_wand); DestroyPixelWand(border_color); DestroyDrawingWand(border_wand); } gettimeofday(&t23, NULL); // set params. double q = small_light_parse_double(r, (char *)apr_table_get(ctx->prm, "q")); if (q > 0.0) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "MagickSetImageComressionQualty(wand, %f)", q); MagickSetImageCompressionQuality(lctx->wand, q); } char *of = (char *)apr_table_get(ctx->prm, "of"); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "MagickSetFormat(wand, '%s')", of); MagickSetFormat(lctx->wand, of); // get small_lighted image as binary. unsigned char *canvas_buff; const char *sled_image; size_t sled_image_size; canvas_buff = MagickGetImageBlob(lctx->wand, &sled_image_size); sled_image = (const char *)apr_pmemdup(r->pool, canvas_buff, sled_image_size); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "sled_image_size = %d", sled_image_size); // free buffer and wand. MagickRelinquishMemory(canvas_buff); small_light_filter_imagemagick_output_data_fini(ctx); // insert new bucket to bucket brigade. apr_bucket *b = apr_bucket_pool_create(sled_image, sled_image_size, r->pool, ctx->bb->bucket_alloc); APR_BRIGADE_INSERT_TAIL(ctx->bb, b); // insert eos to bucket brigade. APR_BRIGADE_INSERT_TAIL(ctx->bb, apr_bucket_eos_create(ctx->bb->bucket_alloc)); // set correct Content-Type and Content-Length. char *cont_type = apr_psprintf(r->pool, "image/%s", of); ap_set_content_type(r, cont_type); ap_set_content_length(r, sled_image_size); // end. gettimeofday(&t3, NULL); // http header. int info = small_light_parse_int(r, (char *)apr_table_get(ctx->prm, "info")); if (info != SMALL_LIGHT_INT_INVALID_VALUE && info != 0) { char *info = (char *)apr_psprintf(r->pool, "transfer=%ldms, modify image=%ldms (load=%ldms, scale=%ldms, save=%ldms)", small_light_timeval_diff(&ctx->t, &t2) / 1000L, small_light_timeval_diff(&t2, &t3) / 1000L, small_light_timeval_diff(&t21, &t22) / 1000L, small_light_timeval_diff(&t22, &t23) / 1000L, small_light_timeval_diff(&t23, &t3) / 1000L ); ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "uri=%s, info=%s)", r->unparsed_uri, info); apr_table_setn(r->headers_out, "X-SmallLight-Description", info); } return ap_pass_brigade(f->next, ctx->bb); }
void generate(char *source_image_path, char *sink_image_path, char *top_text, char *bottom_text) { MagickWand *wand = NULL; DrawingWand *drawing_wand = NULL; PixelWand *pixel_wand = NULL; MagickWandGenesis(); wand = NewMagickWand(); drawing_wand = NewDrawingWand(); pixel_wand = NewPixelWand(); // read base image MagickReadImage(wand, source_image_path); ssize_t width; ssize_t pointsize; ssize_t stroke_width; double scale; char formatted_text[100] = { '\0' }; // Scale text width = MagickGetImageWidth(wand); scale = scaleText(top_text, formatted_text); pointsize = width / 5.0; stroke_width = pointsize / 30.0; // Draw top text PixelSetColor(pixel_wand, "white"); DrawSetFillColor(drawing_wand, pixel_wand); DrawSetFont(drawing_wand, "Impact"); DrawSetFontSize(drawing_wand, pointsize * scale); DrawSetFontWeight(drawing_wand, 700); DrawSetGravity(drawing_wand, NorthGravity); // Add a black outline to the text PixelSetColor(pixel_wand, "black"); DrawSetStrokeWidth(drawing_wand, stroke_width * scale); DrawSetStrokeColor(drawing_wand, pixel_wand); // Turn on Anitalias DrawSetTextAntialias(drawing_wand, MagickTrue); // Draw the text DrawAnnotation(drawing_wand, 0, 0, (const unsigned char *)formatted_text); if (bottom_text) { char formatted_bottom_text[100] = { '\0' }; // Scale text width = MagickGetImageWidth(wand); scale = scaleText(bottom_text, formatted_bottom_text); pointsize = width / 5.0; stroke_width = pointsize / 30.0; // Draw bottom text PixelSetColor(pixel_wand, "white"); DrawSetFillColor(drawing_wand, pixel_wand); DrawSetFont(drawing_wand, "Impact"); DrawSetFontSize(drawing_wand, pointsize * scale); DrawSetFontWeight(drawing_wand, 700); DrawSetGravity(drawing_wand, SouthGravity); // Add a black outline to the text PixelSetColor(pixel_wand, "black"); DrawSetStrokeWidth(drawing_wand, stroke_width * scale); DrawSetStrokeColor(drawing_wand, pixel_wand); // Turn on Anitalias DrawSetTextAntialias(drawing_wand, MagickTrue); // Draw the text DrawAnnotation(drawing_wand, 0, 0, (const unsigned char *)formatted_bottom_text); } // Draw the image on the magick wand MagickDrawImage(wand, drawing_wand); // Write the image if (sink_image_path) { MagickWriteImage(wand, sink_image_path); } else { MagickWriteImageFile(wand, stdout); } // Clean up if(pixel_wand) pixel_wand = DestroyPixelWand(pixel_wand); if(drawing_wand) drawing_wand = DestroyDrawingWand(drawing_wand); if(wand) wand = DestroyMagickWand(wand); MagickWandTerminus(); }
/* gcc -o imagick imagick-landscape-3d.c -Wall -Werror -I/usr/include/ImageMagick -lMagickWand */ int main() { MagickWand *mw, *canvas; PixelWand *pw; DrawingWand *line; size_t w, h, offset; int x, y, r, g, b, grey, lh; MagickBooleanType mbt; MagickWandGenesis(); /* startup */ mw = NewMagickWand(); mbt = MagickReadImage(mw, PNG_IN_FILE); assert(mbt == MagickTrue); w = MagickGetImageWidth(mw); h = MagickGetImageHeight(mw); pw = NewPixelWand(); PixelSetColor(pw, "transparent"); mbt = MagickShearImage(mw, pw, 45, 0); assert(mbt == MagickTrue); w = MagickGetImageWidth(mw); h = MagickGetImageHeight(mw); mbt = MagickScaleImage(mw, w, h/2); assert(mbt = MagickTrue); w = MagickGetImageWidth(mw); h = MagickGetImageHeight(mw); canvas = NewMagickWand(); MagickGetImagePixelColor(mw, 0, 0, pw); MagickNewImage(canvas, w, h*2, pw); offset = h; for (x = 0; x < w; ++x) { line = NewDrawingWand(); lh = 0; for (y = h-1; y >= 0; --y) { if (MagickGetImagePixelColor(mw, x, y, pw) == MagickFalse) continue; r = 255 * PixelGetRed(pw); g = 255 * PixelGetGreen(pw); b = 255 * PixelGetBlue(pw); grey = (r + g + b)/5; if (lh == 0 || lh < grey) { DrawSetFillColor(line, pw); DrawSetStrokeColor(line, pw); DrawLine(line, x, y + offset - lh, x, y - grey + offset); lh = grey; } lh--; } MagickDrawImage(canvas, line); DestroyDrawingWand(line); } MagickScaleImage(canvas, w - h, h * 2); mbt = MagickSetImageFormat(canvas, "png"); assert(mbt == MagickTrue); mbt = MagickWriteImage(canvas, PNG_OUT_FILE); assert(mbt == MagickTrue); pw = DestroyPixelWand(pw); mw = DestroyMagickWand(mw); canvas = DestroyMagickWand(canvas); MagickWandTerminus(); /* shutdown */ return 0; }
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; }
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; }