corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * CVS identifier:
3 *
4 * $Id: ROIScaler.java,v 1.11 2001/09/20 12:42:20 grosbois Exp $
5 *
6 * Class: ROIScaler
7 *
8 * Description: This class takes care of the scaling of the
9 * samples
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.quantization.quantizer;
46 using CSJ2K.j2k.codestream.writer;
47 using CSJ2K.j2k.wavelet.analysis;
48 using CSJ2K.j2k.quantization;
49 using CSJ2K.j2k.image.input;
50 using CSJ2K.j2k.wavelet;
51 using CSJ2K.j2k.encoder;
52 using CSJ2K.j2k.image;
53 using CSJ2K.j2k.util;
54 using CSJ2K.j2k.roi;
55 using CSJ2K.j2k;
56 namespace CSJ2K.j2k.roi.encoder
57 {
58  
59 /// <summary> This class deals with the ROI functionality.
60 ///
61 /// <p>The ROI method is the Maxshift method. The ROIScaler works by scaling
62 /// the quantized wavelet coefficients that do not affect the ROI (i.e
63 /// background coefficients) so that these samples get a lower significance
64 /// than the ROI ones. By scaling the coefficients sufficiently, the ROI
65 /// coefficients can be recognized by their amplitude alone and no ROI mask
66 /// needs to be generated at the decoder side.
67 ///
68 /// <p>The source module must be a quantizer and code-block's data is exchange
69 /// with thanks to CBlkWTData instances.
70 ///
71 /// </summary>
72 /// <seealso cref="Quantizer">
73 /// </seealso>
74 /// <seealso cref="CBlkWTData">
75 ///
76 /// </seealso>
77 public class ROIScaler:ImgDataAdapter, CBlkQuantDataSrcEnc
78 {
79 /// <summary> Returns the horizontal offset of the code-block partition. Allowable
80 /// values are 0 and 1, nothing else.
81 ///
82 /// </summary>
83 virtual public int CbULX
84 {
85 get
86 {
87 return src.CbULX;
88 }
89  
90 }
91 /// <summary> Returns the vertical offset of the code-block partition. Allowable
92 /// values are 0 and 1, nothing else.
93 ///
94 /// </summary>
95 virtual public int CbULY
96 {
97 get
98 {
99 return src.CbULY;
100 }
101  
102 }
103 /// <summary> This function returns the ROI mask generator.
104 ///
105 /// </summary>
106 /// <returns> The roi mask generator
107 /// </returns>
108 virtual public ROIMaskGenerator ROIMaskGenerator
109 {
110 get
111 {
112 return mg;
113 }
114  
115 }
116 /// <summary> This function returns the blockAligned flag
117 ///
118 /// </summary>
119 /// <returns> Flag indicating whether the ROIs were block aligned
120 /// </returns>
121 virtual public bool BlockAligned
122 {
123 get
124 {
125 return blockAligned;
126 }
127  
128 }
129 /// <summary> Returns the parameters that are used in this class and
130 /// implementing classes. It returns a 2D String array. Each of the
131 /// 1D arrays is for a different option, and they have 3
132 /// elements. The first element is the option name, the second one
133 /// is the synopsis, the third one is a long description of what
134 /// the parameter is and the fourth is its default value. The
135 /// synopsis or description may be 'null', in which case it is
136 /// assumed that there is no synopsis or description of the option,
137 /// respectively. Null may be returned if no options are supported.
138 ///
139 /// </summary>
140 /// <returns> the options name, their synopsis and their explanation,
141 /// or null if no options are supported.
142 ///
143 /// </returns>
144 public static System.String[][] ParameterInfo
145 {
146 get
147 {
148 return pinfo;
149 }
150  
151 }
152  
153 /// <summary>The prefix for ROI Scaler options: 'R' </summary>
154 public const char OPT_PREFIX = 'R';
155  
156 /// <summary>The list of parameters that are accepted for ROI coding. Options
157 /// for ROI Scaler start with 'R'.
158 /// </summary>
159 //UPGRADE_NOTE: Final was removed from the declaration of 'pinfo'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
160 private static readonly System.String[][] pinfo = new System.String[][]{new System.String[]{"Rroi", "[<component idx>] R <left> <top> <width> <height>" + " or [<component idx>] C <centre column> <centre row> " + "<radius> or [<component idx>] A <filename>", "Specifies ROIs shape and location. The shape can be either " + "rectangular 'R', or circular 'C' or arbitrary 'A'. " + "Each new occurrence of an 'R', a 'C' or an 'A' is a new ROI. " + "For circular and rectangular ROIs, all values are " + "given as their pixel values relative to the canvas origin. " + "Arbitrary shapes must be included in a PGM file where non 0 " + "values correspond to ROI coefficients. The PGM file must have " + "the size as the image. " + "The component idx specifies which components " + "contain the ROI. The component index is specified as described " + "by points 3 and 4 in the general comment on tile-component idx. " + "If this option is used, the codestream is layer progressive by " + "default unless it is overridden by the 'Aptype' option.", null}, new System.String[]{"Ralign", "[on|off]", "By specifying this argument, the ROI mask will be " + "limited to covering only entire code-blocks. The ROI coding can " + "then be performed without any actual scaling of the coefficients " + "but by instead scaling the distortion estimates.", "off"}, new System.String[]{"Rstart_level", "<level>", "This argument forces the lowest <level> resolution levels to " + "belong to the ROI. By doing this, it is possible to avoid only " + "getting information for the ROI at an early stage of " + "transmission.<level> = 0 means the lowest resolution level " + "belongs to the ROI, 1 means the two lowest etc. (-1 deactivates" + " the option)", "-1"}, new System.String[]{"Rno_rect", "[on|off]", "This argument makes sure that the ROI mask generation is not done " + "using the fast ROI mask generation for rectangular ROIs " + "regardless of whether the specified ROIs are rectangular or not", "off"}};
161  
162 /// <summary>The maximum number of magnitude bit-planes in any subband. One value
163 /// for each tile-component
164 /// </summary>
165 private int[][] maxMagBits;
166  
167 /// <summary>Flag indicating the presence of ROIs </summary>
168 private bool roi;
169  
170 /// <summary>Flag indicating if block aligned ROIs are used </summary>
171 private bool blockAligned;
172  
173 /// <summary>Number of resolution levels to include in ROI mask </summary>
174 private int useStartLevel;
175  
176 /// <summary>The class generating the ROI mask </summary>
177 private ROIMaskGenerator mg;
178  
179 /// <summary>The ROI mask </summary>
180 private DataBlkInt roiMask;
181  
182 /// <summary>The source of quantized wavelet transform coefficients </summary>
183 private Quantizer src;
184  
185 /// <summary> Constructor of the ROI scaler, takes a Quantizer as source of data to
186 /// scale.
187 ///
188 /// </summary>
189 /// <param name="src">The quantizer that is the source of data.
190 ///
191 /// </param>
192 /// <param name="mg">The mask generator that will be used for all components
193 ///
194 /// </param>
195 /// <param name="roi">Flag indicating whether there are rois specified.
196 ///
197 /// </param>
198 /// <param name="sLev">The resolution levels that belong entirely to ROI
199 ///
200 /// </param>
201 /// <param name="uba">Flag indicating whether block aligning is used.
202 ///
203 /// </param>
204 /// <param name="encSpec">The encoder specifications for addition of roi specs
205 ///
206 /// </param>
207 public ROIScaler(Quantizer src, ROIMaskGenerator mg, bool roi, int sLev, bool uba, EncoderSpecs encSpec):base(src)
208 {
209 this.src = src;
210 this.roi = roi;
211 this.useStartLevel = sLev;
212 if (roi)
213 {
214 // If there is no ROI, no need to do this
215 this.mg = mg;
216 roiMask = new DataBlkInt();
217 calcMaxMagBits(encSpec);
218 blockAligned = uba;
219 }
220 }
221  
222 /// <summary> Since ROI scaling is always a reversible operation, it calls
223 /// isReversible() method of it source (the quantizer module).
224 ///
225 /// </summary>
226 /// <param name="t">The tile to test for reversibility
227 ///
228 /// </param>
229 /// <param name="c">The component to test for reversibility
230 ///
231 /// </param>
232 /// <returns> True if the quantized data is reversible, false if not.
233 ///
234 /// </returns>
235 public virtual bool isReversible(int t, int c)
236 {
237 return src.isReversible(t, c);
238 }
239  
240 /// <summary> Returns a reference to the subband tree structure representing the
241 /// subband decomposition for the specified tile-component.
242 ///
243 /// </summary>
244 /// <param name="t">The index of the tile.
245 ///
246 /// </param>
247 /// <param name="c">The index of the component.
248 ///
249 /// </param>
250 /// <returns> The subband tree structure, see SubbandAn.
251 ///
252 /// </returns>
253 /// <seealso cref="SubbandAn">
254 ///
255 /// </seealso>
256 /// <seealso cref="Subband">
257 ///
258 /// </seealso>
259 public virtual SubbandAn getAnSubbandTree(int t, int c)
260 {
261 return src.getAnSubbandTree(t, c);
262 }
263  
264 /// <summary> Creates a ROIScaler object. The Quantizer is the source of data to
265 /// scale.
266 ///
267 /// <p>The ROI Scaler creates a ROIMaskGenerator depending on what ROI
268 /// information is in the ParameterList. If only rectangular ROI are used,
269 /// the fast mask generator for rectangular ROI can be used.</p>
270 ///
271 /// </summary>
272 /// <param name="src">The source of data to scale
273 ///
274 /// </param>
275 /// <param name="pl">The parameter list (or options).
276 ///
277 /// </param>
278 /// <param name="encSpec">The encoder specifications for addition of roi specs
279 ///
280 /// </param>
281 /// <exception cref="IllegalArgumentException">If an error occurs while parsing
282 /// the options in 'pl'
283 ///
284 /// </exception>
285 public static ROIScaler createInstance(Quantizer src, ParameterList pl, EncoderSpecs encSpec)
286 {
287 System.Collections.ArrayList roiVector = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
288 ROIMaskGenerator maskGen = null;
289  
290 // Check parameters
291 pl.checkList(OPT_PREFIX, CSJ2K.j2k.util.ParameterList.toNameArray(pinfo));
292  
293 // Get parameters and check if there are and ROIs specified
294 System.String roiopt = pl.getParameter("Rroi");
295 if (roiopt == null)
296 {
297 // No ROIs specified! Create ROIScaler with no mask generator
298 return new ROIScaler(src, null, false, - 1, false, encSpec);
299 }
300  
301 // Check if the lowest resolution levels should belong to the ROI
302 int sLev = pl.getIntParameter("Rstart_level");
303  
304 // Check if the ROIs are block-aligned
305 bool useBlockAligned = pl.getBooleanParameter("Ralign");
306  
307 // Check if generic mask generation is specified
308 bool onlyRect = !pl.getBooleanParameter("Rno_rect");
309  
310 // Parse the ROIs
311 parseROIs(roiopt, src.NumComps, roiVector);
312 ROI[] roiArray = new ROI[roiVector.Count];
313 roiVector.CopyTo(roiArray);
314  
315 // If onlyRect has been forced, check if there are any non-rectangular
316 // ROIs specified. Currently, only the presence of circular ROIs will
317 // make this false
318 if (onlyRect)
319 {
320 for (int i = roiArray.Length - 1; i >= 0; i--)
321 if (!roiArray[i].rect)
322 {
323 onlyRect = false;
324 break;
325 }
326 }
327  
328 if (onlyRect)
329 {
330 // It's possible to use the fast ROI mask generation when only
331 // rectangular ROIs are specified.
332 maskGen = new RectROIMaskGenerator(roiArray, src.NumComps);
333 }
334 else
335 {
336 // It's necessary to use the generic mask generation
337 maskGen = new ArbROIMaskGenerator(roiArray, src.NumComps, src);
338 }
339 return new ROIScaler(src, maskGen, true, sLev, useBlockAligned, encSpec);
340 }
341  
342 /// <summary> This function parses the values given for the ROIs with the argument
343 /// -Rroi. Currently only circular and rectangular ROIs are supported.
344 ///
345 /// <p>A rectangular ROI is indicated by a 'R' followed the coordinates for
346 /// the upper left corner of the ROI and then its width and height.</p>
347 ///
348 /// <p>A circular ROI is indicated by a 'C' followed by the coordinates of
349 /// the circle center and then the radius.</p>
350 ///
351 /// <p>Before the R and C values, the component that are affected by the
352 /// ROI are indicated.</p>
353 ///
354 /// </summary>
355 /// <param name="roiopt">The info on the ROIs
356 ///
357 /// </param>
358 /// <param name="nc">number of components
359 ///
360 /// </param>
361 /// <param name="roiVector">The vcector containing the ROI parsed from the cmd line
362 ///
363 /// </param>
364 /// <returns> The ROIs specified in roiopt
365 ///
366 /// </returns>
367 protected internal static System.Collections.ArrayList parseROIs(System.String roiopt, int nc, System.Collections.ArrayList roiVector)
368 {
369 //ROI[] ROIs;
370 ROI roi;
371 SupportClass.Tokenizer stok;
372 //char tok;
373 int nrOfROIs = 0;
374 //char c;
375 int ulx, uly, w, h, x, y, rad; // comp removed
376 bool[] roiInComp = null;
377  
378 stok = new SupportClass.Tokenizer(roiopt);
379  
380 System.String word;
381 while (stok.HasMoreTokens())
382 {
383 word = stok.NextToken();
384  
385 switch (word[0])
386 {
387  
388 case 'c': // Components specification
389 roiInComp = ModuleSpec.parseIdx(word, nc);
390 break;
391  
392 case 'R': // Rectangular ROI to be read
393 nrOfROIs++;
394 try
395 {
396 word = stok.NextToken();
397 ulx = (System.Int32.Parse(word));
398 word = stok.NextToken();
399 uly = (System.Int32.Parse(word));
400 word = stok.NextToken();
401 w = (System.Int32.Parse(word));
402 word = stok.NextToken();
403 h = (System.Int32.Parse(word));
404 }
405 catch (System.FormatException)
406 {
407 throw new System.ArgumentException("Bad parameter for " + "'-Rroi R' option : " + word);
408 }
409 catch (System.ArgumentOutOfRangeException)
410 {
411 throw new System.ArgumentException("Wrong number of " + "parameters for " + "h'-Rroi R' option.");
412 }
413  
414 // If the ROI is component-specific, check which comps.
415 if (roiInComp != null)
416 for (int i = 0; i < nc; i++)
417 {
418 if (roiInComp[i])
419 {
420 roi = new ROI(i, ulx, uly, w, h);
421 roiVector.Add(roi);
422 }
423 }
424 else
425 {
426 // Otherwise add ROI for all components
427 for (int i = 0; i < nc; i++)
428 {
429 roi = new ROI(i, ulx, uly, w, h);
430 roiVector.Add(roi);
431 }
432 }
433 break;
434  
435 case 'C': // Circular ROI to be read
436 nrOfROIs++;
437  
438 try
439 {
440 word = stok.NextToken();
441 x = (System.Int32.Parse(word));
442 word = stok.NextToken();
443 y = (System.Int32.Parse(word));
444 word = stok.NextToken();
445 rad = (System.Int32.Parse(word));
446 }
447 catch (System.FormatException)
448 {
449 throw new System.ArgumentException("Bad parameter for " + "'-Rroi C' option : " + word);
450 }
451 catch (System.ArgumentOutOfRangeException)
452 {
453 throw new System.ArgumentException("Wrong number of " + "parameters for " + "'-Rroi C' option.");
454 }
455  
456 // If the ROI is component-specific, check which comps.
457 if (roiInComp != null)
458 for (int i = 0; i < nc; i++)
459 {
460 if (roiInComp[i])
461 {
462 roi = new ROI(i, x, y, rad);
463 roiVector.Add(roi);
464 }
465 }
466 else
467 {
468 // Otherwise add ROI for all components
469 for (int i = 0; i < nc; i++)
470 {
471 roi = new ROI(i, x, y, rad);
472 roiVector.Add(roi);
473 }
474 }
475 break;
476  
477 case 'A': // ROI wth arbitrary shape
478 nrOfROIs++;
479  
480 System.String filename;
481 ImgReaderPGM maskPGM = null;
482  
483 try
484 {
485 filename = stok.NextToken();
486 }
487 catch (System.ArgumentOutOfRangeException)
488 {
489 throw new System.ArgumentException("Wrong number of " + "parameters for " + "'-Rroi A' option.");
490 }
491 try
492 {
493 maskPGM = new ImgReaderPGM(filename);
494 }
495 catch (System.IO.IOException)
496 {
497 throw new System.ApplicationException("Cannot read PGM file with ROI");
498 }
499  
500 // If the ROI is component-specific, check which comps.
501 if (roiInComp != null)
502 for (int i = 0; i < nc; i++)
503 {
504 if (roiInComp[i])
505 {
506 roi = new ROI(i, maskPGM);
507 roiVector.Add(roi);
508 }
509 }
510 else
511 {
512 // Otherwise add ROI for all components
513 for (int i = 0; i < nc; i++)
514 {
515 roi = new ROI(i, maskPGM);
516 roiVector.Add(roi);
517 }
518 }
519 break;
520  
521 default:
522 throw new System.ApplicationException("Bad parameters for ROI nr " + roiVector.Count);
523  
524 }
525 }
526  
527 return roiVector;
528 }
529  
530 /// <summary> This function gets a datablk from the entropy coder. The sample sin the
531 /// block, which consists of the quantized coefficients from the quantizer,
532 /// are scaled by the values given for any ROIs specified.
533 ///
534 /// <p>The function calls on a ROIMaskGenerator to get the mask for scaling
535 /// the coefficients in the current block.</p>
536 ///
537 /// <p>The data returned by this method is a copy of the orignal
538 /// data. Therfore it can be modified "in place" without any problems after
539 /// being returned. The 'offset' of the returned data is 0, and the 'scanw'
540 /// is the same as the code-block width. See the 'CBlkWTData' class.</p>
541 ///
542 /// </summary>
543 /// <param name="c">The component for which to return the next code-block.
544 ///
545 /// </param>
546 /// <param name="cblk">If non-null this object will be used to return the new
547 /// code-block. If null a new one will be allocated and returned. If the
548 /// "data" array of the object is non-null it will be reused, if possible,
549 /// to return the data.
550 ///
551 /// </param>
552 /// <returns> The next code-block in the current tile for component 'n', or
553 /// null if all code-blocks for the current tile have been returned.
554 ///
555 /// </returns>
556 /// <seealso cref="CBlkWTData">
557 ///
558 /// </seealso>
559 public virtual CBlkWTData getNextCodeBlock(int c, CBlkWTData cblk)
560 {
561 return getNextInternCodeBlock(c, cblk);
562 }
563  
564 /// <summary> This function gets a datablk from the entropy coder. The sample sin the
565 /// block, which consists of the quantized coefficients from the quantizer,
566 /// are scaled by the values given for any ROIs specified.
567 ///
568 /// <p>The function calls on a ROIMaskGenerator to get the mask for scaling
569 /// the coefficients in the current block.</p>
570 ///
571 /// </summary>
572 /// <param name="c">The component for which to return the next code-block.
573 ///
574 /// </param>
575 /// <param name="cblk">If non-null this object will be used to return the new
576 /// code-block. If null a new one will be allocated and returned. If the
577 /// "data" array of the object is non-null it will be reused, if possible,
578 /// to return the data.
579 ///
580 /// </param>
581 /// <returns> The next code-block in the current tile for component 'n', or
582 /// null if all code-blocks for the current tile have been returned.
583 ///
584 /// </returns>
585 /// <seealso cref="CBlkWTData">
586 ///
587 /// </seealso>
588 public virtual CBlkWTData getNextInternCodeBlock(int c, CBlkWTData cblk)
589 {
590 int mi, i, j, k, wrap;
591 int ulx, uly, w, h;
592 DataBlkInt mask = roiMask; // local copy of mask
593 int[] maskData; // local copy of mask data
594 int[] data; // local copy of quantized data
595 int tmp;
596 int bitMask = 0x7FFFFFFF;
597 SubbandAn root, sb;
598 int maxBits = 0; // local copy
599 bool roiInTile;
600 bool sbInMask;
601 int nROIcoeff = 0;
602  
603 // Get codeblock's data from quantizer
604 cblk = src.getNextCodeBlock(c, cblk);
605  
606 // If there is no ROI in the image, or if we already got all
607 // code-blocks
608 if (!roi || cblk == null)
609 {
610 return cblk;
611 }
612  
613 data = (int[]) cblk.Data;
614 sb = cblk.sb;
615 ulx = cblk.ulx;
616 uly = cblk.uly;
617 w = cblk.w;
618 h = cblk.h;
619 sbInMask = (sb.resLvl <= useStartLevel);
620  
621 // Check that there is an array for the mask and set it to zero
622 maskData = mask.DataInt; // local copy of mask data
623 if (maskData == null || w * h > maskData.Length)
624 {
625 maskData = new int[w * h];
626 mask.DataInt = maskData;
627 }
628 else
629 {
630 for (i = w * h - 1; i >= 0; i--)
631 maskData[i] = 0;
632 }
633 mask.ulx = ulx;
634 mask.uly = uly;
635 mask.w = w;
636 mask.h = h;
637  
638 // Get ROI mask from generator
639 root = src.getAnSubbandTree(tIdx, c);
640 maxBits = maxMagBits[tIdx][c];
641 roiInTile = mg.getROIMask(mask, root, maxBits, c);
642  
643 // If there is no ROI in this tile, return the code-block untouched
644 if (!roiInTile && (!sbInMask))
645 {
646 cblk.nROIbp = 0;
647 return cblk;
648 }
649  
650 // Update field containing the number of ROI magnitude bit-planes
651 cblk.nROIbp = cblk.magbits;
652  
653 // If the entire subband belongs to the ROI mask, The code-block is
654 // set to belong entirely to the ROI with the highest scaling value
655 if (sbInMask)
656 {
657 // Scale the wmse so that instead of scaling the coefficients, the
658 // wmse is scaled.
659 //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'"
660 cblk.wmseScaling *= (float) (1 << (maxBits << 1));
661 cblk.nROIcoeff = w * h;
662 return cblk;
663 }
664  
665 // In 'block aligned' mode, the code-block is set to belong entirely
666 // to the ROI with the highest scaling value if one coefficient, at
667 // least, belongs to the ROI
668 if (blockAligned)
669 {
670 wrap = cblk.scanw - w;
671 mi = h * w - 1;
672 i = cblk.offset + cblk.scanw * (h - 1) + w - 1;
673 int nroicoeff = 0;
674 for (j = h; j > 0; j--)
675 {
676 for (k = w - 1; k >= 0; k--, i--, mi--)
677 {
678 if (maskData[mi] != 0)
679 {
680 nroicoeff++;
681 }
682 }
683 i -= wrap;
684 }
685 if (nroicoeff != 0)
686 {
687 // Include the subband
688 //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'"
689 cblk.wmseScaling *= (float) (1 << (maxBits << 1));
690 cblk.nROIcoeff = w * h;
691 }
692 return cblk;
693 }
694  
695 // Scale background coefficients
696 bitMask = (((1 << cblk.magbits) - 1) << (31 - cblk.magbits));
697 wrap = cblk.scanw - w;
698 mi = h * w - 1;
699 i = cblk.offset + cblk.scanw * (h - 1) + w - 1;
700 for (j = h; j > 0; j--)
701 {
702 for (k = w; k > 0; k--, i--, mi--)
703 {
704 tmp = data[i];
705 if (maskData[mi] != 0)
706 {
707 // ROI coeff. We need to erase fractional bits to ensure
708 // that they do not conflict with BG coeffs. This is only
709 // strictly necessary for ROI coeffs. which non-fractional
710 // magnitude is zero, but much better BG quality can be
711 // achieved if done if reset to zero since coding zeros is
712 // much more efficient (the entropy coder knows nothing
713 // about ROI and cannot avoid coding the ROI fractional
714 // bits, otherwise this would not be necessary).
715 data[i] = (unchecked((int) 0x80000000) & tmp) | (tmp & bitMask);
716 nROIcoeff++;
717 }
718 else
719 {
720 // BG coeff. it is not necessary to erase fractional bits
721 data[i] = (unchecked((int) 0x80000000) & tmp) | ((tmp & 0x7FFFFFFF) >> maxBits);
722 }
723 }
724 i -= wrap;
725 }
726  
727 // Modify the number of significant bit-planes in the code-block
728 cblk.magbits += maxBits;
729  
730 // Store the number of ROI coefficients present in the code-block
731 cblk.nROIcoeff = nROIcoeff;
732  
733 return cblk;
734 }
735  
736 /// <summary> This function returns the flag indicating if any ROI functionality used
737 ///
738 /// </summary>
739 /// <returns> Flag indicating whether there are ROIs in the image
740 /// </returns>
741 public virtual bool useRoi()
742 {
743 return roi;
744 }
745  
746 /// <summary> Changes the current tile, given the new indexes. An
747 /// IllegalArgumentException is thrown if the indexes do not
748 /// correspond to a valid tile.
749 ///
750 /// </summary>
751 /// <param name="x">The horizontal index of the tile.
752 ///
753 /// </param>
754 /// <param name="y">The vertical index of the new tile.
755 ///
756 /// </param>
757 public override void setTile(int x, int y)
758 {
759 base.setTile(x, y);
760 if (roi)
761 mg.tileChanged();
762 }
763  
764 /// <summary> Advances to the next tile, in standard scan-line order (by rows then
765 /// columns). An NoNextElementException is thrown if the current tile is
766 /// the last one (i.e. there is no next tile).
767 ///
768 /// </summary>
769 public override void nextTile()
770 {
771 base.nextTile();
772 if (roi)
773 mg.tileChanged();
774 }
775  
776 /// <summary> Calculates the maximum amount of magnitude bits for each
777 /// tile-component, and stores it in the 'maxMagBits' array. This is called
778 /// by the constructor
779 ///
780 /// </summary>
781 /// <param name="encSpec">The encoder specifications for addition of roi specs
782 ///
783 /// </param>
784 private void calcMaxMagBits(EncoderSpecs encSpec)
785 {
786 int tmp;
787 MaxShiftSpec rois = encSpec.rois;
788  
789 int nt = src.getNumTiles();
790 int nc = src.NumComps;
791  
792 maxMagBits = new int[nt][];
793 for (int i = 0; i < nt; i++)
794 {
795 maxMagBits[i] = new int[nc];
796 }
797  
798 src.setTile(0, 0);
799 for (int t = 0; t < nt; t++)
800 {
801 for (int c = nc - 1; c >= 0; c--)
802 {
803 tmp = src.getMaxMagBits(c);
804 maxMagBits[t][c] = tmp;
805 rois.setTileCompVal(t, c, (System.Object) tmp);
806 }
807 if (t < nt - 1)
808 src.nextTile();
809 }
810 // Reset to current initial tile position
811 src.setTile(0, 0);
812 }
813 }
814 }