|
1 /* |
|
2 * Copyright (c) 2003-2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: CJp2kReadCodec class implements the ICL read codec interface. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include <fbs.h> |
|
21 #include <JP2KImageData.h> |
|
22 #include "JP2KImageUtils.h" |
|
23 #include "JP2KFormat.h" |
|
24 #include "JP2KStreamReader.h" |
|
25 #include "JP2KTileInfo.h" |
|
26 #include "JP2KImageInfo.h" |
|
27 #include "JP2KCodec.h" |
|
28 #include "JP2KEntropyDecoder.h" |
|
29 #include "JP2KImageWriter.h" |
|
30 #include "JP2KSynthesis.h" |
|
31 |
|
32 // EXTERNAL DATA STRUCTURES |
|
33 |
|
34 // EXTERNAL FUNCTION PROTOTYPES |
|
35 |
|
36 // CONSTANTS |
|
37 |
|
38 // MACROS |
|
39 |
|
40 // LOCAL CONSTANTS AND MACROS |
|
41 |
|
42 // MODULE DATA STRUCTURES |
|
43 |
|
44 // LOCAL FUNCTION PROTOTYPES |
|
45 |
|
46 // FORWARD DECLARATIONS |
|
47 |
|
48 // ============================= LOCAL FUNCTIONS =============================== |
|
49 |
|
50 // ============================ MEMBER FUNCTIONS =============================== |
|
51 |
|
52 // ----------------------------------------------------------------------------- |
|
53 // CJp2kReadCodec::NewL |
|
54 // Two-phased constructor. |
|
55 // ----------------------------------------------------------------------------- |
|
56 // |
|
57 CJp2kReadCodec* CJp2kReadCodec::NewL( const TJ2kInfo& aJ2kInfo ) |
|
58 { |
|
59 CJp2kReadCodec* self = new ( ELeave ) CJp2kReadCodec( aJ2kInfo ); |
|
60 |
|
61 CleanupStack::PushL( self ); |
|
62 self->ConstructL(); |
|
63 CleanupStack::Pop( self ); |
|
64 |
|
65 return self; |
|
66 } |
|
67 |
|
68 // Destructor |
|
69 CJp2kReadCodec::~CJp2kReadCodec() |
|
70 { |
|
71 delete iImageInfo; |
|
72 iImageInfo = 0; |
|
73 |
|
74 delete iEntropy; |
|
75 iEntropy = 0; |
|
76 |
|
77 delete iImageWriter; |
|
78 iImageWriter = 0; |
|
79 |
|
80 delete iSynthesis; |
|
81 iSynthesis = 0; |
|
82 } |
|
83 |
|
84 // ----------------------------------------------------------------------------- |
|
85 // CJp2kReadCodec::DecodeTileL |
|
86 // Decoding the current tile-part |
|
87 // (other items were commented in a header). |
|
88 // ----------------------------------------------------------------------------- |
|
89 // |
|
90 TFrameState CJp2kReadCodec::DecodeTileL() |
|
91 { |
|
92 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
93 |
|
94 // Decode and delete the tile |
|
95 DecodeAndDeleteTileL( tile ); |
|
96 |
|
97 // reset the codec back to the parsing state |
|
98 iDecodeTile = EFalse; |
|
99 TFrameState retCode = EFrameIncomplete; |
|
100 |
|
101 // Start with new tile |
|
102 iUseNewTile = ETrue; |
|
103 if ( !iUseNextTile ) |
|
104 { |
|
105 iFHState = EStateInUnknown; |
|
106 retCode = EFrameIncompleteRepositionRequest; |
|
107 } |
|
108 else |
|
109 { |
|
110 if ( !iSequential ) |
|
111 { |
|
112 // Must be End of Codestream EOC |
|
113 iFHState = EStateInEOC; |
|
114 retCode = EFrameComplete; |
|
115 } |
|
116 else if ( iFHState == EStateInEOC ) |
|
117 { |
|
118 retCode = EFrameComplete; |
|
119 } |
|
120 else |
|
121 { |
|
122 iFHState = EStateInUnknown; |
|
123 } |
|
124 } |
|
125 return retCode; |
|
126 } |
|
127 |
|
128 // ----------------------------------------------------------------------------- |
|
129 // CJp2kReadCodec::IsDecodeTile |
|
130 // Is codec in the decoding state |
|
131 // (other items were commented in a header). |
|
132 // ----------------------------------------------------------------------------- |
|
133 // |
|
134 TBool CJp2kReadCodec::IsDecodeTile() const |
|
135 { |
|
136 return iDecodeTile; |
|
137 } |
|
138 |
|
139 // ----------------------------------------------------------------------------- |
|
140 // CJp2kReadCodec::InitFrameHeader |
|
141 // (other items were commented in a header). |
|
142 // ----------------------------------------------------------------------------- |
|
143 // |
|
144 void CJp2kReadCodec::InitFrameHeader( TFrameInfo& aFrameInfo, CFrameImageData& aFrameData ) |
|
145 { |
|
146 // Initialize internal data structure for holding frame header |
|
147 ASSERT( aFrameInfo.CurrentFrameState() == TFrameInfo::EFrameInfoUninitialised ); |
|
148 |
|
149 iFrame = &aFrameInfo; |
|
150 iFrameData = &aFrameData; |
|
151 aFrameInfo.SetCurrentFrameState( TFrameInfo::EFrameInfoProcessingFrameHeader ); |
|
152 } |
|
153 |
|
154 // ----------------------------------------------------------------------------- |
|
155 // CJp2kReadCodec::ProcessFrameHeaderL |
|
156 // Collect the JP2 codestream Main Header information. |
|
157 // (other items were commented in a header). |
|
158 // ----------------------------------------------------------------------------- |
|
159 // |
|
160 TFrameState CJp2kReadCodec::ProcessFrameHeaderL( TBufPtr8& aData ) |
|
161 { |
|
162 // Read frame header and fill up internal data structure |
|
163 TFrameState retCode = EFrameIncomplete; |
|
164 |
|
165 iReader.iPtr = aData.Ptr(); |
|
166 iReader.iPtrStart = CONST_CAST( TUint8*, iReader.iPtr ); |
|
167 iReader.iPtrEnd = iReader.iPtrStart + aData.Length(); |
|
168 |
|
169 while ( iFHState != EStateInSOT ) |
|
170 { |
|
171 iReader.iPtrStartMarker = CONST_CAST( TUint8*, iReader.iPtr ); |
|
172 switch ( iFHState ) |
|
173 { |
|
174 case EStateInSOC: |
|
175 { |
|
176 retCode = ReadSOCL(); |
|
177 break; |
|
178 } |
|
179 case EStateInSIZ: |
|
180 { |
|
181 retCode = ReadSIZL(); |
|
182 break; |
|
183 } |
|
184 case EStateInCOD: |
|
185 { |
|
186 retCode = ReadCODL(); |
|
187 break; |
|
188 } |
|
189 case EStateInCOC: |
|
190 { |
|
191 retCode = ReadCOCL(); |
|
192 break; |
|
193 } |
|
194 case EStateInQCD: |
|
195 { |
|
196 retCode = ReadQCDL(); |
|
197 break; |
|
198 } |
|
199 case EStateInQCC: |
|
200 { |
|
201 retCode = ReadQCCL(); |
|
202 break; |
|
203 } |
|
204 case EStateInRGN: |
|
205 { |
|
206 retCode = ReadRGNL(); |
|
207 break; |
|
208 } |
|
209 case EStateInPOC: |
|
210 { |
|
211 retCode = ReadPOCL(); |
|
212 break; |
|
213 } |
|
214 case EStateInPPM: |
|
215 { |
|
216 retCode = ReadPPML(); |
|
217 break; |
|
218 } |
|
219 case EStateInTLM: |
|
220 { |
|
221 retCode = ReadTLML(); |
|
222 break; |
|
223 } |
|
224 case EStateInPLM: |
|
225 { |
|
226 retCode = ReadPLML(); |
|
227 break; |
|
228 } |
|
229 case EStateInCRG: |
|
230 { |
|
231 retCode = ReadCRGL(); |
|
232 break; |
|
233 } |
|
234 case EStateInCOM: |
|
235 { |
|
236 retCode = ReadCOML(); |
|
237 break; |
|
238 } |
|
239 case EStateInUnknown: |
|
240 { |
|
241 // Update the internal state based on the Marker |
|
242 retCode = UpdateStateFromMarkerL(); |
|
243 break; |
|
244 } |
|
245 default: |
|
246 { |
|
247 // Unrecognized marker |
|
248 User::Leave( KErrCorrupt ); |
|
249 break; |
|
250 } |
|
251 } |
|
252 // Check for underflow |
|
253 if ( retCode != EFrameComplete ) |
|
254 { |
|
255 aData.Shift( iReader.iPtr - iReader.iPtrStart ); |
|
256 return retCode; |
|
257 } |
|
258 |
|
259 // Update the internal counter for data processed |
|
260 iReader.UpdateMainHeader(); |
|
261 } |
|
262 |
|
263 // Convert the MainHeader's COM marker to TJp2kComment |
|
264 // and let the framework managing the buffer. |
|
265 TMainMarker& mainMarker = CONST_CAST( TMainMarker&, iImageInfo->MainMarker() ); |
|
266 for ( TInt index = 0; index < mainMarker.iCom.Count(); ++index ) |
|
267 { |
|
268 TJp2kComment* jp2kComment = new ( ELeave ) TJp2kComment; |
|
269 CleanupDeletePushL( jp2kComment ); |
|
270 |
|
271 jp2kComment->iComment = mainMarker.iCom[index]->iCcom; |
|
272 |
|
273 User::LeaveIfError( iFrameData->AppendImageData( jp2kComment ) ); |
|
274 CleanupStack::Pop(); |
|
275 |
|
276 // Transfer the ownership of the buffer from TMainMarker to framework |
|
277 User::LeaveIfError( iFrameData->AppendImageBuffer( jp2kComment->iComment ) ); |
|
278 mainMarker.iCom[index]->iCcom = 0; |
|
279 } |
|
280 |
|
281 // Convert some metadata from file format to TImageDataBlock derived objects |
|
282 ConvertImageDataL(); |
|
283 |
|
284 // Try to sort PPM and PLM if there is one |
|
285 iImageInfo->DoCompactMainHeaderL(); |
|
286 |
|
287 aData.Shift( iReader.iPtr - iReader.iPtrStart ); |
|
288 |
|
289 // Fill up the image related information if it is not |
|
290 // JP2 file format |
|
291 if ( !( iJ2kInfo.iOption & TJ2kInfo::EJP2file ) ) |
|
292 { |
|
293 const TSizMarker &sizMarker = iImageInfo->SizMarker(); |
|
294 |
|
295 // To get the right output image size, we must compute the size tile by tile. |
|
296 // Compute the width of the output image |
|
297 TInt32 tileCompCanvasWidth = 0; |
|
298 TInt32 numHorTiles = iImageInfo->NumOfHorizTiles(); |
|
299 TInt32 tileStartCanvas; |
|
300 TInt32 tileEndCanvas; |
|
301 TInt32 tileCompStartCanvas; |
|
302 for(TUint16 indexX = 0; indexX < numHorTiles; ++indexX ) |
|
303 { |
|
304 tileStartCanvas = Max( ( sizMarker.iXTOsiz + indexX * sizMarker.iXTsiz ), sizMarker.iXOsiz ); |
|
305 tileEndCanvas = Min( ( sizMarker.iXTOsiz + ( indexX + 1 ) * sizMarker.iXTsiz ), sizMarker.iXsiz ); |
|
306 |
|
307 // Add this tile's contribution to the total size |
|
308 tileCompStartCanvas = TJ2kUtils::Ceil( tileStartCanvas, sizMarker.iXRsiz[0] ); |
|
309 tileCompCanvasWidth += TJ2kUtils::Ceil( tileEndCanvas, sizMarker.iXRsiz[0] ) - tileCompStartCanvas; |
|
310 } |
|
311 |
|
312 // Compute the height of the output image |
|
313 TInt32 tileCompCanvasHeight = 0; |
|
314 TInt32 numVerTiles = iImageInfo->NumOfVertTiles(); |
|
315 for(TUint16 indexY = 0; indexY < numVerTiles; ++indexY ) |
|
316 { |
|
317 tileStartCanvas = Max( ( sizMarker.iYTOsiz + indexY * sizMarker.iYTsiz ), sizMarker.iYOsiz ); |
|
318 tileEndCanvas = Min( ( sizMarker.iYTOsiz + ( indexY + 1 ) * sizMarker.iYTsiz ), sizMarker.iYsiz ); |
|
319 |
|
320 // Add this tile's contribution to the total size |
|
321 tileCompStartCanvas = TJ2kUtils::Ceil( tileStartCanvas, sizMarker.iYRsiz[0] ); |
|
322 tileCompCanvasHeight += TJ2kUtils::Ceil( tileEndCanvas, sizMarker.iYRsiz[0] ) - tileCompStartCanvas; |
|
323 } |
|
324 |
|
325 iFrame->iOverallSizeInPixels = TSize( tileCompCanvasWidth, tileCompCanvasHeight ); |
|
326 |
|
327 iFrame->iFrameCoordsInPixels.SetRect( TPoint( 0, 0 ), iFrame->iOverallSizeInPixels ); |
|
328 iFrame->iFrameSizeInTwips.SetSize( 0, 0 ); |
|
329 |
|
330 for ( TUint16 index = 0; index < sizMarker.iCsiz; ++index ) |
|
331 { |
|
332 iFrame->iBitsPerPixel += ( ( sizMarker.iSsiz[index] & 0x7f ) + 1 ); |
|
333 } |
|
334 |
|
335 // We can dither. |
|
336 iFrame->iFlags |= TFrameInfo::ECanDither; |
|
337 |
|
338 // Decoder is able to handle scaleable resolution |
|
339 iFrame->iFlags |= TFrameInfo::EConstantAspectRatio; |
|
340 |
|
341 if ( sizMarker.iCsiz > 1 ) |
|
342 { |
|
343 iFrame->iFlags |= TFrameInfo::EColor; |
|
344 } |
|
345 |
|
346 // Animation is not allowed |
|
347 iFrame->iDelay = 0; |
|
348 |
|
349 switch ( iFrame->iBitsPerPixel ) |
|
350 { |
|
351 case 1: |
|
352 { |
|
353 iFrame->iFrameDisplayMode = EGray2; |
|
354 break; |
|
355 } |
|
356 case 2: |
|
357 { |
|
358 iFrame->iFrameDisplayMode = EGray4; |
|
359 break; |
|
360 } |
|
361 case 4: |
|
362 { |
|
363 iFrame->iFrameDisplayMode = ( iFrame->iFlags & TFrameInfo::EColor ) ? EColor16 : EGray16; |
|
364 break; |
|
365 } |
|
366 case 8: |
|
367 { |
|
368 iFrame->iFrameDisplayMode = ( iFrame->iFlags & TFrameInfo::EColor ) ? EColor16M : EGray256; |
|
369 break; |
|
370 } |
|
371 case 12: |
|
372 { |
|
373 iFrame->iFrameDisplayMode = ( iFrame->iFlags & TFrameInfo::EColor ) ? EColor4K : EGray256; |
|
374 break; |
|
375 } |
|
376 case 16: |
|
377 { |
|
378 iFrame->iFrameDisplayMode = EColor64K; |
|
379 break; |
|
380 } |
|
381 case 24: |
|
382 { |
|
383 iFrame->iFrameDisplayMode = EColor16M; |
|
384 break; |
|
385 } |
|
386 default: |
|
387 { |
|
388 iFrame->iFrameDisplayMode = EColor64K; |
|
389 break; |
|
390 } |
|
391 } |
|
392 } |
|
393 |
|
394 // It is the offset that ICL framework used to read in |
|
395 // more data from the image file. |
|
396 iFrame->SetFrameDataOffset( iReader.iStartSOT ); |
|
397 |
|
398 // Frame header has been processed without error |
|
399 // the flag is used by the ICL framework to determine |
|
400 // whether it should continue processing or halt with error |
|
401 iFrame->SetCurrentFrameState( TFrameInfo::EFrameInfoProcessingComplete ); |
|
402 |
|
403 return retCode; |
|
404 } |
|
405 |
|
406 // ----------------------------------------------------------------------------- |
|
407 // CJp2kReadCodec::InitFrameL |
|
408 // Called from ICL framework to initialise frame. |
|
409 // (other items were commented in a header). |
|
410 // ----------------------------------------------------------------------------- |
|
411 // |
|
412 void CJp2kReadCodec::InitFrameL( TFrameInfo& /*aFrameInfo*/, CFrameImageData& /*aFrameData*/, |
|
413 TBool aDisableErrorDiffusion, CFbsBitmap& aDestination, |
|
414 CFbsBitmap* /*aDestinationMask*/ ) |
|
415 { |
|
416 // Always use ERgb mode unless specified in the JP2 file format |
|
417 TDisplayMode mode = ERgb; |
|
418 |
|
419 TInt reductionFactor = ImageProcessorUtility::ReductionFactor( iFrame->iOverallSizeInPixels, |
|
420 aDestination.SizeInPixels() ); |
|
421 |
|
422 iImageInfo->SetLevelDrop( (TUint8)reductionFactor ); |
|
423 |
|
424 // If the codestream doesn't contain enough wavelet levels to do the resolution |
|
425 // reduction required by the framework / calling application, "extraLevels" are |
|
426 // assigned to perform the resolution reduction. The "extra" resolution drop is |
|
427 // performed at the output stage, i.e. all the samples are decoded, but only |
|
428 // 1/4, 1/16, etc. are written to output. |
|
429 if(reductionFactor > iImageInfo->MainMarker().iCod.iNumOfLevels) |
|
430 { |
|
431 iImageInfo->SetExtraLevelDrop( (TUint8)(reductionFactor - iImageInfo->MainMarker().iCod.iNumOfLevels) ); |
|
432 } |
|
433 else |
|
434 { |
|
435 iImageInfo->SetExtraLevelDrop( 0 ); |
|
436 } |
|
437 |
|
438 CImageProcessor* imageProc = ImageProcessorUtility::NewImageProcessorL( aDestination, |
|
439 0, |
|
440 mode, |
|
441 aDisableErrorDiffusion ); |
|
442 TPoint startAt( iFrame->iFrameCoordsInPixels.iTl.iX, |
|
443 iFrame->iFrameCoordsInPixels.iTl.iY ); |
|
444 |
|
445 TRect imageSize( startAt, aDestination.SizeInPixels() ); |
|
446 |
|
447 // Prepare the bitmap using the image size |
|
448 SetImageProcessor( imageProc ); |
|
449 imageProc->PrepareL( aDestination, imageSize ); |
|
450 |
|
451 // Clear bitmap so sensibly draw partial decodes |
|
452 ClearBitmapL(aDestination, KRgbWhite); |
|
453 |
|
454 iUseNewTile = ETrue; |
|
455 iReader.iNewDataStart = iFrame->FrameDataOffset(); |
|
456 iStyleUsed = EUnknownDecoder; |
|
457 |
|
458 iProgressBar = EFalse; |
|
459 if ( ( iImageInfo->NumOfHorizTiles() == 1 ) && |
|
460 ( iImageInfo->NumOfVertTiles() == 1 ) ) |
|
461 { |
|
462 // To force a return immediately from ProcessFrameL() |
|
463 // on first entry to stimulate the occurrance of |
|
464 // the progress bar |
|
465 iProgressBar = ETrue; |
|
466 } |
|
467 |
|
468 if ( iFHState != EStateInSOT ) |
|
469 { |
|
470 // We are in zoom in mode |
|
471 iUseNextTile = iSequential = EFalse; |
|
472 iFHState = EStateInSOT; |
|
473 iLastTileIndex = 0; |
|
474 iImageInfo->SetLastTilePartProcessed( (TUint16)0xffff ); |
|
475 iImageWriter->SetNewImageProcessor( imageProc ); |
|
476 |
|
477 if ( iJ2kInfo.iOption & TJ2kInfo::EJP2file ) |
|
478 { |
|
479 iReader.iCSLength = iJ2kInfo.iCSBoxLength; |
|
480 |
|
481 // We have read in all header information, so skip it |
|
482 if ( iReader.iCSLength > iReader.iStartSOT ) |
|
483 { |
|
484 iReader.iCSLength -= iReader.iStartSOT; |
|
485 } |
|
486 iReader.iDataUsed = 0; |
|
487 } |
|
488 } |
|
489 } |
|
490 |
|
491 // ----------------------------------------------------------------------------- |
|
492 // CJp2kReadCodec::ProcessFrameL |
|
493 // Collect the JP2 codestream Tile Part information. |
|
494 // (other items were commented in a header). |
|
495 // ----------------------------------------------------------------------------- |
|
496 // |
|
497 TFrameState CJp2kReadCodec::ProcessFrameL(TBufPtr8& aSrc) |
|
498 { |
|
499 // Start decoding the compressed data stream |
|
500 TFrameState retCode = EFrameIncomplete; |
|
501 |
|
502 iReader.iPtr = aSrc.Ptr(); |
|
503 |
|
504 iReader.iPtrStart = CONST_CAST( TUint8*, iReader.iPtr ); |
|
505 iReader.iPtrEnd = iReader.iPtrStart + aSrc.Length(); |
|
506 |
|
507 while ( iFHState != EStateInEOC ) |
|
508 { |
|
509 iReader.iPtrStartMarker = CONST_CAST( TUint8*, iReader.iPtr ); |
|
510 switch ( iFHState ) |
|
511 { |
|
512 case EStateInSOT: |
|
513 { |
|
514 retCode = ReadSOTL(); |
|
515 break; |
|
516 } |
|
517 case EStateInSOD: |
|
518 { |
|
519 retCode = ReadSODL(); |
|
520 break; |
|
521 } |
|
522 case EStateInBITSTREAM: |
|
523 { |
|
524 retCode = ReadBitStreamL(); |
|
525 break; |
|
526 } |
|
527 case EStateInCOD: |
|
528 { |
|
529 retCode = ReadCODL( EFalse ); |
|
530 break; |
|
531 } |
|
532 case EStateInCOC: |
|
533 { |
|
534 retCode = ReadCOCL( EFalse ); |
|
535 break; |
|
536 } |
|
537 case EStateInQCD: |
|
538 { |
|
539 retCode = ReadQCDL( EFalse ); |
|
540 break; |
|
541 } |
|
542 case EStateInQCC: |
|
543 { |
|
544 retCode = ReadQCCL( EFalse ); |
|
545 break; |
|
546 } |
|
547 case EStateInRGN: |
|
548 { |
|
549 retCode = ReadRGNL( EFalse ); |
|
550 break; |
|
551 } |
|
552 case EStateInPOC: |
|
553 { |
|
554 retCode = ReadPOCL( EFalse ); |
|
555 break; |
|
556 } |
|
557 case EStateInPPT: |
|
558 { |
|
559 retCode = ReadPPTL(); |
|
560 break; |
|
561 } |
|
562 case EStateInPLT: |
|
563 { |
|
564 retCode = ReadPLTL(); |
|
565 break; |
|
566 } |
|
567 case EStateInCOM: |
|
568 { |
|
569 retCode = ReadCOML( EFalse ); |
|
570 break; |
|
571 } |
|
572 case EStateInUnknown: |
|
573 { |
|
574 // Update the internal state based on the Marker |
|
575 retCode = UpdateStateFromMarkerL(); |
|
576 break; |
|
577 } |
|
578 case EStateInSkipTile: |
|
579 { |
|
580 retCode = ReadSkipTileL(); |
|
581 break; |
|
582 } |
|
583 default: |
|
584 { |
|
585 // Unrecognized marker |
|
586 User::Leave( KErrCorrupt ); |
|
587 break; |
|
588 } |
|
589 } |
|
590 // Check for underflow |
|
591 if ( retCode != EFrameComplete ) |
|
592 { |
|
593 // Request to jump to another section of the image file |
|
594 if ( retCode == EFrameIncompleteRepositionRequest ) |
|
595 { |
|
596 // Update the internal counter for data processed |
|
597 iReader.UpdateTileHeader(); |
|
598 } |
|
599 |
|
600 aSrc.Shift( iReader.iPtr - iReader.iPtrStart ); |
|
601 return retCode; |
|
602 } |
|
603 |
|
604 if ( iFHState != EStateInSkipTile && iFHState != EStateInSOT ) |
|
605 { |
|
606 // Update the internal counter for data processed |
|
607 // only for the current tile |
|
608 iReader.UpdateTileHeader(); |
|
609 } |
|
610 |
|
611 if ( ( iProgressBar && iFHState != EStateInEOC ) || iDecodeTile ) |
|
612 { |
|
613 iProgressBar = EFalse; |
|
614 aSrc.Shift( iReader.iPtr - iReader.iPtrStart ); |
|
615 return EFrameIncomplete; |
|
616 } |
|
617 } |
|
618 |
|
619 if ( iDecodeTile == EFalse ) |
|
620 { |
|
621 ImageProcessor()->FlushPixels(); |
|
622 } |
|
623 |
|
624 return EFrameComplete; |
|
625 } |
|
626 |
|
627 // ----------------------------------------------------------------------------- |
|
628 // CJp2kReadCodec::GetNewDataPosition |
|
629 // Get the new offset where data should be read from. |
|
630 // (other items were commented in a header). |
|
631 // ----------------------------------------------------------------------------- |
|
632 // |
|
633 void CJp2kReadCodec::GetNewDataPosition( TInt& aPosition, TInt& /*aLength*/ ) |
|
634 { |
|
635 // Set new offset position so that |
|
636 // ICL framework will read in more image data for processing |
|
637 aPosition = iReader.iNewDataStart + iJ2kInfo.iCSOffset; |
|
638 } |
|
639 |
|
640 // ----------------------------------------------------------------------------- |
|
641 // CJp2kReadCodec::CJp2kReadCodec |
|
642 // C++ default constructor can NOT contain any code, that |
|
643 // might leave. |
|
644 // ----------------------------------------------------------------------------- |
|
645 // |
|
646 CJp2kReadCodec::CJp2kReadCodec( const TJ2kInfo& aJ2kInfo ) : |
|
647 iJ2kInfo( aJ2kInfo ) |
|
648 { |
|
649 } |
|
650 |
|
651 // ----------------------------------------------------------------------------- |
|
652 // CJp2kReadCodec::ConstructL |
|
653 // Symbian 2nd phase constructor can leave. |
|
654 // ----------------------------------------------------------------------------- |
|
655 // |
|
656 void CJp2kReadCodec::ConstructL() |
|
657 { |
|
658 iImageInfo = new ( ELeave ) CJ2kImageInfo; |
|
659 |
|
660 // Invoke base class 2nd phase constructor. |
|
661 CImageProcessorReadCodec::ConstructL(); |
|
662 } |
|
663 |
|
664 // ----------------------------------------------------------------------------- |
|
665 // CJp2kReadCodec::ReadSOCL |
|
666 // Verify and process Start of Codestream (SOC marker). |
|
667 // (other items were commented in a header). |
|
668 // ----------------------------------------------------------------------------- |
|
669 // |
|
670 TFrameState CJp2kReadCodec::ReadSOCL() |
|
671 { |
|
672 const TUint8* dataPtr = iReader.iPtr; |
|
673 |
|
674 if ( iJ2kInfo.iOption & TJ2kInfo::EJP2file ) |
|
675 { |
|
676 // Codestream box in JP2 file format |
|
677 iReader.iCSLength = iJ2kInfo.iCSBoxLength; |
|
678 iReader.iPtr += KJ2kBoxTypeLength; |
|
679 |
|
680 if ( iReader.iCSLength == 1 ) |
|
681 { |
|
682 // The XLBox shall exist and contains the actual length of the box |
|
683 // XLBox is 8 bytes width |
|
684 iReader.iCSLength = PtrReadUtil::ReadBigEndianUint32Inc( iReader.iPtr ); |
|
685 iReader.iCSLength += PtrReadUtil::ReadBigEndianUint32Inc( iReader.iPtr ); |
|
686 |
|
687 // Populate back to the iJ2kInfo |
|
688 CONST_CAST( TJ2kInfo&, iJ2kInfo ).iCSBoxLength = iReader.iCSLength; |
|
689 } |
|
690 } |
|
691 |
|
692 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerSize ) |
|
693 { |
|
694 // Underflow, backup the pointer to the beginning |
|
695 iReader.iPtr = dataPtr; |
|
696 return EFrameIncomplete; |
|
697 } |
|
698 |
|
699 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KSOC ) |
|
700 { |
|
701 // Unrecognized SOC marker |
|
702 User::Leave( KErrCorrupt ); |
|
703 } |
|
704 |
|
705 // SIZ marker shall immediately follow the SOC marker |
|
706 iFHState = EStateInSIZ; |
|
707 |
|
708 return EFrameComplete; |
|
709 } |
|
710 |
|
711 // ----------------------------------------------------------------------------- |
|
712 // CJp2kReadCodec::ReadSIZL |
|
713 // Verify and process Image and Tile Size (SIZ marker). |
|
714 // (other items were commented in a header). |
|
715 // ----------------------------------------------------------------------------- |
|
716 // |
|
717 TFrameState CJp2kReadCodec::ReadSIZL() |
|
718 { |
|
719 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
720 { |
|
721 // Underflow |
|
722 return EFrameIncomplete; |
|
723 } |
|
724 |
|
725 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KSIZ ) |
|
726 { |
|
727 // Unrecognized SIZ marker |
|
728 User::Leave( KErrCorrupt ); |
|
729 } |
|
730 |
|
731 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
732 |
|
733 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
734 { |
|
735 // Underflow, backup the iterator to the beginning of the marker |
|
736 iReader.iPtr -= KMarkerMinLength; |
|
737 return EFrameIncomplete; |
|
738 } |
|
739 |
|
740 TSizMarker& sizMarker = CONST_CAST( TSizMarker&, iImageInfo->SizMarker() ); |
|
741 |
|
742 sizMarker.iRsiz = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
743 sizMarker.iXsiz = PtrReadUtil::ReadBigEndianUint32Inc( iReader.iPtr ); |
|
744 sizMarker.iYsiz = PtrReadUtil::ReadBigEndianUint32Inc( iReader.iPtr ); |
|
745 sizMarker.iXOsiz = PtrReadUtil::ReadBigEndianUint32Inc( iReader.iPtr ); |
|
746 sizMarker.iYOsiz = PtrReadUtil::ReadBigEndianUint32Inc( iReader.iPtr ); |
|
747 sizMarker.iXTsiz = PtrReadUtil::ReadBigEndianUint32Inc( iReader.iPtr ); |
|
748 sizMarker.iYTsiz = PtrReadUtil::ReadBigEndianUint32Inc( iReader.iPtr ); |
|
749 sizMarker.iXTOsiz = PtrReadUtil::ReadBigEndianUint32Inc( iReader.iPtr ); |
|
750 sizMarker.iYTOsiz = PtrReadUtil::ReadBigEndianUint32Inc( iReader.iPtr ); |
|
751 sizMarker.iCsiz = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
752 |
|
753 if(sizMarker.iXOsiz > sizMarker.iXsiz || sizMarker.iYOsiz > sizMarker.iYsiz) |
|
754 { |
|
755 // Image offset is larger than image size, exit |
|
756 User::Leave( KErrCorrupt ); |
|
757 } |
|
758 |
|
759 if(sizMarker.iXTOsiz > sizMarker.iXsiz || sizMarker.iYTOsiz > sizMarker.iYsiz) |
|
760 { |
|
761 // Tile offset is larger than image size, exit |
|
762 User::Leave( KErrCorrupt ); |
|
763 } |
|
764 |
|
765 for ( TUint16 index = 0; index < sizMarker.iCsiz; ++index ) |
|
766 { |
|
767 // Component's information |
|
768 User::LeaveIfError( sizMarker.iSsiz.Append( *iReader.iPtr++ ) ); |
|
769 User::LeaveIfError( sizMarker.iXRsiz.Append( *iReader.iPtr++ ) ); |
|
770 User::LeaveIfError( sizMarker.iYRsiz.Append( *iReader.iPtr++ ) ); |
|
771 |
|
772 if((( sizMarker.iSsiz[index] & 0x7f ) + 1) > KMaxBitdepth ) |
|
773 { |
|
774 // Invalid bitdepth for this component, exit |
|
775 User::Leave( KErrCorrupt ); |
|
776 } |
|
777 } |
|
778 |
|
779 if ( iJ2kInfo.iCMPList.Count() > sizMarker.iCsiz ) |
|
780 { |
|
781 // Populate the remaining component Rsiz using component 0's Rsiz |
|
782 TUint16 indexi = (TUint16)( iJ2kInfo.iCMPList.Count() - sizMarker.iCsiz ); |
|
783 while ( indexi ) |
|
784 { |
|
785 User::LeaveIfError( sizMarker.iXRsiz.Append( sizMarker.iXRsiz[0] ) ); |
|
786 User::LeaveIfError( sizMarker.iYRsiz.Append( sizMarker.iYRsiz[0] ) ); |
|
787 --indexi; |
|
788 } |
|
789 } |
|
790 |
|
791 // Make sure we read all the data |
|
792 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
793 { |
|
794 // We must be missing some data in the marker |
|
795 User::Leave( KErrCorrupt ); |
|
796 } |
|
797 |
|
798 // Any valid marker may come after SIZ marker |
|
799 iFHState = EStateInUnknown; |
|
800 |
|
801 return EFrameComplete; |
|
802 } |
|
803 |
|
804 // ----------------------------------------------------------------------------- |
|
805 // CJp2kReadCodec::ReadCODL |
|
806 // Verify and process Coding Style Default (COD marker). |
|
807 // (other items were commented in a header). |
|
808 // ----------------------------------------------------------------------------- |
|
809 // |
|
810 TFrameState CJp2kReadCodec::ReadCODL( TBool aMain ) |
|
811 { |
|
812 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
813 { |
|
814 // Underflow |
|
815 return EFrameIncomplete; |
|
816 } |
|
817 |
|
818 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KCOD ) |
|
819 { |
|
820 // Unrecognized COD marker |
|
821 User::Leave(KErrCorrupt); |
|
822 } |
|
823 |
|
824 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
825 |
|
826 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
827 { |
|
828 // Underflow, backup the iterator to the beginning of the marker |
|
829 iReader.iPtr -= KMarkerMinLength; |
|
830 return EFrameIncomplete; |
|
831 } |
|
832 |
|
833 TCODMarker *codMarker = NULL; |
|
834 |
|
835 if ( aMain ) |
|
836 { |
|
837 TMainMarker& mainMarker = CONST_CAST( TMainMarker&, iImageInfo->MainMarker() ); |
|
838 codMarker = &mainMarker.iCod; |
|
839 } |
|
840 else |
|
841 { |
|
842 // COD in Tile Part Header |
|
843 codMarker = new ( ELeave ) TCODMarker; |
|
844 CleanupDeletePushL( codMarker ); |
|
845 } |
|
846 |
|
847 codMarker->iScod = *iReader.iPtr++; |
|
848 codMarker->iProgressionOrder = *iReader.iPtr++; |
|
849 codMarker->iNumOfLayers = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
850 codMarker->iColorTransformation = *iReader.iPtr++; |
|
851 codMarker->iNumOfLevels = *iReader.iPtr++; |
|
852 |
|
853 TUint8 tmp = (TUint8)( ( *iReader.iPtr++ ) + 2 ); |
|
854 codMarker->iCodeBlockSiz.iWidth = 1 << tmp; |
|
855 |
|
856 tmp = (TUint8)( ( *iReader.iPtr++ ) + 2 ); |
|
857 codMarker->iCodeBlockSiz.iHeight = 1 << tmp; |
|
858 |
|
859 codMarker->iCodeBlockStyle = *iReader.iPtr++; |
|
860 codMarker->iWaveletTransformation = *iReader.iPtr++; |
|
861 |
|
862 if ( codMarker->iScod & 0x01 ) |
|
863 { |
|
864 // Entropy coder with precincts defined below |
|
865 codMarker->iPrecinctSiz = HBufC8::NewL( codMarker->iNumOfLevels + 1 ); |
|
866 for ( TUint8 index = 0; index < codMarker->iNumOfLevels + 1; ++index ) |
|
867 { |
|
868 codMarker->iPrecinctSiz->Des().Append( *iReader.iPtr++ ); |
|
869 } |
|
870 } |
|
871 |
|
872 // Make sure we read all the data |
|
873 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
874 { |
|
875 // We must be missing some data in the marker |
|
876 User::Leave( KErrCorrupt ); |
|
877 } |
|
878 |
|
879 if ( !aMain ) |
|
880 { |
|
881 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
882 |
|
883 // Append COD to the current tile and decrement the tile length |
|
884 tile.AppendCOD( codMarker, markerLength + KMarkerSize ); |
|
885 CleanupStack::Pop(); |
|
886 } |
|
887 |
|
888 // Any valid marker may come after COD marker |
|
889 iFHState = EStateInUnknown; |
|
890 return EFrameComplete; |
|
891 } |
|
892 |
|
893 // ----------------------------------------------------------------------------- |
|
894 // CJp2kReadCodec::ReadCOCL |
|
895 // Verify and process Coding Style Component (COC marker). |
|
896 // (other items were commented in a header). |
|
897 // ----------------------------------------------------------------------------- |
|
898 // |
|
899 TFrameState CJp2kReadCodec::ReadCOCL( TBool aMain ) |
|
900 { |
|
901 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
902 { |
|
903 // Underflow |
|
904 return EFrameIncomplete; |
|
905 } |
|
906 |
|
907 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KCOC ) |
|
908 { |
|
909 // Unrecognized COC marker |
|
910 User::Leave( KErrCorrupt ); |
|
911 } |
|
912 |
|
913 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
914 |
|
915 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
916 { |
|
917 // Underflow, backup the iterator to the beginning of the marker |
|
918 iReader.iPtr -= KMarkerMinLength; |
|
919 return EFrameIncomplete; |
|
920 } |
|
921 |
|
922 const TSizMarker& sizMarker = iImageInfo->SizMarker(); |
|
923 |
|
924 TCOCMarker *cocMarker = new ( ELeave ) TCOCMarker; |
|
925 CleanupDeletePushL(cocMarker); |
|
926 |
|
927 if ( sizMarker.iCsiz < 257 ) |
|
928 { |
|
929 // 8 bits component |
|
930 cocMarker->iCcoc = *iReader.iPtr++; |
|
931 } |
|
932 else |
|
933 { |
|
934 // 16 bits component |
|
935 cocMarker->iCcoc = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
936 } |
|
937 |
|
938 cocMarker->iScoc = *iReader.iPtr++; |
|
939 cocMarker->iNumOfLevels = *iReader.iPtr++; |
|
940 |
|
941 TUint8 tmp = (TUint8)( ( *iReader.iPtr++ ) + 2 ); |
|
942 cocMarker->iCodeBlockSiz.iWidth = 1 << tmp; |
|
943 |
|
944 tmp = (TUint8)( ( *iReader.iPtr++ ) + 2 ); |
|
945 cocMarker->iCodeBlockSiz.iHeight = 1 << tmp; |
|
946 |
|
947 cocMarker->iCodeBlockStyle = *iReader.iPtr++; |
|
948 cocMarker->iWaveletTransformation = *iReader.iPtr++; |
|
949 |
|
950 if ( cocMarker->iScoc & 0x01 ) |
|
951 { |
|
952 // Entropy coder with precincts defined below |
|
953 cocMarker->iPrecinctSiz = HBufC8::NewL( cocMarker->iNumOfLevels + 1 ); |
|
954 for ( TUint8 index = 0; index < cocMarker->iNumOfLevels + 1; ++index ) |
|
955 { |
|
956 cocMarker->iPrecinctSiz->Des().Append( *iReader.iPtr++ ); |
|
957 } |
|
958 } |
|
959 |
|
960 // Make sure we read all the data |
|
961 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
962 { |
|
963 // We must be missing some data in the marker |
|
964 User::Leave( KErrCorrupt ); |
|
965 } |
|
966 |
|
967 if ( aMain ) |
|
968 { |
|
969 iImageInfo->AppendCOCL( cocMarker ); |
|
970 } |
|
971 else |
|
972 { |
|
973 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
974 |
|
975 // Append COC to the current tile and decrement the tile length |
|
976 tile.AppendCOCL( cocMarker, markerLength + KMarkerSize ); |
|
977 } |
|
978 CleanupStack::Pop(); |
|
979 |
|
980 // Any valid marker may come after COC marker |
|
981 iFHState = EStateInUnknown; |
|
982 |
|
983 return EFrameComplete; |
|
984 } |
|
985 |
|
986 // ----------------------------------------------------------------------------- |
|
987 // CJp2kReadCodec::ReadQCDL |
|
988 // Verify and process Quantization Default (QCD marker). |
|
989 // (other items were commented in a header). |
|
990 // ----------------------------------------------------------------------------- |
|
991 // |
|
992 TFrameState CJp2kReadCodec::ReadQCDL( TBool aMain ) |
|
993 { |
|
994 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
995 { |
|
996 // Underflow |
|
997 return EFrameIncomplete; |
|
998 } |
|
999 |
|
1000 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KQCD ) |
|
1001 { |
|
1002 // Unrecognized QCD marker |
|
1003 User::Leave( KErrCorrupt ); |
|
1004 } |
|
1005 |
|
1006 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1007 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
1008 { |
|
1009 // Underflow, backup the iterator to the beginning of the marker |
|
1010 iReader.iPtr -= KMarkerMinLength; |
|
1011 return EFrameIncomplete; |
|
1012 } |
|
1013 |
|
1014 TQCDMarker *qcdMarker = NULL; |
|
1015 |
|
1016 if ( aMain ) |
|
1017 { |
|
1018 TMainMarker& mainMarker = CONST_CAST( TMainMarker&, iImageInfo->MainMarker() ); |
|
1019 qcdMarker = &mainMarker.iQcd; |
|
1020 } |
|
1021 else |
|
1022 { |
|
1023 // QCD in Tile Part Header |
|
1024 qcdMarker = new ( ELeave ) TQCDMarker; |
|
1025 |
|
1026 CleanupDeletePushL( qcdMarker ); |
|
1027 } |
|
1028 |
|
1029 qcdMarker->iSqcd = *iReader.iPtr++; |
|
1030 |
|
1031 if ( qcdMarker->iSqcd & 0x01 ) |
|
1032 { |
|
1033 // Scalar derived (values signalled for NLL subband only) |
|
1034 TUint16 tmp = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1035 qcdMarker->iExponent = HBufC8::NewL(1); |
|
1036 qcdMarker->iExponent->Des().Append( (TUint8)( (tmp >> 11) & 0x1f ) ); |
|
1037 qcdMarker->iMantissa = HBufC16::NewL(1); |
|
1038 qcdMarker->iMantissa->Des().Append( (TUint16)( tmp & 0x07ff ) ); |
|
1039 } |
|
1040 else |
|
1041 { |
|
1042 TInt entries = markerLength - ( iReader.iPtr - iReader.iPtrStartMarker ) + KMarkerSize; |
|
1043 if ( qcdMarker->iSqcd & 0x1f ) |
|
1044 { |
|
1045 // Word oriented |
|
1046 TUint16 tmp; |
|
1047 qcdMarker->iExponent = HBufC8::NewL( entries / 2 ); |
|
1048 qcdMarker->iMantissa = HBufC16::NewL( entries / 2 ); |
|
1049 |
|
1050 while ( entries >= 2 ) |
|
1051 { |
|
1052 tmp = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1053 qcdMarker->iExponent->Des().Append((TUint8)( ( tmp >> 11) & 0x1f ) ); |
|
1054 qcdMarker->iMantissa->Des().Append((TUint16)( tmp & 0x07ff ) ); |
|
1055 entries -= 2; |
|
1056 } |
|
1057 } |
|
1058 else |
|
1059 { |
|
1060 // No quantization |
|
1061 qcdMarker->iExponent = HBufC8::NewL( entries ); |
|
1062 while ( entries ) |
|
1063 { |
|
1064 qcdMarker->iExponent->Des().Append( (TUint8)( ( *iReader.iPtr++ >> 3 ) & 0x1f ) ); |
|
1065 --entries; |
|
1066 } |
|
1067 } |
|
1068 } |
|
1069 |
|
1070 // Make sure we read all the data |
|
1071 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
1072 { |
|
1073 // We must be missing some data in the marker |
|
1074 User::Leave( KErrCorrupt ); |
|
1075 } |
|
1076 |
|
1077 if ( !aMain ) |
|
1078 { |
|
1079 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
1080 |
|
1081 // Append QCD to the current tile and decrement the tile length |
|
1082 tile.AppendQCD( qcdMarker, markerLength + KMarkerSize ); |
|
1083 CleanupStack::Pop(); |
|
1084 } |
|
1085 |
|
1086 // Any valid marker may come after QCD marker |
|
1087 iFHState = EStateInUnknown; |
|
1088 |
|
1089 return EFrameComplete; |
|
1090 } |
|
1091 |
|
1092 // ----------------------------------------------------------------------------- |
|
1093 // CJp2kReadCodec::ReadQCCL |
|
1094 // Verify and process Quantization Component (QCC marker). |
|
1095 // (other items were commented in a header). |
|
1096 // ----------------------------------------------------------------------------- |
|
1097 // |
|
1098 TFrameState CJp2kReadCodec::ReadQCCL(TBool aMain) |
|
1099 { |
|
1100 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
1101 { |
|
1102 // Underflow |
|
1103 return EFrameIncomplete; |
|
1104 } |
|
1105 |
|
1106 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KQCC ) |
|
1107 { |
|
1108 // Unrecognized QCC marker |
|
1109 User::Leave( KErrCorrupt ); |
|
1110 } |
|
1111 |
|
1112 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1113 if ( ( iReader.iPtrEnd - iReader.iPtr ) < (markerLength - KMarkerLength ) ) |
|
1114 { |
|
1115 // Underflow, backup the iterator to the beginning of the marker |
|
1116 iReader.iPtr -= KMarkerMinLength; |
|
1117 return EFrameIncomplete; |
|
1118 } |
|
1119 |
|
1120 const TSizMarker& sizMarker = iImageInfo->SizMarker(); |
|
1121 |
|
1122 TQCCMarker *qccMarker = new (ELeave) TQCCMarker; |
|
1123 |
|
1124 CleanupDeletePushL( qccMarker ); |
|
1125 |
|
1126 if ( sizMarker.iCsiz < 257 ) |
|
1127 { |
|
1128 // 8 bits component |
|
1129 qccMarker->iCqcc = *iReader.iPtr++; |
|
1130 } |
|
1131 else |
|
1132 { |
|
1133 // 16 bit component |
|
1134 qccMarker->iCqcc = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1135 } |
|
1136 |
|
1137 qccMarker->iSqcc = *iReader.iPtr++; |
|
1138 |
|
1139 if ( qccMarker->iSqcc & 0x01 ) |
|
1140 { |
|
1141 // Scalar derived (values signalled for NLL subband only) |
|
1142 TUint16 tmp = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1143 qccMarker->iExponent = HBufC8::NewL(1); |
|
1144 qccMarker->iExponent->Des().Append( (TUint8)( ( tmp >> 11 ) & 0x1f ) ); |
|
1145 qccMarker->iMantissa = HBufC16::NewL(1); |
|
1146 qccMarker->iMantissa->Des().Append( (TUint16)( tmp & 0x07ff ) ); |
|
1147 } |
|
1148 else |
|
1149 { |
|
1150 TInt entries = markerLength - ( iReader.iPtr - iReader.iPtrStartMarker ) + KMarkerSize; |
|
1151 if ( qccMarker->iSqcc & 0x1f ) |
|
1152 { |
|
1153 // Word oriented |
|
1154 TUint16 tmp; |
|
1155 qccMarker->iExponent = HBufC8::NewL( entries / 2 ); |
|
1156 qccMarker->iMantissa = HBufC16::NewL( entries / 2 ); |
|
1157 |
|
1158 while ( entries >= 2 ) |
|
1159 { |
|
1160 tmp = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1161 qccMarker->iExponent->Des().Append( (TUint8)( ( tmp >> 11 ) & 0x1f ) ); |
|
1162 qccMarker->iMantissa->Des().Append( (TUint16)( tmp & 0x07ff ) ); |
|
1163 entries -= 2; |
|
1164 } |
|
1165 } |
|
1166 else |
|
1167 { |
|
1168 // No quantization |
|
1169 qccMarker->iExponent = HBufC8::NewL( entries ); |
|
1170 while ( entries ) |
|
1171 { |
|
1172 qccMarker->iExponent->Des().Append( (TUint8)( ( *iReader.iPtr++ >> 3 ) & 0x1f ) ); |
|
1173 --entries; |
|
1174 } |
|
1175 } |
|
1176 } |
|
1177 |
|
1178 // Make sure we read all the data |
|
1179 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
1180 { |
|
1181 // We must be missing some data in the marker |
|
1182 User::Leave( KErrCorrupt ); |
|
1183 } |
|
1184 |
|
1185 if ( aMain ) |
|
1186 { |
|
1187 iImageInfo->AppendQCCL( qccMarker ); |
|
1188 } |
|
1189 else |
|
1190 { |
|
1191 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
1192 |
|
1193 // Append QCC to the current tile and decrement the tile length |
|
1194 tile.AppendQCCL( qccMarker, markerLength + KMarkerSize ); |
|
1195 } |
|
1196 CleanupStack::Pop(); |
|
1197 |
|
1198 // Any valid marker may come after QCC marker |
|
1199 iFHState = EStateInUnknown; |
|
1200 |
|
1201 return EFrameComplete; |
|
1202 } |
|
1203 |
|
1204 // ----------------------------------------------------------------------------- |
|
1205 // CJp2kReadCodec::ReadRGNL |
|
1206 // Verify and process Region of Interest (RGN marker). |
|
1207 // (other items were commented in a header). |
|
1208 // ----------------------------------------------------------------------------- |
|
1209 // |
|
1210 TFrameState CJp2kReadCodec::ReadRGNL( TBool aMain ) |
|
1211 { |
|
1212 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
1213 { |
|
1214 // Underflow |
|
1215 return EFrameIncomplete; |
|
1216 } |
|
1217 |
|
1218 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KRGN ) |
|
1219 { |
|
1220 // Unrecognized RGN marker |
|
1221 User::Leave( KErrCorrupt ); |
|
1222 } |
|
1223 |
|
1224 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1225 |
|
1226 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
1227 { |
|
1228 // Underflow, backup the iterator to the beginning of the marker |
|
1229 iReader.iPtr -= KMarkerMinLength; |
|
1230 return EFrameIncomplete; |
|
1231 } |
|
1232 |
|
1233 const TSizMarker& sizMarker = iImageInfo->SizMarker(); |
|
1234 |
|
1235 TRGNMarker *rgnMarker = new ( ELeave ) TRGNMarker; |
|
1236 CleanupDeletePushL( rgnMarker ); |
|
1237 |
|
1238 if ( sizMarker.iCsiz < 257 ) |
|
1239 { |
|
1240 // 8 bits component |
|
1241 rgnMarker->iCrgn = *iReader.iPtr++; |
|
1242 } |
|
1243 else |
|
1244 { |
|
1245 // 16 bits component |
|
1246 rgnMarker->iCrgn = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1247 } |
|
1248 |
|
1249 rgnMarker->iSrgn = *iReader.iPtr++; |
|
1250 rgnMarker->iSPrgn = *iReader.iPtr++; |
|
1251 |
|
1252 // Make sure we read all the data |
|
1253 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
1254 { |
|
1255 // We must be missing some data in the marker |
|
1256 User::Leave( KErrCorrupt ); |
|
1257 } |
|
1258 |
|
1259 if ( aMain ) |
|
1260 { |
|
1261 iImageInfo->AppendRGNL( rgnMarker ); |
|
1262 } |
|
1263 else |
|
1264 { |
|
1265 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
1266 |
|
1267 // Append RGN to the current tile and decrement the tile length |
|
1268 tile.AppendRGNL( rgnMarker, markerLength + KMarkerSize ); |
|
1269 } |
|
1270 CleanupStack::Pop(); |
|
1271 |
|
1272 // Any valid marker may come after RGN marker |
|
1273 iFHState = EStateInUnknown; |
|
1274 |
|
1275 return EFrameComplete; |
|
1276 } |
|
1277 |
|
1278 // ----------------------------------------------------------------------------- |
|
1279 // CJp2kReadCodec::ReadPOCL |
|
1280 // Verify and process Progression Order Change ( POC marker ). |
|
1281 // (other items were commented in a header). |
|
1282 // ----------------------------------------------------------------------------- |
|
1283 // |
|
1284 TFrameState CJp2kReadCodec::ReadPOCL( TBool aMain ) |
|
1285 { |
|
1286 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
1287 { |
|
1288 // Underflow |
|
1289 return EFrameIncomplete; |
|
1290 } |
|
1291 |
|
1292 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KPOC ) |
|
1293 { |
|
1294 // Unrecognized COC marker |
|
1295 User::Leave( KErrCorrupt ); |
|
1296 } |
|
1297 |
|
1298 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1299 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
1300 { |
|
1301 // Underflow, backup the iterator to the beginning of the marker |
|
1302 iReader.iPtr -= KMarkerMinLength; |
|
1303 return EFrameIncomplete; |
|
1304 } |
|
1305 |
|
1306 const TSizMarker& sizMarker = iImageInfo->SizMarker(); |
|
1307 |
|
1308 TPOCMarker *pocMarker = new ( ELeave ) TPOCMarker; |
|
1309 CleanupDeletePushL( pocMarker ); |
|
1310 |
|
1311 TInt entries = markerLength - KMarkerSize; |
|
1312 TInt sizEntry = ( sizMarker.iCsiz < 257 ) ? 7 : 9; |
|
1313 |
|
1314 while ( entries >= sizEntry ) |
|
1315 { |
|
1316 User::LeaveIfError( pocMarker->iRSpoc.Append( *iReader.iPtr++ ) ); |
|
1317 |
|
1318 if ( sizMarker.iCsiz < 257 ) |
|
1319 { |
|
1320 // 8 bits component |
|
1321 User::LeaveIfError( pocMarker->iCSpoc.Append( *iReader.iPtr++ ) ); |
|
1322 } |
|
1323 else |
|
1324 { |
|
1325 // 16 bits component |
|
1326 User::LeaveIfError( pocMarker->iCSpoc.Append( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) ) ); |
|
1327 } |
|
1328 User::LeaveIfError( pocMarker->iLYEpoc.Append( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) ) ); |
|
1329 User::LeaveIfError( pocMarker->iREpoc.Append( *iReader.iPtr++ ) ); |
|
1330 if ( sizMarker.iCsiz < 257 ) |
|
1331 { |
|
1332 // 8 bits component |
|
1333 User::LeaveIfError( pocMarker->iCEpoc.Append( *iReader.iPtr++ ) ); |
|
1334 } |
|
1335 else |
|
1336 { |
|
1337 // 16 bits component |
|
1338 User::LeaveIfError( pocMarker->iCEpoc.Append( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) ) ); |
|
1339 } |
|
1340 User::LeaveIfError( pocMarker->iPpoc.Append( *iReader.iPtr++ ) ); |
|
1341 |
|
1342 entries -= sizEntry; |
|
1343 } |
|
1344 |
|
1345 // Make sure we read all the data |
|
1346 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
1347 { |
|
1348 // We must be missing some data in the marker |
|
1349 User::Leave( KErrCorrupt ); |
|
1350 } |
|
1351 |
|
1352 if ( aMain ) |
|
1353 { |
|
1354 iImageInfo->AppendPOCL( pocMarker ); |
|
1355 } |
|
1356 else |
|
1357 { |
|
1358 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
1359 |
|
1360 // Append POC to the current tile and decrement the tile length |
|
1361 tile.AppendPOCL( pocMarker, markerLength + KMarkerSize ); |
|
1362 } |
|
1363 CleanupStack::Pop( ); |
|
1364 |
|
1365 // Any valid marker may come after POC marker |
|
1366 iFHState = EStateInUnknown; |
|
1367 |
|
1368 return EFrameComplete; |
|
1369 } |
|
1370 |
|
1371 // ----------------------------------------------------------------------------- |
|
1372 // CJp2kReadCodec::ReadPPML |
|
1373 // Verify and process Packed Packet Headers, Main Header ( PPM marker ). |
|
1374 // (other items were commented in a header). |
|
1375 // ----------------------------------------------------------------------------- |
|
1376 // |
|
1377 TFrameState CJp2kReadCodec::ReadPPML() |
|
1378 { |
|
1379 TUint8 isUnderflow = EFalse; |
|
1380 if ( !iPreviousPPM ) |
|
1381 { |
|
1382 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
1383 { |
|
1384 // Underflow |
|
1385 return EFrameIncomplete; |
|
1386 } |
|
1387 |
|
1388 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KPPM ) |
|
1389 { |
|
1390 // Unrecognized PPM marker |
|
1391 User::Leave( KErrCorrupt ); |
|
1392 } |
|
1393 |
|
1394 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1395 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( KMarkerLength + 1 ) ) |
|
1396 { |
|
1397 // Underflow, we need Zppm and Nppm to be in the buffer |
|
1398 // backup the iterator to the beginning of the marker |
|
1399 iReader.iPtr -= KMarkerMinLength; |
|
1400 return EFrameIncomplete; |
|
1401 } |
|
1402 |
|
1403 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
1404 { |
|
1405 // Underflow, will keep reading |
|
1406 isUnderflow = ETrue; |
|
1407 } |
|
1408 |
|
1409 TPPMMarker *ppmMarker = new ( ELeave ) TPPMMarker; |
|
1410 CleanupDeletePushL( ppmMarker ); |
|
1411 |
|
1412 ppmMarker->iZppm = *iReader.iPtr++; |
|
1413 TUint32 entries = (TUint32)( markerLength - KMarkerSize - 1 ); |
|
1414 |
|
1415 ppmMarker->iNppm = entries; |
|
1416 ppmMarker->iIppm = HBufC8::NewL( entries ); |
|
1417 |
|
1418 if ( !isUnderflow ) |
|
1419 { |
|
1420 ppmMarker->iIppm->Des( ).Append( iReader.iPtr, entries ); |
|
1421 iReader.iPtr += entries; |
|
1422 iPreviousPPM = 0; |
|
1423 |
|
1424 // Make sure we read all the data |
|
1425 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
1426 { |
|
1427 // We must be missing some data in the marker |
|
1428 User::Leave( KErrCorrupt ); |
|
1429 } |
|
1430 } |
|
1431 else |
|
1432 { |
|
1433 ppmMarker->iIppm->Des().Append( iReader.iPtr, ( iReader.iPtrEnd - iReader.iPtr ) ); |
|
1434 ppmMarker->iRemainder = (TUint32)( entries - ( iReader.iPtrEnd - iReader.iPtr ) ); |
|
1435 iReader.iPtr = iReader.iPtrEnd; |
|
1436 iPreviousPPM = ppmMarker; |
|
1437 } |
|
1438 |
|
1439 // Insert the new PPM marker into the right order |
|
1440 TMainMarker& mainMarker = CONST_CAST( TMainMarker&, iImageInfo->MainMarker() ); |
|
1441 TUint8 tmp = ETrue; |
|
1442 if ( mainMarker.iPpm.Count() > 0 && |
|
1443 mainMarker.iPpm[mainMarker.iPpm.Count() - 1]->iZppm > ppmMarker->iZppm ) |
|
1444 { |
|
1445 for ( entries = 0; entries < (TUint32)mainMarker.iPpm.Count(); ++entries ) |
|
1446 { |
|
1447 // Order by iZppm of the PPM marker |
|
1448 if ( mainMarker.iPpm[entries]->iZppm > ppmMarker->iZppm ) |
|
1449 { |
|
1450 User::LeaveIfError( mainMarker.iPpm.Insert( ppmMarker, entries ) ); |
|
1451 |
|
1452 tmp = EFalse; |
|
1453 entries = (TUint32)mainMarker.iPpm.Count(); |
|
1454 } |
|
1455 } |
|
1456 } |
|
1457 |
|
1458 if ( tmp ) |
|
1459 { |
|
1460 User::LeaveIfError( mainMarker.iPpm.Append( ppmMarker ) ); |
|
1461 } |
|
1462 CleanupStack::Pop(); |
|
1463 } |
|
1464 else |
|
1465 { |
|
1466 if ( (TUint32)( iReader.iPtrEnd - iReader.iPtr ) < iPreviousPPM->iRemainder ) |
|
1467 { |
|
1468 // Continue reading incomplete COM marker |
|
1469 iPreviousPPM->iIppm->Des().Append( iReader.iPtr, ( iReader.iPtrEnd - iReader.iPtr ) ); |
|
1470 iPreviousPPM->iRemainder = (TUint32)( iPreviousPPM->iRemainder - ( iReader.iPtrEnd - iReader.iPtr ) ); |
|
1471 iReader.iPtr = iReader.iPtrEnd; |
|
1472 isUnderflow = ETrue; |
|
1473 } |
|
1474 else |
|
1475 { |
|
1476 // We have the complete COM marker now |
|
1477 iPreviousPPM->iIppm->Des().Append( iReader.iPtr, iPreviousPPM->iRemainder ); |
|
1478 iReader.iPtr += iPreviousPPM->iRemainder; |
|
1479 iPreviousPPM->iRemainder = 0; |
|
1480 iPreviousPPM = 0; |
|
1481 } |
|
1482 } |
|
1483 |
|
1484 if ( !isUnderflow ) |
|
1485 { |
|
1486 // Any valid marker may come after PPM marker |
|
1487 iFHState = EStateInUnknown; |
|
1488 return EFrameComplete; |
|
1489 } |
|
1490 else |
|
1491 { |
|
1492 // Underflow, stay in the same state |
|
1493 iReader.UpdateMainHeader(); |
|
1494 return EFrameIncomplete; |
|
1495 } |
|
1496 } |
|
1497 |
|
1498 // ----------------------------------------------------------------------------- |
|
1499 // CJp2kReadCodec::ReadTLML |
|
1500 // Verify and process Tile Part Lengths, Main Header ( TLM marker ). |
|
1501 // (other items were commented in a header). |
|
1502 // ----------------------------------------------------------------------------- |
|
1503 // |
|
1504 TFrameState CJp2kReadCodec::ReadTLML() |
|
1505 { |
|
1506 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
1507 { |
|
1508 // Underflow |
|
1509 return EFrameIncomplete; |
|
1510 } |
|
1511 |
|
1512 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KTLM ) |
|
1513 { |
|
1514 // Unrecognized TLM marker |
|
1515 User::Leave( KErrCorrupt ); |
|
1516 } |
|
1517 |
|
1518 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1519 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
1520 { |
|
1521 // Underflow, backup the iterator to the beginning of the marker |
|
1522 iReader.iPtr -= KMarkerMinLength; |
|
1523 return EFrameIncomplete; |
|
1524 } |
|
1525 |
|
1526 TTLMMarker *tlmMarker = new ( ELeave ) TTLMMarker; |
|
1527 CleanupDeletePushL( tlmMarker ); |
|
1528 |
|
1529 tlmMarker->iZtlm = *iReader.iPtr++; |
|
1530 tlmMarker->iStlm = *iReader.iPtr++; |
|
1531 |
|
1532 TInt entries = markerLength - ( 2 * KMarkerSize ); |
|
1533 TUint8 st = (TUint8)( ( tlmMarker->iStlm >> 4 ) & 0x03 ); |
|
1534 TUint8 sp = (TUint8)( ( tlmMarker->iStlm >> 6 ) & 0x01 ); |
|
1535 TInt sizEntry = st; |
|
1536 sizEntry += ( sp ? 4 : 2 ); |
|
1537 |
|
1538 while ( entries >= sizEntry ) |
|
1539 { |
|
1540 if ( st == 1 ) |
|
1541 { |
|
1542 // 8 bits tile index |
|
1543 User::LeaveIfError( tlmMarker->iTtlm.Append( *iReader.iPtr++ ) ); |
|
1544 } |
|
1545 else if ( st == 2 ) |
|
1546 { |
|
1547 // 16 bits tile index |
|
1548 User::LeaveIfError( tlmMarker->iTtlm.Append( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) ) ); |
|
1549 } |
|
1550 if ( sp ) //lint !e961 no else is needed here at the end of if...else if |
|
1551 { |
|
1552 // 32 bits length |
|
1553 User::LeaveIfError( tlmMarker->iPtlm.Append( PtrReadUtil::ReadBigEndianUint32Inc( iReader.iPtr ) ) ); |
|
1554 } |
|
1555 else |
|
1556 { |
|
1557 // 16 bits length |
|
1558 User::LeaveIfError( tlmMarker->iPtlm.Append( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) ) ); |
|
1559 } |
|
1560 entries -= sizEntry; |
|
1561 } |
|
1562 |
|
1563 // Make sure we read all the data |
|
1564 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
1565 { |
|
1566 // We must be missing some data in the marker |
|
1567 User::Leave( KErrCorrupt ); |
|
1568 } |
|
1569 |
|
1570 // Insert the new TLM marker into the right order |
|
1571 TMainMarker& mainMarker = CONST_CAST( TMainMarker&, iImageInfo->MainMarker() ); |
|
1572 sp = 1; |
|
1573 for ( entries = 0; entries < mainMarker.iTlm.Count(); ++entries ) |
|
1574 { |
|
1575 // Order by iZtlm of the TLM marker |
|
1576 if ( mainMarker.iTlm[entries]->iZtlm > tlmMarker->iZtlm ) |
|
1577 { |
|
1578 User::LeaveIfError( mainMarker.iTlm.Insert( tlmMarker, entries ) ); |
|
1579 sp = 0; |
|
1580 entries = mainMarker.iTlm.Count(); |
|
1581 } |
|
1582 } |
|
1583 |
|
1584 if ( sp ) |
|
1585 { |
|
1586 User::LeaveIfError( mainMarker.iTlm.Append( tlmMarker ) ); |
|
1587 } |
|
1588 CleanupStack::Pop(); |
|
1589 |
|
1590 // Any valid marker may come after TLM marker |
|
1591 iFHState = EStateInUnknown; |
|
1592 |
|
1593 return EFrameComplete; |
|
1594 } |
|
1595 |
|
1596 // ----------------------------------------------------------------------------- |
|
1597 // CJp2kReadCodec::ReadPLML |
|
1598 // Verify and process Packet Length, Main Header ( PLM marker ). |
|
1599 // (other items were commented in a header). |
|
1600 // ----------------------------------------------------------------------------- |
|
1601 // |
|
1602 TFrameState CJp2kReadCodec::ReadPLML() |
|
1603 { |
|
1604 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
1605 { |
|
1606 // Underflow |
|
1607 return EFrameIncomplete; |
|
1608 } |
|
1609 |
|
1610 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KPLM ) |
|
1611 { |
|
1612 // Unrecognized PLM marker |
|
1613 User::Leave( KErrCorrupt ); |
|
1614 } |
|
1615 |
|
1616 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1617 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
1618 { |
|
1619 // Underflow, backup the iterator to the beginning of the marker |
|
1620 iReader.iPtr -= KMarkerMinLength; |
|
1621 return EFrameIncomplete; |
|
1622 } |
|
1623 |
|
1624 TPLMMarker *plmMarker = new ( ELeave ) TPLMMarker; |
|
1625 CleanupDeletePushL( plmMarker ); |
|
1626 |
|
1627 plmMarker->iZplm = *iReader.iPtr++; |
|
1628 TUint32 entries = (TUint32)( markerLength - KMarkerSize - 1 ); |
|
1629 |
|
1630 plmMarker->iNplm = (TUint8)entries; |
|
1631 plmMarker->iIplm = HBufC8::NewL( entries ); |
|
1632 plmMarker->iIplm->Des().Append( iReader.iPtr, entries ); |
|
1633 iReader.iPtr += entries; |
|
1634 |
|
1635 // Make sure we read all the data |
|
1636 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
1637 { |
|
1638 // We must be missing some data in the marker |
|
1639 User::Leave( KErrCorrupt ); |
|
1640 } |
|
1641 |
|
1642 // Insert the new PLM marker into the right order |
|
1643 TMainMarker& mainMarker = CONST_CAST( TMainMarker&, iImageInfo->MainMarker() ); |
|
1644 TUint8 tmp = ETrue; |
|
1645 |
|
1646 if ( mainMarker.iPlm.Count() > 0 && |
|
1647 mainMarker.iPlm[mainMarker.iPlm.Count() - 1]->iZplm > plmMarker->iZplm ) |
|
1648 { |
|
1649 for ( entries = 0; entries < (TUint32)mainMarker.iPlm.Count(); ++entries ) |
|
1650 { |
|
1651 // Order by iZplm of the PLM marker |
|
1652 if ( mainMarker.iPlm[entries]->iZplm > plmMarker->iZplm ) |
|
1653 { |
|
1654 User::LeaveIfError( mainMarker.iPlm.Insert( plmMarker, entries ) ); |
|
1655 tmp = EFalse; |
|
1656 entries = (TUint32)mainMarker.iPlm.Count(); |
|
1657 } |
|
1658 } |
|
1659 } |
|
1660 |
|
1661 if ( tmp ) |
|
1662 { |
|
1663 User::LeaveIfError( mainMarker.iPlm.Append( plmMarker ) ); |
|
1664 } |
|
1665 CleanupStack::Pop(); |
|
1666 |
|
1667 // Any valid marker may come after PLM marker |
|
1668 iFHState = EStateInUnknown; |
|
1669 |
|
1670 return EFrameComplete; |
|
1671 } |
|
1672 |
|
1673 // ----------------------------------------------------------------------------- |
|
1674 // CJp2kReadCodec::ReadCRGL |
|
1675 // Verify and process Component Registration, Main Header ( CRG marker ). |
|
1676 // (other items were commented in a header). |
|
1677 // ----------------------------------------------------------------------------- |
|
1678 // |
|
1679 TFrameState CJp2kReadCodec::ReadCRGL() |
|
1680 { |
|
1681 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
1682 { |
|
1683 // Underflow |
|
1684 return EFrameIncomplete; |
|
1685 } |
|
1686 |
|
1687 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KCRG ) |
|
1688 { |
|
1689 // Unrecognized CRG marker |
|
1690 User::Leave( KErrCorrupt ); |
|
1691 } |
|
1692 |
|
1693 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1694 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
1695 { |
|
1696 // Underflow, backup the iterator to the beginning of the marker |
|
1697 iReader.iPtr -= KMarkerMinLength; |
|
1698 return EFrameIncomplete; |
|
1699 } |
|
1700 |
|
1701 TCRGMarker *crgMarker = new ( ELeave ) TCRGMarker; |
|
1702 CleanupDeletePushL( crgMarker ); |
|
1703 |
|
1704 TInt entries = markerLength - KMarkerSize; |
|
1705 TUint16 xCrg; |
|
1706 TUint16 yCrg; |
|
1707 while ( entries ) |
|
1708 { |
|
1709 xCrg = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1710 yCrg = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1711 User::LeaveIfError( crgMarker->iXYcrg.Append( TPoint( xCrg, yCrg ) ) ); |
|
1712 entries -= 4; |
|
1713 } |
|
1714 |
|
1715 // Make sure we read all the data |
|
1716 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
1717 { |
|
1718 // We must be missing some data in the marker |
|
1719 User::Leave( KErrCorrupt ); |
|
1720 } |
|
1721 |
|
1722 iImageInfo->AppendCRGL( crgMarker ); |
|
1723 |
|
1724 CleanupStack::Pop( ); |
|
1725 |
|
1726 // Any valid marker may come after CRG marker |
|
1727 iFHState = EStateInUnknown; |
|
1728 |
|
1729 return EFrameComplete; |
|
1730 } |
|
1731 |
|
1732 // ----------------------------------------------------------------------------- |
|
1733 // CJp2kReadCodec::ReadCOML |
|
1734 // Verify and process Comment ( COM marker ). |
|
1735 // (other items were commented in a header). |
|
1736 // ----------------------------------------------------------------------------- |
|
1737 // |
|
1738 TFrameState CJp2kReadCodec::ReadCOML( TBool aMain ) |
|
1739 { |
|
1740 TUint8 isUnderflow = EFalse; |
|
1741 if ( !iPreviousCOM ) |
|
1742 { |
|
1743 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
1744 { |
|
1745 // Underflow |
|
1746 return EFrameIncomplete; |
|
1747 } |
|
1748 |
|
1749 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KCME ) |
|
1750 { |
|
1751 // Unrecognized COM marker |
|
1752 User::Leave( KErrCorrupt ); |
|
1753 } |
|
1754 |
|
1755 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1756 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerLength ) |
|
1757 { |
|
1758 // Underflow, we need Rcom to be in the buffer |
|
1759 // backup the iterator to the beginning of the marker |
|
1760 iReader.iPtr -= KMarkerMinLength; |
|
1761 return EFrameIncomplete; |
|
1762 } |
|
1763 |
|
1764 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
1765 { |
|
1766 // Underflow, will keep reading |
|
1767 isUnderflow = ETrue; |
|
1768 } |
|
1769 |
|
1770 TCOMMarker* comMarker = new ( ELeave ) TCOMMarker; |
|
1771 CleanupDeletePushL( comMarker ); |
|
1772 |
|
1773 comMarker->iRcom = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1774 TInt entries = markerLength - ( 2 * KMarkerSize ); |
|
1775 |
|
1776 comMarker->iCcom = HBufC8::NewL( entries ); |
|
1777 if ( !isUnderflow ) |
|
1778 { |
|
1779 comMarker->iCcom->Des().Append( iReader.iPtr, entries ); |
|
1780 iReader.iPtr += entries; |
|
1781 iPreviousCOM = 0; |
|
1782 |
|
1783 // Make sure we read all the data |
|
1784 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
1785 { |
|
1786 // We must be missing some data in the marker |
|
1787 User::Leave( KErrCorrupt ); |
|
1788 } |
|
1789 } |
|
1790 else |
|
1791 { |
|
1792 comMarker->iCcom->Des().Append( iReader.iPtr, ( iReader.iPtrEnd - iReader.iPtr ) ); |
|
1793 comMarker->iRemainder = (TUint16)( entries - ( iReader.iPtrEnd - iReader.iPtr ) ); |
|
1794 iReader.iPtr = iReader.iPtrEnd; |
|
1795 iPreviousCOM = comMarker; |
|
1796 } |
|
1797 |
|
1798 if ( aMain ) |
|
1799 { |
|
1800 iImageInfo->AppendCOML( comMarker ); |
|
1801 } |
|
1802 else |
|
1803 { |
|
1804 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
1805 |
|
1806 // Append COM to the current tile and decrement the tile length |
|
1807 tile.AppendCOML( comMarker, markerLength + KMarkerSize ); |
|
1808 } |
|
1809 CleanupStack::Pop(); |
|
1810 } |
|
1811 else |
|
1812 { |
|
1813 if ( ( iReader.iPtrEnd - iReader.iPtr ) < iPreviousCOM->iRemainder ) |
|
1814 { |
|
1815 // Continue reading incomplete COM marker |
|
1816 iPreviousCOM->iCcom->Des().Append( iReader.iPtr, ( iReader.iPtrEnd - iReader.iPtr ) ); |
|
1817 iPreviousCOM->iRemainder = (TUint16)( iPreviousCOM->iRemainder - ( iReader.iPtrEnd - iReader.iPtr ) ); |
|
1818 iReader.iPtr = iReader.iPtrEnd; |
|
1819 isUnderflow = ETrue; |
|
1820 } |
|
1821 else |
|
1822 { |
|
1823 // We have the complete COM marker now |
|
1824 iPreviousCOM->iCcom->Des( ).Append( iReader.iPtr, iPreviousCOM->iRemainder ); |
|
1825 iReader.iPtr += iPreviousCOM->iRemainder; |
|
1826 iPreviousCOM->iRemainder = 0; |
|
1827 iPreviousCOM = 0; |
|
1828 } |
|
1829 } |
|
1830 |
|
1831 if ( !isUnderflow ) |
|
1832 { |
|
1833 // Any valid marker may come after COM marker |
|
1834 iFHState = EStateInUnknown; |
|
1835 return EFrameComplete; |
|
1836 } |
|
1837 else |
|
1838 { |
|
1839 // Underflow, stay in the same state |
|
1840 if ( aMain ) |
|
1841 { |
|
1842 iReader.UpdateMainHeader( ); |
|
1843 } |
|
1844 return EFrameIncomplete; |
|
1845 } |
|
1846 } |
|
1847 |
|
1848 // ----------------------------------------------------------------------------- |
|
1849 // CJp2kReadCodec::ReadSOTL |
|
1850 // Verify and process Start of Tile Part ( SOT marker ). |
|
1851 // (other items were commented in a header). |
|
1852 // ----------------------------------------------------------------------------- |
|
1853 // |
|
1854 TFrameState CJp2kReadCodec::ReadSOTL() |
|
1855 { |
|
1856 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
1857 { |
|
1858 // Underflow |
|
1859 return EFrameIncomplete; |
|
1860 } |
|
1861 |
|
1862 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KSOT ) |
|
1863 { |
|
1864 // Unrecognized SOT marker |
|
1865 User::Leave( KErrCorrupt ); |
|
1866 } |
|
1867 |
|
1868 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1869 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
1870 { |
|
1871 // Underflow, backup the iterator to the beginning of the marker |
|
1872 iReader.iPtr -= KMarkerMinLength; |
|
1873 return EFrameIncomplete; |
|
1874 } |
|
1875 |
|
1876 TSotMarker sotMarker; |
|
1877 sotMarker.iIsot = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
1878 sotMarker.iPsot = PtrReadUtil::ReadBigEndianUint32Inc( iReader.iPtr ); |
|
1879 sotMarker.iTPsot = *iReader.iPtr++; |
|
1880 sotMarker.iTNsot = *iReader.iPtr++; |
|
1881 |
|
1882 if(sotMarker.iIsot >= ( iImageInfo->NumOfHorizTiles() * iImageInfo->NumOfVertTiles() )) |
|
1883 { |
|
1884 // Invalid tile index, exceeds the number of tiles, exit |
|
1885 User::Leave( KErrCorrupt ); |
|
1886 } |
|
1887 |
|
1888 if ( sotMarker.iPsot == 0 ) |
|
1889 { |
|
1890 // Try to look for tile part length information |
|
1891 // from the TLM in the main header - if there is one |
|
1892 iImageInfo->GetFromTLM( sotMarker ); |
|
1893 } |
|
1894 |
|
1895 iImageInfo->IncrementLastTilePartProcessed(); |
|
1896 |
|
1897 if ( iUseNewTile ) |
|
1898 { |
|
1899 if ( sotMarker.iIsot < iLastTileIndex ) |
|
1900 { |
|
1901 // Skip all tiles with iIsot smaller than the iLastTileIndex |
|
1902 iReader.iSkipLength = sotMarker.iPsot - markerLength - KMarkerSize; |
|
1903 iUseNewTile = EFalse; |
|
1904 iFHState = EStateInSkipTile; |
|
1905 return EFrameComplete; |
|
1906 } |
|
1907 |
|
1908 if(sotMarker.iTPsot >= sotMarker.iTNsot) |
|
1909 { |
|
1910 // Skip the tiles where tile part index is larger than |
|
1911 // the number of tile parts |
|
1912 iReader.iSkipLength = sotMarker.iPsot - markerLength - KMarkerSize; |
|
1913 iUseNewTile = EFalse; |
|
1914 iFHState = EStateInSkipTile; |
|
1915 return EFrameComplete; |
|
1916 } |
|
1917 |
|
1918 // Start using this tile as the current tile |
|
1919 iLastTileIndex = sotMarker.iIsot; |
|
1920 |
|
1921 // Save the next tile offset |
|
1922 iReader.iNewDataStart += sotMarker.iPsot; |
|
1923 iUseNextTile = iSequential = ETrue; |
|
1924 } |
|
1925 else |
|
1926 { |
|
1927 if ( sotMarker.iIsot != iLastTileIndex ) |
|
1928 { |
|
1929 if ( iUseNextTile ) |
|
1930 { |
|
1931 if ( sotMarker.iIsot > iLastTileIndex ) |
|
1932 { |
|
1933 iUseNextTile = EFalse; |
|
1934 } |
|
1935 } |
|
1936 iSequential = EFalse; |
|
1937 |
|
1938 // Skip all tiles that are not equal to current tile |
|
1939 iReader.iSkipLength = sotMarker.iPsot - markerLength - KMarkerSize; |
|
1940 iFHState = EStateInSkipTile; |
|
1941 return EFrameComplete; |
|
1942 } |
|
1943 else |
|
1944 { |
|
1945 // Tiles are in sequential order |
|
1946 if ( iUseNextTile && iSequential ) |
|
1947 { |
|
1948 // Save the next tile offset |
|
1949 iReader.iNewDataStart += sotMarker.iPsot; |
|
1950 } |
|
1951 } |
|
1952 } |
|
1953 |
|
1954 CJ2kTileInfo *tile = 0; |
|
1955 if ( iUseNewTile ) |
|
1956 { |
|
1957 tile = CJ2kTileInfo::NewLC( *iImageInfo, iReader ); |
|
1958 } |
|
1959 else |
|
1960 { |
|
1961 tile = CONST_CAST( CJ2kTileInfo*, &iImageInfo->TileAt( iLastTileIndex ) ); |
|
1962 } |
|
1963 |
|
1964 // Set the SOT marker |
|
1965 tile->SetSotMarker( sotMarker ); |
|
1966 |
|
1967 if ( sotMarker.iPsot ) |
|
1968 { |
|
1969 // Decrement the tile length |
|
1970 tile->SetTileLength( sotMarker.iPsot - markerLength - KMarkerSize ); |
|
1971 } |
|
1972 |
|
1973 // Make sure we read all the data |
|
1974 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
1975 { |
|
1976 // We must be missing some data in the marker |
|
1977 User::Leave( KErrCorrupt ); |
|
1978 } |
|
1979 |
|
1980 if ( iUseNewTile ) |
|
1981 { |
|
1982 iImageInfo->Append( tile ); |
|
1983 CleanupStack::Pop(); |
|
1984 iUseNewTile = EFalse; |
|
1985 } |
|
1986 |
|
1987 // Any valid marker may come after SOT marker |
|
1988 iFHState = EStateInUnknown; |
|
1989 return EFrameComplete; |
|
1990 |
|
1991 } |
|
1992 |
|
1993 // ----------------------------------------------------------------------------- |
|
1994 // CJp2kReadCodec::ReadSODL |
|
1995 // Verify and process Start of Data ( SOD marker ). |
|
1996 // (other items were commented in a header). |
|
1997 // ----------------------------------------------------------------------------- |
|
1998 // |
|
1999 TFrameState CJp2kReadCodec::ReadSODL() |
|
2000 { |
|
2001 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KSOD ) |
|
2002 { |
|
2003 // Unrecognized SOD marker |
|
2004 User::Leave( KErrCorrupt ); |
|
2005 } |
|
2006 |
|
2007 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
2008 |
|
2009 TUint32& length = tile.TileLength(); |
|
2010 if ( length ) |
|
2011 { |
|
2012 // Decrement the tile length |
|
2013 length -= KMarkerSize; |
|
2014 } |
|
2015 |
|
2016 // Initialize the tile only for tile part 0 |
|
2017 if ( tile.IsFirstTilePart() ) |
|
2018 { |
|
2019 tile.InitializeL(); |
|
2020 iImageInfo->SetLastTilePartProcessed( tile.SotMarker().iIsot ); |
|
2021 } |
|
2022 |
|
2023 if ( tile.IsPPT() ) |
|
2024 { |
|
2025 // Use packet header information from PPT |
|
2026 tile.UsePPTL(); |
|
2027 } |
|
2028 else if ( iImageInfo->IsPPM() ) |
|
2029 { |
|
2030 // Use packet header information from PPM |
|
2031 iImageInfo->UsePPM( tile ); |
|
2032 } |
|
2033 else |
|
2034 { |
|
2035 tile.SetPacketHeaderReader( &iReader ); |
|
2036 } |
|
2037 |
|
2038 if ( ( iImageInfo->NumOfHorizTiles() == 1 ) && |
|
2039 ( iImageInfo->NumOfVertTiles() == 1 ) ) |
|
2040 { |
|
2041 // To force a return immediately from ProcessFrameL() |
|
2042 // on first entry to stimulate the occurrance of |
|
2043 // the progress bar |
|
2044 iProgressBar = ETrue; |
|
2045 } |
|
2046 |
|
2047 // We know that bitstream will follow SOD marker |
|
2048 iFHState = EStateInBITSTREAM; |
|
2049 |
|
2050 return EFrameComplete; |
|
2051 } |
|
2052 |
|
2053 // ----------------------------------------------------------------------------- |
|
2054 // CJp2kReadCodec::ReadBitStreamL |
|
2055 // Verify and process BitStream Data. |
|
2056 // (other items were commented in a header). |
|
2057 // ----------------------------------------------------------------------------- |
|
2058 // |
|
2059 TFrameState CJp2kReadCodec::ReadBitStreamL() |
|
2060 { |
|
2061 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
2062 TUint32& length = tile.TileLength( ); |
|
2063 |
|
2064 if ( length ) |
|
2065 { |
|
2066 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( TInt32 )length ) |
|
2067 { |
|
2068 // Larger bitstream will not fit into the internal |
|
2069 // buffer size, so process a chunk at a time |
|
2070 // we have to add some kind of state information |
|
2071 // so that we know where to continue and process |
|
2072 if ( tile.IsSpeedup() ) |
|
2073 { |
|
2074 // For RLCP/RPCL progression order |
|
2075 if ( tile.LastLevelProcessed() <= tile.NumOfLevelsPOC() ) |
|
2076 { |
|
2077 tile.ReadBitStreamL(); |
|
2078 } |
|
2079 else |
|
2080 { |
|
2081 // discard any data that beyond the required resolution level |
|
2082 if ( !tile.IsPPT() ) |
|
2083 { |
|
2084 if ( iImageInfo->IsPPM() ) |
|
2085 { |
|
2086 // discard current packet header in PPM marker |
|
2087 iImageInfo->ResetPPM(); |
|
2088 } |
|
2089 } |
|
2090 iReader.iPtr = iReader.iPtrEnd; |
|
2091 } |
|
2092 } |
|
2093 else |
|
2094 { |
|
2095 tile.ReadBitStreamL(); |
|
2096 } |
|
2097 |
|
2098 length -= ( iReader.iPtr - iReader.iPtrStartMarker ); |
|
2099 iReader.UpdateTileHeader(); |
|
2100 |
|
2101 // stay in the current state |
|
2102 return EFrameIncomplete; |
|
2103 } |
|
2104 |
|
2105 // We are sure that all tile part data fit into the buffer |
|
2106 // so just go ahead and process it |
|
2107 if ( tile.IsSpeedup() ) |
|
2108 { |
|
2109 // For RLCP/RPCL progression order |
|
2110 if ( tile.LastLevelProcessed() <= tile.NumOfLevelsPOC() ) |
|
2111 { |
|
2112 tile.ReadBitStreamL( ETrue ); |
|
2113 iReader.TryReAlignReader(); |
|
2114 } |
|
2115 else |
|
2116 { |
|
2117 // discard any data that beyond the required resolution level |
|
2118 if ( !tile.IsPPT() ) |
|
2119 { |
|
2120 if ( iImageInfo->IsPPM() ) |
|
2121 { |
|
2122 // discard current packet header in PPM marker |
|
2123 iImageInfo->ResetPPM(); |
|
2124 } |
|
2125 } |
|
2126 iReader.iPtr += length; |
|
2127 } |
|
2128 } |
|
2129 else |
|
2130 { |
|
2131 tile.ReadBitStreamL( ETrue ); |
|
2132 iReader.TryReAlignReader(); |
|
2133 } |
|
2134 |
|
2135 length -= ( iReader.iPtr - iReader.iPtrStartMarker ); |
|
2136 |
|
2137 if ( tile.IsSpeedup() ) |
|
2138 { |
|
2139 // discard any data that beyond the required resolution level |
|
2140 if ( !tile.IsPPT() ) |
|
2141 { |
|
2142 if ( iImageInfo->IsPPM() ) |
|
2143 { |
|
2144 // discard current packet header in PPM marker |
|
2145 iImageInfo->ResetPPM(); |
|
2146 } |
|
2147 } |
|
2148 iReader.iPtr += length; |
|
2149 length = 0; |
|
2150 } |
|
2151 |
|
2152 // Sanity check |
|
2153 if ( length != 0 ) |
|
2154 { |
|
2155 User::Leave( KErrCorrupt ); |
|
2156 } |
|
2157 |
|
2158 if ( tile.IsLastTilePart() ) |
|
2159 { |
|
2160 tile.DoReleaseUnusedMarkers(); |
|
2161 |
|
2162 // proceed to the decoding state |
|
2163 iDecodeTile = ETrue; |
|
2164 |
|
2165 // Start with new tile |
|
2166 iUseNewTile = ETrue; |
|
2167 if ( !iUseNextTile ) |
|
2168 { |
|
2169 iFHState = EStateInUnknown; |
|
2170 return EFrameIncompleteRepositionRequest; |
|
2171 } |
|
2172 else |
|
2173 { |
|
2174 if ( !iSequential ) |
|
2175 { |
|
2176 // Must be End of Codestream EOC |
|
2177 iFHState = EStateInEOC; |
|
2178 iReader.iPtr += KMarkerSize; |
|
2179 return EFrameComplete; |
|
2180 } |
|
2181 } |
|
2182 } |
|
2183 |
|
2184 // We do not know what is the next marker |
|
2185 // either next SOT or EOC |
|
2186 iFHState = EStateInUnknown; |
|
2187 } |
|
2188 else |
|
2189 { |
|
2190 if ( iReader.iPtrEnd == iReader.iPtr ) |
|
2191 { |
|
2192 // Assume that we have done with the image |
|
2193 iFHState = EStateInEOC; |
|
2194 } |
|
2195 else |
|
2196 { |
|
2197 if ( ( iReader.iPtrEnd - iReader.iPtr ) >= 2 ) |
|
2198 { |
|
2199 TUint16 marker = PtrReadUtil::ReadBigEndianUint16( iReader.iPtr ); |
|
2200 if ( marker == KSOT ) |
|
2201 { |
|
2202 // Next SOT marker is found |
|
2203 iFHState = EStateInSOT; |
|
2204 } |
|
2205 else if ( marker == EStateInEOC ) |
|
2206 { |
|
2207 // End of Codestream is found |
|
2208 iFHState = EStateInEOC; |
|
2209 iReader.iPtr += KMarkerSize; |
|
2210 } |
|
2211 else |
|
2212 { |
|
2213 tile.ReadBitStreamL(); |
|
2214 marker = PtrReadUtil::ReadBigEndianUint16( iReader.iPtr ); |
|
2215 |
|
2216 if ( marker == KSOT || marker == KEOC ) |
|
2217 { |
|
2218 iFHState = EStateInUnknown; |
|
2219 |
|
2220 if ( tile.IsLastTilePart() ) |
|
2221 { |
|
2222 tile.DoReleaseUnusedMarkers(); |
|
2223 |
|
2224 // proceed to the decoding state |
|
2225 iDecodeTile = ETrue; |
|
2226 |
|
2227 // Start with new tile |
|
2228 iUseNewTile = ETrue; |
|
2229 if ( !iUseNextTile ) |
|
2230 { |
|
2231 return EFrameIncompleteRepositionRequest; |
|
2232 } |
|
2233 else |
|
2234 { |
|
2235 if ( !iSequential ) |
|
2236 { |
|
2237 // Must be End of Codestream EOC |
|
2238 iFHState = EStateInEOC; |
|
2239 iReader.iPtr += KMarkerSize; |
|
2240 } |
|
2241 } |
|
2242 } |
|
2243 } |
|
2244 else |
|
2245 { |
|
2246 iReader.UpdateTileHeader(); |
|
2247 |
|
2248 // Stay in the current state |
|
2249 return EFrameIncomplete; |
|
2250 } |
|
2251 } |
|
2252 } |
|
2253 else |
|
2254 { |
|
2255 iReader.UpdateTileHeader(); |
|
2256 |
|
2257 // Stay in the current state |
|
2258 return EFrameIncomplete; |
|
2259 } |
|
2260 } |
|
2261 } |
|
2262 |
|
2263 if ( ( iImageInfo->NumOfHorizTiles() == 1 ) && |
|
2264 ( iImageInfo->NumOfVertTiles() == 1 ) ) |
|
2265 { |
|
2266 // To force a return immediately from ProcessFrameL() |
|
2267 // on first entry to stimulate the occurrance of |
|
2268 // the progress bar |
|
2269 iProgressBar = ETrue; |
|
2270 } |
|
2271 |
|
2272 return EFrameComplete; |
|
2273 } |
|
2274 |
|
2275 // ----------------------------------------------------------------------------- |
|
2276 // CJp2kReadCodec::ReadPPTL |
|
2277 // Verify and process Packed Packet Headers, Tile Part Header ( PPT marker ). |
|
2278 // (other items were commented in a header). |
|
2279 // ----------------------------------------------------------------------------- |
|
2280 // |
|
2281 TFrameState CJp2kReadCodec::ReadPPTL() |
|
2282 { |
|
2283 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
2284 { |
|
2285 // Underflow |
|
2286 return EFrameIncomplete; |
|
2287 } |
|
2288 |
|
2289 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KPPT ) |
|
2290 { |
|
2291 // Unrecognized PPT marker |
|
2292 User::Leave( KErrCorrupt ); |
|
2293 } |
|
2294 |
|
2295 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
2296 |
|
2297 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
2298 { |
|
2299 // Underflow, backup the iterator to the beginning of the marker |
|
2300 iReader.iPtr -= KMarkerMinLength; |
|
2301 return EFrameIncomplete; |
|
2302 } |
|
2303 |
|
2304 TPPTMarker *pptMarker = new ( ELeave ) TPPTMarker; |
|
2305 CleanupDeletePushL( pptMarker ); |
|
2306 |
|
2307 TInt entries = markerLength - KMarkerSize - 1; |
|
2308 pptMarker->iZppt = *iReader.iPtr++; |
|
2309 pptMarker->iIppt = HBufC8::NewL( entries ); |
|
2310 pptMarker->iIppt->Des( ).Append( iReader.iPtr, entries ); |
|
2311 iReader.iPtr += entries; |
|
2312 |
|
2313 // Make sure we read all the data |
|
2314 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
2315 { |
|
2316 // We must be missing some data in the marker |
|
2317 User::Leave( KErrCorrupt ); |
|
2318 } |
|
2319 |
|
2320 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
2321 |
|
2322 // Append PPT to the current tile and decrement the tile length |
|
2323 tile.AppendPPTL( pptMarker, markerLength + KMarkerSize ); |
|
2324 CleanupStack::Pop(); |
|
2325 |
|
2326 // Any valid marker may come after PPT marker |
|
2327 iFHState = EStateInUnknown; |
|
2328 |
|
2329 return EFrameComplete; |
|
2330 } |
|
2331 |
|
2332 // ----------------------------------------------------------------------------- |
|
2333 // CJp2kReadCodec::ReadPLTL |
|
2334 // Verify and process Packet Length, Tile Part Header ( PLT marker ). |
|
2335 // (other items were commented in a header). |
|
2336 // ----------------------------------------------------------------------------- |
|
2337 // |
|
2338 TFrameState CJp2kReadCodec::ReadPLTL() |
|
2339 { |
|
2340 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerMinLength ) |
|
2341 { |
|
2342 // Underflow |
|
2343 return EFrameIncomplete; |
|
2344 } |
|
2345 |
|
2346 if ( PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ) != KPLT ) |
|
2347 { |
|
2348 // Unrecognized PLT marker |
|
2349 User::Leave( KErrCorrupt ); |
|
2350 } |
|
2351 |
|
2352 TUint16 markerLength = PtrReadUtil::ReadBigEndianUint16Inc( iReader.iPtr ); |
|
2353 |
|
2354 if ( ( iReader.iPtrEnd - iReader.iPtr ) < ( markerLength - KMarkerLength ) ) |
|
2355 { |
|
2356 // Underflow, backup the iterator to the beginning of the marker |
|
2357 iReader.iPtr -= KMarkerMinLength; |
|
2358 return EFrameIncomplete; |
|
2359 } |
|
2360 |
|
2361 TPLTMarker *pltMarker = new ( ELeave ) TPLTMarker; |
|
2362 //CleanupStack::PushL( pltMarker ); |
|
2363 CleanupDeletePushL( pltMarker ); |
|
2364 |
|
2365 pltMarker->iZplt = *iReader.iPtr++; |
|
2366 |
|
2367 TInt entries = markerLength - KMarkerSize - 1; |
|
2368 while ( entries ) |
|
2369 { |
|
2370 User::LeaveIfError( pltMarker->iIplt.Append( *iReader.iPtr++ ) ); |
|
2371 --entries; |
|
2372 } |
|
2373 |
|
2374 // Make sure we read all the data |
|
2375 if ( ( iReader.iPtr - iReader.iPtrStartMarker ) != ( markerLength + KMarkerSize ) ) |
|
2376 { |
|
2377 // We must be missing some data in the marker |
|
2378 User::Leave( KErrCorrupt ); |
|
2379 } |
|
2380 |
|
2381 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
2382 |
|
2383 // Append PLT to the current tile and decrement the tile length |
|
2384 tile.AppendPLTL( pltMarker, markerLength + KMarkerSize ); |
|
2385 CleanupStack::Pop(); |
|
2386 |
|
2387 // Any valid marker may come after PLT marker |
|
2388 iFHState = EStateInUnknown; |
|
2389 |
|
2390 return EFrameComplete; |
|
2391 } |
|
2392 |
|
2393 // ----------------------------------------------------------------------------- |
|
2394 // CJp2kReadCodec::ReadSkipTileL |
|
2395 // Ignore the content and advance the iterator to the next marker. |
|
2396 // (other items were commented in a header). |
|
2397 // ----------------------------------------------------------------------------- |
|
2398 // |
|
2399 TFrameState CJp2kReadCodec::ReadSkipTileL() |
|
2400 { |
|
2401 if ( (TUint32)( iReader.iPtrEnd - iReader.iPtr ) < iReader.iSkipLength ) |
|
2402 { |
|
2403 iReader.iSkipLength -= ( iReader.iPtrEnd - iReader.iPtr ); |
|
2404 iReader.iPtr = iReader.iPtrEnd; |
|
2405 |
|
2406 // Stay in the current state |
|
2407 return EFrameIncomplete; |
|
2408 } |
|
2409 else |
|
2410 { |
|
2411 if ( iReader.iSkipLength ) |
|
2412 { |
|
2413 iReader.iPtr += iReader.iSkipLength; |
|
2414 iReader.iSkipLength = 0; |
|
2415 } |
|
2416 else |
|
2417 { |
|
2418 iFHState = EStateInUnknown; |
|
2419 } |
|
2420 return EFrameComplete; |
|
2421 } |
|
2422 } |
|
2423 |
|
2424 // ----------------------------------------------------------------------------- |
|
2425 // CJp2kReadCodec::UpdateStateFromMarkerL |
|
2426 // Update the current state according to the marker type. |
|
2427 // (other items were commented in a header). |
|
2428 // ----------------------------------------------------------------------------- |
|
2429 // |
|
2430 TFrameState CJp2kReadCodec::UpdateStateFromMarkerL() |
|
2431 { |
|
2432 if ( ( iReader.iPtrEnd - iReader.iPtr ) < KMarkerSize ) |
|
2433 { |
|
2434 // Underflow |
|
2435 return EFrameIncomplete; |
|
2436 } |
|
2437 |
|
2438 TUint16 marker = PtrReadUtil::ReadBigEndianUint16( iReader.iPtr ); |
|
2439 switch ( marker ) |
|
2440 { |
|
2441 case KCOD: |
|
2442 { |
|
2443 iFHState = EStateInCOD; |
|
2444 break; |
|
2445 } |
|
2446 case KCOC: |
|
2447 { |
|
2448 iFHState = EStateInCOC; |
|
2449 break; |
|
2450 } |
|
2451 case KQCD: |
|
2452 { |
|
2453 iFHState = EStateInQCD; |
|
2454 break; |
|
2455 } |
|
2456 case KQCC: |
|
2457 { |
|
2458 iFHState = EStateInQCC; |
|
2459 break; |
|
2460 } |
|
2461 case KRGN: |
|
2462 { |
|
2463 iFHState = EStateInRGN; |
|
2464 break; |
|
2465 } |
|
2466 case KPOC: |
|
2467 { |
|
2468 iFHState = EStateInPOC; |
|
2469 break; |
|
2470 } |
|
2471 case KPPM: |
|
2472 { |
|
2473 iFHState = EStateInPPM; |
|
2474 break; |
|
2475 } |
|
2476 case KTLM: |
|
2477 { |
|
2478 iFHState = EStateInTLM; |
|
2479 break; |
|
2480 } |
|
2481 case KPLM: |
|
2482 { |
|
2483 iFHState = EStateInPLM; |
|
2484 break; |
|
2485 } |
|
2486 case KCRG: |
|
2487 { |
|
2488 iFHState = EStateInCRG; |
|
2489 break; |
|
2490 } |
|
2491 case KCME: |
|
2492 { |
|
2493 iFHState = EStateInCOM; |
|
2494 break; |
|
2495 } |
|
2496 case KSOT: |
|
2497 { |
|
2498 iFHState = EStateInSOT; |
|
2499 break; |
|
2500 } |
|
2501 case KPPT: |
|
2502 { |
|
2503 iFHState = EStateInPPT; |
|
2504 break; |
|
2505 } |
|
2506 case KPLT: |
|
2507 { |
|
2508 iFHState = EStateInPLT; |
|
2509 break; |
|
2510 } |
|
2511 case KSOD: |
|
2512 { |
|
2513 iFHState = EStateInSOD; |
|
2514 break; |
|
2515 } |
|
2516 case KEOC: |
|
2517 { |
|
2518 if ( !iUseNewTile && iImageInfo->TileCount() ) |
|
2519 { |
|
2520 // There is a tile which has not been decoded yet |
|
2521 CJ2kTileInfo& tile = CONST_CAST( CJ2kTileInfo&, iImageInfo->TileAt( iLastTileIndex ) ); |
|
2522 |
|
2523 tile.DoReleaseUnusedMarkers(); |
|
2524 |
|
2525 // Decode and delete the tile |
|
2526 DecodeAndDeleteTileL( tile ); |
|
2527 |
|
2528 // Start with new tile |
|
2529 iUseNewTile = ETrue; |
|
2530 if ( !iUseNextTile ) |
|
2531 { |
|
2532 iFHState = EStateInUnknown; |
|
2533 return EFrameIncompleteRepositionRequest; |
|
2534 } |
|
2535 else |
|
2536 { |
|
2537 if ( !iSequential ) |
|
2538 { |
|
2539 // Must be End of Codestream EOC |
|
2540 iFHState = EStateInEOC; |
|
2541 iReader.iPtr += KMarkerSize; |
|
2542 return EFrameComplete; |
|
2543 } |
|
2544 } |
|
2545 } |
|
2546 else |
|
2547 { |
|
2548 iFHState = EStateInEOC; |
|
2549 |
|
2550 // Have to increment the iterator |
|
2551 iReader.iPtr += KMarkerSize; |
|
2552 } |
|
2553 break; |
|
2554 } |
|
2555 default: |
|
2556 { |
|
2557 if ( marker < KEXTS || marker > KEXTE ) |
|
2558 { |
|
2559 // Unrecognized marker |
|
2560 User::Leave( KErrCorrupt ); |
|
2561 } |
|
2562 else |
|
2563 { |
|
2564 // Ignore the extension marker |
|
2565 iReader.iPtr += KMarkerSize; |
|
2566 } |
|
2567 break; |
|
2568 } |
|
2569 } |
|
2570 return EFrameComplete; |
|
2571 } |
|
2572 |
|
2573 // ----------------------------------------------------------------------------- |
|
2574 // CJp2kReadCodec::DecodeAndDeleteTileL |
|
2575 // Decode the tile, write to image processor and delete the tile. |
|
2576 // (other items were commented in a header). |
|
2577 // ----------------------------------------------------------------------------- |
|
2578 // |
|
2579 void CJp2kReadCodec::DecodeAndDeleteTileL( CJ2kTileInfo& aTile ) |
|
2580 { |
|
2581 if ( !iEntropy ) |
|
2582 { |
|
2583 iEntropy = CJ2kEntropyDecoder::NewL( *iImageInfo ); |
|
2584 } |
|
2585 |
|
2586 if ( !iImageWriter ) |
|
2587 { |
|
2588 iImageWriter = CJ2kImageWriter::NewL( ImageProcessor( ), *iImageInfo, CONST_CAST( TJ2kInfo&,iJ2kInfo ) ); |
|
2589 } |
|
2590 |
|
2591 if ( !iSynthesis ) |
|
2592 { |
|
2593 iSynthesis = new ( ELeave ) CJ2kSynthesis; |
|
2594 } |
|
2595 |
|
2596 if ( iStyleUsed == EUnknownDecoder ) |
|
2597 { |
|
2598 // Use tile-based as the default |
|
2599 iStyleUsed = ETileBasedDecoder; |
|
2600 |
|
2601 // If extra levels are dropped, the resolution of the decoded image is larger than |
|
2602 // the resolution of the output image. levelsDropped here gives the resolution of |
|
2603 // the decoded image (and thus relates to the amount of memory required for decoding). |
|
2604 TUint8 levelsDropped = (TUint8)(iImageInfo->LevelDrop() - iImageInfo->ExtraLevelDrop()); |
|
2605 |
|
2606 TSizMarker& sizMarker = CONST_CAST( TSizMarker&, iImageInfo->SizMarker() ); |
|
2607 if ( ( sizMarker.iXTsiz >> levelsDropped ) > (TUint32) KWaveletBlockSize || |
|
2608 ( sizMarker.iYTsiz >> levelsDropped ) > (TUint32) KWaveletBlockSize ) |
|
2609 { |
|
2610 iStyleUsed = EBlockBasedDecoder; |
|
2611 } |
|
2612 } |
|
2613 |
|
2614 if ( iStyleUsed == ETileBasedDecoder ) |
|
2615 { |
|
2616 iSynthesis->DecodeTileL( *iImageWriter, *iEntropy, *iImageInfo, aTile ); |
|
2617 } |
|
2618 else |
|
2619 { |
|
2620 iSynthesis->DecodeTileBlockL( *iImageWriter, *iEntropy, *iImageInfo, aTile ); |
|
2621 } |
|
2622 |
|
2623 iImageInfo->Remove( 0 ); |
|
2624 } |
|
2625 |
|
2626 // ----------------------------------------------------------------------------- |
|
2627 // CJp2kReadCodec::ConvertImageDataL |
|
2628 // Convert some metadata from file format to TImageDataBlock derived objects |
|
2629 // and let the framework managing the buffer |
|
2630 // (other items were commented in a header). |
|
2631 // ----------------------------------------------------------------------------- |
|
2632 // |
|
2633 void CJp2kReadCodec::ConvertImageDataL() |
|
2634 { |
|
2635 TJ2kInfo& info = CONST_CAST( TJ2kInfo&, iJ2kInfo ); |
|
2636 |
|
2637 TInt index; |
|
2638 // Convert each IPR box to TJp2kIprBox image data |
|
2639 for ( index = 0; index < info.iIPRList.Count(); ++index ) |
|
2640 { |
|
2641 TJp2kIprBox* jp2kIPR = new (ELeave) TJp2kIprBox; |
|
2642 CleanupDeletePushL( jp2kIPR ); |
|
2643 |
|
2644 jp2kIPR->iIprData = info.iIPRList[index]; |
|
2645 |
|
2646 User::LeaveIfError( iFrameData->AppendImageData( jp2kIPR ) ); |
|
2647 CleanupStack::Pop(); // jp2kIPR |
|
2648 |
|
2649 // Transfer the ownership of the buffer to the framework |
|
2650 User::LeaveIfError( iFrameData->AppendImageBuffer( jp2kIPR->iIprData ) ); |
|
2651 info.iIPRList[index] = 0; |
|
2652 } |
|
2653 info.iIPRList.Reset(); |
|
2654 |
|
2655 // Convert each XML box to TJp2kXmlBox image data |
|
2656 for ( index = 0; index < info.iXMLList.Count(); ++index ) |
|
2657 { |
|
2658 TJp2kXmlBox* jp2kXML = new (ELeave) TJp2kXmlBox; |
|
2659 CleanupDeletePushL( jp2kXML ); |
|
2660 |
|
2661 jp2kXML->iXmlData = info.iXMLList[index]; |
|
2662 |
|
2663 User::LeaveIfError( iFrameData->AppendImageData( jp2kXML ) ); |
|
2664 CleanupStack::Pop(); // jp2kXML |
|
2665 |
|
2666 // Transfer the ownership of the buffer to the framework |
|
2667 User::LeaveIfError( iFrameData->AppendImageBuffer( jp2kXML->iXmlData ) ); |
|
2668 info.iXMLList[index] = 0; |
|
2669 } |
|
2670 info.iXMLList.Reset(); |
|
2671 |
|
2672 TInt length; |
|
2673 const TUint8 *ptr = 0; |
|
2674 // Convert each UUID box to TJp2kUuidBox image data |
|
2675 for ( index = 0; index < info.iUUIDList.Count(); ++index ) |
|
2676 { |
|
2677 TJp2kUuidBox* jp2kUUID = new (ELeave) TJp2kUuidBox; |
|
2678 CleanupDeletePushL( jp2kUUID ); |
|
2679 |
|
2680 ptr = info.iUUIDList[index]->Ptr(); |
|
2681 jp2kUUID->iUuidId.Copy( ptr, KJ2KUuidIDSize ); |
|
2682 |
|
2683 // Advance the pointer |
|
2684 ptr += KJ2KUuidIDSize; |
|
2685 |
|
2686 length = info.iUUIDList[index]->Length() - KJ2KUuidIDSize; |
|
2687 jp2kUUID->iUuidData = HBufC8::NewLC( length ); |
|
2688 jp2kUUID->iUuidData->Des().Append( ptr, length ); |
|
2689 |
|
2690 // Transfer the ownership of the buffer to the framework |
|
2691 User::LeaveIfError( iFrameData->AppendImageBuffer( jp2kUUID->iUuidData ) ); |
|
2692 CleanupStack::Pop( 1 ); // jp2kUUID->iUuidData |
|
2693 |
|
2694 User::LeaveIfError( iFrameData->AppendImageData( jp2kUUID ) ); |
|
2695 CleanupStack::Pop( 1 ); // jp2kUUID |
|
2696 } |
|
2697 info.iUUIDList.ResetAndDestroy(); |
|
2698 |
|
2699 // Convert each UUIDInfo box to TJp2kUuidInfoBox image data |
|
2700 for ( index = 0; index < info.iUUIDInfoListList.Count(); ++index ) |
|
2701 { |
|
2702 TJp2kUuidInfoBox* jp2kUUIDInfo = new (ELeave) TJp2kUuidInfoBox; |
|
2703 CleanupDeletePushL( jp2kUUIDInfo ); |
|
2704 |
|
2705 if ( info.iUUIDInfoListList[index]->Length() ) |
|
2706 { |
|
2707 ptr = info.iUUIDInfoListList[index]->Ptr(); |
|
2708 jp2kUUIDInfo->iUuidInfoNu = PtrReadUtil::ReadBigEndianUint16Inc( ptr ); |
|
2709 |
|
2710 length = jp2kUUIDInfo->iUuidInfoNu * KJ2KUuidIDSize; |
|
2711 jp2kUUIDInfo->iUuidInfoId = HBufC8::NewLC( length ); |
|
2712 jp2kUUIDInfo->iUuidInfoId->Des().Append( ptr, length ); |
|
2713 } |
|
2714 |
|
2715 if ( info.iUUIDInfoUrlList[index]->Length() ) |
|
2716 { |
|
2717 ptr = info.iUUIDInfoUrlList[index]->Ptr(); |
|
2718 |
|
2719 // 1 byte unsigned integer |
|
2720 jp2kUUIDInfo->iUuidInfoVersion = *ptr++; |
|
2721 |
|
2722 // 3 bytes unsigned integer (in little endian) |
|
2723 jp2kUUIDInfo->iUuidInfoFlag = *ptr++; |
|
2724 jp2kUUIDInfo->iUuidInfoFlag |= ( *ptr++ << 8 ); |
|
2725 jp2kUUIDInfo->iUuidInfoFlag |= ( *ptr++ << 16 ); |
|
2726 |
|
2727 length = info.iUUIDInfoUrlList[index]->Length() - 4; |
|
2728 jp2kUUIDInfo->iUuidInfoData = HBufC8::NewLC( length ); |
|
2729 jp2kUUIDInfo->iUuidInfoData->Des().Append( ptr, length ); |
|
2730 } |
|
2731 |
|
2732 // Transfer the ownership of the buffer to the framework |
|
2733 if ( jp2kUUIDInfo->iUuidInfoData ) |
|
2734 { |
|
2735 User::LeaveIfError( iFrameData->AppendImageBuffer( jp2kUUIDInfo->iUuidInfoData ) ); |
|
2736 CleanupStack::Pop( 1 ); // jp2kUUIDInfo->iUUidInfoData |
|
2737 } |
|
2738 |
|
2739 // Transfer the ownership of the buffer to the framework |
|
2740 if ( jp2kUUIDInfo->iUuidInfoId ) |
|
2741 { |
|
2742 User::LeaveIfError( iFrameData->AppendImageBuffer( jp2kUUIDInfo->iUuidInfoId ) ); |
|
2743 CleanupStack::Pop( 1 ); // jp2kUUIDInfo->iUuidInfoId |
|
2744 } |
|
2745 |
|
2746 User::LeaveIfError( iFrameData->AppendImageData( jp2kUUIDInfo ) ); |
|
2747 CleanupStack::Pop( 1 ); // jp2kUUIDInfo |
|
2748 } |
|
2749 info.iUUIDInfoListList.ResetAndDestroy(); |
|
2750 info.iUUIDInfoUrlList.ResetAndDestroy(); |
|
2751 } |