Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
// 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);
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}