void *iw_realloc(struct iw_context *ctx, void *m, size_t n) { void *mem; if(n>ctx->max_malloc) { iw_seterror(ctx,iwcore_get_string(ctx,iws_nomem)); return NULL; } mem = iw_realloc_lowlevel(m,n); if(!mem) { iw_seterror(ctx,iwcore_get_string(ctx,iws_nomem)); return NULL; } return mem; }
int iw_write_webp_file(struct iw_context *ctx, struct iw_iodescr *iodescr) { struct iwwebpwritecontext wctx; int retval=0; struct iw_image img1; iw_set_string_table(ctx,IW_STRINGTABLENUM_WEBP,iwwebp_stringtable); memset(&img1,0,sizeof(struct iw_image)); memset(&wctx,0,sizeof(struct iwwebpwritecontext)); wctx.ctx = ctx; wctx.iodescr=iodescr; iw_get_output_image(ctx,&img1); wctx.img = &img1; if(!iwwebp_write_main(&wctx)) { goto done; } retval=1; done: if(!retval) { iw_seterror(ctx,iwwebp_get_string(ctx,iws_webp_write_error)); } if(wctx.iodescr->close_fn) (*wctx.iodescr->close_fn)(ctx,wctx.iodescr); return retval; }
// Allocate a large block of memory, presumably for image data. // Use this if integer overflow is a possibility when multiplying // two factors together. void *iw_malloc_large(struct iw_context *ctx, size_t n1, size_t n2) { if(n1 > ctx->max_malloc/n2) { iw_seterror(ctx,iwcore_get_string(ctx,iws_image_too_large)); return NULL; } return iw_malloc(ctx,n1*n2); }
static int iwwebp_write_main(struct iwwebpwritecontext *wctx) { struct iw_image *img; size_t ret; uint8_t *cmpr_webp_data = NULL; int retval=0; double quality; img = wctx->img; quality = iw_get_value_dbl(wctx->ctx,IW_VAL_WEBP_QUALITY); if(quality<0.0) { quality=80.0; // Default quality. } switch(img->imgtype) { case IW_IMGTYPE_GRAY: // IW requires encoders to support grayscale, but WebP doesn't (?) // support it. So, convert grayscale images to RGB. iwwebp_gray_to_rgb(wctx); // Allocates RGB image at wctx->tmppixels. if(!wctx->tmppixels) goto done; ret = WebPEncodeRGB(wctx->tmppixels, img->width, img->height, 3*img->width, (float)quality, &cmpr_webp_data); break; case IW_IMGTYPE_RGB: ret = WebPEncodeRGB(img->pixels, img->width, img->height, (int)img->bpr, (float)quality, &cmpr_webp_data); break; default: iw_seterror(wctx->ctx,iwwebp_get_string(wctx->ctx,iws_webp_enc_bad_imgtype),img->imgtype); goto done; } if(ret<1 || !cmpr_webp_data) { goto done; } iwwebp_write(wctx, cmpr_webp_data, ret); retval=1; done: if(cmpr_webp_data) free(cmpr_webp_data); if(wctx->tmppixels) iw_free(wctx->tmppixels); return 1; }
int iw_read_webp_file(struct iw_context *ctx, struct iw_iodescr *iodescr) { struct iw_image img; struct iwwebpreadcontext rctx; int retval=0; memset(&rctx,0,sizeof(struct iwwebpreadcontext)); memset(&img,0,sizeof(struct iw_image)); iw_set_string_table(ctx,IW_STRINGTABLENUM_WEBP,iwwebp_stringtable); rctx.ctx = ctx; rctx.iodescr = iodescr; rctx.img = &img; // Assume WebP images are sRGB rctx.csdescr.cstype = IW_CSTYPE_SRGB; rctx.csdescr.sRGB_intent = IW_sRGB_INTENT_PERCEPTUAL; if(!iwwebp_read_main(&rctx)) goto done; iw_set_input_image(ctx, &img); iw_set_input_colorspace(ctx,&rctx.csdescr); retval = 1; done: if(!retval) { iw_seterror(ctx,iwwebp_get_string(ctx,iws_webp_read_error)); } if(iodescr->close_fn) (*iodescr->close_fn)(ctx,iodescr); return retval; }
static int run(struct params_struct *p) { int retval = 0; struct iw_context *ctx = NULL; int imgtype_read; int input_depth; int output_depth; int old_width,old_height; struct iw_iodescr readdescr; struct iw_iodescr writedescr; char errmsg[200]; memset(&readdescr,0,sizeof(struct iw_iodescr)); memset(&writedescr,0,sizeof(struct iw_iodescr)); if(!p->quiet) { iwcmd_message_native(p,_T("%s "),p->infn); iwcmd_message_utf8(p,"\xe2\x86\x92"); iwcmd_message_native(p,_T(" %s\n"),p->outfn); } ctx = iw_create_context(); if(!ctx) goto done; iw_set_userdata(ctx,(void*)p); iw_set_warning_fn(ctx,my_warning_handler); if(p->random_seed!=0 || p->randomize) { iw_set_random_seed(ctx,p->randomize, p->random_seed); } if(p->no_gamma) iw_set_value(ctx,IW_VAL_DISABLE_GAMMA,1); if(p->intclamp) iw_set_value(ctx,IW_VAL_INT_CLAMP,1); if(p->no_cslabel) iw_set_value(ctx,IW_VAL_NO_CSLABEL,1); if(p->noopt_grayscale) iw_set_allow_opt(ctx,IW_OPT_GRAYSCALE,0); if(p->noopt_palette) iw_set_allow_opt(ctx,IW_OPT_PALETTE,0); if(p->noopt_reduceto8) iw_set_allow_opt(ctx,IW_OPT_16_TO_8,0); if(p->noopt_stripalpha) iw_set_allow_opt(ctx,IW_OPT_STRIP_ALPHA,0); if(p->noopt_binarytrns) iw_set_allow_opt(ctx,IW_OPT_BINARY_TRNS,0); if(p->edge_policy>=0) iw_set_value(ctx,IW_VAL_EDGE_POLICY,p->edge_policy); if(p->grayscale_formula>0) iw_set_value(ctx,IW_VAL_GRAYSCALE_FORMULA,p->grayscale_formula); readdescr.read_fn = my_readfn; readdescr.fp = (void*)iwcmd_fopen(p->infn,_T("rb")); if(!readdescr.fp) { iw_seterror(ctx,"Failed to open for reading (error code=%d)",(int)errno); goto done; } if(p->infmt==IWCMD_FMT_UNKNOWN) p->infmt=detect_fmt_of_file((FILE*)readdescr.fp); if(p->infmt==IWCMD_FMT_UNKNOWN) { iw_seterror(ctx,"Unsupported input file format."); goto done; } else if(p->infmt==IWCMD_FMT_BMP) { iw_seterror(ctx,"Reading BMP files is not supported."); goto done; } else if(p->infmt==IWCMD_FMT_TIFF) { iw_seterror(ctx,"Reading TIFF files is not supported."); goto done; } if(p->infmt==IWCMD_FMT_JPEG) { if(!iw_read_jpeg_file(ctx,&readdescr)) goto done; } else { if(!iw_read_png_file(ctx,&readdescr)) goto done; } fclose((FILE*)readdescr.fp); readdescr.fp=NULL; imgtype_read = iw_get_value(ctx,IW_VAL_INPUT_IMAGE_TYPE); input_depth = iw_get_value(ctx,IW_VAL_INPUT_DEPTH); output_depth = input_depth; if(p->outfmt==IWCMD_FMT_UNKNOWN) p->outfmt=detect_fmt_from_filename(p->outfn); if(p->outfmt==IWCMD_FMT_UNKNOWN) { iw_seterror(ctx,"Unknown output format; use -outfmt."); goto done; } // We have to tell the library the output format, so it can know what // kinds of images are allowed (e.g. whether transparency is allowed). if(p->outfmt==IWCMD_FMT_JPEG) { iw_set_output_profile(ctx,IW_PROFILE_JPEG); } else if(p->outfmt==IWCMD_FMT_BMP) { iw_set_output_profile(ctx,IW_PROFILE_BMP); } else if(p->outfmt==IWCMD_FMT_TIFF) { iw_set_output_profile(ctx,IW_PROFILE_TIFF); } else { iw_set_output_profile(ctx,IW_PROFILE_PNG); } if(p->depth != -1) { output_depth = p->depth; iw_set_output_depth(ctx,output_depth); } if(p->cs_in_set) { iw_set_input_colorspace(ctx,&p->cs_in); // The default output colorspace is normally derived from the input // file's colorspace. If the caller wants to pretend the input file // is in a different colorspace, then to be consistent we also // use it for the default output colorspace. iw_set_output_colorspace(ctx,&p->cs_in,0); } if(p->cs_out_set) { iw_set_output_colorspace(ctx,&p->cs_out,1); } if(p->resize_alg_x.family) { iwcmd_set_resize(ctx,IW_CHANNELTYPE_ALL,IW_DIMENSION_H,&p->resize_alg_x); } if(p->resize_alg_y.family) { iwcmd_set_resize(ctx,IW_CHANNELTYPE_ALL,IW_DIMENSION_V,&p->resize_alg_y); } if(p->resize_alg_alpha.family) { iwcmd_set_resize(ctx,IW_CHANNELTYPE_ALPHA,IW_DIMENSION_V,&p->resize_alg_alpha); } if(p->dither_family_all) iw_set_dither_type(ctx,IW_CHANNELTYPE_ALL ,p->dither_family_all ,p->dither_subtype_all); if(p->dither_family_nonalpha) iw_set_dither_type(ctx,IW_CHANNELTYPE_NONALPHA,p->dither_family_nonalpha,p->dither_subtype_nonalpha); if(p->dither_family_red) iw_set_dither_type(ctx,IW_CHANNELTYPE_RED ,p->dither_family_red ,p->dither_subtype_red); if(p->dither_family_green) iw_set_dither_type(ctx,IW_CHANNELTYPE_GREEN,p->dither_family_green,p->dither_subtype_green); if(p->dither_family_blue) iw_set_dither_type(ctx,IW_CHANNELTYPE_BLUE ,p->dither_family_blue ,p->dither_subtype_blue); if(p->dither_family_gray) iw_set_dither_type(ctx,IW_CHANNELTYPE_GRAY ,p->dither_family_gray ,p->dither_subtype_gray); if(p->dither_family_alpha) iw_set_dither_type(ctx,IW_CHANNELTYPE_ALPHA,p->dither_family_alpha,p->dither_subtype_alpha); if(p->color_count_all) iw_set_color_count (ctx,IW_CHANNELTYPE_ALL ,p->color_count_all); if(p->color_count_nonalpha) iw_set_color_count(ctx,IW_CHANNELTYPE_NONALPHA,p->color_count_nonalpha); if(p->color_count_red) iw_set_color_count(ctx,IW_CHANNELTYPE_RED ,p->color_count_red); if(p->color_count_green) iw_set_color_count(ctx,IW_CHANNELTYPE_GREEN,p->color_count_green); if(p->color_count_blue) iw_set_color_count(ctx,IW_CHANNELTYPE_BLUE ,p->color_count_blue); if(p->color_count_gray) iw_set_color_count(ctx,IW_CHANNELTYPE_GRAY ,p->color_count_gray); if(p->color_count_alpha) iw_set_color_count(ctx,IW_CHANNELTYPE_ALPHA,p->color_count_alpha); if(p->grayscale) { iw_set_value(ctx,IW_VAL_CVT_TO_GRAYSCALE,1); } else if(p->condgrayscale) { if(iw_get_value(ctx,IW_VAL_INPUT_NATIVE_GRAYSCALE)) { iw_set_value(ctx,IW_VAL_CVT_TO_GRAYSCALE,1); } } if(p->offset_r_h!=0.0) iw_set_channel_offset(ctx,IW_CHANNELTYPE_RED, IW_DIMENSION_H,p->offset_r_h); if(p->offset_g_h!=0.0) iw_set_channel_offset(ctx,IW_CHANNELTYPE_GREEN,IW_DIMENSION_H,p->offset_g_h); if(p->offset_b_h!=0.0) iw_set_channel_offset(ctx,IW_CHANNELTYPE_BLUE, IW_DIMENSION_H,p->offset_b_h); if(p->offset_r_v!=0.0) iw_set_channel_offset(ctx,IW_CHANNELTYPE_RED, IW_DIMENSION_V,p->offset_r_v); if(p->offset_g_v!=0.0) iw_set_channel_offset(ctx,IW_CHANNELTYPE_GREEN,IW_DIMENSION_V,p->offset_g_v); if(p->offset_b_v!=0.0) iw_set_channel_offset(ctx,IW_CHANNELTYPE_BLUE, IW_DIMENSION_V,p->offset_b_v); if(p->apply_bkgd) { iw_set_applybkgd(ctx,IW_BKGDCOLORSPACE_SRGB,p->bkgd.r,p->bkgd.g,p->bkgd.b); if(p->bkgd_checkerboard) { iw_set_bkgd_checkerboard(ctx,p->bkgd_check_size,p->bkgd2.r,p->bkgd2.g,p->bkgd2.b); iw_set_bkgd_checkerboard_origin(ctx,p->bkgd_check_origin_x,p->bkgd_check_origin_y); } } if(p->use_bkgd_label) { iw_set_value(ctx,IW_VAL_USE_BKGD_LABEL,1); } iw_get_input_image_density(ctx,&p->xdens,&p->ydens,&p->density_code); old_width=iw_get_value(ctx,IW_VAL_INPUT_WIDTH); old_height=iw_get_value(ctx,IW_VAL_INPUT_HEIGHT); if(p->use_crop) { // If we're cropping, adjust some things so that "bestfit" works. if(p->crop_x<0) p->crop_x=0; if(p->crop_y<0) p->crop_y=0; if(p->crop_x>old_width-1) p->crop_x=old_width-1; if(p->crop_y>old_height-1) p->crop_y=old_height-1; if(p->crop_w<0 || p->crop_w>old_width-p->crop_x) p->crop_w=old_width-p->crop_x; if(p->crop_h<0 || p->crop_h>old_height-p->crop_y) p->crop_h=old_height-p->crop_y; if(p->crop_w<1) p->crop_w=1; if(p->crop_h<1) p->crop_h=1; old_width = p->crop_w; old_height = p->crop_h; } if(p->new_width<0) p->new_width = -1; if(p->new_height<0) p->new_height = -1; if(p->new_width==0) p->new_width = 1; if(p->new_height==0) p->new_height = 1; if(p->new_width == -1 && p->new_height == -1) { // Neither -width nor -height specified. Keep image the same size. p->new_width=old_width; p->new_height=old_height; } else if(p->new_height == -1) { // -width given but not -height. Fit to width. p->new_height=1000000; do_bestfit(p,old_width,old_height); } else if(p->new_width == -1) { // -height given but not -width. Fit to height. p->new_width=1000000; do_bestfit(p,old_width,old_height); } else if(p->bestfit) { // -width and -height and -bestfit all given. Best-fit into the given dimensions. do_bestfit(p,old_width,old_height); } else { // -width and -height given but not -bestfit. Use the exact dimensions given. ; } if(p->new_width<1) p->new_width=1; if(p->new_height<1) p->new_height=1; if(p->quiet) { ; } else if(p->new_width==old_width && p->new_height==old_height) { iwcmd_message_utf8(p,"Processing (%d\xc3\x97%d)\n",p->new_width,p->new_height); } else { iwcmd_message_utf8(p,"Resizing (%d\xc3\x97%d) \xe2\x86\x92 (%d\xc3\x97%d)\n",old_width,old_height, p->new_width,p->new_height); } iw_set_output_canvas_size(ctx,p->new_width,p->new_height); if(p->use_crop) { iw_set_input_crop(ctx,p->crop_x,p->crop_y,p->crop_w,p->crop_h); } if(!iw_process_image(ctx)) goto done; if(p->interlace) { iw_set_value(ctx,IW_VAL_OUTPUT_INTERLACED,1); } writedescr.write_fn = my_writefn; writedescr.fp = (void*)iwcmd_fopen(p->outfn,_T("wb")); if(!writedescr.fp) { iw_seterror(ctx,"Failed to open for writing (error code=%d)",(int)errno); goto done; } if(p->outfmt==IWCMD_FMT_JPEG) { if(p->jpeg_quality>0) iw_set_value(ctx,IW_VAL_JPEG_QUALITY,p->jpeg_quality); if(p->jpeg_samp_factor_h>0) iw_set_value(ctx,IW_VAL_JPEG_SAMP_FACTOR_H,p->jpeg_samp_factor_h); if(p->jpeg_samp_factor_v>0) iw_set_value(ctx,IW_VAL_JPEG_SAMP_FACTOR_V,p->jpeg_samp_factor_v); if(!iw_write_jpeg_file(ctx,&writedescr)) goto done; } else if(p->outfmt==IWCMD_FMT_BMP) { if(!iw_write_bmp_file(ctx,&writedescr)) goto done; } else if(p->outfmt==IWCMD_FMT_TIFF) { if(!iw_write_tiff_file(ctx,&writedescr)) goto done; } else { if(p->pngcmprlevel >= 0) iw_set_value(ctx,IW_VAL_PNG_CMPR_LEVEL,p->pngcmprlevel); if(!iw_write_png_file(ctx,&writedescr)) goto done; } fclose((FILE*)writedescr.fp); writedescr.fp=NULL; retval = 1; done: if(readdescr.fp) fclose((FILE*)readdescr.fp); if(writedescr.fp) fclose((FILE*)writedescr.fp); if(ctx) { if(iw_get_errorflag(ctx)) { iwcmd_error_utf8(p,"imagew error: %s\n",iw_get_errormsg(ctx,errmsg,200)); } } iw_destroy_context(ctx); return retval; }