Exemplo n.º 1
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;

}
Exemplo n.º 2
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;
}
Exemplo 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;
		}
	}
}
Exemplo n.º 4
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);
}
Exemplo n.º 5
0
static void iwwebp_gray_to_rgb(struct iwwebpwritecontext *wctx)
{
	int i,j;
	struct iw_image *img = wctx->img;
	size_t bpr;
	unsigned char g;

	bpr = 3 * img->width;
	wctx->tmppixels = iw_malloc_large(wctx->ctx, img->height, bpr);
	if(!wctx) return;

	for(j=0;j<img->height;j++) {
		for(i=0;i<img->width;i++) {
			g = img->pixels[j*img->bpr+i];
			wctx->tmppixels[j*bpr+3*i+0]=g;
			wctx->tmppixels[j*bpr+3*i+1]=g;
			wctx->tmppixels[j*bpr+3*i+2]=g;
		}
	}
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
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);
}
Exemplo n.º 8
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);
}
Exemplo n.º 9
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);
}
Exemplo n.º 10
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;
}