corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * CVS identifier:
3 *
4 * $Id: EBCOTRateAllocator.java,v 1.97 2002/05/22 14:59:44 grosbois Exp $
5 *
6 * Class: EBCOTRateAllocator
7 *
8 * Description: Generic interface for post-compression
9 * rate allocator.
10 *
11 *
12 *
13 * COPYRIGHT:
14 *
15 * This software module was originally developed by Raphaël Grosbois and
16 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
17 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
18 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
19 * Centre France S.A) in the course of development of the JPEG2000
20 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
21 * software module is an implementation of a part of the JPEG 2000
22 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
23 * Systems AB and Canon Research Centre France S.A (collectively JJ2000
24 * Partners) agree not to assert against ISO/IEC and users of the JPEG
25 * 2000 Standard (Users) any of their rights under the copyright, not
26 * including other intellectual property rights, for this software module
27 * with respect to the usage by ISO/IEC and Users of this software module
28 * or modifications thereof for use in hardware or software products
29 * claiming conformance to the JPEG 2000 Standard. Those intending to use
30 * this software module in hardware or software products are advised that
31 * their use may infringe existing patents. The original developers of
32 * this software module, JJ2000 Partners and ISO/IEC assume no liability
33 * for use of this software module or modifications thereof. No license
34 * or right to this software module is granted for non JPEG 2000 Standard
35 * conforming products. JJ2000 Partners have full right to use this
36 * software module for his/her own purpose, assign or donate this
37 * software module to any third party and to inhibit third parties from
38 * using this software module for non JPEG 2000 Standard conforming
39 * products. This copyright notice must be included in all copies or
40 * derivative works of this software module.
41 *
42 * Copyright (c) 1999/2000 JJ2000 Partners.
43 * */
44 using System;
45 using CSJ2K.j2k.codestream.writer;
46 using CSJ2K.j2k.wavelet.analysis;
47 using CSJ2K.j2k.entropy.encoder;
48 using CSJ2K.j2k.codestream;
49 using CSJ2K.j2k.entropy;
50 using CSJ2K.j2k.encoder;
51 using CSJ2K.j2k.image;
52 using CSJ2K.j2k.util;
53 namespace CSJ2K.j2k.entropy.encoder
54 {
55  
56 /// <summary> This implements the EBCOT post compression rate allocation algorithm. This
57 /// algorithm finds the most suitable truncation points for the set of
58 /// code-blocks, for each layer target bitrate. It works by first collecting
59 /// the rate distortion info from all code-blocks, in all tiles and all
60 /// components, and then running the rate-allocation on the whole image at
61 /// once, for each layer.
62 ///
63 /// <p>This implementation also provides some timing features. They can be
64 /// enabled by setting the 'DO_TIMING' constant of this class to true and
65 /// recompiling. The timing uses the 'System.currentTimeMillis()' Java API
66 /// call, which returns wall clock time, not the actual CPU time used. The
67 /// timing results will be printed on the message output. Since the times
68 /// reported are wall clock times and not CPU usage times they can not be added
69 /// to find the total used time (i.e. some time might be counted in several
70 /// places). When timing is disabled ('DO_TIMING' is false) there is no penalty
71 /// if the compiler performs some basic optimizations. Even if not the penalty
72 /// should be negligeable.</p>
73 ///
74 /// </summary>
75 /// <seealso cref="PostCompRateAllocator">
76 /// </seealso>
77 /// <seealso cref="CodedCBlkDataSrcEnc">
78 /// </seealso>
79 /// <seealso cref="jj2000.j2k.codestream.writer.CodestreamWriter">
80 ///
81 /// </seealso>
82 public class EBCOTRateAllocator:PostCompRateAllocator
83 {
84  
85 /// <summary>Whether to collect timing information or not: false. Used as a compile
86 /// time directive.
87 /// </summary>
88  
89 #if DO_TIMING
90 /// <summary>The wall time for the initialization. </summary>
91 //private long initTime;
92  
93 /// <summary>The wall time for the building of layers. </summary>
94 //private long buildTime;
95  
96 /// <summary>The wall time for the writing of layers. </summary>
97 //private long writeTime;
98 #endif
99  
100 /// <summary> 5D Array containing all the coded code-blocks:
101 ///
102 /// <ul>
103 /// <li>1st index: tile index</li>
104 /// <li>2nd index: component index</li>
105 /// <li>3rd index: resolution level index</li>
106 /// <li>4th index: subband index</li>
107 /// <li>5th index: code-block index</li>
108 /// </ul>
109 ///
110 /// </summary>
111 private CBlkRateDistStats[][][][][] cblks;
112  
113 /// <summary> 6D Array containing the indices of the truncation points. It actually
114 /// contains the index of the element in CBlkRateDistStats.truncIdxs that
115 /// gives the real truncation point index.
116 ///
117 /// <ul>
118 /// <li>1st index: tile index</li>
119 /// <li>2nd index: layer index</li>
120 /// <li>3rd index: component index</li>
121 /// <li>4th index: resolution level index</li>
122 /// <li>5th index: subband index</li>
123 /// <li>6th index: code-block index</li>
124 /// </ul>
125 ///
126 /// </summary>
127 private int[][][][][][] truncIdxs;
128  
129 /// <summary> Number of precincts in each resolution level:
130 ///
131 /// <ul>
132 /// <li>1st dim: tile index.</li>
133 /// <li>2nd dim: component index.</li>
134 /// <li>3nd dim: resolution level index.</li>
135 /// </ul>
136 ///
137 /// </summary>
138 private Coord[][][] numPrec;
139  
140 /// <summary>Array containing the layers information. </summary>
141 private EBCOTLayer[] layers;
142  
143 /// <summary>The log of 2, natural base </summary>
144 //UPGRADE_NOTE: Final was removed from the declaration of 'LOG2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
145 private static readonly double LOG2 = System.Math.Log(2);
146  
147 /// <summary>The normalization offset for the R-D summary table </summary>
148 private const int RD_SUMMARY_OFF = 24;
149  
150 /// <summary>The size of the summary table </summary>
151 private const int RD_SUMMARY_SIZE = 64;
152  
153 /// <summary>The relative precision for float data. This is the relative tolerance
154 /// up to which the layer slope thresholds are calculated.
155 /// </summary>
156 private const float FLOAT_REL_PRECISION = 1e-4f;
157  
158 /// <summary>The precision for float data type, in an absolute sense. Two float
159 /// numbers are considered "equal" if they are within this precision.
160 /// </summary>
161 private const float FLOAT_ABS_PRECISION = 1e-10f;
162  
163 /// <summary>Minimum average size of a packet. If layer has less bytes than the
164 /// this constant multiplied by number of packets in the layer, then the
165 /// layer is skipped.
166 /// </summary>
167 private const int MIN_AVG_PACKET_SZ = 32;
168  
169 /// <summary>The R-D summary information collected from the coding of all
170 /// code-blocks. For each entry it contains the accumulated length of all
171 /// truncation points that have a slope not less than
172 /// '2*(k-RD_SUMMARY_OFF)', where 'k' is the entry index.
173 ///
174 /// <p>Therefore, the length at entry 'k' is the total number of bytes of
175 /// code-block data that would be obtained if the truncation slope was
176 /// chosen as '2*(k-RD_SUMMARY_OFF)', without counting the overhead
177 /// associated with the packet heads.</p>
178 ///
179 /// <p>This summary is used to estimate the relation of the R-D slope to
180 /// coded length, and to obtain absolute minimums on the slope given a
181 /// length. </p>
182 /// </summary>
183 private int[] RDSlopesRates;
184  
185 /// <summary>Packet encoder. </summary>
186 private PktEncoder pktEnc;
187  
188 /// <summary>The layer specifications </summary>
189 private LayersInfo lyrSpec;
190  
191 /// <summary>The maximum slope accross all code-blocks and truncation points. </summary>
192 private float maxSlope;
193  
194 /// <summary>The minimum slope accross all code-blocks and truncation points. </summary>
195 private float minSlope;
196  
197 /// <summary> Initializes the EBCOT rate allocator of entropy coded data. The layout
198 /// of layers, and their bitrate constraints, is specified by the 'lyrs'
199 /// parameter.
200 ///
201 /// </summary>
202 /// <param name="src">The source of entropy coded data.
203 ///
204 /// </param>
205 /// <param name="lyrs">The layers layout specification.
206 ///
207 /// </param>
208 /// <param name="writer">The bit stream writer.
209 ///
210 /// </param>
211 /// <seealso cref="ProgressionType">
212 ///
213 /// </seealso>
214 public EBCOTRateAllocator(CodedCBlkDataSrcEnc src, LayersInfo lyrs, CodestreamWriter writer, EncoderSpecs encSpec, ParameterList pl):base(src, lyrs.TotNumLayers, writer, encSpec)
215 {
216  
217 int minsbi, maxsbi;
218 int i;
219 SubbandAn sb, sb2;
220 Coord ncblks = null;
221  
222 // If we do timing create necessary structures
223 #if DO_TIMING
224 // If we are timing make sure that 'finalize' gets called.
225 //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'"
226 // CONVERSION PROBLEM?
227 //System_Renamed.runFinalizersOnExit(true);
228 // The System.runFinalizersOnExit() method is deprecated in Java
229 // 1.2 since it can cause a deadlock in some cases. However, here
230 // we use it only for profiling purposes and is disabled in
231 // production code.
232 initTime = 0L;
233 buildTime = 0L;
234 writeTime = 0L;
235 #endif
236  
237 // Save the layer specs
238 lyrSpec = lyrs;
239  
240 //Initialize the size of the RD slope rates array
241 RDSlopesRates = new int[RD_SUMMARY_SIZE];
242  
243 //Get number of tiles, components
244 int nt = src.getNumTiles();
245 int nc = NumComps;
246  
247 //Allocate the coded code-blocks and truncation points indexes arrays
248 cblks = new CBlkRateDistStats[nt][][][][];
249 for (int i2 = 0; i2 < nt; i2++)
250 {
251 cblks[i2] = new CBlkRateDistStats[nc][][][];
252 }
253 truncIdxs = new int[nt][][][][][];
254 for (int i3 = 0; i3 < nt; i3++)
255 {
256 truncIdxs[i3] = new int[num_Layers][][][][];
257 for (int i4 = 0; i4 < num_Layers; i4++)
258 {
259 truncIdxs[i3][i4] = new int[nc][][][];
260 }
261 }
262  
263 int cblkPerSubband; // Number of code-blocks per subband
264 int mrl; // Number of resolution levels
265 int l; // layer index
266 int s; //subband index
267  
268 // Used to compute the maximum number of precincts for each resolution
269 // level
270 int tx0, ty0, tx1, ty1; // Current tile position in the reference grid
271 int tcx0, tcy0, tcx1, tcy1; // Current tile position in the domain of
272 // the image component
273 int trx0, try0, trx1, try1; // Current tile position in the reduced
274 // resolution image domain
275 int xrsiz, yrsiz; // Component sub-sampling factors
276 Coord tileI = null;
277 Coord nTiles = null;
278 int xsiz, ysiz, x0siz, y0siz;
279 int xt0siz, yt0siz;
280 int xtsiz, ytsiz;
281  
282 int cb0x = src.CbULX;
283 int cb0y = src.CbULY;
284  
285 src.setTile(0, 0);
286 for (int t = 0; t < nt; t++)
287 {
288 // Loop on tiles
289 nTiles = src.getNumTiles(nTiles);
290 tileI = src.getTile(tileI);
291 x0siz = ImgULX;
292 y0siz = ImgULY;
293 xsiz = x0siz + ImgWidth;
294 ysiz = y0siz + ImgHeight;
295 xt0siz = src.TilePartULX;
296 yt0siz = src.TilePartULY;
297 xtsiz = src.NomTileWidth;
298 ytsiz = src.NomTileHeight;
299  
300 // Tile's coordinates on the reference grid
301 tx0 = (tileI.x == 0)?x0siz:xt0siz + tileI.x * xtsiz;
302 ty0 = (tileI.y == 0)?y0siz:yt0siz + tileI.y * ytsiz;
303 tx1 = (tileI.x != nTiles.x - 1)?xt0siz + (tileI.x + 1) * xtsiz:xsiz;
304 ty1 = (tileI.y != nTiles.y - 1)?yt0siz + (tileI.y + 1) * ytsiz:ysiz;
305  
306 for (int c = 0; c < nc; c++)
307 {
308 // loop on components
309  
310 //Get the number of resolution levels
311 sb = src.getAnSubbandTree(t, c);
312 mrl = sb.resLvl + 1;
313  
314 // Initialize maximum number of precincts per resolution array
315 if (numPrec == null)
316 {
317 Coord[][][] tmpArray = new Coord[nt][][];
318 for (int i5 = 0; i5 < nt; i5++)
319 {
320 tmpArray[i5] = new Coord[nc][];
321 }
322 numPrec = tmpArray;
323 }
324 if (numPrec[t][c] == null)
325 {
326 numPrec[t][c] = new Coord[mrl];
327 }
328  
329 // Subsampling factors
330 xrsiz = src.getCompSubsX(c);
331 yrsiz = src.getCompSubsY(c);
332  
333 // Tile's coordinates in the image component domain
334 //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'"
335 tcx0 = (int) System.Math.Ceiling(tx0 / (double) (xrsiz));
336 //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'"
337 tcy0 = (int) System.Math.Ceiling(ty0 / (double) (yrsiz));
338 //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'"
339 tcx1 = (int) System.Math.Ceiling(tx1 / (double) (xrsiz));
340 //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'"
341 tcy1 = (int) System.Math.Ceiling(ty1 / (double) (yrsiz));
342  
343 cblks[t][c] = new CBlkRateDistStats[mrl][][];
344  
345 for (l = 0; l < num_Layers; l++)
346 {
347 truncIdxs[t][l][c] = new int[mrl][][];
348 }
349  
350 for (int r = 0; r < mrl; r++)
351 {
352 // loop on resolution levels
353  
354 // Tile's coordinates in the reduced resolution image
355 // domain
356 //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'"
357 trx0 = (int) System.Math.Ceiling(tcx0 / (double) (1 << (mrl - 1 - r)));
358 //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'"
359 try0 = (int) System.Math.Ceiling(tcy0 / (double) (1 << (mrl - 1 - r)));
360 //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'"
361 trx1 = (int) System.Math.Ceiling(tcx1 / (double) (1 << (mrl - 1 - r)));
362 //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'"
363 try1 = (int) System.Math.Ceiling(tcy1 / (double) (1 << (mrl - 1 - r)));
364  
365 // Calculate the maximum number of precincts for each
366 // resolution level taking into account tile specific
367 // options.
368 double twoppx = (double) encSpec.pss.getPPX(t, c, r);
369 double twoppy = (double) encSpec.pss.getPPY(t, c, r);
370 numPrec[t][c][r] = new Coord();
371 if (trx1 > trx0)
372 {
373 //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'"
374 numPrec[t][c][r].x = (int) System.Math.Ceiling((trx1 - cb0x) / twoppx) - (int) System.Math.Floor((trx0 - cb0x) / twoppx);
375 }
376 else
377 {
378 numPrec[t][c][r].x = 0;
379 }
380 if (try1 > try0)
381 {
382 //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'"
383 numPrec[t][c][r].y = (int) System.Math.Ceiling((try1 - cb0y) / twoppy) - (int) System.Math.Floor((try0 - cb0y) / (double) twoppy);
384 }
385 else
386 {
387 numPrec[t][c][r].y = 0;
388 }
389  
390 minsbi = (r == 0)?0:1;
391 maxsbi = (r == 0)?1:4;
392  
393 cblks[t][c][r] = new CBlkRateDistStats[maxsbi][];
394 for (l = 0; l < num_Layers; l++)
395 {
396 truncIdxs[t][l][c][r] = new int[maxsbi][];
397 }
398  
399 for (s = minsbi; s < maxsbi; s++)
400 {
401 // loop on subbands
402 //Get the number of blocks in the current subband
403 sb2 = (SubbandAn) sb.getSubbandByIdx(r, s);
404 ncblks = sb2.numCb;
405 cblkPerSubband = ncblks.x * ncblks.y;
406 cblks[t][c][r][s] = new CBlkRateDistStats[cblkPerSubband];
407  
408 for (l = 0; l < num_Layers; l++)
409 {
410 truncIdxs[t][l][c][r][s] = new int[cblkPerSubband];
411 for (i = 0; i < cblkPerSubband; i++)
412 {
413 truncIdxs[t][l][c][r][s][i] = - 1;
414 }
415 }
416 } // End loop on subbands
417 } // End lopp on resolution levels
418 } // End loop on components
419 if (t != nt - 1)
420 {
421 src.nextTile();
422 }
423 } // End loop on tiles
424  
425 //Initialize the packet encoder
426 pktEnc = new PktEncoder(src, encSpec, numPrec, pl);
427  
428 // The layers array has to be initialized after the constructor since
429 // it is needed that the bit stream header has been entirely written
430 }
431  
432 #if DO_TIMING
433 /// <summary> Prints the timing information, if collected, and calls 'finalize' on
434 /// the super class.
435 ///
436 /// </summary>
437 ~EBCOTRateAllocator()
438 {
439  
440 System.Text.StringBuilder sb;
441  
442 sb = new System.Text.StringBuilder("EBCOTRateAllocator wall clock times:\n");
443 sb.Append(" initialization: ");
444 sb.Append(initTime);
445 sb.Append(" ms\n");
446 sb.Append(" layer building: ");
447 sb.Append(buildTime);
448 sb.Append(" ms\n");
449 sb.Append(" final writing: ");
450 sb.Append(writeTime);
451 sb.Append(" ms");
452 FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.INFO, sb.ToString());
453 //UPGRADE_NOTE: Call to 'super.finalize()' was removed. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1124'"
454 }
455 #endif
456 /// <summary> Runs the rate allocation algorithm and writes the data to the bit
457 /// stream writer object provided to the constructor.
458 ///
459 /// </summary>
460 public override void runAndWrite()
461 {
462 //Now, run the rate allocation
463 buildAndWriteLayers();
464 }
465  
466 /// <summary> Initializes the layers array. This must be called after the main header
467 /// has been entirely written or simulated, so as to take its overhead into
468 /// account. This method will get all the code-blocks and then initialize
469 /// the target bitrates for each layer, according to the specifications.
470 ///
471 /// </summary>
472 public override void initialize()
473 {
474 int n, i, l;
475 int ho; // The header overhead (in bytes)
476 float np; // The number of pixels divided by the number of bits per byte
477 double ls; // Step for log-scale
478 double basebytes;
479 int lastbytes, newbytes, nextbytes;
480 int loopnlyrs;
481 int minlsz; // The minimum allowable number of bytes in a layer
482 int totenclength;
483 int maxpkt;
484 int numTiles = src.getNumTiles();
485 int numComps = src.NumComps;
486 int numLvls;
487 int avgPktLen;
488 #if DO_TIMING
489 long stime = 0L;
490 #endif
491 // Start by getting all the code-blocks, we need this in order to have
492 // an idea of the total encoded bitrate.
493 getAllCodeBlocks();
494  
495 #if DO_TIMING
496 stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
497 #endif
498  
499 // Now get the total encoded length
500 totenclength = RDSlopesRates[0]; // all the encoded data
501 // Make a rough estimation of the packet head overhead, as 2 bytes per
502 // packet in average (plus EPH / SOP) , and add that to the total
503 // encoded length
504 for (int t = 0; t < numTiles; t++)
505 {
506 avgPktLen = 2;
507 // Add SOP length if set
508 if (((System.String) encSpec.sops.getTileDef(t)).ToUpper().Equals("on".ToUpper()))
509 {
510 avgPktLen += CSJ2K.j2k.codestream.Markers.SOP_LENGTH;
511 }
512 // Add EPH length if set
513 if (((System.String) encSpec.ephs.getTileDef(t)).ToUpper().Equals("on".ToUpper()))
514 {
515 avgPktLen += CSJ2K.j2k.codestream.Markers.EPH_LENGTH;
516 }
517  
518 for (int c = 0; c < numComps; c++)
519 {
520 numLvls = src.getAnSubbandTree(t, c).resLvl + 1;
521 if (!src.precinctPartitionUsed(c, t))
522 {
523 // Precinct partition is not used so there is only
524 // one packet per resolution level/layer
525 totenclength += num_Layers * avgPktLen * numLvls;
526 }
527 else
528 {
529 // Precinct partition is used so for each
530 // component/tile/resolution level, we get the maximum
531 // number of packets
532 for (int rl = 0; rl < numLvls; rl++)
533 {
534 maxpkt = numPrec[t][c][rl].x * numPrec[t][c][rl].y;
535 totenclength += num_Layers * avgPktLen * maxpkt;
536 }
537 }
538 } // End loop on components
539 } // End loop on tiles
540  
541 // If any layer specifies more than 'totenclength' as its target
542 // length then 'totenclength' is used. This is to prevent that
543 // estimated layers get excessively large target lengths due to an
544 // excessively large target bitrate. At the end the last layer is set
545 // to the target length corresponding to the overall target
546 // bitrate. Thus, 'totenclength' can not limit the total amount of
547 // encoded data, as intended.
548  
549 ho = headEnc.Length;
550 np = src.ImgWidth * src.ImgHeight / 8f;
551  
552 // SOT marker must be taken into account
553 for (int t = 0; t < numTiles; t++)
554 {
555 headEnc.reset();
556 headEnc.encodeTilePartHeader(0, t);
557 ho += headEnc.Length;
558 }
559  
560 layers = new EBCOTLayer[num_Layers];
561 for (n = num_Layers - 1; n >= 0; n--)
562 {
563 layers[n] = new EBCOTLayer();
564 }
565  
566 minlsz = 0; // To keep compiler happy
567 for (int t = 0; t < numTiles; t++)
568 {
569 for (int c = 0; c < numComps; c++)
570 {
571 numLvls = src.getAnSubbandTree(t, c).resLvl + 1;
572  
573 if (!src.precinctPartitionUsed(c, t))
574 {
575 // Precinct partition is not used
576 minlsz += MIN_AVG_PACKET_SZ * numLvls;
577 }
578 else
579 {
580 // Precinct partition is used
581 for (int rl = 0; rl < numLvls; rl++)
582 {
583 maxpkt = numPrec[t][c][rl].x * numPrec[t][c][rl].y;
584 minlsz += MIN_AVG_PACKET_SZ * maxpkt;
585 }
586 }
587 } // End loop on components
588 } // End loop on tiles
589  
590 // Initialize layers
591 n = 0;
592 i = 0;
593 lastbytes = 0;
594  
595 while (n < num_Layers - 1)
596 {
597 // At an optimized layer
598 basebytes = System.Math.Floor(lyrSpec.getTargetBitrate(i) * np);
599 if (i < lyrSpec.NOptPoints - 1)
600 {
601 //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'"
602 nextbytes = (int) (lyrSpec.getTargetBitrate(i + 1) * np);
603 // Limit target length to 'totenclength'
604 if (nextbytes > totenclength)
605 nextbytes = totenclength;
606 }
607 else
608 {
609 nextbytes = 1;
610 }
611 loopnlyrs = lyrSpec.getExtraLayers(i) + 1;
612 ls = System.Math.Exp(System.Math.Log((double) nextbytes / basebytes) / loopnlyrs);
613 layers[n].optimize = true;
614 for (l = 0; l < loopnlyrs; l++)
615 {
616 //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'"
617 newbytes = (int) basebytes - lastbytes - ho;
618 if (newbytes < minlsz)
619 {
620 // Skip layer (too small)
621 basebytes *= ls;
622 num_Layers--;
623 continue;
624 }
625 //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'"
626 lastbytes = (int) basebytes - ho;
627 layers[n].maxBytes = lastbytes;
628 basebytes *= ls;
629 n++;
630 }
631 i++; // Goto next optimization point
632 }
633  
634 // Ensure minimum size of last layer (this one determines overall
635 // bitrate)
636 n = num_Layers - 2;
637 //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'"
638 nextbytes = (int) (lyrSpec.TotBitrate * np) - ho;
639 newbytes = nextbytes - ((n >= 0)?layers[n].maxBytes:0);
640 while (newbytes < minlsz)
641 {
642 if (num_Layers == 1)
643 {
644 if (newbytes <= 0)
645 {
646 throw new System.ArgumentException("Overall target bitrate too " + "low, given the current " + "bit stream header overhead");
647 }
648 break;
649 }
650 // Delete last layer
651 num_Layers--;
652 n--;
653 newbytes = nextbytes - ((n >= 0)?layers[n].maxBytes:0);
654 }
655 // Set last layer to the overall target bitrate
656 n++;
657 layers[n].maxBytes = nextbytes;
658 layers[n].optimize = true;
659  
660 // Re-initialize progression order changes if needed Default values
661 Progression[] prog1; // prog2 removed
662 prog1 = (Progression[]) encSpec.pocs.getDefault();
663 int nValidProg = prog1.Length;
664 for (int prg = 0; prg < prog1.Length; prg++)
665 {
666 if (prog1[prg].lye > num_Layers)
667 {
668 prog1[prg].lye = num_Layers;
669 }
670 }
671 if (nValidProg == 0)
672 {
673 throw new System.ApplicationException("Unable to initialize rate allocator: No " + "default progression type has been defined.");
674 }
675  
676 // Tile specific values
677 for (int t = 0; t < numTiles; t++)
678 {
679 if (encSpec.pocs.isTileSpecified(t))
680 {
681 prog1 = (Progression[]) encSpec.pocs.getTileDef(t);
682 nValidProg = prog1.Length;
683 for (int prg = 0; prg < prog1.Length; prg++)
684 {
685 if (prog1[prg].lye > num_Layers)
686 {
687 prog1[prg].lye = num_Layers;
688 }
689 }
690 if (nValidProg == 0)
691 {
692 throw new System.ApplicationException("Unable to initialize rate allocator:" + " No default progression type has been " + "defined for tile " + t);
693 }
694 }
695 } // End loop on tiles
696  
697 #if DO_TIMING
698 initTime += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
699 #endif
700 }
701  
702 /// <summary> This method gets all the coded code-blocks from the EBCOT entropy coder
703 /// for every component and every tile. Each coded code-block is stored in
704 /// a 5D array according to the component, the resolution level, the tile,
705 /// the subband it belongs and its position in the subband.
706 ///
707 /// <P> For each code-block, the valid slopes are computed and converted
708 /// into the mantissa-exponent representation.
709 ///
710 /// </summary>
711 private void getAllCodeBlocks()
712 {
713  
714 int numComps, numTiles; // numBytes removed
715 int c, r, t, s, sidx, k;
716 //int slope;
717 SubbandAn subb;
718 CBlkRateDistStats ccb = null;
719 Coord ncblks = null;
720 int last_sidx;
721 float fslope;
722 #if DO_TIMING
723 long stime = 0L;
724 #endif
725 maxSlope = 0f;
726 minSlope = System.Single.MaxValue;
727  
728 //Get the number of components and tiles
729 numComps = src.NumComps;
730 numTiles = src.getNumTiles();
731  
732 SubbandAn root, sb;
733 int cblkToEncode = 0;
734 int nEncCblk = 0;
735 ProgressWatch pw = FacilityManager.ProgressWatch;
736  
737 //Get all coded code-blocks Goto first tile
738 src.setTile(0, 0);
739 for (t = 0; t < numTiles; t++)
740 {
741 //loop on tiles
742 nEncCblk = 0;
743 cblkToEncode = 0;
744 for (c = 0; c < numComps; c++)
745 {
746 root = src.getAnSubbandTree(t, c);
747 for (r = 0; r <= root.resLvl; r++)
748 {
749 if (r == 0)
750 {
751 sb = (SubbandAn) root.getSubbandByIdx(0, 0);
752 if (sb != null)
753 cblkToEncode += sb.numCb.x * sb.numCb.y;
754 }
755 else
756 {
757 sb = (SubbandAn) root.getSubbandByIdx(r, 1);
758 if (sb != null)
759 cblkToEncode += sb.numCb.x * sb.numCb.y;
760 sb = (SubbandAn) root.getSubbandByIdx(r, 2);
761 if (sb != null)
762 cblkToEncode += sb.numCb.x * sb.numCb.y;
763 sb = (SubbandAn) root.getSubbandByIdx(r, 3);
764 if (sb != null)
765 cblkToEncode += sb.numCb.x * sb.numCb.y;
766 }
767 }
768 }
769 if (pw != null)
770 {
771 pw.initProgressWatch(0, cblkToEncode, "Encoding tile " + t + "...");
772 }
773  
774 for (c = 0; c < numComps; c++)
775 {
776 //loop on components
777  
778 //Get next coded code-block coordinates
779 while ((ccb = src.getNextCodeBlock(c, ccb)) != null)
780 {
781 #if DO_TIMING
782 stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
783 #endif
784  
785 if (pw != null)
786 {
787 nEncCblk++;
788 pw.updateProgressWatch(nEncCblk, null);
789 }
790  
791 subb = ccb.sb;
792  
793 //Get the coded code-block resolution level index
794 r = subb.resLvl;
795  
796 //Get the coded code-block subband index
797 s = subb.sbandIdx;
798  
799 //Get the number of blocks in the current subband
800 ncblks = subb.numCb;
801  
802 // Add code-block contribution to summary R-D table
803 // RDSlopesRates
804 last_sidx = - 1;
805 for (k = ccb.nVldTrunc - 1; k >= 0; k--)
806 {
807 fslope = ccb.truncSlopes[k];
808 if (fslope > maxSlope)
809 maxSlope = fslope;
810 if (fslope < minSlope)
811 minSlope = fslope;
812 sidx = getLimitedSIndexFromSlope(fslope);
813 for (; sidx > last_sidx; sidx--)
814 {
815 RDSlopesRates[sidx] += ccb.truncRates[ccb.truncIdxs[k]];
816 }
817 last_sidx = getLimitedSIndexFromSlope(fslope);
818 }
819  
820 //Fills code-blocks array
821 cblks[t][c][r][s][(ccb.m * ncblks.x) + ccb.n] = ccb;
822 ccb = null;
823  
824 #if DO_TIMING
825 initTime += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
826 #endif
827 }
828 }
829  
830 if (pw != null)
831 {
832 pw.terminateProgressWatch();
833 }
834  
835 //Goto next tile
836 if (t < numTiles - 1)
837 //not at last tile
838 src.nextTile();
839 }
840 }
841  
842 /// <summary> This method builds all the bit stream layers and then writes them to
843 /// the output bit stream. Firstly it builds all the layers by computing
844 /// the threshold according to the layer target bit-rate, and then it
845 /// writes the layer bit streams according to the progressive type.
846 ///
847 /// </summary>
848 private void buildAndWriteLayers()
849 {
850 int nPrec = 0;
851 int maxBytes, actualBytes;
852 float rdThreshold;
853 SubbandAn sb;
854 //float threshold;
855 BitOutputBuffer hBuff = null;
856 byte[] bBuff = null;
857 int[] tileLengths; // Length of each tile
858 int tmp;
859 bool sopUsed; // Should SOP markers be used ?
860 bool ephUsed; // Should EPH markers be used ?
861 int nc = src.NumComps;
862 int nt = src.getNumTiles();
863 int mrl;
864 #if DO_TIMING
865 long stime = 0L;
866 stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
867 #endif
868  
869 // Start with the maximum slope
870 rdThreshold = maxSlope;
871  
872 tileLengths = new int[nt];
873 actualBytes = 0;
874  
875 // +------------------------------+
876 // | First we build the layers |
877 // +------------------------------+
878 // Bitstream is simulated to know tile length
879 for (int l = 0; l < num_Layers; l++)
880 {
881 //loop on layers
882  
883 maxBytes = layers[l].maxBytes;
884 if (layers[l].optimize)
885 {
886 rdThreshold = optimizeBitstreamLayer(l, rdThreshold, maxBytes, actualBytes);
887 }
888 else
889 {
890 if (l <= 0 || l >= num_Layers - 1)
891 {
892 throw new System.ArgumentException("The first and the" + " last layer " + "thresholds" + " must be optimized");
893 }
894 rdThreshold = estimateLayerThreshold(maxBytes, layers[l - 1]);
895 }
896  
897 for (int t = 0; t < nt; t++)
898 {
899 //loop on tiles
900 if (l == 0)
901 {
902 // Tile header
903 headEnc.reset();
904 headEnc.encodeTilePartHeader(0, t);
905 tileLengths[t] += headEnc.Length;
906 }
907  
908 for (int c = 0; c < nc; c++)
909 {
910 //loop on components
911  
912 // set boolean sopUsed here (SOP markers)
913 sopUsed = ((System.String) encSpec.sops.getTileDef(t)).ToUpper().Equals("on".ToUpper());
914 // set boolean ephUsed here (EPH markers)
915 ephUsed = ((System.String) encSpec.ephs.getTileDef(t)).ToUpper().Equals("on".ToUpper());
916  
917 // Go to LL band
918 sb = src.getAnSubbandTree(t, c);
919 mrl = sb.resLvl + 1;
920  
921 while (sb.subb_LL != null)
922 {
923 sb = sb.subb_LL;
924 }
925  
926 for (int r = 0; r < mrl; r++)
927 {
928 // loop on resolution levels
929  
930 nPrec = numPrec[t][c][r].x * numPrec[t][c][r].y;
931 for (int p = 0; p < nPrec; p++)
932 {
933 // loop on precincts
934  
935 findTruncIndices(l, c, r, t, sb, rdThreshold, p);
936  
937 hBuff = pktEnc.encodePacket(l + 1, c, r, t, cblks[t][c][r], truncIdxs[t][l][c][r], hBuff, bBuff, p);
938 if (pktEnc.PacketWritable)
939 {
940 tmp = bsWriter.writePacketHead(hBuff.Buffer, hBuff.Length, true, sopUsed, ephUsed);
941 tmp += bsWriter.writePacketBody(pktEnc.LastBodyBuf, pktEnc.LastBodyLen, true, pktEnc.ROIinPkt, pktEnc.ROILen);
942 actualBytes += tmp;
943 tileLengths[t] += tmp;
944 }
945 } // End loop on precincts
946 sb = sb.parentband;
947 } // End loop on resolution levels
948 } // End loop on components
949 } // end loop on tiles
950 layers[l].rdThreshold = rdThreshold;
951 layers[l].actualBytes = actualBytes;
952 } // end loop on layers
953  
954 #if DO_TIMING
955 buildTime += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
956 stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
957 #endif
958 // +--------------------------------------------------+
959 // | Write tiles according to their Progression order |
960 // +--------------------------------------------------+
961 // Reset the packet encoder before writing all packets
962 pktEnc.reset();
963 Progression[] prog; // Progression(s) in each tile
964 int cs, ce, rs, re, lye;
965  
966 int[] mrlc = new int[nc];
967 for (int t = 0; t < nt; t++)
968 {
969 //loop on tiles
970 //int[][] lysA; // layer index start for each component and
971 // resolution level
972 int[][] lys = new int[nc][];
973 for (int c = 0; c < nc; c++)
974 {
975 mrlc[c] = src.getAnSubbandTree(t, c).resLvl;
976 lys[c] = new int[mrlc[c] + 1];
977 }
978  
979 // Tile header
980 headEnc.reset();
981 headEnc.encodeTilePartHeader(tileLengths[t], t);
982 bsWriter.commitBitstreamHeader(headEnc);
983 prog = (Progression[]) encSpec.pocs.getTileDef(t);
984  
985 for (int prg = 0; prg < prog.Length; prg++)
986 {
987 // Loop on progression
988 lye = prog[prg].lye;
989 cs = prog[prg].cs;
990 ce = prog[prg].ce;
991 rs = prog[prg].rs;
992 re = prog[prg].re;
993  
994 switch (prog[prg].type)
995 {
996  
997 case CSJ2K.j2k.codestream.ProgressionType.RES_LY_COMP_POS_PROG:
998 writeResLyCompPos(t, rs, re, cs, ce, lys, lye);
999 break;
1000  
1001 case CSJ2K.j2k.codestream.ProgressionType.LY_RES_COMP_POS_PROG:
1002 writeLyResCompPos(t, rs, re, cs, ce, lys, lye);
1003 break;
1004  
1005 case CSJ2K.j2k.codestream.ProgressionType.POS_COMP_RES_LY_PROG:
1006 writePosCompResLy(t, rs, re, cs, ce, lys, lye);
1007 break;
1008  
1009 case CSJ2K.j2k.codestream.ProgressionType.COMP_POS_RES_LY_PROG:
1010 writeCompPosResLy(t, rs, re, cs, ce, lys, lye);
1011 break;
1012  
1013 case CSJ2K.j2k.codestream.ProgressionType.RES_POS_COMP_LY_PROG:
1014 writeResPosCompLy(t, rs, re, cs, ce, lys, lye);
1015 break;
1016  
1017 default:
1018 throw new System.ApplicationException("Unsupported bit stream progression type");
1019  
1020 } // switch on progression
1021  
1022 // Update next first layer index
1023 for (int c = cs; c < ce; c++)
1024 for (int r = rs; r < re; r++)
1025 {
1026 if (r > mrlc[c])
1027 continue;
1028 lys[c][r] = lye;
1029 }
1030 } // End loop on progression
1031 } // End loop on tiles
1032  
1033 #if DO_TIMING
1034 writeTime += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
1035 #endif
1036 }
1037  
1038 /// <summary> Write a piece of bit stream according to the
1039 /// RES_LY_COMP_POS_PROG progression mode and between given bounds
1040 ///
1041 /// </summary>
1042 /// <param name="t">Tile index.
1043 ///
1044 /// </param>
1045 /// <param name="rs">First resolution level index.
1046 ///
1047 /// </param>
1048 /// <param name="re">Last resolution level index.
1049 ///
1050 /// </param>
1051 /// <param name="cs">First component index.
1052 ///
1053 /// </param>
1054 /// <param name="ce">Last component index.
1055 ///
1056 /// </param>
1057 /// <param name="lys">First layer index for each component and resolution.
1058 ///
1059 /// </param>
1060 /// <param name="lye">Index of the last layer.
1061 ///
1062 /// </param>
1063 public virtual void writeResLyCompPos(int t, int rs, int re, int cs, int ce, int[][] lys, int lye)
1064 {
1065  
1066 bool sopUsed; // Should SOP markers be used ?
1067 bool ephUsed; // Should EPH markers be used ?
1068 int nc = src.NumComps;
1069 int[] mrl = new int[nc];
1070 SubbandAn sb;
1071 float threshold;
1072 BitOutputBuffer hBuff = null;
1073 byte[] bBuff = null;
1074 int nPrec = 0;
1075  
1076 // Max number of resolution levels in the tile
1077 int maxResLvl = 0;
1078 for (int c = 0; c < nc; c++)
1079 {
1080 mrl[c] = src.getAnSubbandTree(t, c).resLvl;
1081 if (mrl[c] > maxResLvl)
1082 maxResLvl = mrl[c];
1083 }
1084  
1085 int minlys; // minimum layer start index of each component
1086  
1087 for (int r = rs; r < re; r++)
1088 {
1089 //loop on resolution levels
1090 if (r > maxResLvl)
1091 continue;
1092  
1093 minlys = 100000;
1094 for (int c = cs; c < ce; c++)
1095 {
1096 if (r < lys[c].Length && lys[c][r] < minlys)
1097 {
1098 minlys = lys[c][r];
1099 }
1100 }
1101  
1102 for (int l = minlys; l < lye; l++)
1103 {
1104 //loop on layers
1105 for (int c = cs; c < ce; c++)
1106 {
1107 //loop on components
1108 if (r >= lys[c].Length)
1109 continue;
1110 if (l < lys[c][r])
1111 continue;
1112  
1113 // If no more decomposition levels for this component
1114 if (r > mrl[c])
1115 continue;
1116  
1117 nPrec = numPrec[t][c][r].x * numPrec[t][c][r].y;
1118 for (int p = 0; p < nPrec; p++)
1119 {
1120 // loop on precincts
1121  
1122 // set boolean sopUsed here (SOP markers)
1123 sopUsed = ((System.String) encSpec.sops.getTileDef(t)).Equals("on");
1124 // set boolean ephUsed here (EPH markers)
1125 ephUsed = ((System.String) encSpec.ephs.getTileDef(t)).Equals("on");
1126  
1127 sb = src.getAnSubbandTree(t, c);
1128 for (int i = mrl[c]; i > r; i--)
1129 {
1130 sb = sb.subb_LL;
1131 }
1132  
1133 threshold = layers[l].rdThreshold;
1134 findTruncIndices(l, c, r, t, sb, threshold, p);
1135  
1136 hBuff = pktEnc.encodePacket(l + 1, c, r, t, cblks[t][c][r], truncIdxs[t][l][c][r], hBuff, bBuff, p);
1137  
1138 if (pktEnc.PacketWritable)
1139 {
1140 bsWriter.writePacketHead(hBuff.Buffer, hBuff.Length, false, sopUsed, ephUsed);
1141 bsWriter.writePacketBody(pktEnc.LastBodyBuf, pktEnc.LastBodyLen, false, pktEnc.ROIinPkt, pktEnc.ROILen);
1142 }
1143 } // End loop on precincts
1144 } // End loop on components
1145 } // End loop on layers
1146 } // End loop on resolution levels
1147 }
1148  
1149 /// <summary> Write a piece of bit stream according to the
1150 /// LY_RES_COMP_POS_PROG progression mode and between given bounds
1151 ///
1152 /// </summary>
1153 /// <param name="t">Tile index.
1154 ///
1155 /// </param>
1156 /// <param name="rs">First resolution level index.
1157 ///
1158 /// </param>
1159 /// <param name="re">Last resolution level index.
1160 ///
1161 /// </param>
1162 /// <param name="cs">First component index.
1163 ///
1164 /// </param>
1165 /// <param name="ce">Last component index.
1166 ///
1167 /// </param>
1168 /// <param name="lys">First layer index for each component and resolution.
1169 ///
1170 /// </param>
1171 /// <param name="lye">Index of the last layer.
1172 ///
1173 /// </param>
1174 public virtual void writeLyResCompPos(int t, int rs, int re, int cs, int ce, int[][] lys, int lye)
1175 {
1176  
1177 bool sopUsed; // Should SOP markers be used ?
1178 bool ephUsed; // Should EPH markers be used ?
1179 int nc = src.NumComps;
1180 int mrl;
1181 SubbandAn sb;
1182 float threshold;
1183 BitOutputBuffer hBuff = null;
1184 byte[] bBuff = null;
1185 int nPrec = 0;
1186  
1187 int minlys = 100000; // minimum layer start index of each component
1188 for (int c = cs; c < ce; c++)
1189 {
1190 for (int r = 0; r < lys.Length; r++)
1191 {
1192 if (lys[c] != null && r < lys[c].Length && lys[c][r] < minlys)
1193 {
1194 minlys = lys[c][r];
1195 }
1196 }
1197 }
1198  
1199 for (int l = minlys; l < lye; l++)
1200 {
1201 // loop on layers
1202 for (int r = rs; r < re; r++)
1203 {
1204 // loop on resolution level
1205 for (int c = cs; c < ce; c++)
1206 {
1207 // loop on components
1208 mrl = src.getAnSubbandTree(t, c).resLvl;
1209 if (r > mrl)
1210 continue;
1211 if (r >= lys[c].Length)
1212 continue;
1213 if (l < lys[c][r])
1214 continue;
1215  
1216 nPrec = numPrec[t][c][r].x * numPrec[t][c][r].y;
1217 for (int p = 0; p < nPrec; p++)
1218 {
1219 // loop on precincts
1220  
1221 // set boolean sopUsed here (SOP markers)
1222 sopUsed = ((System.String) encSpec.sops.getTileDef(t)).Equals("on");
1223 // set boolean ephUsed here (EPH markers)
1224 ephUsed = ((System.String) encSpec.ephs.getTileDef(t)).Equals("on");
1225  
1226 sb = src.getAnSubbandTree(t, c);
1227 for (int i = mrl; i > r; i--)
1228 {
1229 sb = sb.subb_LL;
1230 }
1231  
1232 threshold = layers[l].rdThreshold;
1233 findTruncIndices(l, c, r, t, sb, threshold, p);
1234  
1235 hBuff = pktEnc.encodePacket(l + 1, c, r, t, cblks[t][c][r], truncIdxs[t][l][c][r], hBuff, bBuff, p);
1236  
1237 if (pktEnc.PacketWritable)
1238 {
1239 bsWriter.writePacketHead(hBuff.Buffer, hBuff.Length, false, sopUsed, ephUsed);
1240 bsWriter.writePacketBody(pktEnc.LastBodyBuf, pktEnc.LastBodyLen, false, pktEnc.ROIinPkt, pktEnc.ROILen);
1241 }
1242 } // end loop on precincts
1243 } // end loop on components
1244 } // end loop on resolution levels
1245 } // end loop on layers
1246 }
1247  
1248 /// <summary> Write a piece of bit stream according to the
1249 /// COMP_POS_RES_LY_PROG progression mode and between given bounds
1250 ///
1251 /// </summary>
1252 /// <param name="t">Tile index.
1253 ///
1254 /// </param>
1255 /// <param name="rs">First resolution level index.
1256 ///
1257 /// </param>
1258 /// <param name="re">Last resolution level index.
1259 ///
1260 /// </param>
1261 /// <param name="cs">First component index.
1262 ///
1263 /// </param>
1264 /// <param name="ce">Last component index.
1265 ///
1266 /// </param>
1267 /// <param name="lys">First layer index for each component and resolution.
1268 ///
1269 /// </param>
1270 /// <param name="lye">Index of the last layer.
1271 ///
1272 /// </param>
1273 public virtual void writePosCompResLy(int t, int rs, int re, int cs, int ce, int[][] lys, int lye)
1274 {
1275  
1276 bool sopUsed; // Should SOP markers be used ?
1277 bool ephUsed; // Should EPH markers be used ?
1278 int nc = src.NumComps;
1279 int mrl;
1280 SubbandAn sb;
1281 float threshold;
1282 BitOutputBuffer hBuff = null;
1283 byte[] bBuff = null;
1284  
1285 // Computes current tile offset in the reference grid
1286 Coord nTiles = src.getNumTiles(null);
1287 Coord tileI = src.getTile(null);
1288 int x0siz = src.ImgULX;
1289 int y0siz = src.ImgULY;
1290 int xsiz = x0siz + src.ImgWidth;
1291 int ysiz = y0siz + src.ImgHeight;
1292 int xt0siz = src.TilePartULX;
1293 int yt0siz = src.TilePartULY;
1294 int xtsiz = src.NomTileWidth;
1295 int ytsiz = src.NomTileHeight;
1296 int tx0 = (tileI.x == 0)?x0siz:xt0siz + tileI.x * xtsiz;
1297 int ty0 = (tileI.y == 0)?y0siz:yt0siz + tileI.y * ytsiz;
1298 int tx1 = (tileI.x != nTiles.x - 1)?xt0siz + (tileI.x + 1) * xtsiz:xsiz;
1299 int ty1 = (tileI.y != nTiles.y - 1)?yt0siz + (tileI.y + 1) * ytsiz:ysiz;
1300  
1301 // Get precinct information (number,distance between two consecutive
1302 // precincts in the reference grid) in each component and resolution
1303 // level
1304 PrecInfo prec; // temporary variable
1305 int p; // Current precinct index
1306 int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid
1307 int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid
1308 int nPrec = 0; // Total number of found precincts
1309 int[][] nextPrec = new int[ce][]; // Next precinct index in each
1310 // component and resolution level
1311 int minlys = 100000; // minimum layer start index of each component
1312 int minx = tx1; // Horiz. offset of the second precinct in the
1313 // reference grid
1314 int miny = ty1; // Vert. offset of the second precinct in the
1315 // reference grid.
1316 int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid
1317 int maxy = ty0; // Max. vert. offset of precincts in the ref. grid
1318 for (int c = cs; c < ce; c++)
1319 {
1320 mrl = src.getAnSubbandTree(t, c).resLvl;
1321 nextPrec[c] = new int[mrl + 1];
1322 for (int r = rs; r < re; r++)
1323 {
1324 if (r > mrl)
1325 continue;
1326 if (r < lys[c].Length && lys[c][r] < minlys)
1327 {
1328 minlys = lys[c][r];
1329 }
1330 p = numPrec[t][c][r].y * numPrec[t][c][r].x - 1;
1331 for (; p >= 0; p--)
1332 {
1333 prec = pktEnc.getPrecInfo(t, c, r, p);
1334 if (prec.rgulx != tx0)
1335 {
1336 if (prec.rgulx < minx)
1337 minx = prec.rgulx;
1338 if (prec.rgulx > maxx)
1339 maxx = prec.rgulx;
1340 }
1341 if (prec.rguly != ty0)
1342 {
1343 if (prec.rguly < miny)
1344 miny = prec.rguly;
1345 if (prec.rguly > maxy)
1346 maxy = prec.rguly;
1347 }
1348  
1349 if (nPrec == 0)
1350 {
1351 gcd_x = prec.rgw;
1352 gcd_y = prec.rgh;
1353 }
1354 else
1355 {
1356 gcd_x = MathUtil.gcd(gcd_x, prec.rgw);
1357 gcd_y = MathUtil.gcd(gcd_y, prec.rgh);
1358 }
1359 nPrec++;
1360 } // precincts
1361 } // resolution levels
1362 } // components
1363  
1364 if (nPrec == 0)
1365 {
1366 throw new System.ApplicationException("Image cannot have no precinct");
1367 }
1368  
1369 int pyend = (maxy - miny) / gcd_y + 1;
1370 int pxend = (maxx - minx) / gcd_x + 1;
1371 int y = ty0;
1372 int x = tx0;
1373 for (int py = 0; py <= pyend; py++)
1374 {
1375 // Vertical precincts
1376 for (int px = 0; px <= pxend; px++)
1377 {
1378 // Horiz. precincts
1379 for (int c = cs; c < ce; c++)
1380 {
1381 // Components
1382 mrl = src.getAnSubbandTree(t, c).resLvl;
1383 for (int r = rs; r < re; r++)
1384 {
1385 // Resolution levels
1386 if (r > mrl)
1387 continue;
1388 if (nextPrec[c][r] >= numPrec[t][c][r].x * numPrec[t][c][r].y)
1389 {
1390 continue;
1391 }
1392 prec = pktEnc.getPrecInfo(t, c, r, nextPrec[c][r]);
1393 if ((prec.rgulx != x) || (prec.rguly != y))
1394 {
1395 continue;
1396 }
1397 for (int l = minlys; l < lye; l++)
1398 {
1399 // Layers
1400 if (r >= lys[c].Length)
1401 continue;
1402 if (l < lys[c][r])
1403 continue;
1404  
1405 // set boolean sopUsed here (SOP markers)
1406 sopUsed = ((System.String) encSpec.sops.getTileDef(t)).Equals("on");
1407 // set boolean ephUsed here (EPH markers)
1408 ephUsed = ((System.String) encSpec.ephs.getTileDef(t)).Equals("on");
1409  
1410 sb = src.getAnSubbandTree(t, c);
1411 for (int i = mrl; i > r; i--)
1412 {
1413 sb = sb.subb_LL;
1414 }
1415  
1416 threshold = layers[l].rdThreshold;
1417 findTruncIndices(l, c, r, t, sb, threshold, nextPrec[c][r]);
1418  
1419 hBuff = pktEnc.encodePacket(l + 1, c, r, t, cblks[t][c][r], truncIdxs[t][l][c][r], hBuff, bBuff, nextPrec[c][r]);
1420  
1421 if (pktEnc.PacketWritable)
1422 {
1423 bsWriter.writePacketHead(hBuff.Buffer, hBuff.Length, false, sopUsed, ephUsed);
1424 bsWriter.writePacketBody(pktEnc.LastBodyBuf, pktEnc.LastBodyLen, false, pktEnc.ROIinPkt, pktEnc.ROILen);
1425 }
1426 } // layers
1427 nextPrec[c][r]++;
1428 } // Resolution levels
1429 } // Components
1430 if (px != pxend)
1431 {
1432 x = minx + px * gcd_x;
1433 }
1434 else
1435 {
1436 x = tx0;
1437 }
1438 } // Horizontal precincts
1439 if (py != pyend)
1440 {
1441 y = miny + py * gcd_y;
1442 }
1443 else
1444 {
1445 y = ty0;
1446 }
1447 } // Vertical precincts
1448  
1449 // Check that all precincts have been written
1450 for (int c = cs; c < ce; c++)
1451 {
1452 mrl = src.getAnSubbandTree(t, c).resLvl;
1453 for (int r = rs; r < re; r++)
1454 {
1455 if (r > mrl)
1456 continue;
1457 if (nextPrec[c][r] < numPrec[t][c][r].x * numPrec[t][c][r].y - 1)
1458 {
1459 throw new System.ApplicationException("JJ2000 bug: One precinct at least has " + "not been written for resolution level " + r + " of component " + c + " in tile " + t + ".");
1460 }
1461 }
1462 }
1463 }
1464  
1465 /// <summary> Write a piece of bit stream according to the
1466 /// COMP_POS_RES_LY_PROG progression mode and between given bounds
1467 ///
1468 /// </summary>
1469 /// <param name="t">Tile index.
1470 ///
1471 /// </param>
1472 /// <param name="rs">First resolution level index.
1473 ///
1474 /// </param>
1475 /// <param name="re">Last resolution level index.
1476 ///
1477 /// </param>
1478 /// <param name="cs">First component index.
1479 ///
1480 /// </param>
1481 /// <param name="ce">Last component index.
1482 ///
1483 /// </param>
1484 /// <param name="lys">First layer index for each component and resolution.
1485 ///
1486 /// </param>
1487 /// <param name="lye">Index of the last layer.
1488 ///
1489 /// </param>
1490 public virtual void writeCompPosResLy(int t, int rs, int re, int cs, int ce, int[][] lys, int lye)
1491 {
1492  
1493 bool sopUsed; // Should SOP markers be used ?
1494 bool ephUsed; // Should EPH markers be used ?
1495 int nc = src.NumComps;
1496 int mrl;
1497 SubbandAn sb;
1498 float threshold;
1499 BitOutputBuffer hBuff = null;
1500 byte[] bBuff = null;
1501  
1502 // Computes current tile offset in the reference grid
1503 Coord nTiles = src.getNumTiles(null);
1504 Coord tileI = src.getTile(null);
1505 int x0siz = src.ImgULX;
1506 int y0siz = src.ImgULY;
1507 int xsiz = x0siz + src.ImgWidth;
1508 int ysiz = y0siz + src.ImgHeight;
1509 int xt0siz = src.TilePartULX;
1510 int yt0siz = src.TilePartULY;
1511 int xtsiz = src.NomTileWidth;
1512 int ytsiz = src.NomTileHeight;
1513 int tx0 = (tileI.x == 0)?x0siz:xt0siz + tileI.x * xtsiz;
1514 int ty0 = (tileI.y == 0)?y0siz:yt0siz + tileI.y * ytsiz;
1515 int tx1 = (tileI.x != nTiles.x - 1)?xt0siz + (tileI.x + 1) * xtsiz:xsiz;
1516 int ty1 = (tileI.y != nTiles.y - 1)?yt0siz + (tileI.y + 1) * ytsiz:ysiz;
1517  
1518 // Get precinct information (number,distance between two consecutive
1519 // precincts in the reference grid) in each component and resolution
1520 // level
1521 PrecInfo prec; // temporary variable
1522 int p; // Current precinct index
1523 int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid
1524 int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid
1525 int nPrec = 0; // Total number of found precincts
1526 int[][] nextPrec = new int[ce][]; // Next precinct index in each
1527 // component and resolution level
1528 int minlys = 100000; // minimum layer start index of each component
1529 int minx = tx1; // Horiz. offset of the second precinct in the
1530 // reference grid
1531 int miny = ty1; // Vert. offset of the second precinct in the
1532 // reference grid.
1533 int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid
1534 int maxy = ty0; // Max. vert. offset of precincts in the ref. grid
1535 for (int c = cs; c < ce; c++)
1536 {
1537 mrl = src.getAnSubbandTree(t, c).resLvl;
1538 for (int r = rs; r < re; r++)
1539 {
1540 if (r > mrl)
1541 continue;
1542 nextPrec[c] = new int[mrl + 1];
1543 if (r < lys[c].Length && lys[c][r] < minlys)
1544 {
1545 minlys = lys[c][r];
1546 }
1547 p = numPrec[t][c][r].y * numPrec[t][c][r].x - 1;
1548 for (; p >= 0; p--)
1549 {
1550 prec = pktEnc.getPrecInfo(t, c, r, p);
1551 if (prec.rgulx != tx0)
1552 {
1553 if (prec.rgulx < minx)
1554 minx = prec.rgulx;
1555 if (prec.rgulx > maxx)
1556 maxx = prec.rgulx;
1557 }
1558 if (prec.rguly != ty0)
1559 {
1560 if (prec.rguly < miny)
1561 miny = prec.rguly;
1562 if (prec.rguly > maxy)
1563 maxy = prec.rguly;
1564 }
1565  
1566 if (nPrec == 0)
1567 {
1568 gcd_x = prec.rgw;
1569 gcd_y = prec.rgh;
1570 }
1571 else
1572 {
1573 gcd_x = MathUtil.gcd(gcd_x, prec.rgw);
1574 gcd_y = MathUtil.gcd(gcd_y, prec.rgh);
1575 }
1576 nPrec++;
1577 } // precincts
1578 } // resolution levels
1579 } // components
1580  
1581 if (nPrec == 0)
1582 {
1583 throw new System.ApplicationException("Image cannot have no precinct");
1584 }
1585  
1586 int pyend = (maxy - miny) / gcd_y + 1;
1587 int pxend = (maxx - minx) / gcd_x + 1;
1588 int y;
1589 int x;
1590 for (int c = cs; c < ce; c++)
1591 {
1592 // Loop on components
1593 y = ty0;
1594 x = tx0;
1595 mrl = src.getAnSubbandTree(t, c).resLvl;
1596 for (int py = 0; py <= pyend; py++)
1597 {
1598 // Vertical precincts
1599 for (int px = 0; px <= pxend; px++)
1600 {
1601 // Horiz. precincts
1602 for (int r = rs; r < re; r++)
1603 {
1604 // Resolution levels
1605 if (r > mrl)
1606 continue;
1607 if (nextPrec[c][r] >= numPrec[t][c][r].x * numPrec[t][c][r].y)
1608 {
1609 continue;
1610 }
1611 prec = pktEnc.getPrecInfo(t, c, r, nextPrec[c][r]);
1612 if ((prec.rgulx != x) || (prec.rguly != y))
1613 {
1614 continue;
1615 }
1616  
1617 for (int l = minlys; l < lye; l++)
1618 {
1619 // Layers
1620 if (r >= lys[c].Length)
1621 continue;
1622 if (l < lys[c][r])
1623 continue;
1624  
1625 // set boolean sopUsed here (SOP markers)
1626 sopUsed = ((System.String) encSpec.sops.getTileDef(t)).Equals("on");
1627 // set boolean ephUsed here (EPH markers)
1628 ephUsed = ((System.String) encSpec.ephs.getTileDef(t)).Equals("on");
1629  
1630 sb = src.getAnSubbandTree(t, c);
1631 for (int i = mrl; i > r; i--)
1632 {
1633 sb = sb.subb_LL;
1634 }
1635  
1636 threshold = layers[l].rdThreshold;
1637 findTruncIndices(l, c, r, t, sb, threshold, nextPrec[c][r]);
1638  
1639 hBuff = pktEnc.encodePacket(l + 1, c, r, t, cblks[t][c][r], truncIdxs[t][l][c][r], hBuff, bBuff, nextPrec[c][r]);
1640  
1641 if (pktEnc.PacketWritable)
1642 {
1643 bsWriter.writePacketHead(hBuff.Buffer, hBuff.Length, false, sopUsed, ephUsed);
1644 bsWriter.writePacketBody(pktEnc.LastBodyBuf, pktEnc.LastBodyLen, false, pktEnc.ROIinPkt, pktEnc.ROILen);
1645 }
1646 } // Layers
1647 nextPrec[c][r]++;
1648 } // Resolution levels
1649 if (px != pxend)
1650 {
1651 x = minx + px * gcd_x;
1652 }
1653 else
1654 {
1655 x = tx0;
1656 }
1657 } // Horizontal precincts
1658 if (py != pyend)
1659 {
1660 y = miny + py * gcd_y;
1661 }
1662 else
1663 {
1664 y = ty0;
1665 }
1666 } // Vertical precincts
1667 } // components
1668  
1669 // Check that all precincts have been written
1670 for (int c = cs; c < ce; c++)
1671 {
1672 mrl = src.getAnSubbandTree(t, c).resLvl;
1673 for (int r = rs; r < re; r++)
1674 {
1675 if (r > mrl)
1676 continue;
1677 if (nextPrec[c][r] < numPrec[t][c][r].x * numPrec[t][c][r].y - 1)
1678 {
1679 throw new System.ApplicationException("JJ2000 bug: One precinct at least has " + "not been written for resolution level " + r + " of component " + c + " in tile " + t + ".");
1680 }
1681 }
1682 }
1683 }
1684  
1685 /// <summary> Write a piece of bit stream according to the
1686 /// RES_POS_COMP_LY_PROG progression mode and between given bounds
1687 ///
1688 /// </summary>
1689 /// <param name="t">Tile index.
1690 ///
1691 /// </param>
1692 /// <param name="rs">First resolution level index.
1693 ///
1694 /// </param>
1695 /// <param name="re">Last resolution level index.
1696 ///
1697 /// </param>
1698 /// <param name="cs">First component index.
1699 ///
1700 /// </param>
1701 /// <param name="ce">Last component index.
1702 ///
1703 /// </param>
1704 /// <param name="lys">First layer index for each component and resolution.
1705 ///
1706 /// </param>
1707 /// <param name="lye">Last layer index.
1708 ///
1709 /// </param>
1710 public virtual void writeResPosCompLy(int t, int rs, int re, int cs, int ce, int[][] lys, int lye)
1711 {
1712  
1713 bool sopUsed; // Should SOP markers be used ?
1714 bool ephUsed; // Should EPH markers be used ?
1715 int nc = src.NumComps;
1716 int mrl;
1717 SubbandAn sb;
1718 float threshold;
1719 BitOutputBuffer hBuff = null;
1720 byte[] bBuff = null;
1721  
1722 // Computes current tile offset in the reference grid
1723 Coord nTiles = src.getNumTiles(null);
1724 Coord tileI = src.getTile(null);
1725 int x0siz = src.ImgULX;
1726 int y0siz = src.ImgULY;
1727 int xsiz = x0siz + src.ImgWidth;
1728 int ysiz = y0siz + src.ImgHeight;
1729 int xt0siz = src.TilePartULX;
1730 int yt0siz = src.TilePartULY;
1731 int xtsiz = src.NomTileWidth;
1732 int ytsiz = src.NomTileHeight;
1733 int tx0 = (tileI.x == 0)?x0siz:xt0siz + tileI.x * xtsiz;
1734 int ty0 = (tileI.y == 0)?y0siz:yt0siz + tileI.y * ytsiz;
1735 int tx1 = (tileI.x != nTiles.x - 1)?xt0siz + (tileI.x + 1) * xtsiz:xsiz;
1736 int ty1 = (tileI.y != nTiles.y - 1)?yt0siz + (tileI.y + 1) * ytsiz:ysiz;
1737  
1738 // Get precinct information (number,distance between two consecutive
1739 // precincts in the reference grid) in each component and resolution
1740 // level
1741 PrecInfo prec; // temporary variable
1742 int p; // Current precinct index
1743 int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid
1744 int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid
1745 int nPrec = 0; // Total number of found precincts
1746 int[][] nextPrec = new int[ce][]; // Next precinct index in each
1747 // component and resolution level
1748 int minlys = 100000; // minimum layer start index of each component
1749 int minx = tx1; // Horiz. offset of the second precinct in the
1750 // reference grid
1751 int miny = ty1; // Vert. offset of the second precinct in the
1752 // reference grid.
1753 int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid
1754 int maxy = ty0; // Max. vert. offset of precincts in the ref. grid
1755 for (int c = cs; c < ce; c++)
1756 {
1757 mrl = src.getAnSubbandTree(t, c).resLvl;
1758 nextPrec[c] = new int[mrl + 1];
1759 for (int r = rs; r < re; r++)
1760 {
1761 if (r > mrl)
1762 continue;
1763 if (r < lys[c].Length && lys[c][r] < minlys)
1764 {
1765 minlys = lys[c][r];
1766 }
1767 p = numPrec[t][c][r].y * numPrec[t][c][r].x - 1;
1768 for (; p >= 0; p--)
1769 {
1770 prec = pktEnc.getPrecInfo(t, c, r, p);
1771 if (prec.rgulx != tx0)
1772 {
1773 if (prec.rgulx < minx)
1774 minx = prec.rgulx;
1775 if (prec.rgulx > maxx)
1776 maxx = prec.rgulx;
1777 }
1778 if (prec.rguly != ty0)
1779 {
1780 if (prec.rguly < miny)
1781 miny = prec.rguly;
1782 if (prec.rguly > maxy)
1783 maxy = prec.rguly;
1784 }
1785  
1786 if (nPrec == 0)
1787 {
1788 gcd_x = prec.rgw;
1789 gcd_y = prec.rgh;
1790 }
1791 else
1792 {
1793 gcd_x = MathUtil.gcd(gcd_x, prec.rgw);
1794 gcd_y = MathUtil.gcd(gcd_y, prec.rgh);
1795 }
1796 nPrec++;
1797 } // precincts
1798 } // resolution levels
1799 } // components
1800  
1801 if (nPrec == 0)
1802 {
1803 throw new System.ApplicationException("Image cannot have no precinct");
1804 }
1805  
1806 int pyend = (maxy - miny) / gcd_y + 1;
1807 int pxend = (maxx - minx) / gcd_x + 1;
1808 int x, y;
1809 for (int r = rs; r < re; r++)
1810 {
1811 // Resolution levels
1812 y = ty0;
1813 x = tx0;
1814 for (int py = 0; py <= pyend; py++)
1815 {
1816 // Vertical precincts
1817 for (int px = 0; px <= pxend; px++)
1818 {
1819 // Horiz. precincts
1820 for (int c = cs; c < ce; c++)
1821 {
1822 // Components
1823 mrl = src.getAnSubbandTree(t, c).resLvl;
1824 if (r > mrl)
1825 continue;
1826 if (nextPrec[c][r] >= numPrec[t][c][r].x * numPrec[t][c][r].y)
1827 {
1828 continue;
1829 }
1830 prec = pktEnc.getPrecInfo(t, c, r, nextPrec[c][r]);
1831 if ((prec.rgulx != x) || (prec.rguly != y))
1832 {
1833 continue;
1834 }
1835 for (int l = minlys; l < lye; l++)
1836 {
1837 if (r >= lys[c].Length)
1838 continue;
1839 if (l < lys[c][r])
1840 continue;
1841  
1842 // set boolean sopUsed here (SOP markers)
1843 sopUsed = ((System.String) encSpec.sops.getTileDef(t)).Equals("on");
1844 // set boolean ephUsed here (EPH markers)
1845 ephUsed = ((System.String) encSpec.ephs.getTileDef(t)).Equals("on");
1846  
1847 sb = src.getAnSubbandTree(t, c);
1848 for (int i = mrl; i > r; i--)
1849 {
1850 sb = sb.subb_LL;
1851 }
1852  
1853 threshold = layers[l].rdThreshold;
1854 findTruncIndices(l, c, r, t, sb, threshold, nextPrec[c][r]);
1855  
1856 hBuff = pktEnc.encodePacket(l + 1, c, r, t, cblks[t][c][r], truncIdxs[t][l][c][r], hBuff, bBuff, nextPrec[c][r]);
1857  
1858 if (pktEnc.PacketWritable)
1859 {
1860 bsWriter.writePacketHead(hBuff.Buffer, hBuff.Length, false, sopUsed, ephUsed);
1861 bsWriter.writePacketBody(pktEnc.LastBodyBuf, pktEnc.LastBodyLen, false, pktEnc.ROIinPkt, pktEnc.ROILen);
1862 }
1863 } // layers
1864 nextPrec[c][r]++;
1865 } // Components
1866 if (px != pxend)
1867 {
1868 x = minx + px * gcd_x;
1869 }
1870 else
1871 {
1872 x = tx0;
1873 }
1874 } // Horizontal precincts
1875 if (py != pyend)
1876 {
1877 y = miny + py * gcd_y;
1878 }
1879 else
1880 {
1881 y = ty0;
1882 }
1883 } // Vertical precincts
1884 } // Resolution levels
1885  
1886 // Check that all precincts have been written
1887 for (int c = cs; c < ce; c++)
1888 {
1889 mrl = src.getAnSubbandTree(t, c).resLvl;
1890 for (int r = rs; r < re; r++)
1891 {
1892 if (r > mrl)
1893 continue;
1894 if (nextPrec[c][r] < numPrec[t][c][r].x * numPrec[t][c][r].y - 1)
1895 {
1896 throw new System.ApplicationException("JJ2000 bug: One precinct at least has " + "not been written for resolution level " + r + " of component " + c + " in tile " + t + ".");
1897 }
1898 }
1899 }
1900 }
1901  
1902 /// <summary> This function implements the rate-distortion optimization algorithm.
1903 /// It saves the state of any previously generated bit-stream layers and
1904 /// then simulate the formation of a new layer in the bit stream as often
1905 /// as necessary to find the smallest rate-distortion threshold such that
1906 /// the total number of bytes required to represent the layer does not
1907 /// exceed `maxBytes' minus `prevBytes'. It then restores the state of any
1908 /// previously generated bit-stream layers and returns the threshold.
1909 ///
1910 /// </summary>
1911 /// <param name="layerIdx">The index of the current layer
1912 ///
1913 /// </param>
1914 /// <param name="fmaxt">The maximum admissible slope value. Normally the threshold
1915 /// slope of the previous layer.
1916 ///
1917 /// </param>
1918 /// <param name="maxBytes">The maximum number of bytes that can be written. It
1919 /// includes the length of the current layer bistream length and all the
1920 /// previous layers bit streams.
1921 ///
1922 /// </param>
1923 /// <param name="prevBytes">The number of bytes of all the previous layers.
1924 ///
1925 /// </param>
1926 /// <returns> The value of the slope threshold.
1927 ///
1928 /// </returns>
1929 private float optimizeBitstreamLayer(int layerIdx, float fmaxt, int maxBytes, int prevBytes)
1930 {
1931  
1932 int nt; // The total number of tiles
1933 int nc; // The total number of components
1934 int numLvls; // The total number of resolution levels
1935 int actualBytes; // Actual number of bytes for a layer
1936 float fmint; // Minimum of the current threshold interval
1937 float ft; // Current threshold
1938 SubbandAn sb; // Current subband
1939 BitOutputBuffer hBuff; // The packet head buffer
1940 byte[] bBuff; // The packet body buffer
1941 int sidx; // The index in the summary table
1942 bool sopUsed; // Should SOP markers be used ?
1943 bool ephUsed; // Should EPH markers be used ?
1944 //int precinctIdx; // Precinct index for current packet
1945 int nPrec; // Number of precincts in the current resolution level
1946  
1947 // Save the packet encoder state
1948 pktEnc.save();
1949  
1950 nt = src.getNumTiles();
1951 nc = src.NumComps;
1952 hBuff = null;
1953 bBuff = null;
1954  
1955 // Estimate the minimum slope to start with from the summary
1956 // information in 'RDSlopesRates'. This is a real minimum since it
1957 // does not include the packet head overhead, which is always
1958 // non-zero.
1959  
1960 // Look for the summary entry that gives 'maxBytes' or more data
1961 for (sidx = RD_SUMMARY_SIZE - 1; sidx > 0; sidx--)
1962 {
1963 if (RDSlopesRates[sidx] >= maxBytes)
1964 {
1965 break;
1966 }
1967 }
1968 // Get the corresponding minimum slope
1969 fmint = getSlopeFromSIndex(sidx);
1970 // Ensure that it is smaller the maximum slope
1971 if (fmint >= fmaxt)
1972 {
1973 sidx--;
1974 fmint = getSlopeFromSIndex(sidx);
1975 }
1976 // If we are using the last entry of the summary, then that
1977 // corresponds to all the data, Thus, set the minimum slope to 0.
1978 if (sidx <= 0)
1979 fmint = 0;
1980  
1981 // We look for the best threshold 'ft', which is the lowest threshold
1982 // that generates no more than 'maxBytes' code bytes.
1983  
1984 // The search is done iteratively using a binary split algorithm. We
1985 // start with 'fmaxt' as the maximum possible threshold, and 'fmint'
1986 // as the minimum threshold. The threshold 'ft' is calculated as the
1987 // middle point of 'fmaxt'-'fmint' interval. The 'fmaxt' or 'fmint'
1988 // bounds are moved according to the number of bytes obtained from a
1989 // simulation, where 'ft' is used as the threshold.
1990  
1991 // We stop whenever the interval is sufficiently small, and thus
1992 // enough precision is achieved.
1993  
1994 // Initialize threshold as the middle point of the interval.
1995 ft = (fmaxt + fmint) / 2f;
1996 // If 'ft' reaches 'fmint' it means that 'fmaxt' and 'fmint' are so
1997 // close that the average is 'fmint', due to rounding. Force it to
1998 // 'fmaxt' instead, since 'fmint' is normally an exclusive lower
1999 // bound.
2000 if (ft <= fmint)
2001 ft = fmaxt;
2002  
2003 do
2004 {
2005 // Get the number of bytes used by this layer, if 'ft' is the
2006 // threshold, by simulation.
2007 actualBytes = prevBytes;
2008 src.setTile(0, 0);
2009  
2010 for (int t = 0; t < nt; t++)
2011 {
2012 for (int c = 0; c < nc; c++)
2013 {
2014 // set boolean sopUsed here (SOP markers)
2015 sopUsed = ((System.String) encSpec.sops.getTileDef(t)).ToUpper().Equals("on".ToUpper());
2016 // set boolean ephUsed here (EPH markers)
2017 ephUsed = ((System.String) encSpec.ephs.getTileDef(t)).ToUpper().Equals("on".ToUpper());
2018  
2019 // Get LL subband
2020 sb = (SubbandAn) src.getAnSubbandTree(t, c);
2021 numLvls = sb.resLvl + 1;
2022 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
2023 //loop on resolution levels
2024 for (int r = 0; r < numLvls; r++)
2025 {
2026  
2027 nPrec = numPrec[t][c][r].x * numPrec[t][c][r].y;
2028 for (int p = 0; p < nPrec; p++)
2029 {
2030  
2031 findTruncIndices(layerIdx, c, r, t, sb, ft, p);
2032 hBuff = pktEnc.encodePacket(layerIdx + 1, c, r, t, cblks[t][c][r], truncIdxs[t][layerIdx][c][r], hBuff, bBuff, p);
2033  
2034 if (pktEnc.PacketWritable)
2035 {
2036 bBuff = pktEnc.LastBodyBuf;
2037 actualBytes += bsWriter.writePacketHead(hBuff.Buffer, hBuff.Length, true, sopUsed, ephUsed);
2038 actualBytes += bsWriter.writePacketBody(bBuff, pktEnc.LastBodyLen, true, pktEnc.ROIinPkt, pktEnc.ROILen);
2039 }
2040 } // end loop on precincts
2041 sb = sb.parentband;
2042 } // End loop on resolution levels
2043 } // End loop on components
2044 } // End loop on tiles
2045  
2046 // Move the interval bounds according to simulation result
2047 if (actualBytes > maxBytes)
2048 {
2049 // 'ft' is too low and generates too many bytes, make it the
2050 // new minimum.
2051 fmint = ft;
2052 }
2053 else
2054 {
2055 // 'ft' is too high and does not generate as many bytes as we
2056 // are allowed too, make it the new maximum.
2057 fmaxt = ft;
2058 }
2059  
2060 // Update 'ft' for the new iteration as the middle point of the
2061 // new interval.
2062 ft = (fmaxt + fmint) / 2f;
2063 // If 'ft' reaches 'fmint' it means that 'fmaxt' and 'fmint' are
2064 // so close that the average is 'fmint', due to rounding. Force it
2065 // to 'fmaxt' instead, since 'fmint' is normally an exclusive
2066 // lower bound.
2067 if (ft <= fmint)
2068 ft = fmaxt;
2069  
2070 // Restore previous packet encoder state
2071 pktEnc.restore();
2072  
2073 // We continue to iterate, until the threshold reaches the upper
2074 // limit of the interval, within a FLOAT_REL_PRECISION relative
2075 // tolerance, or a FLOAT_ABS_PRECISION absolute tolerance. This is
2076 // the sign that the interval is sufficiently small.
2077 }
2078 while (ft < fmaxt * (1f - FLOAT_REL_PRECISION) && ft < (fmaxt - FLOAT_ABS_PRECISION));
2079  
2080 // If we have a threshold which is close to 0, set it to 0 so that
2081 // everything is taken into the layer. This is to avoid not sending
2082 // some least significant bit-planes in the lossless case. We use the
2083 // FLOAT_ABS_PRECISION value as a measure of "close" to 0.
2084 if (ft <= FLOAT_ABS_PRECISION)
2085 {
2086 ft = 0f;
2087 }
2088 else
2089 {
2090 // Otherwise make the threshold 'fmaxt', just to be sure that we
2091 // will not send more bytes than allowed.
2092 ft = fmaxt;
2093 }
2094 return ft;
2095 }
2096  
2097 /// <summary> This function attempts to estimate a rate-distortion slope threshold
2098 /// which will achieve a target number of code bytes close the
2099 /// `targetBytes' value.
2100 ///
2101 /// </summary>
2102 /// <param name="targetBytes">The target number of bytes for the current layer
2103 ///
2104 /// </param>
2105 /// <param name="lastLayer">The previous layer information.
2106 ///
2107 /// </param>
2108 /// <returns> The value of the slope threshold for the estimated layer
2109 ///
2110 /// </returns>
2111 private float estimateLayerThreshold(int targetBytes, EBCOTLayer lastLayer)
2112 {
2113 float log_sl1; // The log of the first slope used for interpolation
2114 float log_sl2; // The log of the second slope used for interpolation
2115 float log_len1; // The log of the first length used for interpolation
2116 float log_len2; // The log of the second length used for interpolation
2117 float log_isl; // The log of the interpolated slope
2118 float log_ilen; // Log of the interpolated length
2119 float log_ab; // Log of actual bytes in last layer
2120 int sidx; // Index into the summary R-D info array
2121 float log_off; // The log of the offset proportion
2122 int tlen; // The corrected target layer length
2123 float lthresh; // The threshold of the last layer
2124 float eth; // The estimated threshold
2125  
2126 // In order to estimate the threshold we base ourselves in the summary
2127 // R-D info in RDSlopesRates. In order to use it we must compensate
2128 // for the overhead of the packet heads. The proportion of overhead is
2129 // estimated using the last layer simulation results.
2130  
2131 // NOTE: the model used in this method is that the slope varies
2132 // linearly with the log of the rate (i.e. length).
2133  
2134 // NOTE: the model used in this method is that the distortion is
2135 // proprotional to a power of the rate. Thus, the slope is also
2136 // proportional to another power of the rate. This translates as the
2137 // log of the slope varies linearly with the log of the rate, which is
2138 // what we use.
2139  
2140 // 1) Find the offset of the length predicted from the summary R-D
2141 // information, to the actual length by using the last layer.
2142  
2143 // We ensure that the threshold we use for estimation actually
2144 // includes some data.
2145 lthresh = lastLayer.rdThreshold;
2146 if (lthresh > maxSlope)
2147 lthresh = maxSlope;
2148 // If the slope of the last layer is too small then we just include
2149 // all the rest (not possible to do better).
2150 if (lthresh < FLOAT_ABS_PRECISION)
2151 return 0f;
2152 sidx = getLimitedSIndexFromSlope(lthresh);
2153 // If the index is outside of the summary info array use the last two,
2154 // or first two, indexes, as appropriate
2155 if (sidx >= RD_SUMMARY_SIZE - 1)
2156 sidx = RD_SUMMARY_SIZE - 2;
2157  
2158 // Get the logs of the lengths and the slopes
2159  
2160 if (RDSlopesRates[sidx + 1] == 0)
2161 {
2162 // Pathological case, we can not use log of 0. Add
2163 // RDSlopesRates[sidx]+1 bytes to the rates (just a crude simple
2164 // solution to this rare case)
2165 //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'"
2166 log_len1 = (float) System.Math.Log((RDSlopesRates[sidx] << 1) + 1);
2167 //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'"
2168 log_len2 = (float) System.Math.Log(RDSlopesRates[sidx] + 1);
2169 //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'"
2170 log_ab = (float) System.Math.Log(lastLayer.actualBytes + RDSlopesRates[sidx] + 1);
2171 }
2172 else
2173 {
2174 //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'"
2175 log_len1 = (float) System.Math.Log(RDSlopesRates[sidx]);
2176 //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'"
2177 log_len2 = (float) System.Math.Log(RDSlopesRates[sidx + 1]);
2178 //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'"
2179 log_ab = (float) System.Math.Log(lastLayer.actualBytes);
2180 }
2181  
2182 //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'"
2183 log_sl1 = (float) System.Math.Log(getSlopeFromSIndex(sidx));
2184 //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'"
2185 log_sl2 = (float) System.Math.Log(getSlopeFromSIndex(sidx + 1));
2186  
2187 //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'"
2188 log_isl = (float) System.Math.Log(lthresh);
2189  
2190 log_ilen = log_len1 + (log_isl - log_sl1) * (log_len1 - log_len2) / (log_sl1 - log_sl2);
2191  
2192 log_off = log_ab - log_ilen;
2193  
2194 // Do not use negative offsets (i.e. offset proportion larger than 1)
2195 // since that is probably a sign that our model is off. To be
2196 // conservative use an offset of 0 (i.e. offset proportiojn 1).
2197 if (log_off < 0)
2198 log_off = 0f;
2199  
2200 // 2) Correct the target layer length by the offset.
2201  
2202 //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'"
2203 tlen = (int) (targetBytes / (float) System.Math.Exp(log_off));
2204  
2205 // 3) Find, from the summary R-D info, the thresholds that generate
2206 // lengths just above and below our corrected target layer length.
2207  
2208 // Look for the index in the summary info array that gives the largest
2209 // length smaller than the target length
2210 for (sidx = RD_SUMMARY_SIZE - 1; sidx >= 0; sidx--)
2211 {
2212 if (RDSlopesRates[sidx] >= tlen)
2213 break;
2214 }
2215 sidx++;
2216 // Correct if out of the array
2217 if (sidx >= RD_SUMMARY_SIZE)
2218 sidx = RD_SUMMARY_SIZE - 1;
2219 if (sidx <= 0)
2220 sidx = 1;
2221  
2222 // Get the log of the lengths and the slopes that are just above and
2223 // below the target length.
2224  
2225 if (RDSlopesRates[sidx] == 0)
2226 {
2227 // Pathological case, we can not use log of 0. Add
2228 // RDSlopesRates[sidx-1]+1 bytes to the rates (just a crude simple
2229 // solution to this rare case)
2230 //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'"
2231 log_len1 = (float) System.Math.Log(RDSlopesRates[sidx - 1] + 1);
2232 //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'"
2233 log_len2 = (float) System.Math.Log((RDSlopesRates[sidx - 1] << 1) + 1);
2234 //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'"
2235 log_ilen = (float) System.Math.Log(tlen + RDSlopesRates[sidx - 1] + 1);
2236 }
2237 else
2238 {
2239 // Normal case, we can safely take the logs.
2240 //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'"
2241 log_len1 = (float) System.Math.Log(RDSlopesRates[sidx]);
2242 //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'"
2243 log_len2 = (float) System.Math.Log(RDSlopesRates[sidx - 1]);
2244 //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'"
2245 log_ilen = (float) System.Math.Log(tlen);
2246 }
2247  
2248 //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'"
2249 log_sl1 = (float) System.Math.Log(getSlopeFromSIndex(sidx));
2250 //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'"
2251 log_sl2 = (float) System.Math.Log(getSlopeFromSIndex(sidx - 1));
2252  
2253 // 4) Interpolate the two thresholds to find the target threshold.
2254  
2255 log_isl = log_sl1 + (log_ilen - log_len1) * (log_sl1 - log_sl2) / (log_len1 - log_len2);
2256  
2257 //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'"
2258 eth = (float) System.Math.Exp(log_isl);
2259  
2260 // Correct out of bounds results
2261 if (eth > lthresh)
2262 eth = lthresh;
2263 if (eth < FLOAT_ABS_PRECISION)
2264 eth = 0f;
2265  
2266 // Return the estimated threshold
2267 return eth;
2268 }
2269  
2270 /// <summary> This function finds the new truncation points indices for a packet. It
2271 /// does so by including the data from the code-blocks in the component,
2272 /// resolution level and tile, associated with a R-D slope which is larger
2273 /// than or equal to 'fthresh'.
2274 ///
2275 /// </summary>
2276 /// <param name="layerIdx">The index of the current layer
2277 ///
2278 /// </param>
2279 /// <param name="compIdx">The index of the current component
2280 ///
2281 /// </param>
2282 /// <param name="lvlIdx">The index of the current resolution level
2283 ///
2284 /// </param>
2285 /// <param name="tileIdx">The index of the current tile
2286 ///
2287 /// </param>
2288 /// <param name="subb">The LL subband in the resolution level lvlIdx, which is
2289 /// parent of all the subbands in the packet. Except for resolution level 0
2290 /// this subband is always a node.
2291 ///
2292 /// </param>
2293 /// <param name="fthresh">The value of the rate-distortion threshold
2294 ///
2295 /// </param>
2296 private void findTruncIndices(int layerIdx, int compIdx, int lvlIdx, int tileIdx, SubbandAn subb, float fthresh, int precinctIdx)
2297 {
2298 int minsbi, maxsbi, b, n; // bIdx removed
2299 //Coord ncblks = null;
2300 SubbandAn sb;
2301 CBlkRateDistStats cur_cblk;
2302 PrecInfo prec = pktEnc.getPrecInfo(tileIdx, compIdx, lvlIdx, precinctIdx);
2303 Coord cbCoord;
2304  
2305 sb = subb;
2306 while (sb.subb_HH != null)
2307 {
2308 sb = sb.subb_HH;
2309 }
2310 minsbi = (lvlIdx == 0)?0:1;
2311 maxsbi = (lvlIdx == 0)?1:4;
2312  
2313 int yend, xend;
2314  
2315 sb = (SubbandAn) subb.getSubbandByIdx(lvlIdx, minsbi);
2316 for (int s = minsbi; s < maxsbi; s++)
2317 {
2318 //loop on subbands
2319 yend = (prec.cblk[s] != null)?prec.cblk[s].Length:0;
2320 for (int y = 0; y < yend; y++)
2321 {
2322 xend = (prec.cblk[s][y] != null)?prec.cblk[s][y].Length:0;
2323 for (int x = 0; x < xend; x++)
2324 {
2325 cbCoord = prec.cblk[s][y][x].idx;
2326 b = cbCoord.x + cbCoord.y * sb.numCb.x;
2327  
2328 //Get the current code-block
2329 cur_cblk = cblks[tileIdx][compIdx][lvlIdx][s][b];
2330 for (n = 0; n < cur_cblk.nVldTrunc; n++)
2331 {
2332 if (cur_cblk.truncSlopes[n] < fthresh)
2333 {
2334 break;
2335 }
2336 else
2337 {
2338 continue;
2339 }
2340 }
2341 // Store the index in the code-block truncIdxs that gives
2342 // the real truncation index.
2343 truncIdxs[tileIdx][layerIdx][compIdx][lvlIdx][s][b] = n - 1;
2344 } // End loop on horizontal code-blocks
2345 } // End loop on vertical code-blocks
2346 sb = (SubbandAn) sb.nextSubband();
2347 } // End loop on subbands
2348 }
2349  
2350 /// <summary> Returns the index of a slope for the summary table, limiting to the
2351 /// admissible values. The index is calculated as RD_SUMMARY_OFF plus the
2352 /// maximum exponent, base 2, that yields a value not larger than the slope
2353 /// itself.
2354 ///
2355 /// <p>If the value to return is lower than 0, 0 is returned. If it is
2356 /// larger than the maximum table index, then the maximum is returned.</p>
2357 ///
2358 /// </summary>
2359 /// <param name="slope">The slope value
2360 ///
2361 /// </param>
2362 /// <returns> The index for the summary table of the slope.
2363 ///
2364 /// </returns>
2365 private static int getLimitedSIndexFromSlope(float slope)
2366 {
2367 int idx;
2368  
2369 //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'"
2370 idx = (int) System.Math.Floor(System.Math.Log(slope) / LOG2) + RD_SUMMARY_OFF;
2371  
2372 if (idx < 0)
2373 {
2374 return 0;
2375 }
2376 else if (idx >= RD_SUMMARY_SIZE)
2377 {
2378 return RD_SUMMARY_SIZE - 1;
2379 }
2380 else
2381 {
2382 return idx;
2383 }
2384 }
2385  
2386 /// <summary> Returns the minimum slope value associated with a summary table
2387 /// index. This minimum slope is just 2^(index-RD_SUMMARY_OFF).
2388 ///
2389 /// </summary>
2390 /// <param name="index">The summary index value.
2391 ///
2392 /// </param>
2393 /// <returns> The minimum slope value associated with a summary table index.
2394 ///
2395 /// </returns>
2396 private static float getSlopeFromSIndex(int index)
2397 {
2398 //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'"
2399 return (float) System.Math.Pow(2, (index - RD_SUMMARY_OFF));
2400 }
2401 }
2402 }