Ejemplo n.º 1
0
static void iw_opt_16_to_8(struct iw_context *ctx, struct iw_opt_ctx *optctx, int spp)
{
	unsigned char *newpixels;
	size_t newbpr;
	int i,j;

	if(!ctx->opt_16_to_8) return;

	newbpr = iw_calc_bytesperrow(optctx->width,8*spp);
	newpixels = iw_malloc_large(ctx, newbpr, optctx->height);
	if(!newpixels) return;

	for(j=0;j<optctx->height;j++) {
		for(i=0;i<spp*optctx->width;i++) {
			// i is a sample number, not a pixel number.
			newpixels[j*newbpr + i] = optctx->pixelsptr[j*optctx->bpr + i*2];
		}
	}

	// Remove previous image if it was allocated by the optimization code.
	if(optctx->tmp_pixels) iw_free(optctx->tmp_pixels);

	// Attach our new image
	optctx->tmp_pixels = newpixels;
	optctx->pixelsptr = optctx->tmp_pixels;
	optctx->bpr = newbpr;
	optctx->bit_depth = 8;
}
Ejemplo n.º 2
0
// Create a new (8-bit) image by copying up to 3 channels from the old image.
static void iw_opt_copychannels_8(struct iw_context *ctx, struct iw_opt_ctx *optctx,
			int new_imgtype, int c0, int c1, int c2)
{
	unsigned char *newpixels;
	int oldnc, newnc; // num_channels
	size_t newbpr;
	int i,j;

	oldnc = iw_imgtype_num_channels(optctx->imgtype);
	newnc = iw_imgtype_num_channels(new_imgtype);

	newbpr = iw_calc_bytesperrow(optctx->width,8*newnc);
	newpixels = iw_malloc_large(ctx, newbpr, optctx->height);
	if(!newpixels) return;

	for(j=0;j<optctx->height;j++) {
		for(i=0;i<optctx->width;i++) {
			newpixels[j*newbpr + i*newnc +0] = optctx->pixelsptr[j*optctx->bpr + i*oldnc +c0];
			if(newnc>1)
				newpixels[j*newbpr + i*newnc +1] = optctx->pixelsptr[j*optctx->bpr + i*oldnc +c1];
			if(newnc>2)
				newpixels[j*newbpr + i*newnc +2] = optctx->pixelsptr[j*optctx->bpr + i*oldnc +c2];
		}
	}

	// Remove previous image if it was allocated by the optimization code.
	if(optctx->tmp_pixels) iw_free(optctx->tmp_pixels);

	// Attach our new image
	optctx->tmp_pixels = newpixels;
	optctx->pixelsptr = optctx->tmp_pixels;
	optctx->bpr = newbpr;
	optctx->imgtype = new_imgtype;

}
Ejemplo n.º 3
0
static void iw_opt_16_to_8(struct iw_context *ctx, struct iw_opt_ctx *optctx, int spp)
{
	iw_byte *newpixels;
	size_t newbpr;
	int i,j,k;

	if(!ctx->opt_16_to_8) return;

	newbpr = iw_calc_bytesperrow(optctx->width,8*spp);
	newpixels = iw_malloc_large(ctx, newbpr, optctx->height);
	if(!newpixels) return;

	for(j=0;j<optctx->height;j++) {
		for(i=0;i<spp*optctx->width;i++) {
			// i is a sample number, not a pixel number.
			newpixels[j*newbpr + i] = optctx->pixelsptr[j*optctx->bpr + i*2];
		}
	}

	// Remove previous image if it was allocated by the optimization code.
	if(optctx->tmp_pixels) iw_free(ctx,optctx->tmp_pixels);

	// Attach our new image
	optctx->tmp_pixels = newpixels;
	optctx->pixelsptr = optctx->tmp_pixels;
	optctx->bpr = newbpr;
	optctx->bit_depth = 8;

	// If there's a background color label, also reduce its precision.
	if(optctx->has_bkgdlabel) {
		for(k=0;k<4;k++) {
			optctx->bkgdlabel[k] >>= 8;
		}
	}
}
Ejemplo n.º 4
0
void *iw_realloc(const char *file, unsigned int line, void *ptr, size_t size) {
    if(!iw_memory_tracking) {
        return realloc(ptr, size);
    }

    void *new_chunk = NULL;

    // TODO: To simplify realloc we just allocate a new memory chunk and free the
    // old one.
    if(size != 0) {
        new_chunk = iw_malloc(file, line, size);
        if(new_chunk == NULL) {
            // Realloc does not free or move the old memory if allocation fails.
            return NULL;
        }
    }

    if(ptr != NULL) {
        if(new_chunk != NULL) {
            void *len_ptr = ptr - PRE_GUARD_SIZE - LEN_SIZE;
            unsigned int len = ntohl(*(unsigned int *)len_ptr);
            memcpy(new_chunk, ptr, len);
        }
        iw_free(ptr);
    }

    return new_chunk;
}
Ejemplo n.º 5
0
static void iwopt_try_gray8_binary_trns(struct iw_context *ctx, struct iw_opt_ctx *optctx)
{
	int i,j;
	const unsigned char *ptr;
	unsigned char *ptr2;
	unsigned char clr_used[256];
	unsigned char key_clr;
	unsigned char *trns_mask = NULL;

	if(!(ctx->output_profile&IW_PROFILE_BINARYTRNS)) return;
	if(!ctx->opt_binary_trns) return;

	memset(&clr_used,0,256*sizeof(unsigned char));

	trns_mask = iw_malloc_large(ctx, optctx->width, optctx->height);
	if(!trns_mask) goto done;

	for(j=0;j<optctx->height;j++) {
		for(i=0;i<optctx->width;i++) {
			ptr = &optctx->pixelsptr[j*optctx->bpr+i*2];
			if(ptr[1]==0) {
				// Transparent pixel
				trns_mask[j*optctx->width+i] = 0;
				continue;
			}
			else {
				// Nontransparent pixel
				trns_mask[j*optctx->width+i] = 1;
			}
			clr_used[(int)ptr[0]] = 1;
		}
	}

	if(!iwopt_find_unused(clr_used,256,&key_clr)) {
		goto done;
	}

	// Strip the alpha channel:
	iw_opt_copychannels_8(ctx,optctx,IW_IMGTYPE_GRAY,0,0,0);
	if(!optctx->tmp_pixels) goto done;

	// Change the color of all transparent pixels to the key color
	for(j=0;j<optctx->height;j++) {
		for(i=0;i<optctx->width;i++) {
			ptr2 = &optctx->tmp_pixels[j*optctx->bpr+i];
			if(trns_mask[j*optctx->width+i]==0) {
				ptr2[0] = key_clr;
			}
		}
	}

	optctx->has_colorkey_trns = 1;
	optctx->colorkey_r = key_clr;
	optctx->colorkey_g = key_clr;
	optctx->colorkey_b = key_clr;

done:
	if(trns_mask) iw_free(trns_mask);
}
Ejemplo n.º 6
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.º 7
0
// Optimize to palette, or 1-, 2-, or 4-bpp grayscale.
static void iwopt_try_pal_lowgray_optimization(struct iw_context *ctx, struct iw_opt_ctx *optctx)
{
	int ret;
	int binary_trns;
	unsigned int trns_shade;

	if(!(ctx->output_profile&IW_PROFILE_PAL1) &&
	   !(ctx->output_profile&IW_PROFILE_PAL2) &&
	   !(ctx->output_profile&IW_PROFILE_PAL4) &&
	   !(ctx->output_profile&IW_PROFILE_PAL8) &&
	   !(ctx->output_profile&IW_PROFILE_GRAY1) &&
	   !(ctx->output_profile&IW_PROFILE_GRAY2) &&
	   !(ctx->output_profile&IW_PROFILE_GRAY4) )
	{
		// Output format doesn't support anything that this optimization can provide.
		return;
	}

	if(optctx->bit_depth!=8) {
		// Palettes aren't supported with bitdepth>8.
		return;
	}

	optctx->palette = iw_malloc(ctx,sizeof(struct iw_palette));
	if(!optctx->palette) return;

	optctx->palette->num_entries=0;

	ret = optctx_collect_palette_colors(ctx,optctx);
	if(!ret) {
		// Image can't be converted to a palette image.
		goto done;
	}

	// optctx->palette now contains a palette that can be used.

	// For images that have at most 256 (8-bit-compatible) colors, the order
	// of preference is gray1, pal1, gray2, pal2, gray4, pal4, gray8, pal8.

	if(ctx->opt_grayscale && (ctx->output_profile&IW_PROFILE_GRAY1) && iwopt_palette_is_valid_gray(ctx,optctx,1,&binary_trns,&trns_shade)) {
		// Replace the palette with a fully-populated grayscale palette.
		// The palette might already be correct, but it might not be.
		// It will be missing any gray shade that wasn't in the image.
		iwopt_make_gray_palette(ctx,optctx,1);
		if(binary_trns) {
			optctx->has_colorkey_trns = 1;
			optctx->colorkey_r = optctx->colorkey_b = optctx->colorkey_g = trns_shade;
		}
	}
	else if(iwopt_palette_opt_ok(ctx,optctx,1)) {
		;
	}
	else if(ctx->opt_grayscale && (ctx->output_profile&IW_PROFILE_GRAY2) && iwopt_palette_is_valid_gray(ctx,optctx,2,&binary_trns,&trns_shade)) {
		iwopt_make_gray_palette(ctx,optctx,2);
		if(binary_trns) {
			optctx->has_colorkey_trns = 1;
			optctx->colorkey_r = optctx->colorkey_b = optctx->colorkey_g = trns_shade;
		}
	}
	else if(iwopt_palette_opt_ok(ctx,optctx,2)) {
		;
	}
	else if(ctx->opt_grayscale && (ctx->output_profile&IW_PROFILE_GRAY4) && iwopt_palette_is_valid_gray(ctx,optctx,4,&binary_trns,&trns_shade)) {
		iwopt_make_gray_palette(ctx,optctx,4);
		if(binary_trns) {
			optctx->has_colorkey_trns = 1;
			optctx->colorkey_r = optctx->colorkey_b = optctx->colorkey_g = trns_shade;
		}
	}
	else if(iwopt_palette_opt_ok(ctx,optctx,4)) {
		;
	}
	else if(ctx->opt_grayscale && (ctx->output_profile&IW_PROFILE_GRAYSCALE) && iwopt_palette_is_valid_gray(ctx,optctx,8,&binary_trns,&trns_shade)) {
		// This image can best be encoded as 8-bit grayscale. We don't handle that here.
		goto done;
	}
	else if(iwopt_palette_opt_ok(ctx,optctx,8)) {
		;
	}
	else {
		// Found no optimizations that we can perform.
		goto done;
	}

	if(!optctx->palette_is_grayscale) {
		// Sort the palette
		qsort((void*)optctx->palette->entry,optctx->palette->num_entries,
			sizeof(struct iw_rgba8color),iwopt_palsortfunc);
	}

	iwopt_convert_to_palette_image(ctx,optctx);

done:
	if(optctx->imgtype!=IW_IMGTYPE_PALETTE) {
		iw_free(optctx->palette);
		optctx->palette = NULL;
	}
}
Ejemplo n.º 8
0
static void iwopt_convert_to_palette_image(struct iw_context *ctx, struct iw_opt_ctx *optctx)
{
	unsigned char *newpixels;
	size_t newbpr;
	int x,y;
	struct iw_rgba8color c;
	const unsigned char *ptr;
	int spp;
	int e;

	spp = iw_imgtype_num_channels(optctx->imgtype);

	newbpr = optctx->width;
	newpixels = iw_malloc_large(ctx, newbpr, optctx->height);
	if(!newpixels) return;

	for(y=0;y<optctx->height;y++) {
		for(x=0;x<optctx->width;x++) {
			ptr = &optctx->pixelsptr[y*optctx->bpr + x*spp];

			if(optctx->imgtype==IW_IMGTYPE_RGB) {
				c.r = ptr[0];
				c.g = ptr[1];
				c.b = ptr[2];
				c.a = 255;
			}
			else if(optctx->imgtype==IW_IMGTYPE_RGBA) {
				c.r = ptr[0];
				c.g = ptr[1];
				c.b = ptr[2];
				c.a = ptr[3];
				if(c.a==0) { c.r = c.g = c.b = 0; }
			}
			else if(optctx->imgtype==IW_IMGTYPE_GRAYA) {
				c.r = c.g = c.b = ptr[0];
				c.a = ptr[1];
				if(c.a==0) { c.r = c.g = c.b = 0; }
			}
			else { // optctx->imgtype==IW_IMGTYPE_GRAY(?)
				c.r = c.g = c.b = ptr[0];
				c.a = 255;
			}

			if(optctx->has_colorkey_trns && c.a==0) {
				// We'll only get here if the image is really grayscale.
				e = optctx->colorkey_r;
			}
			else {
				e = iwopt_find_color(optctx->palette,&c);
				if(e<0) e=0; // shouldn't happen
			}

			newpixels[y*newbpr + x] = e;
		}
	}

	// Remove previous image if it was allocated by the optimization code.
	if(optctx->tmp_pixels) iw_free(optctx->tmp_pixels);

	// Attach our new image
	optctx->tmp_pixels = newpixels;
	optctx->pixelsptr = optctx->tmp_pixels;
	optctx->bpr = newbpr;
	optctx->bit_depth = 8;
	optctx->imgtype = IW_IMGTYPE_PALETTE;
}
Ejemplo n.º 9
0
static void iwopt_try_rgb16_binary_trns(struct iw_context *ctx, struct iw_opt_ctx *optctx)
{
	int i,j;
	const unsigned char *ptr;
	unsigned char *ptr2;
	unsigned char clr_used[256];
	unsigned char key_clr; // low 8-bits of red component of the key color
	unsigned char *trns_mask = NULL;

	if(!(ctx->output_profile&IW_PROFILE_BINARYTRNS)) return;
	if(!ctx->opt_binary_trns) return;

	memset(&clr_used,0,256*sizeof(unsigned char));

	trns_mask = iw_malloc_large(ctx, optctx->width, optctx->height);
	if(!trns_mask) goto done;

	for(j=0;j<optctx->height;j++) {
		for(i=0;i<optctx->width;i++) {
			ptr = &optctx->pixelsptr[j*optctx->bpr+(i*2)*4];
			if(ptr[6]==0 && ptr[7]==0) {
				// Transparent pixel
				trns_mask[j*optctx->width+i] = 0;
				continue;
			}
			else {
				// Nontransparent pixel
				trns_mask[j*optctx->width+i] = 1;
			}
			// For the colors we look for, all bytes are 192 except possibly the low-red byte.
			if(ptr[0]!=192 || ptr[2]!=192 || ptr[3]!=192 || ptr[4]!=192 || ptr[5]!=192)
				continue;
			clr_used[(int)ptr[1]] = 1;
		}
	}

	if(!iwopt_find_unused(clr_used,256,&key_clr)) {
		goto done;
	}

	// Strip the alpha channel:
	iw_opt_copychannels_16(ctx,optctx,IW_IMGTYPE_RGB,0,1,2);
	if(!optctx->tmp_pixels) goto done;

	// Change the color of all transparent pixels to the key color
	for(j=0;j<optctx->height;j++) {
		for(i=0;i<optctx->width;i++) {
			ptr2 = &optctx->tmp_pixels[j*optctx->bpr+(i*2)*3];
			if(trns_mask[j*optctx->width+i]==0) {
				ptr2[0] = 192;
				ptr2[1] = key_clr;
				ptr2[2] = 192;
				ptr2[3] = 192;
				ptr2[4] = 192;
				ptr2[5] = 192;
			}
		}
	}

	optctx->has_colorkey_trns = 1;
	optctx->colorkey_r = 192*256+key_clr;
	optctx->colorkey_g = 192*256+192;
	optctx->colorkey_b = 192*256+192;

done:
	if(trns_mask) iw_free(trns_mask);
}
Ejemplo n.º 10
0
// Try to convert from RGBA to RGB+binary trns.
// Assumes we already know there is transparency, but no partial transparency.
static void iwopt_try_rgb8_binary_trns(struct iw_context *ctx, struct iw_opt_ctx *optctx)
{
	int i,j;
	const unsigned char *ptr;
	unsigned char *ptr2;
	unsigned char clr_used[256];
	unsigned char key_clr; // Red component of the key color
	unsigned char *trns_mask = NULL;

	if(!(ctx->output_profile&IW_PROFILE_BINARYTRNS)) return;
	if(!ctx->opt_binary_trns) return;

	// Try to find a color that's not used in the image.
	// Looking for all 2^24 possible colors is too much work.
	// We will just look for 256 predefined colors: R={0-255},G=192,B=192
	memset(&clr_used,0,256*sizeof(unsigned char));

	// Hard to decide how to do this. I don't want the optimization phase
	// to modify img2.pixels, though that would be the easiest method.
	// Another option would be to make a version of iw_opt_copychannels_8()
	// that sets the transparent pixels to a certain value, but that would
	// get messy.
	// Instead, I'll make a transparency mask, then strip the alpha
	// channel, then use the mask to patch up the new image.
	trns_mask = iw_malloc_large(ctx, optctx->width, optctx->height);
	if(!trns_mask) goto done;

	for(j=0;j<optctx->height;j++) {
		for(i=0;i<optctx->width;i++) {
			ptr = &optctx->pixelsptr[j*optctx->bpr+i*4];
			if(ptr[3]==0) {
				// transparent pixel
				trns_mask[j*optctx->width+i] = 0; // Remember which pixels are transparent.
				continue;
			}
			else {
				trns_mask[j*optctx->width+i] = 1;
			}
			if(ptr[1]!=192 || ptr[2]!=192) continue;
			clr_used[(int)ptr[0]] = 1;
		}
	}

	if(!iwopt_find_unused(clr_used,256,&key_clr)) {
		goto done;
	}

	// Strip the alpha channel:
	iw_opt_copychannels_8(ctx,optctx,IW_IMGTYPE_RGB,0,1,2);
	if(!optctx->tmp_pixels) goto done;

	// Change the color of all transparent pixels to the key color
	for(j=0;j<optctx->height;j++) {
		for(i=0;i<optctx->width;i++) {
			ptr2 = &optctx->tmp_pixels[j*optctx->bpr+i*3];
			if(trns_mask[j*optctx->width+i]==0) {
				ptr2[0] = key_clr;
				ptr2[1] = 192;
				ptr2[2] = 192;
			}
		}
	}

	optctx->has_colorkey_trns = 1;
	optctx->colorkey_r = key_clr;
	optctx->colorkey_g = 192;
	optctx->colorkey_b = 192;

done:
	if(trns_mask) iw_free(trns_mask);
}
Ejemplo n.º 11
0
static void iwopt_try_gray16_binary_trns(struct iw_context *ctx, struct iw_opt_ctx *optctx)
{
	int i,j;
	const iw_byte *ptr;
	iw_byte *ptr2;
	iw_byte clr_used[256];
	iw_byte key_clr=0; // low 8-bits of the key color
	iw_byte *trns_mask = NULL;

	if(!(ctx->output_profile&IW_PROFILE_BINARYTRNS)) return;
	if(!ctx->opt_binary_trns) return;

	iw_zeromem(clr_used,256);

	trns_mask = iw_malloc_large(ctx, optctx->width, optctx->height);
	if(!trns_mask) goto done;

	for(j=0;j<optctx->height;j++) {
		for(i=0;i<optctx->width;i++) {
			ptr = &optctx->pixelsptr[j*optctx->bpr+(i*2)*2];
			if(ptr[2]==0 && ptr[3]==0) {
				// Transparent pixel
				trns_mask[j*optctx->width+i] = 0;
				continue;
			}
			else {
				// Nontransparent pixel
				trns_mask[j*optctx->width+i] = 1;
			}
			// For the colors we look for, the high byte is always 192.
			if(ptr[0]!=192)
				continue;
			clr_used[(int)ptr[1]] = 1;
		}
	}

	if(!iwopt_find_unused(clr_used,256,&key_clr)) {
		goto done;
	}

	// Strip the alpha channel:
	iw_opt_copychannels_16(ctx,optctx,IW_IMGTYPE_GRAY,0,0,0);
	if(!optctx->tmp_pixels) goto done;

	// Change the color of all transparent pixels to the key color
	for(j=0;j<optctx->height;j++) {
		for(i=0;i<optctx->width;i++) {
			ptr2 = &optctx->tmp_pixels[j*optctx->bpr+(i*2)];
			if(trns_mask[j*optctx->width+i]==0) {
				ptr2[0] = 192;
				ptr2[1] = key_clr;
			}
		}
	}

	optctx->has_colorkey_trns = 1;
	optctx->colorkey[IW_CHANNELTYPE_RED] = 192*256+key_clr;
	optctx->colorkey[IW_CHANNELTYPE_GREEN] = 192*256+key_clr;
	optctx->colorkey[IW_CHANNELTYPE_BLUE] = 192*256+key_clr;

done:
	if(trns_mask) iw_free(ctx,trns_mask);
}
Ejemplo n.º 12
0
static int iwwebp_read_main(struct iwwebpreadcontext *rctx)
{
	struct iw_image *img;
	int retval=0;
	void *webpimage=NULL;
	size_t webpimage_size=0;
	uint8_t* uncmpr_webp_pixels = NULL;
	int width, height;
	size_t npixels;
	int bytes_per_pixel;

	img = rctx->img;

	// TODO: This is really memory-inefficient.
	// Honestly, I just can't figure out libwebp.
	// It has several different ways to decode a webp image, but they don't
	// seem to add up to any way to do it without allocating at least one
	// more image's worth of memory than ought to be necessary.
	// It's like it expects you to know the width, height, and color format
	// of the image before that information has been read from the file.

	// Read the whole WebP file into a memory block.
	if(!iw_file_to_memory(rctx->ctx, rctx->iodescr, &webpimage, &webpimage_size)) {
		goto done;
	}

	// Have libwebp decode that memory block, to a memory block that
	// it allocates.
	width=height=0;
	uncmpr_webp_pixels = WebPDecodeRGBA(webpimage, (uint32_t)webpimage_size, &width, &height);
	if(!uncmpr_webp_pixels) goto done;

	if(!iw_check_image_dimensons(rctx->ctx,width,height))
		goto done;

	npixels = ((size_t)width)*height;

	// Figure out if the image has transparency, etc.
	iwwebp_scan_pixels(rctx,uncmpr_webp_pixels,npixels);

	// Choose the color format to use for IW's internal source image.
	if(rctx->has_color)
		img->imgtype = rctx->has_transparency ? IW_IMGTYPE_RGBA : IW_IMGTYPE_RGB;
	else
		img->imgtype = rctx->has_transparency ? IW_IMGTYPE_GRAYA : IW_IMGTYPE_GRAY;

	img->width = width;
	img->height = height;
	img->bit_depth = 8;
	bytes_per_pixel = iw_imgtype_num_channels(img->imgtype);
	img->bpr = bytes_per_pixel * img->width;
	img->pixels = (unsigned char*)iw_malloc_large(rctx->ctx, img->bpr, img->height);
	if(!img->pixels) goto done;

	switch(img->imgtype) {
	case IW_IMGTYPE_GRAY:  iwwebpr_convert_pixels_gray(rctx,(unsigned char*)uncmpr_webp_pixels,npixels); break;
	case IW_IMGTYPE_GRAYA: iwwebpr_convert_pixels_graya(rctx,(unsigned char*)uncmpr_webp_pixels,npixels); break;
	case IW_IMGTYPE_RGB:   iwwebpr_convert_pixels_rgb(rctx,(unsigned char*)uncmpr_webp_pixels,npixels); break;
	default:               iwwebpr_convert_pixels_rgba(rctx,(unsigned char*)uncmpr_webp_pixels,npixels); break;
	}

	retval=1;

done:
	if(webpimage) iw_free(webpimage);

	// Caution: We must use the right free() function: the one that corresponds
	// to the malloc function that libwebp used. But we can't always be sure
	// how to do that. It depends on how libwebp was compiled.
	if(uncmpr_webp_pixels) free(uncmpr_webp_pixels);

	return retval;
}