jpc_qmfb.c

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 1,657 行 · 第 1/3 页

C
1,657
字号
/*
 * Copyright (c) 1999-2000 Image Power, Inc. and the University of
 *   British Columbia.
 * Copyright (c) 2001-2003 Michael David Adams.
 * Copyright (c) 2005-2006 artofcode LLC.
 *
 * All rights reserved.
 */

/* __START_OF_JASPER_LICENSE__
 * 
 * JasPer License Version 2.0
 * 
 * Copyright (c) 1999-2000 Image Power, Inc.
 * Copyright (c) 1999-2000 The University of British Columbia
 * Copyright (c) 2001-2003 Michael David Adams
 * 
 * All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person (the
 * "User") obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, and/or sell copies of the Software, and to permit
 * persons to whom the Software is furnished to do so, subject to the
 * following conditions:
 * 
 * 1.  The above copyright notices and this permission notice (which
 * includes the disclaimer below) shall be included in all copies or
 * substantial portions of the Software.
 * 
 * 2.  The name of a copyright holder shall not be used to endorse or
 * promote products derived from the Software without specific prior
 * written permission.
 * 
 * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
 * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
 * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
 * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
 * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
 * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
 * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
 * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
 * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
 * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
 * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
 * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
 * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
 * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
 * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
 * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
 * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
 * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
 * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
 * 
 * __END_OF_JASPER_LICENSE__
 */

/*
 * Quadrature Mirror-Image Filter Bank (QMFB) Library
 *
 * $Id$
 */

/******************************************************************************\
* Includes.
\******************************************************************************/

#include <assert.h>

#include "jasper/jas_fix.h"
#include "jasper/jas_malloc.h"
#include "jasper/jas_math.h"
#include "jasper/jas_debug.h"

#include "jpc_qmfb.h"
#include "jpc_tsfb.h"
#include "jpc_math.h"

#ifndef USE_ASM_WIN32
# if defined(_WIN32) && !defined(_WIN64)
#  define USE_ASM_WIN32
# endif
#endif

/******************************************************************************\
*
\******************************************************************************/

static jpc_qmfb1d_t *jpc_qmfb1d_create(void);

static int jpc_ft_getnumchans(jpc_qmfb1d_t *qmfb);
static int jpc_ft_getanalfilters(jpc_qmfb1d_t *qmfb, int len, jas_seq2d_t **filters);
static int jpc_ft_getsynfilters(jpc_qmfb1d_t *qmfb, int len, jas_seq2d_t **filters);
static void jpc_ft_analyze(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x);
static void jpc_ft_synthesize(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x);

static int jpc_ns_getnumchans(jpc_qmfb1d_t *qmfb);
static int jpc_ns_getanalfilters(jpc_qmfb1d_t *qmfb, int len, jas_seq2d_t **filters);
static int jpc_ns_getsynfilters(jpc_qmfb1d_t *qmfb, int len, jas_seq2d_t **filters);
static void jpc_ns_analyze(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x);


static void jpc_ns_synthesize(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x);

#ifdef USE_ASM_WIN32
static void jpc_win32_ns_synthesize( jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x);
#endif

/******************************************************************************\
*
\******************************************************************************/

jpc_qmfb1dops_t jpc_ft_ops = {
	jpc_ft_getnumchans,
	jpc_ft_getanalfilters,
	jpc_ft_getsynfilters,
	jpc_ft_analyze,
	jpc_ft_synthesize
};

jpc_qmfb1dops_t jpc_ns_ops = {
	jpc_ns_getnumchans,
	jpc_ns_getanalfilters,
	jpc_ns_getsynfilters,
	jpc_ns_analyze,
#ifdef USE_ASM_WIN32
	jpc_win32_ns_synthesize
#else
	jpc_ns_synthesize
#endif
};

/******************************************************************************\
*
\******************************************************************************/

static void jpc_qmfb1d_setup(jpc_fix_t *startptr, int startind, int endind,
  int intrastep, jpc_fix_t **lstartptr, int *lstartind, int *lendind,
  jpc_fix_t **hstartptr, int *hstartind, int *hendind)
{
	*lstartind = JPC_CEILDIVPOW2(startind, 1);
	*lendind = JPC_CEILDIVPOW2(endind, 1);
	*hstartind = JPC_FLOORDIVPOW2(startind, 1);
	*hendind = JPC_FLOORDIVPOW2(endind, 1);
	*lstartptr = startptr;
	*hstartptr = &startptr[(*lendind - *lstartind) * intrastep];
}

static void jpc_qmfb1d_split(jpc_fix_t *startptr, int startind, int endind,
  register int step, jpc_fix_t *lstartptr, int lstartind, int lendind,
  jpc_fix_t *hstartptr, int hstartind, int hendind)
{
	int bufsize = JPC_CEILDIVPOW2(endind - startind, 2);
#if !defined(HAVE_VLA)
#define QMFB_SPLITBUFSIZE 4096
	jpc_fix_t splitbuf[QMFB_SPLITBUFSIZE];
#else
	jpc_fix_t splitbuf[bufsize];
#endif
	jpc_fix_t *buf = splitbuf;
	int llen;
	int hlen;
	int twostep;
	jpc_fix_t *tmpptr;
	register jpc_fix_t *ptr;
	register jpc_fix_t *hptr;
	register jpc_fix_t *lptr;
	register int n;
	int state;

	twostep = step << 1;
	llen = lendind - lstartind;
	hlen = hendind - hstartind;

#if !defined(HAVE_VLA)
	/* Get a buffer. */
	if (bufsize > QMFB_SPLITBUFSIZE) {
		if (!(buf = jas_malloc(bufsize * sizeof(jpc_fix_t)))) {
			/* We have no choice but to commit suicide in this case. */
			jas_error(	JAS_ERR_MALLOC_FAILURE_JPC_QMFB1D_SPLIT,
						"JAS_ERR_MALLOC_FAILURE_JPC_QMFB1D_SPLIT"
					);
			return;
		}
	}
#endif

	if (hstartind < lstartind) {
		/* The first sample in the input signal is to appear
		  in the highpass subband signal. */
		/* Copy the appropriate samples into the lowpass subband
		  signal, saving any samples destined for the highpass subband
		  signal as they are overwritten. */
		tmpptr = buf;
		ptr = &startptr[step];
		lptr = lstartptr;
		n = llen;
		state = 1;
		while (n-- > 0) {
			if (state) {
				*tmpptr = *lptr;
				++tmpptr;
			}
			*lptr = *ptr;
			ptr += twostep;
			lptr += step;
			state ^= 1;
		}
		/* Copy the appropriate samples into the highpass subband
		  signal. */
		/* Handle the nonoverwritten samples. */
		hptr = &hstartptr[(hlen - 1) * step];
		ptr = &startptr[(((llen + hlen - 1) >> 1) << 1) * step];
		n = hlen - (tmpptr - buf);
		while (n-- > 0) {
			*hptr = *ptr;
			hptr -= step;
			ptr -= twostep;
		}
		/* Handle the overwritten samples. */
		n = tmpptr - buf;
		while (n-- > 0) {
			--tmpptr;
			*hptr = *tmpptr;
			hptr -= step;
		}
	} else {
		/* The first sample in the input signal is to appear
		  in the lowpass subband signal. */
		/* Copy the appropriate samples into the lowpass subband
		  signal, saving any samples for the highpass subband
		  signal as they are overwritten. */
		state = 0;
		ptr = startptr;
		lptr = lstartptr;
		tmpptr = buf;
		n = llen;
		while (n-- > 0) {
			if (state) {
				*tmpptr = *lptr;
				++tmpptr;
			}
			*lptr = *ptr;
			ptr += twostep;
			lptr += step;
			state ^= 1;
		}
		/* Copy the appropriate samples into the highpass subband
		  signal. */
		/* Handle the nonoverwritten samples. */
		ptr = &startptr[((((llen + hlen) >> 1) << 1) - 1) * step];
		hptr = &hstartptr[(hlen - 1) * step];
		n = hlen - (tmpptr - buf);
		while (n-- > 0) {
			*hptr = *ptr;
			ptr -= twostep;
			hptr -= step;
		}
		/* Handle the overwritten samples. */
		n = tmpptr - buf;
		while (n-- > 0) {
			--tmpptr;
			*hptr = *tmpptr;
			hptr -= step;
		}
	}

#if !defined(HAVE_VLA)
	/* If the split buffer was allocated on the heap, free this memory. */
	if (buf != splitbuf) {
		jas_free(buf);
	}
#endif
}

static void jpc_qmfb1d_join(jpc_fix_t *startptr, int startind, int endind,
  register int step, jpc_fix_t *lstartptr, int lstartind, int lendind,
  jpc_fix_t *hstartptr, int hstartind, int hendind)
{
	int bufsize = JPC_CEILDIVPOW2(endind - startind, 2);
#if !defined(HAVE_VLA)
#define	QMFB_JOINBUFSIZE	4096
	jpc_fix_t joinbuf[QMFB_JOINBUFSIZE];
#else
	jpc_fix_t joinbuf[bufsize];
#endif
	jpc_fix_t *buf = joinbuf;
	int llen;
	int hlen;
	int twostep;
	jpc_fix_t *tmpptr;
	register jpc_fix_t *ptr;
	register jpc_fix_t *hptr;
	register jpc_fix_t *lptr;
	register int n;
	int state;

#if !defined(HAVE_VLA)
	/* Allocate memory for the join buffer from the heap. */
	if (bufsize > QMFB_JOINBUFSIZE) {
		if (!(buf = jas_malloc(bufsize * sizeof(jpc_fix_t)))) {
			/* We have no choice but to commit suicide. */
			jas_error(	JAS_ERR_MALLOC_FAILURE_JPC_QMFB1D_JOIN,
						"JAS_ERR_MALLOC_FAILURE_JPC_QMFB1D_JOIN"
					);
			return;
		}
	}
#endif

	twostep = step << 1;
	llen = lendind - lstartind;
	hlen = hendind - hstartind;

	if (hstartind < lstartind) {
		/* The first sample in the highpass subband signal is to
		  appear first in the output signal. */
		/* Copy the appropriate samples into the first phase of the
		  output signal. */
		tmpptr = buf;
		hptr = hstartptr;
		ptr = startptr;
		n = (llen + 1) >> 1;
		while (n-- > 0) {
			*tmpptr = *ptr;
			*ptr = *hptr;
			++tmpptr;
			ptr += twostep;
			hptr += step;
		}
		n = hlen - ((llen + 1) >> 1);
		while (n-- > 0) {
			*ptr = *hptr;
			ptr += twostep;
			hptr += step;
		}
		/* Copy the appropriate samples into the second phase of
		  the output signal. */
		ptr -= (lendind > hendind) ? (step) : (step + twostep);
		state = !((llen - 1) & 1);
		lptr = &lstartptr[(llen - 1) * step];
		n = llen;
		while (n-- > 0) {
			if (state) {
				--tmpptr;
				*ptr = *tmpptr;
			} else {
				*ptr = *lptr;
			}
			lptr -= step;
			ptr -= twostep;
			state ^= 1;
		}
	} else {
		/* The first sample in the lowpass subband signal is to
		  appear first in the output signal. */
		/* Copy the appropriate samples into the first phase of the
		  output signal (corresponding to even indexed samples). */
		lptr = &lstartptr[(llen - 1) * step];
		ptr = &startptr[((llen - 1) << 1) * step];
		n = llen >> 1;
		tmpptr = buf;
		while (n-- > 0) {
			*tmpptr = *ptr;
			*ptr = *lptr;
			++tmpptr;
			ptr -= twostep;
			lptr -= step;
		}
		n = llen - (llen >> 1);
		while (n-- > 0) {
			*ptr = *lptr;
			ptr -= twostep;
			lptr -= step;
		}
		/* Copy the appropriate samples into the second phase of
		  the output signal (corresponding to odd indexed
		  samples). */
		ptr = &startptr[step];
		hptr = hstartptr;
		state = !(llen & 1);
		n = hlen;
		while (n-- > 0) {
			if (state) {
				--tmpptr;
				*ptr = *tmpptr;
			} else {
				*ptr = *hptr;
			}
			hptr += step;
			ptr += twostep;
			state ^= 1;
		}
	}

#if !defined(HAVE_VLA)
	/* If the join buffer was allocated on the heap, free this memory. */
	if (buf != joinbuf) {
		jas_free(buf);
	}
#endif
}

/******************************************************************************\
* Code for 5/3 transform.
\******************************************************************************/

static int jpc_ft_getnumchans(jpc_qmfb1d_t *qmfb)
{
	/* Avoid compiler warnings about unused parameters. */
	qmfb = 0;

	return 2;
}

static int jpc_ft_getanalfilters(jpc_qmfb1d_t *qmfb, int len, jas_seq2d_t **filters)
{
	/* Avoid compiler warnings about unused parameters. */
	qmfb = 0;
	len = 0;
	filters = 0;

	jas_error(	JAS_ERR_INCOMPLETE_STUB_INVOKED_JPC_FT_GETANALFILTERS,
				"JAS_ERR_INCOMPLETE_STUB_INVOKED_JPC_FT_GETANALFILTERS"
			);
	return -1;
}

static int jpc_ft_getsynfilters(jpc_qmfb1d_t *qmfb, int len, jas_seq2d_t **filters)
{
	jas_seq_t *lf;
	jas_seq_t *hf;

	/* Avoid compiler warnings about unused parameters. */
	qmfb = 0;

	lf = 0;
	hf = 0;

	if (len > 1 || (!len)) {
		if (!(lf = jas_seq_create(-1, 2))) {
			goto error;
		}
		jas_seq_set(lf, -1, jpc_dbltofix(0.5));
		jas_seq_set(lf, 0, jpc_dbltofix(1.0));
		jas_seq_set(lf, 1, jpc_dbltofix(0.5));
		if (!(hf = jas_seq_create(-1, 4))) {
			goto error;
		}
		jas_seq_set(hf, -1, jpc_dbltofix(-0.125));
		jas_seq_set(hf, 0, jpc_dbltofix(-0.25));
		jas_seq_set(hf, 1, jpc_dbltofix(0.75));
		jas_seq_set(hf, 2, jpc_dbltofix(-0.25));
		jas_seq_set(hf, 3, jpc_dbltofix(-0.125));
	} else if (len == 1) {
		if (!(lf = jas_seq_create(0, 1))) {
			goto error;
		}
		jas_seq_set(lf, 0, jpc_dbltofix(1.0));
		if (!(hf = jas_seq_create(0, 1))) {
			goto error;
		}
		jas_seq_set(hf, 0, jpc_dbltofix(2.0));
	} else {
		jas_error(	JAS_ERR_INVALID_LEN_PARAM_JPC_FT_GETSYNFILTERS,
					"JAS_ERR_INVALID_LEN_PARAM_JPC_FT_GETSYNFILTERS"
				);
		goto error;
	}

	filters[0] = lf;
	filters[1] = hf;

	return 0;

error:
	if (lf) {
		jas_seq_destroy(lf);
	}
	if (hf) {
		jas_seq_destroy(hf);
	}
	return -1;
}

#define	NFT_LIFT0(lstartptr, lstartind, lendind, hstartptr, hstartind, hendind, step, pluseq) \
{ \
	register jpc_fix_t *lptr = (lstartptr); \
	register jpc_fix_t *hptr = (hstartptr); \
	register int n = (hendind) - (hstartind); \
	if ((hstartind) < (lstartind)) { \
		pluseq(*hptr, *lptr); \
		hptr += (step); \
		--n; \
	} \
	if ((hendind) >= (lendind)) { \
		--n; \
	} \
	while (n-- > 0) { \
		pluseq(*hptr, jpc_fix_asr(jpc_fix_add(*lptr, lptr[(step)]), 1)); \
		hptr += (step); \
		lptr += (step); \
	} \
	if ((hendind) >= (lendind)) { \
		pluseq(*hptr, *lptr); \
	} \
}

#define	NFT_LIFT1(lstartptr, lstartind, lendind, hstartptr, hstartind, hendind, step, pluseq) \
{ \
	register jpc_fix_t *lptr = (lstartptr); \
	register jpc_fix_t *hptr = (hstartptr); \
	register int n = (lendind) - (lstartind); \
	if ((hstartind) >= (lstartind)) { \
		pluseq(*lptr, *hptr); \
		lptr += (step); \
		--n; \
	} \
	if ((lendind) > (hendind)) { \
		--n; \
	} \
	while (n-- > 0) { \
		pluseq(*lptr, jpc_fix_asr(jpc_fix_add(*hptr, hptr[(step)]), 2)); \
		lptr += (step); \
		hptr += (step); \
	} \
	if ((lendind) > (hendind)) { \
		pluseq(*lptr, *hptr); \
	} \
}

#define	RFT_LIFT0(lstartptr, lstartind, lendind, hstartptr, hstartind, hendind, step, pmeqop) \
{ \
	register jpc_fix_t *lptr = (lstartptr); \
	register jpc_fix_t *hptr = (hstartptr); \
	register int n = (hendind) - (hstartind); \
	if ((hstartind) < (lstartind)) { \
		*hptr pmeqop *lptr; \
		hptr += (step); \
		--n; \
	} \
	if ((hendind) >= (lendind)) { \
		--n; \
	} \
	while (n-- > 0) { \

⌨️ 快捷键说明

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