corrade-vassal – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 1 | /* |
2 | * CVS identifier: |
||
3 | * |
||
4 | * $Id: StdEntropyCoder.java,v 1.41 2002/07/04 15:53:32 grosbois Exp $ |
||
5 | * |
||
6 | * Class: StdEntropyCoder |
||
7 | * |
||
8 | * Description: Entropy coding engine of stripes in code-blocks |
||
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.codestream; |
||
47 | using CSJ2K.j2k.wavelet; |
||
48 | using CSJ2K.j2k.encoder; |
||
49 | using CSJ2K.j2k.entropy; |
||
50 | using CSJ2K.j2k.image; |
||
51 | using CSJ2K.j2k.util; |
||
52 | using CSJ2K.j2k.io; |
||
53 | using CSJ2K.j2k; |
||
54 | namespace CSJ2K.j2k.entropy.encoder |
||
55 | { |
||
56 | |||
57 | /// <summary> This class implements the JPEG 2000 entropy coder, which codes stripes in |
||
58 | /// code-blocks. This entropy coding engine can function in a single-threaded |
||
59 | /// mode where one code-block is encoded at a time, or in a multi-threaded mode |
||
60 | /// where multiple code-blocks are entropy coded in parallel. The interface |
||
61 | /// presented by this class is the same in both modes. |
||
62 | /// |
||
63 | /// <p>The number of threads used by this entropy coder is specified by the |
||
64 | /// "jj2000.j2k.entropy.encoder.StdEntropyCoder.nthreads" Java system |
||
65 | /// property. If set to "0" the single threaded implementation is used. If set |
||
66 | /// to 'n' ('n' larger than 0) then 'n' extra threads are started by this class |
||
67 | /// which are used to encode the code-blocks in parallel (i.e. ideally 'n' |
||
68 | /// code-blocks will be encoded in parallel at a time). On multiprocessor |
||
69 | /// machines under a "native threads" Java Virtual Machine implementation each |
||
70 | /// one of these threads can run on a separate processor speeding up the |
||
71 | /// encoding time. By default the single-threaded implementation is used. The |
||
72 | /// multi-threaded implementation currently assumes that the vast majority of |
||
73 | /// consecutive calls to 'getNextCodeBlock()' will be done on the same |
||
74 | /// component. If this is not the case, the speed-up that can be expected on |
||
75 | /// multiprocessor machines might be significantly decreased.</p> |
||
76 | /// |
||
77 | /// <p>The code-blocks are rectangular, with dimensions which must be powers of |
||
78 | /// 2. Each dimension has to be no smaller than 4 and no larger than 256. The |
||
79 | /// product of the two dimensions (i.e. area of the code-block) may not exceed |
||
80 | /// 4096.</p> |
||
81 | /// |
||
82 | /// <p>Context 0 of the MQ-coder is used as the uniform one (uniform, |
||
83 | /// non-adaptive probability distribution). Context 1 is used for RLC |
||
84 | /// coding. Contexts 2-10 are used for zero-coding (ZC), contexts 11-15 are |
||
85 | /// used for sign-coding (SC) and contexts 16-18 are used for |
||
86 | /// magnitude-refinement (MR).</p> |
||
87 | /// |
||
88 | /// <p>This implementation buffers the symbols and calls the MQ coder only once |
||
89 | /// per stripe and per coding pass, to reduce the method call overhead.</p> |
||
90 | /// |
||
91 | /// <p>This implementation also provides some timing features. They can be |
||
92 | /// enabled by setting the 'DO_TIMING' constant of this class to true and |
||
93 | /// recompiling. The timing uses the 'System.currentTimeMillis()' Java API |
||
94 | /// call, which returns wall clock time, not the actual CPU time used. The |
||
95 | /// timing results will be printed on the message output. Since the times |
||
96 | /// reported are wall clock times and not CPU usage times they can not be added |
||
97 | /// to find the total used time (i.e. some time might be counted in several |
||
98 | /// places). When timing is disabled ('DO_TIMING' is false) there is no penalty |
||
99 | /// if the compiler performs some basic optimizations. Even if not the penalty |
||
100 | /// should be negligeable.</p> |
||
101 | /// |
||
102 | /// <p>The source module must implement the CBlkQuantDataSrcEnc interface and |
||
103 | /// code-block's data is received in a CBlkWTData instance. This modules sends |
||
104 | /// code-block's information in a CBlkRateDistStats instance.</p> |
||
105 | /// |
||
106 | /// </summary> |
||
107 | /// <seealso cref="CBlkQuantDataSrcEnc"> |
||
108 | /// </seealso> |
||
109 | /// <seealso cref="CBlkWTData"> |
||
110 | /// </seealso> |
||
111 | /// <seealso cref="CBlkRateDistStats"> |
||
112 | /// |
||
113 | /// </seealso> |
||
114 | public class StdEntropyCoder:EntropyCoder |
||
115 | { |
||
116 | |||
117 | /// <summary>Whether to collect timing information or not: false. Used as a compile |
||
118 | /// time directive. |
||
119 | /// </summary> |
||
120 | private const bool DO_TIMING = false; |
||
121 | |||
122 | /// <summary>The cumulative wall time for the entropy coding engine, for each |
||
123 | /// component. In the single-threaded implementation it is the total time, |
||
124 | /// in the multi-threaded implementation it is the time spent managing the |
||
125 | /// compressor threads only. |
||
126 | /// </summary> |
||
127 | //private long[] time; |
||
128 | |||
129 | /// <summary>The Java system property name for the number of threads to use: |
||
130 | /// jj2000.j2k.entropy.encoder.StdEntropyCoder.nthreads |
||
131 | /// </summary> |
||
132 | public const System.String THREADS_PROP_NAME = "jj2000.j2k.entropy.encoder.StdEntropyCoder.nthreads"; |
||
133 | |||
134 | /// <summary>The default value for the property in THREADS_PROP_NAME: 0 </summary> |
||
135 | public const System.String DEF_THREADS_NUM = "0"; |
||
136 | |||
137 | /// <summary>The increase in priority for the compressor threads, currently 3. The |
||
138 | /// compressor threads will have a priority of THREADS_PRIORITY_INC more |
||
139 | /// than the priority of the thread calling this class constructor. Used |
||
140 | /// only in the multi-threaded implementation. |
||
141 | /// </summary> |
||
142 | public const int THREADS_PRIORITY_INC = 0; |
||
143 | |||
144 | /// <summary>The pool of threads, for the threaded implementation. It is null, if |
||
145 | /// non threaded implementation is used |
||
146 | /// </summary> |
||
147 | private ThreadPool tPool; |
||
148 | |||
149 | /// <summary>The queue of idle compressors. Used in multithreaded |
||
150 | /// implementation only |
||
151 | /// </summary> |
||
152 | private System.Collections.ArrayList idleComps; |
||
153 | |||
154 | /// <summary>The queue of completed compressors, for each component. Used |
||
155 | /// in multithreaded implementation only. |
||
156 | /// </summary> |
||
157 | private System.Collections.ArrayList[] completedComps; |
||
158 | |||
159 | /// <summary>The number of busy compressors, for each component. Used in |
||
160 | /// multithreaded implementation only. |
||
161 | /// </summary> |
||
162 | private int[] nBusyComps; |
||
163 | |||
164 | /// <summary>A flag indicating for each component if all the code-blocks of the * |
||
165 | /// current tile have been returned. Used in multithreaded implementation |
||
166 | /// only. |
||
167 | /// </summary> |
||
168 | private bool[] finishedTileComponent; |
||
169 | |||
170 | /// <summary>The MQ coder used, for each thread </summary> |
||
171 | private MQCoder[] mqT; |
||
172 | |||
173 | /// <summary>The raw bit output used, for each thread </summary> |
||
174 | private BitToByteOutput[] boutT; |
||
175 | |||
176 | /// <summary>The output stream used, for each thread </summary> |
||
177 | private ByteOutputBuffer[] outT; |
||
178 | |||
179 | /// <summary>The code-block size specifications </summary> |
||
180 | private CBlkSizeSpec cblks; |
||
181 | |||
182 | /// <summary>The precinct partition specifications </summary> |
||
183 | private PrecinctSizeSpec pss; |
||
184 | |||
185 | /// <summary>By-pass mode specifications </summary> |
||
186 | public StringSpec bms; |
||
187 | |||
188 | /// <summary>MQ reset specifications </summary> |
||
189 | public StringSpec mqrs; |
||
190 | |||
191 | /// <summary>Regular termination specifications </summary> |
||
192 | public StringSpec rts; |
||
193 | |||
194 | /// <summary>Causal stripes specifications </summary> |
||
195 | public StringSpec css; |
||
196 | |||
197 | /// <summary>Error resilience segment symbol use specifications </summary> |
||
198 | public StringSpec sss; |
||
199 | |||
200 | /// <summary>The length calculation specifications </summary> |
||
201 | public StringSpec lcs; |
||
202 | |||
203 | /// <summary>The termination type specifications </summary> |
||
204 | public StringSpec tts; |
||
205 | |||
206 | /// <summary>The options that are turned on, as flag bits. One element for each |
||
207 | /// tile-component. The options are 'OPT_TERM_PASS', 'OPT_RESET_MQ', |
||
208 | /// 'OPT_VERT_STR_CAUSAL', 'OPT_BYPASS' and 'OPT_SEG_SYMBOLS' as defined in |
||
209 | /// the StdEntropyCoderOptions interface |
||
210 | /// |
||
211 | /// </summary> |
||
212 | /// <seealso cref="StdEntropyCoderOptions"> |
||
213 | /// |
||
214 | /// </seealso> |
||
215 | private int[][] opts = null; |
||
216 | |||
217 | /// <summary>The length calculation type for each tile-component </summary> |
||
218 | private int[][] lenCalc = null; |
||
219 | |||
220 | /// <summary>The termination type for each tile-component </summary> |
||
221 | private int[][] tType = null; |
||
222 | |||
223 | /// <summary>Number of bits used for the Zero Coding lookup table </summary> |
||
224 | private const int ZC_LUT_BITS = 8; |
||
225 | |||
226 | /// <summary>Zero Coding context lookup tables for the LH global orientation </summary> |
||
227 | //UPGRADE_NOTE: Final was removed from the declaration of 'ZC_LUT_LH '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
228 | private static readonly int[] ZC_LUT_LH = new int[1 << ZC_LUT_BITS]; |
||
229 | |||
230 | /// <summary>Zero Coding context lookup tables for the HL global orientation </summary> |
||
231 | //UPGRADE_NOTE: Final was removed from the declaration of 'ZC_LUT_HL '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
232 | private static readonly int[] ZC_LUT_HL = new int[1 << ZC_LUT_BITS]; |
||
233 | |||
234 | /// <summary>Zero Coding context lookup tables for the HH global orientation </summary> |
||
235 | //UPGRADE_NOTE: Final was removed from the declaration of 'ZC_LUT_HH '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
236 | private static readonly int[] ZC_LUT_HH = new int[1 << ZC_LUT_BITS]; |
||
237 | |||
238 | /// <summary>Number of bits used for the Sign Coding lookup table </summary> |
||
239 | private const int SC_LUT_BITS = 9; |
||
240 | |||
241 | /// <summary>Sign Coding context lookup table. The index into the table is a 9 bit |
||
242 | /// index, which correspond the the value in the 'state' array shifted by |
||
243 | /// 'SC_SHIFT'. Bits 8-5 are the signs of the horizontal-left, |
||
244 | /// horizontal-right, vertical-up and vertical-down neighbors, |
||
245 | /// respectively. Bit 4 is not used (0 or 1 makes no difference). Bits 3-0 |
||
246 | /// are the significance of the horizontal-left, horizontal-right, |
||
247 | /// vertical-up and vertical-down neighbors, respectively. The least 4 bits |
||
248 | /// of the value in the lookup table define the context number and the sign |
||
249 | /// bit defines the "sign predictor". |
||
250 | /// </summary> |
||
251 | //UPGRADE_NOTE: Final was removed from the declaration of 'SC_LUT '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
252 | private static readonly int[] SC_LUT = new int[1 << SC_LUT_BITS]; |
||
253 | |||
254 | /// <summary>The mask to obtain the context index from the 'SC_LUT' </summary> |
||
255 | private const int SC_LUT_MASK = (1 << 4) - 1; |
||
256 | |||
257 | /// <summary>The shift to obtain the sign predictor from the 'SC_LUT'. It must be |
||
258 | /// an unsigned shift. |
||
259 | /// </summary> |
||
260 | private const int SC_SPRED_SHIFT = 31; |
||
261 | |||
262 | /// <summary>The sign bit for int data </summary> |
||
263 | private const int INT_SIGN_BIT = 1 << 31; |
||
264 | |||
265 | /// <summary>The number of bits used for the Magnitude Refinement lookup table </summary> |
||
266 | private const int MR_LUT_BITS = 9; |
||
267 | |||
268 | /// <summary>Magnitude Refinement context lookup table </summary> |
||
269 | //UPGRADE_NOTE: Final was removed from the declaration of 'MR_LUT '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
270 | private static readonly int[] MR_LUT = new int[1 << MR_LUT_BITS]; |
||
271 | |||
272 | /// <summary>The number of contexts used </summary> |
||
273 | private const int NUM_CTXTS = 19; |
||
274 | |||
275 | /// <summary>The RLC context </summary> |
||
276 | private const int RLC_CTXT = 1; |
||
277 | |||
278 | /// <summary>The UNIFORM context (with a uniform probability distribution which |
||
279 | /// does not adapt) |
||
280 | /// </summary> |
||
281 | private const int UNIF_CTXT = 0; |
||
282 | |||
283 | /// <summary>The initial states for the MQ coder </summary> |
||
284 | //UPGRADE_NOTE: Final was removed from the declaration of 'MQ_INIT'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
285 | private static readonly int[] MQ_INIT = new int[]{46, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
||
286 | |||
287 | /// <summary>The 4 bits of the error resilience segmentation symbol (1010) </summary> |
||
288 | //UPGRADE_NOTE: Final was removed from the declaration of 'SEG_SYMBOLS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
289 | private static readonly int[] SEG_SYMBOLS = new int[]{1, 0, 1, 0}; |
||
290 | |||
291 | /// <summary>The 4 contexts for the error resilience segmentation symbol (always |
||
292 | /// the UNIFORM context, UNIF_CTXT) |
||
293 | /// </summary> |
||
294 | //UPGRADE_NOTE: Final was removed from the declaration of 'SEG_SYMB_CTXTS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
295 | private static readonly int[] SEG_SYMB_CTXTS = new int[]{UNIF_CTXT, UNIF_CTXT, UNIF_CTXT, UNIF_CTXT}; |
||
296 | |||
297 | /// <summary> The state array for each thread. Each element of the state array stores |
||
298 | /// the state of two coefficients. The lower 16 bits store the state of a |
||
299 | /// coefficient in row 'i' and column 'j', while the upper 16 bits store |
||
300 | /// the state of a coefficient in row 'i+1' and column 'j'. The 'i' row is |
||
301 | /// either the first or the third row of a stripe. This packing of the |
||
302 | /// states into 32 bit words allows a faster scan of all coefficients on |
||
303 | /// each coding pass and diminished the amount of data transferred. The |
||
304 | /// size of the state array is increased by 1 on each side (top, bottom, |
||
305 | /// left, right) to handle boundary conditions without any special logic. |
||
306 | /// |
||
307 | /// <p>The state of a coefficient is stored in the following way in the |
||
308 | /// lower 16 bits, where bit 0 is the least significant bit. Bit 15 is the |
||
309 | /// significance of a coefficient (0 if non-significant, 1 otherwise). Bit |
||
310 | /// 14 is the visited state (i.e. if a coefficient has been coded in the |
||
311 | /// significance propagation pass of the current bit-plane). Bit 13 is the |
||
312 | /// "non zero-context" state (i.e. if one of the eight immediate neighbors |
||
313 | /// is significant it is 1, otherwise is 0). Bits 12 to 9 store the sign of |
||
314 | /// the already significant left, right, up and down neighbors (1 for |
||
315 | /// negative, 0 for positive or not yet significant). Bit 8 indicates if |
||
316 | /// the magnitude refinement has already been applied to the |
||
317 | /// coefficient. Bits 7 to 4 store the significance of the left, right, up |
||
318 | /// and down neighbors (1 for significant, 0 for non significant). Bits 3 |
||
319 | /// to 0 store the significance of the diagonal coefficients (up-left, |
||
320 | /// up-right, down-left and down-right; 1 for significant, 0 for non |
||
321 | /// significant).</p> |
||
322 | /// |
||
323 | /// <p>The upper 16 bits the state is stored as in the lower 16 bits, but |
||
324 | /// with the bits shifted up by 16.</p> |
||
325 | /// |
||
326 | /// <p>The lower 16 bits are referred to as "row 1" ("R1") while the upper |
||
327 | /// 16 bits are referred to as "row 2" ("R2").</p> |
||
328 | /// |
||
329 | /// </summary> |
||
330 | private int[][] stateT; |
||
331 | |||
332 | /* The separation between the upper and lower bits in the state array: 16 |
||
333 | * */ |
||
334 | private const int STATE_SEP = 16; |
||
335 | |||
336 | /// <summary>The flag bit for the significance in the state array, for row 1. </summary> |
||
337 | private const int STATE_SIG_R1 = 1 << 15; |
||
338 | |||
339 | /// <summary>The flag bit for the "visited" bit in the state array, for row 1. </summary> |
||
340 | private const int STATE_VISITED_R1 = 1 << 14; |
||
341 | |||
342 | /// <summary>The flag bit for the "not zero context" bit in the state array, for |
||
343 | /// row 1. This bit is always the OR of bits STATE_H_L_R1, STATE_H_R_R1, |
||
344 | /// STATE_V_U_R1, STATE_V_D_R1, STATE_D_UL_R1, STATE_D_UR_R1, STATE_D_DL_R1 |
||
345 | /// and STATE_D_DR_R1. |
||
346 | /// </summary> |
||
347 | private const int STATE_NZ_CTXT_R1 = 1 << 13; |
||
348 | |||
349 | /// <summary>The flag bit for the horizontal-left sign in the state array, for row |
||
350 | /// 1. This bit can only be set if the STATE_H_L_R1 is also set. |
||
351 | /// </summary> |
||
352 | private const int STATE_H_L_SIGN_R1 = 1 << 12; |
||
353 | |||
354 | /// <summary>The flag bit for the horizontal-right sign in the state array, for |
||
355 | /// row 1. This bit can only be set if the STATE_H_R_R1 is also set. |
||
356 | /// </summary> |
||
357 | private const int STATE_H_R_SIGN_R1 = 1 << 11; |
||
358 | |||
359 | /// <summary>The flag bit for the vertical-up sign in the state array, for row |
||
360 | /// 1. This bit can only be set if the STATE_V_U_R1 is also set. |
||
361 | /// </summary> |
||
362 | private const int STATE_V_U_SIGN_R1 = 1 << 10; |
||
363 | |||
364 | /// <summary>The flag bit for the vertical-down sign in the state array, for row |
||
365 | /// 1. This bit can only be set if the STATE_V_D_R1 is also set. |
||
366 | /// </summary> |
||
367 | private const int STATE_V_D_SIGN_R1 = 1 << 9; |
||
368 | |||
369 | /// <summary>The flag bit for the previous MR primitive applied in the state array, |
||
370 | /// for row 1. |
||
371 | /// </summary> |
||
372 | private const int STATE_PREV_MR_R1 = 1 << 8; |
||
373 | |||
374 | /// <summary>The flag bit for the horizontal-left significance in the state array, |
||
375 | /// for row 1. |
||
376 | /// </summary> |
||
377 | private const int STATE_H_L_R1 = 1 << 7; |
||
378 | |||
379 | /// <summary>The flag bit for the horizontal-right significance in the state array, |
||
380 | /// for row 1. |
||
381 | /// </summary> |
||
382 | private const int STATE_H_R_R1 = 1 << 6; |
||
383 | |||
384 | /// <summary>The flag bit for the vertical-up significance in the state array, for |
||
385 | /// row 1. |
||
386 | /// </summary> |
||
387 | private const int STATE_V_U_R1 = 1 << 5; |
||
388 | |||
389 | /// <summary>The flag bit for the vertical-down significance in the state array, |
||
390 | /// for row 1. |
||
391 | /// </summary> |
||
392 | private const int STATE_V_D_R1 = 1 << 4; |
||
393 | |||
394 | /// <summary>The flag bit for the diagonal up-left significance in the state array, |
||
395 | /// for row 1. |
||
396 | /// </summary> |
||
397 | private const int STATE_D_UL_R1 = 1 << 3; |
||
398 | |||
399 | /// <summary>The flag bit for the diagonal up-right significance in the state |
||
400 | /// array, for row 1. |
||
401 | /// </summary> |
||
402 | private const int STATE_D_UR_R1 = 1 << 2; |
||
403 | |||
404 | /// <summary>The flag bit for the diagonal down-left significance in the state |
||
405 | /// array, for row 1. |
||
406 | /// </summary> |
||
407 | private const int STATE_D_DL_R1 = 1 << 1; |
||
408 | |||
409 | /// <summary>The flag bit for the diagonal down-right significance in the state |
||
410 | /// array , for row 1. |
||
411 | /// </summary> |
||
412 | private const int STATE_D_DR_R1 = 1; |
||
413 | |||
414 | /// <summary>The flag bit for the significance in the state array, for row 2. </summary> |
||
415 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_SIG_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
416 | private static readonly int STATE_SIG_R2 = STATE_SIG_R1 << STATE_SEP; |
||
417 | |||
418 | /// <summary>The flag bit for the "visited" bit in the state array, for row 2. </summary> |
||
419 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_VISITED_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
420 | private static readonly int STATE_VISITED_R2 = STATE_VISITED_R1 << STATE_SEP; |
||
421 | |||
422 | /// <summary>The flag bit for the "not zero context" bit in the state array, for |
||
423 | /// row 2. This bit is always the OR of bits STATE_H_L_R2, STATE_H_R_R2, |
||
424 | /// STATE_V_U_R2, STATE_V_D_R2, STATE_D_UL_R2, STATE_D_UR_R2, STATE_D_DL_R2 |
||
425 | /// and STATE_D_DR_R2. |
||
426 | /// </summary> |
||
427 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_NZ_CTXT_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
428 | private static readonly int STATE_NZ_CTXT_R2 = STATE_NZ_CTXT_R1 << STATE_SEP; |
||
429 | |||
430 | /// <summary>The flag bit for the horizontal-left sign in the state array, for row |
||
431 | /// 2. This bit can only be set if the STATE_H_L_R2 is also set. |
||
432 | /// </summary> |
||
433 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_H_L_SIGN_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
434 | private static readonly int STATE_H_L_SIGN_R2 = STATE_H_L_SIGN_R1 << STATE_SEP; |
||
435 | |||
436 | /// <summary>The flag bit for the horizontal-right sign in the state array, for |
||
437 | /// row 2. This bit can only be set if the STATE_H_R_R2 is also set. |
||
438 | /// </summary> |
||
439 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_H_R_SIGN_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
440 | private static readonly int STATE_H_R_SIGN_R2 = STATE_H_R_SIGN_R1 << STATE_SEP; |
||
441 | |||
442 | /// <summary>The flag bit for the vertical-up sign in the state array, for row |
||
443 | /// 2. This bit can only be set if the STATE_V_U_R2 is also set. |
||
444 | /// </summary> |
||
445 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_V_U_SIGN_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
446 | private static readonly int STATE_V_U_SIGN_R2 = STATE_V_U_SIGN_R1 << STATE_SEP; |
||
447 | |||
448 | /// <summary>The flag bit for the vertical-down sign in the state array, for row |
||
449 | /// 2. This bit can only be set if the STATE_V_D_R2 is also set. |
||
450 | /// </summary> |
||
451 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_V_D_SIGN_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
452 | private static readonly int STATE_V_D_SIGN_R2 = STATE_V_D_SIGN_R1 << STATE_SEP; |
||
453 | |||
454 | /// <summary>The flag bit for the previous MR primitive applied in the state array, |
||
455 | /// for row 2. |
||
456 | /// </summary> |
||
457 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_PREV_MR_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
458 | private static readonly int STATE_PREV_MR_R2 = STATE_PREV_MR_R1 << STATE_SEP; |
||
459 | |||
460 | /// <summary>The flag bit for the horizontal-left significance in the state array, |
||
461 | /// for row 2. |
||
462 | /// </summary> |
||
463 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_H_L_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
464 | private static readonly int STATE_H_L_R2 = STATE_H_L_R1 << STATE_SEP; |
||
465 | |||
466 | /// <summary>The flag bit for the horizontal-right significance in the state array, |
||
467 | /// for row 2. |
||
468 | /// </summary> |
||
469 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_H_R_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
470 | private static readonly int STATE_H_R_R2 = STATE_H_R_R1 << STATE_SEP; |
||
471 | |||
472 | /// <summary>The flag bit for the vertical-up significance in the state array, for |
||
473 | /// row 2. |
||
474 | /// </summary> |
||
475 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_V_U_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
476 | private static readonly int STATE_V_U_R2 = STATE_V_U_R1 << STATE_SEP; |
||
477 | |||
478 | /// <summary>The flag bit for the vertical-down significance in the state array, |
||
479 | /// for row 2. |
||
480 | /// </summary> |
||
481 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_V_D_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
482 | private static readonly int STATE_V_D_R2 = STATE_V_D_R1 << STATE_SEP; |
||
483 | |||
484 | /// <summary>The flag bit for the diagonal up-left significance in the state array, |
||
485 | /// for row 2. |
||
486 | /// </summary> |
||
487 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_D_UL_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
488 | private static readonly int STATE_D_UL_R2 = STATE_D_UL_R1 << STATE_SEP; |
||
489 | |||
490 | /// <summary>The flag bit for the diagonal up-right significance in the state |
||
491 | /// array, for row 2. |
||
492 | /// </summary> |
||
493 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_D_UR_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
494 | private static readonly int STATE_D_UR_R2 = STATE_D_UR_R1 << STATE_SEP; |
||
495 | |||
496 | /// <summary>The flag bit for the diagonal down-left significance in the state |
||
497 | /// array, for row 2. |
||
498 | /// </summary> |
||
499 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_D_DL_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
500 | private static readonly int STATE_D_DL_R2 = STATE_D_DL_R1 << STATE_SEP; |
||
501 | |||
502 | /// <summary>The flag bit for the diagonal down-right significance in the state |
||
503 | /// array , for row 2. |
||
504 | /// </summary> |
||
505 | //UPGRADE_NOTE: Final was removed from the declaration of 'STATE_D_DR_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
506 | private static readonly int STATE_D_DR_R2 = STATE_D_DR_R1 << STATE_SEP; |
||
507 | |||
508 | /// <summary>The mask to isolate the significance bits for row 1 and 2 of the state |
||
509 | /// array. |
||
510 | /// </summary> |
||
511 | //UPGRADE_NOTE: Final was removed from the declaration of 'SIG_MASK_R1R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
512 | private static readonly int SIG_MASK_R1R2 = STATE_SIG_R1 | STATE_SIG_R2; |
||
513 | |||
514 | /// <summary>The mask to isolate the visited bits for row 1 and 2 of the state |
||
515 | /// array. |
||
516 | /// </summary> |
||
517 | //UPGRADE_NOTE: Final was removed from the declaration of 'VSTD_MASK_R1R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
518 | private static readonly int VSTD_MASK_R1R2 = STATE_VISITED_R1 | STATE_VISITED_R2; |
||
519 | |||
520 | /// <summary>The mask to isolate the bits necessary to identify RLC coding state |
||
521 | /// (significant, visited and non-zero context, for row 1 and 2). |
||
522 | /// </summary> |
||
523 | //UPGRADE_NOTE: Final was removed from the declaration of 'RLC_MASK_R1R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
524 | private static readonly int RLC_MASK_R1R2 = STATE_SIG_R1 | STATE_SIG_R2 | STATE_VISITED_R1 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2; |
||
525 | |||
526 | /// <summary>The mask to obtain the ZC_LUT index from the state information </summary> |
||
527 | // This is needed because of the STATE_V_D_SIGN_R1, STATE_V_U_SIGN_R1, |
||
528 | // STATE_H_R_SIGN_R1, and STATE_H_L_SIGN_R1 bits. |
||
529 | private const int ZC_MASK = (1 << 8) - 1; |
||
530 | |||
531 | /// <summary>The shift to obtain the SC index to 'SC_LUT' from the state |
||
532 | /// information, for row 1. |
||
533 | /// </summary> |
||
534 | private const int SC_SHIFT_R1 = 4; |
||
535 | |||
536 | /// <summary>The shift to obtain the SC index to 'SC_LUT' from the state |
||
537 | /// information, for row 2. |
||
538 | /// </summary> |
||
539 | //UPGRADE_NOTE: Final was removed from the declaration of 'SC_SHIFT_R2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
540 | private static readonly int SC_SHIFT_R2 = SC_SHIFT_R1 + STATE_SEP; |
||
541 | |||
542 | /// <summary>The bit mask to isolate the state bits relative to the sign coding |
||
543 | /// lookup table ('SC_LUT'). |
||
544 | /// </summary> |
||
545 | //UPGRADE_NOTE: Final was removed from the declaration of 'SC_MASK '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
546 | private static readonly int SC_MASK = (1 << SC_LUT_BITS) - 1; |
||
547 | |||
548 | /// <summary>The mask to obtain the MR index to 'MR_LUT' from the 'state' |
||
549 | /// information. It is to be applied after the 'MR_SHIFT'. |
||
550 | /// </summary> |
||
551 | //UPGRADE_NOTE: Final was removed from the declaration of 'MR_MASK '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
552 | private static readonly int MR_MASK = (1 << MR_LUT_BITS) - 1; |
||
553 | |||
554 | /// <summary>The number of bits used to index in the 'fm' lookup table, 7. The 'fs' |
||
555 | /// table is indexed with one less bit. |
||
556 | /// </summary> |
||
557 | private const int MSE_LKP_BITS = 7; |
||
558 | |||
559 | private const int MSE_LKP_BITS_M1 = 6; |
||
560 | |||
561 | /// <summary>The number of fractional bits used to store data in the 'fm' and 'fs' |
||
562 | /// lookup tables. |
||
563 | /// </summary> |
||
564 | private const int MSE_LKP_FRAC_BITS = 13; |
||
565 | |||
566 | /// <summary>Distortion estimation lookup table for bits coded using the sign-code |
||
567 | /// (SC) primative, for lossy coding (i.e. normal). |
||
568 | /// </summary> |
||
569 | //UPGRADE_NOTE: Final was removed from the declaration of 'FS_LOSSY '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
570 | private static readonly int[] FS_LOSSY = new int[1 << MSE_LKP_BITS_M1]; |
||
571 | |||
572 | /// <summary>Distortion estimation lookup table for bits coded using the |
||
573 | /// magnitude-refinement (MR) primative, for lossy coding (i.e. normal) |
||
574 | /// </summary> |
||
575 | //UPGRADE_NOTE: Final was removed from the declaration of 'FM_LOSSY '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
576 | private static readonly int[] FM_LOSSY = new int[1 << MSE_LKP_BITS]; |
||
577 | |||
578 | /// <summary>Distortion estimation lookup table for bits coded using the sign-code |
||
579 | /// (SC) primative, for lossless coding and last bit-plane. This table is |
||
580 | /// different from 'fs_lossy' since when doing lossless coding the residual |
||
581 | /// distortion after the last bit-plane is coded is strictly 0. |
||
582 | /// </summary> |
||
583 | //UPGRADE_NOTE: Final was removed from the declaration of 'FS_LOSSLESS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
584 | private static readonly int[] FS_LOSSLESS = new int[1 << MSE_LKP_BITS_M1]; |
||
585 | |||
586 | /// <summary>Distortion estimation lookup table for bits coded using the |
||
587 | /// magnitude-refinement (MR) primative, for lossless coding and last |
||
588 | /// bit-plane. This table is different from 'fs_lossless' since when doing |
||
589 | /// lossless coding the residual distortion after the last bit-plane is |
||
590 | /// coded is strictly 0. |
||
591 | /// </summary> |
||
592 | //UPGRADE_NOTE: Final was removed from the declaration of 'FM_LOSSLESS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
593 | private static readonly int[] FM_LOSSLESS = new int[1 << MSE_LKP_BITS]; |
||
594 | |||
595 | /// <summary>The buffer for distortion values (avoids reallocation for each |
||
596 | /// code-block), for each thread. |
||
597 | /// </summary> |
||
598 | private double[][] distbufT; |
||
599 | |||
600 | /// <summary>The buffer for rate values (avoids reallocation for each |
||
601 | /// code-block), for each thread. |
||
602 | /// </summary> |
||
603 | private int[][] ratebufT; |
||
604 | |||
605 | /// <summary>The buffer for indicating terminated passes (avoids reallocation for |
||
606 | /// each code-block), for each thread. |
||
607 | /// </summary> |
||
608 | private bool[][] istermbufT; |
||
609 | |||
610 | /// <summary>The source code-block to entropy code (avoids reallocation for each |
||
611 | /// code-block), for each thread. |
||
612 | /// </summary> |
||
613 | private CBlkWTData[] srcblkT; |
||
614 | |||
615 | /// <summary>Buffer for symbols to send to the MQ-coder, for each thread. Used to |
||
616 | /// reduce the number of calls to the MQ coder. |
||
617 | /// </summary> |
||
618 | // NOTE: The symbol buffer has not prooved to be of any great improvement |
||
619 | // in encoding time, but it does not hurt. It's performance should be |
||
620 | // better studied under different JVMs. |
||
621 | private int[][] symbufT; |
||
622 | |||
623 | /// <summary>Buffer for the contexts to use when sending buffered symbols to the |
||
624 | /// MQ-coder, for each thread. Used to reduce the number of calls to the MQ |
||
625 | /// coder. |
||
626 | /// </summary> |
||
627 | private int[][] ctxtbufT; |
||
628 | |||
629 | /// <summary>boolean used to signal if the precinct partition is used for |
||
630 | /// each component and each tile. |
||
631 | /// </summary> |
||
632 | private bool[][] precinctPartition; |
||
633 | |||
634 | //UPGRADE_NOTE: Field 'EnclosingInstance' was added to class 'Compressor' to access its enclosing instance. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1019'" |
||
635 | /// <summary> Class that takes care of running the 'compressCodeBlock()' method with |
||
636 | /// thread local arguments. Used only in multithreaded implementation. |
||
637 | /// |
||
638 | /// </summary> |
||
639 | private class Compressor : IThreadRunnable |
||
640 | { |
||
641 | private void InitBlock(StdEntropyCoder enclosingInstance) |
||
642 | { |
||
643 | this.enclosingInstance = enclosingInstance; |
||
644 | } |
||
645 | private StdEntropyCoder enclosingInstance; |
||
646 | /// <summary> Returns the index of this compressor. |
||
647 | /// |
||
648 | /// </summary> |
||
649 | /// <returns> The index of this compressor. |
||
650 | /// |
||
651 | /// </returns> |
||
652 | virtual public int Idx |
||
653 | { |
||
654 | get |
||
655 | { |
||
656 | return idx; |
||
657 | } |
||
658 | |||
659 | } |
||
660 | public StdEntropyCoder Enclosing_Instance |
||
661 | { |
||
662 | get |
||
663 | { |
||
664 | return enclosingInstance; |
||
665 | } |
||
666 | |||
667 | } |
||
668 | /// <summary>The index of this compressor. Used to access thread local |
||
669 | /// variables |
||
670 | /// </summary> |
||
671 | //UPGRADE_NOTE: Final was removed from the declaration of 'idx '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" |
||
672 | private int idx; |
||
673 | |||
674 | /// <summary>The object where to store the compressed code-block </summary> |
||
675 | // Should be private, but some buggy JDK 1.1 compilers complain |
||
676 | internal CBlkRateDistStats ccb; |
||
677 | |||
678 | /// <summary>The component on which to compress </summary> |
||
679 | // Should be private, but some buggy JDK 1.1 compilers complain |
||
680 | internal int c; |
||
681 | |||
682 | /// <summary>The options bitmask to use in compression </summary> |
||
683 | // Should be private, but some buggy JDK 1.1 compilers complain |
||
684 | internal int options; |
||
685 | |||
686 | /// <summary>The reversible flag to use in compression </summary> |
||
687 | // Should be private, but some buggy JDK 1.1 compilers complain |
||
688 | internal bool rev; |
||
689 | |||
690 | /// <summary>The length calculation type to use in compression </summary> |
||
691 | // Should be private, but some buggy JDK 1.1 compilers complain |
||
692 | internal int lcType; |
||
693 | |||
694 | /// <summary>The MQ termination type to use in compression </summary> |
||
695 | // Should be private, but some buggy JDK 1.1 compilers complain |
||
696 | internal int tType; |
||
697 | |||
698 | /// <summary>The cumulative wall time for this compressor, for each |
||
699 | /// component. |
||
700 | /// </summary> |
||
701 | //private long[] time; |
||
702 | |||
703 | /// <summary> Creates a new compressor object with the given index. |
||
704 | /// |
||
705 | /// </summary> |
||
706 | /// <param name="idx">The index of this compressor. |
||
707 | /// |
||
708 | /// </param> |
||
709 | internal Compressor(StdEntropyCoder enclosingInstance, int idx) |
||
710 | { |
||
711 | InitBlock(enclosingInstance); |
||
712 | this.idx = idx; |
||
713 | #if DO_TIMING |
||
714 | time = new long[Enclosing_Instance.src.NumComps]; |
||
715 | #endif |
||
716 | } |
||
717 | |||
718 | /// <summary> Calls the 'compressCodeBlock()' method with thread local |
||
719 | /// arguments. Once completed it adds itself to the 'completedComps[c]' |
||
720 | /// stack, where 'c' is the component for which this compressor is |
||
721 | /// running. This last step occurs even if exceptions are thrown by the |
||
722 | /// 'compressCodeBlock()' method. |
||
723 | /// |
||
724 | /// </summary> |
||
725 | public virtual void Run() |
||
726 | { |
||
727 | // Start the code-block compression |
||
728 | try |
||
729 | { |
||
730 | #if DO_TIMING |
||
731 | long stime = 0L; |
||
732 | stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; |
||
733 | #endif |
||
734 | CSJ2K.j2k.entropy.encoder.StdEntropyCoder.compressCodeBlock(c, ccb, Enclosing_Instance.srcblkT[idx], Enclosing_Instance.mqT[idx], Enclosing_Instance.boutT[idx], Enclosing_Instance.outT[idx], Enclosing_Instance.stateT[idx], Enclosing_Instance.distbufT[idx], Enclosing_Instance.ratebufT[idx], Enclosing_Instance.istermbufT[idx], Enclosing_Instance.symbufT[idx], Enclosing_Instance.ctxtbufT[idx], options, rev, lcType, tType); |
||
735 | #if DO_TIMING |
||
736 | time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime; |
||
737 | #endif |
||
738 | } |
||
739 | finally |
||
740 | { |
||
741 | // Join the queue of completed compression, even if exceptions |
||
742 | // occurred. |
||
743 | Enclosing_Instance.completedComps[c].Add(this); |
||
744 | } |
||
745 | } |
||
746 | } |
||
747 | |||
748 | /// <summary> Instantiates a new entropy coder engine, with the specified source of |
||
749 | /// data, nominal block width and height. |
||
750 | /// |
||
751 | /// <p>If the 'OPT_PRED_TERM' option is given then the MQ termination must |
||
752 | /// be 'TERM_PRED_ER' or an exception is thrown.</p> |
||
753 | /// |
||
754 | /// </summary> |
||
755 | /// <param name="src">The source of data |
||
756 | /// |
||
757 | /// </param> |
||
758 | /// <param name="cbks">Code-block size specifications |
||
759 | /// |
||
760 | /// </param> |
||
761 | /// <param name="pss">Precinct partition specifications |
||
762 | /// |
||
763 | /// </param> |
||
764 | /// <param name="bms">By-pass mode specifications |
||
765 | /// |
||
766 | /// </param> |
||
767 | /// <param name="mqrs">MQ-reset specifications |
||
768 | /// |
||
769 | /// </param> |
||
770 | /// <param name="rts">Regular termination specifications |
||
771 | /// |
||
772 | /// </param> |
||
773 | /// <param name="css">Causal stripes specifications |
||
774 | /// |
||
775 | /// </param> |
||
776 | /// <param name="sss">Error resolution segment symbol use specifications |
||
777 | /// |
||
778 | /// </param> |
||
779 | /// <param name="lcs">Length computation specifications |
||
780 | /// |
||
781 | /// </param> |
||
782 | /// <param name="tts">Termination type specifications |
||
783 | /// |
||
784 | /// </param> |
||
785 | /// <seealso cref="MQCoder"> |
||
786 | /// |
||
787 | /// </seealso> |
||
788 | public StdEntropyCoder(CBlkQuantDataSrcEnc src, CBlkSizeSpec cblks, PrecinctSizeSpec pss, StringSpec bms, StringSpec mqrs, StringSpec rts, StringSpec css, StringSpec sss, StringSpec lcs, StringSpec tts):base(src) |
||
789 | { |
||
790 | this.cblks = cblks; |
||
791 | this.pss = pss; |
||
792 | this.bms = bms; |
||
793 | this.mqrs = mqrs; |
||
794 | this.rts = rts; |
||
795 | this.css = css; |
||
796 | this.sss = sss; |
||
797 | this.lcs = lcs; |
||
798 | this.tts = tts; |
||
799 | int maxCBlkWidth, maxCBlkHeight; |
||
800 | int i; // Counter |
||
801 | int nt; // The number of threads |
||
802 | int tsl; // Size for thread structures |
||
803 | |||
804 | // Get the biggest width/height for the code-blocks |
||
805 | maxCBlkWidth = cblks.MaxCBlkWidth; |
||
806 | maxCBlkHeight = cblks.MaxCBlkHeight; |
||
807 | |||
808 | nt = Environment.ProcessorCount; |
||
809 | /* |
||
810 | // Get the number of threads to use, or default to one |
||
811 | try |
||
812 | { |
||
813 | //UPGRADE_ISSUE: Method 'java.lang.System.getProperty' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javalangSystem'" |
||
814 | nt = System.Int32.Parse(System_Renamed.getProperty(THREADS_PROP_NAME, DEF_THREADS_NUM)); |
||
815 | if (nt < 0) |
||
816 | throw new System.FormatException(); |
||
817 | } |
||
818 | catch (System.FormatException e) |
||
819 | { |
||
820 | throw new System.ArgumentException("Invalid number of threads " + "for " + "entropy coding in property " + THREADS_PROP_NAME); |
||
821 | } |
||
822 | */ |
||
823 | |||
824 | // If we do timing create necessary structures |
||
825 | #if DO_TIMING |
||
826 | time = new long[src.NumComps]; |
||
827 | // If we are timing make sure that 'finalize' gets called. |
||
828 | //UPGRADE_ISSUE: Method 'java.lang.System.runFinalizersOnExit' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javalangSystem'" |
||
829 | // CONVERSION PROBLEM? |
||
830 | //System_Renamed.runFinalizersOnExit(true); |
||
831 | #endif |
||
832 | // If using multithreaded implementation get necessasry objects |
||
833 | if (nt > 0) |
||
834 | { |
||
835 | FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.INFO, "Using multithreaded entropy coder " + "with " + nt + " compressor threads."); |
||
836 | tsl = nt; |
||
837 | tPool = new ThreadPool(nt, (System.Int32) SupportClass.ThreadClass.Current().Priority + THREADS_PRIORITY_INC, "StdEntropyCoder"); |
||
838 | idleComps = new System.Collections.ArrayList(); |
||
839 | completedComps = new System.Collections.ArrayList[src.NumComps]; |
||
840 | nBusyComps = new int[src.NumComps]; |
||
841 | finishedTileComponent = new bool[src.NumComps]; |
||
842 | for (i = src.NumComps - 1; i >= 0; i--) |
||
843 | { |
||
844 | completedComps[i] = new System.Collections.ArrayList(); |
||
845 | } |
||
846 | for (i = 0; i < nt; i++) |
||
847 | { |
||
848 | idleComps.Add(new StdEntropyCoder.Compressor(this, i)); |
||
849 | } |
||
850 | } |
||
851 | else |
||
852 | { |
||
853 | tsl = 1; |
||
854 | tPool = null; |
||
855 | idleComps = null; |
||
856 | completedComps = null; |
||
857 | nBusyComps = null; |
||
858 | finishedTileComponent = null; |
||
859 | } |
||
860 | |||
861 | // Allocate data structures |
||
862 | outT = new ByteOutputBuffer[tsl]; |
||
863 | mqT = new MQCoder[tsl]; |
||
864 | boutT = new BitToByteOutput[tsl]; |
||
865 | stateT = new int[tsl][]; |
||
866 | for (int i2 = 0; i2 < tsl; i2++) |
||
867 | { |
||
868 | stateT[i2] = new int[(maxCBlkWidth + 2) * ((maxCBlkHeight + 1) / 2 + 2)]; |
||
869 | } |
||
870 | symbufT = new int[tsl][]; |
||
871 | for (int i3 = 0; i3 < tsl; i3++) |
||
872 | { |
||
873 | symbufT[i3] = new int[maxCBlkWidth * (CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT * 2 + 2)]; |
||
874 | } |
||
875 | ctxtbufT = new int[tsl][]; |
||
876 | for (int i4 = 0; i4 < tsl; i4++) |
||
877 | { |
||
878 | ctxtbufT[i4] = new int[maxCBlkWidth * (CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT * 2 + 2)]; |
||
879 | } |
||
880 | distbufT = new double[tsl][]; |
||
881 | for (int i5 = 0; i5 < tsl; i5++) |
||
882 | { |
||
883 | distbufT[i5] = new double[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES]; |
||
884 | } |
||
885 | ratebufT = new int[tsl][]; |
||
886 | for (int i6 = 0; i6 < tsl; i6++) |
||
887 | { |
||
888 | ratebufT[i6] = new int[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES]; |
||
889 | } |
||
890 | istermbufT = new bool[tsl][]; |
||
891 | for (int i7 = 0; i7 < tsl; i7++) |
||
892 | { |
||
893 | istermbufT[i7] = new bool[32 * CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES]; |
||
894 | } |
||
895 | srcblkT = new CBlkWTData[tsl]; |
||
896 | for (i = 0; i < tsl; i++) |
||
897 | { |
||
898 | outT[i] = new ByteOutputBuffer(); |
||
899 | mqT[i] = new MQCoder(outT[i], NUM_CTXTS, MQ_INIT); |
||
900 | } |
||
901 | precinctPartition = new bool[src.NumComps][]; |
||
902 | for (int i8 = 0; i8 < src.NumComps; i8++) |
||
903 | { |
||
904 | precinctPartition[i8] = new bool[src.getNumTiles()]; |
||
905 | } |
||
906 | |||
907 | // Create the subband description for each component and each tile |
||
908 | //Subband sb = null; |
||
909 | Coord numTiles = null; |
||
910 | int nc = NumComps; |
||
911 | numTiles = src.getNumTiles(numTiles); |
||
912 | initTileComp(getNumTiles(), nc); |
||
913 | |||
914 | for (int c = 0; c < nc; c++) |
||
915 | { |
||
916 | for (int tY = 0; tY < numTiles.y; tY++) |
||
917 | { |
||
918 | for (int tX = 0; tX < numTiles.x; tX++) |
||
919 | { |
||
920 | precinctPartition[c][tIdx] = false; |
||
921 | } |
||
922 | } |
||
923 | } |
||
924 | } |
||
925 | |||
926 | #if DO_TIMING |
||
927 | /// <summary> Prints the timing information, if collected, and calls 'finalize' on |
||
928 | /// the super class. |
||
929 | /// |
||
930 | /// </summary> |
||
931 | ~StdEntropyCoder() |
||
932 | { |
||
933 | |||
934 | int c; |
||
935 | System.Text.StringBuilder sb; |
||
936 | |||
937 | if (tPool == null) |
||
938 | { |
||
939 | // Single threaded implementation |
||
940 | sb = new System.Text.StringBuilder("StdEntropyCoder compression wall " + "clock time:"); |
||
941 | for (c = 0; c < time.Length; c++) |
||
942 | { |
||
943 | sb.Append("\n component "); |
||
944 | sb.Append(c); |
||
945 | sb.Append(": "); |
||
946 | sb.Append(time[c]); |
||
947 | sb.Append(" ms"); |
||
948 | } |
||
949 | FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.INFO, sb.ToString()); |
||
950 | } |
||
951 | else |
||
952 | { |
||
953 | // Multithreaded implementation |
||
954 | Compressor compr; |
||
955 | MsgLogger msglog = FacilityManager.getMsgLogger(); |
||
956 | |||
957 | sb = new System.Text.StringBuilder("StdEntropyCoder manager thread " + "wall clock time:"); |
||
958 | for (c = 0; c < time.Length; c++) |
||
959 | { |
||
960 | sb.Append("\n component "); |
||
961 | sb.Append(c); |
||
962 | sb.Append(": "); |
||
963 | sb.Append(time[c]); |
||
964 | sb.Append(" ms"); |
||
965 | } |
||
966 | System.Collections.IEnumerator Enum = idleComps.GetEnumerator(); |
||
967 | sb.Append("\nStdEntropyCoder compressor threads wall clock " + "time:"); |
||
968 | //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'" |
||
969 | while (Enum.MoveNext()) |
||
970 | { |
||
971 | //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'" |
||
972 | compr = (Compressor)(Enum.Current); |
||
973 | for (c = 0; c < time.Length; c++) |
||
974 | { |
||
975 | sb.Append("\n compressor "); |
||
976 | sb.Append(compr.Idx); |
||
977 | sb.Append(", component "); |
||
978 | sb.Append(c); |
||
979 | sb.Append(": "); |
||
980 | sb.Append(compr.getTiming(c)); |
||
981 | sb.Append(" ms"); |
||
982 | } |
||
983 | } |
||
984 | FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.INFO, sb.ToString()); |
||
985 | } |
||
986 | |||
987 | //UPGRADE_NOTE: Call to 'super.finalize()' was removed. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1124'" |
||
988 | } |
||
989 | #endif |
||
990 | |||
991 | /// <summary> Returns the code-block width for the specified tile and component. |
||
992 | /// |
||
993 | /// </summary> |
||
994 | /// <param name="t">The tile index |
||
995 | /// |
||
996 | /// </param> |
||
997 | /// <param name="c">the component index |
||
998 | /// |
||
999 | /// </param> |
||
1000 | /// <returns> The code-block width for the specified tile and component |
||
1001 | /// |
||
1002 | /// </returns> |
||
1003 | public override int getCBlkWidth(int t, int c) |
||
1004 | { |
||
1005 | return cblks.getCBlkWidth(ModuleSpec.SPEC_TILE_COMP, t, c); |
||
1006 | } |
||
1007 | |||
1008 | /// <summary> Returns the code-block height for the specified tile and component. |
||
1009 | /// |
||
1010 | /// </summary> |
||
1011 | /// <param name="t">The tile index |
||
1012 | /// |
||
1013 | /// </param> |
||
1014 | /// <param name="c">The component index |
||
1015 | /// |
||
1016 | /// </param> |
||
1017 | /// <returns> The code-block height for the specified tile and component. |
||
1018 | /// |
||
1019 | /// </returns> |
||
1020 | public override int getCBlkHeight(int t, int c) |
||
1021 | { |
||
1022 | return cblks.getCBlkHeight(ModuleSpec.SPEC_TILE_COMP, t, c); |
||
1023 | } |
||
1024 | |||
1025 | /// <summary> Returns the next coded code-block in the current tile for the specified |
||
1026 | /// component, as a copy (see below). The order in which code-blocks are |
||
1027 | /// returned is not specified. However each code-block is returned only |
||
1028 | /// once and all code-blocks will be returned if the method is called 'N' |
||
1029 | /// times, where 'N' is the number of code-blocks in the tile. After all |
||
1030 | /// the code-blocks have been returned for the current tile calls to this |
||
1031 | /// method will return 'null'. |
||
1032 | /// |
||
1033 | /// <p>When changing the current tile (through 'setTile()' or 'nextTile()') |
||
1034 | /// this method will always return the first code-block, as if this method |
||
1035 | /// was never called before for the new current tile.</p> |
||
1036 | /// |
||
1037 | /// <p>The data returned by this method is always a copy of the internal |
||
1038 | /// data of this object, if any, and it can be modified "in place" without |
||
1039 | /// any problems after being returned.</p> |
||
1040 | /// |
||
1041 | /// </summary> |
||
1042 | /// <param name="c">The component for which to return the next code-block. |
||
1043 | /// |
||
1044 | /// </param> |
||
1045 | /// <param name="ccb">If non-null this object might be used in returning the coded |
||
1046 | /// code-block in this or any subsequent call to this method. If null a new |
||
1047 | /// one is created and returned. If the 'data' array of 'cbb' is not null |
||
1048 | /// it may be reused to return the compressed data. |
||
1049 | /// |
||
1050 | /// </param> |
||
1051 | /// <returns> The next coded code-block in the current tile for component |
||
1052 | /// 'n', or null if all code-blocks for the current tile have been |
||
1053 | /// returned. |
||
1054 | /// |
||
1055 | /// </returns> |
||
1056 | /// <seealso cref="CBlkRateDistStats"> |
||
1057 | /// |
||
1058 | /// </seealso> |
||
1059 | public override CBlkRateDistStats getNextCodeBlock(int c, CBlkRateDistStats ccb) |
||
1060 | { |
||
1061 | #if DO_TIMING |
||
1062 | long stime = 0L; // Start time for timed sections |
||
1063 | #endif |
||
1064 | if (tPool == null) |
||
1065 | { |
||
1066 | // Use single threaded implementation |
||
1067 | // Get code-block data from source |
||
1068 | srcblkT[0] = src.getNextInternCodeBlock(c, srcblkT[0]); |
||
1069 | |||
1070 | #if DO_TIMING |
||
1071 | stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; |
||
1072 | #endif |
||
1073 | |||
1074 | if (srcblkT[0] == null) |
||
1075 | { |
||
1076 | // We got all code-blocks |
||
1077 | return null; |
||
1078 | } |
||
1079 | // Initialize thread local variables |
||
1080 | if ((opts[tIdx][c] & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && boutT[0] == null) |
||
1081 | { |
||
1082 | boutT[0] = new BitToByteOutput(outT[0]); |
||
1083 | } |
||
1084 | // Initialize output code-block |
||
1085 | if (ccb == null) |
||
1086 | { |
||
1087 | ccb = new CBlkRateDistStats(); |
||
1088 | } |
||
1089 | // Compress code-block |
||
1090 | compressCodeBlock(c, ccb, srcblkT[0], mqT[0], boutT[0], outT[0], stateT[0], distbufT[0], ratebufT[0], istermbufT[0], symbufT[0], ctxtbufT[0], opts[tIdx][c], isReversible(tIdx, c), lenCalc[tIdx][c], tType[tIdx][c]); |
||
1091 | |||
1092 | #if DO_TIMING |
||
1093 | time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime; |
||
1094 | #endif |
||
1095 | |||
1096 | // Return result |
||
1097 | return ccb; |
||
1098 | } |
||
1099 | else |
||
1100 | { |
||
1101 | // Use multiple threaded implementation |
||
1102 | int cIdx; // Compressor idx |
||
1103 | Compressor compr; // Compressor |
||
1104 | |||
1105 | #if DO_TIMING |
||
1106 | stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; |
||
1107 | #endif |
||
1108 | // Give data to all free compressors, using the current component |
||
1109 | while (!finishedTileComponent[c] && !(idleComps.Count == 0)) |
||
1110 | { |
||
1111 | // Get an idle compressor |
||
1112 | compr = (Compressor) SupportClass.StackSupport.Pop(idleComps); |
||
1113 | cIdx = compr.Idx; |
||
1114 | // Get data for the compressor and wake it up |
||
1115 | #if DO_TIMING |
||
1116 | time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime; |
||
1117 | #endif |
||
1118 | srcblkT[cIdx] = src.getNextInternCodeBlock(c, srcblkT[cIdx]); |
||
1119 | #if DO_TIMING |
||
1120 | stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; |
||
1121 | #endif |
||
1122 | if (srcblkT[cIdx] != null) |
||
1123 | { |
||
1124 | // Initialize thread local variables |
||
1125 | if ((opts[tIdx][c] & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && boutT[cIdx] == null) |
||
1126 | { |
||
1127 | boutT[cIdx] = new BitToByteOutput(outT[cIdx]); |
||
1128 | } |
||
1129 | // Initialize output code-block and compressor thread |
||
1130 | if (ccb == null) |
||
1131 | ccb = new CBlkRateDistStats(); |
||
1132 | compr.ccb = ccb; |
||
1133 | compr.c = c; |
||
1134 | compr.options = opts[tIdx][c]; |
||
1135 | compr.rev = isReversible(tIdx, c); |
||
1136 | compr.lcType = lenCalc[tIdx][c]; |
||
1137 | compr.tType = tType[tIdx][c]; |
||
1138 | nBusyComps[c]++; |
||
1139 | ccb = null; |
||
1140 | // Send compressor to execution in thread pool |
||
1141 | tPool.runTarget(compr, completedComps[c]); |
||
1142 | } |
||
1143 | else |
||
1144 | { |
||
1145 | // We finished with all the code-blocks in the current |
||
1146 | // tile component |
||
1147 | idleComps.Add(compr); |
||
1148 | finishedTileComponent[c] = true; |
||
1149 | } |
||
1150 | } |
||
1151 | // If there are threads for this component which result has not |
||
1152 | // been returned yet, get it |
||
1153 | if (nBusyComps[c] > 0) |
||
1154 | { |
||
1155 | lock (completedComps[c]) |
||
1156 | { |
||
1157 | // If no compressor is done, wait until one is |
||
1158 | if ((completedComps[c].Count == 0)) |
||
1159 | { |
||
1160 | try |
||
1161 | { |
||
1162 | #if DO_TIMING |
||
1163 | time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime; |
||
1164 | #endif |
||
1165 | System.Threading.Monitor.Wait(completedComps[c]); |
||
1166 | #if DO_TIMING |
||
1167 | stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; |
||
1168 | #endif |
||
1169 | } |
||
1170 | catch (System.Threading.ThreadInterruptedException) |
||
1171 | { |
||
1172 | } |
||
1173 | } |
||
1174 | // Remove the thread from the completed queue and put it |
||
1175 | // on the idle queue |
||
1176 | compr = (Compressor) SupportClass.StackSupport.Pop(completedComps[c]); |
||
1177 | cIdx = compr.Idx; |
||
1178 | nBusyComps[c]--; |
||
1179 | idleComps.Add(compr); |
||
1180 | // Check targets error condition |
||
1181 | tPool.checkTargetErrors(); |
||
1182 | // Get the result of compression and return that. |
||
1183 | #if DO_TIMING |
||
1184 | time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime; |
||
1185 | #endif |
||
1186 | return compr.ccb; |
||
1187 | } |
||
1188 | } |
||
1189 | else |
||
1190 | { |
||
1191 | // Check targets error condition |
||
1192 | tPool.checkTargetErrors(); |
||
1193 | // Printing timing info if necessary |
||
1194 | #if DO_TIMING |
||
1195 | time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime; |
||
1196 | #endif |
||
1197 | // Nothing is running => no more code-blocks |
||
1198 | return null; |
||
1199 | } |
||
1200 | } |
||
1201 | } |
||
1202 | |||
1203 | /// <summary> Changes the current tile, given the new indexes. An |
||
1204 | /// IllegalArgumentException is thrown if the indexes do not correspond to |
||
1205 | /// a valid tile. |
||
1206 | /// |
||
1207 | /// <p>This default implementation just changes the tile in the source.</p> |
||
1208 | /// |
||
1209 | /// </summary> |
||
1210 | /// <param name="x">The horizontal index of the tile. |
||
1211 | /// |
||
1212 | /// </param> |
||
1213 | /// <param name="y">The vertical index of the new tile. |
||
1214 | /// |
||
1215 | /// </param> |
||
1216 | public override void setTile(int x, int y) |
||
1217 | { |
||
1218 | base.setTile(x, y); |
||
1219 | // Reset the tile specific variables |
||
1220 | if (finishedTileComponent != null) |
||
1221 | { |
||
1222 | for (int c = src.NumComps - 1; c >= 0; c--) |
||
1223 | { |
||
1224 | finishedTileComponent[c] = false; |
||
1225 | } |
||
1226 | } |
||
1227 | } |
||
1228 | |||
1229 | /// <summary> Advances to the next tile, in standard scan-line order (by rows then |
||
1230 | /// columns). An NoNextElementException is thrown if the current tile is |
||
1231 | /// the last one (i.e. there is no next tile). |
||
1232 | /// |
||
1233 | /// <p>This default implementation just advances to the next tile in the |
||
1234 | /// source.</p> |
||
1235 | /// |
||
1236 | /// </summary> |
||
1237 | public override void nextTile() |
||
1238 | { |
||
1239 | // Reset the tilespecific variables |
||
1240 | if (finishedTileComponent != null) |
||
1241 | { |
||
1242 | for (int c = src.NumComps - 1; c >= 0; c--) |
||
1243 | { |
||
1244 | finishedTileComponent[c] = false; |
||
1245 | } |
||
1246 | } |
||
1247 | base.nextTile(); |
||
1248 | } |
||
1249 | |||
1250 | |||
1251 | /// <summary> Compresses the code-block in 'srcblk' and puts the results in 'ccb', |
||
1252 | /// using the specified options and temporary storage. |
||
1253 | /// |
||
1254 | /// </summary> |
||
1255 | /// <param name="c">The component for which to return the next code-block. |
||
1256 | /// |
||
1257 | /// </param> |
||
1258 | /// <param name="ccb">The object where the compressed data will be stored. If the |
||
1259 | /// 'data' array of 'cbb' is not null it may be reused to return the |
||
1260 | /// compressed data. |
||
1261 | /// |
||
1262 | /// </param> |
||
1263 | /// <param name="srcblk">The code-block data to code |
||
1264 | /// |
||
1265 | /// </param> |
||
1266 | /// <param name="mq">The MQ-coder to use |
||
1267 | /// |
||
1268 | /// </param> |
||
1269 | /// <param name="bout">The bit level output to use. Used only if 'OPT_BYPASS' is |
||
1270 | /// turned on in the 'options' argument. |
||
1271 | /// |
||
1272 | /// </param> |
||
1273 | /// <param name="out">The byte buffer trough which the compressed data is stored. |
||
1274 | /// |
||
1275 | /// </param> |
||
1276 | /// <param name="state">The state information for the code-block |
||
1277 | /// |
||
1278 | /// </param> |
||
1279 | /// <param name="distbuf">The buffer where to store the distortion at |
||
1280 | /// the end of each coding pass. |
||
1281 | /// |
||
1282 | /// </param> |
||
1283 | /// <param name="ratebuf">The buffer where to store the rate (i.e. coded lenth) at |
||
1284 | /// the end of each coding pass. |
||
1285 | /// |
||
1286 | /// </param> |
||
1287 | /// <param name="istermbuf">The buffer where to store the terminated flag for each |
||
1288 | /// coding pass. |
||
1289 | /// |
||
1290 | /// </param> |
||
1291 | /// <param name="symbuf">The buffer to hold symbols to send to the MQ coder |
||
1292 | /// |
||
1293 | /// </param> |
||
1294 | /// <param name="ctxtbuf">A buffer to hold the contexts to use in sending the |
||
1295 | /// buffered symbols to the MQ coder. |
||
1296 | /// |
||
1297 | /// </param> |
||
1298 | /// <param name="options">The options to use when coding this code-block |
||
1299 | /// |
||
1300 | /// </param> |
||
1301 | /// <param name="rev">The reversible flag. Should be true if the source of this |
||
1302 | /// code-block's data is reversible. |
||
1303 | /// |
||
1304 | /// </param> |
||
1305 | /// <param name="lcType">The type of length calculation to use with the MQ coder. |
||
1306 | /// |
||
1307 | /// </param> |
||
1308 | /// <param name="tType">The type of termination to use with the MQ coder. |
||
1309 | /// |
||
1310 | /// </param> |
||
1311 | /// <seealso cref="getNextCodeBlock"> |
||
1312 | /// |
||
1313 | /// </seealso> |
||
1314 | static private void compressCodeBlock(int c, CBlkRateDistStats ccb, CBlkWTData srcblk, MQCoder mq, BitToByteOutput bout, ByteOutputBuffer out_Renamed, int[] state, double[] distbuf, int[] ratebuf, bool[] istermbuf, int[] symbuf, int[] ctxtbuf, int options, bool rev, int lcType, int tType) |
||
1315 | { |
||
1316 | // NOTE: This method should not access any non-final instance or |
||
1317 | // static variables, either directly or indirectly through other |
||
1318 | // methods in order to be sure that the method is thread safe. |
||
1319 | |||
1320 | int[] zc_lut; // The ZC lookup table to use |
||
1321 | int skipbp; // The number of non-significant bit-planes to skip |
||
1322 | int curbp; // The current magnitude bit-plane (starts at 30) |
||
1323 | int[] fm; // The distortion estimation lookup table for MR |
||
1324 | int[] fs; // The distortion estimation lookup table for SC |
||
1325 | int lmb; // The least significant magnitude bit |
||
1326 | int npass; // The number of coding passes, for R-D statistics |
||
1327 | double msew; // The distortion (MSE weight) for the current bit-plane |
||
1328 | double totdist; // The total cumulative distortion decrease |
||
1329 | int ltpidx; // The index of the last pass which is terminated |
||
1330 | |||
1331 | // Check error-resilient termination |
||
1332 | if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0 && tType != MQCoder.TERM_PRED_ER) |
||
1333 | { |
||
1334 | throw new System.ArgumentException("Embedded error-resilient info " + "in MQ termination option " + "specified but incorrect MQ " + "termination " + "policy specified"); |
||
1335 | } |
||
1336 | // Set MQ flags |
||
1337 | mq.LenCalcType = lcType; |
||
1338 | mq.TermType = tType; |
||
1339 | |||
1340 | lmb = 30 - srcblk.magbits + 1; |
||
1341 | // If there are more bit-planes to code than the implementation |
||
1342 | // bit-depth set lmb to 0 |
||
1343 | lmb = (lmb < 0)?0:lmb; |
||
1344 | |||
1345 | // Reset state |
||
1346 | ArrayUtil.intArraySet(state, 0); |
||
1347 | |||
1348 | // Find the most significant bit-plane |
||
1349 | skipbp = calcSkipMSBP(srcblk, lmb); |
||
1350 | |||
1351 | // Initialize output code-block |
||
1352 | ccb.m = srcblk.m; |
||
1353 | ccb.n = srcblk.n; |
||
1354 | ccb.sb = srcblk.sb; |
||
1355 | ccb.nROIcoeff = srcblk.nROIcoeff; |
||
1356 | ccb.skipMSBP = skipbp; |
||
1357 | if (ccb.nROIcoeff != 0) |
||
1358 | { |
||
1359 | ccb.nROIcp = 3 * (srcblk.nROIbp - skipbp - 1) + 1; |
||
1360 | } |
||
1361 | else |
||
1362 | { |
||
1363 | ccb.nROIcp = 0; |
||
1364 | } |
||
1365 | |||
1366 | // Choose correct ZC lookup table for global orientation |
||
1367 | switch (srcblk.sb.orientation) |
||
1368 | { |
||
1369 | |||
1370 | case Subband.WT_ORIENT_HL: |
||
1371 | zc_lut = ZC_LUT_HL; |
||
1372 | break; |
||
1373 | |||
1374 | case Subband.WT_ORIENT_LL: |
||
1375 | case Subband.WT_ORIENT_LH: |
||
1376 | zc_lut = ZC_LUT_LH; |
||
1377 | break; |
||
1378 | |||
1379 | case Subband.WT_ORIENT_HH: |
||
1380 | zc_lut = ZC_LUT_HH; |
||
1381 | break; |
||
1382 | |||
1383 | default: |
||
1384 | throw new System.ApplicationException("JJ2000 internal error"); |
||
1385 | |||
1386 | } |
||
1387 | |||
1388 | // Loop on significant magnitude bit-planes doing the 3 passes |
||
1389 | curbp = 30 - skipbp; |
||
1390 | fs = FS_LOSSY; |
||
1391 | fm = FM_LOSSY; |
||
1392 | msew = System.Math.Pow(2, ((curbp - lmb) << 1) - MSE_LKP_FRAC_BITS) * srcblk.sb.stepWMSE * srcblk.wmseScaling; |
||
1393 | totdist = 0f; |
||
1394 | npass = 0; |
||
1395 | ltpidx = - 1; |
||
1396 | |||
1397 | // First significant bit-plane has only the pass pass |
||
1398 | if (curbp >= lmb) |
||
1399 | { |
||
1400 | // Do we need the "lossless" 'fs' table ? |
||
1401 | if (rev && curbp == lmb) |
||
1402 | { |
||
1403 | fs = FM_LOSSLESS; |
||
1404 | } |
||
1405 | // We terminate if regular termination, last bit-plane, or next |
||
1406 | // bit-plane is "raw". |
||
1407 | istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || curbp == lmb || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp) >= curbp); |
||
1408 | totdist += cleanuppass(srcblk, mq, istermbuf[npass], curbp, state, fs, zc_lut, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew; |
||
1409 | distbuf[npass] = totdist; |
||
1410 | if (istermbuf[npass]) |
||
1411 | ltpidx = npass; |
||
1412 | npass++; |
||
1413 | msew *= 0.25; |
||
1414 | curbp--; |
||
1415 | } |
||
1416 | // Other bit-planes have all passes |
||
1417 | while (curbp >= lmb) |
||
1418 | { |
||
1419 | // Do we need the "lossless" 'fs' and 'fm' tables ? |
||
1420 | if (rev && curbp == lmb) |
||
1421 | { |
||
1422 | fs = FS_LOSSLESS; |
||
1423 | fm = FM_LOSSLESS; |
||
1424 | } |
||
1425 | |||
1426 | // Do the significance propagation pass |
||
1427 | // We terminate if regular termination only |
||
1428 | istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0; |
||
1429 | if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) == 0 || (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp <= curbp)) |
||
1430 | { |
||
1431 | // No bypass coding |
||
1432 | totdist += sigProgPass(srcblk, mq, istermbuf[npass], curbp, state, fs, zc_lut, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew; |
||
1433 | } |
||
1434 | else |
||
1435 | { |
||
1436 | // Bypass ("raw") coding |
||
1437 | bout.PredTerm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0; |
||
1438 | totdist += rawSigProgPass(srcblk, bout, istermbuf[npass], curbp, state, fs, ratebuf, npass, ltpidx, options) * msew; |
||
1439 | } |
||
1440 | distbuf[npass] = totdist; |
||
1441 | if (istermbuf[npass]) |
||
1442 | ltpidx = npass; |
||
1443 | npass++; |
||
1444 | |||
1445 | // Do the magnitude refinement pass |
||
1446 | // We terminate if regular termination or bypass ("raw") coding |
||
1447 | istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp > curbp)); |
||
1448 | if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) == 0 || (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp <= curbp)) |
||
1449 | { |
||
1450 | // No bypass coding |
||
1451 | totdist += magRefPass(srcblk, mq, istermbuf[npass], curbp, state, fm, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew; |
||
1452 | } |
||
1453 | else |
||
1454 | { |
||
1455 | // Bypass ("raw") coding |
||
1456 | bout.PredTerm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0; |
||
1457 | totdist += rawMagRefPass(srcblk, bout, istermbuf[npass], curbp, state, fm, ratebuf, npass, ltpidx, options) * msew; |
||
1458 | } |
||
1459 | distbuf[npass] = totdist; |
||
1460 | if (istermbuf[npass]) |
||
1461 | ltpidx = npass; |
||
1462 | npass++; |
||
1463 | |||
1464 | // Do the clenup pass |
||
1465 | // We terminate if regular termination, last bit-plane, or next |
||
1466 | // bit-plane is "raw". |
||
1467 | istermbuf[npass] = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || curbp == lmb || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - skipbp) >= curbp); |
||
1468 | totdist += cleanuppass(srcblk, mq, istermbuf[npass], curbp, state, fs, zc_lut, symbuf, ctxtbuf, ratebuf, npass, ltpidx, options) * msew; |
||
1469 | distbuf[npass] = totdist; |
||
1470 | |||
1471 | if (istermbuf[npass]) |
||
1472 | ltpidx = npass; |
||
1473 | npass++; |
||
1474 | |||
1475 | // Goto next bit-plane |
||
1476 | msew *= 0.25; |
||
1477 | curbp--; |
||
1478 | } |
||
1479 | |||
1480 | // Copy compressed data and rate-distortion statistics to output |
||
1481 | ccb.data = new byte[out_Renamed.size()]; |
||
1482 | out_Renamed.toByteArray(0, out_Renamed.size(), ccb.data, 0); |
||
1483 | checkEndOfPassFF(ccb.data, ratebuf, istermbuf, npass); |
||
1484 | ccb.selectConvexHull(ratebuf, distbuf, (options & (CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS | CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS)) != 0?istermbuf:null, npass, rev); |
||
1485 | |||
1486 | // Reset MQ coder and bit output for next code-block |
||
1487 | mq.reset(); |
||
1488 | if (bout != null) |
||
1489 | bout.reset(); |
||
1490 | } |
||
1491 | |||
1492 | /// <summary> Calculates the number of magnitude bit-planes that are to be skipped, |
||
1493 | /// because they are non-significant. The algorithm looks for the largest |
||
1494 | /// magnitude and calculates the most significant bit-plane of it. |
||
1495 | /// |
||
1496 | /// </summary> |
||
1497 | /// <param name="cblk">The code-block of data to scan |
||
1498 | /// |
||
1499 | /// </param> |
||
1500 | /// <param name="lmb">The least significant magnitude bit in the data |
||
1501 | /// |
||
1502 | /// </param> |
||
1503 | /// <returns> The number of magnitude bit-planes to skip (i.e. all zero most |
||
1504 | /// significant bit-planes). |
||
1505 | /// |
||
1506 | /// </returns> |
||
1507 | static private int calcSkipMSBP(CBlkWTData cblk, int lmb) |
||
1508 | { |
||
1509 | int k, kmax, mask; |
||
1510 | int[] data; |
||
1511 | int maxmag; |
||
1512 | int mag; |
||
1513 | int w, h; |
||
1514 | int msbp; |
||
1515 | int l; |
||
1516 | |||
1517 | data = (int[]) cblk.Data; |
||
1518 | w = cblk.w; |
||
1519 | h = cblk.h; |
||
1520 | |||
1521 | // First look for the maximum magnitude in the code-block |
||
1522 | maxmag = 0; |
||
1523 | // Consider only magnitude bits that are in non-fractional bit-planes. |
||
1524 | mask = 0x7FFFFFFF & (~ ((1 << lmb) - 1)); |
||
1525 | for (l = h - 1, k = cblk.offset; l >= 0; l--) |
||
1526 | { |
||
1527 | for (kmax = k + w; k < kmax; k++) |
||
1528 | { |
||
1529 | mag = data[k] & mask; |
||
1530 | if (mag > maxmag) |
||
1531 | maxmag = mag; |
||
1532 | } |
||
1533 | k += cblk.scanw - w; |
||
1534 | } |
||
1535 | // Now calculate the number of all zero most significant |
||
1536 | // bit-planes for the maximum magnitude. |
||
1537 | msbp = 30; |
||
1538 | do |
||
1539 | { |
||
1540 | if (((1 << msbp) & maxmag) != 0) |
||
1541 | break; |
||
1542 | msbp--; |
||
1543 | } |
||
1544 | while (msbp >= lmb); |
||
1545 | |||
1546 | // Return the number of non-significant bit-planes to skip |
||
1547 | return 30 - msbp; |
||
1548 | } |
||
1549 | |||
1550 | /// <summary> Performs the significance propagation pass on the specified data and |
||
1551 | /// bit-plane. It codes all insignificant samples which have, at least, one |
||
1552 | /// of its immediate eight neighbors already significant, using the ZC and |
||
1553 | /// SC primitives as needed. It toggles the "visited" state bit to 1 for |
||
1554 | /// all those samples. |
||
1555 | /// |
||
1556 | /// </summary> |
||
1557 | /// <param name="srcblk">The code-block data to code |
||
1558 | /// |
||
1559 | /// </param> |
||
1560 | /// <param name="mq">The MQ-coder to use |
||
1561 | /// |
||
1562 | /// </param> |
||
1563 | /// <param name="doterm">If true it performs an MQ-coder termination after the end |
||
1564 | /// of the pass |
||
1565 | /// |
||
1566 | /// </param> |
||
1567 | /// <param name="bp">The bit-plane to code |
||
1568 | /// |
||
1569 | /// </param> |
||
1570 | /// <param name="state">The state information for the code-block |
||
1571 | /// |
||
1572 | /// </param> |
||
1573 | /// <param name="fs">The distortion estimation lookup table for SC |
||
1574 | /// |
||
1575 | /// </param> |
||
1576 | /// <param name="zc_lut">The ZC lookup table to use in ZC. |
||
1577 | /// |
||
1578 | /// </param> |
||
1579 | /// <param name="symbuf">The buffer to hold symbols to send to the MQ coder |
||
1580 | /// |
||
1581 | /// </param> |
||
1582 | /// <param name="ctxtbuf">A buffer to hold the contexts to use in sending the |
||
1583 | /// buffered symbols to the MQ coder. |
||
1584 | /// |
||
1585 | /// </param> |
||
1586 | /// <param name="ratebuf">The buffer where to store the rate (i.e. coded lenth) at |
||
1587 | /// the end of this coding pass. |
||
1588 | /// |
||
1589 | /// </param> |
||
1590 | /// <param name="pidx">The coding pass index. Is the index in the 'ratebuf' array |
||
1591 | /// where to store the coded length after this coding pass. |
||
1592 | /// |
||
1593 | /// </param> |
||
1594 | /// <param name="ltpidx">The index of the last pass that was terminated, or |
||
1595 | /// negative if none. |
||
1596 | /// |
||
1597 | /// </param> |
||
1598 | /// <param name="options">The bitmask of entropy coding options to apply to the |
||
1599 | /// code-block |
||
1600 | /// |
||
1601 | /// </param> |
||
1602 | /// <returns> The decrease in distortion for this pass, in the fixed-point |
||
1603 | /// normalized representation of the 'FS_LOSSY' and 'FS_LOSSLESS' tables. |
||
1604 | /// |
||
1605 | /// </returns> |
||
1606 | static private int sigProgPass(CBlkWTData srcblk, MQCoder mq, bool doterm, int bp, int[] state, int[] fs, int[] zc_lut, int[] symbuf, int[] ctxtbuf, int[] ratebuf, int pidx, int ltpidx, int options) |
||
1607 | { |
||
1608 | int j, sj; // The state index for line and stripe |
||
1609 | int k, sk; // The data index for line and stripe |
||
1610 | int nsym = 0; // Symbol counter for symbol and context buffers |
||
1611 | int dscanw; // The data scan-width |
||
1612 | int sscanw; // The state and packed state scan-width |
||
1613 | int jstep; // Stripe to stripe step for 'sj' |
||
1614 | int kstep; // Stripe to stripe step for 'sk' |
||
1615 | int stopsk; // The loop limit on the variable sk |
||
1616 | int csj; // Local copy (i.e. cached) of 'state[j]' |
||
1617 | int mask; // The mask for the current bit-plane |
||
1618 | int sym; // The symbol to code |
||
1619 | int ctxt; // The context to use |
||
1620 | int[] data; // The data buffer |
||
1621 | int dist; // The distortion reduction for this pass |
||
1622 | int shift; // Shift amount for distortion |
||
1623 | int upshift; // Shift left amount for distortion |
||
1624 | int downshift; // Shift right amount for distortion |
||
1625 | int normval; // The normalized sample magnitude value |
||
1626 | int s; // The stripe index |
||
1627 | bool causal; // Flag to indicate if stripe-causal context |
||
1628 | // formation is to be used |
||
1629 | int nstripes; // The number of stripes in the code-block |
||
1630 | int sheight; // Height of the current stripe |
||
1631 | int off_ul, off_ur, off_dr, off_dl; // offsets |
||
1632 | |||
1633 | // Initialize local variables |
||
1634 | dscanw = srcblk.scanw; |
||
1635 | sscanw = srcblk.w + 2; |
||
1636 | jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - srcblk.w; |
||
1637 | kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - srcblk.w; |
||
1638 | mask = 1 << bp; |
||
1639 | data = (int[]) srcblk.Data; |
||
1640 | nstripes = (srcblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; |
||
1641 | dist = 0; |
||
1642 | // We use the MSE_LKP_BITS-1 bits below the bit just coded for |
||
1643 | // distortion estimation. |
||
1644 | shift = bp - MSE_LKP_BITS_M1; |
||
1645 | upshift = (shift >= 0)?0:- shift; |
||
1646 | downshift = (shift <= 0)?0:shift; |
||
1647 | causal = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL) != 0; |
||
1648 | |||
1649 | // Pre-calculate offsets in 'state' for diagonal neighbors |
||
1650 | off_ul = - sscanw - 1; // up-left |
||
1651 | off_ur = - sscanw + 1; // up-right |
||
1652 | off_dr = sscanw + 1; // down-right |
||
1653 | off_dl = sscanw - 1; // down-left |
||
1654 | |||
1655 | // Code stripe by stripe |
||
1656 | sk = srcblk.offset; |
||
1657 | sj = sscanw + 1; |
||
1658 | for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep) |
||
1659 | { |
||
1660 | sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:srcblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; |
||
1661 | stopsk = sk + srcblk.w; |
||
1662 | // Scan by set of 1 stripe column at a time |
||
1663 | for (nsym = 0; sk < stopsk; sk++, sj++) |
||
1664 | { |
||
1665 | // Do half top of column |
||
1666 | j = sj; |
||
1667 | csj = state[j]; |
||
1668 | // If any of the two samples is not significant and has a |
||
1669 | // non-zero context (i.e. some neighbor is significant) we can |
||
1670 | // not skip them |
||
1671 | if ((((~ csj) & (csj << 2)) & SIG_MASK_R1R2) != 0) |
||
1672 | { |
||
1673 | k = sk; |
||
1674 | // Scan first row |
||
1675 | if ((csj & (STATE_SIG_R1 | STATE_NZ_CTXT_R1)) == STATE_NZ_CTXT_R1) |
||
1676 | { |
||
1677 | // Apply zero coding |
||
1678 | ctxtbuf[nsym] = zc_lut[csj & ZC_MASK]; |
||
1679 | if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0) |
||
1680 | { |
||
1681 | // Became significant |
||
1682 | // Apply sign coding |
||
1683 | sym = SupportClass.URShift(data[k], 31); |
||
1684 | ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK]; |
||
1685 | symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); |
||
1686 | ctxtbuf[nsym++] = ctxt & SC_LUT_MASK; |
||
1687 | // Update state information (significant bit, |
||
1688 | // visited bit, neighbor significant bit of |
||
1689 | // neighbors, non zero context of neighbors, sign |
||
1690 | // of neighbors) |
||
1691 | if (!causal) |
||
1692 | { |
||
1693 | // If in causal mode do not change contexts of |
||
1694 | // previous stripe. |
||
1695 | state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2; |
||
1696 | state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2; |
||
1697 | } |
||
1698 | // Update sign state information of neighbors |
||
1699 | if (sym != 0) |
||
1700 | { |
||
1701 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2; |
||
1702 | if (!causal) |
||
1703 | { |
||
1704 | // If in causal mode do not change |
||
1705 | // contexts of previous stripe. |
||
1706 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2; |
||
1707 | } |
||
1708 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2; |
||
1709 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2; |
||
1710 | } |
||
1711 | else |
||
1712 | { |
||
1713 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2; |
||
1714 | if (!causal) |
||
1715 | { |
||
1716 | // If in causal mode do not change |
||
1717 | // contexts of previous stripe. |
||
1718 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2; |
||
1719 | } |
||
1720 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2; |
||
1721 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2; |
||
1722 | } |
||
1723 | // Update distortion |
||
1724 | normval = (data[k] >> downshift) << upshift; |
||
1725 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
1726 | } |
||
1727 | else |
||
1728 | { |
||
1729 | csj |= STATE_VISITED_R1; |
||
1730 | } |
||
1731 | } |
||
1732 | if (sheight < 2) |
||
1733 | { |
||
1734 | state[j] = csj; |
||
1735 | continue; |
||
1736 | } |
||
1737 | // Scan second row |
||
1738 | if ((csj & (STATE_SIG_R2 | STATE_NZ_CTXT_R2)) == STATE_NZ_CTXT_R2) |
||
1739 | { |
||
1740 | k += dscanw; |
||
1741 | // Apply zero coding |
||
1742 | ctxtbuf[nsym] = zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]; |
||
1743 | if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0) |
||
1744 | { |
||
1745 | // Became significant |
||
1746 | // Apply sign coding |
||
1747 | sym = SupportClass.URShift(data[k], 31); |
||
1748 | ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK]; |
||
1749 | symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); |
||
1750 | ctxtbuf[nsym++] = ctxt & SC_LUT_MASK; |
||
1751 | // Update state information (significant bit, |
||
1752 | // visited bit, neighbor significant bit of |
||
1753 | // neighbors, non zero context of neighbors, sign |
||
1754 | // of neighbors) |
||
1755 | state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1; |
||
1756 | state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1; |
||
1757 | // Update sign state information of neighbors |
||
1758 | if (sym != 0) |
||
1759 | { |
||
1760 | csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1; |
||
1761 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1; |
||
1762 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2; |
||
1763 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2; |
||
1764 | } |
||
1765 | else |
||
1766 | { |
||
1767 | csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1; |
||
1768 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1; |
||
1769 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2; |
||
1770 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2; |
||
1771 | } |
||
1772 | // Update distortion |
||
1773 | normval = (data[k] >> downshift) << upshift; |
||
1774 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
1775 | } |
||
1776 | else |
||
1777 | { |
||
1778 | csj |= STATE_VISITED_R2; |
||
1779 | } |
||
1780 | } |
||
1781 | state[j] = csj; |
||
1782 | } |
||
1783 | // Do half bottom of column |
||
1784 | if (sheight < 3) |
||
1785 | continue; |
||
1786 | j += sscanw; |
||
1787 | csj = state[j]; |
||
1788 | // If any of the two samples is not significant and has a |
||
1789 | // non-zero context (i.e. some neighbor is significant) we can |
||
1790 | // not skip them |
||
1791 | if ((((~ csj) & (csj << 2)) & SIG_MASK_R1R2) != 0) |
||
1792 | { |
||
1793 | k = sk + (dscanw << 1); |
||
1794 | // Scan first row |
||
1795 | if ((csj & (STATE_SIG_R1 | STATE_NZ_CTXT_R1)) == STATE_NZ_CTXT_R1) |
||
1796 | { |
||
1797 | // Apply zero coding |
||
1798 | ctxtbuf[nsym] = zc_lut[csj & ZC_MASK]; |
||
1799 | if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0) |
||
1800 | { |
||
1801 | // Became significant |
||
1802 | // Apply sign coding |
||
1803 | sym = SupportClass.URShift(data[k], 31); |
||
1804 | ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK]; |
||
1805 | symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); |
||
1806 | ctxtbuf[nsym++] = ctxt & SC_LUT_MASK; |
||
1807 | // Update state information (significant bit, |
||
1808 | // visited bit, neighbor significant bit of |
||
1809 | // neighbors, non zero context of neighbors, sign |
||
1810 | // of neighbors) |
||
1811 | state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2; |
||
1812 | state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2; |
||
1813 | // Update sign state information of neighbors |
||
1814 | if (sym != 0) |
||
1815 | { |
||
1816 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2; |
||
1817 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2; |
||
1818 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2; |
||
1819 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2; |
||
1820 | } |
||
1821 | else |
||
1822 | { |
||
1823 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2; |
||
1824 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2; |
||
1825 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2; |
||
1826 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2; |
||
1827 | } |
||
1828 | // Update distortion |
||
1829 | normval = (data[k] >> downshift) << upshift; |
||
1830 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
1831 | } |
||
1832 | else |
||
1833 | { |
||
1834 | csj |= STATE_VISITED_R1; |
||
1835 | } |
||
1836 | } |
||
1837 | if (sheight < 4) |
||
1838 | { |
||
1839 | state[j] = csj; |
||
1840 | continue; |
||
1841 | } |
||
1842 | // Scan second row |
||
1843 | if ((csj & (STATE_SIG_R2 | STATE_NZ_CTXT_R2)) == STATE_NZ_CTXT_R2) |
||
1844 | { |
||
1845 | k += dscanw; |
||
1846 | // Apply zero coding |
||
1847 | ctxtbuf[nsym] = zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]; |
||
1848 | if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0) |
||
1849 | { |
||
1850 | // Became significant |
||
1851 | // Apply sign coding |
||
1852 | sym = SupportClass.URShift(data[k], 31); |
||
1853 | ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK]; |
||
1854 | symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); |
||
1855 | ctxtbuf[nsym++] = ctxt & SC_LUT_MASK; |
||
1856 | // Update state information (significant bit, |
||
1857 | // visited bit, neighbor significant bit of |
||
1858 | // neighbors, non zero context of neighbors, sign |
||
1859 | // of neighbors) |
||
1860 | state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1; |
||
1861 | state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1; |
||
1862 | // Update sign state information of neighbors |
||
1863 | if (sym != 0) |
||
1864 | { |
||
1865 | csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1; |
||
1866 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1; |
||
1867 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2; |
||
1868 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2; |
||
1869 | } |
||
1870 | else |
||
1871 | { |
||
1872 | csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1; |
||
1873 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1; |
||
1874 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2; |
||
1875 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2; |
||
1876 | } |
||
1877 | // Update distortion |
||
1878 | normval = (data[k] >> downshift) << upshift; |
||
1879 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
1880 | } |
||
1881 | else |
||
1882 | { |
||
1883 | csj |= STATE_VISITED_R2; |
||
1884 | } |
||
1885 | } |
||
1886 | state[j] = csj; |
||
1887 | } |
||
1888 | } |
||
1889 | // Code all buffered symbols |
||
1890 | mq.codeSymbols(symbuf, ctxtbuf, nsym); |
||
1891 | } |
||
1892 | // Reset the MQ context states if we need to |
||
1893 | if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ) != 0) |
||
1894 | { |
||
1895 | mq.resetCtxts(); |
||
1896 | } |
||
1897 | |||
1898 | // Terminate the MQ bit stream if we need to |
||
1899 | if (doterm) |
||
1900 | { |
||
1901 | ratebuf[pidx] = mq.terminate(); // Termination has special length |
||
1902 | } |
||
1903 | else |
||
1904 | { |
||
1905 | // Use normal length calculation |
||
1906 | ratebuf[pidx] = mq.NumCodedBytes; |
||
1907 | } |
||
1908 | // Add length of previous segments, if any |
||
1909 | if (ltpidx >= 0) |
||
1910 | { |
||
1911 | ratebuf[pidx] += ratebuf[ltpidx]; |
||
1912 | } |
||
1913 | // Finish length calculation if needed |
||
1914 | if (doterm) |
||
1915 | { |
||
1916 | mq.finishLengthCalculation(ratebuf, pidx); |
||
1917 | } |
||
1918 | |||
1919 | // Return the reduction in distortion |
||
1920 | return dist; |
||
1921 | } |
||
1922 | |||
1923 | /// <summary> Performs the significance propagation pass on the specified data and |
||
1924 | /// bit-plane, without using the arithmetic coder. It codes all |
||
1925 | /// insignificant samples which have, at least, one of its immediate eight |
||
1926 | /// neighbors already significant, using the ZC and SC primitives as |
||
1927 | /// needed. It toggles the "visited" state bit to 1 for all those samples. |
||
1928 | /// |
||
1929 | /// <p>In this method, the arithmetic coder is bypassed, and raw bits are |
||
1930 | /// directly written in the bit stream (useful when distribution are close |
||
1931 | /// to uniform, for intance, at high bit-rates and at lossless |
||
1932 | /// compression).</p> |
||
1933 | /// |
||
1934 | /// </summary> |
||
1935 | /// <param name="srcblk">The code-block data to code |
||
1936 | /// |
||
1937 | /// </param> |
||
1938 | /// <param name="bout">The bit based output |
||
1939 | /// |
||
1940 | /// </param> |
||
1941 | /// <param name="doterm">If true the bit based output is byte aligned after the |
||
1942 | /// end of the pass. |
||
1943 | /// |
||
1944 | /// </param> |
||
1945 | /// <param name="bp">The bit-plane to code |
||
1946 | /// |
||
1947 | /// </param> |
||
1948 | /// <param name="state">The state information for the code-block |
||
1949 | /// |
||
1950 | /// </param> |
||
1951 | /// <param name="fs">The distortion estimation lookup table for SC |
||
1952 | /// |
||
1953 | /// </param> |
||
1954 | /// <param name="ratebuf">The buffer where to store the rate (i.e. coded lenth) at |
||
1955 | /// the end of this coding pass. |
||
1956 | /// |
||
1957 | /// </param> |
||
1958 | /// <param name="pidx">The coding pass index. Is the index in the 'ratebuf' array |
||
1959 | /// where to store the coded length after this coding pass. |
||
1960 | /// |
||
1961 | /// </param> |
||
1962 | /// <param name="ltpidx">The index of the last pass that was terminated, or |
||
1963 | /// negative if none. |
||
1964 | /// |
||
1965 | /// </param> |
||
1966 | /// <param name="options">The bitmask of entropy coding options to apply to the |
||
1967 | /// code-block |
||
1968 | /// |
||
1969 | /// </param> |
||
1970 | /// <returns> The decrease in distortion for this pass, in the fixed-point |
||
1971 | /// normalized representation of the 'FS_LOSSY' and 'FS_LOSSLESS' tables. |
||
1972 | /// |
||
1973 | /// </returns> |
||
1974 | static private int rawSigProgPass(CBlkWTData srcblk, BitToByteOutput bout, bool doterm, int bp, int[] state, int[] fs, int[] ratebuf, int pidx, int ltpidx, int options) |
||
1975 | { |
||
1976 | int j, sj; // The state index for line and stripe |
||
1977 | int k, sk; // The data index for line and stripe |
||
1978 | int dscanw; // The data scan-width |
||
1979 | int sscanw; // The state scan-width |
||
1980 | int jstep; // Stripe to stripe step for 'sj' |
||
1981 | int kstep; // Stripe to stripe step for 'sk' |
||
1982 | int stopsk; // The loop limit on the variable sk |
||
1983 | int csj; // Local copy (i.e. cached) of 'state[j]' |
||
1984 | int mask; // The mask for the current bit-plane |
||
1985 | int nsym = 0; // Number of symbol |
||
1986 | int sym; // The symbol to code |
||
1987 | int[] data; // The data buffer |
||
1988 | int dist; // The distortion reduction for this pass |
||
1989 | int shift; // Shift amount for distortion |
||
1990 | int upshift; // Shift left amount for distortion |
||
1991 | int downshift; // Shift right amount for distortion |
||
1992 | int normval; // The normalized sample magnitude value |
||
1993 | int s; // The stripe index |
||
1994 | bool causal; // Flag to indicate if stripe-causal context |
||
1995 | // formation is to be used |
||
1996 | int nstripes; // The number of stripes in the code-block |
||
1997 | int sheight; // Height of the current stripe |
||
1998 | int off_ul, off_ur, off_dr, off_dl; // offsets |
||
1999 | |||
2000 | // Initialize local variables |
||
2001 | dscanw = srcblk.scanw; |
||
2002 | sscanw = srcblk.w + 2; |
||
2003 | jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - srcblk.w; |
||
2004 | kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - srcblk.w; |
||
2005 | mask = 1 << bp; |
||
2006 | data = (int[]) srcblk.Data; |
||
2007 | nstripes = (srcblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; |
||
2008 | dist = 0; |
||
2009 | // We use the MSE_LKP_BITS-1 bits below the bit just coded for |
||
2010 | // distortion estimation. |
||
2011 | shift = bp - MSE_LKP_BITS_M1; |
||
2012 | upshift = (shift >= 0)?0:- shift; |
||
2013 | downshift = (shift <= 0)?0:shift; |
||
2014 | causal = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL) != 0; |
||
2015 | |||
2016 | // Pre-calculate offsets in 'state' for neighbors |
||
2017 | off_ul = - sscanw - 1; // up-left |
||
2018 | off_ur = - sscanw + 1; // up-right |
||
2019 | off_dr = sscanw + 1; // down-right |
||
2020 | off_dl = sscanw - 1; // down-left |
||
2021 | |||
2022 | // Code stripe by stripe |
||
2023 | sk = srcblk.offset; |
||
2024 | sj = sscanw + 1; |
||
2025 | for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep) |
||
2026 | { |
||
2027 | sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:srcblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; |
||
2028 | stopsk = sk + srcblk.w; |
||
2029 | // Scan by set of 1 stripe column at a time |
||
2030 | for (; sk < stopsk; sk++, sj++) |
||
2031 | { |
||
2032 | // Do half top of column |
||
2033 | j = sj; |
||
2034 | csj = state[j]; |
||
2035 | // If any of the two samples is not significant and has a |
||
2036 | // non-zero context (i.e. some neighbor is significant) we can |
||
2037 | // not skip them |
||
2038 | if ((((~ csj) & (csj << 2)) & SIG_MASK_R1R2) != 0) |
||
2039 | { |
||
2040 | k = sk; |
||
2041 | // Scan first row |
||
2042 | if ((csj & (STATE_SIG_R1 | STATE_NZ_CTXT_R1)) == STATE_NZ_CTXT_R1) |
||
2043 | { |
||
2044 | // Apply zero coding |
||
2045 | sym = SupportClass.URShift((data[k] & mask), bp); |
||
2046 | bout.writeBit(sym); |
||
2047 | nsym++; |
||
2048 | if (sym != 0) |
||
2049 | { |
||
2050 | // Became significant |
||
2051 | // Apply sign coding |
||
2052 | sym = SupportClass.URShift(data[k], 31); |
||
2053 | bout.writeBit(sym); |
||
2054 | nsym++; |
||
2055 | // Update state information (significant bit, |
||
2056 | // visited bit, neighbor significant bit of |
||
2057 | // neighbors, non zero context of neighbors, sign |
||
2058 | // of neighbors) |
||
2059 | if (!causal) |
||
2060 | { |
||
2061 | // If in causal mode do not change contexts of |
||
2062 | // previous stripe. |
||
2063 | state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2; |
||
2064 | state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2; |
||
2065 | } |
||
2066 | // Update sign state information of neighbors |
||
2067 | if (sym != 0) |
||
2068 | { |
||
2069 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2; |
||
2070 | if (!causal) |
||
2071 | { |
||
2072 | // If in causal mode do not change |
||
2073 | // contexts of previous stripe. |
||
2074 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2; |
||
2075 | } |
||
2076 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2; |
||
2077 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2; |
||
2078 | } |
||
2079 | else |
||
2080 | { |
||
2081 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2; |
||
2082 | if (!causal) |
||
2083 | { |
||
2084 | // If in causal mode do not change |
||
2085 | // contexts of previous stripe. |
||
2086 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2; |
||
2087 | } |
||
2088 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2; |
||
2089 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2; |
||
2090 | } |
||
2091 | // Update distortion |
||
2092 | normval = (data[k] >> downshift) << upshift; |
||
2093 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
2094 | } |
||
2095 | else |
||
2096 | { |
||
2097 | csj |= STATE_VISITED_R1; |
||
2098 | } |
||
2099 | } |
||
2100 | if (sheight < 2) |
||
2101 | { |
||
2102 | state[j] = csj; |
||
2103 | continue; |
||
2104 | } |
||
2105 | // Scan second row |
||
2106 | if ((csj & (STATE_SIG_R2 | STATE_NZ_CTXT_R2)) == STATE_NZ_CTXT_R2) |
||
2107 | { |
||
2108 | k += dscanw; |
||
2109 | // Apply zero coding |
||
2110 | sym = SupportClass.URShift((data[k] & mask), bp); |
||
2111 | bout.writeBit(sym); |
||
2112 | nsym++; |
||
2113 | if (sym != 0) |
||
2114 | { |
||
2115 | // Became significant |
||
2116 | // Apply sign coding |
||
2117 | sym = SupportClass.URShift(data[k], 31); |
||
2118 | bout.writeBit(sym); |
||
2119 | nsym++; |
||
2120 | // Update state information (significant bit, |
||
2121 | // visited bit, neighbor significant bit of |
||
2122 | // neighbors, non zero context of neighbors, sign |
||
2123 | // of neighbors) |
||
2124 | state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1; |
||
2125 | state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1; |
||
2126 | // Update sign state information of neighbors |
||
2127 | if (sym != 0) |
||
2128 | { |
||
2129 | csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1; |
||
2130 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1; |
||
2131 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2; |
||
2132 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2; |
||
2133 | } |
||
2134 | else |
||
2135 | { |
||
2136 | csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1; |
||
2137 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1; |
||
2138 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2; |
||
2139 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2; |
||
2140 | } |
||
2141 | // Update distortion |
||
2142 | normval = (data[k] >> downshift) << upshift; |
||
2143 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
2144 | } |
||
2145 | else |
||
2146 | { |
||
2147 | csj |= STATE_VISITED_R2; |
||
2148 | } |
||
2149 | } |
||
2150 | state[j] = csj; |
||
2151 | } |
||
2152 | // Do half bottom of column |
||
2153 | if (sheight < 3) |
||
2154 | continue; |
||
2155 | j += sscanw; |
||
2156 | csj = state[j]; |
||
2157 | // If any of the two samples is not significant and has a |
||
2158 | // non-zero context (i.e. some neighbor is significant) we can |
||
2159 | // not skip them |
||
2160 | if ((((~ csj) & (csj << 2)) & SIG_MASK_R1R2) != 0) |
||
2161 | { |
||
2162 | k = sk + (dscanw << 1); |
||
2163 | // Scan first row |
||
2164 | if ((csj & (STATE_SIG_R1 | STATE_NZ_CTXT_R1)) == STATE_NZ_CTXT_R1) |
||
2165 | { |
||
2166 | sym = SupportClass.URShift((data[k] & mask), bp); |
||
2167 | bout.writeBit(sym); |
||
2168 | nsym++; |
||
2169 | if (sym != 0) |
||
2170 | { |
||
2171 | // Became significant |
||
2172 | // Apply sign coding |
||
2173 | sym = SupportClass.URShift(data[k], 31); |
||
2174 | bout.writeBit(sym); |
||
2175 | nsym++; |
||
2176 | // Update state information (significant bit, |
||
2177 | // visited bit, neighbor significant bit of |
||
2178 | // neighbors, non zero context of neighbors, sign |
||
2179 | // of neighbors) |
||
2180 | state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2; |
||
2181 | state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2; |
||
2182 | // Update sign state information of neighbors |
||
2183 | if (sym != 0) |
||
2184 | { |
||
2185 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2; |
||
2186 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2; |
||
2187 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2; |
||
2188 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2; |
||
2189 | } |
||
2190 | else |
||
2191 | { |
||
2192 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2; |
||
2193 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2; |
||
2194 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2; |
||
2195 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2; |
||
2196 | } |
||
2197 | // Update distortion |
||
2198 | normval = (data[k] >> downshift) << upshift; |
||
2199 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
2200 | } |
||
2201 | else |
||
2202 | { |
||
2203 | csj |= STATE_VISITED_R1; |
||
2204 | } |
||
2205 | } |
||
2206 | if (sheight < 4) |
||
2207 | { |
||
2208 | state[j] = csj; |
||
2209 | continue; |
||
2210 | } |
||
2211 | if ((csj & (STATE_SIG_R2 | STATE_NZ_CTXT_R2)) == STATE_NZ_CTXT_R2) |
||
2212 | { |
||
2213 | k += dscanw; |
||
2214 | // Apply zero coding |
||
2215 | sym = SupportClass.URShift((data[k] & mask), bp); |
||
2216 | bout.writeBit(sym); |
||
2217 | nsym++; |
||
2218 | if (sym != 0) |
||
2219 | { |
||
2220 | // Became significant |
||
2221 | // Apply sign coding |
||
2222 | sym = SupportClass.URShift(data[k], 31); |
||
2223 | bout.writeBit(sym); |
||
2224 | nsym++; |
||
2225 | // Update state information (significant bit, |
||
2226 | // visited bit, neighbor significant bit of |
||
2227 | // neighbors, non zero context of neighbors, sign |
||
2228 | // of neighbors) |
||
2229 | state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1; |
||
2230 | state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1; |
||
2231 | // Update sign state information of neighbors |
||
2232 | if (sym != 0) |
||
2233 | { |
||
2234 | csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1; |
||
2235 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1; |
||
2236 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2; |
||
2237 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2; |
||
2238 | } |
||
2239 | else |
||
2240 | { |
||
2241 | csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1; |
||
2242 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1; |
||
2243 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2; |
||
2244 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2; |
||
2245 | } |
||
2246 | // Update distortion |
||
2247 | normval = (data[k] >> downshift) << upshift; |
||
2248 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
2249 | } |
||
2250 | else |
||
2251 | { |
||
2252 | csj |= STATE_VISITED_R2; |
||
2253 | } |
||
2254 | } |
||
2255 | state[j] = csj; |
||
2256 | } |
||
2257 | } |
||
2258 | } |
||
2259 | |||
2260 | // Get length and terminate if needed |
||
2261 | if (doterm) |
||
2262 | { |
||
2263 | ratebuf[pidx] = bout.terminate(); |
||
2264 | } |
||
2265 | else |
||
2266 | { |
||
2267 | ratebuf[pidx] = bout.length(); |
||
2268 | } |
||
2269 | // Add length of previous segments, if any |
||
2270 | if (ltpidx >= 0) |
||
2271 | { |
||
2272 | ratebuf[pidx] += ratebuf[ltpidx]; |
||
2273 | } |
||
2274 | |||
2275 | // Return the reduction in distortion |
||
2276 | return dist; |
||
2277 | } |
||
2278 | |||
2279 | /// <summary> Performs the magnitude refinement pass on the specified data and |
||
2280 | /// bit-plane. It codes the samples which are significant and which do not |
||
2281 | /// have the "visited" state bit turned on, using the MR primitive. The |
||
2282 | /// "visited" state bit is not mofified for any samples. |
||
2283 | /// |
||
2284 | /// </summary> |
||
2285 | /// <param name="srcblk">The code-block data to code |
||
2286 | /// |
||
2287 | /// </param> |
||
2288 | /// <param name="mq">The MQ-coder to use |
||
2289 | /// |
||
2290 | /// </param> |
||
2291 | /// <param name="doterm">If true it performs an MQ-coder termination after the end |
||
2292 | /// of the pass |
||
2293 | /// |
||
2294 | /// </param> |
||
2295 | /// <param name="bp">The bit-plane to code |
||
2296 | /// |
||
2297 | /// </param> |
||
2298 | /// <param name="state">The state information for the code-block |
||
2299 | /// |
||
2300 | /// </param> |
||
2301 | /// <param name="fm">The distortion estimation lookup table for MR |
||
2302 | /// |
||
2303 | /// </param> |
||
2304 | /// <param name="symbuf">The buffer to hold symbols to send to the MQ coder |
||
2305 | /// |
||
2306 | /// </param> |
||
2307 | /// <param name="ctxtbuf">A buffer to hold the contexts to use in sending the |
||
2308 | /// buffered symbols to the MQ coder. |
||
2309 | /// |
||
2310 | /// </param> |
||
2311 | /// <param name="ratebuf">The buffer where to store the rate (i.e. coded lenth) at |
||
2312 | /// the end of this coding pass. |
||
2313 | /// |
||
2314 | /// </param> |
||
2315 | /// <param name="pidx">The coding pass index. Is the index in the 'ratebuf' array |
||
2316 | /// where to store the coded length after this coding pass. |
||
2317 | /// |
||
2318 | /// </param> |
||
2319 | /// <param name="ltpidx">The index of the last pass that was terminated, or |
||
2320 | /// negative if none. |
||
2321 | /// |
||
2322 | /// </param> |
||
2323 | /// <param name="options">The bitmask of entropy coding options to apply to the |
||
2324 | /// code-block |
||
2325 | /// |
||
2326 | /// </param> |
||
2327 | /// <returns> The decrease in distortion for this pass, in the fixed-point |
||
2328 | /// normalized representation of the 'FS_LOSSY' and 'FS_LOSSLESS' tables. |
||
2329 | /// |
||
2330 | /// </returns> |
||
2331 | static private int magRefPass(CBlkWTData srcblk, MQCoder mq, bool doterm, int bp, int[] state, int[] fm, int[] symbuf, int[] ctxtbuf, int[] ratebuf, int pidx, int ltpidx, int options) |
||
2332 | { |
||
2333 | int j, sj; // The state index for line and stripe |
||
2334 | int k, sk; // The data index for line and stripe |
||
2335 | int nsym = 0; // Symbol counter for symbol and context buffers |
||
2336 | int dscanw; // The data scan-width |
||
2337 | int sscanw; // The state scan-width |
||
2338 | int jstep; // Stripe to stripe step for 'sj' |
||
2339 | int kstep; // Stripe to stripe step for 'sk' |
||
2340 | int stopsk; // The loop limit on the variable sk |
||
2341 | int csj; // Local copy (i.e. cached) of 'state[j]' |
||
2342 | int mask; // The mask for the current bit-plane |
||
2343 | int[] data; // The data buffer |
||
2344 | int dist; // The distortion reduction for this pass |
||
2345 | int shift; // Shift amount for distortion |
||
2346 | int upshift; // Shift left amount for distortion |
||
2347 | int downshift; // Shift right amount for distortion |
||
2348 | int normval; // The normalized sample magnitude value |
||
2349 | int s; // The stripe index |
||
2350 | int nstripes; // The number of stripes in the code-block |
||
2351 | int sheight; // Height of the current stripe |
||
2352 | |||
2353 | // Initialize local variables |
||
2354 | dscanw = srcblk.scanw; |
||
2355 | sscanw = srcblk.w + 2; |
||
2356 | jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - srcblk.w; |
||
2357 | kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - srcblk.w; |
||
2358 | mask = 1 << bp; |
||
2359 | data = (int[]) srcblk.Data; |
||
2360 | nstripes = (srcblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; |
||
2361 | dist = 0; |
||
2362 | // We use the bit just coded plus MSE_LKP_BITS-1 bits below the bit |
||
2363 | // just coded for distortion estimation. |
||
2364 | shift = bp - MSE_LKP_BITS_M1; |
||
2365 | upshift = (shift >= 0)?0:- shift; |
||
2366 | downshift = (shift <= 0)?0:shift; |
||
2367 | |||
2368 | // Code stripe by stripe |
||
2369 | sk = srcblk.offset; |
||
2370 | sj = sscanw + 1; |
||
2371 | for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep) |
||
2372 | { |
||
2373 | sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:srcblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; |
||
2374 | stopsk = sk + srcblk.w; |
||
2375 | // Scan by set of 1 stripe column at a time |
||
2376 | for (nsym = 0; sk < stopsk; sk++, sj++) |
||
2377 | { |
||
2378 | // Do half top of column |
||
2379 | j = sj; |
||
2380 | csj = state[j]; |
||
2381 | // If any of the two samples is significant and not yet |
||
2382 | // visited in the current bit-plane we can not skip them |
||
2383 | if ((((SupportClass.URShift(csj, 1)) & (~ csj)) & VSTD_MASK_R1R2) != 0) |
||
2384 | { |
||
2385 | k = sk; |
||
2386 | // Scan first row |
||
2387 | if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == STATE_SIG_R1) |
||
2388 | { |
||
2389 | // Apply MR primitive |
||
2390 | symbuf[nsym] = SupportClass.URShift((data[k] & mask), bp); |
||
2391 | ctxtbuf[nsym++] = MR_LUT[csj & MR_MASK]; |
||
2392 | // Update the STATE_PREV_MR bit |
||
2393 | csj |= STATE_PREV_MR_R1; |
||
2394 | // Update distortion |
||
2395 | normval = (data[k] >> downshift) << upshift; |
||
2396 | dist += fm[normval & ((1 << MSE_LKP_BITS) - 1)]; |
||
2397 | } |
||
2398 | if (sheight < 2) |
||
2399 | { |
||
2400 | state[j] = csj; |
||
2401 | continue; |
||
2402 | } |
||
2403 | // Scan second row |
||
2404 | if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == STATE_SIG_R2) |
||
2405 | { |
||
2406 | k += dscanw; |
||
2407 | // Apply MR primitive |
||
2408 | symbuf[nsym] = SupportClass.URShift((data[k] & mask), bp); |
||
2409 | ctxtbuf[nsym++] = MR_LUT[(SupportClass.URShift(csj, STATE_SEP)) & MR_MASK]; |
||
2410 | // Update the STATE_PREV_MR bit |
||
2411 | csj |= STATE_PREV_MR_R2; |
||
2412 | // Update distortion |
||
2413 | normval = (data[k] >> downshift) << upshift; |
||
2414 | dist += fm[normval & ((1 << MSE_LKP_BITS) - 1)]; |
||
2415 | } |
||
2416 | state[j] = csj; |
||
2417 | } |
||
2418 | // Do half bottom of column |
||
2419 | if (sheight < 3) |
||
2420 | continue; |
||
2421 | j += sscanw; |
||
2422 | csj = state[j]; |
||
2423 | // If any of the two samples is significant and not yet |
||
2424 | // visited in the current bit-plane we can not skip them |
||
2425 | if ((((SupportClass.URShift(csj, 1)) & (~ csj)) & VSTD_MASK_R1R2) != 0) |
||
2426 | { |
||
2427 | k = sk + (dscanw << 1); |
||
2428 | // Scan first row |
||
2429 | if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == STATE_SIG_R1) |
||
2430 | { |
||
2431 | // Apply MR primitive |
||
2432 | symbuf[nsym] = SupportClass.URShift((data[k] & mask), bp); |
||
2433 | ctxtbuf[nsym++] = MR_LUT[csj & MR_MASK]; |
||
2434 | // Update the STATE_PREV_MR bit |
||
2435 | csj |= STATE_PREV_MR_R1; |
||
2436 | // Update distortion |
||
2437 | normval = (data[k] >> downshift) << upshift; |
||
2438 | dist += fm[normval & ((1 << MSE_LKP_BITS) - 1)]; |
||
2439 | } |
||
2440 | if (sheight < 4) |
||
2441 | { |
||
2442 | state[j] = csj; |
||
2443 | continue; |
||
2444 | } |
||
2445 | // Scan second row |
||
2446 | if ((state[j] & (STATE_SIG_R2 | STATE_VISITED_R2)) == STATE_SIG_R2) |
||
2447 | { |
||
2448 | k += dscanw; |
||
2449 | // Apply MR primitive |
||
2450 | symbuf[nsym] = SupportClass.URShift((data[k] & mask), bp); |
||
2451 | ctxtbuf[nsym++] = MR_LUT[(SupportClass.URShift(csj, STATE_SEP)) & MR_MASK]; |
||
2452 | // Update the STATE_PREV_MR bit |
||
2453 | csj |= STATE_PREV_MR_R2; |
||
2454 | // Update distortion |
||
2455 | normval = (data[k] >> downshift) << upshift; |
||
2456 | dist += fm[normval & ((1 << MSE_LKP_BITS) - 1)]; |
||
2457 | } |
||
2458 | state[j] = csj; |
||
2459 | } |
||
2460 | } |
||
2461 | // Code all buffered symbols, if any |
||
2462 | if (nsym > 0) |
||
2463 | mq.codeSymbols(symbuf, ctxtbuf, nsym); |
||
2464 | } |
||
2465 | |||
2466 | // Reset the MQ context states if we need to |
||
2467 | if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ) != 0) |
||
2468 | { |
||
2469 | mq.resetCtxts(); |
||
2470 | } |
||
2471 | |||
2472 | // Terminate the MQ bit stream if we need to |
||
2473 | if (doterm) |
||
2474 | { |
||
2475 | ratebuf[pidx] = mq.terminate(); // Termination has special length |
||
2476 | } |
||
2477 | else |
||
2478 | { |
||
2479 | // Use normal length calculation |
||
2480 | ratebuf[pidx] = mq.NumCodedBytes; |
||
2481 | } |
||
2482 | // Add length of previous segments, if any |
||
2483 | if (ltpidx >= 0) |
||
2484 | { |
||
2485 | ratebuf[pidx] += ratebuf[ltpidx]; |
||
2486 | } |
||
2487 | // Finish length calculation if needed |
||
2488 | if (doterm) |
||
2489 | { |
||
2490 | mq.finishLengthCalculation(ratebuf, pidx); |
||
2491 | } |
||
2492 | |||
2493 | // Return the reduction in distortion |
||
2494 | return dist; |
||
2495 | } |
||
2496 | |||
2497 | /// <summary> Performs the magnitude refinement pass on the specified data and |
||
2498 | /// bit-plane, without using the arithmetic coder. It codes the samples |
||
2499 | /// which are significant and which do not have the "visited" state bit |
||
2500 | /// turned on, using the MR primitive. The "visited" state bit is not |
||
2501 | /// mofified for any samples. |
||
2502 | /// |
||
2503 | /// <p>In this method, the arithmetic coder is bypassed, and raw bits are |
||
2504 | /// directly written in the bit stream (useful when distribution are close |
||
2505 | /// to uniform, for intance, at high bit-rates and at lossless |
||
2506 | /// compression). The 'STATE_PREV_MR_R1' and 'STATE_PREV_MR_R2' bits are |
||
2507 | /// not set because they are used only when the arithmetic coder is not |
||
2508 | /// bypassed.</p> |
||
2509 | /// |
||
2510 | /// </summary> |
||
2511 | /// <param name="srcblk">The code-block data to code |
||
2512 | /// |
||
2513 | /// </param> |
||
2514 | /// <param name="bout">The bit based output |
||
2515 | /// |
||
2516 | /// </param> |
||
2517 | /// <param name="doterm">If true the bit based output is byte aligned after the |
||
2518 | /// end of the pass. |
||
2519 | /// |
||
2520 | /// </param> |
||
2521 | /// <param name="bp">The bit-plane to code |
||
2522 | /// |
||
2523 | /// </param> |
||
2524 | /// <param name="state">The state information for the code-block |
||
2525 | /// |
||
2526 | /// </param> |
||
2527 | /// <param name="fm">The distortion estimation lookup table for MR |
||
2528 | /// |
||
2529 | /// </param> |
||
2530 | /// <param name="ratebuf">The buffer where to store the rate (i.e. coded lenth) at |
||
2531 | /// the end of this coding pass. |
||
2532 | /// |
||
2533 | /// </param> |
||
2534 | /// <param name="pidx">The coding pass index. Is the index in the 'ratebuf' array |
||
2535 | /// where to store the coded length after this coding pass. |
||
2536 | /// |
||
2537 | /// </param> |
||
2538 | /// <param name="ltpidx">The index of the last pass that was terminated, or |
||
2539 | /// negative if none. |
||
2540 | /// |
||
2541 | /// </param> |
||
2542 | /// <param name="options">The bitmask of entropy coding options to apply to the |
||
2543 | /// code-block |
||
2544 | /// |
||
2545 | /// </param> |
||
2546 | /// <returns> The decrease in distortion for this pass, in the fixed-point |
||
2547 | /// normalized representation of the 'FS_LOSSY' and 'FS_LOSSLESS' tables. |
||
2548 | /// |
||
2549 | /// </returns> |
||
2550 | static private int rawMagRefPass(CBlkWTData srcblk, BitToByteOutput bout, bool doterm, int bp, int[] state, int[] fm, int[] ratebuf, int pidx, int ltpidx, int options) |
||
2551 | { |
||
2552 | int j, sj; // The state index for line and stripe |
||
2553 | int k, sk; // The data index for line and stripe |
||
2554 | int dscanw; // The data scan-width |
||
2555 | int sscanw; // The state scan-width |
||
2556 | int jstep; // Stripe to stripe step for 'sj' |
||
2557 | int kstep; // Stripe to stripe step for 'sk' |
||
2558 | int stopsk; // The loop limit on the variable sk |
||
2559 | int csj; // Local copy (i.e. cached) of 'state[j]' |
||
2560 | int mask; // The mask for the current bit-plane |
||
2561 | int[] data; // The data buffer |
||
2562 | int dist; // The distortion reduction for this pass |
||
2563 | int shift; // Shift amount for distortion |
||
2564 | int upshift; // Shift left amount for distortion |
||
2565 | int downshift; // Shift right amount for distortion |
||
2566 | int normval; // The normalized sample magnitude value |
||
2567 | int s; // The stripe index |
||
2568 | int nstripes; // The number of stripes in the code-block |
||
2569 | int sheight; // Height of the current stripe |
||
2570 | int nsym = 0; |
||
2571 | |||
2572 | // Initialize local variables |
||
2573 | dscanw = srcblk.scanw; |
||
2574 | sscanw = srcblk.w + 2; |
||
2575 | jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - srcblk.w; |
||
2576 | kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - srcblk.w; |
||
2577 | mask = 1 << bp; |
||
2578 | data = (int[]) srcblk.Data; |
||
2579 | nstripes = (srcblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; |
||
2580 | dist = 0; |
||
2581 | // We use the bit just coded plus MSE_LKP_BITS-1 bits below the bit |
||
2582 | // just coded for distortion estimation. |
||
2583 | shift = bp - MSE_LKP_BITS_M1; |
||
2584 | upshift = (shift >= 0)?0:- shift; |
||
2585 | downshift = (shift <= 0)?0:shift; |
||
2586 | |||
2587 | // Code stripe by stripe |
||
2588 | sk = srcblk.offset; |
||
2589 | sj = sscanw + 1; |
||
2590 | for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep) |
||
2591 | { |
||
2592 | sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:srcblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; |
||
2593 | stopsk = sk + srcblk.w; |
||
2594 | // Scan by set of 1 stripe column at a time |
||
2595 | for (; sk < stopsk; sk++, sj++) |
||
2596 | { |
||
2597 | // Do half top of column |
||
2598 | j = sj; |
||
2599 | csj = state[j]; |
||
2600 | // If any of the two samples is significant and not yet |
||
2601 | // visited in the current bit-plane we can not skip them |
||
2602 | if ((((SupportClass.URShift(csj, 1)) & (~ csj)) & VSTD_MASK_R1R2) != 0) |
||
2603 | { |
||
2604 | k = sk; |
||
2605 | // Scan first row |
||
2606 | if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == STATE_SIG_R1) |
||
2607 | { |
||
2608 | // Code bit "raw" |
||
2609 | bout.writeBit(SupportClass.URShift((data[k] & mask), bp)); |
||
2610 | nsym++; |
||
2611 | // No need to set STATE_PREV_MR_R1 since all magnitude |
||
2612 | // refinement passes to follow are "raw" |
||
2613 | // Update distortion |
||
2614 | normval = (data[k] >> downshift) << upshift; |
||
2615 | dist += fm[normval & ((1 << MSE_LKP_BITS) - 1)]; |
||
2616 | } |
||
2617 | if (sheight < 2) |
||
2618 | continue; |
||
2619 | // Scan second row |
||
2620 | if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == STATE_SIG_R2) |
||
2621 | { |
||
2622 | k += dscanw; |
||
2623 | // Code bit "raw" |
||
2624 | bout.writeBit(SupportClass.URShift((data[k] & mask), bp)); |
||
2625 | nsym++; |
||
2626 | // No need to set STATE_PREV_MR_R2 since all magnitude |
||
2627 | // refinement passes to follow are "raw" |
||
2628 | // Update distortion |
||
2629 | normval = (data[k] >> downshift) << upshift; |
||
2630 | dist += fm[normval & ((1 << MSE_LKP_BITS) - 1)]; |
||
2631 | } |
||
2632 | } |
||
2633 | // Do half bottom of column |
||
2634 | if (sheight < 3) |
||
2635 | continue; |
||
2636 | j += sscanw; |
||
2637 | csj = state[j]; |
||
2638 | // If any of the two samples is significant and not yet |
||
2639 | // visited in the current bit-plane we can not skip them |
||
2640 | if ((((SupportClass.URShift(csj, 1)) & (~ csj)) & VSTD_MASK_R1R2) != 0) |
||
2641 | { |
||
2642 | k = sk + (dscanw << 1); |
||
2643 | // Scan first row |
||
2644 | if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == STATE_SIG_R1) |
||
2645 | { |
||
2646 | // Code bit "raw" |
||
2647 | bout.writeBit(SupportClass.URShift((data[k] & mask), bp)); |
||
2648 | nsym++; |
||
2649 | // No need to set STATE_PREV_MR_R1 since all magnitude |
||
2650 | // refinement passes to follow are "raw" |
||
2651 | // Update distortion |
||
2652 | normval = (data[k] >> downshift) << upshift; |
||
2653 | dist += fm[normval & ((1 << MSE_LKP_BITS) - 1)]; |
||
2654 | } |
||
2655 | if (sheight < 4) |
||
2656 | continue; |
||
2657 | // Scan second row |
||
2658 | if ((state[j] & (STATE_SIG_R2 | STATE_VISITED_R2)) == STATE_SIG_R2) |
||
2659 | { |
||
2660 | k += dscanw; |
||
2661 | // Code bit "raw" |
||
2662 | bout.writeBit(SupportClass.URShift((data[k] & mask), bp)); |
||
2663 | nsym++; |
||
2664 | // No need to set STATE_PREV_MR_R2 since all magnitude |
||
2665 | // refinement passes to follow are "raw" |
||
2666 | // Update distortion |
||
2667 | normval = (data[k] >> downshift) << upshift; |
||
2668 | dist += fm[normval & ((1 << MSE_LKP_BITS) - 1)]; |
||
2669 | } |
||
2670 | } |
||
2671 | } |
||
2672 | } |
||
2673 | |||
2674 | // Get length and terminate if needed |
||
2675 | if (doterm) |
||
2676 | { |
||
2677 | ratebuf[pidx] = bout.terminate(); |
||
2678 | } |
||
2679 | else |
||
2680 | { |
||
2681 | ratebuf[pidx] = bout.length(); |
||
2682 | } |
||
2683 | |||
2684 | // Add length of previous segments, if any |
||
2685 | if (ltpidx >= 0) |
||
2686 | { |
||
2687 | ratebuf[pidx] += ratebuf[ltpidx]; |
||
2688 | } |
||
2689 | |||
2690 | // Return the reduction in distortion |
||
2691 | return dist; |
||
2692 | } |
||
2693 | |||
2694 | /// <summary> Performs the cleanup pass on the specified data and bit-plane. It codes |
||
2695 | /// all insignificant samples which have its "visited" state bit off, using |
||
2696 | /// the ZC, SC, and RLC primitives. It toggles the "visited" state bit to 0 |
||
2697 | /// (off) for all samples in the code-block. |
||
2698 | /// |
||
2699 | /// </summary> |
||
2700 | /// <param name="srcblk">The code-block data to code |
||
2701 | /// |
||
2702 | /// </param> |
||
2703 | /// <param name="mq">The MQ-coder to use |
||
2704 | /// |
||
2705 | /// </param> |
||
2706 | /// <param name="doterm">If true it performs an MQ-coder termination after the end |
||
2707 | /// of the pass |
||
2708 | /// |
||
2709 | /// </param> |
||
2710 | /// <param name="bp">The bit-plane to code |
||
2711 | /// |
||
2712 | /// </param> |
||
2713 | /// <param name="state">The state information for the code-block |
||
2714 | /// |
||
2715 | /// </param> |
||
2716 | /// <param name="fs">The distortion estimation lookup table for SC |
||
2717 | /// |
||
2718 | /// </param> |
||
2719 | /// <param name="zc_lut">The ZC lookup table to use in ZC. |
||
2720 | /// |
||
2721 | /// </param> |
||
2722 | /// <param name="symbuf">The buffer to hold symbols to send to the MQ coder |
||
2723 | /// |
||
2724 | /// </param> |
||
2725 | /// <param name="ctxtbuf">A buffer to hold the contexts to use in sending the |
||
2726 | /// buffered symbols to the MQ coder. |
||
2727 | /// |
||
2728 | /// </param> |
||
2729 | /// <param name="ratebuf">The buffer where to store the rate (i.e. coded lenth) at |
||
2730 | /// the end of this coding pass. |
||
2731 | /// |
||
2732 | /// </param> |
||
2733 | /// <param name="pidx">The coding pass index. Is the index in the 'ratebuf' array |
||
2734 | /// where to store the coded length after this coding pass. |
||
2735 | /// |
||
2736 | /// </param> |
||
2737 | /// <param name="ltpidx">The index of the last pass that was terminated, or |
||
2738 | /// negative if none. |
||
2739 | /// |
||
2740 | /// </param> |
||
2741 | /// <param name="options">The bitmask of entropy coding options to apply to the |
||
2742 | /// code-block |
||
2743 | /// |
||
2744 | /// </param> |
||
2745 | /// <returns> The decrease in distortion for this pass, in the fixed-point |
||
2746 | /// normalized representation of the 'FS_LOSSY' and 'FS_LOSSLESS' tables. |
||
2747 | /// |
||
2748 | /// </returns> |
||
2749 | static private int cleanuppass(CBlkWTData srcblk, MQCoder mq, bool doterm, int bp, int[] state, int[] fs, int[] zc_lut, int[] symbuf, int[] ctxtbuf, int[] ratebuf, int pidx, int ltpidx, int options) |
||
2750 | { |
||
2751 | // NOTE: The speedup mode of the MQ coder has been briefly tried to |
||
2752 | // speed up the coding of insignificants RLCs, without any success |
||
2753 | // (i.e. no speedup whatsoever). The use of the speedup mode should be |
||
2754 | // revisisted more in depth and the implementationn of it in MQCoder |
||
2755 | // should be reviewed for optimization opportunities. |
||
2756 | int j, sj; // The state index for line and stripe |
||
2757 | int k, sk; // The data index for line and stripe |
||
2758 | int nsym = 0; // Symbol counter for symbol and context buffers |
||
2759 | int dscanw; // The data scan-width |
||
2760 | int sscanw; // The state scan-width |
||
2761 | int jstep; // Stripe to stripe step for 'sj' |
||
2762 | int kstep; // Stripe to stripe step for 'sk' |
||
2763 | int stopsk; // The loop limit on the variable sk |
||
2764 | int csj; // Local copy (i.e. cached) of 'state[j]' |
||
2765 | int mask; // The mask for the current bit-plane |
||
2766 | int sym; // The symbol to code |
||
2767 | int rlclen; // Length of RLC |
||
2768 | int ctxt; // The context to use |
||
2769 | int[] data; // The data buffer |
||
2770 | int dist; // The distortion reduction for this pass |
||
2771 | int shift; // Shift amount for distortion |
||
2772 | int upshift; // Shift left amount for distortion |
||
2773 | int downshift; // Shift right amount for distortion |
||
2774 | int normval; // The normalized sample magnitude value |
||
2775 | int s; // The stripe index |
||
2776 | bool causal; // Flag to indicate if stripe-causal context |
||
2777 | // formation is to be used |
||
2778 | int nstripes; // The number of stripes in the code-block |
||
2779 | int sheight; // Height of the current stripe |
||
2780 | int off_ul, off_ur, off_dr, off_dl; // offsets |
||
2781 | |||
2782 | // Initialize local variables |
||
2783 | dscanw = srcblk.scanw; |
||
2784 | sscanw = srcblk.w + 2; |
||
2785 | jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - srcblk.w; |
||
2786 | kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - srcblk.w; |
||
2787 | mask = 1 << bp; |
||
2788 | data = (int[]) srcblk.Data; |
||
2789 | nstripes = (srcblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; |
||
2790 | dist = 0; |
||
2791 | // We use the MSE_LKP_BITS-1 bits below the bit just coded for |
||
2792 | // distortion estimation. |
||
2793 | shift = bp - MSE_LKP_BITS_M1; |
||
2794 | upshift = (shift >= 0)?0:- shift; |
||
2795 | downshift = (shift <= 0)?0:shift; |
||
2796 | causal = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL) != 0; |
||
2797 | |||
2798 | // Pre-calculate offsets in 'state' for diagonal neighbors |
||
2799 | off_ul = - sscanw - 1; // up-left |
||
2800 | off_ur = - sscanw + 1; // up-right |
||
2801 | off_dr = sscanw + 1; // down-right |
||
2802 | off_dl = sscanw - 1; // down-left |
||
2803 | |||
2804 | // Code stripe by stripe |
||
2805 | sk = srcblk.offset; |
||
2806 | sj = sscanw + 1; |
||
2807 | for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep) |
||
2808 | { |
||
2809 | sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:srcblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; |
||
2810 | stopsk = sk + srcblk.w; |
||
2811 | // Scan by set of 1 stripe column at a time |
||
2812 | for (nsym = 0; sk < stopsk; sk++, sj++) |
||
2813 | { |
||
2814 | // Start column |
||
2815 | j = sj; |
||
2816 | csj = state[j]; |
||
2817 | { |
||
2818 | // Check for RLC: if all samples are not significant, not |
||
2819 | // visited and do not have a non-zero context, and column |
||
2820 | // is full height, we do RLC. |
||
2821 | if (csj == 0 && state[j + sscanw] == 0 && sheight == CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT) |
||
2822 | { |
||
2823 | k = sk; |
||
2824 | if ((data[k] & mask) != 0) |
||
2825 | { |
||
2826 | rlclen = 0; |
||
2827 | } |
||
2828 | else if ((data[k += dscanw] & mask) != 0) |
||
2829 | { |
||
2830 | rlclen = 1; |
||
2831 | } |
||
2832 | else if ((data[k += dscanw] & mask) != 0) |
||
2833 | { |
||
2834 | rlclen = 2; |
||
2835 | j += sscanw; |
||
2836 | csj = state[j]; |
||
2837 | } |
||
2838 | else if ((data[k += dscanw] & mask) != 0) |
||
2839 | { |
||
2840 | rlclen = 3; |
||
2841 | j += sscanw; |
||
2842 | csj = state[j]; |
||
2843 | } |
||
2844 | else |
||
2845 | { |
||
2846 | // Code insignificant RLC |
||
2847 | symbuf[nsym] = 0; |
||
2848 | ctxtbuf[nsym++] = RLC_CTXT; |
||
2849 | // Goto next column |
||
2850 | continue; |
||
2851 | } |
||
2852 | // Code significant RLC |
||
2853 | symbuf[nsym] = 1; |
||
2854 | ctxtbuf[nsym++] = RLC_CTXT; |
||
2855 | // Send MSB bit index |
||
2856 | symbuf[nsym] = rlclen >> 1; |
||
2857 | ctxtbuf[nsym++] = UNIF_CTXT; |
||
2858 | // Send LSB bit index |
||
2859 | symbuf[nsym] = rlclen & 0x01; |
||
2860 | ctxtbuf[nsym++] = UNIF_CTXT; |
||
2861 | // Code sign of sample that became significant |
||
2862 | // Update distortion |
||
2863 | normval = (data[k] >> downshift) << upshift; |
||
2864 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
2865 | // Apply sign coding |
||
2866 | sym = SupportClass.URShift(data[k], 31); |
||
2867 | if ((rlclen & 0x01) == 0) |
||
2868 | { |
||
2869 | // Sample that became significant is first row of |
||
2870 | // its column half |
||
2871 | ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK]; |
||
2872 | symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); |
||
2873 | ctxtbuf[nsym++] = ctxt & SC_LUT_MASK; |
||
2874 | // Update state information (significant bit, |
||
2875 | // visited bit, neighbor significant bit of |
||
2876 | // neighbors, non zero context of neighbors, sign |
||
2877 | // of neighbors) |
||
2878 | if (rlclen != 0 || !causal) |
||
2879 | { |
||
2880 | // If in causal mode do not change contexts of |
||
2881 | // previous stripe. |
||
2882 | state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2; |
||
2883 | state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2; |
||
2884 | } |
||
2885 | // Update sign state information of neighbors |
||
2886 | if (sym != 0) |
||
2887 | { |
||
2888 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2; |
||
2889 | if (rlclen != 0 || !causal) |
||
2890 | { |
||
2891 | // If in causal mode do not change |
||
2892 | // contexts of previous stripe. |
||
2893 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2; |
||
2894 | } |
||
2895 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2; |
||
2896 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2; |
||
2897 | } |
||
2898 | else |
||
2899 | { |
||
2900 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2; |
||
2901 | if (rlclen != 0 || !causal) |
||
2902 | { |
||
2903 | // If in causal mode do not change |
||
2904 | // contexts of previous stripe. |
||
2905 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2; |
||
2906 | } |
||
2907 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2; |
||
2908 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2; |
||
2909 | } |
||
2910 | // Changes to csj are saved later |
||
2911 | if ((rlclen >> 1) != 0) |
||
2912 | { |
||
2913 | // Sample that became significant is in bottom |
||
2914 | // half of column => jump to bottom half |
||
2915 | //UPGRADE_NOTE: Labeled break statement was changed to a goto statement. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1012'" |
||
2916 | goto top_half_brk; |
||
2917 | } |
||
2918 | // Otherwise sample that became significant is in |
||
2919 | // top half of column => continue on top half |
||
2920 | } |
||
2921 | else |
||
2922 | { |
||
2923 | // Sample that became significant is second row of |
||
2924 | // its column half |
||
2925 | ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK]; |
||
2926 | symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); |
||
2927 | ctxtbuf[nsym++] = ctxt & SC_LUT_MASK; |
||
2928 | // Update state information (significant bit, |
||
2929 | // neighbor significant bit of neighbors, non zero |
||
2930 | // context of neighbors, sign of neighbors) |
||
2931 | state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1; |
||
2932 | state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1; |
||
2933 | // Update sign state information of neighbors |
||
2934 | if (sym != 0) |
||
2935 | { |
||
2936 | csj |= STATE_SIG_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1; |
||
2937 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1; |
||
2938 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2; |
||
2939 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2; |
||
2940 | } |
||
2941 | else |
||
2942 | { |
||
2943 | csj |= STATE_SIG_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1; |
||
2944 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1; |
||
2945 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2; |
||
2946 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2; |
||
2947 | } |
||
2948 | // Save changes to csj |
||
2949 | state[j] = csj; |
||
2950 | if ((rlclen >> 1) != 0) |
||
2951 | { |
||
2952 | // Sample that became significant is in bottom |
||
2953 | // half of column => we're done with this |
||
2954 | // column |
||
2955 | continue; |
||
2956 | } |
||
2957 | // Otherwise sample that became significant is in |
||
2958 | // top half of column => we're done with top |
||
2959 | // column |
||
2960 | j += sscanw; |
||
2961 | csj = state[j]; |
||
2962 | //UPGRADE_NOTE: Labeled break statement was changed to a goto statement. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1012'" |
||
2963 | goto top_half_brk; |
||
2964 | } |
||
2965 | } |
||
2966 | // Do half top of column |
||
2967 | // If any of the two samples is not significant and has |
||
2968 | // not been visited in the current bit-plane we can not |
||
2969 | // skip them |
||
2970 | if ((((csj >> 1) | csj) & VSTD_MASK_R1R2) != VSTD_MASK_R1R2) |
||
2971 | { |
||
2972 | k = sk; |
||
2973 | // Scan first row |
||
2974 | if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == 0) |
||
2975 | { |
||
2976 | // Apply zero coding |
||
2977 | ctxtbuf[nsym] = zc_lut[csj & ZC_MASK]; |
||
2978 | if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0) |
||
2979 | { |
||
2980 | // Became significant |
||
2981 | // Apply sign coding |
||
2982 | sym = SupportClass.URShift(data[k], 31); |
||
2983 | ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK]; |
||
2984 | symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); |
||
2985 | ctxtbuf[nsym++] = ctxt & SC_LUT_MASK; |
||
2986 | // Update state information (significant bit, |
||
2987 | // visited bit, neighbor significant bit of |
||
2988 | // neighbors, non zero context of neighbors, |
||
2989 | // sign of neighbors) |
||
2990 | if (!causal) |
||
2991 | { |
||
2992 | // If in causal mode do not change |
||
2993 | // contexts of previous stripe. |
||
2994 | state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2; |
||
2995 | state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2; |
||
2996 | } |
||
2997 | // Update sign state information of neighbors |
||
2998 | if (sym != 0) |
||
2999 | { |
||
3000 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2; |
||
3001 | if (!causal) |
||
3002 | { |
||
3003 | // If in causal mode do not change |
||
3004 | // contexts of previous stripe. |
||
3005 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2; |
||
3006 | } |
||
3007 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2; |
||
3008 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2; |
||
3009 | } |
||
3010 | else |
||
3011 | { |
||
3012 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2; |
||
3013 | if (!causal) |
||
3014 | { |
||
3015 | // If in causal mode do not change |
||
3016 | // contexts of previous stripe. |
||
3017 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2; |
||
3018 | } |
||
3019 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2; |
||
3020 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2; |
||
3021 | } |
||
3022 | // Update distortion |
||
3023 | normval = (data[k] >> downshift) << upshift; |
||
3024 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
3025 | } |
||
3026 | } |
||
3027 | if (sheight < 2) |
||
3028 | { |
||
3029 | csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2); |
||
3030 | state[j] = csj; |
||
3031 | continue; |
||
3032 | } |
||
3033 | // Scan second row |
||
3034 | if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == 0) |
||
3035 | { |
||
3036 | k += dscanw; |
||
3037 | // Apply zero coding |
||
3038 | ctxtbuf[nsym] = zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]; |
||
3039 | if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0) |
||
3040 | { |
||
3041 | // Became significant |
||
3042 | // Apply sign coding |
||
3043 | sym = SupportClass.URShift(data[k], 31); |
||
3044 | ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK]; |
||
3045 | symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); |
||
3046 | ctxtbuf[nsym++] = ctxt & SC_LUT_MASK; |
||
3047 | // Update state information (significant bit, |
||
3048 | // visited bit, neighbor significant bit of |
||
3049 | // neighbors, non zero context of neighbors, |
||
3050 | // sign of neighbors) |
||
3051 | state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1; |
||
3052 | state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1; |
||
3053 | // Update sign state information of neighbors |
||
3054 | if (sym != 0) |
||
3055 | { |
||
3056 | csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1; |
||
3057 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1; |
||
3058 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2; |
||
3059 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2; |
||
3060 | } |
||
3061 | else |
||
3062 | { |
||
3063 | csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1; |
||
3064 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1; |
||
3065 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2; |
||
3066 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2; |
||
3067 | } |
||
3068 | // Update distortion |
||
3069 | normval = (data[k] >> downshift) << upshift; |
||
3070 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
3071 | } |
||
3072 | } |
||
3073 | } |
||
3074 | csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2); |
||
3075 | state[j] = csj; |
||
3076 | // Do half bottom of column |
||
3077 | if (sheight < 3) |
||
3078 | continue; |
||
3079 | j += sscanw; |
||
3080 | csj = state[j]; |
||
3081 | } |
||
3082 | //UPGRADE_NOTE: Label 'top_half_brk' was added. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1011'" |
||
3083 | |||
3084 | top_half_brk: ; |
||
3085 | // end of 'top_half' block |
||
3086 | // If any of the two samples is not significant and has |
||
3087 | // not been visited in the current bit-plane we can not |
||
3088 | // skip them |
||
3089 | if ((((csj >> 1) | csj) & VSTD_MASK_R1R2) != VSTD_MASK_R1R2) |
||
3090 | { |
||
3091 | k = sk + (dscanw << 1); |
||
3092 | // Scan first row |
||
3093 | if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == 0) |
||
3094 | { |
||
3095 | // Apply zero coding |
||
3096 | ctxtbuf[nsym] = zc_lut[csj & ZC_MASK]; |
||
3097 | if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0) |
||
3098 | { |
||
3099 | // Became significant |
||
3100 | // Apply sign coding |
||
3101 | sym = SupportClass.URShift(data[k], 31); |
||
3102 | ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK]; |
||
3103 | symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); |
||
3104 | ctxtbuf[nsym++] = ctxt & SC_LUT_MASK; |
||
3105 | // Update state information (significant bit, |
||
3106 | // visited bit, neighbor significant bit of |
||
3107 | // neighbors, non zero context of neighbors, |
||
3108 | // sign of neighbors) |
||
3109 | state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2; |
||
3110 | state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2; |
||
3111 | // Update sign state information of neighbors |
||
3112 | if (sym != 0) |
||
3113 | { |
||
3114 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2; |
||
3115 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2; |
||
3116 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2; |
||
3117 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2; |
||
3118 | } |
||
3119 | else |
||
3120 | { |
||
3121 | csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2; |
||
3122 | state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2; |
||
3123 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2; |
||
3124 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2; |
||
3125 | } |
||
3126 | // Update distortion |
||
3127 | normval = (data[k] >> downshift) << upshift; |
||
3128 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
3129 | } |
||
3130 | } |
||
3131 | if (sheight < 4) |
||
3132 | { |
||
3133 | csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2); |
||
3134 | state[j] = csj; |
||
3135 | continue; |
||
3136 | } |
||
3137 | // Scan second row |
||
3138 | if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == 0) |
||
3139 | { |
||
3140 | k += dscanw; |
||
3141 | // Apply zero coding |
||
3142 | ctxtbuf[nsym] = zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]; |
||
3143 | if ((symbuf[nsym++] = SupportClass.URShift((data[k] & mask), bp)) != 0) |
||
3144 | { |
||
3145 | // Became significant |
||
3146 | // Apply sign coding |
||
3147 | sym = SupportClass.URShift(data[k], 31); |
||
3148 | ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK]; |
||
3149 | symbuf[nsym] = sym ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); |
||
3150 | ctxtbuf[nsym++] = ctxt & SC_LUT_MASK; |
||
3151 | // Update state information (significant bit, |
||
3152 | // visited bit, neighbor significant bit of |
||
3153 | // neighbors, non zero context of neighbors, |
||
3154 | // sign of neighbors) |
||
3155 | state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1; |
||
3156 | state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1; |
||
3157 | // Update sign state information of neighbors |
||
3158 | if (sym != 0) |
||
3159 | { |
||
3160 | csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1; |
||
3161 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1; |
||
3162 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2; |
||
3163 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2; |
||
3164 | } |
||
3165 | else |
||
3166 | { |
||
3167 | csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1; |
||
3168 | state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1; |
||
3169 | state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2; |
||
3170 | state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2; |
||
3171 | } |
||
3172 | // Update distortion |
||
3173 | normval = (data[k] >> downshift) << upshift; |
||
3174 | dist += fs[normval & ((1 << MSE_LKP_BITS_M1) - 1)]; |
||
3175 | } |
||
3176 | } |
||
3177 | } |
||
3178 | csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2); |
||
3179 | state[j] = csj; |
||
3180 | } |
||
3181 | // Code all buffered symbols, if any |
||
3182 | if (nsym > 0) |
||
3183 | mq.codeSymbols(symbuf, ctxtbuf, nsym); |
||
3184 | } |
||
3185 | |||
3186 | // Insert a segment marker if we need to |
||
3187 | if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_SEG_SYMBOLS) != 0) |
||
3188 | { |
||
3189 | mq.codeSymbols(SEG_SYMBOLS, SEG_SYMB_CTXTS, SEG_SYMBOLS.Length); |
||
3190 | } |
||
3191 | |||
3192 | // Reset the MQ context states if we need to |
||
3193 | if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ) != 0) |
||
3194 | { |
||
3195 | mq.resetCtxts(); |
||
3196 | } |
||
3197 | |||
3198 | // Terminate the MQ bit stream if we need to |
||
3199 | if (doterm) |
||
3200 | { |
||
3201 | ratebuf[pidx] = mq.terminate(); // Termination has special length |
||
3202 | } |
||
3203 | else |
||
3204 | { |
||
3205 | // Use normal length calculation |
||
3206 | ratebuf[pidx] = mq.NumCodedBytes; |
||
3207 | } |
||
3208 | // Add length of previous segments, if any |
||
3209 | if (ltpidx >= 0) |
||
3210 | { |
||
3211 | ratebuf[pidx] += ratebuf[ltpidx]; |
||
3212 | } |
||
3213 | // Finish length calculation if needed |
||
3214 | if (doterm) |
||
3215 | { |
||
3216 | mq.finishLengthCalculation(ratebuf, pidx); |
||
3217 | } |
||
3218 | // Return the reduction in distortion |
||
3219 | return dist; |
||
3220 | } |
||
3221 | |||
3222 | /// <summary> Ensures that at the end of a non-terminated coding pass there is not a |
||
3223 | /// 0xFF byte, modifying the stored rates if necessary. |
||
3224 | /// |
||
3225 | /// <p>Due to error resiliance reasons, a coding pass should never have its |
||
3226 | /// last byte be a 0xFF, since that can lead to the emulation of a resync |
||
3227 | /// marker. This method checks if that is the case, and reduces the rate |
||
3228 | /// for a given pass if necessary. The ommitted 0xFF will be synthetized by |
||
3229 | /// the decoder if necessary, as required by JPEG 2000. This method should |
||
3230 | /// only be called once that the entire code-block is coded.</p> |
||
3231 | /// |
||
3232 | /// <p>Passes that are terminated are not checked for the 0xFF byte, since |
||
3233 | /// it is assumed that the termination procedure does not output any |
||
3234 | /// trailing 0xFF. Checking the terminated segments would involve much more |
||
3235 | /// than just modifying the stored rates.</p> |
||
3236 | /// |
||
3237 | /// <p>NOTE: It is assumed by this method that the coded data does not |
||
3238 | /// contain consecutive 0xFF bytes, as is the case with the MQ and |
||
3239 | /// 'arithemetic coding bypass' bit stuffing policy. However, the |
||
3240 | /// termination policies used should also respect this requirement.</p> |
||
3241 | /// |
||
3242 | /// </summary> |
||
3243 | /// <param name="data">The coded data for the code-block |
||
3244 | /// |
||
3245 | /// </param> |
||
3246 | /// <param name="rates">The rate (i.e. accumulated number of bytes) for each |
||
3247 | /// coding pass |
||
3248 | /// |
||
3249 | /// </param> |
||
3250 | /// <param name="isterm">An array of flags indicating, for each pass, if it is |
||
3251 | /// terminated or not. If null it is assumed that no pass is terminated, |
||
3252 | /// except the last one. |
||
3253 | /// |
||
3254 | /// </param> |
||
3255 | /// <param name="n">The number of coding passes |
||
3256 | /// |
||
3257 | /// </param> |
||
3258 | static private void checkEndOfPassFF(byte[] data, int[] rates, bool[] isterm, int n) |
||
3259 | { |
||
3260 | int dp; // the position to test in 'data' |
||
3261 | |||
3262 | // If a pass ends in 0xFF we need to reduce the number of bytes in it, |
||
3263 | // so that it does not end in 0xFF. We only need to go back one byte |
||
3264 | // since there can be no consecutive 0xFF bytes. |
||
3265 | |||
3266 | // If there are no terminated passes avoid the test on 'isterm' |
||
3267 | if (isterm == null) |
||
3268 | { |
||
3269 | for (n--; n >= 0; n--) |
||
3270 | { |
||
3271 | dp = rates[n] - 1; |
||
3272 | if (dp >= 0 && (data[dp] == (byte)0xFF)) |
||
3273 | { |
||
3274 | rates[n]--; |
||
3275 | } |
||
3276 | } |
||
3277 | } |
||
3278 | else |
||
3279 | { |
||
3280 | for (n--; n >= 0; n--) |
||
3281 | { |
||
3282 | if (!isterm[n]) |
||
3283 | { |
||
3284 | dp = rates[n] - 1; |
||
3285 | if (dp >= 0 && (data[dp] == (byte)0xFF)) |
||
3286 | { |
||
3287 | rates[n]--; |
||
3288 | } |
||
3289 | } |
||
3290 | } |
||
3291 | } |
||
3292 | } |
||
3293 | |||
3294 | /// <summary> Load options, length calculation type and termination type for each |
||
3295 | /// tile-component. |
||
3296 | /// |
||
3297 | /// </summary> |
||
3298 | /// <param name="nt">The number of tiles |
||
3299 | /// |
||
3300 | /// </param> |
||
3301 | /// <param name="nc">The number of components |
||
3302 | /// |
||
3303 | /// </param> |
||
3304 | public virtual void initTileComp(int nt, int nc) |
||
3305 | { |
||
3306 | |||
3307 | opts = new int[nt][]; |
||
3308 | for (int i2 = 0; i2 < nt; i2++) |
||
3309 | { |
||
3310 | opts[i2] = new int[nc]; |
||
3311 | } |
||
3312 | lenCalc = new int[nt][]; |
||
3313 | for (int i3 = 0; i3 < nt; i3++) |
||
3314 | { |
||
3315 | lenCalc[i3] = new int[nc]; |
||
3316 | } |
||
3317 | tType = new int[nt][]; |
||
3318 | for (int i4 = 0; i4 < nt; i4++) |
||
3319 | { |
||
3320 | tType[i4] = new int[nc]; |
||
3321 | } |
||
3322 | |||
3323 | for (int t = 0; t < nt; t++) |
||
3324 | { |
||
3325 | for (int c = 0; c < nc; c++) |
||
3326 | { |
||
3327 | opts[t][c] = 0; |
||
3328 | |||
3329 | // Bypass coding mode ? |
||
3330 | if (((System.String) bms.getTileCompVal(t, c)).ToUpper().Equals("on".ToUpper())) |
||
3331 | { |
||
3332 | opts[t][c] |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS; |
||
3333 | } |
||
3334 | // MQ reset after each coding pass ? |
||
3335 | if (((System.String) mqrs.getTileCompVal(t, c)).ToUpper().Equals("on".ToUpper())) |
||
3336 | { |
||
3337 | opts[t][c] |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ; |
||
3338 | } |
||
3339 | // MQ termination after each arithmetically coded coding pass ? |
||
3340 | if (((System.String) rts.getTileCompVal(t, c)).ToUpper().Equals("on".ToUpper())) |
||
3341 | { |
||
3342 | opts[t][c] |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS; |
||
3343 | } |
||
3344 | // Vertically stripe-causal context mode ? |
||
3345 | if (((System.String) css.getTileCompVal(t, c)).ToUpper().Equals("on".ToUpper())) |
||
3346 | { |
||
3347 | opts[t][c] |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL; |
||
3348 | } |
||
3349 | // Error resilience segmentation symbol insertion ? |
||
3350 | if (((System.String) sss.getTileCompVal(t, c)).ToUpper().Equals("on".ToUpper())) |
||
3351 | { |
||
3352 | opts[t][c] |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_SEG_SYMBOLS; |
||
3353 | } |
||
3354 | |||
3355 | // Set length calculation type of the MQ coder |
||
3356 | System.String lCalcType = (System.String) lcs.getTileCompVal(t, c); |
||
3357 | if (lCalcType.Equals("near_opt")) |
||
3358 | { |
||
3359 | lenCalc[t][c] = MQCoder.LENGTH_NEAR_OPT; |
||
3360 | } |
||
3361 | else if (lCalcType.Equals("lazy_good")) |
||
3362 | { |
||
3363 | lenCalc[t][c] = MQCoder.LENGTH_LAZY_GOOD; |
||
3364 | } |
||
3365 | else if (lCalcType.Equals("lazy")) |
||
3366 | { |
||
3367 | lenCalc[t][c] = MQCoder.LENGTH_LAZY; |
||
3368 | } |
||
3369 | else |
||
3370 | { |
||
3371 | throw new System.ArgumentException("Unrecognized or " + "unsupported MQ " + "length calculation."); |
||
3372 | } |
||
3373 | |||
3374 | // Set termination type of MQ coder |
||
3375 | System.String termType = (System.String) tts.getTileCompVal(t, c); |
||
3376 | if (termType.ToUpper().Equals("easy".ToUpper())) |
||
3377 | { |
||
3378 | tType[t][c] = MQCoder.TERM_EASY; |
||
3379 | } |
||
3380 | else if (termType.ToUpper().Equals("full".ToUpper())) |
||
3381 | { |
||
3382 | tType[t][c] = MQCoder.TERM_FULL; |
||
3383 | } |
||
3384 | else if (termType.ToUpper().Equals("near_opt".ToUpper())) |
||
3385 | { |
||
3386 | tType[t][c] = MQCoder.TERM_NEAR_OPT; |
||
3387 | } |
||
3388 | else if (termType.ToUpper().Equals("predict".ToUpper())) |
||
3389 | { |
||
3390 | tType[t][c] = MQCoder.TERM_PRED_ER; |
||
3391 | opts[t][c] |= CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM; |
||
3392 | if ((opts[t][c] & (CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS | CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS)) == 0) |
||
3393 | { |
||
3394 | FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.INFO, "Using error resilient MQ" + " termination, but terminating only at " + "the end of code-blocks. The error " + "protection offered by this option will" + " be very weak. Specify the " + "'Cterminate' " + "and/or 'Cbypass' option for " + "increased error resilience."); |
||
3395 | } |
||
3396 | } |
||
3397 | else |
||
3398 | { |
||
3399 | throw new System.ArgumentException("Unrecognized or " + "unsupported " + "MQ coder " + "termination."); |
||
3400 | } |
||
3401 | } // End loop on components |
||
3402 | } // End loop on tiles |
||
3403 | } |
||
3404 | |||
3405 | /// <summary> Returns the precinct partition width for the specified component, tile |
||
3406 | /// and resolution level. |
||
3407 | /// |
||
3408 | /// </summary> |
||
3409 | /// <param name="t">the tile index |
||
3410 | /// |
||
3411 | /// </param> |
||
3412 | /// <param name="c">the component |
||
3413 | /// |
||
3414 | /// </param> |
||
3415 | /// <param name="rl">the resolution level |
||
3416 | /// |
||
3417 | /// </param> |
||
3418 | /// <returns> The precinct partition width for the specified component, tile |
||
3419 | /// and resolution level |
||
3420 | /// |
||
3421 | /// </returns> |
||
3422 | public override int getPPX(int t, int c, int rl) |
||
3423 | { |
||
3424 | return pss.getPPX(t, c, rl); |
||
3425 | } |
||
3426 | |||
3427 | /// <summary> Returns the precinct partition height for the specified component, tile |
||
3428 | /// and resolution level. |
||
3429 | /// |
||
3430 | /// </summary> |
||
3431 | /// <param name="t">the tile index |
||
3432 | /// |
||
3433 | /// </param> |
||
3434 | /// <param name="c">the component |
||
3435 | /// |
||
3436 | /// </param> |
||
3437 | /// <param name="rl">the resolution level |
||
3438 | /// |
||
3439 | /// </param> |
||
3440 | /// <returns> The precinct partition height for the specified component, tile |
||
3441 | /// and resolution level |
||
3442 | /// |
||
3443 | /// </returns> |
||
3444 | public override int getPPY(int t, int c, int rl) |
||
3445 | { |
||
3446 | return pss.getPPY(t, c, rl); |
||
3447 | } |
||
3448 | |||
3449 | /// <summary> Returns true if precinct partition is used for the specified component |
||
3450 | /// and tile, returns false otherwise. |
||
3451 | /// |
||
3452 | /// </summary> |
||
3453 | /// <param name="c">The component |
||
3454 | /// |
||
3455 | /// </param> |
||
3456 | /// <param name="t">The tile |
||
3457 | /// |
||
3458 | /// </param> |
||
3459 | /// <returns> True if precinct partition is used for the specified component |
||
3460 | /// and tile, returns false otherwise. |
||
3461 | /// |
||
3462 | /// </returns> |
||
3463 | public override bool precinctPartitionUsed(int c, int t) |
||
3464 | { |
||
3465 | return precinctPartition[c][t]; |
||
3466 | } |
||
3467 | /// <summary>Static initializer: initializes all the lookup tables. </summary> |
||
3468 | static StdEntropyCoder() |
||
3469 | { |
||
3470 | { |
||
3471 | int i, j; |
||
3472 | double val, deltaMSE; |
||
3473 | int[] inter_sc_lut; |
||
3474 | int ds, us, rs, ls; |
||
3475 | int dsgn, usgn, rsgn, lsgn; |
||
3476 | int h, v; |
||
3477 | |||
3478 | // Initialize the zero coding lookup tables |
||
3479 | |||
3480 | // LH |
||
3481 | |||
3482 | // - No neighbors significant |
||
3483 | ZC_LUT_LH[0] = 2; |
||
3484 | |||
3485 | // - No horizontal or vertical neighbors significant |
||
3486 | for (i = 1; i < 16; i++) |
||
3487 | { |
||
3488 | // Two or more diagonal coeffs significant |
||
3489 | ZC_LUT_LH[i] = 4; |
||
3490 | } |
||
3491 | for (i = 0; i < 4; i++) |
||
3492 | { |
||
3493 | // Only one diagonal coeff significant |
||
3494 | ZC_LUT_LH[1 << i] = 3; |
||
3495 | } |
||
3496 | // - No horizontal neighbors significant, diagonal irrelevant |
||
3497 | for (i = 0; i < 16; i++) |
||
3498 | { |
||
3499 | // Only one vertical coeff significant |
||
3500 | ZC_LUT_LH[STATE_V_U_R1 | i] = 5; |
||
3501 | ZC_LUT_LH[STATE_V_D_R1 | i] = 5; |
||
3502 | // The two vertical coeffs significant |
||
3503 | ZC_LUT_LH[STATE_V_U_R1 | STATE_V_D_R1 | i] = 6; |
||
3504 | } |
||
3505 | // - One horiz. neighbor significant, diagonal/vertical non-significant |
||
3506 | ZC_LUT_LH[STATE_H_L_R1] = 7; |
||
3507 | ZC_LUT_LH[STATE_H_R_R1] = 7; |
||
3508 | // - One horiz. significant, no vertical significant, one or more |
||
3509 | // diagonal significant |
||
3510 | for (i = 1; i < 16; i++) |
||
3511 | { |
||
3512 | ZC_LUT_LH[STATE_H_L_R1 | i] = 8; |
||
3513 | ZC_LUT_LH[STATE_H_R_R1 | i] = 8; |
||
3514 | } |
||
3515 | // - One horiz. significant, one or more vertical significant, |
||
3516 | // diagonal irrelevant |
||
3517 | for (i = 1; i < 4; i++) |
||
3518 | { |
||
3519 | for (j = 0; j < 16; j++) |
||
3520 | { |
||
3521 | ZC_LUT_LH[STATE_H_L_R1 | (i << 4) | j] = 9; |
||
3522 | ZC_LUT_LH[STATE_H_R_R1 | (i << 4) | j] = 9; |
||
3523 | } |
||
3524 | } |
||
3525 | // - Two horiz. significant, others irrelevant |
||
3526 | for (i = 0; i < 64; i++) |
||
3527 | { |
||
3528 | ZC_LUT_LH[STATE_H_L_R1 | STATE_H_R_R1 | i] = 10; |
||
3529 | } |
||
3530 | |||
3531 | // HL |
||
3532 | |||
3533 | // - No neighbors significant |
||
3534 | ZC_LUT_HL[0] = 2; |
||
3535 | // - No horizontal or vertical neighbors significant |
||
3536 | for (i = 1; i < 16; i++) |
||
3537 | { |
||
3538 | // Two or more diagonal coeffs significant |
||
3539 | ZC_LUT_HL[i] = 4; |
||
3540 | } |
||
3541 | for (i = 0; i < 4; i++) |
||
3542 | { |
||
3543 | // Only one diagonal coeff significant |
||
3544 | ZC_LUT_HL[1 << i] = 3; |
||
3545 | } |
||
3546 | // - No vertical significant, diagonal irrelevant |
||
3547 | for (i = 0; i < 16; i++) |
||
3548 | { |
||
3549 | // One horiz. significant |
||
3550 | ZC_LUT_HL[STATE_H_L_R1 | i] = 5; |
||
3551 | ZC_LUT_HL[STATE_H_R_R1 | i] = 5; |
||
3552 | // Two horiz. significant |
||
3553 | ZC_LUT_HL[STATE_H_L_R1 | STATE_H_R_R1 | i] = 6; |
||
3554 | } |
||
3555 | // - One vert. significant, diagonal/horizontal non-significant |
||
3556 | ZC_LUT_HL[STATE_V_U_R1] = 7; |
||
3557 | ZC_LUT_HL[STATE_V_D_R1] = 7; |
||
3558 | // - One vert. significant, horizontal non-significant, one or more |
||
3559 | // diag. significant |
||
3560 | for (i = 1; i < 16; i++) |
||
3561 | { |
||
3562 | ZC_LUT_HL[STATE_V_U_R1 | i] = 8; |
||
3563 | ZC_LUT_HL[STATE_V_D_R1 | i] = 8; |
||
3564 | } |
||
3565 | // - One vertical significant, one or more horizontal significant, |
||
3566 | // diagonal irrelevant |
||
3567 | for (i = 1; i < 4; i++) |
||
3568 | { |
||
3569 | for (j = 0; j < 16; j++) |
||
3570 | { |
||
3571 | ZC_LUT_HL[(i << 6) | STATE_V_U_R1 | j] = 9; |
||
3572 | ZC_LUT_HL[(i << 6) | STATE_V_D_R1 | j] = 9; |
||
3573 | } |
||
3574 | } |
||
3575 | // - Two vertical significant, others irrelevant |
||
3576 | for (i = 0; i < 4; i++) |
||
3577 | { |
||
3578 | for (j = 0; j < 16; j++) |
||
3579 | { |
||
3580 | ZC_LUT_HL[(i << 6) | STATE_V_U_R1 | STATE_V_D_R1 | j] = 10; |
||
3581 | } |
||
3582 | } |
||
3583 | |||
3584 | // HH |
||
3585 | int[] twoBits = new int[]{3, 5, 6, 9, 10, 12}; // Figures (between 0 and 15) |
||
3586 | // countaning 2 and only 2 bits on in its binary representation. |
||
3587 | |||
3588 | int[] oneBit = new int[]{1, 2, 4, 8}; // Figures (between 0 and 15) |
||
3589 | // countaning 1 and only 1 bit on in its binary representation. |
||
3590 | |||
3591 | int[] twoLeast = new int[]{3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15}; // Figures |
||
3592 | // (between 0 and 15) countaining, at least, 2 bits on in its |
||
3593 | // binary representation. |
||
3594 | |||
3595 | int[] threeLeast = new int[]{7, 11, 13, 14, 15}; // Figures |
||
3596 | // (between 0 and 15) countaining, at least, 3 bits on in its |
||
3597 | // binary representation. |
||
3598 | |||
3599 | // - None significant |
||
3600 | ZC_LUT_HH[0] = 2; |
||
3601 | |||
3602 | // - One horizontal+vertical significant, none diagonal |
||
3603 | for (i = 0; i < oneBit.Length; i++) |
||
3604 | ZC_LUT_HH[oneBit[i] << 4] = 3; |
||
3605 | |||
3606 | // - Two or more horizontal+vertical significant, diagonal non-signif |
||
3607 | for (i = 0; i < twoLeast.Length; i++) |
||
3608 | ZC_LUT_HH[twoLeast[i] << 4] = 4; |
||
3609 | |||
3610 | // - One diagonal significant, horiz./vert. non-significant |
||
3611 | for (i = 0; i < oneBit.Length; i++) |
||
3612 | ZC_LUT_HH[oneBit[i]] = 5; |
||
3613 | |||
3614 | // - One diagonal significant, one horiz.+vert. significant |
||
3615 | for (i = 0; i < oneBit.Length; i++) |
||
3616 | for (j = 0; j < oneBit.Length; j++) |
||
3617 | ZC_LUT_HH[(oneBit[i] << 4) | oneBit[j]] = 6; |
||
3618 | |||
3619 | // - One diag signif, two or more horiz+vert signif |
||
3620 | for (i = 0; i < twoLeast.Length; i++) |
||
3621 | for (j = 0; j < oneBit.Length; j++) |
||
3622 | ZC_LUT_HH[(twoLeast[i] << 4) | oneBit[j]] = 7; |
||
3623 | |||
3624 | // - Two diagonal significant, none horiz+vert significant |
||
3625 | for (i = 0; i < twoBits.Length; i++) |
||
3626 | ZC_LUT_HH[twoBits[i]] = 8; |
||
3627 | |||
3628 | // - Two diagonal significant, one or more horiz+vert significant |
||
3629 | for (j = 0; j < twoBits.Length; j++) |
||
3630 | for (i = 1; i < 16; i++) |
||
3631 | ZC_LUT_HH[(i << 4) | twoBits[j]] = 9; |
||
3632 | |||
3633 | // - Three or more diagonal significant, horiz+vert irrelevant |
||
3634 | for (i = 0; i < 16; i++) |
||
3635 | for (j = 0; j < threeLeast.Length; j++) |
||
3636 | ZC_LUT_HH[(i << 4) | threeLeast[j]] = 10; |
||
3637 | |||
3638 | // Initialize the SC lookup tables |
||
3639 | |||
3640 | // Use an intermediate sign code lookup table that is similar to the |
||
3641 | // one in the VM text, in that it depends on the 'h' and 'v' |
||
3642 | // quantities. The index into this table is a 6 bit index, the top 3 |
||
3643 | // bits are (h+1) and the low 3 bits (v+1). |
||
3644 | inter_sc_lut = new int[36]; |
||
3645 | inter_sc_lut[(2 << 3) | 2] = 15; |
||
3646 | inter_sc_lut[(2 << 3) | 1] = 14; |
||
3647 | inter_sc_lut[(2 << 3) | 0] = 13; |
||
3648 | inter_sc_lut[(1 << 3) | 2] = 12; |
||
3649 | inter_sc_lut[(1 << 3) | 1] = 11; |
||
3650 | inter_sc_lut[(1 << 3) | 0] = 12 | INT_SIGN_BIT; |
||
3651 | inter_sc_lut[(0 << 3) | 2] = 13 | INT_SIGN_BIT; |
||
3652 | inter_sc_lut[(0 << 3) | 1] = 14 | INT_SIGN_BIT; |
||
3653 | inter_sc_lut[(0 << 3) | 0] = 15 | INT_SIGN_BIT; |
||
3654 | |||
3655 | // Using the intermediate sign code lookup table create the final |
||
3656 | // one. The index into this table is a 9 bit index, the low 4 bits are |
||
3657 | // the significance of the 4 horizontal/vertical neighbors, while the |
||
3658 | // top 4 bits are the signs of those neighbors. The bit in the middle |
||
3659 | // is ignored. This index arrangement matches the state bits in the |
||
3660 | // 'state' array, thus direct addressing of the table can be done from |
||
3661 | // the sate information. |
||
3662 | for (i = 0; i < (1 << SC_LUT_BITS) - 1; i++) |
||
3663 | { |
||
3664 | ds = i & 0x01; // significance of down neighbor |
||
3665 | us = (i >> 1) & 0x01; // significance of up neighbor |
||
3666 | rs = (i >> 2) & 0x01; // significance of right neighbor |
||
3667 | ls = (i >> 3) & 0x01; // significance of left neighbor |
||
3668 | dsgn = (i >> 5) & 0x01; // sign of down neighbor |
||
3669 | usgn = (i >> 6) & 0x01; // sign of up neighbor |
||
3670 | rsgn = (i >> 7) & 0x01; // sign of right neighbor |
||
3671 | lsgn = (i >> 8) & 0x01; // sign of left neighbor |
||
3672 | // Calculate 'h' and 'v' as in VM text |
||
3673 | h = ls * (1 - 2 * lsgn) + rs * (1 - 2 * rsgn); |
||
3674 | h = (h >= - 1)?h:- 1; |
||
3675 | h = (h <= 1)?h:1; |
||
3676 | v = us * (1 - 2 * usgn) + ds * (1 - 2 * dsgn); |
||
3677 | v = (v >= - 1)?v:- 1; |
||
3678 | v = (v <= 1)?v:1; |
||
3679 | // Get context and sign predictor from 'inter_sc_lut' |
||
3680 | SC_LUT[i] = inter_sc_lut[(h + 1) << 3 | (v + 1)]; |
||
3681 | } |
||
3682 | inter_sc_lut = null; |
||
3683 | |||
3684 | // Initialize the MR lookup tables |
||
3685 | |||
3686 | // None significant, prev MR off |
||
3687 | MR_LUT[0] = 16; |
||
3688 | // One or more significant, prev MR off |
||
3689 | for (i = 1; i < (1 << (MR_LUT_BITS - 1)); i++) |
||
3690 | { |
||
3691 | MR_LUT[i] = 17; |
||
3692 | } |
||
3693 | // Previous MR on, significance irrelevant |
||
3694 | for (; i < (1 << MR_LUT_BITS); i++) |
||
3695 | { |
||
3696 | MR_LUT[i] = 18; |
||
3697 | } |
||
3698 | |||
3699 | // Initialize the distortion estimation lookup tables |
||
3700 | |||
3701 | // fs tables |
||
3702 | for (i = 0; i < (1 << MSE_LKP_BITS_M1); i++) |
||
3703 | { |
||
3704 | // In fs we index by val-1, since val is really: 1 <= val < 2 |
||
3705 | val = (double) i / (1 << MSE_LKP_BITS_M1) + 1.0; |
||
3706 | deltaMSE = val * val; |
||
3707 | //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'" |
||
3708 | FS_LOSSLESS[i] = (int) System.Math.Floor(deltaMSE * ((double) (1 << MSE_LKP_FRAC_BITS)) + 0.5); |
||
3709 | val -= 1.5; |
||
3710 | deltaMSE -= val * val; |
||
3711 | //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'" |
||
3712 | FS_LOSSY[i] = (int) System.Math.Floor(deltaMSE * ((double) (1 << MSE_LKP_FRAC_BITS)) + 0.5); |
||
3713 | } |
||
3714 | |||
3715 | // fm tables |
||
3716 | for (i = 0; i < (1 << MSE_LKP_BITS); i++) |
||
3717 | { |
||
3718 | val = (double) i / (1 << MSE_LKP_BITS_M1); |
||
3719 | deltaMSE = (val - 1.0) * (val - 1.0); |
||
3720 | //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'" |
||
3721 | FM_LOSSLESS[i] = (int) System.Math.Floor(deltaMSE * ((double) (1 << MSE_LKP_FRAC_BITS)) + 0.5); |
||
3722 | val -= ((i < (1 << MSE_LKP_BITS_M1))?0.5:1.5); |
||
3723 | deltaMSE -= val * val; |
||
3724 | //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'" |
||
3725 | FM_LOSSY[i] = (int) System.Math.Floor(deltaMSE * ((double) (1 << MSE_LKP_FRAC_BITS)) + 0.5); |
||
3726 | } |
||
3727 | } |
||
3728 | } |
||
3729 | } |
||
3730 | } |