⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 jpeg and mpeg 编解码技术源代码
💻 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#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);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -