Esempio n. 1
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);
}
Esempio n. 2
0
// Strip alpha channel if there are no actual transparent pixels, etc.
void iw_optimize_image(struct iw_context *ctx)
{
	struct iw_opt_ctx *optctx;

	optctx = &ctx->optctx;

	memset(optctx,0,sizeof(struct iw_opt_ctx));
	optctx->width = ctx->img2.width;
	optctx->height = ctx->img2.height;
	optctx->imgtype = ctx->img2.imgtype;
	optctx->bit_depth = ctx->img2.bit_depth;
	optctx->bpr = ctx->img2.bpr;
	optctx->pixelsptr = ctx->img2.pixels;
	optctx->has_transparency=0;
	optctx->has_partial_transparency=0;
	optctx->has_16bit_precision=0;
	optctx->has_color=0;

	if(ctx->img2.sampletype!=IW_SAMPLETYPE_UINT) {
		return;
	}

	make_transparent_pixels_black(ctx,&ctx->img2);

	if(!iw_opt_scanpixels(ctx,optctx)) {
		goto noscan;
	}

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==16 && !optctx->has_16bit_precision) {
		iw_opt_16_to_8(ctx,optctx,4);
	}

	if(optctx->imgtype==IW_IMGTYPE_RGB && optctx->bit_depth==16 && !optctx->has_16bit_precision) {
		iw_opt_16_to_8(ctx,optctx,3);
	}

	if(optctx->imgtype==IW_IMGTYPE_GRAYA && optctx->bit_depth==16 && !optctx->has_16bit_precision) {
		iw_opt_16_to_8(ctx,optctx,2);
	}

	if(optctx->imgtype==IW_IMGTYPE_GRAY && optctx->bit_depth==16 && !optctx->has_16bit_precision) {
		iw_opt_16_to_8(ctx,optctx,1);
	}

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==8 && !optctx->has_transparency && ctx->opt_strip_alpha) {
		iw_opt_copychannels_8(ctx,optctx,IW_IMGTYPE_RGB,0,1,2); // RGBA -> RGB
	}

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==16 && !optctx->has_transparency && ctx->opt_strip_alpha) {
		iw_opt_copychannels_16(ctx,optctx,IW_IMGTYPE_RGB,0,1,2); // RGBA -> RGB (16)
	}

	if(optctx->imgtype==IW_IMGTYPE_GRAYA && optctx->bit_depth==16 && !optctx->has_transparency && ctx->opt_strip_alpha) {
		iw_opt_copychannels_16(ctx,optctx,IW_IMGTYPE_GRAY,0, 0,0); // GA -> G (16)
	}

	if(optctx->imgtype==IW_IMGTYPE_GRAYA && optctx->bit_depth==8 && !optctx->has_transparency && ctx->opt_strip_alpha) {
		iw_opt_copychannels_8(ctx,optctx,IW_IMGTYPE_GRAY,0, 0,0); // GA -> G
	}

	if(optctx->imgtype==IW_IMGTYPE_RGB && optctx->bit_depth==8 && !optctx->has_color &&
	   (ctx->output_profile&IW_PROFILE_GRAYSCALE) && ctx->opt_grayscale)
	{
		iw_opt_copychannels_8(ctx,optctx,IW_IMGTYPE_GRAY,0, 0,0); // RGB -> G
	}

	if(optctx->imgtype==IW_IMGTYPE_RGB && optctx->bit_depth==16 && !optctx->has_color &&
	   (ctx->output_profile&IW_PROFILE_GRAYSCALE) && ctx->opt_grayscale)
	{
		iw_opt_copychannels_16(ctx,optctx,IW_IMGTYPE_GRAY,0, 0,0); // RGB -> G (16)
	}

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==8 && !optctx->has_color &&
	   (ctx->output_profile&IW_PROFILE_GRAYSCALE) && ctx->opt_grayscale)
	{
		iw_opt_copychannels_8(ctx,optctx,IW_IMGTYPE_GRAYA,0,3, 0); // RGBA -> GA
	}

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==16 && !optctx->has_color &&
	   (ctx->output_profile&IW_PROFILE_GRAYSCALE) && ctx->opt_grayscale)
	{
		iw_opt_copychannels_16(ctx,optctx,IW_IMGTYPE_GRAYA,0,3, 0); // RGBA -> GA (16)
	}

noscan:

	iwopt_try_pal_lowgray_optimization(ctx,optctx);

	// Try to convert an alpha channel to binary transparency.

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==8 && !optctx->has_partial_transparency) {
		iwopt_try_rgb8_binary_trns(ctx,optctx);
	}

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==16 && !optctx->has_partial_transparency) {
		iwopt_try_rgb16_binary_trns(ctx,optctx);
	}

	if(optctx->imgtype==IW_IMGTYPE_GRAYA && optctx->bit_depth==8 && !optctx->has_partial_transparency) {
		iwopt_try_gray8_binary_trns(ctx,optctx);
	}

	if(optctx->imgtype==IW_IMGTYPE_GRAYA && optctx->bit_depth==16 && !optctx->has_partial_transparency) {
		iwopt_try_gray16_binary_trns(ctx,optctx);
	}
}
Esempio n. 3
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);
}
Esempio n. 4
0
// Strip alpha channel if there are no actual transparent pixels, etc.
void iwpvt_optimize_image(struct iw_context *ctx)
{
	struct iw_opt_ctx *optctx;
	int k;

	optctx = &ctx->optctx;

	//iw_zeromem(optctx,sizeof(struct iw_opt_ctx));
	optctx->width = ctx->img2.width;
	optctx->height = ctx->img2.height;
	optctx->imgtype = ctx->img2.imgtype;
	optctx->bit_depth = ctx->img2.bit_depth;
	optctx->bpr = ctx->img2.bpr;
	optctx->pixelsptr = ctx->img2.pixels;
	//optctx->has_transparency=0;
	//optctx->has_partial_transparency=0;
	//optctx->has_16bit_precision=0;
	//optctx->has_color=0;
	if(ctx->img2.has_bkgdlabel) {
		optctx->has_bkgdlabel = ctx->img2.has_bkgdlabel;
		for(k=0;k<4;k++) {
			optctx->bkgdlabel[k] = iw_color_get_int_sample(&ctx->img2.bkgdlabel, k,
				ctx->img2.bit_depth==8?255:65535);
		}
	}

	if(ctx->img2.sampletype!=IW_SAMPLETYPE_UINT) {
		return;
	}

	if(ctx->reduced_output_maxcolor_flag) {
		return;
	}

	make_transparent_pixels_black(ctx,&ctx->img2);

	if(optctx->has_bkgdlabel) {
		// The optimization routines are responsible for ensuring that the
		// background color label can easily be written to the optimized image.
		// For example, they may have to add a color to the palette just for
		// the background color.
		// They are NOT responsible for telling the image encoder module
		// precisely how to write the background color. The encoder will be
		// given the background color in RGB format, and it will have to figure
		// out what to do with it. For example, it may have to search for that
		// color in the palette.

		// If the background color label exists, and is non-gray,
		// make sure we don't write a grayscale image
		// (assuming we're writing to a PNG-like format).
		if(optctx->bkgdlabel[0] != optctx->bkgdlabel[1] ||
			optctx->bkgdlabel[0] != optctx->bkgdlabel[2])
		{
			optctx->has_color = 1;
		}

		// If 16-bit precision is desired, and the background color cannot be
		// losslessly reduced to 8-bit precision, use 16-bit precision.
		if(optctx->bit_depth==16) {
			if(optctx->bkgdlabel[0]%257!=0 || optctx->bkgdlabel[1]%257!=0 ||
				optctx->bkgdlabel[2]%257!=0)
			{
				optctx->has_16bit_precision=1;
			}
		}
	}

	if(!iw_opt_scanpixels(ctx,optctx)) {
		goto noscan;
	}

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==16 && !optctx->has_16bit_precision) {
		iw_opt_16_to_8(ctx,optctx,4);
	}

	if(optctx->imgtype==IW_IMGTYPE_RGB && optctx->bit_depth==16 && !optctx->has_16bit_precision) {
		iw_opt_16_to_8(ctx,optctx,3);
	}

	if(optctx->imgtype==IW_IMGTYPE_GRAYA && optctx->bit_depth==16 && !optctx->has_16bit_precision) {
		iw_opt_16_to_8(ctx,optctx,2);
	}

	if(optctx->imgtype==IW_IMGTYPE_GRAY && optctx->bit_depth==16 && !optctx->has_16bit_precision) {
		iw_opt_16_to_8(ctx,optctx,1);
	}

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==8 && !optctx->has_transparency && ctx->opt_strip_alpha) {
		iw_opt_copychannels_8(ctx,optctx,IW_IMGTYPE_RGB,0,1,2); // RGBA -> RGB
	}

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==16 && !optctx->has_transparency && ctx->opt_strip_alpha) {
		iw_opt_copychannels_16(ctx,optctx,IW_IMGTYPE_RGB,0,1,2); // RGBA -> RGB (16)
	}

	if(optctx->imgtype==IW_IMGTYPE_GRAYA && optctx->bit_depth==16 && !optctx->has_transparency && ctx->opt_strip_alpha) {
		iw_opt_copychannels_16(ctx,optctx,IW_IMGTYPE_GRAY,0, 0,0); // GA -> G (16)
	}

	if(optctx->imgtype==IW_IMGTYPE_GRAYA && optctx->bit_depth==8 && !optctx->has_transparency && ctx->opt_strip_alpha) {
		iw_opt_copychannels_8(ctx,optctx,IW_IMGTYPE_GRAY,0, 0,0); // GA -> G
	}

	if(optctx->imgtype==IW_IMGTYPE_RGB && optctx->bit_depth==8 && !optctx->has_color &&
	   (ctx->output_profile&IW_PROFILE_GRAYSCALE) && ctx->opt_grayscale)
	{
		iw_opt_copychannels_8(ctx,optctx,IW_IMGTYPE_GRAY,0, 0,0); // RGB -> G
	}

	if(optctx->imgtype==IW_IMGTYPE_RGB && optctx->bit_depth==16 && !optctx->has_color &&
	   (ctx->output_profile&IW_PROFILE_GRAYSCALE) && ctx->opt_grayscale)
	{
		iw_opt_copychannels_16(ctx,optctx,IW_IMGTYPE_GRAY,0, 0,0); // RGB -> G (16)
	}

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==8 && !optctx->has_color &&
	   (ctx->output_profile&IW_PROFILE_GRAYSCALE) && ctx->opt_grayscale)
	{
		iw_opt_copychannels_8(ctx,optctx,IW_IMGTYPE_GRAYA,0,3, 0); // RGBA -> GA
	}

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==16 && !optctx->has_color &&
	   (ctx->output_profile&IW_PROFILE_GRAYSCALE) && ctx->opt_grayscale)
	{
		iw_opt_copychannels_16(ctx,optctx,IW_IMGTYPE_GRAYA,0,3, 0); // RGBA -> GA (16)
	}

noscan:

	iwopt_try_pal_lowgray_optimization(ctx,optctx);

	// Try to convert an alpha channel to binary transparency.

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==8 && !optctx->has_partial_transparency) {
		iwopt_try_rgb8_binary_trns(ctx,optctx);
	}

	if(optctx->imgtype==IW_IMGTYPE_RGBA && optctx->bit_depth==16 && !optctx->has_partial_transparency) {
		iwopt_try_rgb16_binary_trns(ctx,optctx);
	}

	if(optctx->imgtype==IW_IMGTYPE_GRAYA && optctx->bit_depth==8 && !optctx->has_partial_transparency) {
		iwopt_try_gray8_binary_trns(ctx,optctx);
	}

	if(optctx->imgtype==IW_IMGTYPE_GRAYA && optctx->bit_depth==16 && !optctx->has_partial_transparency) {
		iwopt_try_gray16_binary_trns(ctx,optctx);
	}
}