📄 compress.c
字号:
/*****************************************************************************/
/* Copyright 1998, Hewlett-Packard Company */
/* All rights reserved */
/* Author: David Taubman */
/* Version: V2.0 */
/* Last Revised: 9/22/98 */
/*****************************************************************************/
#include <local_heap.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <line_block_ifc.h>
#include <hplx_coeffs.h>
#include <compress_config.h>
#define MAX_COMPONENTS 256
/*****************************************************************************/
/* STATIC local_fopen */
/*****************************************************************************/
static FILE *
local_fopen(char *fname, char *mode)
/* Same as `fopen', but accepts `-' to identify std-output or std-input. */
{
if (strcmp(fname,"-") == 0)
{
#ifdef WIN32
if (strchr(mode,'b') != NULL)
{
fprintf(stderr,"The UNIX \"-\" convention for std-input and/or "
"std-output\n should not be used to open binary files on "
"WIN32 platforms!\n");
exit(-1);
}
#endif
if (strchr(mode,'r') != NULL)
return(stdin);
else
return(stdout);
}
return(fopen(fname,mode));
}
/*****************************************************************************/
/* STATIC local_fclose */
/*****************************************************************************/
static void
local_fclose(FILE *fp)
{
if ((fp != stdin) && (fp != stdout) && (fp != stderr))
fclose(fp);
}
/*****************************************************************************/
/* STATIC print_profile_vector */
/*****************************************************************************/
static void
print_profile_vector(int profile, FILE *dest)
{
fprintf(dest,
" Random access [a] : %s\n"
" SNR progressive [sp]: %s\n"
" SNR parsable (scalable) [ss]: %s\n"
" Resolution progressive [rp]: %s\n"
" Resolution parsable (scalable) [rs]: %s\n"
" Component parsable (scalable) [cs]: %s\n",
(profile & PROFILE__RANDOM_ACCESS)?"YES":"NO",
(profile & PROFILE__SNR_PROGRESSIVE)?"YES":"NO",
(profile & PROFILE__SNR_PARSABLE)?"YES":"NO",
(profile & PROFILE__RESOLUTION_PROGRESSIVE)?"YES":"NO",
(profile & PROFILE__RESOLUTION_PARSABLE)?"YES":"NO",
(profile & PROFILE__COMPONENT_PARSABLE)?"YES":"NO");
}
/*****************************************************************************/
/* STATIC print_usage */
/*****************************************************************************/
static void
print_usage(int default_header_bytes, int default_levels,
int default_profile, float default_max_bpp,
float default_base_step, int default_iterations,
char *prog_name, FILE *dest)
{
filter_info_ref info;
analysis_ref analysis;
quantizer_ref quantizer;
encoder_ref encoder;
bitstream_sink_ref bitstream;
fprintf(dest,"\n"
"Usage: \"%s args...\",\n"
" where the following arguments are recognized:\n",prog_name);
fprintf(dest,
" -i <input image file> (mandatory, PGM or PPM only for now)\n"
" -- Accepts UNIX \"-\" convention to identify std-input.\n");
fprintf(dest,
" -o <output compressed file> (mandatory)\n"
" -- Accepts UNIX \"-\" convention to identify std-output.\n");
fprintf(dest,
" -head <header bytes> (default = %d)\n"
" -- Note that 8 extra bytes are added for each non-initial "
"component.\n",
default_header_bytes);
fprintf(dest,
" -lev <transform levels> (default = %d) -- may not exceeed 16.\n",
default_levels);
fprintf(dest,
" -fil <built-in filter set> (default = 0)\n"
" -- must lie in range 0 to 14.\n"
" \"0\" -> Daubechies 9/7 filters.\n");
fprintf(dest,
" -loc <file name for local filter set> "
"(default = built-in filter set)\n"
" -- the same argument must be given to the decoder.\n");
fprintf(dest,
" -radix_quant\n"
" -- use power-of-two quantization step sizes only.\n");
fprintf(dest,
" -ideal_quant\n"
" -- use idealized filter taps when computing quantization\n"
" step sizes for the different subbands.\n");
fprintf(dest,
" -prof \"[a] [sp] [ss] [rp] [rs] [cs]\" (default = \"\")\n");
print_profile_vector(default_profile,dest);
fprintf(dest,
" -rate <max rate in bpp> (default = %g)\n",
default_max_bpp);
fprintf(dest,
" -step <normalized base step> (default = %g)\n",
default_base_step);
fprintf(dest,
" -iter <num rate-control iterations> (default = %d)\n",
default_iterations);
fprintf(dest,
" -q -- turns off verbose mode.\n");
info = info_creator();
info->print_usage(info,dest);
info->terminate(info);
analysis = analysis_creator();
analysis->print_usage(analysis,dest);
analysis->terminate(analysis);
quantizer = quantizer_creator();
quantizer->print_usage(quantizer,dest);
encoder = encoder_creator();
encoder->print_usage(encoder,dest);
encoder->terminate(encoder);
bitstream = bitstream_creator();
bitstream->print_usage(bitstream,dest);
bitstream->terminate(bitstream);
fprintf(dest,
" -u [<output file>]\n"
" -- print usage statement & exit. Overrides other args.\n"
" Prints to std-error unless output file given.\n"
" Accepts UNIX \"-\" convention to identify std-output.\n");
}
/*****************************************************************************/
/* STATIC parse_common_arguments */
/*****************************************************************************/
static void
parse_common_arguments(int argc, char *argv[], int *header_bytes,
int *num_levels, int *filter_set,
char **local_filter_name, int *filter_flags,
int *profile, float *max_bpp, float *base_step,
int *max_iterations, int *verbose)
{
*filter_flags = 0;
for (argc--, argv++; argc > 0; argc--, argv++)
if (strcmp(*argv,"-head") == 0)
{
*(argv++) = ""; argc--;
if ((argc == 0) || (sscanf(*argv,"%d",header_bytes) == 0))
{
fprintf(stderr,"\nThe `-head' argument requires the header size "
"in bytes!\n");
exit(-1);
}
*argv = "";
}
else if (strcmp(*argv,"-lev") == 0)
{
*(argv++) = ""; argc--;
if ((argc == 0) || (sscanf(*argv,"%d",num_levels) == 0) ||
(*num_levels > 16))
{
fprintf(stderr,"\nThe `-lev' argument requires a non-negative "
"number of resolution\n levels, no larger than 16!\n");
exit(-1);
}
*argv = "";
}
else if (strcmp(*argv,"-fil") == 0)
{
*(argv++) = ""; argc--;
if ((argc == 0) || (sscanf(*argv,"%d",filter_set) == 0) ||
(*filter_set < 0) || (*filter_set > 14))
{
fprintf(stderr,"\nThe `-fil' argument requires a built-in "
"filter set number\n in the range 0 to 14!\n");
exit(-1);
}
*argv = "";
}
else if (strcmp(*argv,"-loc") == 0)
{
*(argv++) = ""; argc--;
if ((argc == 0) || (strlen(*argv) <= 1))
{
fprintf(stderr,"\nThe `-loc' argument requires the name of "
"a local filter\n set file; the name must be at least "
"2 characters long!\n");
exit(-1);
}
*local_filter_name = *argv;
*argv = "";
*filter_set = 15;
}
else if (strcmp(*argv,"-ideal_quant") == 0)
{
*argv = "";
*filter_flags |= FILTER_INFO__IDEAL_QUANT;
}
else if (strcmp(*argv,"-radix_quant") == 0)
{
*argv = "";
*filter_flags |= FILTER_INFO__RADIX_QUANT;
}
else if (strcmp(*argv,"-prof") == 0)
{
*argv = "";
*profile = 0;
if ((argc > 1) && ((argv[1])[0] != '-'))
{
char *ch;
argc--; argv++;
for (ch=*argv; *ch != '\0'; )
{
if (strncmp(ch,"a",1) == 0)
{ *profile |= PROFILE__RANDOM_ACCESS; ch++; }
else if (strncmp(ch,"sp",2) == 0)
{ *profile |= PROFILE__SNR_PROGRESSIVE; ch += 2; }
else if (strncmp(ch,"ss",2) == 0)
{ *profile |= PROFILE__SNR_PARSABLE; ch += 2; }
else if (strncmp(ch,"rp",2) == 0)
{ *profile |= PROFILE__RESOLUTION_PROGRESSIVE; ch += 2; }
else if (strncmp(ch,"rs",2) == 0)
{ *profile |= PROFILE__RESOLUTION_PARSABLE; ch += 2; }
else if (strncmp(ch,"cs",2) == 0)
{ *profile |= PROFILE__COMPONENT_PARSABLE; ch += 2; }
else
{
fprintf(stderr,"Unrecognized profile flag, \"%s\", "
"found with `-prof' argument!!\n",ch);
exit(-1);
}
}
*argv = "";
}
}
else if (strcmp(*argv,"-rate") == 0)
{
*(argv++) = ""; argc--;
if ((argc == 0) || (sscanf(*argv,"%f",max_bpp) == 0))
{
fprintf(stderr,"\nThe `-rate' argument requires the number of "
"bits per pixel!\n");
exit(-1);
}
*argv = "";
}
else if (strcmp(*argv,"-step") == 0)
{
*(argv++) = ""; argc--;
if ((argc == 0) || (sscanf(*argv,"%f",base_step) == 0))
{
fprintf(stderr,"\nThe `-step' argument requires the base step "
"size!\n");
exit(-1);
}
*argv = "";
}
else if (strcmp(*argv,"-iter") == 0)
{
*(argv++) = ""; argc--;
if ((argc == 0) || (sscanf(*argv,"%d",max_iterations) == 0))
{
fprintf(stderr,"\nThe `-iter' argument requires the number of "
"rate-control iterations!\n");
exit(-1);
}
*argv = "";
}
else if (strcmp(*argv,"-q") == 0)
{
*argv = "";
*verbose = 0;
}
}
/*****************************************************************************/
/* STATIC check_all_arguments_used */
/*****************************************************************************/
static void
check_all_arguments_used(int argc, char *argv[])
{
int i;
for (i=1; i < argc; i++)
if (*(argv[i]) != '\0')
fprintf(stderr,"\nWarning: The command-line argument, \"%s\", does "
"not\n appear to have been recognized by any object in the "
"compression system!\n",argv[i]);
}
/*****************************************************************************/
/* STATIC get_fixed_point_step */
/*****************************************************************************/
static unsigned short int
get_fixed_point_step(float *step)
/* This function returns a 16-bit fixed-precision approximation to the
step size referenced by the `step' argument. It also modifies the
*`step' value to correspond exactly with this approximation. */
{
float delta;
int result;
delta = *step;
result = (int)(delta * ((float)(1<<16)));
if (result >= (1<<16))
result = (1<<16)-1;
if (result <= 0)
result = 1;
delta = ((float) result) / ((float)(1<<16));
*step = delta;
return((unsigned short int) result);
}
/*****************************************************************************/
/* STATIC eat_white */
/*****************************************************************************/
static void
eat_white(FILE *fp)
{
int ch;
while ((ch=getc(fp)) != EOF)
if (ch == '#')
do {
ch = getc(fp);
} while ((ch != '\n') && (ch != EOF));
else if ((ch != ' ') && (ch != '\t') && (ch != '\n'))
{
ungetc(ch,fp);
return;
}
}
/*****************************************************************************/
/* STATIC open_input_image_file */
/*****************************************************************************/
static FILE *
open_input_image_file(int argc, char *argv[], int *num_rows, int *num_cols,
int *num_planes)
/* Works only for PNM files. */
{
int i, rows, cols, planes, depth, ch;
char *name;
FILE *fp;
for (name=NULL, i=1; i < (argc-1); i++)
if (strcmp(argv[i],"-i") == 0)
{
name = argv[i+1];
argv[i] = argv[i+1] = "";
}
if (name == NULL)
{
fprintf(stderr,"Must supply input file name via `-i' switch!\n");
exit(-1);
}
fp = local_fopen(name,"rb");
if (fp == NULL)
{
fprintf(stderr,"Cannot open input file, \"%s\"!\n",name);
exit(-1);
}
if ((fgetc(fp) != 'P') || (((ch = fgetc(fp)) != '5') && (ch != '6')))
{
fprintf(stderr,"The image file, \"%s\", does not have a PGM or PPM "
"format!\n",name);
exit(-1);
}
if (ch == '5')
planes = 1;
else
planes = 3;
eat_white(fp);
if ((fscanf(fp,"%d",&cols) != 1) || (cols < 1))
{
fprintf(stderr,"Invalid PNM header in input image, \"%s\"!\n",name);
exit(-1);
}
eat_white(fp);
if ((fscanf(fp,"%d",&rows) != 1) || (rows < 1))
{
fprintf(stderr,"Invalid PNM header in input image, \"%s\"!\n",name);
exit(-1);
}
eat_white(fp);
if ((fscanf(fp,"%d",&depth) != 1) || (depth > 255) || (depth < 0))
{
fprintf(stderr,"Invalid PNM header in input image, \"%s\"!\n",name);
exit(-1);
}
fgetc(fp);
*num_rows = rows;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -