www.pudn.com > Delphi_VC_JPEG2000.rar > MAIN.C


// wavelet image compression (main programm) 
// (c) 2001-2002 Daniel Vollmer (maven@maven.de) 
 
/* 	This program is free software; you can redistribute it and/or modify 
	it under the terms of the GNU General Public License as published by 
	the Free Software Foundation; either version 2 of the License, or 
	(at your option) any later version. 
 
	This program is distributed in the hope that it will be useful, 
	but WITHOUT ANY WARRANTY; without even the implied warranty of 
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the 
	GNU General Public License for more details. 
 
	You should have received a copy of the GNU General Public License 
	along with this program; if not, write to the Free Software 
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA	02111-1307	USA 
*/ 
 
#include  
#include  
#include  
#include  
#include "wavelet.h" 
#include "mchannel.h" 
 
 
// loads a raw gray-scale image and convert the unsigned chars to bytes 
static wv_pel* raw_load(const char *fname, const int header, const int width, const int height) 
{ 
	FILE* in = fopen(fname, "rb"); 
	wv_pel* out = NULL; 
 
	if (in) 
	{ 
		int i, j, k, xpitch, ypitch; 
		unsigned char* tmp_row; 
 
		xpitch = 1 << log2i(width - 1); 
		ypitch = 1 << log2i(height - 1); 
 
		out = malloc(xpitch * ypitch * sizeof *out); 
		tmp_row = malloc(width * sizeof *tmp_row); 
		fseek(in, header, SEEK_SET); 
		for (i = 0; i < height; i++) 
		{ 
			k = fread(tmp_row, sizeof *tmp_row, width, in); 
			for (j = 0; j < k; j++) 
				out[i * xpitch + j] = tmp_row[j]; // convert to int 
		} 
		if (k != width) 
		{ // couldn't read all of it 
			free(out); 
			out = NULL; 
		} 
		for (i = 0; i < height; i++) 
			for (j = width; j < xpitch; j++) 
				out[i * xpitch + j] = out[i * xpitch + width - 1]; 
		for (i = height; i < ypitch; i++) 
			memcpy(out + i * xpitch, out + (height - 1) * xpitch, xpitch * sizeof *out); 
		free(tmp_row); 
		fclose(in); 
	} 
	return out; 
} 
 
 
// saves a raw gray-scale image from integers (takes abs/min) 
static void raw_save(const char *fname, const wv_pel* src, const int width, const int height, const int pitch) 
{ 
	FILE* out = fopen(fname, "wb"); 
 
	if (out) 
	{ 
		int i, j; 
		unsigned char *tmp_row; 
 
		tmp_row = malloc(width * sizeof *tmp_row); 
		for (i = 0; i < height; i++) 
		{ 
			for (j = 0; j < width; j++) 
				tmp_row[j] = min(255, abs(src[i * pitch + j])); // convert to unsigned char 
			fwrite(tmp_row, sizeof *tmp_row, width, out); 
		} 
		free(tmp_row); 
		fclose(out); 
	} 
} 
 
typedef struct 
{ 
	char	name[256]; 
	float	max_mse; 
	int		input_offset; 
	wv_pel*	data; 
} t_channel_params; 
 
 
void prog_func(int ccur, int mmax, void* userdata) 
{ 
	int ofs = (((int)userdata & 0xffff) * 100) / ((int)userdata >> 16); 
 
	printf("\r%02i%%", ofs + (ccur * 100) / (mmax * ((int)userdata >> 16))); 
} 
 
 
int main(int argc, char *argv[]) 
{ 
	const char help[] =  
		"-input      [-i]     string (\"\")  -- greyscale channels\n" 
		"-offset     [-ofs]   int    (0)   -- skip bytes of (raw) input\n" 
		"-maxmse     [-mse]   float  (0.0) -- mean square error\n" 
		"-minpsnr    [-psnr]  float  (0.0) -- peak signal-noise ratio\n" 
		"-width      [-w]     int    (512) -- must be a power of 2\n" 
		"-height     [-h]     int    (512) -- must be a power of 2\n" 
		"-maxbits    [-bits]  int    (0)   -- quantitization target\n" 
		"-ycbcr      [-y]     int    (0)   -- enable RGB -> YCbCr conversion\n" 
		"-output     [-o]     string (\"\")  -- greyscale raw or wko\n" 
		"-decompress [-d]     string (\"\")  -- decompress to output\n" 
		"-decompbits [-db]    int    (0)   -- bits to use for decompression"; 
	char	dec_input[256] = ""; 
	char	output[256] = ""; 
	int		ycbcr = 0; 
	int		i; 
	int		decompress = 0; 
	int		decompbits = 0; 
	int		num_channels = 0; 
	int		max_bits = 0; 
	int		width = 512, height = 512; 
	t_channel_params channel_params[wv_MAX_CHANNELS]; 
 
	puts("\nWavelet Koder 1.8 (c) 2001 - 2002 by Daniel Vollmer (maven@maven.de)\n"); 
 
	if (argc <= 2 || (argc % 2) == 0) 
	{ 
		puts(help); 
		exit(1); 
	} 
	 
	// init to lossless 
	for (i = 0; i < wv_MAX_CHANNELS; i++) 
	{ 
		channel_params[i].name[0] = 0; 
		channel_params[i].input_offset = 0; 
		channel_params[i].max_mse = 0.0f; 
		channel_params[i].data = NULL; 
	} 
	 
	for (i = 1; i < argc - 1; i++) 
	{ 
		int j; 
		char* arg = argv[i]; 
 
		if (*arg == '/' || *arg == '-') 
			arg++; 
		if (stricmp(arg, "decompress") == 0 || stricmp(arg, "d") == 0) 
		{ 
			i++; 
			strcpy(dec_input, argv[i]); 
			decompress = 1; 
		} 
		else if (stricmp(arg, "decompbits") == 0 || stricmp(arg, "db") == 0) 
		{ 
			i++; 
			decompbits = atoi(argv[i]); 
		} 
		else if (stricmp(arg, "width") == 0 || stricmp(arg, "w") == 0) 
		{ 
			i++; 
			width = atoi(argv[i]); 
		} 
		else if (stricmp(arg, "height") == 0 || stricmp(arg, "h") == 0) 
		{ 
			i++; 
			height = atoi(argv[i]); 
		} 
		else if (stricmp(arg, "ycbcr") == 0 || stricmp(arg, "y") == 0) 
		{ 
			i++; 
			ycbcr = atoi(argv[i]); 
		} 
		else if (stricmp(arg, "maxbits") == 0 || stricmp(arg, "bits") == 0) 
		{ 
			i++; 
			max_bits = atoi(argv[i]); 
		} 
		else if (stricmp(arg, "offset") == 0 || stricmp(arg, "ofs") == 0) 
		{ 
			i++; 
			for (j = max(0, num_channels - 1); j < wv_MAX_CHANNELS; j++) 
				channel_params[j].input_offset = atoi(argv[i]); 
		} 
		else if (stricmp(arg, "maxmse") == 0 || stricmp(arg, "mse") == 0) 
		{ 
			i++; 
			for (j = max(0, num_channels - 1); j < wv_MAX_CHANNELS; j++) 
				channel_params[j].max_mse = (float)atof(argv[i]); 
		} 
		else if (stricmp(arg, "minpsnr") == 0 || stricmp(arg, "psnr") == 0) 
		{ 
			i++; 
			for (j = max(0, num_channels - 1); j < wv_MAX_CHANNELS; j++) 
				channel_params[j].max_mse = psnr_to_mse((float)atof(argv[i])); 
		} 
		else if (stricmp(arg, "input") == 0 || stricmp(arg, "i") == 0) 
		{ 
			i++; 
			for (j = num_channels; j < wv_MAX_CHANNELS; j++) 
				strcpy(channel_params[j].name, argv[i]); 
			num_channels++; 
		} 
		else if (stricmp(arg, "output") == 0 || stricmp(arg, "o") == 0) 
		{ 
			i++; 
			strcpy(output, argv[i]); 
		} 
		else 
		{ 
			printf("Unknown Param \"%s\"...\n", arg); 
			puts(help); 
			exit(1); 
		} 
	} 
 
	if (!decompress) 
	{ 
		int		num_found = 0; 
 
		// try to load the channels 
		for (i = 0; i < num_channels; i++) 
		{ 
			channel_params[i].data = raw_load(channel_params[i].name, channel_params[i].input_offset, width, height); 
			if (channel_params[i].data) 
				num_found++; 
			else 
				printf("could not open input channel \"%s\"...\n", channel_params[i].name); 
		} 
 
		if (num_found == num_channels && num_found > 0) 
		{ 
			int bits; 
			int owidth = width, oheight = height; 
			t_wv_mchannel_params par[wv_MAX_CHANNELS]; 
			t_wv_csettings* sets[wv_MAX_CHANNELS]; 
 
			width = 1 << log2i(width - 1); 
			height = 1 << log2i(height - 1); 
			 
			if (num_found >= 3 && ycbcr != 0) 
			{ // convert RGB -> YCbCr 
				wv_pel* y = malloc(width * height * sizeof *y); 
				wv_pel* cb = malloc(width * height * sizeof *cb); 
				wv_pel* cr = malloc(width * height * sizeof *cr); 
 
				printf("converting RGB -> YCbCr\n"); 
				wv_rgb_to_ycbcr(width * height, channel_params[0].data, channel_params[1].data, channel_params[2].data, y, cb, cr); 
				free(channel_params[2].data); channel_params[2].data = cr; 
				free(channel_params[1].data); channel_params[1].data = cb; 
				free(channel_params[0].data); channel_params[0].data = y; 
			} 
 
			// init the channels (should display progress...) 
			for (i = 0; i < num_channels; i++) 
			{ 
				par[i].cc = wv_init_channel(owidth, oheight, channel_params[i].data, max_bits / num_channels, ((max_bits <= 0) && (channel_params[i].max_mse == 0.0f)), (i == 0) ? NULL : &par[0].cc->num_blocks, (i == 0) ? NULL : &par[0].cc->reorder_table, prog_func, (void*)((num_channels << 16) + i)); 
				par[i].max_mse = channel_params[i].max_mse; 
				free(channel_params[i].data); 
				channel_params[i].data = NULL; 
				sets[i] = NULL; 
			} 
			printf("\n"); 
			 
			bits = wv_init_multi_channels(max_bits, 1.0f, num_channels, par, sets); 
			 
			if (bits > 0) 
			{ 
				for (i = 0; i < num_channels; i++) 
					printf("%i. emse: %.03f ermse: %.03f epsnr: %.03f bits: %i\n", i, sets[i]->emse, sqrt(sets[i]->emse), mse_to_psnr(sets[i]->emse), sets[i]->num_bits); 
				if (*output) 
				{ 
					t_bit_file* bf = bit_open(output, "wb", 0); 
 
					if (bf) 
					{ // FILE FORMAT 
						bit_write(ycbcr != 0, 1, bf); // write whether we did ycbcr conversion 
						wv_encode_channels(num_channels, sets, bf); // plus the channels themselves 
						bit_close(bf, NULL); 
					} 
				} 
			} 
			else 
				printf("could not meet constraints...\n"); 
 
			for (i = 0; i < num_channels; i++) 
			{ 
				wv_done_channel_settings(sets[i]); 
				if (par[i].cc) 
					wv_done_channel(par[i].cc, (i == 0)); 
			} 
		} 
		for (i = 0; i < num_channels; i++) 
		{ 
			if (channel_params[i].data) 
				free(channel_params[i].data); 
		} 
	} 
	else 
	{ // decompress 
		t_bit_file* bf = bit_open(dec_input, "rb", decompbits); 
 
		if (bf) 
		{ 
			t_wv_dchannels* dc; 
 
			ycbcr = bit_read(1, bf); 
			dc = wv_init_decode_channels(bf); 
 
			if (dc) 
			{ 
				char *ext_out = NULL; 
 
				printf("width: %i height: %i channels: %i\n", dc->owidth, dc->oheight, dc->num_channels); 
 
				if (*output) 
				{ 
					ext_out = strrchr(output, '.'); 
					if (ext_out) 
						*ext_out++ = 0; 
				} 
 
				if (ycbcr && dc->num_channels >= 3) 
				{ // ycbcr -> rgb 
					wv_pel* r = malloc(dc->width * dc->height * sizeof *r); 
					wv_pel* g = malloc(dc->width * dc->height * sizeof *g); 
					wv_pel* b = malloc(dc->width * dc->height * sizeof *b); 
 
					printf("converting YCbCr -> RGB\n"); 
					wv_ycbcr_to_rgb(dc->width * dc->height, dc->channels[0], dc->channels[1], dc->channels[2], r, g, b); 
					free(dc->channels[2]); dc->channels[2] = b; 
					free(dc->channels[1]); dc->channels[1] = g; 
					free(dc->channels[0]); dc->channels[0] = r; 
				} 
				 
				for (i = 0; i < dc->num_channels; i++) 
				{ 
					char buf[256]; 
 
					if (*output) 
					{ 
						sprintf(buf, "%s%i.", output, i); 
						if (ext_out) 
							strcat(buf, ext_out); 
						raw_save(buf, dc->channels[i], dc->owidth, dc->oheight, dc->width); 
					} 
					if (channel_params[i].name[0]) 
					{ 
						wv_pel* image = raw_load(channel_params[i].name, channel_params[i].input_offset, dc->owidth, dc->oheight); 
						 
						if (image) 
						{ 
							float psnr, mse; 
 
							psnr = wv_calc_psnr(image, dc->channels[i], dc->owidth, dc->oheight, dc->width, &mse); 
							printf("mse: %.03f rmse: %.03f psnr: %.03f\n", mse, sqrt(mse), psnr); 
							free(image); 
						} 
					} 
				} 
				wv_done_decode_channels(dc); 
			} 
			bit_close(bf, NULL); 
		} 
		else 
			printf("could not open compressed image \"%s\"...\n", dec_input); 
	} 
}