📄 mqcoder.java
字号:
} break; default: throw new Error("Illegal termination type code"); } // Reinitialize the state (without modifying the contexts) int len; len = nrOfWrittenBytes; a = 0x8000; c = 0; b = 0; cT = 12; delFF = false; nrOfWrittenBytes = -1; // Return the terminated length return len; } /** * Returns the number of contexts in the arithmetic coder. * * @return The number of contexts * */ public final int getNumCtxts(){ return I.length; } /** * Resets a context to the original probability distribution, and sets its * more probable symbol to 0. * * @param c The number of the context (it starts at 0). * */ public final void resetCtxt(int c){ I[c]=initStates[c]; mPS[c] = 0; } /** * Resets all contexts to their original probability distribution and sets * all more probable symbols to 0. * */ public final void resetCtxts(){ System.arraycopy(initStates,0,I,0,I.length); ArrayUtil.intArraySet(mPS,0); } /** * Returns the number of bytes that are necessary from the compressed * output stream to decode all the symbols that have been coded this * far. The number of returned bytes does not include anything coded * previous to the last time the 'terminate()' or 'reset()' methods where * called. * * <P>The values returned by this method are then to be used in finishing * the length calculation with the 'finishLengthCalculation()' method, * after compensation of the offset in the number of bytes due to previous * terminated segments. * * <P>This method should not be called if the current coding pass is to be * terminated. The 'terminate()' method should be called instead. * * <P>The calculation is done based on the type of length calculation * specified at the constructor. * * @return The number of bytes in the compressed output stream necessary * to decode all the information coded this far. * */ public final int getNumCodedBytes(){ // NOTE: testing these algorithms for correctness is quite // difficult. One way is to modify the rate allocator so that not all // bit-planes are output if the distortion estimate for last passes is // the same as for the previous ones. switch (ltype) { case LENGTH_LAZY_GOOD: // This one is a bit better than LENGTH_LAZY. int bitsInN3Bytes; // The minimum amount of bits that can be stored // in the 3 bytes following the current byte // buffer 'b'. if (b >= 0xFE) { // The byte after b can have a bit stuffed so ther could be // one less bit available bitsInN3Bytes = 22; // 7 + 8 + 7 } else { // We are sure that next byte after current byte buffer has no // bit stuffing bitsInN3Bytes = 23; // 8 + 7 + 8 } if ((11-cT+16) <= bitsInN3Bytes) { return nrOfWrittenBytes+(delFF ? 1 : 0)+1+3; } else { return nrOfWrittenBytes+(delFF ? 1 : 0)+1+4; } case LENGTH_LAZY: // This is the very basic one that appears in the VM text if ((27-cT) <= 22) { return nrOfWrittenBytes+(delFF ? 1 : 0)+1+3; } else { return nrOfWrittenBytes+(delFF ? 1 : 0)+1+4; } case LENGTH_NEAR_OPT: // This is the best length calculation implemented in this class. // It is almost always optimal. In order to calculate the length // it is necessary to know which bytes will follow in the MQ // bit stream, so we need to wait until termination to perform it. // Save the state to perform the calculation later, in // finishLengthCalculation() saveState(); // Return current number of output bytes to use it later in // finishLengthCalculation() return nrOfWrittenBytes; default: throw new Error("Illegal length calculation type code"); } } /** * Reinitializes the MQ coder and the underlying 'ByteOutputBuffer' buffer * as if a new object was instantaited. All the data in the * 'ByteOutputBuffer' buffer is erased and the state and contexts of the * MQ coder are reinitialized). Additionally any saved MQ states are * discarded. * */ public final void reset() { // Reset the output buffer out.reset(); a=0x8000; c=0; b=0; if(b==0xFF) cT=13; else cT=12; resetCtxts(); nrOfWrittenBytes = -1; delFF = false; nSaved = 0; } /** * Saves the current state of the MQ coder (just the registers, not the * contexts) so that a near optimal length calculation can be performed * later. * */ private void saveState() { // Increase capacity if necessary if (nSaved == savedC.length) { Object tmp; tmp = savedC; savedC = new int[nSaved+SAVED_INC]; System.arraycopy(tmp,0,savedC,0,nSaved); tmp = savedCT; savedCT = new int[nSaved+SAVED_INC]; System.arraycopy(tmp,0,savedCT,0,nSaved); tmp = savedA; savedA = new int[nSaved+SAVED_INC]; System.arraycopy(tmp,0,savedA,0,nSaved); tmp = savedB; savedB = new int[nSaved+SAVED_INC]; System.arraycopy(tmp,0,savedB,0,nSaved); tmp = savedDelFF; savedDelFF = new boolean[nSaved+SAVED_INC]; System.arraycopy(tmp,0,savedDelFF,0,nSaved); } // Save the current sate savedC[nSaved] = c; savedCT[nSaved] = cT; savedA[nSaved] = a; savedB[nSaved] = b; savedDelFF[nSaved] = delFF; nSaved++; } /** * Terminates the calculation of the required length for each coding * pass. This method must be called just after the 'terminate()' one has * been called for each terminated MQ segment. * * <P>The values in 'rates' must have been compensated for any offset due * to previous terminated segments, so that the correct index to the * stored coded data is used. * * @param rates The array containing the values returned by * 'getNumCodedBytes()' for each coding pass. * * @param n The index in the 'rates' array of the last terminated length. * */ public void finishLengthCalculation(int rates[], int n) { if (ltype != LENGTH_NEAR_OPT) { // For the simple calculations the only thing we need to do is to // ensure that the calculated lengths are no greater than the // terminated one if (n > 0 && rates[n-1] > rates[n]) { // We need correction int tl = rates[n]; // The terminated length n--; do { rates[n--] = tl; } while (n >= 0 && rates[n] > tl); } } else { // We need to perform the more sophisticated near optimal // calculation. // The calculation of the length is based on the fact that the // decoder will pad the codestream with an endless string of // (binary) 1s after termination. If the codestream, padded with // 1s, is within the bounds of the current interval then correct // decoding is guaranteed. The lower inclusive bound of the // current interval is the value of C (i.e. if only lower // intervals would be coded in the future). The upper exclusive // bound of the current interval is C+A (i.e. if only upper // intervals would be coded in the future). We therefore calculate // the minimum length that would be needed so that padding with 1s // gives a codestream within the interval. // In order to know what will be appended to the current base of // the interval we need to know what is in the MQ bit stream after // the current last output byte until the termination. This is why // this calculation has to be performed after the MQ segment has // been entirely coded and terminated. int cLow; // lower bound on the C register for correct decoding int cUp; // upper bound on the C register for correct decoding int bLow; // lower bound on the byte buffer for correct decoding int bUp; // upper bound on the byte buffer for correct decoding int ridx; // index in the rates array of the pass we are // calculating int sidx; // index in the saved state array int clen; // current calculated length boolean cdFF; // the current delayed FF state int nb; // the next byte of output int minlen; // minimum possible length int maxlen; // maximum possible length // Start on the first pass of this segment ridx = n-nSaved; // Minimum allowable length is length of previous termination minlen = (ridx-1>=0) ? rates[ridx-1] : 0; // Maximum possible length is the terminated length maxlen = rates[n]; for (sidx = 0; ridx < n; ridx++, sidx++) { // Load the initial values of the bounds cLow = savedC[sidx]; cUp = savedC[sidx]+savedA[sidx]; bLow = savedB[sidx]; bUp = savedB[sidx]; // Normalize to CT = 0 and propagate and reset any carry bits cLow <<= savedCT[sidx]; if ((cLow & 0x8000000) != 0) { bLow++; cLow &= 0x7FFFFFF; } cUp <<= savedCT[sidx]; if ((cUp & 0x8000000) != 0) { bUp++; cUp &= 0x7FFFFFF; } // Initialize current calculated length cdFF = savedDelFF[sidx]; // rates[ridx] contains the number of bytes already output // when the state was saved, compensated for the offset in the // output stream. clen = rates[ridx]+(cdFF? 1 : 0); while (true) { // If we are at end of coded data then this is the length if (clen >= maxlen) { clen = maxlen; break; } // Check for sufficiency of coded data if (cdFF) { if (bLow < 128 && bUp >= 128) { // We are done for this pass clen--; // Don't need delayed FF break; } } else { if (bLow < 256 && bUp >= 256) { // We are done for this pass break; } } // Update bounds with next byte of coded data and // normalize to CT = 0 again. nb = (clen >= minlen) ? out.getByte(clen) : 0; bLow -= nb; bUp -= nb; clen++; if (nb == 0xFF) { bLow <<= 7; bLow |= (cLow >> 20) & 0x7F; cLow &= 0xFFFFF; cLow <<= 7; bUp <<= 7; bUp |= (cUp >> 20) & 0x7F; cUp &= 0xFFFFF; cUp <<= 7; cdFF = true; } else { bLow <<= 8; bLow |= (cLow >> 19) & 0xFF; cLow &= 0x7FFFF; cLow <<= 8; bUp <<= 8; bUp |= (cUp >> 19) & 0xFF; cUp &= 0x7FFFF; cUp <<= 8; cdFF = false; } // Test again } // Store the rate found rates[ridx] = (clen>=minlen) ? clen : minlen; } // Reset the saved states nSaved = 0; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -