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 + -
显示快捷键?