/// <summary> Reads a QCD marker segment and realigns the codestream at the point /// where the next marker should be found. QCD is a functional marker /// segment that describes the quantization default. /// /// </summary> /// <param name="ehs">The encoded stream. /// /// </param> /// <param name="mainh">Flag indicating whether or not this marker segment is read /// from the main header. /// /// </param> /// <param name="tileIdx">The index of the current tile /// /// </param> /// <param name="tpIdx">Tile-part index /// /// </param> /// <exception cref="IOException">If an I/O error occurs while reading from the /// encoded header stream. /// /// </exception> //UPGRADE_TODO: Class 'java.io.DataInputStream' was converted to 'System.IO.BinaryReader' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioDataInputStream'" private void readQCD(System.IO.BinaryReader ehs, bool mainh, int tileIdx, int tpIdx) { StdDequantizerParams qParms; int guardBits; int[][] exp; float[][] nStep = null; HeaderInfo.QCD ms = hi.NewQCD; // Lqcd (length of QCD field) ms.lqcd = ehs.ReadUInt16(); // Sqcd (quantization style) ms.sqcd = ehs.ReadByte(); guardBits = ms.NumGuardBits; int qType = ms.QuantType; if (mainh) { hi.qcdValue["main"] = ms; // If the main header is being read set default value of // dequantization spec switch (qType) { case CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION: decSpec.qts.setDefault("reversible"); break; case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED: decSpec.qts.setDefault("derived"); break; case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED: decSpec.qts.setDefault("expounded"); break; default: throw new CorruptedCodestreamException("Unknown or " + "unsupported " + "quantization style " + "in Sqcd field, QCD " + "marker main header"); } } else { hi.qcdValue["t" + tileIdx] = ms; // If the tile header is being read set default value of // dequantization spec for tile switch (qType) { case CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION: decSpec.qts.setTileDef(tileIdx, "reversible"); break; case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED: decSpec.qts.setTileDef(tileIdx, "derived"); break; case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED: decSpec.qts.setTileDef(tileIdx, "expounded"); break; default: throw new CorruptedCodestreamException("Unknown or " + "unsupported " + "quantization style " + "in Sqcd field, QCD " + "marker, tile header"); } } qParms = new StdDequantizerParams(); if (qType == CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION) { int maxrl = (mainh?((System.Int32) decSpec.dls.getDefault()):((System.Int32) decSpec.dls.getTileDef(tileIdx))); int j, rl; // i removed int minb, maxb, hpd; int tmp; exp = qParms.exp = new int[maxrl + 1][]; int[][] tmpArray = new int[maxrl + 1][]; for (int i2 = 0; i2 < maxrl + 1; i2++) { tmpArray[i2] = new int[4]; } ms.spqcd = tmpArray; for (rl = 0; rl <= maxrl; rl++) { // Loop on resolution levels // Find the number of subbands in the resolution level if (rl == 0) { // Only the LL subband minb = 0; maxb = 1; } else { // Dyadic decomposition hpd = 1; // Adapt hpd to resolution level if (hpd > maxrl - rl) { hpd -= (maxrl - rl); } else { hpd = 1; } // Determine max and min subband index minb = 1 << ((hpd - 1) << 1); // minb = 4^(hpd-1) maxb = 1 << (hpd << 1); // maxb = 4^hpd } // Allocate array for subbands in resolution level exp[rl] = new int[maxb]; for (j = minb; j < maxb; j++) { tmp = ms.spqcd[rl][j] = ehs.ReadByte(); exp[rl][j] = (tmp >> CSJ2K.j2k.codestream.Markers.SQCX_EXP_SHIFT) & CSJ2K.j2k.codestream.Markers.SQCX_EXP_MASK; } } // end for rl } else { int maxrl = (qType == CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED)?0:(mainh?((System.Int32) decSpec.dls.getDefault()):((System.Int32) decSpec.dls.getTileDef(tileIdx))); int j, rl; // i removed int minb, maxb, hpd; int tmp; exp = qParms.exp = new int[maxrl + 1][]; nStep = qParms.nStep = new float[maxrl + 1][]; int[][] tmpArray2 = new int[maxrl + 1][]; for (int i3 = 0; i3 < maxrl + 1; i3++) { tmpArray2[i3] = new int[4]; } ms.spqcd = tmpArray2; for (rl = 0; rl <= maxrl; rl++) { // Loop on resolution levels // Find the number of subbands in the resolution level if (rl == 0) { // Only the LL subband minb = 0; maxb = 1; } else { // Dyadic decomposition hpd = 1; // Adapt hpd to resolution level if (hpd > maxrl - rl) { hpd -= (maxrl - rl); } else { hpd = 1; } // Determine max and min subband index minb = 1 << ((hpd - 1) << 1); // minb = 4^(hpd-1) maxb = 1 << (hpd << 1); // maxb = 4^hpd } // Allocate array for subbands in resolution level exp[rl] = new int[maxb]; nStep[rl] = new float[maxb]; for (j = minb; j < maxb; j++) { tmp = ms.spqcd[rl][j] = ehs.ReadUInt16(); exp[rl][j] = (tmp >> 11) & 0x1f; // NOTE: the formula below does not support more than 5 // bits for the exponent, otherwise (-1<<exp) might // overflow (the - is used to be able to represent 2**31) //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" nStep[rl][j] = (- 1f - ((float) (tmp & 0x07ff)) / (1 << 11)) / (- 1 << exp[rl][j]); } } // end for rl } // end if (qType != SQCX_NO_QUANTIZATION) // Fill qsss, gbs if (mainh) { decSpec.qsss.setDefault(qParms); decSpec.gbs.setDefault((System.Object) guardBits); } else { decSpec.qsss.setTileDef(tileIdx, qParms); decSpec.gbs.setTileDef(tileIdx, (System.Object) guardBits); } // Check marker length checkMarkerLength(ehs, "QCD marker"); }
/// <summary> Changes the current tile, given the new indexes. An /// IllegalArgumentException is thrown if the indexes do not correspond to /// a valid tile. /// /// </summary> /// <param name="x">The horizontal indexes the tile. /// /// </param> /// <param name="y">The vertical indexes of the new tile. /// /// </param> public override void setTile(int x, int y) { int i; // counter // Check validity of tile indexes if (x < 0 || y < 0 || x >= ntX || y >= ntY) { throw new System.ArgumentException(); } int t = (y * ntX + x); // Reset number of read bytes if needed if (t == 0) { anbytes = headLen; if (!isTruncMode) { anbytes += 2; } // Restore values of nBytes for (int tIdx = 0; tIdx < nt; tIdx++) { nBytes[tIdx] = baknBytes[tIdx]; } } // Set the new current tile ctX = x; ctY = y; // Calculate tile relative points int ctox = (x == 0)?ax:px + x * ntW; int ctoy = (y == 0)?ay:py + y * ntH; for (i = nc - 1; i >= 0; i--) { culx[i] = (ctox + hd.getCompSubsX(i) - 1) / hd.getCompSubsX(i); culy[i] = (ctoy + hd.getCompSubsY(i) - 1) / hd.getCompSubsY(i); offX[i] = (px + x * ntW + hd.getCompSubsX(i) - 1) / hd.getCompSubsX(i); offY[i] = (py + y * ntH + hd.getCompSubsY(i) - 1) / hd.getCompSubsY(i); } // Initialize subband tree and number of resolution levels subbTrees = new SubbandSyn[nc]; mdl = new int[nc]; derived = new bool[nc]; params_Renamed = new StdDequantizerParams[nc]; gb = new int[nc]; for (int c = 0; c < nc; c++) { derived[c] = decSpec.qts.isDerived(t, c); params_Renamed[c] = (StdDequantizerParams) decSpec.qsss.getTileCompVal(t, c); gb[c] = ((System.Int32) decSpec.gbs.getTileCompVal(t, c)); mdl[c] = ((System.Int32) decSpec.dls.getTileCompVal(t, c)); subbTrees[c] = new SubbandSyn(getTileCompWidth(t, c, mdl[c]), getTileCompHeight(t, c, mdl[c]), getResULX(c, mdl[c]), getResULY(c, mdl[c]), mdl[c], decSpec.wfs.getHFilters(t, c), decSpec.wfs.getVFilters(t, c)); initSubbandsFields(c, subbTrees[c]); } // Read tile's packets try { readTilePkts(t); } catch (System.IO.IOException e) { SupportClass.WriteStackTrace(e, Console.Error); throw new System.ApplicationException("IO Error when reading tile " + x + " x " + y); } }
/// <summary> Returns the specified code-block in the current tile for the specified /// component (as a reference or copy). /// /// <p>The returned code-block may be progressive, which is indicated by /// the 'progressive' variable of the returned 'DataBlk' /// object. If a code-block is progressive it means that in a later request /// to this method for the same code-block it is possible to retrieve data /// which is a better approximation, since meanwhile more data to decode /// for the code-block could have been received. If the code-block is not /// progressive then later calls to this method for the same code-block /// will return the exact same data values.</p> /// /// <p>The data returned by this method can be the data in the internal /// buffer of this object, if any, and thus can not be modified by the /// caller. The 'offset' and 'scanw' of the returned data can be /// arbitrary. See the 'DataBlk' class.</p> /// /// </summary> /// <param name="c">The component for which to return the next code-block. /// /// </param> /// <param name="m">The vertical index of the code-block to return, in the /// specified subband. /// /// </param> /// <param name="n">The horizontal index of the code-block to return, in the /// specified subband. /// /// </param> /// <param name="sb">The subband in which the code-block to return is. /// /// </param> /// <param name="cblk">If non-null this object will be used to return the new /// code-block. If null a new one will be allocated and returned. If the /// "data" array of the object is non-null it will be reused, if possible, /// to return the data. /// /// </param> /// <returns> The next code-block in the current tile for component 'n', or /// null if all code-blocks for the current tile have been returned. /// /// </returns> /// <seealso cref="DataBlk"> /// /// </seealso> public override DataBlk getInternCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk) { // This method is declared final since getNextCodeBlock() relies on // the actual implementation of this method. int j, jmin, k; int temp; float step; int shiftBits; int magBits; int[] outiarr, inarr; float[] outfarr; int w, h; bool reversible = qts.isReversible(tIdx, c); bool derived = qts.isDerived(tIdx, c); StdDequantizerParams params_Renamed = (StdDequantizerParams)qsss.getTileCompVal(tIdx, c); int G = ((System.Int32)gbs.getTileCompVal(tIdx, c)); outdtype = cblk.DataType; if (reversible && outdtype != DataBlk.TYPE_INT) { throw new System.ArgumentException("Reversible quantizations " + "must use int data"); } // To get compiler happy outiarr = null; outfarr = null; inarr = null; // Get source data and initialize output DataBlk object. switch (outdtype) { case DataBlk.TYPE_INT: // With int data we can use the same DataBlk object to get the // data from the source and return the dequantized data, and we // can also work "in place" (i.e. same buffer). cblk = src.getCodeBlock(c, m, n, sb, cblk); // Input and output arrays are the same outiarr = (int[])cblk.Data; break; case DataBlk.TYPE_FLOAT: // With float data we must use a different DataBlk objects to get // the data from the source and to return the dequantized data. inblk = (DataBlkInt)src.getInternCodeBlock(c, m, n, sb, inblk); inarr = inblk.DataInt; if (cblk == null) { cblk = new DataBlkFloat(); } // Copy the attributes of the CodeBlock object cblk.ulx = inblk.ulx; cblk.uly = inblk.uly; cblk.w = inblk.w; cblk.h = inblk.h; cblk.offset = 0; cblk.scanw = cblk.w; cblk.progressive = inblk.progressive; // Get output data array and check its size outfarr = (float[])cblk.Data; if (outfarr == null || outfarr.Length < cblk.w * cblk.h) { outfarr = new float[cblk.w * cblk.h]; cblk.Data = outfarr; } break; } magBits = sb.magbits; // Calculate quantization step and number of magnitude bits // depending on reversibility and derivedness and perform // inverse quantization if (reversible) { shiftBits = 31 - magBits; // For int data Inverse quantization happens "in-place". The input // array has an offset of 0 and scan width equal to the code-block // width. for (j = outiarr.Length - 1; j >= 0; j--) { temp = outiarr[j]; // input array is same as output one outiarr[j] = (temp >= 0) ? (temp >> shiftBits) : -((temp & 0x7FFFFFFF) >> shiftBits); } } else { // Not reversible if (derived) { // Max resolution level int mrl = src.getSynSubbandTree(TileIdx, c).resLvl; step = params_Renamed.nStep[0][0] * (1L << (rb[c] + sb.anGainExp + mrl - sb.level)); } else { step = params_Renamed.nStep[sb.resLvl][sb.sbandIdx] * (1L << (rb[c] + sb.anGainExp)); } shiftBits = 31 - magBits; // Adjust step to the number of shiftBits step /= (1 << shiftBits); switch (outdtype) { case DataBlk.TYPE_INT: // For int data Inverse quantization happens "in-place". The // input array has an offset of 0 and scan width equal to the // code-block width. for (j = outiarr.Length - 1; j >= 0; j--) { temp = outiarr[j]; // input array is same as output one //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" outiarr[j] = (int)(((float)((temp >= 0) ? temp : -(temp & 0x7FFFFFFF))) * step); } break; case DataBlk.TYPE_FLOAT: // For float data the inverse quantization can not happen // "in-place". w = cblk.w; h = cblk.h; for (j = w * h - 1, k = inblk.offset + (h - 1) * inblk.scanw + w - 1, jmin = w * (h - 1); j >= 0; jmin -= w) { for (; j >= jmin; k--, j--) { temp = inarr[k]; //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" outfarr[j] = ((float)((temp >= 0) ? temp : -(temp & 0x7FFFFFFF))) * step; } // Jump to beggining of previous line in input k -= (inblk.scanw - w); } break; } } // Return the output code-block return(cblk); }