/** * @brief add_info Added image info to the request * * @param im The image struct * @param req The evhtp request */ void add_info(MagickWand *im, evhtp_request_t *req) { MagickSizeType size = MagickGetImageSize(im); unsigned long width = MagickGetImageWidth(im); unsigned long height = MagickGetImageHeight(im); size_t quality = MagickGetImageCompressionQuality(im); quality = (quality == 0 ? 100 : quality); char *format = MagickGetImageFormat(im); //{"ret":true,"info":{"size":195135,"width":720,"height":480,"quality":75,"format":"JPEG"}} cJSON *j_ret = cJSON_CreateObject(); cJSON *j_ret_info = cJSON_CreateObject(); cJSON_AddBoolToObject(j_ret, "ret", 1); cJSON_AddNumberToObject(j_ret_info, "size", size); cJSON_AddNumberToObject(j_ret_info, "width", width); cJSON_AddNumberToObject(j_ret_info, "height", height); cJSON_AddNumberToObject(j_ret_info, "quality", quality); cJSON_AddStringToObject(j_ret_info, "format", format); cJSON_AddItemToObject(j_ret, "info", j_ret_info); char *ret_str_unformat = cJSON_PrintUnformatted(j_ret); LOG_PRINT(LOG_DEBUG, "ret_str_unformat: %s", ret_str_unformat); evbuffer_add_printf(req->buffer_out, "%s", ret_str_unformat); cJSON_Delete(j_ret); free(ret_str_unformat); free(format); }
static void optimize_image(MagickWand *mw, const char *src, const char *dst, size_t size_in, unsigned char *blob_in, const struct imgmin_options *opt) { MagickWand *tmp; size_t size_out = size_in + 1; report_before(mw, size_in); #ifdef IMGMIN_STANDALONE /* * NOTE: for now only allow use of external PNG tools in a standalone cmdline app, * not the built-in apache -- it's slower and less trustworthy. */ if (strcmp("-", src) && !strcmp("PNG", MagickGetImageFormat(mw))) { do_png(mw, src, dst, opt); return; } else { #endif tmp = search_quality(mw, dst, opt); #ifdef IMGMIN_STANDALONE } #endif size_out = blob_write(blob_in, size_in, tmp, dst); report_after(tmp, size_in, size_out); DestroyMagickWand(tmp); }
static int get_wi_format(lua_State *L) { lua_arg *larg = pthread_getspecific(thread_key); char *format = MagickGetImageFormat(larg->img); LOG_PRINT(LOG_DEBUG, "get_wi_format: %s", format); lua_pushstring(L, format); free(format); return 1; }
caddr_t bif_im_DeepZoom4to1 (caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; caddr_t res; int fmt_is_set = 0; int image_ctr; im_init (&env, qst, args, "IM DeepZoom4to1"); im_set_background (&env, "#000000"); env.ime_target_magick_wand = NewMagickWand (); if (MagickFalse == MagickNewImage (env.ime_target_magick_wand, 256, 256, env.ime_background)) im_leave_with_error (&env, "22023", "IM001", "Can not make new image"); if (MagickFalse == MagickSetImageType (env.ime_target_magick_wand, TrueColorType)) im_leave_with_error (&env, "22023", "IM001", "Can not set image type"); if (MagickFalse == MagickSetImageDepth (env.ime_target_magick_wand, 16)) im_leave_with_error (&env, "22023", "IM001", "Can not set image depth"); if (MagickFalse == MagickSetImageExtent (env.ime_target_magick_wand, 256, 256)) im_leave_with_error (&env, "22023", "IM001", "Can not set image extent"); if (MagickFalse == MagickSetImageBackgroundColor (env.ime_target_magick_wand, env.ime_background)) im_leave_with_error (&env, "22023", "IM001", "Can not set image background"); image_ctr = BOX_ELEMENTS (args) / 2; if (image_ctr > 4) image_ctr = 4; while (0 < image_ctr--) { if (DV_DB_NULL == DV_TYPE_OF (bif_arg (qst, args, image_ctr*2, "IM DeepZoom4to1"))) continue; im_env_set_input_blob (&env, image_ctr * 2); /*im_env_set_blob_ext (&env, 2);*/ im_read (&env); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { unsigned long v_size, h_size; if (!fmt_is_set) { if (MagickFalse == MagickSetImageFormat (env.ime_target_magick_wand, MagickGetImageFormat (env.ime_magick_wand))) im_leave_with_error (&env, "22023", "IM001", "Can not set image format"); fmt_is_set = 1; } h_size = MagickGetImageWidth (env.ime_magick_wand); v_size = MagickGetImageHeight (env.ime_magick_wand); if ((256 < h_size) || (256 < v_size)) continue; MagickResizeImage (env.ime_magick_wand, h_size/2, v_size/2, BoxFilter, 1.0); if (MagickFalse == MagickCompositeImage (env.ime_target_magick_wand, env.ime_magick_wand, OverCompositeOp, (image_ctr & 1) * 128, (image_ctr & 2) * 64)) im_leave_with_error (&env, "22023", "IM001", "Can not composite image"); } im_reset_read (&env); } MagickProfileImage (env.ime_target_magick_wand, "*", NULL, 0); DestroyMagickWand (env.ime_magick_wand); env.ime_magick_wand = env.ime_target_magick_wand; env.ime_target_magick_wand = NULL; res = im_write (&env); im_leave (&env); return res; }
/* Check the magick_wand is not empty. If it's empty and raise an exception */ void c_Gmagick::checkHasFormat() { char *buffer = MagickGetImageFormat(magick_wand); if (!buffer || *buffer == '\0') { MagickRelinquishMemory(buffer); throwException("Image has no format", ImageError); } else { MagickRelinquishMemory(buffer); } }
static void report_before(MagickWand *mw, size_t size_in) { const double ks = size_in / 1024.; fprintf(stdout, "Before quality:%lu colors:%lu size:%5.1fkB type:%s format:%s ", quality(mw), (unsigned long)unique_colors(mw), ks, type2str(MagickGetImageType(mw)), MagickGetImageFormat(mw)); }
int parse (size_t size, unsigned char *data) { int writtendata = 0; MagickWand *input = NewMagickWand(); MagickWand *output = input; convert_t *opts = (convert_t*) data; convert_info_t info_data; size -= sizeof(convert_t); data += sizeof(convert_t); int status = convert(input, &output, opts, data, size); if (status < 0) { destroy(input, output); return status; } if (opts->format == INFO) { to_convert_info(output, &info_data); data = (unsigned char*) &info_data; size = sizeof(convert_info_t); writtendata = io_write(size, data); } else { if (opts->split) { // If we split the file then we will make a tarball containing all the pages char* filename; filename = tmpnam (NULL); size = write_archive_from_mem(filename, output); writtendata = io_write_file_to_stdout(filename); unlink(filename); } else { char *format = MagickGetImageFormat(output); if(strcmp(format,"PNG") == 0 && opts->quality != 0){ struct bufferAndSize d = pngQuant(output); writtendata = io_write(d.size, d.data); free(d.data); free(format); }else{ data = MagickWriteImageBlob(output, &size); writtendata = io_write(size, data); free(data); } destroy(input, output); } } return writtendata; }
String c_Gmagick::t_getimageformat() { INSTANCE_METHOD_INJECTION_BUILTIN(Gmagick, Gmagick::getimageformat); checkNotEmpty(); char * format = MagickGetImageFormat(magick_wand); if (!format) { return null; } return String(format, strlen(format), AttachString); }
int main (int argc,char **argv) { FILE *fp; unsigned char *polje; char format[5] = {0}; int len; size_t width, height; MagickWand *image_wand; MagickBooleanType status; //ucitavanje slike if( (fp = fopen(argv[1],"rb")) == NULL) printf("nemoze otvorit sliku\n"); fseek(fp,0,SEEK_END); len = ftell(fp); fseek(fp,0,SEEK_SET); polje = (unsigned char*) malloc (len); fread(polje,1,len,fp); //ucitavanje u imagemagick MagickWandGenesis(); image_wand = NewMagickWand(); status = MagickReadImageBlob(image_wand, polje, len); free(polje); if (status == MagickFalse) {printf("\nnevalja status\n"); exit(-1);} strcpy(format,MagickGetImageFormat(image_wand)); width = MagickGetImageWidth(image_wand); height = MagickGetImageHeight(image_wand); printf("width = %d\nheight = %d\nformat = %s\n",width,height,format); fclose(fp); image_wand = DestroyMagickWand(image_wand); MagickWandTerminus(); system("pause"); return 0; }
void to_convert_info (MagickWand *input, convert_info_t *res) { res->width = MagickGetImageWidth(input); res->height = MagickGetImageHeight(input); res->format = NOOP; res->pages = MagickGetNumberImages(input); char *fmt = MagickGetImageFormat(input); int i; for (i = JPEG; i <= PDF; i++) { if (strcmp(fmt, formats[i])) continue; res->format = i; break; } }
int main(int argc, char *argv[]) { MagickWand *wand = NULL; MagickBooleanType ret; char *description; ExceptionType excep; if (argc < 2) { fprintf(stderr, "Usage: %s file\n", argv[0]); return 1; } MagickWandGenesis(); wand = NewMagickWand(); if (wand == NULL) { description = MagickGetException(wand, &excep); fprintf(stderr, "%s; %s\n", "NewMagickWand() failed", description); MagickRelinquishMemory(description); return 1; } ret = MagickReadImage(wand, argv[1]); if (ret != MagickTrue) { description = MagickGetException(wand, &excep); fprintf(stderr, "%s; %s\n", "MagickReadImage() failed", description); MagickRelinquishMemory(description); return 1; } printf("Format: %s\n", MagickGetImageFormat(wand)); printf("Filename: %s\n", MagickGetImageFilename(wand)); printf("Compression Quality: %ld\n", MagickGetCompressionQuality(wand)); printf("Signature: %s\n", MagickGetImageSignature(wand)); printf("Width: %ld\n", MagickGetImageWidth(wand)); printf("Height: %ld\n", MagickGetImageHeight(wand)); if (wand != NULL) { DestroyMagickWand(wand); } MagickWandTerminus(); return 0; }
unsigned char *covert_image(MagickWand *magick_wand, img_transition_info *image_transition_info, size_t *thumbnail_size) { unsigned char *image_data = NULL; MagickBooleanType status; // MagickWand *tmp_magick_wand = NULL; PixelWand *background = NULL; size_t height = MagickGetImageHeight(magick_wand); size_t old_height = height; size_t width = MagickGetImageWidth(magick_wand); size_t old_width = width; int is_crop = 0; int is_Crop = 0; int is_thumbnail = 0; ssize_t i = 0, j = 0; char is_gif_flag = 0; char is_jpeg_flag = 0; int do_quality = 0; char *fileformat = NULL; size_t cw = 0; //crop weight size_t ch = 0; //crop height size_t x_offset = 0; size_t y_offset = 0; fileformat = MagickGetImageFormat(magick_wand); if (fileformat == NULL) { return NULL; } if (0 == strcasecmp(fileformat, image_format[GIFEXT])) { is_gif_flag = 1; } else if (0 == strcasecmp(fileformat, image_format[JPEGEXT])) { is_jpeg_flag = 1; } else if (0 == strcasecmp(fileformat, image_format[JPGEXT])) { is_jpeg_flag = 1; } fileformat = (char *) MagickRelinquishMemory(fileformat); //free(); if ('c' == image_transition_info->transition_str[0]) { is_crop = 1; } else if ('C' == image_transition_info->transition_str[0]) { is_Crop = 1; } else { is_thumbnail = 1; } if (is_crop) { ParseMetaGeometry(image_transition_info->transition_str + 1, &i, &j, &width, &height); } else if (is_thumbnail) { ParseMetaGeometry(image_transition_info->transition_str, &i, &j, &width, &height); if (old_width == width && height == old_height) //���ߴ���ͬ���������� is_thumbnail = 0; } else if (is_Crop) { if (0 >= get_Crop_width_height( image_transition_info->transition_str + 1, &cw, &ch, &x_offset, &y_offset)) { logError("%s%s:Crop %s error\n", __FILE__, __func__, image_transition_info->transition_str + 1); return NULL; } #if 0 if(cw > width || ch > height) { image_data = MagickGetImagesBlob(magick_wand, thumbnail_size); magick_wand = DestroyMagickWand(magick_wand); return image_data; } #endif //�õ�height��width,�����Ӧ��x_offset,yoffset; get_Crop_offset_and_wh(cw, ch, &width, &height, &x_offset, &y_offset); } if (old_width == width && height == old_height && (is_Crop == 0) && (image_transition_info->is_rotate == 0) && (image_transition_info->is_quality == 0)) { image_data = MagickGetImagesBlob(magick_wand, thumbnail_size); } else if (width <= 0 || height <= 0) { logError("%s%s:Geometry %s error\n", __FILE__, __func__, image_transition_info->transition_str); } else { /* * if type of the image is GIF, maybe have more than one frame, so do this different * from others */ // if (is_gif_flag) { // tmp_magick_wand = magick_wand; // magick_wand = MagickCoalesceImages(tmp_magick_wand); // tmp_magick_wand = magick_wand; // magick_wand = MagickOptimizeImageLayers(tmp_magick_wand); // tmp_magick_wand = DestroyMagickWand(tmp_magick_wand); // } /* * if size of the image less than 800 * 600 and that's type is JPEG, then do * quality 100 OP */ if ((old_width < 800) && (old_height < 600) && is_jpeg_flag && is_crop != 1 && (image_transition_info->is_quality == 0)) { do_quality = 1; } background = NewPixelWand(); status = PixelSetColor(background, "#000000"); /* for gif MagickResetIterator(magick_wand); */ MagickWand *tmp_magick_wand = MagickGetImage(magick_wand); // while (MagickNextImage(tmp_magick_wand) != MagickFalse) { if (do_quality) { MagickSetImageCompressionQuality(tmp_magick_wand, 100); MagickStripImage(tmp_magick_wand); } if (is_thumbnail == 1) { MagickThumbnailImage(tmp_magick_wand, width, height); } else if (is_crop == 1) { MagickCropImage(tmp_magick_wand, width, height, i, j); } else if (is_Crop == 1) { MagickThumbnailImage(tmp_magick_wand, width, height); MagickCropImage(tmp_magick_wand, cw, ch, x_offset, y_offset); if (is_gif_flag) { // gif should thumbnail again MagickThumbnailImage(tmp_magick_wand, cw, ch); } } if (image_transition_info->is_rotate == 1) { MagickRotateImage(tmp_magick_wand, background, (double) (image_transition_info->degree)); } if (image_transition_info->is_quality) { MagickSetImageCompressionQuality(tmp_magick_wand, image_transition_info->quality); } MagickStripImage(tmp_magick_wand); // } background = DestroyPixelWand(background); image_data = MagickGetImagesBlob(tmp_magick_wand, thumbnail_size); tmp_magick_wand = DestroyMagickWand(tmp_magick_wand); // // if (is_gif_flag) { // magick_wand = DestroyMagickWand(magick_wand); // } } return image_data; }
/** * @brief get_img_mode_db Get image from db mode backend. * * @param req zimg request struct * @param buff_ptr buff pointer * @param img_size buff size * * @return 1 for success and -1 for failed */ int get_img_mode_db(zimg_req_t *req, evhtp_request_t *request) { int result = -1; char cache_key[CACHE_KEY_SIZE]; char *img_format = NULL; char *buff_ptr = NULL; size_t img_size; MagickBooleanType status; MagickWand *magick_wand = NULL; bool got_rsp = true; bool got_color = false; LOG_PRINT(LOG_DEBUG, "get_img() start processing zimg request..."); if(req->gray == 1) { gen_key(cache_key, req->md5, 4, req->width, req->height, req->proportion, req->gray); } else { if(req->proportion == 0 && req->width == 0 && req->height == 0) { gen_key(cache_key, req->md5, 0); } else { gen_key(cache_key, req->md5, 3, req->width, req->height, req->proportion); } } if(find_cache_bin(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1) { LOG_PRINT(LOG_DEBUG, "Hit Cache[Key: %s].", cache_key); goto done; } LOG_PRINT(LOG_DEBUG, "Start to Find the Image..."); if(get_img_db(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1) { LOG_PRINT(LOG_DEBUG, "Get image [%s] from backend db succ.", cache_key); if(img_size < CACHE_MAX_SIZE) { set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size); } goto done; } magick_wand = NewMagickWand(); got_rsp = false; if(req->gray == 1) { gen_key(cache_key, req->md5, 3, req->width, req->height, req->proportion); if(find_cache_bin(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1) { LOG_PRINT(LOG_DEBUG, "Hit Color Image Cache[Key: %s, len: %d].", cache_key, img_size); status = MagickReadImageBlob(magick_wand, buff_ptr, img_size); free(buff_ptr); buff_ptr = NULL; if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Color Image Cache[Key: %s] is Bad. Remove.", cache_key); del_cache(req->thr_arg, cache_key); } else { got_color = true; LOG_PRINT(LOG_DEBUG, "Read Image from Color Image Cache[Key: %s, len: %d] Succ. Goto Convert.", cache_key, img_size); goto convert; } } if(get_img_db(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1) { LOG_PRINT(LOG_DEBUG, "Get color image [%s] from backend db.", cache_key); status = MagickReadImageBlob(magick_wand, buff_ptr, img_size); if(status == MagickTrue) { got_color = true; LOG_PRINT(LOG_DEBUG, "Read Image from Color Image[%s] Succ. Goto Convert.", cache_key); if(img_size < CACHE_MAX_SIZE) { set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size); } free(buff_ptr); buff_ptr = NULL; goto convert; } } } gen_key(cache_key, req->md5, 0); if(find_cache_bin(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1) { LOG_PRINT(LOG_DEBUG, "Hit Cache[Key: %s].", cache_key); } else { if(get_img_db(req->thr_arg, cache_key, &buff_ptr, &img_size) == -1) { LOG_PRINT(LOG_DEBUG, "Get image [%s] from backend db failed.", cache_key); goto err; } else if(img_size < CACHE_MAX_SIZE) { set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size); } } status = MagickReadImageBlob(magick_wand, buff_ptr, img_size); free(buff_ptr); buff_ptr = NULL; if(status == MagickFalse) { ThrowWandException(magick_wand); del_cache(req->thr_arg, cache_key); LOG_PRINT(LOG_DEBUG, "Read image [%s] from blob failed.", cache_key); goto err; } if(req->width == 0 && req->height == 0) { LOG_PRINT(LOG_DEBUG, "Image [%s] needn't resize. Goto Convert.", cache_key); goto convert; } int width, height; width = req->width; height = req->height; float owidth = MagickGetImageWidth(magick_wand); float oheight = MagickGetImageHeight(magick_wand); if(width <= owidth && height <= oheight) { if(req->proportion == 1 || (req->proportion == 0 && req->width * req->height == 0)) { if(req->height == 0) { height = width * oheight / owidth; } else { width = height * owidth / oheight; } } status = MagickResizeImage(magick_wand, width, height, LanczosFilter, 1.0); if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Image[%s] Resize Failed!", cache_key); goto err; } LOG_PRINT(LOG_DEBUG, "Resize img succ."); } else { got_rsp = true; LOG_PRINT(LOG_DEBUG, "Args width/height is bigger than real size, return original image."); } convert: //compress image if(got_color == false) { LOG_PRINT(LOG_DEBUG, "Start to Compress the Image!"); img_format = MagickGetImageFormat(magick_wand); LOG_PRINT(LOG_DEBUG, "Image Format is %s", img_format); if(strcmp(img_format, "JPEG") != 0) { LOG_PRINT(LOG_DEBUG, "Convert Image Format from %s to JPEG.", img_format); status = MagickSetImageFormat(magick_wand, "JPEG"); if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Image[%s] Convert Format Failed!", cache_key); } LOG_PRINT(LOG_DEBUG, "Compress Image with JPEGCompression"); status = MagickSetImageCompression(magick_wand, JPEGCompression); if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Image[%s] Compression Failed!", cache_key); } } size_t quality = MagickGetImageCompressionQuality(magick_wand); LOG_PRINT(LOG_DEBUG, "Image Compression Quality is %u.", quality); if(quality > WAP_QUALITY) { quality = WAP_QUALITY; } LOG_PRINT(LOG_DEBUG, "Set Compression Quality to 75%."); status = MagickSetImageCompressionQuality(magick_wand, quality); if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Set Compression Quality Failed!"); } //strip image EXIF infomation LOG_PRINT(LOG_DEBUG, "Start to Remove Exif Infomation of the Image..."); status = MagickStripImage(magick_wand); if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Remove Exif Infomation of the ImageFailed!"); } buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size); if(buff_ptr == NULL) { LOG_PRINT(LOG_DEBUG, "Magick Get Image Blob Failed!"); goto err; } gen_key(cache_key, req->md5, 3, req->width, req->height, req->proportion); if(got_rsp == false) { save_img_db(req->thr_arg, cache_key, buff_ptr, img_size); } if(img_size < CACHE_MAX_SIZE) { set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size); } if(req->gray == 1) { free(buff_ptr); buff_ptr = NULL; } else { goto done; } } //gray image if(req->gray == 1) { LOG_PRINT(LOG_DEBUG, "Start to Remove Color!"); status = MagickSetImageColorspace(magick_wand, GRAYColorspace); if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Image[%s] Remove Color Failed!", cache_key); goto err; } LOG_PRINT(LOG_DEBUG, "Image Remove Color Finish!"); buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size); if(buff_ptr == NULL) { LOG_PRINT(LOG_DEBUG, "Magick Get Image Blob Failed!"); goto err; } gen_key(cache_key, req->md5, 4, req->width, req->height, req->proportion, req->gray); if(got_rsp == false) { save_img_db(req->thr_arg, cache_key, buff_ptr, img_size); } if(img_size < CACHE_MAX_SIZE) { set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size); } } done: result = evbuffer_add(request->buffer_out, buff_ptr, img_size); if(result != -1) { result = 1; } err: if(magick_wand) { magick_wand=DestroyMagickWand(magick_wand); } if(img_format) free(img_format); if(buff_ptr) free(buff_ptr); return result; }
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; }
/** * @brief get_img The function of getting a image buffer and it's length. * * @param req The zimg_req_t from zhttp and it has the params of a request. * @param buff_ptr This function return image buffer in it. * @param img_size Get_img will change this number to return the size of image buffer. * * @return ZIMG_OK for success and ZIMG_ERR for fail. */ int get_img(zimg_req_t *req, char **buff_ptr, size_t *img_size) { int result = -1; char *rsp_path = NULL; char *whole_path = NULL; char *orig_path = NULL; char *color_path = NULL; char *img_format = NULL; size_t len; int fd = -1; struct stat f_stat; MagickBooleanType status; MagickWand *magick_wand = NULL; LOG_PRINT(LOG_INFO, "get_img() start processing zimg request..."); char *cache_key = (char *)malloc(strlen(req->md5) + 32); if(cache_key == NULL){ LOG_PRINT(LOG_INFO, "malloc failed!"); return ZIMG_ERR; } // to gen cache_key like this: img:926ee2f570dc50b2575e35a6712b08ce:0:0:1:0 sprintf(cache_key, "img:%s:%d:%d:%d:%d", req->md5, req->width, req->height, req->proportion, req->gray); if(find_cache_bin(cache_key, buff_ptr, img_size) == 1){ LOG_PRINT(LOG_INFO, "Hit Cache[Key: %s].", cache_key); // sprintf(cache_key, "type:%s:%d:%d:%d:%d", req->md5, req->width, req->height, req->proportion, req->gray); // if(find_cache(cache_key, img_format) == -1) // { // LOG_PRINT(LOG_WARNING, "Cannot Hit Type Cache[Key: %s]. Use jpeg As Default.", cache_key); // strcpy(img_format, "jpeg"); // } free(cache_key); return ZIMG_OK; } free(cache_key); LOG_PRINT(LOG_INFO, "Start to Find the Image..."); //check img dir // /1023/1023/xxxxxxxxxxxxxxx.png len = strlen(req->md5) + strlen(settings.img_path) + 12; whole_path = malloc(len); if (whole_path == NULL){ LOG_PRINT(LOG_ERROR, "whole_path malloc failed!"); return ZIMG_ERR; } int lvl1 = str_hash(req->md5); int lvl2 = str_hash(req->md5 + 3); sprintf(whole_path, "%s/%d/%d/%s", settings.img_path, lvl1, lvl2, req->md5); LOG_PRINT(LOG_INFO, "docroot: %s", settings.img_path); LOG_PRINT(LOG_INFO, "req->md5: %s", req->md5); LOG_PRINT(LOG_INFO, "whole_path: %s", whole_path); char name[128]; if(req->proportion && req->gray) sprintf(name, "%d*%dpg", req->width, req->height); else if(req->proportion && !req->gray) sprintf(name, "%d*%dp", req->width, req->height); else if(!req->proportion && req->gray) sprintf(name, "%d*%dg", req->width, req->height); else sprintf(name, "%d*%d", req->width, req->height); orig_path = (char *)malloc(strlen(whole_path) + 6); sprintf(orig_path, "%s/0*0p", whole_path); LOG_PRINT(LOG_INFO, "0rig File Path: %s", orig_path); rsp_path = (char *)malloc(512); if(req->width == 0 && req->height == 0 && req->gray == 0) { LOG_PRINT(LOG_INFO, "Return original image."); strcpy(rsp_path, orig_path); } else { sprintf(rsp_path, "%s/%s", whole_path, name); } LOG_PRINT(LOG_INFO, "Got the rsp_path: %s", rsp_path); bool got_rsp = true; bool got_color = false; //status=MagickReadImage(magick_wand, rsp_path); if((fd = open(rsp_path, O_RDONLY)) == -1) //if(status == MagickFalse) { magick_wand = NewMagickWand(); got_rsp = false; if(req->gray == 1) { sprintf(cache_key, "img:%s:%d:%d:%d:0", req->md5, req->width, req->height, req->proportion); if(find_cache_bin(cache_key, buff_ptr, img_size) == 1) { LOG_PRINT(LOG_INFO, "Hit Color Image Cache[Key: %s, len: %d].", cache_key, *img_size); status = MagickReadImageBlob(magick_wand, *buff_ptr, *img_size); if(status == MagickFalse) { LOG_PRINT(LOG_WARNING, "Color Image Cache[Key: %s] is Bad. Remove.", cache_key); del_cache(cache_key); } else { got_color = true; LOG_PRINT(LOG_INFO, "Read Image from Color Image Cache[Key: %s, len: %d] Succ. Goto Convert.", cache_key, *img_size); goto convert; } } len = strlen(rsp_path); color_path = (char *)malloc(len); strncpy(color_path, rsp_path, len); color_path[len - 1] = '\0'; LOG_PRINT(LOG_INFO, "color_path: %s", color_path); status=MagickReadImage(magick_wand, color_path); if(status == MagickTrue) { got_color = true; LOG_PRINT(LOG_INFO, "Read Image from Color Image[%s] Succ. Goto Convert.", color_path); *buff_ptr = (char *)MagickGetImageBlob(magick_wand, img_size); if(*img_size < CACHE_MAX_SIZE) { set_cache_bin(cache_key, *buff_ptr, *img_size); // img_format = MagickGetImageFormat(magick_wand); // sprintf(cache_key, "type:%s:%d:%d:%d:0", req->md5, req->width, req->height, req->proportion); // set_cache(cache_key, img_format); } goto convert; } } // to gen cache_key like this: rsp_path-/926ee2f570dc50b2575e35a6712b08ce sprintf(cache_key, "img:%s:0:0:1:0", req->md5); if(find_cache_bin(cache_key, buff_ptr, img_size) == 1) { LOG_PRINT(LOG_INFO, "Hit Orignal Image Cache[Key: %s].", cache_key); status = MagickReadImageBlob(magick_wand, *buff_ptr, *img_size); if(status == MagickFalse) { LOG_PRINT(LOG_WARNING, "Open Original Image From Blob Failed! Begin to Open it From Disk."); ThrowWandException(magick_wand); del_cache(cache_key); status = MagickReadImage(magick_wand, orig_path); if(status == MagickFalse) { ThrowWandException(magick_wand); goto err; } else { *buff_ptr = (char *)MagickGetImageBlob(magick_wand, img_size); if(*img_size < CACHE_MAX_SIZE) { set_cache_bin(cache_key, *buff_ptr, *img_size); // img_format = MagickGetImageFormat(magick_wand); // sprintf(cache_key, "type:%s:0:0:1:0", req->md5); // set_cache(cache_key, img_format); } } } } else { LOG_PRINT(LOG_INFO, "Not Hit Original Image Cache. Begin to Open it."); status = MagickReadImage(magick_wand, orig_path); if(status == MagickFalse) { ThrowWandException(magick_wand); goto err; } else { *buff_ptr = (char *)MagickGetImageBlob(magick_wand, img_size); if(*img_size < CACHE_MAX_SIZE) { set_cache_bin(cache_key, *buff_ptr, *img_size); // img_format = MagickGetImageFormat(magick_wand); // sprintf(cache_key, "type:%s:0:0:1:0", req->md5); // set_cache(cache_key, img_format); } } } int width, height; width = req->width; height = req->height; float owidth = MagickGetImageWidth(magick_wand); float oheight = MagickGetImageHeight(magick_wand); if(width <= owidth && height <= oheight) { if(req->proportion == 1) { if(req->width != 0 && req->height == 0) { height = width * oheight / owidth; } //else if(height != 0 && width == 0) else { width = height * owidth / oheight; } } status = MagickResizeImage(magick_wand, width, height, LanczosFilter, 1.0); if(status == MagickFalse) { LOG_PRINT(LOG_ERROR, "Image[%s] Resize Failed!", orig_path); goto err; } LOG_PRINT(LOG_INFO, "Resize img succ."); } /* this section can caculate the correct rsp_path, but not use, so I note them else if(req->gray == true) { strcpy(rsp_path, orig_path); rsp_path[strlen(orig_path)] = 'g'; rsp_path[strlen(orig_path) + 1] = '\0'; got_rsp = true; LOG_PRINT(LOG_INFO, "Args width/height is bigger than real size, return original gray image."); LOG_PRINT(LOG_INFO, "Original Gray Image: %s", rsp_path); } */ else { // Note this strcpy because rsp_path is not useful. We needn't to save the new image. //strcpy(rsp_path, orig_path); got_rsp = true; LOG_PRINT(LOG_INFO, "Args width/height is bigger than real size, return original image."); } } else { fstat(fd, &f_stat); size_t rlen = 0; *img_size = f_stat.st_size; if(*img_size <= 0) { LOG_PRINT(LOG_ERROR, "File[%s] is Empty.", rsp_path); goto err; } if((*buff_ptr = (char *)malloc(*img_size)) == NULL) { LOG_PRINT(LOG_ERROR, "buff_ptr Malloc Failed!"); goto err; } LOG_PRINT(LOG_INFO, "img_size = %d", *img_size); //*buff_ptr = (char *)MagickGetImageBlob(magick_wand, img_size); if((rlen = read(fd, *buff_ptr, *img_size)) == -1) { LOG_PRINT(LOG_ERROR, "File[%s] Read Failed.", rsp_path); LOG_PRINT(LOG_ERROR, "Error: %s.", strerror(errno)); goto err; } else if(rlen < *img_size) { LOG_PRINT(LOG_ERROR, "File[%s] Read Not Compeletly.", rsp_path); goto err; } goto done; } convert: //gray image if(req->gray == true) { LOG_PRINT(LOG_INFO, "Start to Remove Color!"); status = MagickSetImageColorspace(magick_wand, GRAYColorspace); if(status == MagickFalse) { LOG_PRINT(LOG_ERROR, "Image[%s] Remove Color Failed!", orig_path); goto err; } LOG_PRINT(LOG_INFO, "Image Remove Color Finish!"); } if(got_color == false || (got_color == true && req->width == 0) ) { //compress image LOG_PRINT(LOG_INFO, "Start to Compress the Image!"); img_format = MagickGetImageFormat(magick_wand); LOG_PRINT(LOG_INFO, "Image Format is %s", img_format); if(strcmp(img_format, "JPEG") != 0) { LOG_PRINT(LOG_INFO, "Convert Image Format from %s to JPEG.", img_format); status = MagickSetImageFormat(magick_wand, "JPEG"); if(status == MagickFalse) { LOG_PRINT(LOG_WARNING, "Image[%s] Convert Format Failed!", orig_path); } LOG_PRINT(LOG_INFO, "Compress Image with JPEGCompression"); status = MagickSetImageCompression(magick_wand, JPEGCompression); if(status == MagickFalse) { LOG_PRINT(LOG_WARNING, "Image[%s] Compression Failed!", orig_path); } } size_t quality = MagickGetImageCompressionQuality(magick_wand) * 0.75; LOG_PRINT(LOG_INFO, "Image Compression Quality is %u.", quality); if(quality == 0) { quality = 75; } LOG_PRINT(LOG_INFO, "Set Compression Quality to 75%."); status = MagickSetImageCompressionQuality(magick_wand, quality); if(status == MagickFalse) { LOG_PRINT(LOG_WARNING, "Set Compression Quality Failed!"); } //strip image EXIF infomation LOG_PRINT(LOG_INFO, "Start to Remove Exif Infomation of the Image..."); status = MagickStripImage(magick_wand); if(status == MagickFalse) { LOG_PRINT(LOG_WARNING, "Remove Exif Infomation of the ImageFailed!"); } } *buff_ptr = (char *)MagickGetImageBlob(magick_wand, img_size); if(*buff_ptr == NULL) { LOG_PRINT(LOG_ERROR, "Magick Get Image Blob Failed!"); goto err; } done: if(*img_size < CACHE_MAX_SIZE) { // to gen cache_key like this: rsp_path-/926ee2f570dc50b2575e35a6712b08ce sprintf(cache_key, "img:%s:%d:%d:%d:%d", req->md5, req->width, req->height, req->proportion, req->gray); set_cache_bin(cache_key, *buff_ptr, *img_size); // sprintf(cache_key, "type:%s:%d:%d:%d:%d", req->md5, req->width, req->height, req->proportion, req->gray); // set_cache(cache_key, img_format); } result = 1; if(got_rsp == false) { LOG_PRINT(LOG_INFO, "Image[%s] is Not Existed. Begin to Save it.", rsp_path); result = 2; } else LOG_PRINT(LOG_INFO, "Image Needn't to Storage.", rsp_path); err: if(fd != -1) close(fd); req->rsp_path = rsp_path; if(magick_wand) { magick_wand=DestroyMagickWand(magick_wand); } if(img_format) free(img_format); if(cache_key) free(cache_key); if (orig_path) free(orig_path); if (whole_path) free(whole_path); return result; }
caddr_t bif_im_get_impl (caddr_t * qst, caddr_t * err, state_slot_t ** args, int is_file_in, int op, const char *bifname) { im_env_t env; char *strg_value = NULL; unsigned long ul_value = 0; caddr_t res = NULL; int is_string_res = (('A' == op) || ('F' == op) || ('I' == op)); int is_list_res = ('2' == op); int is_key_needed = ('A' == op); caddr_t key = is_key_needed ? bif_string_arg (qst, args, (is_file_in ? 1 : 2), bifname) : NULL; im_init (&env, qst, args, bifname); if (is_file_in) im_env_set_filenames (&env, 0, -1); else { im_env_set_input_blob (&env, 0); im_env_set_blob_ext (&env, (is_key_needed ? 3 : 2), -1); } im_read (&env); MagickResetIterator(env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { switch (op) { case 'A': strg_value = MagickGetImageAttribute (env.ime_magick_wand, key); break; case 'F': strg_value = MagickGetImageFormat (env.ime_magick_wand); break; case 'I': strg_value = MagickIdentifyImage (env.ime_magick_wand); break; case 'W': ul_value = MagickGetImageWidth (env.ime_magick_wand); break; case 'H': ul_value = MagickGetImageHeight (env.ime_magick_wand); break; case 'D': ul_value = MagickGetImageDepth (env.ime_magick_wand); break; case '2': ul_value = MagickGetImageWidth (env.ime_magick_wand); if (ul_value) { dk_free_tree (res); res = dk_alloc_box (2 * sizeof (caddr_t), DV_ARRAY_OF_POINTER); ((caddr_t *)res)[0] = box_num (ul_value); ((caddr_t *)res)[1] = box_num (MagickGetImageHeight (env.ime_magick_wand)); } break; } } if (is_string_res) { if (strg_value) { res = box_dv_short_string (strg_value); MagickRelinquishMemory (strg_value); } } else if (!is_list_res) { if (ul_value) res = box_num (ul_value); } if (NULL == res) res = NEW_DB_NULL; im_leave (&env); return res; }
unsigned char *get_thumbnail(char *full_filename, char *thumbnail_str, size_t *thumbnail_size, int is_rotate, int rotate_degree) { unsigned char *image_data = NULL; if (full_filename == NULL || thumbnail_str == NULL) return NULL; MagickBooleanType status; MagickWand *tmp_magick_wand = NULL; MagickWand *magick_wand = NULL; magick_wand = NewMagickWand(); status = MagickReadImage(magick_wand, full_filename); if (status == MagickFalse) { ThrowWandException(magick_wand); return NULL; } PixelWand *background = NULL; size_t height = MagickGetImageHeight(magick_wand); size_t old_height = height; size_t width = MagickGetImageWidth(magick_wand); size_t old_width = width; ssize_t i = 0, j = 0; int is_crop = 0; char is_gif_flag = 0; char is_jpeg_flag = 0; int do_quality = 0; char *fileformat = NULL; fileformat = MagickGetImageFormat(magick_wand); if (fileformat == NULL) { return NULL; } if (0 == strcasecmp(fileformat, image_format[GIFEXT])) { is_gif_flag = 1; } else if (0 == strcasecmp(fileformat, image_format[JPEGEXT])) { is_jpeg_flag = 1; } else if (0 == strcasecmp(fileformat, image_format[JPGEXT])) { is_jpeg_flag = 1; } fileformat = (char *)MagickRelinquishMemory(fileformat); //free(); if( 'C' == *thumbnail_str ||'c' == *thumbnail_str ) { is_crop = 1; } if(is_crop) { ParseMetaGeometry(thumbnail_str + 1, &i, &j, &width, &height); } else { ParseMetaGeometry(thumbnail_str, &i, &j, &width, &height); } if (old_width == width && height == old_height) { image_data = MagickGetImagesBlob(magick_wand, thumbnail_size); } else if (width <= 0 || height <= 0) { logError("%s%s:Geometry %s error\n", __FILE__, __func__, thumbnail_str); } else { /* * if type of the image is GIF, maybe have more than one frame, so do this different * from others */ if (is_gif_flag) { tmp_magick_wand = magick_wand; magick_wand = MagickCoalesceImages(tmp_magick_wand); tmp_magick_wand = DestroyMagickWand(tmp_magick_wand); } /* * if size of the image less than 800 * 600 and that's type is JPEG, then do * quality 100 OP */ if ((old_width < 800) && (old_height < 600) && is_jpeg_flag && is_crop != 1) { do_quality = 1; } MagickResetIterator(magick_wand); while (MagickNextImage(magick_wand) != MagickFalse) { if(do_quality) { MagickSetImageCompressionQuality(magick_wand, 100); MagickStripImage(magick_wand); } if(is_crop == 0) MagickThumbnailImage(magick_wand, width, height); else { logInfo("crop Image %ld, %ld", i, j); MagickCropImage(magick_wand, width, height, i, j); } if(is_rotate == 1) { background=NewPixelWand(); status=PixelSetColor(background,"#000000"); MagickRotateImage(magick_wand, background,(double)rotate_degree); background=DestroyPixelWand(background); } } image_data = MagickGetImagesBlob(magick_wand, thumbnail_size); } magick_wand = DestroyMagickWand(magick_wand); return image_data; }
/** * @brief get_img The function of getting a image buffer and it's length. * * @param req The zimg_req_t from zhttp and it has the params of a request. * @param buff_ptr This function return image buffer in it. * @param img_size Get_img will change this number to return the size of image buffer. * * @return 1 for success and -1 for fail. */ int get_img(zimg_req_t *req, evhtp_request_t *request) { int result = -1; char cache_key[CACHE_KEY_SIZE]; char *img_format = NULL; int fd = -1; struct stat f_stat; char *buff_ptr; size_t img_size; MagickBooleanType status; MagickWand *magick_wand = NULL; bool got_rsp = true; bool got_color = false; LOG_PRINT(LOG_DEBUG, "get_img() start processing zimg request..."); // to gen cache_key like this: 926ee2f570dc50b2575e35a6712b08ce:0:0:1:0 gen_key(cache_key, req->md5, 4, req->width, req->height, req->proportion, req->gray); if(find_cache_bin(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1) { LOG_PRINT(LOG_DEBUG, "Hit Cache[Key: %s].", cache_key); goto done; } LOG_PRINT(LOG_DEBUG, "Start to Find the Image..."); char whole_path[512]; int lvl1 = str_hash(req->md5); int lvl2 = str_hash(req->md5 + 3); snprintf(whole_path, 512, "%s/%d/%d/%s", settings.img_path, lvl1, lvl2, req->md5); LOG_PRINT(LOG_DEBUG, "docroot: %s", settings.img_path); LOG_PRINT(LOG_DEBUG, "req->md5: %s", req->md5); LOG_PRINT(LOG_DEBUG, "whole_path: %s", whole_path); char name[128]; if(req->proportion && req->gray) snprintf(name, 128, "%d*%dpg", req->width, req->height); else if(req->proportion && !req->gray) snprintf(name, 128, "%d*%dp", req->width, req->height); else if(!req->proportion && req->gray) snprintf(name, 128, "%d*%dg", req->width, req->height); else snprintf(name, 128, "%d*%d", req->width, req->height); char color_name[128]; if(req->proportion) snprintf(color_name, 128, "%d*%dp", req->width, req->height); else snprintf(color_name, 128, "%d*%d", req->width, req->height); char orig_path[512]; snprintf(orig_path, strlen(whole_path) + 6, "%s/0*0", whole_path); LOG_PRINT(LOG_DEBUG, "0rig File Path: %s", orig_path); char rsp_path[512]; if(req->width == 0 && req->height == 0 && req->proportion == 0 && req->gray == 0) { LOG_PRINT(LOG_DEBUG, "Return original image."); strncpy(rsp_path, orig_path, 512); } else { snprintf(rsp_path, 512, "%s/%s", whole_path, name); } LOG_PRINT(LOG_DEBUG, "Got the rsp_path: %s", rsp_path); char color_path[512]; snprintf(color_path, 512, "%s/%s", whole_path, color_name); //status=MagickReadImage(magick_wand, rsp_path); if((fd = open(rsp_path, O_RDONLY)) == -1) { magick_wand = NewMagickWand(); got_rsp = false; if(req->gray == 1) { gen_key(cache_key, req->md5, 3, req->width, req->height, req->proportion); if(find_cache_bin(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1) { LOG_PRINT(LOG_DEBUG, "Hit Color Image Cache[Key: %s, len: %d].", cache_key, img_size); status = MagickReadImageBlob(magick_wand, buff_ptr, img_size); free(buff_ptr); buff_ptr = NULL; if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Color Image Cache[Key: %s] is Bad. Remove.", cache_key); del_cache(req->thr_arg, cache_key); } else { got_color = true; LOG_PRINT(LOG_DEBUG, "Read Image from Color Image Cache[Key: %s, len: %d] Succ. Goto Convert.", cache_key, img_size); goto convert; } } status=MagickReadImage(magick_wand, color_path); if(status == MagickTrue) { got_color = true; LOG_PRINT(LOG_DEBUG, "Read Image from Color Image[%s] Succ. Goto Convert.", rsp_path); buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size); if(img_size < CACHE_MAX_SIZE) { set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size); } free(buff_ptr); buff_ptr = NULL; goto convert; } } // to gen cache_key like this: rsp_path-/926ee2f570dc50b2575e35a6712b08ce gen_key(cache_key, req->md5, 0); if(find_cache_bin(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1) { LOG_PRINT(LOG_DEBUG, "Hit Orignal Image Cache[Key: %s].", cache_key); status = MagickReadImageBlob(magick_wand, buff_ptr, img_size); free(buff_ptr); buff_ptr = NULL; if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Open Original Image From Blob Failed! Begin to Open it From Disk."); ThrowWandException(magick_wand); del_cache(req->thr_arg, cache_key); status = MagickReadImage(magick_wand, orig_path); if(status == MagickFalse) { ThrowWandException(magick_wand); goto err; } else { buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size); if(img_size < CACHE_MAX_SIZE) { set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size); } free(buff_ptr); buff_ptr = NULL; } } } else { LOG_PRINT(LOG_DEBUG, "Not Hit Original Image Cache. Begin to Open it."); status = MagickReadImage(magick_wand, orig_path); if(status == MagickFalse) { ThrowWandException(magick_wand); goto err; } else { buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size); if(img_size < CACHE_MAX_SIZE) { set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size); } free(buff_ptr); buff_ptr = NULL; } } int width, height; width = req->width; height = req->height; if(width == 0 && height == 0) { LOG_PRINT(LOG_DEBUG, "Image[%s] needn't resize. Goto Convert.", orig_path); goto convert; } float owidth = MagickGetImageWidth(magick_wand); float oheight = MagickGetImageHeight(magick_wand); if(width <= owidth && height <= oheight) { if(req->proportion == 1 || (req->proportion == 0 && req->width * req->height == 0)) { if(req->height == 0) { height = width * oheight / owidth; } else { width = height * owidth / oheight; } } status = MagickResizeImage(magick_wand, width, height, LanczosFilter, 1.0); if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Image[%s] Resize Failed!", orig_path); goto err; } LOG_PRINT(LOG_DEBUG, "Resize img succ."); } else { // Note this strcpy because rsp_path is not useful. We needn't to save the new image. got_rsp = true; LOG_PRINT(LOG_DEBUG, "Args width/height is bigger than real size, return original image."); } } else { fstat(fd, &f_stat); size_t rlen = 0; img_size = f_stat.st_size; if(img_size <= 0) { LOG_PRINT(LOG_DEBUG, "File[%s] is Empty.", rsp_path); goto err; } if((buff_ptr = (char *)malloc(img_size)) == NULL) { LOG_PRINT(LOG_DEBUG, "buff_ptr Malloc Failed!"); goto err; } LOG_PRINT(LOG_DEBUG, "img_size = %d", img_size); if((rlen = read(fd, buff_ptr, img_size)) == -1) { LOG_PRINT(LOG_DEBUG, "File[%s] Read Failed.", rsp_path); LOG_PRINT(LOG_DEBUG, "Error: %s.", strerror(errno)); goto err; } else if(rlen < img_size) { LOG_PRINT(LOG_DEBUG, "File[%s] Read Not Compeletly.", rsp_path); goto err; } if(img_size < CACHE_MAX_SIZE) { set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size); } goto done; } convert: if(got_color == false) { //compress image LOG_PRINT(LOG_DEBUG, "Start to Compress the Image!"); img_format = MagickGetImageFormat(magick_wand); LOG_PRINT(LOG_DEBUG, "Image Format is %s", img_format); if(strcmp(img_format, "JPEG") != 0) { LOG_PRINT(LOG_DEBUG, "Convert Image Format from %s to JPEG.", img_format); status = MagickSetImageFormat(magick_wand, "JPEG"); if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Image[%s] Convert Format Failed!", orig_path); } LOG_PRINT(LOG_DEBUG, "Compress Image with JPEGCompression"); status = MagickSetImageCompression(magick_wand, JPEGCompression); if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Image[%s] Compression Failed!", orig_path); } } size_t quality = MagickGetImageCompressionQuality(magick_wand); LOG_PRINT(LOG_DEBUG, "Image Compression Quality is %u.", quality); if(quality > WAP_QUALITY) { quality = WAP_QUALITY; } LOG_PRINT(LOG_DEBUG, "Set Compression Quality to 75%."); status = MagickSetImageCompressionQuality(magick_wand, quality); if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Set Compression Quality Failed!"); } //strip image EXIF infomation LOG_PRINT(LOG_DEBUG, "Start to Remove Exif Infomation of the Image..."); status = MagickStripImage(magick_wand); if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Remove Exif Infomation of the ImageFailed!"); } buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size); if(buff_ptr == NULL) { LOG_PRINT(LOG_DEBUG, "Magick Get Image Blob Failed!"); goto err; } gen_key(cache_key, req->md5, 3, req->width, req->height, req->proportion); if(img_size < CACHE_MAX_SIZE) { set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size); } if(got_rsp == false) { LOG_PRINT(LOG_DEBUG, "Color Image[%s] is Not Existed. Begin to Save it.", color_path); if(new_img(buff_ptr, img_size, color_path) == -1) { LOG_PRINT(LOG_DEBUG, "Color Image[%s] Save Failed!", color_path); LOG_PRINT(LOG_WARNING, "fail save %s", color_path); } } if(req->gray == 1) { free(buff_ptr); buff_ptr = NULL; } else { goto done; } } //gray image if(req->gray == 1) { LOG_PRINT(LOG_DEBUG, "Start to Remove Color!"); status = MagickSetImageColorspace(magick_wand, GRAYColorspace); if(status == MagickFalse) { LOG_PRINT(LOG_DEBUG, "Image[%s] Remove Color Failed!", orig_path); goto err; } LOG_PRINT(LOG_DEBUG, "Image Remove Color Finish!"); buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size); if(buff_ptr == NULL) { LOG_PRINT(LOG_DEBUG, "Magick Get Image Blob Failed!"); goto err; } gen_key(cache_key, req->md5, 4, req->width, req->height, req->proportion, req->gray); if(img_size < CACHE_MAX_SIZE) { set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size); } if(got_rsp == false) { if(new_img(buff_ptr, img_size, rsp_path) == -1) { LOG_PRINT(LOG_DEBUG, "New Image[%s] Save Failed!", rsp_path); LOG_PRINT(LOG_WARNING, "fail save %s", rsp_path); } } else LOG_PRINT(LOG_DEBUG, "Image Needn't to Storage.", rsp_path); } done: result = evbuffer_add(request->buffer_out, buff_ptr, img_size); if(result != -1) { result = 1; } err: if(fd != -1) close(fd); if(magick_wand) { magick_wand=DestroyMagickWand(magick_wand); } if(img_format) free(img_format); if(buff_ptr) free(buff_ptr); return result; }
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; }