mqcoder.java

来自「jpeg2000编解码」· Java 代码 · 共 1,321 行 · 第 1/4 页

JAVA
1,321
字号
     * this array to reinitialize the contexts whenever 'reset()' or     * 'resetCtxts()' is called.     * */    public MQCoder(ByteOutputBuffer oStream, int nrOfContexts, int init[]) {        out = oStream;        // --- INITENC        // Default initialization of the statistics bins is MPS=0 and        // I=0        I=new int[nrOfContexts];        mPS=new int[nrOfContexts];        initStates = init;        a=0x8000;        c=0;        if(b==0xFF) {            cT=13;        } else {            cT=12;        }        resetCtxts();                // End of INITENC ---        b=0;    }    /**     * This method performs the coding of the symbol 'bit', using context     * 'ctxt', 'n' times, using the MQ-coder speedup mode if possible.     *     * <p>If the symbol 'bit' is the current more probable symbol (MPS) and     * qe[ctxt]<=0x4000, and (A-0x8000)>=qe[ctxt], speedup mode will be     * used. Otherwise the normal mode will be used. The speedup mode can     * significantly improve the speed of arithmetic coding when several MPS     * symbols, with a high probability distribution, must be coded with the     * same context. The generated bit stream is the same as if the normal mode     * was used.</p>     *     * <p>This method is also faster than the 'codeSymbols()' and     * 'codeSymbol()' ones, for coding the same symbols with the same context     * several times, when speedup mode can not be used, although not     * significantly.</p>     *     * @param bit The symbol do code, 0 or 1.     *     * @param ctxt The context to us in coding the symbol.     *     * @param n The number of times that the symbol must be coded.     * */    public final void fastCodeSymbols(int bit, int ctxt, int n) {        int q;  // cache for context's Qe        int la; // cache for A register        int nc; // counter for renormalization shifts        int ns; // the maximum length of a speedup mode run        int li; // cache for I[ctxt]        li = I[ctxt]; // cache current index        q=qe[li];     // retrieve current LPS prob.        if ((q<=0x4000) && (bit==mPS[ctxt])            && ((ns = (a-0x8000)/q+1) > 1)) { // Do speed up mode            // coding MPS, no conditional exchange can occur and            // speedup mode is possible for more than 1 symbol            do { // do as many speedup runs as necessary                if (n<=ns) { // All symbols in this run                    // code 'n' symbols                    la = n*q; // accumulated Q                    a -= la;                    c += la;                    if (a>=0x8000) { // no renormalization                        I[ctxt] = li;  // save the current state                        return; // done                    }                    I[ctxt] = nMPS[li]; // goto next state and save it                    // -- Renormalization (MPS: no need for while loop)                    a <<= 1; // a is doubled                    c <<= 1; // c is doubled                    cT--;                    if(cT==0) {                        byteOut();                    }                    // -- End of renormalization                    return; // done                } else { // Not all symbols in this run                    // code 'ns' symbols                    la = ns*q; // accumulated Q                    c += la;                    a -= la;                    // cache li and q for next iteration                    li = nMPS[li];                    q = qe[li]; // New q is always less than current one                    // new I[ctxt] is stored in last run                    // Renormalization always occurs since we exceed 'ns'                    // -- Renormalization (MPS: no need for while loop)                    a <<= 1; // a is doubled                    c <<= 1; // c is doubled                    cT--;                    if(cT==0) {                        byteOut();                    }                    // -- End of renormalization                    n -= ns; // symbols left to code                    ns = (a-0x8000)/q+1; // max length of next speedup run                    continue; // goto next iteration                }            } while (n>0);        } // end speed up mode        else { // No speedup mode            // Either speedup mode is not possible or not worth doing it            // because of probable conditional exchange            // Code everything as in normal mode            la = a;       // cache A register in local variable            do {                if (bit==mPS[ctxt]) { // -- code MPS                    la -= q; // Interval division associated with MPS coding                    if(la>=0x8000){ // Interval big enough                        c += q;                    } else { // Interval too short                        if(la<q) { // Probabilities are inverted                            la = q;                        } else {                            c += q;                        }                        // cache new li and q for next iteration                        li = nMPS[li];                        q = qe[li];                        // new I[ctxt] is stored after end of loop                        // -- Renormalization (MPS: no need for while loop)                        la <<= 1; // a is doubled                        c <<= 1;  // c is doubled                        cT--;                        if(cT==0) {                            byteOut();                        }                        // -- End of renormalization                    }                } else { // -- code LPS                    la -= q; // Interval division according to LPS coding                    if(la<q) {                        c += q;                    } else {                        la = q;                    }                    if(switchLM[li]!=0) {                        mPS[ctxt]=1-mPS[ctxt];                    }                    // cache new li and q for next iteration                    li = nLPS[li];                    q = qe[li];                    // new I[ctxt] is stored after end of loop                    // -- Renormalization                    // sligthly better than normal loop                    nc = 0;                    do {                        la <<= 1;                        nc++; // count number of necessary shifts                    } while (la<0x8000);                    if (cT>nc) {                        c <<= nc;                        cT -= nc;                    } else {                        do {                            c <<= cT;                            nc -= cT;                            // cT = 0; // not necessary                            byteOut();                        } while (cT<=nc);                        c <<= nc;                        cT -= nc;                    }                    // -- End of renormalization                }                n--;            } while (n>0);            I[ctxt] = li; // store new I[ctxt]            a = la; // save cached A register        }    }        /**     * This function performs the arithmetic encoding of several symbols     * together. The function receives an array of symbols that are to be     * encoded and an array containing the contexts with which to encode them.     *     * <p>The advantage of using this function is that the cost of the method     * call is amortized by the number of coded symbols per method call.</p>     *      * <p>Each context has a current MPS and an index describing what the      * current probability is for the LPS. Each bit is encoded and if the     * probability of the LPS exceeds .5, the MPS and LPS are switched.</p>     *     * @param bits An array containing the symbols to be encoded. Valid     * symbols are 0 and 1.     *     * @param cX The context for each of the symbols to be encoded.     *     * @param n The number of symbols to encode.     * */    public final void codeSymbols(int[] bits, int[] cX, int n) {        int q;        int li; // local cache of I[context]        int la;        int nc;        int ctxt; // context of current symbol        int i; // counter        // NOTE: here we could use symbol aggregation to speed things up.        // It remains to be studied.	        la = a; // cache A register in local variable        for(i=0; i<n; i++) {            // NOTE: (a<0x8000) is equivalent to ((a&0x8000)==0)            // since 'a' is always less than or equal to 0xFFFF            // NOTE: conditional exchange guarantees that A for MPS is            // always greater than 0x4000 (i.e. 0.375)            // => one renormalization shift is enough for MPS            // => no need to do a renormalization while loop for MPS            ctxt = cX[i];            li = I[ctxt];            q = qe[li]; // Retrieve current LPS prob.                        if(bits[i]==mPS[ctxt]) { // -- Code MPS                la -= q; // Interval division associated with MPS coding                                if(la>=0x8000) { // Interval big enough                    c += q;                } else { // Interval too short                    if(la<q) {// Probabilities are inverted                        la = q;                    } else {                        c += q;                    }                                    I[ctxt]=nMPS[li];                    // -- Renormalization (MPS: no need for while loop)                    la <<= 1; // a is doubled                    c <<= 1; // c is doubled                    cT--;                    if(cT==0) {                        byteOut();                    }                    // -- End of renormalization                }            } else { // -- Code LPS                la -= q; // Interval division according to LPS coding                if(la<q) {                    c += q;                } else {                    la = q;                }                if(switchLM[li]!=0) {                    mPS[ctxt]=1-mPS[ctxt];                }                I[ctxt]=nLPS[li];                            // -- Renormalization                // sligthly better than normal loop                nc = 0;                do {                    la <<= 1;                    nc++; // count number of necessary shifts                } while (la<0x8000);                if (cT>nc) {                    c <<= nc;                    cT -= nc;                } else {                    do {                        c <<= cT;                        nc -= cT;                        // cT = 0; // not necessary                        byteOut();                    } while (cT<=nc);                    c <<= nc;                    cT -= nc;                }                            // -- End of renormalization            }        }        a = la; // save cached A register    }    /**     * This function performs the arithmetic encoding of one symbol. The      * function receives a bit that is to be encoded and a context with which     * to encode it.     *     * <p>Each context has a current MPS and an index describing what the      * current probability is for the LPS. Each bit is encoded and if the     * probability of the LPS exceeds .5, the MPS and LPS are switched.</p>     *     * @param bit The symbol to be encoded, must be 0 or 1.     *     * @param context the context with which to encode the symbol.     * */    public final void codeSymbol(int bit, int context) {        int q;        int li; // local cache of I[context]        int la;        int n;        // NOTE: (a < 0x8000) is equivalent to ((a & 0x8000)==0)        // since 'a' is always less than or equal to 0xFFFF        // NOTE: conditional exchange guarantees that A for MPS is        // always greater than 0x4000 (i.e. 0.375)        // => one renormalization shift is enough for MPS        // => no need to do a renormalization while loop for MPS        li = I[context];        q=qe[li]; // Retrieve current LPS prob.        if(bit==mPS[context]) {// -- Code MPS            a -= q; // Interval division associated with MPS coding            if(a>=0x8000){ // Interval big enough                c += q;            } else { // Interval too short                if(a<q) { // Probabilities are inverted                    a = q;                } else {

⌨️ 快捷键说明

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