/// <summary> Compresses the code-block in 'srcblk' and puts the results in 'ccb', /// using the specified options and temporary storage. /// /// </summary> /// <param name="c">The component for which to return the next code-block. /// /// </param> /// <param name="ccb">The object where the compressed data will be stored. If the /// 'data' array of 'cbb' is not null it may be reused to return the /// compressed data. /// /// </param> /// <param name="srcblk">The code-block data to code /// /// </param> /// <param name="mq">The MQ-coder to use /// /// </param> /// <param name="bout">The bit level output to use. Used only if 'OPT_BYPASS' is /// turned on in the 'options' argument. /// /// </param> /// <param name="out">The byte buffer trough which the compressed data is stored. /// /// </param> /// <param name="state">The state information for the code-block /// /// </param> /// <param name="distbuf">The buffer where to store the distortion at /// the end of each coding pass. /// /// </param> /// <param name="ratebuf">The buffer where to store the rate (i.e. coded lenth) at /// the end of each coding pass. /// /// </param> /// <param name="istermbuf">The buffer where to store the terminated flag for each /// coding pass. /// /// </param> /// <param name="symbuf">The buffer to hold symbols to send to the MQ coder /// /// </param> /// <param name="ctxtbuf">A buffer to hold the contexts to use in sending the /// buffered symbols to the MQ coder. /// /// </param> /// <param name="options">The options to use when coding this code-block /// /// </param> /// <param name="rev">The reversible flag. Should be true if the source of this /// code-block's data is reversible. /// /// </param> /// <param name="lcType">The type of length calculation to use with the MQ coder. /// /// </param> /// <param name="tType">The type of termination to use with the MQ coder. /// /// </param> /// <seealso cref="getNextCodeBlock"> /// /// </seealso> static private void compressCodeBlock(int c, CBlkRateDistStats ccb, CBlkWTData srcblk, MQCoder mq, BitToByteOutput bout, ByteOutputBuffer out_Renamed, int[] state, double[] distbuf, int[] ratebuf, bool[] istermbuf, int[] symbuf, int[] ctxtbuf, int options, bool rev, int lcType, int tType) { // NOTE: This method should not access any non-final instance or // static variables, either directly or indirectly through other // methods in order to be sure that the method is thread safe. int[] zc_lut; // The ZC lookup table to use int skipbp; // The number of non-significant bit-planes to skip int curbp; // The current magnitude bit-plane (starts at 30) int[] fm; // The distortion estimation lookup table for MR int[] fs; // The distortion estimation lookup table for SC int lmb; // The least significant magnitude bit int npass; // The number of coding passes, for R-D statistics double msew; // The distortion (MSE weight) for the current bit-plane double totdist; // The total cumulative distortion decrease int ltpidx; // The index of the last pass which is terminated // Check error-resilient termination if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0 && tType != MQCoder.TERM_PRED_ER) { throw new System.ArgumentException("Embedded error-resilient info " + "in MQ termination option " + "specified but incorrect MQ " + "termination " + "policy specified"); } // Set MQ flags mq.LenCalcType = lcType; mq.TermType = tType; lmb = 30 - srcblk.magbits + 1; // If there are more bit-planes to code than the implementation // bit-depth set lmb to 0 lmb = (lmb < 0)?0:lmb; // Reset state ArrayUtil.intArraySet(state, 0); // Find the most significant bit-plane skipbp = calcSkipMSBP(srcblk, lmb); // Initialize output code-block ccb.m = srcblk.m; ccb.n = srcblk.n; ccb.sb = srcblk.sb; ccb.nROIcoeff = srcblk.nROIcoeff; ccb.skipMSBP = skipbp; if (ccb.nROIcoeff != 0) { ccb.nROIcp = 3 * (srcblk.nROIbp - skipbp - 1) + 1; } else { ccb.nROIcp = 0; } // Choose correct ZC lookup table for global orientation switch (srcblk.sb.orientation) { case Subband.WT_ORIENT_HL: zc_lut = ZC_LUT_HL; break; case Subband.WT_ORIENT_LL: case Subband.WT_ORIENT_LH: zc_lut = ZC_LUT_LH; break; case Subband.WT_ORIENT_HH: zc_lut = ZC_LUT_HH; break; default: throw new System.InvalidOperationException("JJ2000 internal error"); } // Loop on significant magnitude bit-planes doing the 3 passes curbp = 30 - skipbp; fs = FS_LOSSY; fm = FM_LOSSY; msew = System.Math.Pow(2, ((curbp - lmb) << 1) - MSE_LKP_FRAC_BITS) * srcblk.sb.stepWMSE * srcblk.wmseScaling; totdist = 0f; npass = 0; ltpidx = - 1; // First significant bit-plane has only the pass pass if (curbp >= lmb) { // Do we need the "lossless" 'fs' table ? if (rev && curbp == lmb) { fs = FM_LOSSLESS; } // We terminate if regular termination, last bit-plane, or next // bit-plane is "raw". istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || curbp == lmb || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp) >= curbp); totdist += cleanuppass(srcblk, mq, istermbuf[npass], curbp, state, fs, zc_lut, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew; distbuf[npass] = totdist; if (istermbuf[npass]) ltpidx = npass; npass++; msew *= 0.25; curbp--; } // Other bit-planes have all passes while (curbp >= lmb) { // Do we need the "lossless" 'fs' and 'fm' tables ? if (rev && curbp == lmb) { fs = FS_LOSSLESS; fm = FM_LOSSLESS; } // Do the significance propagation pass // We terminate if regular termination only istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0; if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) == 0 || (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp <= curbp)) { // No bypass coding totdist += sigProgPass(srcblk, mq, istermbuf[npass], curbp, state, fs, zc_lut, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew; } else { // Bypass ("raw") coding bout.PredTerm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0; totdist += rawSigProgPass(srcblk, bout, istermbuf[npass], curbp, state, fs, ratebuf, npass, ltpidx, options) * msew; } distbuf[npass] = totdist; if (istermbuf[npass]) ltpidx = npass; npass++; // Do the magnitude refinement pass // We terminate if regular termination or bypass ("raw") coding istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp > curbp)); if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) == 0 || (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp <= curbp)) { // No bypass coding totdist += magRefPass(srcblk, mq, istermbuf[npass], curbp, state, fm, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew; } else { // Bypass ("raw") coding bout.PredTerm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0; totdist += rawMagRefPass(srcblk, bout, istermbuf[npass], curbp, state, fm, ratebuf, npass, ltpidx, options) * msew; } distbuf[npass] = totdist; if (istermbuf[npass]) ltpidx = npass; npass++; // Do the clenup pass // We terminate if regular termination, last bit-plane, or next // bit-plane is "raw". istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || curbp == lmb || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp) >= curbp); totdist += cleanuppass(srcblk, mq, istermbuf[npass], curbp, state, fs, zc_lut, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew; distbuf[npass] = totdist; if (istermbuf[npass]) ltpidx = npass; npass++; // Goto next bit-plane msew *= 0.25; curbp--; } // Copy compressed data and rate-distortion statistics to output ccb.data = new byte[out_Renamed.size()]; out_Renamed.toByteArray(0, out_Renamed.size(), ccb.data, 0); checkEndOfPassFF(ccb.data, ratebuf, istermbuf, npass); ccb.selectConvexHull(ratebuf, distbuf, (options & (CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS | CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS)) != 0?istermbuf:null, npass, rev); // Reset MQ coder and bit output for next code-block mq.reset(); if (bout != null) bout.reset(); }
/// <summary> Instantiates a new entropy coder engine, with the specified source of /// data, nominal block width and height. /// /// <p>If the 'OPT_PRED_TERM' option is given then the MQ termination must /// be 'TERM_PRED_ER' or an exception is thrown.</p> /// /// </summary> /// <param name="src">The source of data /// /// </param> /// <param name="cbks">Code-block size specifications /// /// </param> /// <param name="pss">Precinct partition specifications /// /// </param> /// <param name="bms">By-pass mode specifications /// /// </param> /// <param name="mqrs">MQ-reset specifications /// /// </param> /// <param name="rts">Regular termination specifications /// /// </param> /// <param name="css">Causal stripes specifications /// /// </param> /// <param name="sss">Error resolution segment symbol use specifications /// /// </param> /// <param name="lcs">Length computation specifications /// /// </param> /// <param name="tts">Termination type specifications /// /// </param> /// <seealso cref="MQCoder"> /// /// </seealso> public StdEntropyCoder(CBlkQuantDataSrcEnc src, CBlkSizeSpec cblks, PrecinctSizeSpec pss, StringSpec bms, StringSpec mqrs, StringSpec rts, StringSpec css, StringSpec sss, StringSpec lcs, StringSpec tts):base(src) { this.cblks = cblks; this.pss = pss; this.bms = bms; this.mqrs = mqrs; this.rts = rts; this.css = css; this.sss = sss; this.lcs = lcs; this.tts = tts; int maxCBlkWidth, maxCBlkHeight; int i; // Counter int tsl; // Size for thread structures // Get the biggest width/height for the code-blocks maxCBlkWidth = cblks.MaxCBlkWidth; maxCBlkHeight = cblks.MaxCBlkHeight; // If we do timing create necessary structures #if DO_TIMING time = new long[src.NumComps]; // If we are timing make sure that 'finalize' gets called. //UPGRADE_ISSUE: Method 'java.lang.System.runFinalizersOnExit' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javalangSystem'" // CONVERSION PROBLEM? //System_Renamed.runFinalizersOnExit(true); #endif tsl = 1; finishedTileComponent = null; // Allocate data structures outT = new ByteOutputBuffer[tsl]; mqT = new MQCoder[tsl]; boutT = new BitToByteOutput[tsl]; stateT = new int[tsl][]; for (int i2 = 0; i2 < tsl; i2++) { stateT[i2] = new int[(maxCBlkWidth + 2) * ((maxCBlkHeight + 1) / 2 + 2)]; } symbufT = new int[tsl][]; for (int i3 = 0; i3 < tsl; i3++) { symbufT[i3] = new int[maxCBlkWidth * (CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT * 2 + 2)]; } ctxtbufT = new int[tsl][]; for (int i4 = 0; i4 < tsl; i4++) { ctxtbufT[i4] = new int[maxCBlkWidth * (CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT * 2 + 2)]; } distbufT = new double[tsl][]; for (int i5 = 0; i5 < tsl; i5++) { distbufT[i5] = new double[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES]; } ratebufT = new int[tsl][]; for (int i6 = 0; i6 < tsl; i6++) { ratebufT[i6] = new int[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES]; } istermbufT = new bool[tsl][]; for (int i7 = 0; i7 < tsl; i7++) { istermbufT[i7] = new bool[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES]; } srcblkT = new CBlkWTData[tsl]; for (i = 0; i < tsl; i++) { outT[i] = new ByteOutputBuffer(); mqT[i] = new MQCoder(outT[i], NUM_CTXTS, MQ_INIT); } precinctPartition = new bool[src.NumComps][]; for (int i8 = 0; i8 < src.NumComps; i8++) { precinctPartition[i8] = new bool[src.getNumTiles()]; } // Create the subband description for each component and each tile //Subband sb = null; Coord numTiles = null; int nc = NumComps; numTiles = src.getNumTiles(numTiles); initTileComp(getNumTiles(), nc); for (int c = 0; c < nc; c++) { for (int tY = 0; tY < numTiles.y; tY++) { for (int tX = 0; tX < numTiles.x; tX++) { precinctPartition[c][tIdx] = false; } } } }
/// <summary> Instantiates a new MQ-coder, with the specified number of contexts and /// initial states. The compressed bytestream is written to the 'oStream' /// object. /// /// </summary> /// <param name="oStream">where to output the compressed data. /// /// </param> /// <param name="nrOfContexts">The number of contexts used by the MQ coder. /// /// </param> /// <param name="init">The initial state for each context. A reference is kept to /// this array to reinitialize the contexts whenever 'reset()' or /// 'resetCtxts()' is called. /// /// </param> public MQCoder(ByteOutputBuffer oStream, int nrOfContexts, int[] init) { out_Renamed = 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; }
/// <summary> Instantiates a new 'BitToByteOutput' object that uses 'out' as the /// underlying byte based output. /// /// </summary> /// <param name="out">The underlying byte based output /// /// </param> internal BitToByteOutput(ByteOutputBuffer out_Renamed) { this.out_Renamed = out_Renamed; }
/// <summary> Instantiates a new 'BitToByteOutput' object that uses 'out' as the /// underlying byte based output. /// /// </summary> /// <param name="out">The underlying byte based output /// /// </param> internal BitToByteOutput(ByteOutputBuffer out_Renamed) { this.out_Renamed = out_Renamed; }
/// <summary> Instantiates a new entropy coder engine, with the specified source of /// data, nominal block width and height. /// /// <p>If the 'OPT_PRED_TERM' option is given then the MQ termination must /// be 'TERM_PRED_ER' or an exception is thrown.</p> /// /// </summary> /// <param name="src">The source of data /// /// </param> /// <param name="cbks">Code-block size specifications /// /// </param> /// <param name="pss">Precinct partition specifications /// /// </param> /// <param name="bms">By-pass mode specifications /// /// </param> /// <param name="mqrs">MQ-reset specifications /// /// </param> /// <param name="rts">Regular termination specifications /// /// </param> /// <param name="css">Causal stripes specifications /// /// </param> /// <param name="sss">Error resolution segment symbol use specifications /// /// </param> /// <param name="lcs">Length computation specifications /// /// </param> /// <param name="tts">Termination type specifications /// /// </param> /// <seealso cref="MQCoder"> /// /// </seealso> public StdEntropyCoder(CBlkQuantDataSrcEnc src, CBlkSizeSpec cblks, PrecinctSizeSpec pss, StringSpec bms, StringSpec mqrs, StringSpec rts, StringSpec css, StringSpec sss, StringSpec lcs, StringSpec tts):base(src) { this.cblks = cblks; this.pss = pss; this.bms = bms; this.mqrs = mqrs; this.rts = rts; this.css = css; this.sss = sss; this.lcs = lcs; this.tts = tts; int maxCBlkWidth, maxCBlkHeight; int i; // Counter int nt; // The number of threads int tsl; // Size for thread structures // Get the biggest width/height for the code-blocks maxCBlkWidth = cblks.MaxCBlkWidth; maxCBlkHeight = cblks.MaxCBlkHeight; nt = Environment.ProcessorCount; /* // Get the number of threads to use, or default to one try { //UPGRADE_ISSUE: Method 'java.lang.System.getProperty' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javalangSystem'" nt = System.Int32.Parse(System_Renamed.getProperty(THREADS_PROP_NAME, DEF_THREADS_NUM)); if (nt < 0) throw new System.FormatException(); } catch (System.FormatException e) { throw new System.ArgumentException("Invalid number of threads " + "for " + "entropy coding in property " + THREADS_PROP_NAME); } */ // If we do timing create necessary structures #if DO_TIMING time = new long[src.NumComps]; // If we are timing make sure that 'finalize' gets called. //UPGRADE_ISSUE: Method 'java.lang.System.runFinalizersOnExit' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javalangSystem'" // CONVERSION PROBLEM? //System_Renamed.runFinalizersOnExit(true); #endif // If using multithreaded implementation get necessasry objects if (nt > 0) { FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.INFO, "Using multithreaded entropy coder " + "with " + nt + " compressor threads."); tsl = nt; tPool = new ThreadPool(nt, (System.Int32) SupportClass.ThreadClass.Current().Priority + THREADS_PRIORITY_INC, "StdEntropyCoder"); idleComps = new System.Collections.ArrayList(); completedComps = new System.Collections.ArrayList[src.NumComps]; nBusyComps = new int[src.NumComps]; finishedTileComponent = new bool[src.NumComps]; for (i = src.NumComps - 1; i >= 0; i--) { completedComps[i] = new System.Collections.ArrayList(); } for (i = 0; i < nt; i++) { idleComps.Add(new StdEntropyCoder.Compressor(this, i)); } } else { tsl = 1; tPool = null; idleComps = null; completedComps = null; nBusyComps = null; finishedTileComponent = null; } // Allocate data structures outT = new ByteOutputBuffer[tsl]; mqT = new MQCoder[tsl]; boutT = new BitToByteOutput[tsl]; stateT = new int[tsl][]; for (int i2 = 0; i2 < tsl; i2++) { stateT[i2] = new int[(maxCBlkWidth + 2) * ((maxCBlkHeight + 1) / 2 + 2)]; } symbufT = new int[tsl][]; for (int i3 = 0; i3 < tsl; i3++) { symbufT[i3] = new int[maxCBlkWidth * (CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT * 2 + 2)]; } ctxtbufT = new int[tsl][]; for (int i4 = 0; i4 < tsl; i4++) { ctxtbufT[i4] = new int[maxCBlkWidth * (CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT * 2 + 2)]; } distbufT = new double[tsl][]; for (int i5 = 0; i5 < tsl; i5++) { distbufT[i5] = new double[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES]; } ratebufT = new int[tsl][]; for (int i6 = 0; i6 < tsl; i6++) { ratebufT[i6] = new int[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES]; } istermbufT = new bool[tsl][]; for (int i7 = 0; i7 < tsl; i7++) { istermbufT[i7] = new bool[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES]; } srcblkT = new CBlkWTData[tsl]; for (i = 0; i < tsl; i++) { outT[i] = new ByteOutputBuffer(); mqT[i] = new MQCoder(outT[i], NUM_CTXTS, MQ_INIT); } precinctPartition = new bool[src.NumComps][]; for (int i8 = 0; i8 < src.NumComps; i8++) { precinctPartition[i8] = new bool[src.getNumTiles()]; } // Create the subband description for each component and each tile //Subband sb = null; Coord numTiles = null; int nc = NumComps; numTiles = src.getNumTiles(numTiles); initTileComp(getNumTiles(), nc); for (int c = 0; c < nc; c++) { for (int tY = 0; tY < numTiles.y; tY++) { for (int tX = 0; tX < numTiles.x; tX++) { precinctPartition[c][tIdx] = false; } } } }