diff options
Diffstat (limited to 'converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c')
-rw-r--r-- | converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c | 1125 |
1 files changed, 1125 insertions, 0 deletions
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c b/converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c new file mode 100644 index 00000000..1ed0dd90 --- /dev/null +++ b/converter/other/jpeg2000/libjasper/jpc/jpc_qmfb.c @@ -0,0 +1,1125 @@ +/* + * Copyright (c) 1999-2000 Image Power, Inc. and the University of + * British Columbia. + * Copyright (c) 2001-2002 Michael David Adams. + * All rights reserved. + */ + +/* __START_OF_JASPER_LICENSE__ + * + * JasPer Software License + * + * IMAGE POWER JPEG-2000 PUBLIC LICENSE + * ************************************ + * + * GRANT: + * + * Permission is hereby granted, free of charge, to any person (the "User") + * obtaining a copy of this software and associated documentation, to deal + * in the JasPer Software without restriction, including without limitation + * the right to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the JasPer Software (in source and binary forms), + * and to permit persons to whom the JasPer Software is furnished to do so, + * provided further that the License Conditions below are met. + * + * License Conditions + * ****************** + * + * A. Redistributions of source code must retain the above copyright notice, + * and this list of conditions, and the following disclaimer. + * + * B. Redistributions in binary form must reproduce the above copyright + * notice, and this list of conditions, and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * C. Neither the name of Image Power, Inc. nor any other contributor + * (including, but not limited to, the University of British Columbia and + * Michael David Adams) may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * D. User agrees that it shall not commence any action against Image Power, + * Inc., the University of British Columbia, Michael David Adams, or any + * other contributors (collectively "Licensors") for infringement of any + * intellectual property rights ("IPR") held by the User in respect of any + * technology that User owns or has a right to license or sublicense and + * which is an element required in order to claim compliance with ISO/IEC + * 15444-1 (i.e., JPEG-2000 Part 1). "IPR" means all intellectual property + * rights worldwide arising under statutory or common law, and whether + * or not perfected, including, without limitation, all (i) patents and + * patent applications owned or licensable by User; (ii) rights associated + * with works of authorship including copyrights, copyright applications, + * copyright registrations, mask work rights, mask work applications, + * mask work registrations; (iii) rights relating to the protection of + * trade secrets and confidential information; (iv) any right analogous + * to those set forth in subsections (i), (ii), or (iii) and any other + * proprietary rights relating to intangible property (other than trademark, + * trade dress, or service mark rights); and (v) divisions, continuations, + * renewals, reissues and extensions of the foregoing (as and to the extent + * applicable) now existing, hereafter filed, issued or acquired. + * + * E. If User commences an infringement action against any Licensor(s) then + * such Licensor(s) shall have the right to terminate User's license and + * all sublicenses that have been granted hereunder by User to other parties. + * + * F. This software is for use only in hardware or software products that + * are compliant with ISO/IEC 15444-1 (i.e., JPEG-2000 Part 1). No license + * or right to this Software is granted for products that do not comply + * with ISO/IEC 15444-1. The JPEG-2000 Part 1 standard can be purchased + * from the ISO. + * + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. + * NO USE OF THE JASPER SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER + * THIS DISCLAIMER. THE JASPER SOFTWARE IS PROVIDED BY THE LICENSORS AND + * CONTRIBUTORS UNDER THIS LICENSE ON AN ``AS-IS'' BASIS, WITHOUT WARRANTY + * OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, + * WARRANTIES THAT THE JASPER SOFTWARE IS FREE OF DEFECTS, IS MERCHANTABLE, + * IS FIT FOR A PARTICULAR PURPOSE OR IS NON-INFRINGING. THOSE INTENDING + * TO USE THE JASPER SOFTWARE OR MODIFICATIONS THEREOF FOR USE IN HARDWARE + * OR SOFTWARE PRODUCTS ARE ADVISED THAT THEIR USE MAY INFRINGE EXISTING + * PATENTS, COPYRIGHTS, TRADEMARKS, OR OTHER INTELLECTUAL PROPERTY RIGHTS. + * THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE JASPER SOFTWARE + * IS WITH THE USER. SHOULD ANY PART OF THE JASPER SOFTWARE PROVE DEFECTIVE + * IN ANY RESPECT, THE USER (AND NOT THE INITIAL DEVELOPERS, THE UNIVERSITY + * OF BRITISH COLUMBIA, IMAGE POWER, INC., MICHAEL DAVID ADAMS, OR ANY + * OTHER CONTRIBUTOR) SHALL ASSUME THE COST OF ANY NECESSARY SERVICING, + * REPAIR OR CORRECTION. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, + * WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE + * INITIAL DEVELOPER, THE UNIVERSITY OF BRITISH COLUMBIA, IMAGE POWER, INC., + * MICHAEL DAVID ADAMS, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF THE + * JASPER SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO + * THE USER OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, + * DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR + * MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF + * SUCH PARTY HAD BEEN INFORMED, OR OUGHT TO HAVE KNOWN, OF THE POSSIBILITY + * OF SUCH DAMAGES. THE JASPER SOFTWARE AND UNDERLYING TECHNOLOGY ARE NOT + * FAULT-TOLERANT AND ARE NOT DESIGNED, MANUFACTURED OR INTENDED FOR USE OR + * RESALE AS ON-LINE CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING + * FAIL-SAFE PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT + * LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE + * JASPER SOFTWARE OR UNDERLYING TECHNOLOGY OR PRODUCT COULD LEAD DIRECTLY + * TO DEATH, PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE + * ("HIGH RISK ACTIVITIES"). LICENSOR SPECIFICALLY DISCLAIMS ANY EXPRESS + * OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. USER WILL NOT + * KNOWINGLY USE, DISTRIBUTE OR RESELL THE JASPER SOFTWARE OR UNDERLYING + * TECHNOLOGY OR PRODUCTS FOR HIGH RISK ACTIVITIES AND WILL ENSURE THAT ITS + * CUSTOMERS AND END-USERS OF ITS PRODUCTS ARE PROVIDED WITH A COPY OF THE + * NOTICE SPECIFIED IN THIS SECTION. + * + * __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 "jpc_qmfb.h" +#include "jpc_tsfb.h" +#include "jpc_math.h" + +/******************************************************************************\ +* +\******************************************************************************/ + +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); + +/******************************************************************************\ +* +\******************************************************************************/ + +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, + jpc_ns_synthesize +}; + +/******************************************************************************\ +* +\******************************************************************************/ + +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) +{ +#define QMFB_SPLITBUFSIZE 4096 + jpc_fix_t splitbuf[QMFB_SPLITBUFSIZE]; + 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(WIN32) + /* 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. */ + abort(); + } + } +#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(WIN32) + /* 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) +{ +#define QMFB_JOINBUFSIZE 4096 + jpc_fix_t joinbuf[QMFB_JOINBUFSIZE]; + 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(WIN32) + /* 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. */ + abort(); + } + } +#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(WIN32) + /* 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) +{ + return 2; +} + +static int jpc_ft_getanalfilters(jpc_qmfb1d_t *qmfb, int len, jas_seq2d_t **filters) +{ + abort(); + 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; + + 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 { + abort(); + } + + 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) { \ + *hptr pmeqop (*lptr + lptr[(step)]) >> 1; \ + hptr += (step); \ + lptr += (step); \ + } \ + if ((hendind) >= (lendind)) { \ + *hptr pmeqop *lptr; \ + } \ +} + +#define RFT_LIFT1(lstartptr, lstartind, lendind, hstartptr, hstartind, hendind, step, pmeqop) \ +{ \ + register jpc_fix_t *lptr = (lstartptr); \ + register jpc_fix_t *hptr = (hstartptr); \ + register int n = (lendind) - (lstartind); \ + if ((hstartind) >= (lstartind)) { \ + *lptr pmeqop ((*hptr << 1) + 2) >> 2; \ + lptr += (step); \ + --n; \ + } \ + if ((lendind) > (hendind)) { \ + --n; \ + } \ + while (n-- > 0) { \ + *lptr pmeqop ((*hptr + hptr[(step)]) + 2) >> 2; \ + lptr += (step); \ + hptr += (step); \ + } \ + if ((lendind) > (hendind)) { \ + *lptr pmeqop ((*hptr << 1) + 2) >> 2; \ + } \ +} + +static void jpc_ft_analyze(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x) +{ + jpc_fix_t *startptr; + int startind; + int endind; + jpc_fix_t * lstartptr; + int lstartind; + int lendind; + jpc_fix_t * hstartptr; + int hstartind; + int hendind; + int interstep; + int intrastep; + int numseq; + + if (flags & JPC_QMFB1D_VERT) { + interstep = 1; + intrastep = jas_seq2d_rowstep(x); + numseq = jas_seq2d_width(x); + startind = jas_seq2d_ystart(x); + endind = jas_seq2d_yend(x); + } else { + interstep = jas_seq2d_rowstep(x); + intrastep = 1; + numseq = jas_seq2d_height(x); + startind = jas_seq2d_xstart(x); + endind = jas_seq2d_xend(x); + } + + assert(startind < endind); + + startptr = jas_seq2d_getref(x, jas_seq2d_xstart(x), jas_seq2d_ystart(x)); + if (flags & JPC_QMFB1D_RITIMODE) { + while (numseq-- > 0) { + jpc_qmfb1d_setup(startptr, startind, endind, intrastep, + &lstartptr, &lstartind, &lendind, &hstartptr, + &hstartind, &hendind); + if (endind - startind > 1) { + jpc_qmfb1d_split(startptr, startind, endind, + intrastep, lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind); + RFT_LIFT0(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, -=); + RFT_LIFT1(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, +=); + } else { + if (lstartind == lendind) { + *startptr <<= 1; + } + } + startptr += interstep; + } + } else { + while (numseq-- > 0) { + jpc_qmfb1d_setup(startptr, startind, endind, intrastep, + &lstartptr, &lstartind, &lendind, &hstartptr, + &hstartind, &hendind); + if (endind - startind > 1) { + jpc_qmfb1d_split(startptr, startind, endind, + intrastep, lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind); + NFT_LIFT0(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, + jpc_fix_minuseq); + NFT_LIFT1(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, + jpc_fix_pluseq); + } else { + if (lstartind == lendind) { + *startptr = jpc_fix_asl(*startptr, 1); + } + } + startptr += interstep; + } + } +} + +static void jpc_ft_synthesize(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x) +{ + jpc_fix_t *startptr; + int startind; + int endind; + jpc_fix_t *lstartptr; + int lstartind; + int lendind; + jpc_fix_t *hstartptr; + int hstartind; + int hendind; + int interstep; + int intrastep; + int numseq; + + if (flags & JPC_QMFB1D_VERT) { + interstep = 1; + intrastep = jas_seq2d_rowstep(x); + numseq = jas_seq2d_width(x); + startind = jas_seq2d_ystart(x); + endind = jas_seq2d_yend(x); + } else { + interstep = jas_seq2d_rowstep(x); + intrastep = 1; + numseq = jas_seq2d_height(x); + startind = jas_seq2d_xstart(x); + endind = jas_seq2d_xend(x); + } + + assert(startind < endind); + + startptr = jas_seq2d_getref(x, jas_seq2d_xstart(x), jas_seq2d_ystart(x)); + if (flags & JPC_QMFB1D_RITIMODE) { + while (numseq-- > 0) { + jpc_qmfb1d_setup(startptr, startind, endind, intrastep, + &lstartptr, &lstartind, &lendind, &hstartptr, + &hstartind, &hendind); + if (endind - startind > 1) { + RFT_LIFT1(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, -=); + RFT_LIFT0(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, +=); + jpc_qmfb1d_join(startptr, startind, endind, + intrastep, lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind); + } else { + if (lstartind == lendind) { + *startptr >>= 1; + } + } + startptr += interstep; + } + } else { + while (numseq-- > 0) { + jpc_qmfb1d_setup(startptr, startind, endind, intrastep, + &lstartptr, &lstartind, &lendind, &hstartptr, + &hstartind, &hendind); + if (endind - startind > 1) { + NFT_LIFT1(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, + jpc_fix_minuseq); + NFT_LIFT0(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, + jpc_fix_pluseq); + jpc_qmfb1d_join(startptr, startind, endind, + intrastep, lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind); + } else { + if (lstartind == lendind) { + *startptr = jpc_fix_asr(*startptr, 1); + } + } + startptr += interstep; + } + } +} + +/******************************************************************************\ +* Code for 9/7 transform. +\******************************************************************************/ + +static int jpc_ns_getnumchans(jpc_qmfb1d_t *qmfb) +{ + return 2; +} + +static int jpc_ns_getanalfilters(jpc_qmfb1d_t *qmfb, int len, jas_seq2d_t **filters) +{ + abort(); + return -1; +} + +static int jpc_ns_getsynfilters(jpc_qmfb1d_t *qmfb, int len, jas_seq2d_t **filters) +{ + jas_seq_t *lf; + jas_seq_t *hf; + + lf = 0; + hf = 0; + + if (len > 1 || (!len)) { + if (!(lf = jas_seq_create(-3, 4))) { + goto error; + } + jas_seq_set(lf, -3, jpc_dbltofix(-0.09127176311424948)); + jas_seq_set(lf, -2, jpc_dbltofix(-0.05754352622849957)); + jas_seq_set(lf, -1, jpc_dbltofix(0.5912717631142470)); + jas_seq_set(lf, 0, jpc_dbltofix(1.115087052456994)); + jas_seq_set(lf, 1, jpc_dbltofix(0.5912717631142470)); + jas_seq_set(lf, 2, jpc_dbltofix(-0.05754352622849957)); + jas_seq_set(lf, 3, jpc_dbltofix(-0.09127176311424948)); + if (!(hf = jas_seq_create(-3, 6))) { + goto error; + } + jas_seq_set(hf, -3, jpc_dbltofix(-0.02674875741080976 * 2.0)); + jas_seq_set(hf, -2, jpc_dbltofix(-0.01686411844287495 * 2.0)); + jas_seq_set(hf, -1, jpc_dbltofix(0.07822326652898785 * 2.0)); + jas_seq_set(hf, 0, jpc_dbltofix(0.2668641184428723 * 2.0)); + jas_seq_set(hf, 1, jpc_dbltofix(-0.6029490182363579 * 2.0)); + jas_seq_set(hf, 2, jpc_dbltofix(0.2668641184428723 * 2.0)); + jas_seq_set(hf, 3, jpc_dbltofix(0.07822326652898785 * 2.0)); + jas_seq_set(hf, 4, jpc_dbltofix(-0.01686411844287495 * 2.0)); + jas_seq_set(hf, 5, jpc_dbltofix(-0.02674875741080976 * 2.0)); + } 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 { + abort(); + } + + filters[0] = lf; + filters[1] = hf; + + return 0; + +error: + if (lf) { + jas_seq_destroy(lf); + } + if (hf) { + jas_seq_destroy(hf); + } + return -1; +} + +#define NNS_LIFT0(lstartptr, lstartind, lendind, hstartptr, hstartind, hendind, step, alpha) \ +{ \ + register jpc_fix_t *lptr = (lstartptr); \ + register jpc_fix_t *hptr = (hstartptr); \ + register int n = (hendind) - (hstartind); \ + jpc_fix_t twoalpha = jpc_fix_mulbyint(alpha, 2); \ + if ((hstartind) < (lstartind)) { \ + jpc_fix_pluseq(*hptr, jpc_fix_mul(*lptr, (twoalpha))); \ + hptr += (step); \ + --n; \ + } \ + if ((hendind) >= (lendind)) { \ + --n; \ + } \ + while (n-- > 0) { \ + jpc_fix_pluseq(*hptr, jpc_fix_mul(jpc_fix_add(*lptr, lptr[(step)]), (alpha))); \ + hptr += (step); \ + lptr += (step); \ + } \ + if ((hendind) >= (lendind)) { \ + jpc_fix_pluseq(*hptr, jpc_fix_mul(*lptr, (twoalpha))); \ + } \ +} + +#define NNS_LIFT1(lstartptr, lstartind, lendind, hstartptr, hstartind, hendind, step, alpha) \ +{ \ + register jpc_fix_t *lptr = (lstartptr); \ + register jpc_fix_t *hptr = (hstartptr); \ + register int n = (lendind) - (lstartind); \ + int twoalpha = jpc_fix_mulbyint(alpha, 2); \ + if ((hstartind) >= (lstartind)) { \ + jpc_fix_pluseq(*lptr, jpc_fix_mul(*hptr, (twoalpha))); \ + lptr += (step); \ + --n; \ + } \ + if ((lendind) > (hendind)) { \ + --n; \ + } \ + while (n-- > 0) { \ + jpc_fix_pluseq(*lptr, jpc_fix_mul(jpc_fix_add(*hptr, hptr[(step)]), (alpha))); \ + lptr += (step); \ + hptr += (step); \ + } \ + if ((lendind) > (hendind)) { \ + jpc_fix_pluseq(*lptr, jpc_fix_mul(*hptr, (twoalpha))); \ + } \ +} + +#define NNS_SCALE(startptr, startind, endind, step, alpha) \ +{ \ + register jpc_fix_t *ptr = (startptr); \ + register int n = (endind) - (startind); \ + while (n-- > 0) { \ + jpc_fix_muleq(*ptr, alpha); \ + ptr += (step); \ + } \ +} + +static void jpc_ns_analyze(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x) +{ + jpc_fix_t *startptr; + int startind; + int endind; + jpc_fix_t *lstartptr; + int lstartind; + int lendind; + jpc_fix_t *hstartptr; + int hstartind; + int hendind; + int interstep; + int intrastep; + int numseq; + + if (flags & JPC_QMFB1D_VERT) { + interstep = 1; + intrastep = jas_seq2d_rowstep(x); + numseq = jas_seq2d_width(x); + startind = jas_seq2d_ystart(x); + endind = jas_seq2d_yend(x); + } else { + interstep = jas_seq2d_rowstep(x); + intrastep = 1; + numseq = jas_seq2d_height(x); + startind = jas_seq2d_xstart(x); + endind = jas_seq2d_xend(x); + } + + assert(startind < endind); + + startptr = jas_seq2d_getref(x, jas_seq2d_xstart(x), jas_seq2d_ystart(x)); + if (!(flags & JPC_QMFB1D_RITIMODE)) { + while (numseq-- > 0) { + jpc_qmfb1d_setup(startptr, startind, endind, intrastep, + &lstartptr, &lstartind, &lendind, &hstartptr, + &hstartind, &hendind); + if (endind - startind > 1) { + jpc_qmfb1d_split(startptr, startind, endind, + intrastep, lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind); + NNS_LIFT0(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, + jpc_dbltofix(-1.586134342)); + NNS_LIFT1(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, + jpc_dbltofix(-0.052980118)); + NNS_LIFT0(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, + jpc_dbltofix(0.882911075)); + NNS_LIFT1(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, + jpc_dbltofix(0.443506852)); + NNS_SCALE(lstartptr, lstartind, lendind, + intrastep, jpc_dbltofix(1.0/1.23017410558578)); + NNS_SCALE(hstartptr, hstartind, hendind, + intrastep, jpc_dbltofix(1.0/1.62578613134411)); + } else { +#if 0 + if (lstartind == lendind) { + *startptr = jpc_fix_asl(*startptr, 1); + } +#endif + } + startptr += interstep; + } + } else { + /* The reversible integer-to-integer mode is not supported + for this transform. */ + abort(); + } +} + +static void jpc_ns_synthesize(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x) +{ + jpc_fix_t *startptr; + int startind; + int endind; + jpc_fix_t *lstartptr; + int lstartind; + int lendind; + jpc_fix_t *hstartptr; + int hstartind; + int hendind; + int interstep; + int intrastep; + int numseq; + + if (flags & JPC_QMFB1D_VERT) { + interstep = 1; + intrastep = jas_seq2d_rowstep(x); + numseq = jas_seq2d_width(x); + startind = jas_seq2d_ystart(x); + endind = jas_seq2d_yend(x); + } else { + interstep = jas_seq2d_rowstep(x); + intrastep = 1; + numseq = jas_seq2d_height(x); + startind = jas_seq2d_xstart(x); + endind = jas_seq2d_xend(x); + } + + assert(startind < endind); + + startptr = jas_seq2d_getref(x, jas_seq2d_xstart(x), jas_seq2d_ystart(x)); + if (!(flags & JPC_QMFB1D_RITIMODE)) { + while (numseq-- > 0) { + jpc_qmfb1d_setup(startptr, startind, endind, intrastep, + &lstartptr, &lstartind, &lendind, &hstartptr, + &hstartind, &hendind); + if (endind - startind > 1) { + NNS_SCALE(lstartptr, lstartind, lendind, + intrastep, jpc_dbltofix(1.23017410558578)); + NNS_SCALE(hstartptr, hstartind, hendind, + intrastep, jpc_dbltofix(1.62578613134411)); + NNS_LIFT1(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, + jpc_dbltofix(-0.443506852)); + NNS_LIFT0(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, + jpc_dbltofix(-0.882911075)); + NNS_LIFT1(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, + jpc_dbltofix(0.052980118)); + NNS_LIFT0(lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind, intrastep, + jpc_dbltofix(1.586134342)); + jpc_qmfb1d_join(startptr, startind, endind, + intrastep, lstartptr, lstartind, lendind, + hstartptr, hstartind, hendind); + } else { +#if 0 + if (lstartind == lendind) { + *startptr = jpc_fix_asr(*startptr, 1); + } +#endif + } + startptr += interstep; + } + } else { + /* The reversible integer-to-integer mode is not supported + for this transform. */ + abort(); + } +} + +/******************************************************************************\ +* +\******************************************************************************/ + +jpc_qmfb1d_t *jpc_qmfb1d_make(int qmfbid) +{ + jpc_qmfb1d_t *qmfb; + if (!(qmfb = jpc_qmfb1d_create())) { + return 0; + } + switch (qmfbid) { + case JPC_QMFB1D_FT: + qmfb->ops = &jpc_ft_ops; + break; + case JPC_QMFB1D_NS: + qmfb->ops = &jpc_ns_ops; + break; + default: + jpc_qmfb1d_destroy(qmfb); + return 0; + break; + } + return qmfb; +} + +static jpc_qmfb1d_t *jpc_qmfb1d_create() +{ + jpc_qmfb1d_t *qmfb; + if (!(qmfb = jas_malloc(sizeof(jpc_qmfb1d_t)))) { + return 0; + } + qmfb->ops = 0; + return qmfb; +} + +jpc_qmfb1d_t *jpc_qmfb1d_copy(jpc_qmfb1d_t *qmfb) +{ + jpc_qmfb1d_t *newqmfb; + + if (!(newqmfb = jpc_qmfb1d_create())) { + return 0; + } + newqmfb->ops = qmfb->ops; + return newqmfb; +} + +void jpc_qmfb1d_destroy(jpc_qmfb1d_t *qmfb) +{ + jas_free(qmfb); +} + +/******************************************************************************\ +* +\******************************************************************************/ + +void jpc_qmfb1d_getbands(jpc_qmfb1d_t *qmfb, int flags, uint_fast32_t xstart, + uint_fast32_t ystart, uint_fast32_t xend, uint_fast32_t yend, int maxbands, + int *numbandsptr, jpc_qmfb1dband_t *bands) +{ + int start; + int end; + if (flags & JPC_QMFB1D_VERT) { + start = ystart; + end = yend; + } else { + start = xstart; + end = xend; + } + assert(jpc_qmfb1d_getnumchans(qmfb) == 2); + assert(start <= end); + bands[0].start = JPC_CEILDIVPOW2(start, 1); + bands[0].end = JPC_CEILDIVPOW2(end, 1); + bands[0].locstart = start; + bands[0].locend = start + bands[0].end - bands[0].start; + bands[1].start = JPC_FLOORDIVPOW2(start, 1); + bands[1].end = JPC_FLOORDIVPOW2(end, 1); + bands[1].locstart = bands[0].locend; + bands[1].locend = bands[1].locstart + bands[1].end - bands[1].start; + assert(bands[1].locend == end); + *numbandsptr = 2; +} + +/******************************************************************************\ +* +\******************************************************************************/ + +int jpc_qmfb1d_getnumchans(jpc_qmfb1d_t *qmfb) +{ + return (*qmfb->ops->getnumchans)(qmfb); +} + +int jpc_qmfb1d_getanalfilters(jpc_qmfb1d_t *qmfb, int len, jas_seq2d_t **filters) +{ + return (*qmfb->ops->getanalfilters)(qmfb, len, filters); +} + +int jpc_qmfb1d_getsynfilters(jpc_qmfb1d_t *qmfb, int len, jas_seq2d_t **filters) +{ + return (*qmfb->ops->getsynfilters)(qmfb, len, filters); +} + +void jpc_qmfb1d_analyze(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x) +{ + (*qmfb->ops->analyze)(qmfb, flags, x); +} + +void jpc_qmfb1d_synthesize(jpc_qmfb1d_t *qmfb, int flags, jas_seq2d_t *x) +{ + (*qmfb->ops->synthesize)(qmfb, flags, x); +} |