www.pudn.com > Jpeg2000en.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); } }