corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * CVS identifier:
3 *
4 * $Id: HeaderEncoder.java,v 1.43 2001/10/12 09:02:14 grosbois Exp $
5 *
6 * Class: HeaderEncoder
7 *
8 * Description: Write codestream headers.
9 *
10 *
11 *
12 * COPYRIGHT:
13 *
14 * This software module was originally developed by Raphaël Grosbois and
15 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
16 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
17 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
18 * Centre France S.A) in the course of development of the JPEG2000
19 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
20 * software module is an implementation of a part of the JPEG 2000
21 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
22 * Systems AB and Canon Research Centre France S.A (collectively JJ2000
23 * Partners) agree not to assert against ISO/IEC and users of the JPEG
24 * 2000 Standard (Users) any of their rights under the copyright, not
25 * including other intellectual property rights, for this software module
26 * with respect to the usage by ISO/IEC and Users of this software module
27 * or modifications thereof for use in hardware or software products
28 * claiming conformance to the JPEG 2000 Standard. Those intending to use
29 * this software module in hardware or software products are advised that
30 * their use may infringe existing patents. The original developers of
31 * this software module, JJ2000 Partners and ISO/IEC assume no liability
32 * for use of this software module or modifications thereof. No license
33 * or right to this software module is granted for non JPEG 2000 Standard
34 * conforming products. JJ2000 Partners have full right to use this
35 * software module for his/her own purpose, assign or donate this
36 * software module to any third party and to inhibit third parties from
37 * using this software module for non JPEG 2000 Standard conforming
38 * products. This copyright notice must be included in all copies or
39 * derivative works of this software module.
40 *
41 * Copyright (c) 1999/2000 JJ2000 Partners.
42 * */
43 using System;
44 using CSJ2K.j2k.quantization.quantizer;
45 using CSJ2K.j2k.wavelet.analysis;
46 using CSJ2K.j2k.entropy.encoder;
47 using CSJ2K.j2k.quantization;
48 using CSJ2K.j2k.image.input;
49 using CSJ2K.j2k.roi.encoder;
50 using CSJ2K.j2k.codestream;
51 using CSJ2K.j2k.wavelet;
52 using CSJ2K.j2k.encoder;
53 using CSJ2K.j2k.entropy;
54 using CSJ2K.j2k.image;
55 using CSJ2K.j2k.util;
56 using CSJ2K.j2k.io;
57 using CSJ2K.j2k;
58 namespace CSJ2K.j2k.codestream.writer
59 {
60  
61 /// <summary> This class writes almost of the markers and marker segments in main header
62 /// and in tile-part headers. It is created by the run() method of the Encoder
63 /// instance.
64 ///
65 /// <p>A marker segment includes a marker and eventually marker segment
66 /// parameters. It is designed by the three letter code of the marker
67 /// associated with the marker segment. JPEG 2000 part I defines 6 types of
68 /// markers:
69 /// <ul>
70 /// <li>Delimiting : SOC,SOT,SOD,EOC (written in FileCodestreamWriter).</li>
71 /// <li>Fixed information: SIZ.</li>
72 /// <li>Functional: COD,COC,RGN,QCD,QCC,POC.</li>
73 /// <li> In bit-stream: SOP,EPH.</li>
74 /// <li> Pointer: TLM,PLM,PLT,PPM,PPT.</li>
75 /// <li> Informational: CRG,COM.</li>
76 /// </ul></p>
77 ///
78 /// <p>Main Header is written when Encoder instance calls encodeMainHeader
79 /// whereas tile-part headers are written when the EBCOTRateAllocator instance
80 /// calls encodeTilePartHeader.</p>
81 ///
82 /// </summary>
83 /// <seealso cref="Encoder">
84 /// </seealso>
85 /// <seealso cref="Markers">
86 /// </seealso>
87 /// <seealso cref="EBCOTRateAllocator">
88 ///
89 /// </seealso>
90 public class HeaderEncoder
91 {
92 /// <summary> Returns the parameters that are used in this class and implementing
93 /// classes. It returns a 2D String array. Each of the 1D arrays is for a
94 /// different option, and they have 3 elements. The first element is the
95 /// option name, the second one is the synopsis, the third one is a long
96 /// description of what the parameter is and the fourth is its default
97 /// value. The synopsis or description may be 'null', in which case it is
98 /// assumed that there is no synopsis or description of the option,
99 /// respectively. Null may be returned if no options are supported.
100 ///
101 /// </summary>
102 /// <returns> the options name, their synopsis and their explanation, or null
103 /// if no options are supported.
104 ///
105 /// </returns>
106 public static System.String[][] ParameterInfo
107 {
108 get
109 {
110 return pinfo;
111 }
112  
113 }
114 /// <summary> Returns the byte-buffer used to store the codestream header.
115 ///
116 /// </summary>
117 /// <returns> A byte array countaining codestream header
118 ///
119 /// </returns>
120 virtual protected internal byte[] Buffer
121 {
122 get
123 {
124 return baos.ToArray();
125 }
126  
127 }
128 /// <summary> Returns the length of the header.
129 ///
130 /// </summary>
131 /// <returns> The length of the header in bytes
132 ///
133 /// </returns>
134 virtual public int Length
135 {
136 get
137 {
138 return (int)hbuf.BaseStream.Length;
139 }
140  
141 }
142 /// <summary> Returns the number of bytes used in the codestream header's buffer.
143 ///
144 /// </summary>
145 /// <returns> Header length in buffer (without any header overhead)
146 ///
147 /// </returns>
148 virtual protected internal int BufferLength
149 {
150 get
151 {
152 return (int)baos.Length;
153 }
154  
155 }
156  
157 /// <summary>The prefix for the header encoder options: 'H' </summary>
158 public const char OPT_PREFIX = 'H';
159  
160 /// <summary>The list of parameters that are accepted for the header encoder
161 /// module. Options for this modules start with 'H'.
162 /// </summary>
163 //UPGRADE_NOTE: Final was removed from the declaration of 'pinfo'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
164 private static readonly System.String[][] pinfo = new System.String[][]{new System.String[]{"Hjj2000_COM", null, "Writes or not the JJ2000 COM marker in the " + "codestream", "off"}, new System.String[]{"HCOM", "<Comment 1>[#<Comment 2>[#<Comment3...>]]", "Adds COM marker segments in the codestream. Comments must be " + "separated with '#' and are written into distinct maker segments.", null}};
165  
166 /// <summary>Nominal range bit of the component defining default values in QCD for
167 /// main header
168 /// </summary>
169 private int defimgn;
170  
171 /// <summary>Nominal range bit of the component defining default values in QCD for
172 /// tile headers
173 /// </summary>
174 private int deftilenr;
175  
176 /// <summary>The number of components in the image </summary>
177 private int nComp;
178  
179 /// <summary>Whether or not to write the JJ2000 COM marker segment </summary>
180 private bool enJJ2KMarkSeg = true;
181  
182 /// <summary>Other COM marker segments specified in the command line </summary>
183 private System.String otherCOMMarkSeg = null;
184  
185 /// <summary>The ByteArrayOutputStream to store header data. This handler is kept
186 /// in order to use methods not accessible from a general
187 /// DataOutputStream. For the other methods, it's better to use variable
188 /// hbuf.
189 ///
190 /// </summary>
191 /// <seealso cref="hbuf">
192 /// </seealso>
193 protected internal System.IO.MemoryStream baos;
194  
195 /// <summary>The DataOutputStream to store header data. This kind of object is
196 /// useful to write short, int, .... It's constructor takes baos as
197 /// parameter.
198 ///
199 /// </summary>
200 /// <seealso cref="baos">
201 ///
202 /// </seealso>
203 //UPGRADE_TODO: Class 'java.io.DataOutputStream' was converted to 'System.IO.BinaryWriter' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioDataOutputStream'"
204 protected internal System.IO.BinaryWriter hbuf;
205  
206 /// <summary>The image data reader. Source of original data info </summary>
207 protected internal ImgData origSrc;
208  
209 /// <summary>An array specifying, for each component,if the data was signed or not
210 ///
211 /// </summary>
212 protected internal bool[] isOrigSig;
213  
214 /// <summary>Reference to the rate allocator </summary>
215 protected internal PostCompRateAllocator ralloc;
216  
217 /// <summary>Reference to the DWT module </summary>
218 protected internal ForwardWT dwt;
219  
220 /// <summary>Reference to the tiler module </summary>
221 protected internal Tiler tiler;
222  
223 /// <summary>Reference to the ROI module </summary>
224 protected internal ROIScaler roiSc;
225  
226 /// <summary>The encoder specifications </summary>
227 protected internal EncoderSpecs encSpec;
228  
229 /// <summary> Initializes the header writer with the references to the coding chain.
230 ///
231 /// </summary>
232 /// <param name="origsrc">The original image data (before any component mixing,
233 /// tiling, etc.)
234 ///
235 /// </param>
236 /// <param name="isorigsig">An array specifying for each component if it was
237 /// originally signed or not.
238 ///
239 /// </param>
240 /// <param name="dwt">The discrete wavelet transform module.
241 ///
242 /// </param>
243 /// <param name="tiler">The tiler module.
244 ///
245 /// </param>
246 /// <param name="encSpec">The encoder specifications
247 ///
248 /// </param>
249 /// <param name="roiSc">The ROI scaler module.
250 ///
251 /// </param>
252 /// <param name="ralloc">The post compression rate allocator.
253 ///
254 /// </param>
255 /// <param name="pl">ParameterList instance.
256 ///
257 /// </param>
258 public HeaderEncoder(ImgData origsrc, bool[] isorigsig, ForwardWT dwt, Tiler tiler, EncoderSpecs encSpec, ROIScaler roiSc, PostCompRateAllocator ralloc, ParameterList pl)
259 {
260 pl.checkList(OPT_PREFIX, CSJ2K.j2k.util.ParameterList.toNameArray(pinfo));
261 if (origsrc.NumComps != isorigsig.Length)
262 {
263 throw new System.ArgumentException();
264 }
265 this.origSrc = origsrc;
266 this.isOrigSig = isorigsig;
267 this.dwt = dwt;
268 this.tiler = tiler;
269 this.encSpec = encSpec;
270 this.roiSc = roiSc;
271 this.ralloc = ralloc;
272  
273 baos = new System.IO.MemoryStream();
274 //UPGRADE_TODO: Class 'java.io.DataOutputStream' was converted to 'System.IO.BinaryWriter' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioDataOutputStream'"
275 hbuf = new CSJ2K.Util.EndianBinaryWriter(baos, true);
276 nComp = origsrc.NumComps;
277 enJJ2KMarkSeg = pl.getBooleanParameter("Hjj2000_COM");
278 otherCOMMarkSeg = pl.getParameter("HCOM");
279 }
280  
281 /// <summary> Resets the contents of this HeaderEncoder to its initial state. It
282 /// erases all the data in the header buffer and reactualizes the
283 /// headerLength field of the bit stream writer.
284 ///
285 /// </summary>
286 public virtual void reset()
287 {
288 //UPGRADE_ISSUE: Method 'java.io.ByteArrayOutputStream.reset' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javaioByteArrayOutputStreamreset'"
289 // CONVERSION PROBLEM?
290 //baos.reset();
291 baos.SetLength(0);
292 //UPGRADE_TODO: Class 'java.io.DataOutputStream' was converted to 'System.IO.BinaryWriter' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioDataOutputStream'"
293 hbuf = new CSJ2K.Util.EndianBinaryWriter(baos, true); //new System.IO.BinaryWriter(baos);
294 }
295  
296 /// <summary> Writes the header to the specified BinaryDataOutput.
297 ///
298 /// </summary>
299 /// <param name="out">Where to write the header.
300 ///
301 /// </param>
302 public virtual void writeTo(BinaryDataOutput out_Renamed)
303 {
304 int i, len;
305 byte[] buf;
306  
307 buf = Buffer;
308 len = Length;
309  
310 for (i = 0; i < len; i++)
311 {
312 out_Renamed.writeByte(buf[i]);
313 }
314 }
315  
316 /// <summary> Writes the header to the specified OutputStream.
317 ///
318 /// </summary>
319 /// <param name="out">Where to write the header.
320 ///
321 /// </param>
322 public virtual void writeTo(System.IO.Stream out_Renamed)
323 {
324 out_Renamed.Write(Buffer, 0, BufferLength);
325 }
326  
327 /// <summary> Start Of Codestream marker (SOC) signalling the beginning of a
328 /// codestream.
329 ///
330 /// </summary>
331 private void writeSOC()
332 {
333 hbuf.Write((System.Int16) CSJ2K.j2k.codestream.Markers.SOC);
334 }
335  
336 /// <summary> Writes SIZ marker segment of the codestream header. It is a fixed
337 /// information marker segment containing informations about image and tile
338 /// sizes. It is required in the main header immediately after SOC marker
339 /// segment.
340 ///
341 /// </summary>
342 private void writeSIZ()
343 {
344 int tmp;
345  
346 // SIZ marker
347 hbuf.Write((System.Int16) CSJ2K.j2k.codestream.Markers.SIZ);
348  
349 // Lsiz (Marker length) corresponding to
350 // Lsiz(2 bytes)+Rsiz(2)+Xsiz(4)+Ysiz(4)+XOsiz(4)+YOsiz(4)+
351 // XTsiz(4)+YTsiz(4)+XTOsiz(4)+YTOsiz(4)+Csiz(2)+
352 // (Ssiz(1)+XRsiz(1)+YRsiz(1))*nComp
353 // markSegLen = 38 + 3*nComp;
354 int markSegLen = 38 + 3 * nComp;
355 hbuf.Write((System.Int16) markSegLen);
356  
357 // Rsiz (codestream capabilities)
358 hbuf.Write((System.Int16) 0); // JPEG 2000 - Part I
359  
360 // Xsiz (original image width)
361 hbuf.Write(tiler.ImgWidth + tiler.ImgULX);
362  
363 // Ysiz (original image height)
364 hbuf.Write(tiler.ImgHeight + tiler.ImgULY);
365  
366 // XOsiz (horizontal offset from the origin of the reference
367 // grid to the left side of the image area)
368 hbuf.Write(tiler.ImgULX);
369  
370 // YOsiz (vertical offset from the origin of the reference
371 // grid to the top side of the image area)
372 hbuf.Write(tiler.ImgULY);
373  
374 // XTsiz (nominal tile width)
375 hbuf.Write(tiler.NomTileWidth);
376  
377 // YTsiz (nominal tile height)
378 hbuf.Write(tiler.NomTileHeight);
379  
380 Coord torig = tiler.getTilingOrigin(null);
381 // XTOsiz (Horizontal offset from the origin of the reference
382 // grid to the left side of the first tile)
383 hbuf.Write(torig.x);
384  
385 // YTOsiz (Vertical offset from the origin of the reference
386 // grid to the top side of the first tile)
387 hbuf.Write(torig.y);
388  
389 // Csiz (number of components)
390 hbuf.Write((System.Int16) nComp);
391  
392 // Bit-depth and downsampling factors.
393 for (int c = 0; c < nComp; c++)
394 {
395 // Loop on each component
396  
397 // Ssiz bit-depth before mixing
398 tmp = origSrc.getNomRangeBits(c) - 1;
399  
400 tmp |= ((isOrigSig[c]?1:0) << CSJ2K.j2k.codestream.Markers.SSIZ_DEPTH_BITS);
401 hbuf.Write((System.Byte) tmp);
402  
403 // XRsiz (component sub-sampling value x-wise)
404 hbuf.Write((System.Byte) tiler.getCompSubsX(c));
405  
406 // YRsiz (component sub-sampling value y-wise)
407 hbuf.Write((System.Byte) tiler.getCompSubsY(c));
408 } // End loop on each component
409 }
410  
411 /// <summary> Writes COD marker segment. COD is a functional marker segment
412 /// containing the code style default (coding style, decomposition,
413 /// layering) used for compressing all the components in an image.
414 ///
415 /// <p>The values can be overriden for an individual component by a COC
416 /// marker in either the main or the tile header.</p>
417 ///
418 /// </summary>
419 /// <param name="mh">Flag indicating whether this marker belongs to the main
420 /// header
421 ///
422 /// </param>
423 /// <param name="tileIdx">Tile index if the marker belongs to a tile-part header
424 ///
425 /// </param>
426 /// <seealso cref="writeCOC">
427 ///
428 /// </seealso>
429 protected internal virtual void writeCOD(bool mh, int tileIdx)
430 {
431 AnWTFilter[][] filt;
432 bool precinctPartitionUsed;
433 int tmp;
434 int mrl = 0, a = 0;
435 int ppx = 0, ppy = 0;
436 Progression[] prog;
437  
438 if (mh)
439 {
440 mrl = ((System.Int32) encSpec.dls.getDefault());
441 // get default precinct size
442 ppx = encSpec.pss.getPPX(- 1, - 1, mrl);
443 ppy = encSpec.pss.getPPY(- 1, - 1, mrl);
444 prog = (Progression[]) (encSpec.pocs.getDefault());
445 }
446 else
447 {
448 mrl = ((System.Int32) encSpec.dls.getTileDef(tileIdx));
449 // get precinct size for specified tile
450 ppx = encSpec.pss.getPPX(tileIdx, - 1, mrl);
451 ppy = encSpec.pss.getPPY(tileIdx, - 1, mrl);
452 prog = (Progression[]) (encSpec.pocs.getTileDef(tileIdx));
453 }
454  
455 if (ppx != CSJ2K.j2k.codestream.Markers.PRECINCT_PARTITION_DEF_SIZE || ppy != CSJ2K.j2k.codestream.Markers.PRECINCT_PARTITION_DEF_SIZE)
456 {
457 precinctPartitionUsed = true;
458 }
459 else
460 {
461 precinctPartitionUsed = false;
462 }
463  
464 if (precinctPartitionUsed)
465 {
466 // If precinct partition is used we add one byte per resolution
467 // level i.e. mrl+1 (+1 for resolution 0).
468 a = mrl + 1;
469 }
470  
471 // Write COD marker
472 hbuf.Write((System.Int16) CSJ2K.j2k.codestream.Markers.COD);
473  
474 // Lcod (marker segment length (in bytes)) Basic : Lcod(2
475 // bytes)+Scod(1)+SGcod(4)+SPcod(5+a) where:
476 // a=0 if no precinct partition is used
477 // a=mrl+1 if precinct partition used
478 int markSegLen = 12 + a;
479 hbuf.Write((System.Int16) markSegLen);
480  
481 // Scod (coding style parameter)
482 tmp = 0;
483 if (precinctPartitionUsed)
484 {
485 tmp = CSJ2K.j2k.codestream.Markers.SCOX_PRECINCT_PARTITION;
486 }
487  
488 // Are SOP markers used ?
489 if (mh)
490 {
491 //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Object.toString' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
492 if (((System.String) encSpec.sops.getDefault().ToString()).ToUpper().Equals("on".ToUpper()))
493 {
494 tmp |= CSJ2K.j2k.codestream.Markers.SCOX_USE_SOP;
495 }
496 }
497 else
498 {
499 //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Object.toString' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
500 if (((System.String) encSpec.sops.getTileDef(tileIdx).ToString()).ToUpper().Equals("on".ToUpper()))
501 {
502 tmp |= CSJ2K.j2k.codestream.Markers.SCOX_USE_SOP;
503 }
504 }
505  
506 // Are EPH markers used ?
507 if (mh)
508 {
509 //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Object.toString' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
510 if (((System.String) encSpec.ephs.getDefault().ToString()).ToUpper().Equals("on".ToUpper()))
511 {
512 tmp |= CSJ2K.j2k.codestream.Markers.SCOX_USE_EPH;
513 }
514 }
515 else
516 {
517 //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Object.toString' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
518 if (((System.String) encSpec.ephs.getTileDef(tileIdx).ToString()).ToUpper().Equals("on".ToUpper()))
519 {
520 tmp |= CSJ2K.j2k.codestream.Markers.SCOX_USE_EPH;
521 }
522 }
523 if (dwt.CbULX != 0)
524 tmp |= CSJ2K.j2k.codestream.Markers.SCOX_HOR_CB_PART;
525 if (dwt.CbULY != 0)
526 tmp |= CSJ2K.j2k.codestream.Markers.SCOX_VER_CB_PART;
527 hbuf.Write((System.Byte) tmp);
528  
529 // SGcod
530 // Progression order
531 hbuf.Write((System.Byte) prog[0].type);
532  
533 // Number of layers
534 hbuf.Write((System.Int16) ralloc.NumLayers);
535  
536 // Multiple component transform
537 // CSsiz (Color transform)
538 System.String str = null;
539 if (mh)
540 {
541 str = ((System.String) encSpec.cts.getDefault());
542 }
543 else
544 {
545 str = ((System.String) encSpec.cts.getTileDef(tileIdx));
546 }
547  
548 if (str.Equals("none"))
549 {
550 hbuf.Write((System.Byte) 0);
551 }
552 else
553 {
554 hbuf.Write((System.Byte) 1);
555 }
556  
557 // SPcod
558 // Number of decomposition levels
559 hbuf.Write((System.Byte) mrl);
560  
561 // Code-block width and height
562 if (mh)
563 {
564 // main header, get default values
565 tmp = encSpec.cblks.getCBlkWidth(ModuleSpec.SPEC_DEF, - 1, - 1);
566 hbuf.Write((System.Byte) (MathUtil.log2(tmp) - 2));
567 tmp = encSpec.cblks.getCBlkHeight(ModuleSpec.SPEC_DEF, - 1, - 1);
568 hbuf.Write((System.Byte) (MathUtil.log2(tmp) - 2));
569 }
570 else
571 {
572 // tile header, get tile default values
573 tmp = encSpec.cblks.getCBlkWidth(ModuleSpec.SPEC_TILE_DEF, tileIdx, - 1);
574 hbuf.Write((System.Byte) (MathUtil.log2(tmp) - 2));
575 tmp = encSpec.cblks.getCBlkHeight(ModuleSpec.SPEC_TILE_DEF, tileIdx, - 1);
576 hbuf.Write((System.Byte) (MathUtil.log2(tmp) - 2));
577 }
578  
579 // Style of the code-block coding passes
580 tmp = 0;
581 if (mh)
582 {
583 // Main header
584 // Selective arithmetic coding bypass ?
585 if (((System.String) encSpec.bms.getDefault()).Equals("on"))
586 {
587 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS;
588 }
589 // MQ reset after each coding pass ?
590 if (((System.String) encSpec.mqrs.getDefault()).Equals("on"))
591 {
592 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ;
593 }
594 // MQ termination after each arithmetically coded coding pass ?
595 if (((System.String) encSpec.rts.getDefault()).Equals("on"))
596 {
597 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS;
598 }
599 // Vertically stripe-causal context mode ?
600 if (((System.String) encSpec.css.getDefault()).Equals("on"))
601 {
602 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL;
603 }
604 // Predictable termination ?
605 if (((System.String) encSpec.tts.getDefault()).Equals("predict"))
606 {
607 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM;
608 }
609 // Error resilience segmentation symbol insertion ?
610 if (((System.String) encSpec.sss.getDefault()).Equals("on"))
611 {
612 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_SEG_SYMBOLS;
613 }
614 }
615 else
616 {
617 // Tile header
618 // Selective arithmetic coding bypass ?
619 if (((System.String) encSpec.bms.getTileDef(tileIdx)).Equals("on"))
620 {
621 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS;
622 }
623 // MQ reset after each coding pass ?
624 if (((System.String) encSpec.mqrs.getTileDef(tileIdx)).Equals("on"))
625 {
626 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ;
627 }
628 // MQ termination after each arithmetically coded coding pass ?
629 if (((System.String) encSpec.rts.getTileDef(tileIdx)).Equals("on"))
630 {
631 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS;
632 }
633 // Vertically stripe-causal context mode ?
634 if (((System.String) encSpec.css.getTileDef(tileIdx)).Equals("on"))
635 {
636 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL;
637 }
638 // Predictable termination ?
639 if (((System.String) encSpec.tts.getTileDef(tileIdx)).Equals("predict"))
640 {
641 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM;
642 }
643 // Error resilience segmentation symbol insertion ?
644 if (((System.String) encSpec.sss.getTileDef(tileIdx)).Equals("on"))
645 {
646 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_SEG_SYMBOLS;
647 }
648 }
649 hbuf.Write((System.Byte) tmp);
650  
651 // Wavelet transform
652 // Wavelet Filter
653 if (mh)
654 {
655 filt = ((AnWTFilter[][]) encSpec.wfs.getDefault());
656 hbuf.Write((System.Byte) filt[0][0].FilterType);
657 }
658 else
659 {
660 filt = ((AnWTFilter[][]) encSpec.wfs.getTileDef(tileIdx));
661 hbuf.Write((System.Byte) filt[0][0].FilterType);
662 }
663  
664 // Precinct partition
665 if (precinctPartitionUsed)
666 {
667 // Write the precinct size for each resolution level + 1
668 // (resolution 0) if precinct partition is used.
669 System.Collections.ArrayList[] v = null;
670 if (mh)
671 {
672 v = (System.Collections.ArrayList[]) encSpec.pss.getDefault();
673 }
674 else
675 {
676 v = (System.Collections.ArrayList[]) encSpec.pss.getTileDef(tileIdx);
677 }
678 for (int r = mrl; r >= 0; r--)
679 {
680 if (r >= v[1].Count)
681 {
682 tmp = ((System.Int32) v[1][v[1].Count - 1]);
683 }
684 else
685 {
686 tmp = ((System.Int32) v[1][r]);
687 }
688 int yExp = (MathUtil.log2(tmp) << 4) & 0x00F0;
689  
690 if (r >= v[0].Count)
691 {
692 tmp = ((System.Int32) v[0][v[0].Count - 1]);
693 }
694 else
695 {
696 tmp = ((System.Int32) v[0][r]);
697 }
698 int xExp = MathUtil.log2(tmp) & 0x000F;
699 hbuf.Write((System.Byte) (yExp | xExp));
700 }
701 }
702 }
703  
704 /// <summary> Writes COC marker segment . It is a functional marker containing the
705 /// coding style for one component (coding style, decomposition, layering).
706 ///
707 /// <p>Its values overrides any value previously set in COD in the main
708 /// header or in the tile header.</p>
709 ///
710 /// </summary>
711 /// <param name="mh">Flag indicating whether the main header is to be written.
712 ///
713 /// </param>
714 /// <param name="tileIdx">Tile index.
715 ///
716 /// </param>
717 /// <param name="compIdx">index of the component which need use of the COC marker
718 /// segment.
719 ///
720 /// </param>
721 /// <seealso cref="writeCOD">
722 ///
723 /// </seealso>
724 protected internal virtual void writeCOC(bool mh, int tileIdx, int compIdx)
725 {
726 AnWTFilter[][] filt;
727 bool precinctPartitionUsed;
728 int tmp;
729 int mrl = 0, a = 0;
730 int ppx = 0, ppy = 0;
731 Progression[] prog;
732  
733 if (mh)
734 {
735 mrl = ((System.Int32) encSpec.dls.getCompDef(compIdx));
736 // Get precinct size for specified component
737 ppx = encSpec.pss.getPPX(- 1, compIdx, mrl);
738 ppy = encSpec.pss.getPPY(- 1, compIdx, mrl);
739 prog = (Progression[]) (encSpec.pocs.getCompDef(compIdx));
740 }
741 else
742 {
743 mrl = ((System.Int32) encSpec.dls.getTileCompVal(tileIdx, compIdx));
744 // Get precinct size for specified component/tile
745 ppx = encSpec.pss.getPPX(tileIdx, compIdx, mrl);
746 ppy = encSpec.pss.getPPY(tileIdx, compIdx, mrl);
747 prog = (Progression[]) (encSpec.pocs.getTileCompVal(tileIdx, compIdx));
748 }
749  
750 if (ppx != CSJ2K.j2k.codestream.Markers.PRECINCT_PARTITION_DEF_SIZE || ppy != CSJ2K.j2k.codestream.Markers.PRECINCT_PARTITION_DEF_SIZE)
751 {
752 precinctPartitionUsed = true;
753 }
754 else
755 {
756 precinctPartitionUsed = false;
757 }
758 if (precinctPartitionUsed)
759 {
760 // If precinct partition is used we add one byte per resolution
761 // level i.e. mrl+1 (+1 for resolution 0).
762 a = mrl + 1;
763 }
764  
765 // COC marker
766 hbuf.Write((System.Int16) CSJ2K.j2k.codestream.Markers.COC);
767  
768 // Lcoc (marker segment length (in bytes))
769 // Basic: Lcoc(2 bytes)+Scoc(1)+ Ccoc(1 or 2)+SPcod(5+a)
770 int markSegLen = 8 + ((nComp < 257)?1:2) + a;
771  
772 // Rounded to the nearest even value greater or equals
773 hbuf.Write((System.Int16) markSegLen);
774  
775 // Ccoc
776 if (nComp < 257)
777 {
778 hbuf.Write((System.Byte) compIdx);
779 }
780 else
781 {
782 hbuf.Write((System.Int16) compIdx);
783 }
784  
785 // Scod (coding style parameter)
786 tmp = 0;
787 if (precinctPartitionUsed)
788 {
789 tmp = CSJ2K.j2k.codestream.Markers.SCOX_PRECINCT_PARTITION;
790 }
791 hbuf.Write((System.Byte) tmp);
792  
793  
794 // SPcoc
795  
796 // Number of decomposition levels
797 hbuf.Write((System.Byte) mrl);
798  
799 // Code-block width and height
800 if (mh)
801 {
802 // main header, get component default values
803 tmp = encSpec.cblks.getCBlkWidth(ModuleSpec.SPEC_COMP_DEF, - 1, compIdx);
804 hbuf.Write((System.Byte) (MathUtil.log2(tmp) - 2));
805 tmp = encSpec.cblks.getCBlkHeight(ModuleSpec.SPEC_COMP_DEF, - 1, compIdx);
806 hbuf.Write((System.Byte) (MathUtil.log2(tmp) - 2));
807 }
808 else
809 {
810 // tile header, get tile component values
811 tmp = encSpec.cblks.getCBlkWidth(ModuleSpec.SPEC_TILE_COMP, tileIdx, compIdx);
812 hbuf.Write((System.Byte) (MathUtil.log2(tmp) - 2));
813 tmp = encSpec.cblks.getCBlkHeight(ModuleSpec.SPEC_TILE_COMP, tileIdx, compIdx);
814 hbuf.Write((System.Byte) (MathUtil.log2(tmp) - 2));
815 }
816  
817 // Entropy coding mode options
818 tmp = 0;
819 if (mh)
820 {
821 // Main header
822 // Lazy coding mode ?
823 if (((System.String) encSpec.bms.getCompDef(compIdx)).Equals("on"))
824 {
825 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS;
826 }
827 // MQ reset after each coding pass ?
828 if (((System.String) encSpec.mqrs.getCompDef(compIdx)).ToUpper().Equals("on".ToUpper()))
829 {
830 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ;
831 }
832 // MQ termination after each arithmetically coded coding pass ?
833 if (((System.String) encSpec.rts.getCompDef(compIdx)).Equals("on"))
834 {
835 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS;
836 }
837 // Vertically stripe-causal context mode ?
838 if (((System.String) encSpec.css.getCompDef(compIdx)).Equals("on"))
839 {
840 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL;
841 }
842 // Predictable termination ?
843 if (((System.String) encSpec.tts.getCompDef(compIdx)).Equals("predict"))
844 {
845 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM;
846 }
847 // Error resilience segmentation symbol insertion ?
848 if (((System.String) encSpec.sss.getCompDef(compIdx)).Equals("on"))
849 {
850 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_SEG_SYMBOLS;
851 }
852 }
853 else
854 {
855 // Tile Header
856 if (((System.String) encSpec.bms.getTileCompVal(tileIdx, compIdx)).Equals("on"))
857 {
858 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS;
859 }
860 // MQ reset after each coding pass ?
861 if (((System.String) encSpec.mqrs.getTileCompVal(tileIdx, compIdx)).Equals("on"))
862 {
863 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ;
864 }
865 // MQ termination after each arithmetically coded coding pass ?
866 if (((System.String) encSpec.rts.getTileCompVal(tileIdx, compIdx)).Equals("on"))
867 {
868 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS;
869 }
870 // Vertically stripe-causal context mode ?
871 if (((System.String) encSpec.css.getTileCompVal(tileIdx, compIdx)).Equals("on"))
872 {
873 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL;
874 }
875 // Predictable termination ?
876 if (((System.String) encSpec.tts.getTileCompVal(tileIdx, compIdx)).Equals("predict"))
877 {
878 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM;
879 }
880 // Error resilience segmentation symbol insertion ?
881 if (((System.String) encSpec.sss.getTileCompVal(tileIdx, compIdx)).Equals("on"))
882 {
883 tmp |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_SEG_SYMBOLS;
884 }
885 }
886 hbuf.Write((System.Byte) tmp);
887  
888 // Wavelet transform
889 // Wavelet Filter
890 if (mh)
891 {
892 filt = ((AnWTFilter[][]) encSpec.wfs.getCompDef(compIdx));
893 hbuf.Write((System.Byte) filt[0][0].FilterType);
894 }
895 else
896 {
897 filt = ((AnWTFilter[][]) encSpec.wfs.getTileCompVal(tileIdx, compIdx));
898 hbuf.Write((System.Byte) filt[0][0].FilterType);
899 }
900  
901 // Precinct partition
902 if (precinctPartitionUsed)
903 {
904 // Write the precinct size for each resolution level + 1
905 // (resolution 0) if precinct partition is used.
906 System.Collections.ArrayList[] v = null;
907 if (mh)
908 {
909 v = (System.Collections.ArrayList[]) encSpec.pss.getCompDef(compIdx);
910 }
911 else
912 {
913 v = (System.Collections.ArrayList[]) encSpec.pss.getTileCompVal(tileIdx, compIdx);
914 }
915 for (int r = mrl; r >= 0; r--)
916 {
917 if (r >= v[1].Count)
918 {
919 tmp = ((System.Int32) v[1][v[1].Count - 1]);
920 }
921 else
922 {
923 tmp = ((System.Int32) v[1][r]);
924 }
925 int yExp = (MathUtil.log2(tmp) << 4) & 0x00F0;
926  
927 if (r >= v[0].Count)
928 {
929 tmp = ((System.Int32) v[0][v[0].Count - 1]);
930 }
931 else
932 {
933 tmp = ((System.Int32) v[0][r]);
934 }
935 int xExp = MathUtil.log2(tmp) & 0x000F;
936 hbuf.Write((System.Byte) (yExp | xExp));
937 }
938 }
939 }
940  
941 /// <summary> Writes QCD marker segment in main header. QCD is a functional marker
942 /// segment countaining the quantization default used for compressing all
943 /// the components in an image. The values can be overriden for an
944 /// individual component by a QCC marker in either the main or the tile
945 /// header.
946 ///
947 /// </summary>
948 protected internal virtual void writeMainQCD()
949 {
950 int mrl;
951 int qstyle;
952  
953 float step;
954  
955 System.String qType = (System.String) encSpec.qts.getDefault();
956 //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
957 float baseStep = (float) ((System.Single) encSpec.qsss.getDefault());
958 int gb = ((System.Int32) encSpec.gbs.getDefault());
959  
960 bool isDerived = qType.Equals("derived");
961 bool isReversible = qType.Equals("reversible");
962  
963 mrl = ((System.Int32) encSpec.dls.getDefault());
964  
965 int nt = dwt.getNumTiles();
966 int nc = dwt.NumComps;
967 int tmpI;
968 int[] tcIdx = new int[2];
969 System.String tmpStr;
970 bool notFound = true;
971 for (int t = 0; t < nt && notFound; t++)
972 {
973 for (int c = 0; c < nc && notFound; c++)
974 {
975 tmpI = ((System.Int32) encSpec.dls.getTileCompVal(t, c));
976 tmpStr = ((System.String) encSpec.qts.getTileCompVal(t, c));
977 if (tmpI == mrl && tmpStr.Equals(qType))
978 {
979 tcIdx[0] = t; tcIdx[1] = c;
980 notFound = false;
981 }
982 }
983 }
984 if (notFound)
985 {
986 throw new System.ApplicationException("Default representative for quantization type " + " and number of decomposition levels not found " + " in main QCD marker segment. " + "You have found a JJ2000 bug.");
987 }
988 SubbandAn sb, csb, sbRoot = dwt.getAnSubbandTree(tcIdx[0], tcIdx[1]);
989 defimgn = dwt.getNomRangeBits(tcIdx[1]);
990  
991 int nqcd; // Number of quantization step-size to transmit
992  
993 // Get the quantization style
994 qstyle = (isReversible)?CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION:((isDerived)?CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED:CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED);
995  
996 // QCD marker
997 hbuf.Write((System.Int16) CSJ2K.j2k.codestream.Markers.QCD);
998  
999 // Compute the number of steps to send
1000 switch (qstyle)
1001 {
1002  
1003 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED:
1004 nqcd = 1; // Just the LL value
1005 break;
1006  
1007 case CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION:
1008 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED:
1009 // One value per subband
1010 nqcd = 0;
1011  
1012 sb = sbRoot;
1013  
1014 // Get the subband at first resolution level
1015 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1016  
1017 // Count total number of subbands
1018 for (int j = 0; j <= mrl; j++)
1019 {
1020 csb = sb;
1021 while (csb != null)
1022 {
1023 nqcd++;
1024 csb = (SubbandAn) csb.nextSubband();
1025 }
1026 // Go up one resolution level
1027 sb = (SubbandAn) sb.NextResLevel;
1028 }
1029 break;
1030  
1031 default:
1032 throw new System.ApplicationException("Internal JJ2000 error");
1033  
1034 }
1035  
1036 // Lqcd (marker segment length (in bytes))
1037 // Lqcd(2 bytes)+Sqcd(1)+ SPqcd (2*Nqcd)
1038 int markSegLen = 3 + ((isReversible)?nqcd:2 * nqcd);
1039  
1040 // Rounded to the nearest even value greater or equals
1041 hbuf.Write((System.Int16) markSegLen);
1042  
1043 // Sqcd
1044 hbuf.Write((System.Byte) (qstyle + (gb << CSJ2K.j2k.codestream.Markers.SQCX_GB_SHIFT)));
1045  
1046 // SPqcd
1047 switch (qstyle)
1048 {
1049  
1050 case CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION:
1051 sb = sbRoot;
1052 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1053  
1054 // Output one exponent per subband
1055 for (int j = 0; j <= mrl; j++)
1056 {
1057 csb = sb;
1058 while (csb != null)
1059 {
1060 int tmp = (defimgn + csb.anGainExp);
1061 hbuf.Write((System.Byte) (tmp << CSJ2K.j2k.codestream.Markers.SQCX_EXP_SHIFT));
1062  
1063 csb = (SubbandAn) csb.nextSubband();
1064 // Go up one resolution level
1065 }
1066 sb = (SubbandAn) sb.NextResLevel;
1067 }
1068 break;
1069  
1070 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED:
1071 sb = sbRoot;
1072 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1073  
1074 // Calculate subband step (normalized to unit
1075 // dynamic range)
1076 step = baseStep / (1 << sb.level);
1077  
1078 // Write exponent-mantissa, 16 bits
1079 hbuf.Write((System.Int16) StdQuantizer.convertToExpMantissa(step));
1080 break;
1081  
1082 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED:
1083 sb = sbRoot;
1084 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1085  
1086 // Output one step per subband
1087 for (int j = 0; j <= mrl; j++)
1088 {
1089 csb = sb;
1090 while (csb != null)
1091 {
1092 // Calculate subband step (normalized to unit
1093 // dynamic range)
1094 step = baseStep / (csb.l2Norm * (1 << csb.anGainExp));
1095  
1096 // Write exponent-mantissa, 16 bits
1097 hbuf.Write((System.Int16) StdQuantizer.convertToExpMantissa(step));
1098  
1099 csb = (SubbandAn) csb.nextSubband();
1100 }
1101 // Go up one resolution level
1102 sb = (SubbandAn) sb.NextResLevel;
1103 }
1104 break;
1105  
1106 default:
1107 throw new System.ApplicationException("Internal JJ2000 error");
1108  
1109 }
1110 }
1111  
1112 /// <summary> Writes QCC marker segment in main header. It is a functional marker
1113 /// segment countaining the quantization used for compressing the specified
1114 /// component in an image. The values override for the specified component
1115 /// what was defined by a QCC marker in either the main or the tile header.
1116 ///
1117 /// </summary>
1118 /// <param name="compIdx">Index of the component which needs QCC marker segment.
1119 ///
1120 /// </param>
1121 protected internal virtual void writeMainQCC(int compIdx)
1122 {
1123  
1124 int mrl;
1125 int qstyle;
1126 int tIdx = 0;
1127 float step;
1128  
1129 SubbandAn sb, sb2;
1130 SubbandAn sbRoot;
1131  
1132 int imgnr = dwt.getNomRangeBits(compIdx);
1133 System.String qType = (System.String) encSpec.qts.getCompDef(compIdx);
1134 //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
1135 float baseStep = (float) ((System.Single) encSpec.qsss.getCompDef(compIdx));
1136 int gb = ((System.Int32) encSpec.gbs.getCompDef(compIdx));
1137  
1138 bool isReversible = qType.Equals("reversible");
1139 bool isDerived = qType.Equals("derived");
1140  
1141 mrl = ((System.Int32) encSpec.dls.getCompDef(compIdx));
1142  
1143 int nt = dwt.getNumTiles();
1144 int nc = dwt.NumComps;
1145 int tmpI;
1146 System.String tmpStr;
1147 bool notFound = true;
1148 for (int t = 0; t < nt && notFound; t++)
1149 {
1150 for (int c = 0; c < nc && notFound; c++)
1151 {
1152 tmpI = ((System.Int32) encSpec.dls.getTileCompVal(t, c));
1153 tmpStr = ((System.String) encSpec.qts.getTileCompVal(t, c));
1154 if (tmpI == mrl && tmpStr.Equals(qType))
1155 {
1156 tIdx = t;
1157 notFound = false;
1158 }
1159 }
1160 }
1161 if (notFound)
1162 {
1163 throw new System.ApplicationException("Default representative for quantization type " + " and number of decomposition levels not found " + " in main QCC (c=" + compIdx + ") marker segment. " + "You have found a JJ2000 bug.");
1164 }
1165 sbRoot = dwt.getAnSubbandTree(tIdx, compIdx);
1166  
1167 int nqcc; // Number of quantization step-size to transmit
1168  
1169 // Get the quantization style
1170 if (isReversible)
1171 {
1172 qstyle = CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION;
1173 }
1174 else if (isDerived)
1175 {
1176 qstyle = CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED;
1177 }
1178 else
1179 {
1180 qstyle = CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED;
1181 }
1182  
1183 // QCC marker
1184 hbuf.Write((System.Int16) CSJ2K.j2k.codestream.Markers.QCC);
1185  
1186 // Compute the number of steps to send
1187 switch (qstyle)
1188 {
1189  
1190 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED:
1191 nqcc = 1; // Just the LL value
1192 break;
1193  
1194 case CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION:
1195 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED:
1196 // One value per subband
1197 nqcc = 0;
1198  
1199 sb = sbRoot;
1200 mrl = sb.resLvl;
1201  
1202 // Get the subband at first resolution level
1203 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1204  
1205 // Find root element for LL subband
1206 while (sb.resLvl != 0)
1207 {
1208 sb = sb.subb_LL;
1209 }
1210  
1211 // Count total number of subbands
1212 for (int j = 0; j <= mrl; j++)
1213 {
1214 sb2 = sb;
1215 while (sb2 != null)
1216 {
1217 nqcc++;
1218 sb2 = (SubbandAn) sb2.nextSubband();
1219 }
1220 // Go up one resolution level
1221 sb = (SubbandAn) sb.NextResLevel;
1222 }
1223 break;
1224  
1225 default:
1226 throw new System.ApplicationException("Internal JJ2000 error");
1227  
1228 }
1229  
1230 // Lqcc (marker segment length (in bytes))
1231 // Lqcc(2 bytes)+Cqcc(1 or 2)+Sqcc(1)+ SPqcc (2*Nqcc)
1232 int markSegLen = 3 + ((nComp < 257)?1:2) + ((isReversible)?nqcc:2 * nqcc);
1233 hbuf.Write((System.Int16) markSegLen);
1234  
1235 // Cqcc
1236 if (nComp < 257)
1237 {
1238 hbuf.Write((System.Byte) compIdx);
1239 }
1240 else
1241 {
1242 hbuf.Write((System.Int16) compIdx);
1243 }
1244  
1245 // Sqcc (quantization style)
1246 hbuf.Write((System.Byte) (qstyle + (gb << CSJ2K.j2k.codestream.Markers.SQCX_GB_SHIFT)));
1247  
1248 // SPqcc
1249 switch (qstyle)
1250 {
1251  
1252 case CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION:
1253 // Get resolution level 0 subband
1254 sb = sbRoot;
1255 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1256  
1257 // Output one exponent per subband
1258 for (int j = 0; j <= mrl; j++)
1259 {
1260 sb2 = sb;
1261 while (sb2 != null)
1262 {
1263 int tmp = (imgnr + sb2.anGainExp);
1264 hbuf.Write((System.Byte) (tmp << CSJ2K.j2k.codestream.Markers.SQCX_EXP_SHIFT));
1265  
1266 sb2 = (SubbandAn) sb2.nextSubband();
1267 }
1268 // Go up one resolution level
1269 sb = (SubbandAn) sb.NextResLevel;
1270 }
1271 break;
1272  
1273 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED:
1274 // Get resolution level 0 subband
1275 sb = sbRoot;
1276 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1277  
1278 // Calculate subband step (normalized to unit
1279 // dynamic range)
1280 step = baseStep / (1 << sb.level);
1281  
1282 // Write exponent-mantissa, 16 bits
1283 hbuf.Write((System.Int16) StdQuantizer.convertToExpMantissa(step));
1284 break;
1285  
1286 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED:
1287 // Get resolution level 0 subband
1288 sb = sbRoot;
1289 mrl = sb.resLvl;
1290  
1291 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1292  
1293 for (int j = 0; j <= mrl; j++)
1294 {
1295 sb2 = sb;
1296 while (sb2 != null)
1297 {
1298 // Calculate subband step (normalized to unit
1299 // dynamic range)
1300 step = baseStep / (sb2.l2Norm * (1 << sb2.anGainExp));
1301  
1302 // Write exponent-mantissa, 16 bits
1303 hbuf.Write((System.Int16) StdQuantizer.convertToExpMantissa(step));
1304 sb2 = (SubbandAn) sb2.nextSubband();
1305 }
1306 // Go up one resolution level
1307 sb = (SubbandAn) sb.NextResLevel;
1308 }
1309 break;
1310  
1311 default:
1312 throw new System.ApplicationException("Internal JJ2000 error");
1313  
1314 }
1315 }
1316  
1317 /// <summary> Writes QCD marker segment in tile header. QCD is a functional marker
1318 /// segment countaining the quantization default used for compressing all
1319 /// the components in an image. The values can be overriden for an
1320 /// individual component by a QCC marker in either the main or the tile
1321 /// header.
1322 ///
1323 /// </summary>
1324 /// <param name="tIdx">Tile index
1325 ///
1326 /// </param>
1327 protected internal virtual void writeTileQCD(int tIdx)
1328 {
1329 int mrl;
1330 int qstyle;
1331  
1332 float step;
1333 SubbandAn sb, csb, sbRoot;
1334  
1335 System.String qType = (System.String) encSpec.qts.getTileDef(tIdx);
1336 //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
1337 float baseStep = (float) ((System.Single) encSpec.qsss.getTileDef(tIdx));
1338 mrl = ((System.Int32) encSpec.dls.getTileDef(tIdx));
1339  
1340 int nc = dwt.NumComps;
1341 int tmpI;
1342 System.String tmpStr;
1343 bool notFound = true;
1344 int compIdx = 0;
1345 for (int c = 0; c < nc && notFound; c++)
1346 {
1347 tmpI = ((System.Int32) encSpec.dls.getTileCompVal(tIdx, c));
1348 tmpStr = ((System.String) encSpec.qts.getTileCompVal(tIdx, c));
1349 if (tmpI == mrl && tmpStr.Equals(qType))
1350 {
1351 compIdx = c;
1352 notFound = false;
1353 }
1354 }
1355 if (notFound)
1356 {
1357 throw new System.ApplicationException("Default representative for quantization type " + " and number of decomposition levels not found " + " in tile QCD (t=" + tIdx + ") marker segment. " + "You have found a JJ2000 bug.");
1358 }
1359  
1360 sbRoot = dwt.getAnSubbandTree(tIdx, compIdx);
1361 deftilenr = dwt.getNomRangeBits(compIdx);
1362 int gb = ((System.Int32) encSpec.gbs.getTileDef(tIdx));
1363  
1364 bool isDerived = qType.Equals("derived");
1365 bool isReversible = qType.Equals("reversible");
1366  
1367 int nqcd; // Number of quantization step-size to transmit
1368  
1369 // Get the quantization style
1370 qstyle = (isReversible)?CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION:((isDerived)?CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED:CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED);
1371  
1372 // QCD marker
1373 hbuf.Write((System.Int16) CSJ2K.j2k.codestream.Markers.QCD);
1374  
1375 // Compute the number of steps to send
1376 switch (qstyle)
1377 {
1378  
1379 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED:
1380 nqcd = 1; // Just the LL value
1381 break;
1382  
1383 case CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION:
1384 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED:
1385 // One value per subband
1386 nqcd = 0;
1387  
1388 sb = sbRoot;
1389  
1390 // Get the subband at first resolution level
1391 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1392  
1393 // Count total number of subbands
1394 for (int j = 0; j <= mrl; j++)
1395 {
1396 csb = sb;
1397 while (csb != null)
1398 {
1399 nqcd++;
1400 csb = (SubbandAn) csb.nextSubband();
1401 }
1402 // Go up one resolution level
1403 sb = (SubbandAn) sb.NextResLevel;
1404 }
1405 break;
1406  
1407 default:
1408 throw new System.ApplicationException("Internal JJ2000 error");
1409  
1410 }
1411  
1412 // Lqcd (marker segment length (in bytes))
1413 // Lqcd(2 bytes)+Sqcd(1)+ SPqcd (2*Nqcd)
1414 int markSegLen = 3 + ((isReversible)?nqcd:2 * nqcd);
1415  
1416 // Rounded to the nearest even value greater or equals
1417 hbuf.Write((System.Int16) markSegLen);
1418  
1419 // Sqcd
1420 hbuf.Write((System.Byte) (qstyle + (gb << CSJ2K.j2k.codestream.Markers.SQCX_GB_SHIFT)));
1421  
1422 // SPqcd
1423 switch (qstyle)
1424 {
1425  
1426 case CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION:
1427 sb = sbRoot;
1428 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1429  
1430 // Output one exponent per subband
1431 for (int j = 0; j <= mrl; j++)
1432 {
1433 csb = sb;
1434 while (csb != null)
1435 {
1436 int tmp = (deftilenr + csb.anGainExp);
1437 hbuf.Write((System.Byte) (tmp << CSJ2K.j2k.codestream.Markers.SQCX_EXP_SHIFT));
1438  
1439 csb = (SubbandAn) csb.nextSubband();
1440 // Go up one resolution level
1441 }
1442 sb = (SubbandAn) sb.NextResLevel;
1443 }
1444 break;
1445  
1446 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED:
1447 sb = sbRoot;
1448 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1449  
1450 // Calculate subband step (normalized to unit
1451 // dynamic range)
1452 step = baseStep / (1 << sb.level);
1453  
1454 // Write exponent-mantissa, 16 bits
1455 hbuf.Write((System.Int16) StdQuantizer.convertToExpMantissa(step));
1456 break;
1457  
1458 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED:
1459 sb = sbRoot;
1460 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1461  
1462 // Output one step per subband
1463 for (int j = 0; j <= mrl; j++)
1464 {
1465 csb = sb;
1466 while (csb != null)
1467 {
1468 // Calculate subband step (normalized to unit
1469 // dynamic range)
1470 step = baseStep / (csb.l2Norm * (1 << csb.anGainExp));
1471  
1472 // Write exponent-mantissa, 16 bits
1473 hbuf.Write((System.Int16) StdQuantizer.convertToExpMantissa(step));
1474  
1475 csb = (SubbandAn) csb.nextSubband();
1476 }
1477 // Go up one resolution level
1478 sb = (SubbandAn) sb.NextResLevel;
1479 }
1480 break;
1481  
1482 default:
1483 throw new System.ApplicationException("Internal JJ2000 error");
1484  
1485 }
1486 }
1487  
1488 /// <summary> Writes QCC marker segment in tile header. It is a functional marker
1489 /// segment countaining the quantization used for compressing the specified
1490 /// component in an image. The values override for the specified component
1491 /// what was defined by a QCC marker in either the main or the tile header.
1492 ///
1493 /// </summary>
1494 /// <param name="t">Tile index
1495 ///
1496 /// </param>
1497 /// <param name="compIdx">Index of the component which needs QCC marker segment.
1498 ///
1499 /// </param>
1500 protected internal virtual void writeTileQCC(int t, int compIdx)
1501 {
1502  
1503 int mrl;
1504 int qstyle;
1505 float step;
1506  
1507 SubbandAn sb, sb2;
1508 int nqcc; // Number of quantization step-size to transmit
1509  
1510 SubbandAn sbRoot = dwt.getAnSubbandTree(t, compIdx);
1511 int imgnr = dwt.getNomRangeBits(compIdx);
1512 System.String qType = (System.String) encSpec.qts.getTileCompVal(t, compIdx);
1513 //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
1514 float baseStep = (float) ((System.Single) encSpec.qsss.getTileCompVal(t, compIdx));
1515 int gb = ((System.Int32) encSpec.gbs.getTileCompVal(t, compIdx));
1516  
1517 bool isReversible = qType.Equals("reversible");
1518 bool isDerived = qType.Equals("derived");
1519  
1520 mrl = ((System.Int32) encSpec.dls.getTileCompVal(t, compIdx));
1521  
1522 // Get the quantization style
1523 if (isReversible)
1524 {
1525 qstyle = CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION;
1526 }
1527 else if (isDerived)
1528 {
1529 qstyle = CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED;
1530 }
1531 else
1532 {
1533 qstyle = CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED;
1534 }
1535  
1536 // QCC marker
1537 hbuf.Write((System.Int16) CSJ2K.j2k.codestream.Markers.QCC);
1538  
1539 // Compute the number of steps to send
1540 switch (qstyle)
1541 {
1542  
1543 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED:
1544 nqcc = 1; // Just the LL value
1545 break;
1546  
1547 case CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION:
1548 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED:
1549 // One value per subband
1550 nqcc = 0;
1551  
1552 sb = sbRoot;
1553 mrl = sb.resLvl;
1554  
1555 // Get the subband at first resolution level
1556 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1557  
1558 // Find root element for LL subband
1559 while (sb.resLvl != 0)
1560 {
1561 sb = sb.subb_LL;
1562 }
1563  
1564 // Count total number of subbands
1565 for (int j = 0; j <= mrl; j++)
1566 {
1567 sb2 = sb;
1568 while (sb2 != null)
1569 {
1570 nqcc++;
1571 sb2 = (SubbandAn) sb2.nextSubband();
1572 }
1573 // Go up one resolution level
1574 sb = (SubbandAn) sb.NextResLevel;
1575 }
1576 break;
1577  
1578 default:
1579 throw new System.ApplicationException("Internal JJ2000 error");
1580  
1581 }
1582  
1583 // Lqcc (marker segment length (in bytes))
1584 // Lqcc(2 bytes)+Cqcc(1 or 2)+Sqcc(1)+ SPqcc (2*Nqcc)
1585 int markSegLen = 3 + ((nComp < 257)?1:2) + ((isReversible)?nqcc:2 * nqcc);
1586 hbuf.Write((System.Int16) markSegLen);
1587  
1588 // Cqcc
1589 if (nComp < 257)
1590 {
1591 hbuf.Write((System.Byte) compIdx);
1592 }
1593 else
1594 {
1595 hbuf.Write((System.Int16) compIdx);
1596 }
1597  
1598 // Sqcc (quantization style)
1599 hbuf.Write((System.Byte) (qstyle + (gb << CSJ2K.j2k.codestream.Markers.SQCX_GB_SHIFT)));
1600  
1601 // SPqcc
1602 switch (qstyle)
1603 {
1604  
1605 case CSJ2K.j2k.codestream.Markers.SQCX_NO_QUANTIZATION:
1606 // Get resolution level 0 subband
1607 sb = sbRoot;
1608 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1609  
1610 // Output one exponent per subband
1611 for (int j = 0; j <= mrl; j++)
1612 {
1613 sb2 = sb;
1614 while (sb2 != null)
1615 {
1616 int tmp = (imgnr + sb2.anGainExp);
1617 hbuf.Write((System.Byte) (tmp << CSJ2K.j2k.codestream.Markers.SQCX_EXP_SHIFT));
1618  
1619 sb2 = (SubbandAn) sb2.nextSubband();
1620 }
1621 // Go up one resolution level
1622 sb = (SubbandAn) sb.NextResLevel;
1623 }
1624 break;
1625  
1626 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_DERIVED:
1627 // Get resolution level 0 subband
1628 sb = sbRoot;
1629 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1630  
1631 // Calculate subband step (normalized to unit
1632 // dynamic range)
1633 step = baseStep / (1 << sb.level);
1634  
1635 // Write exponent-mantissa, 16 bits
1636 hbuf.Write((System.Int16) StdQuantizer.convertToExpMantissa(step));
1637 break;
1638  
1639 case CSJ2K.j2k.codestream.Markers.SQCX_SCALAR_EXPOUNDED:
1640 // Get resolution level 0 subband
1641 sb = sbRoot;
1642 mrl = sb.resLvl;
1643  
1644 sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1645  
1646 for (int j = 0; j <= mrl; j++)
1647 {
1648 sb2 = sb;
1649 while (sb2 != null)
1650 {
1651 // Calculate subband step (normalized to unit
1652 // dynamic range)
1653 step = baseStep / (sb2.l2Norm * (1 << sb2.anGainExp));
1654  
1655 // Write exponent-mantissa, 16 bits
1656 hbuf.Write((System.Int16) StdQuantizer.convertToExpMantissa(step));
1657 sb2 = (SubbandAn) sb2.nextSubband();
1658 }
1659 // Go up one resolution level
1660 sb = (SubbandAn) sb.NextResLevel;
1661 }
1662 break;
1663  
1664 default:
1665 throw new System.ApplicationException("Internal JJ2000 error");
1666  
1667 }
1668 }
1669  
1670 /// <summary> Writes POC marker segment. POC is a functional marker segment
1671 /// containing the bounds and progression order for any progression order
1672 /// other than default in the codestream.
1673 ///
1674 /// </summary>
1675 /// <param name="mh">Flag indicating whether the main header is to be written
1676 ///
1677 /// </param>
1678 /// <param name="tileIdx">Tile index
1679 ///
1680 /// </param>
1681 protected internal virtual void writePOC(bool mh, int tileIdx)
1682 {
1683 int markSegLen = 0; // Segment marker length
1684 int lenCompField; // Holds the size of any component field as
1685 // this size depends on the number of
1686 //components
1687 Progression[] prog = null; // Holds the progression(s)
1688 int npoc; // Number of progression order changes
1689  
1690 // Get the progression order changes, their number and checks
1691 // if it is ok
1692 if (mh)
1693 {
1694 prog = (Progression[]) (encSpec.pocs.getDefault());
1695 }
1696 else
1697 {
1698 prog = (Progression[]) (encSpec.pocs.getTileDef(tileIdx));
1699 }
1700  
1701 // Calculate the length of a component field (depends on the number of
1702 // components)
1703 lenCompField = (nComp < 257?1:2);
1704  
1705 // POC marker
1706 hbuf.Write((System.Int16) CSJ2K.j2k.codestream.Markers.POC);
1707  
1708 // Lpoc (marker segment length (in bytes))
1709 // Basic: Lpoc(2 bytes) + npoc * [ RSpoc(1) + CSpoc(1 or 2) +
1710 // LYEpoc(2) + REpoc(1) + CEpoc(1 or 2) + Ppoc(1) ]
1711 npoc = prog.Length;
1712 markSegLen = 2 + npoc * (1 + lenCompField + 2 + 1 + lenCompField + 1);
1713 hbuf.Write((System.Int16) markSegLen);
1714  
1715 // Write each progression order change
1716 for (int i = 0; i < npoc; i++)
1717 {
1718 // RSpoc(i)
1719 hbuf.Write((System.Byte) prog[i].rs);
1720 // CSpoc(i)
1721 if (lenCompField == 2)
1722 {
1723 hbuf.Write((System.Int16) prog[i].cs);
1724 }
1725 else
1726 {
1727 hbuf.Write((System.Byte) prog[i].cs);
1728 }
1729 // LYEpoc(i)
1730 hbuf.Write((System.Int16) prog[i].lye);
1731 // REpoc(i)
1732 hbuf.Write((System.Byte) prog[i].re);
1733 // CEpoc(i)
1734 if (lenCompField == 2)
1735 {
1736 hbuf.Write((System.Int16) prog[i].ce);
1737 }
1738 else
1739 {
1740 hbuf.Write((System.Byte) prog[i].ce);
1741 }
1742 // Ppoc(i)
1743 hbuf.Write((System.Byte) prog[i].type);
1744 }
1745 }
1746  
1747  
1748 /// <summary> Write main header. JJ2000 main header corresponds to the following
1749 /// sequence of marker segments:
1750 ///
1751 /// <ol>
1752 /// <li>SOC</li>
1753 /// <li>SIZ</li>
1754 /// <li>COD</li>
1755 /// <li>COC (if needed)</li>
1756 /// <li>QCD</li>
1757 /// <li>QCC (if needed)</li>
1758 /// <li>POC (if needed)</li>
1759 /// </ol>
1760 ///
1761 /// </summary>
1762 public virtual void encodeMainHeader()
1763 {
1764 int i;
1765  
1766  
1767 // +---------------------------------+
1768 // | SOC marker segment |
1769 // +---------------------------------+
1770 writeSOC();
1771  
1772 // +---------------------------------+
1773 // | Image and tile SIZe (SIZ) |
1774 // +---------------------------------+
1775 writeSIZ();
1776  
1777 // +-------------------------------+
1778 // | COding style Default (COD) |
1779 // +-------------------------------+
1780 bool isEresUsed = ((System.String) encSpec.tts.getDefault()).Equals("predict");
1781 writeCOD(true, 0);
1782  
1783 // +---------------------------------+
1784 // | COding style Component (COC) |
1785 // +---------------------------------+
1786 for (i = 0; i < nComp; i++)
1787 {
1788 bool isEresUsedinComp = ((System.String) encSpec.tts.getCompDef(i)).Equals("predict");
1789 if (encSpec.wfs.isCompSpecified(i) || encSpec.dls.isCompSpecified(i) || encSpec.bms.isCompSpecified(i) || encSpec.mqrs.isCompSpecified(i) || encSpec.rts.isCompSpecified(i) || encSpec.sss.isCompSpecified(i) || encSpec.css.isCompSpecified(i) || encSpec.pss.isCompSpecified(i) || encSpec.cblks.isCompSpecified(i) || (isEresUsed != isEresUsedinComp))
1790 // Some component non-default stuff => need COC
1791 writeCOC(true, 0, i);
1792 }
1793  
1794 // +-------------------------------+
1795 // | Quantization Default (QCD) |
1796 // +-------------------------------+
1797 writeMainQCD();
1798  
1799 // +-------------------------------+
1800 // | Quantization Component (QCC) |
1801 // +-------------------------------+
1802 // Write needed QCC markers
1803 for (i = 0; i < nComp; i++)
1804 {
1805 if (dwt.getNomRangeBits(i) != defimgn || encSpec.qts.isCompSpecified(i) || encSpec.qsss.isCompSpecified(i) || encSpec.dls.isCompSpecified(i) || encSpec.gbs.isCompSpecified(i))
1806 {
1807 writeMainQCC(i);
1808 }
1809 }
1810  
1811 // +--------------------------+
1812 // | POC maker segment |
1813 // +--------------------------+
1814 Progression[] prog = (Progression[]) (encSpec.pocs.getDefault());
1815 if (prog.Length > 1)
1816 writePOC(true, 0);
1817  
1818 // +---------------------------+
1819 // | Comments (COM) |
1820 // +---------------------------+
1821 writeCOM();
1822 }
1823  
1824 /// <summary> Write COM marker segment(s) to the codestream.
1825 ///
1826 /// <p>This marker is currently written in main header and indicates the
1827 /// JJ2000 encoder's version that has created the codestream.</p>
1828 ///
1829 /// </summary>
1830 private void writeCOM()
1831 {
1832 // JJ2000 COM marker segment
1833 if (enJJ2KMarkSeg)
1834 {
1835 System.String str = "Created by: CSJ2K version " + JJ2KInfo.version;
1836 int markSegLen; // the marker segment length
1837  
1838 // COM marker
1839 hbuf.Write((System.Int16) CSJ2K.j2k.codestream.Markers.COM);
1840  
1841 // Calculate length: Lcom(2) + Rcom (2) + string's length;
1842 markSegLen = 2 + 2 + str.Length;
1843 hbuf.Write((System.Int16) markSegLen);
1844  
1845 // Rcom
1846 hbuf.Write((System.Int16) 1); // General use (IS 8859-15:1999(Latin) values)
1847  
1848 byte[] chars = System.Text.ASCIIEncoding.ASCII.GetBytes(str);
1849 for (int i = 0; i < chars.Length; i++)
1850 {
1851 hbuf.Write((byte) chars[i]);
1852 }
1853 }
1854 // other COM marker segments
1855 if (otherCOMMarkSeg != null)
1856 {
1857 SupportClass.Tokenizer stk = new SupportClass.Tokenizer(otherCOMMarkSeg, "#");
1858 while (stk.HasMoreTokens())
1859 {
1860 System.String str = stk.NextToken();
1861 int markSegLen; // the marker segment length
1862  
1863 // COM marker
1864 hbuf.Write((System.Int16) CSJ2K.j2k.codestream.Markers.COM);
1865  
1866 // Calculate length: Lcom(2) + Rcom (2) + string's length;
1867 markSegLen = 2 + 2 + str.Length;
1868 hbuf.Write((System.Int16) markSegLen);
1869  
1870 // Rcom
1871 hbuf.Write((System.Int16) 1); // General use (IS 8859-15:1999(Latin)
1872 // values)
1873  
1874 byte[] chars = System.Text.ASCIIEncoding.ASCII.GetBytes(str);
1875 for (int i = 0; i < chars.Length; i++)
1876 {
1877 hbuf.Write((byte) chars[i]);
1878 }
1879 }
1880 }
1881 }
1882  
1883 /// <summary> Writes the RGN marker segment in the tile header. It describes the
1884 /// scaling value in each tile component
1885 ///
1886 /// <p>May be used in tile or main header. If used in main header, it
1887 /// refers to a ROI of the whole image, regardless of tiling. When used in
1888 /// tile header, only the particular tile is affected.</p>
1889 ///
1890 /// </summary>
1891 /// <param name="tIdx">The tile index
1892 ///
1893 /// </param>
1894 /// <exception cref="IOException">If an I/O error occurs while reading from the
1895 /// encoder header stream
1896 ///
1897 /// </exception>
1898 private void writeRGN(int tIdx)
1899 {
1900 int i;
1901 int markSegLen; // the marker length
1902  
1903 // Write one RGN marker per component
1904 for (i = 0; i < nComp; i++)
1905 {
1906 // RGN marker
1907 hbuf.Write((System.Int16) CSJ2K.j2k.codestream.Markers.RGN);
1908  
1909 // Calculate length (Lrgn)
1910 // Basic: Lrgn (2) + Srgn (1) + SPrgn + one byte
1911 // or two for component number
1912 markSegLen = 4 + ((nComp < 257)?1:2);
1913 hbuf.Write((System.Int16) markSegLen);
1914  
1915 // Write component (Crgn)
1916 if (nComp < 257)
1917 {
1918 hbuf.Write((System.Byte) i);
1919 }
1920 else
1921 {
1922 hbuf.Write((System.Int16) i);
1923 }
1924  
1925 // Write type of ROI (Srgn)
1926 hbuf.Write((System.Byte) CSJ2K.j2k.codestream.Markers.SRGN_IMPLICIT);
1927  
1928 // Write ROI info (SPrgn)
1929 hbuf.Write((System.Byte) ((System.Int32) (encSpec.rois.getTileCompVal(tIdx, i))));
1930 }
1931 }
1932 /// <summary> Writes tile-part header. JJ2000 tile-part header corresponds to the
1933 /// following sequence of marker segments:
1934 ///
1935 /// <ol>
1936 /// <li>SOT</li>
1937 /// <li>COD (if needed)</li>
1938 /// <li>COC (if needed)</li>
1939 /// <li>QCD (if needed)</li>
1940 /// <li>QCC (if needed)</li>
1941 /// <li>RGN (if needed)</li>
1942 /// <li>POC (if needed)</li>
1943 /// <li>SOD</li>
1944 /// </ol>
1945 ///
1946 /// </summary>
1947 /// <param name="length">The length of the current tile-part.
1948 ///
1949 /// </param>
1950 /// <param name="tileIdx">Index of the tile to write
1951 ///
1952 /// </param>
1953 public virtual void encodeTilePartHeader(int tileLength, int tileIdx)
1954 {
1955  
1956 int tmp;
1957 Coord numTiles = ralloc.getNumTiles(null);
1958 ralloc.setTile(tileIdx % numTiles.x, tileIdx / numTiles.x);
1959  
1960 // +--------------------------+
1961 // | SOT maker segment |
1962 // +--------------------------+
1963 // SOT marker
1964 hbuf.Write((System.Byte) SupportClass.URShift(CSJ2K.j2k.codestream.Markers.SOT, 8));
1965 hbuf.Write((System.Byte) (CSJ2K.j2k.codestream.Markers.SOT & 0x00FF));
1966  
1967 // Lsot (10 bytes)
1968 hbuf.Write((System.Byte) 0);
1969 hbuf.Write((System.Byte) 10);
1970  
1971 // Isot
1972 if (tileIdx > 65534)
1973 {
1974 throw new System.ArgumentException("Trying to write a tile-part " + "header whose tile index is " + "too high");
1975 }
1976 hbuf.Write((System.Byte) (tileIdx >> 8));
1977 hbuf.Write((System.Byte) tileIdx);
1978  
1979 // Psot
1980 tmp = tileLength;
1981 hbuf.Write((System.Byte) (tmp >> 24));
1982 hbuf.Write((System.Byte) (tmp >> 16));
1983 hbuf.Write((System.Byte) (tmp >> 8));
1984 hbuf.Write((System.Byte) tmp);
1985  
1986 // TPsot
1987 hbuf.Write((System.Byte) 0); // Only one tile-part currently supported !
1988  
1989 // TNsot
1990 hbuf.Write((System.Byte) 1); // Only one tile-part currently supported !
1991  
1992 // +--------------------------+
1993 // | COD maker segment |
1994 // +--------------------------+
1995 bool isEresUsed = ((System.String) encSpec.tts.getDefault()).Equals("predict");
1996 bool isEresUsedInTile = ((System.String) encSpec.tts.getTileDef(tileIdx)).Equals("predict");
1997 bool tileCODwritten = false;
1998 if (encSpec.wfs.isTileSpecified(tileIdx) || encSpec.cts.isTileSpecified(tileIdx) || encSpec.dls.isTileSpecified(tileIdx) || encSpec.bms.isTileSpecified(tileIdx) || encSpec.mqrs.isTileSpecified(tileIdx) || encSpec.rts.isTileSpecified(tileIdx) || encSpec.css.isTileSpecified(tileIdx) || encSpec.pss.isTileSpecified(tileIdx) || encSpec.sops.isTileSpecified(tileIdx) || encSpec.sss.isTileSpecified(tileIdx) || encSpec.pocs.isTileSpecified(tileIdx) || encSpec.ephs.isTileSpecified(tileIdx) || encSpec.cblks.isTileSpecified(tileIdx) || (isEresUsed != isEresUsedInTile))
1999 {
2000 writeCOD(false, tileIdx);
2001 tileCODwritten = true;
2002 }
2003  
2004 // +--------------------------+
2005 // | COC maker segment |
2006 // +--------------------------+
2007 for (int c = 0; c < nComp; c++)
2008 {
2009 bool isEresUsedInTileComp = ((System.String) encSpec.tts.getTileCompVal(tileIdx, c)).Equals("predict");
2010  
2011 if (encSpec.wfs.isTileCompSpecified(tileIdx, c) || encSpec.dls.isTileCompSpecified(tileIdx, c) || encSpec.bms.isTileCompSpecified(tileIdx, c) || encSpec.mqrs.isTileCompSpecified(tileIdx, c) || encSpec.rts.isTileCompSpecified(tileIdx, c) || encSpec.css.isTileCompSpecified(tileIdx, c) || encSpec.pss.isTileCompSpecified(tileIdx, c) || encSpec.sss.isTileCompSpecified(tileIdx, c) || encSpec.cblks.isTileCompSpecified(tileIdx, c) || (isEresUsedInTileComp != isEresUsed))
2012 {
2013 writeCOC(false, tileIdx, c);
2014 }
2015 else if (tileCODwritten)
2016 {
2017 if (encSpec.wfs.isCompSpecified(c) || encSpec.dls.isCompSpecified(c) || encSpec.bms.isCompSpecified(c) || encSpec.mqrs.isCompSpecified(c) || encSpec.rts.isCompSpecified(c) || encSpec.sss.isCompSpecified(c) || encSpec.css.isCompSpecified(c) || encSpec.pss.isCompSpecified(c) || encSpec.cblks.isCompSpecified(c) || (encSpec.tts.isCompSpecified(c) && ((System.String) encSpec.tts.getCompDef(c)).Equals("predict")))
2018 {
2019 writeCOC(false, tileIdx, c);
2020 }
2021 }
2022 }
2023  
2024 // +--------------------------+
2025 // | QCD maker segment |
2026 // +--------------------------+
2027 bool tileQCDwritten = false;
2028 if (encSpec.qts.isTileSpecified(tileIdx) || encSpec.qsss.isTileSpecified(tileIdx) || encSpec.dls.isTileSpecified(tileIdx) || encSpec.gbs.isTileSpecified(tileIdx))
2029 {
2030 writeTileQCD(tileIdx);
2031 tileQCDwritten = true;
2032 }
2033 else
2034 {
2035 deftilenr = defimgn;
2036 }
2037  
2038 // +--------------------------+
2039 // | QCC maker segment |
2040 // +--------------------------+
2041 for (int c = 0; c < nComp; c++)
2042 {
2043 if (dwt.getNomRangeBits(c) != deftilenr || encSpec.qts.isTileCompSpecified(tileIdx, c) || encSpec.qsss.isTileCompSpecified(tileIdx, c) || encSpec.dls.isTileCompSpecified(tileIdx, c) || encSpec.gbs.isTileCompSpecified(tileIdx, c))
2044 {
2045 writeTileQCC(tileIdx, c);
2046 }
2047 else if (tileQCDwritten)
2048 {
2049 if (encSpec.qts.isCompSpecified(c) || encSpec.qsss.isCompSpecified(c) || encSpec.dls.isCompSpecified(c) || encSpec.gbs.isCompSpecified(c))
2050 {
2051 writeTileQCC(tileIdx, c);
2052 }
2053 }
2054 }
2055  
2056 // +--------------------------+
2057 // | RGN maker segment |
2058 // +--------------------------+
2059 if (roiSc.useRoi() && (!roiSc.BlockAligned))
2060 writeRGN(tileIdx);
2061  
2062 // +--------------------------+
2063 // | POC maker segment |
2064 // +--------------------------+
2065 Progression[] prog;
2066 if (encSpec.pocs.isTileSpecified(tileIdx))
2067 {
2068 prog = (Progression[]) (encSpec.pocs.getTileDef(tileIdx));
2069 if (prog.Length > 1)
2070 writePOC(false, tileIdx);
2071 }
2072  
2073 // +--------------------------+
2074 // | SOD maker |
2075 // +--------------------------+
2076 hbuf.Write((System.Byte) SupportClass.URShift(CSJ2K.j2k.codestream.Markers.SOD, 8));
2077 hbuf.Write((System.Byte) (CSJ2K.j2k.codestream.Markers.SOD & 0x00FF));
2078 }
2079 }
2080 }