/* * misc.c: Some useful functions, that don't fit in one of * the other files and that are needed by at least * two modules. * * Written by: Stefan Frank * Ullrich Hafner * * This file is part of FIASCO (Fractal Image And Sequence COdec) * Copyright (C) 1994-2000 Ullrich Hafner */ /* * $Date: 2000/06/14 20:49:37 $ * $Author: hafner $ * $Revision: 5.1 $ * $State: Exp $ */ #include "config.h" #include #include #ifdef TIME_WITH_SYS_TIME # include # include #else /* not TIME_WITH_SYS_TIME */ # if HAVE_SYS_TIME_H # include # else /* not HAVE_SYS_TIME_H */ # include # endif /* not HAVE_SYS_TIME_H */ #endif /* not TIME_WITH_SYS_TIME */ #include #include #include "pm_c_util.h" #include "types.h" #include "macros.h" #include "error.h" #include "bit-io.h" #include "misc.h" /***************************************************************************** prototypes *****************************************************************************/ static void remove_comments (FILE *file); /***************************************************************************** public code *****************************************************************************/ void * Calloc (size_t n, size_t size) /* * Allocate memory like calloc (). * * Return value: Pointer to the new block of memory on success, * otherwise the program is terminated. */ { void *ptr; /* pointer to the new memory block */ if (n <= 0 || size <= 0) error ("Can't allocate memory for %d items of size %d", (int) n, (int) size); ptr = calloc (n, size); if (!ptr) error ("Out of memory!"); return ptr; } void Free (void *memory) /* * Free memory given by the pointer 'memory' * * No return value. */ { if (memory != NULL) free (memory); else warning ("Can't free memory block ."); } unsigned prg_timer (clock_t *last_timer, enum action_e action) /* * If 'action' == START then store current value of system timer. * If 'action' == STOP then compute number of elapsed micro seconds since * the last time 'prg_timer' was called * with 'action' == START. * * Return value: * Number of elapsed micro seconds if 'action' == STOP * 0 if 'action' == START * * Side effects: * last_timer is set to current timer if action == START */ { assert (last_timer); if (action == START) { *last_timer = clock (); return 0; } else return (clock () - *last_timer) / (CLOCKS_PER_SEC / 1000.0); } real_t read_real (FILE *infile) /* * Read one real value from the given input stream 'infile'. * * Return value: * real value on success */ { float input; assert (infile); remove_comments (infile); if (fscanf(infile, "%f", &input) != 1) error("Can't read float value!"); return (real_t) input; } int read_int (FILE *infile) /* * Read one integer value from the given input stream 'infile'. * * Return value: * integer value on success */ { int input; /* integer */ assert (infile); remove_comments (infile); if (fscanf(infile, "%d", &input) != 1) error("Can't read integer value!"); return input; } static void remove_comments (FILE *file) /* * Remove shell/pgm style comments (#) from the input 'file' * * No return value. */ { int c; /* current character */ assert (file); do { while (isspace(c = getc (file))) ; if (c == EOF) error ("EOF reached, input seems to be truncated!"); if (c == '#') { int dummy; while (((dummy = getc (file)) != '\n') && dummy != EOF) ; if (dummy == EOF) error ("EOF reached, input seems to be truncated!"); } else ungetc (c, file); } while (c == '#'); } void write_rice_code (unsigned value, unsigned rice_k, bitfile_t *output) /* * Write 'value' to the stream 'output' using Rice coding with base 'rice_k'. * * No return value. */ { unsigned unary; /* unary part of Rice Code */ assert (output); for (unary = value >> rice_k; unary; unary--) put_bit (output, 1); put_bit (output, 0); put_bits (output, value & ((1 << rice_k) - 1), rice_k); } unsigned read_rice_code (unsigned rice_k, bitfile_t *input) /* * Read a Rice encoded integer (base 'rice_k') from the stream 'input'. * * Return value: * decoded integer */ { unsigned unary; /* unary part of Rice code */ assert (input); for (unary = 0; get_bit (input); unary++) /* unary part */ ; return (unary << rice_k) | get_bits (input, rice_k); } void write_bin_code (unsigned value, unsigned maxval, bitfile_t *output) /* * Write 'value' to the stream 'output' using an adjusted binary code * based on given 'maxval'. * * No return value. */ { unsigned k; unsigned r; assert (output && maxval && value <= maxval); k = log2 (maxval + 1); r = (maxval + 1) % (1 << k); if (value < maxval + 1 - 2 * r) /* 0, ... , maxval - 2r */ put_bits (output, value, k); else /* maxval - 2r + 1, ..., maxval */ put_bits (output, value + maxval + 1 - 2 * r, k + 1); } unsigned read_bin_code (unsigned maxval, bitfile_t *input) /* * Read a bincode encoded integer from the stream 'input'. * * Return value: * decoded integer */ { unsigned k; unsigned r; unsigned value; assert (input); k = log2 (maxval + 1); r = (maxval + 1) % (1 << k); value = get_bits (input, k); if (value < maxval + 1 - 2 * r) return value; else { value <<= 1; if (get_bit (input)) value++; return value - maxval - 1 + 2 * r; } } unsigned bits_rice_code (unsigned value, unsigned rice_k) /* * Compute number of bits needed for coding integer 'value' * with given Rice code 'rice_k'. * * Return value: * number of bits */ { unsigned unary; unsigned bits = 0; for (unary = value >> rice_k; unary; unary--) bits++; bits += rice_k + 1; return bits; } unsigned bits_bin_code (unsigned value, unsigned maxval) /* * Compute number of bits needed for coding integer 'value' * with adjusted binary code of given maximum value 'maxval'. * * Return value: * number of bits */ { unsigned k; unsigned r; assert (maxval && value <= maxval); k = log2 (maxval + 1); r = (maxval + 1) % (1 << k); return value < maxval + 1 - 2 * r ? k : k + 1; } unsigned * init_clipping (void) /* * Initialize the clipping tables * * Return value: * pointer to clipping table */ { static unsigned *gray_clip = NULL; /* clipping array */ if (gray_clip == NULL) /* initialize clipping table */ { int i; /* counter */ gray_clip = calloc (256 * 3, sizeof (unsigned)); if (!gray_clip) { set_error (_("Out of memory.")); return NULL; } gray_clip += 256; for (i = -256; i < 512; i++) if (i < 0) gray_clip [i] = 0; else if (i > 255) gray_clip [i] = 255; else gray_clip [i] = i; } return gray_clip; } #ifndef HAVE_MEMMOVE void * memmove (void *v_dst, const void *v_src, size_t n) /* * Copy 'n' bytes from memory area 'src' to memory area 'dest'. * The memory areas may overlap. * * Return value: * pointer 'dest' */ { byte_t *to, *dst = (byte_t *) v_dst; const byte_t *from, *src = (byte_t *) v_src; assert (v_dst && v_src); if (dst <= src) { from = src; to = dst; for (; n; n--) *to++ = *from++; } else { from = src + (n - 1); to = dst + (n - 1); for (; n; n--) *to-- = *from--; } return v_dst; } #endif /* not HAVE_MEMMOVE */ /* Note that some systems have a "log2()" in the math library and some have a "log2" macro. So we name ours Log2. But to avoid lots of differences from the original fiasco source code, we define a macro log2 in config.h to expand to Log2. */ double Log2 (double x) /* * Return value: * base-2 logarithm of 'x' */ { return log (x) / 0.69314718; } real_t variance (const word_t *pixels, unsigned x0, unsigned y0, unsigned width, unsigned height, unsigned cols) /* * Compute variance of subimage ('x0', y0', 'width', 'height') of * the image data given by 'pixels' ('cols' is the number of pixels * in one row of the image). * * Return value: * variance */ { real_t average; /* average of pixel values */ real_t variance; /* variance of pixel values */ unsigned x, y; /* pixel counter */ unsigned n; /* number of pixels */ assert (pixels); for (average = 0, n = 0, y = y0; y < y0 + height; y++) for (x = x0; x < MIN(x0 + width, cols); x++, n++) average += pixels [y * cols + x] / 16; average /= n; for (variance = 0, y = y0; y < y0 + height; y++) for (x = x0; x < MIN(x0 + width, cols); x++) variance += square ((pixels [y * cols + x] / 16) - average); return variance; } int sort_asc_word (const void *value1, const void *value2) /* * Sorting function for quicksort. * Smallest values come first. */ { if (* (word_t *) value1 < * (word_t *) value2) return -1; else if (* (word_t *) value1 > * (word_t *) value2) return +1; else return 0; } int sort_desc_word (const void *value1, const void *value2) /* * Sorting function for quicksort. * Largest values come first. */ { if (* (word_t *) value1 > * (word_t *) value2) return -1; else if (* (word_t *) value1 < * (word_t *) value2) return +1; else return 0; } int sort_asc_pair (const void *value1, const void *value2) /* * Sorting function for quicksort. * Smallest values come first. */ { word_t v1 = ((pair_t *) value1)->key; word_t v2 = ((pair_t *) value2)->key; if (v1 < v2) return -1; else if (v1 > v2) return +1; else return 0; } int sort_desc_pair (const void *value1, const void *value2) /* * Sorting function for quicksort. * Largest values come first. */ { word_t v1 = ((pair_t *) value1)->key; word_t v2 = ((pair_t *) value2)->key; if (v1 > v2) return -1; else if (v1 < v2) return +1; else return 0; }