|
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: JPEG2000 image encoder/decoder plugin class. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include "JP2KImageUtils.h" |
|
21 #include "JP2KFormat.h" |
|
22 #include "JP2KConvert.h" |
|
23 #include "JP2KStreamReader.h" |
|
24 #include "JP2KImageClientMain.h" |
|
25 #include "JP2KCodec.h" |
|
26 #include <barsc.h> |
|
27 #include <imageconversion.h> |
|
28 #include <barsread.h> |
|
29 #include <bautils.h> |
|
30 #include <e32math.h> |
|
31 #include <101F862D_extra.rsg> |
|
32 #include <icl/icl_uids.hrh> |
|
33 #include "JP2KUids.hrh" |
|
34 #include <JP2KImageData.h> |
|
35 |
|
36 // EXTERNAL DATA STRUCTURES |
|
37 |
|
38 // EXTERNAL FUNCTION PROTOTYPES |
|
39 |
|
40 // CONSTANTS |
|
41 |
|
42 // MACROS |
|
43 |
|
44 // LOCAL CONSTANTS AND MACROS |
|
45 _LIT( KJ2KPanicCategory, "J2KConvertPlugin" ); |
|
46 |
|
47 // MODULE DATA STRUCTURES |
|
48 |
|
49 // LOCAL FUNCTION PROTOTYPES |
|
50 |
|
51 // FORWARD DECLARATIONS |
|
52 |
|
53 // ============================ MEMBER FUNCTIONS =============================== |
|
54 |
|
55 // ----------------------------------------------------------------------------- |
|
56 // CJp2kDecoder::NewL |
|
57 // Two-phased constructor. |
|
58 // ----------------------------------------------------------------------------- |
|
59 // |
|
60 CJp2kDecoder* CJp2kDecoder::NewL() |
|
61 { |
|
62 return new ( ELeave ) CJp2kDecoder; |
|
63 } |
|
64 |
|
65 // Destructor |
|
66 CJp2kDecoder::~CJp2kDecoder() |
|
67 { |
|
68 // Call base class Cleanup(), else there is a possibility |
|
69 // of memory leak |
|
70 CImageDecoderPlugin::Cleanup(); |
|
71 } |
|
72 |
|
73 // ----------------------------------------------------------------------------- |
|
74 // CJp2kDecoder::ImageType |
|
75 // Get the image type uid of this plugin. |
|
76 // (other items were commented in a header). |
|
77 // ----------------------------------------------------------------------------- |
|
78 // |
|
79 void CJp2kDecoder::ImageType( TInt aFrameNumber, TUid& aImageType, TUid& aImageSubType ) const |
|
80 { |
|
81 __ASSERT_ALWAYS( aFrameNumber == 0, Panic( EFrameNumberOutOfRange ) ); |
|
82 |
|
83 TUid uid = {KImageTypeJ2KUid}; |
|
84 aImageType = uid; |
|
85 aImageSubType = KNullUid; |
|
86 } |
|
87 |
|
88 // ----------------------------------------------------------------------------- |
|
89 // CJp2kDecoder::NumberOfImageComments |
|
90 // Get the number of image comment. |
|
91 // ----------------------------------------------------------------------------- |
|
92 // |
|
93 TInt CJp2kDecoder::NumberOfImageComments() const |
|
94 { |
|
95 __ASSERT_ALWAYS( IsImageHeaderProcessingComplete(), Panic( EHeaderProcessingNotComplete ) ); |
|
96 |
|
97 const TUid commentUid = { KJ2KCommentUid }; |
|
98 const CFrameImageData& frameImageData = FrameData( 0 ); |
|
99 const TInt imageDataCount = frameImageData.ImageDataCount(); |
|
100 const TImageDataBlock *imageData = 0; |
|
101 TInt imageCommentCount = 0; |
|
102 for ( TInt index = 0; index < imageDataCount; ++index ) |
|
103 { |
|
104 imageData = frameImageData.GetImageData( index ); |
|
105 if ( imageData->DataType() == commentUid ) |
|
106 { |
|
107 imageCommentCount++; |
|
108 } |
|
109 } |
|
110 return imageCommentCount; |
|
111 } |
|
112 |
|
113 // ----------------------------------------------------------------------------- |
|
114 // CJp2kDecoder::ImageCommentL |
|
115 // Get the image comment. |
|
116 // (other items were commented in a header). |
|
117 // ----------------------------------------------------------------------------- |
|
118 // |
|
119 HBufC* CJp2kDecoder::ImageCommentL( TInt aCommentNumber ) const |
|
120 { |
|
121 __ASSERT_ALWAYS( IsImageHeaderProcessingComplete(), Panic( EHeaderProcessingNotComplete ) ); |
|
122 __ASSERT_ALWAYS( ( aCommentNumber >= 0 ) && ( aCommentNumber < NumberOfImageComments() ), |
|
123 Panic( ECommentNumberOutOfRange ) ); |
|
124 |
|
125 HBufC *comment = 0; |
|
126 |
|
127 if( FrameData( 0 ).ImageDataCount() > 0 ) |
|
128 { |
|
129 const TUid commentUid = { KJ2KCommentUid }; |
|
130 const CFrameImageData& frameImageData = FrameData( 0 ); |
|
131 const TInt imageDataCount = frameImageData.ImageDataCount(); |
|
132 const TImageDataBlock *imageData = 0; |
|
133 TInt commentCount = 0; |
|
134 for ( TInt index = 0; index < imageDataCount; ++index ) |
|
135 { |
|
136 imageData = frameImageData.GetImageData( index ); |
|
137 if ( imageData->DataType() == commentUid ) |
|
138 { |
|
139 if ( commentCount == aCommentNumber ) |
|
140 { |
|
141 index = imageDataCount; // Break from the for loop |
|
142 } |
|
143 else |
|
144 { |
|
145 commentCount++; |
|
146 } |
|
147 } |
|
148 } |
|
149 |
|
150 if( imageData != 0 ) |
|
151 { |
|
152 const TJp2kComment *jp2kComment = STATIC_CAST( const TJp2kComment*, imageData ); |
|
153 comment = HBufC::NewL( jp2kComment->iComment->Length() ); |
|
154 |
|
155 // Create 16 bit copy of the 8 bit original |
|
156 comment->Des().Copy( *( jp2kComment->iComment ) ); |
|
157 } |
|
158 } |
|
159 return comment; |
|
160 } |
|
161 |
|
162 // ----------------------------------------------------------------------------- |
|
163 // CJp2kDecoder::NumberOfFrameComments |
|
164 // Get the number of frame comment. |
|
165 // (other items were commented in a header). |
|
166 // ----------------------------------------------------------------------------- |
|
167 // |
|
168 TInt CJp2kDecoder::NumberOfFrameComments( TInt aFrameNumber ) const |
|
169 { |
|
170 __ASSERT_ALWAYS( IsImageHeaderProcessingComplete(), Panic( EHeaderProcessingNotComplete ) ); |
|
171 __ASSERT_ALWAYS( aFrameNumber == 0, Panic( EFrameNumberOutOfRange ) ); |
|
172 |
|
173 return NumberOfImageComments(); |
|
174 } |
|
175 |
|
176 // ----------------------------------------------------------------------------- |
|
177 // CJp2kDecoder::FrameCommentL |
|
178 // Get the frame comment. |
|
179 // (other items were commented in a header). |
|
180 // ----------------------------------------------------------------------------- |
|
181 // |
|
182 HBufC* CJp2kDecoder::FrameCommentL( TInt aFrameNumber, TInt aCommentNumber ) const |
|
183 { |
|
184 __ASSERT_ALWAYS( IsImageHeaderProcessingComplete(), Panic( EHeaderProcessingNotComplete ) ); |
|
185 __ASSERT_ALWAYS( aFrameNumber == 0, Panic( EFrameNumberOutOfRange ) ); |
|
186 |
|
187 return ImageCommentL( aCommentNumber ); |
|
188 } |
|
189 |
|
190 // ----------------------------------------------------------------------------- |
|
191 // CJp2kDecoder::FrameInfoStringsL |
|
192 // Retrieve frame information and format it according to info stored in .rss file. |
|
193 // (other items were commented in a header). |
|
194 // ----------------------------------------------------------------------------- |
|
195 // |
|
196 CFrameInfoStrings* CJp2kDecoder::FrameInfoStringsL( RFs& aFs, TInt aFrameNumber ) |
|
197 { |
|
198 const TUid KJp2kCodecDllUid = { KJ2KCodecDllUidValue }; |
|
199 |
|
200 RResourceFile resourceFile; |
|
201 OpenExtraResourceFileLC( aFs, KJp2kCodecDllUid, resourceFile ); |
|
202 |
|
203 HBufC8* resourceInfo = resourceFile.AllocReadLC( THEDECODERINFO ); |
|
204 TResourceReader resourceReader; |
|
205 resourceReader.SetBuffer( resourceInfo ); |
|
206 |
|
207 TBuf<KCodecResourceStringMax> info; |
|
208 TBuf<KCodecResourceStringMax> templte; |
|
209 |
|
210 const TFrameInfo& frameInfo = FrameInfo( aFrameNumber ); |
|
211 CFrameInfoStrings* frameInfoStrings = CFrameInfoStrings::NewLC(); |
|
212 |
|
213 info = resourceReader.ReadTPtrC(); |
|
214 frameInfoStrings->SetDecoderL( info ); |
|
215 |
|
216 info = resourceReader.ReadTPtrC(); |
|
217 frameInfoStrings->SetFormatL( info ); |
|
218 |
|
219 TInt width = frameInfo.iOverallSizeInPixels.iWidth; |
|
220 TInt height = frameInfo.iOverallSizeInPixels.iHeight; |
|
221 TInt depth = frameInfo.iBitsPerPixel; |
|
222 |
|
223 templte = resourceReader.ReadTPtrC(); |
|
224 info.Format( templte, width, height ); |
|
225 frameInfoStrings->SetDimensionsL( info ); |
|
226 |
|
227 CDesCArrayFlat* resourceArray = resourceReader.ReadDesCArrayL(); |
|
228 CleanupStack::PushL( resourceArray ); |
|
229 TUint formatIndex = ( frameInfo.iFlags & TFrameInfo::EColor ) ? 1 : 0; |
|
230 templte = ( *resourceArray )[formatIndex]; |
|
231 CleanupStack::PopAndDestroy( resourceArray ); |
|
232 info.Format( templte, depth ); |
|
233 frameInfoStrings->SetDepthL( info ); |
|
234 |
|
235 resourceArray = resourceReader.ReadDesCArrayL(); |
|
236 CleanupStack::PushL( resourceArray ); |
|
237 formatIndex = 0; |
|
238 info = ( *resourceArray )[formatIndex]; |
|
239 CleanupStack::PopAndDestroy( resourceArray ); |
|
240 frameInfoStrings->SetDetailsL( info ); |
|
241 |
|
242 CleanupStack::Pop( frameInfoStrings ); |
|
243 CleanupStack::PopAndDestroy( 2 ); // resourceInfo + resourceFile |
|
244 return frameInfoStrings; |
|
245 } |
|
246 |
|
247 // ----------------------------------------------------------------------------- |
|
248 // CJp2kDecoder::FrameHeaderBlockSize |
|
249 // Returns the frame header block size. |
|
250 // (other items were commented in a header). |
|
251 // ----------------------------------------------------------------------------- |
|
252 // |
|
253 TInt CJp2kDecoder::FrameHeaderBlockSize( TInt aFrameNumber ) const |
|
254 { |
|
255 __ASSERT_ALWAYS( aFrameNumber == 0, Panic( EFrameNumberOutOfRange ) ); |
|
256 |
|
257 return KJ2kInputBufferSize; |
|
258 } |
|
259 |
|
260 // ----------------------------------------------------------------------------- |
|
261 // CJp2kDecoder::FrameBlockSize |
|
262 // Returns the frame block size. |
|
263 // (other items were commented in a header). |
|
264 // ----------------------------------------------------------------------------- |
|
265 // |
|
266 TInt CJp2kDecoder::FrameBlockSize(TInt aFrameNumber) const |
|
267 { |
|
268 __ASSERT_ALWAYS( aFrameNumber == 0, Panic( EFrameNumberOutOfRange ) ); |
|
269 |
|
270 return KJ2kInputBufferSize; |
|
271 } |
|
272 |
|
273 // ----------------------------------------------------------------------------- |
|
274 // CJp2kDecoder::DoConvert |
|
275 // Override the default DoConvert to split out the parsing and decoding |
|
276 // process into multiple steps. |
|
277 // (other items were commented in a header). |
|
278 // ----------------------------------------------------------------------------- |
|
279 // |
|
280 void CJp2kDecoder::DoConvert() |
|
281 { |
|
282 TFrameState codecState = EFrameIncomplete; |
|
283 TInt errCode = KErrNone; |
|
284 |
|
285 CJp2kReadCodec *j2kCodec = static_cast<CJp2kReadCodec*>( ImageReadCodec() ); |
|
286 |
|
287 if ( !j2kCodec->IsDecodeTile() ) |
|
288 { |
|
289 // parsing of a tile-part |
|
290 TRAP( errCode, PrepareForProcessFrameL() ); |
|
291 if ( errCode != KErrNone ) |
|
292 { |
|
293 RequestComplete( errCode ); |
|
294 return; |
|
295 } |
|
296 |
|
297 TBufPtr8& sourceData = SourceData(); |
|
298 TInt sourceLength = sourceData.Length(); |
|
299 if ( sourceLength != 0 ) |
|
300 { |
|
301 TRAP( errCode, codecState = j2kCodec->ProcessFrameL( sourceData ) ); |
|
302 |
|
303 if ( j2kCodec->IsDecodeTile() ) |
|
304 { |
|
305 // tile-part contains all compressed data |
|
306 // and proceed to the decoding |
|
307 SelfComplete( KErrNone ); |
|
308 return; |
|
309 } |
|
310 } |
|
311 // continue on parsing the tile-part |
|
312 HandleProcessFrameResult( errCode, codecState ); |
|
313 } |
|
314 else |
|
315 { |
|
316 // decoding of the tile-part |
|
317 TRAP( errCode, codecState = j2kCodec->DecodeTileL() ); |
|
318 |
|
319 if ( errCode == KErrNone ) |
|
320 { |
|
321 if ( j2kCodec->IsDecodeTile() ) |
|
322 { |
|
323 // continue on decoding the tile-part |
|
324 // if we split the decoding into multiple steps |
|
325 SelfComplete( KErrNone ); |
|
326 return; |
|
327 } |
|
328 } |
|
329 // either continue on parsing the next tile-part |
|
330 // or done with the whole image |
|
331 HandleProcessFrameResult( errCode, codecState ); |
|
332 } |
|
333 } |
|
334 |
|
335 // ----------------------------------------------------------------------------- |
|
336 // CJp2kDecoder::CJp2kDecoder |
|
337 // C++ default constructor can NOT contain any code, that |
|
338 // might leave. |
|
339 // ----------------------------------------------------------------------------- |
|
340 // |
|
341 CJp2kDecoder::CJp2kDecoder() |
|
342 { |
|
343 } |
|
344 |
|
345 // ----------------------------------------------------------------------------- |
|
346 // CJp2kDecoder::ReadFormatL |
|
347 // JP2 File Format detection state machine. |
|
348 // (other items were commented in a header). |
|
349 // ----------------------------------------------------------------------------- |
|
350 // |
|
351 void CJp2kDecoder::ReadFormatL() |
|
352 { |
|
353 // Verify the JP2 file format if it exist |
|
354 iCallFromFramework = ETrue; |
|
355 |
|
356 while ( iState != EStateInCodestreamBox ) |
|
357 { |
|
358 switch ( iState ) |
|
359 { |
|
360 case EStateInSignatureBox: |
|
361 { |
|
362 ReadSignatureBoxL(); |
|
363 break; |
|
364 } |
|
365 case EStateInFileTypeBox: |
|
366 { |
|
367 ReadFileTypeBoxL(); |
|
368 break; |
|
369 } |
|
370 case EStateInJP2SuperBox: |
|
371 { |
|
372 ReadJp2HeaderBoxL(); |
|
373 break; |
|
374 } |
|
375 case EStateInIPRBox: |
|
376 { |
|
377 ReadIPRBoxL(); |
|
378 break; |
|
379 } |
|
380 case EStateInXMLBox: |
|
381 { |
|
382 ReadXMLBoxL(); |
|
383 break; |
|
384 } |
|
385 case EStateInUUIDBox: |
|
386 { |
|
387 ReadUUIDBoxL(); |
|
388 break; |
|
389 } |
|
390 case EStateInUUIDInfoBox: |
|
391 { |
|
392 ReadUUIDInfoBoxL(); |
|
393 break; |
|
394 } |
|
395 case EStateInUnknown: |
|
396 { |
|
397 if ( iCallFromFramework ) |
|
398 { |
|
399 // Always read the length and type of the box |
|
400 ReadDataL( iLastRead, iBufferDes, KJ2kBoxTypeLength ); |
|
401 |
|
402 if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength ) |
|
403 { |
|
404 if ( ( iJ2kInfo.iCSOffset != 0 ) && |
|
405 ( (TUint32)iBufferDes.Length() == 0 ) ) |
|
406 { |
|
407 // We have reach the end of file/stream and |
|
408 // CodeStream box has been recognized |
|
409 iState = EStateInCodestreamBox; |
|
410 } |
|
411 else |
|
412 { |
|
413 // Need more data from the ICL framework |
|
414 User::Leave( KErrUnderflow ); |
|
415 } |
|
416 } |
|
417 iPtr = iBufferDes.Ptr(); |
|
418 } |
|
419 |
|
420 if ( iState != EStateInCodestreamBox ) |
|
421 { |
|
422 // Length and Type of next box |
|
423 iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
424 iBoxType = PtrReadUtil::ReadBigEndianUint32( iPtr ); |
|
425 |
|
426 // Update the internal state based on the iBoxType |
|
427 UpdateStateFromBoxTypeL(); |
|
428 |
|
429 if ( iState != EStateInCodestreamBox ) |
|
430 { |
|
431 // Corrupted box length |
|
432 if ( ( (TInt32)iBoxLength ) < 0 ) |
|
433 { |
|
434 User::Leave( KErrCorrupt ); |
|
435 } |
|
436 } |
|
437 } |
|
438 break; |
|
439 } |
|
440 default: |
|
441 { |
|
442 break; |
|
443 } |
|
444 } |
|
445 iCallFromFramework = EFalse; |
|
446 } |
|
447 |
|
448 // When the code reach here, it means that we have found the |
|
449 // codestream box in JP2 file format or the codestream SOC itself |
|
450 // in case of the JP2 file format, all the boxes after the |
|
451 // codestream box will not be read and parsed. |
|
452 |
|
453 // In JP2 file format, iLastRead points to codestream box |
|
454 // in JP2 codestream, iLastRead points to SOC marker |
|
455 // it is the offset that ICL framework used to read |
|
456 // in more data from the image file. |
|
457 SetStartPosition( iJ2kInfo.iCSOffset ); |
|
458 |
|
459 // Always set the image data length to KMaxTInt32 |
|
460 SetDataLength( KMaxTInt ); |
|
461 |
|
462 // Fill up the image related information, if it is |
|
463 // in JP2 file format, else defer the setting of the |
|
464 // image info til SIZ marker in the codestream has |
|
465 // been processed. |
|
466 if ( iJ2kInfo.iOption & TJ2kInfo::EJP2file ) |
|
467 { |
|
468 TFrameInfo& imageInfo = CONST_CAST( TFrameInfo&, ImageInfo() ); |
|
469 imageInfo.iOverallSizeInPixels = iJ2kInfo.iImageSize; |
|
470 imageInfo.iFrameCoordsInPixels.SetRect( TPoint( 0, 0 ), iJ2kInfo.iImageSize ); |
|
471 imageInfo.iFrameSizeInTwips = iJ2kInfo.iImageSizeInTwips; |
|
472 |
|
473 if ( iJ2kInfo.iBPCList.Count() > 0 ) |
|
474 { |
|
475 // Calculate based on the bitdepth per component |
|
476 for ( TUint16 index = 0; index < iJ2kInfo.iNC; ++index ) |
|
477 { |
|
478 imageInfo.iBitsPerPixel += ( ( 0x7f & iJ2kInfo.iBPCList[index] ) + 1 ); |
|
479 } |
|
480 } |
|
481 else |
|
482 { |
|
483 if ( iJ2kInfo.iBPC == KJ2kIsBPCBoxExist ) |
|
484 { |
|
485 User::Leave( KErrCorrupt ); |
|
486 } |
|
487 |
|
488 // Has the same bitdepth on each component |
|
489 imageInfo.iBitsPerPixel = ( ( 0x7f & iJ2kInfo.iBPC ) + 1 ) * iJ2kInfo.iNC; |
|
490 } |
|
491 imageInfo.iFlags |= TFrameInfo::ECanDither; |
|
492 |
|
493 // Decoder is able to handle scaleable resolution |
|
494 imageInfo.iFlags |= TFrameInfo::EConstantAspectRatio; |
|
495 |
|
496 if ( iJ2kInfo.iEnumCS != KJ2kColourSpecGrayScale ) |
|
497 { |
|
498 imageInfo.iFlags |= TFrameInfo::EColor; |
|
499 } |
|
500 |
|
501 // No animation. |
|
502 imageInfo.iDelay = 0; |
|
503 |
|
504 switch ( imageInfo.iBitsPerPixel ) |
|
505 { |
|
506 case 1: |
|
507 { |
|
508 imageInfo.iFrameDisplayMode = EGray2; |
|
509 break; |
|
510 } |
|
511 case 2: |
|
512 { |
|
513 imageInfo.iFrameDisplayMode = EGray4; |
|
514 break; |
|
515 } |
|
516 case 4: |
|
517 { |
|
518 imageInfo.iFrameDisplayMode = ( imageInfo.iFlags & TFrameInfo::EColor ) ? EColor16 : EGray16; |
|
519 break; |
|
520 } |
|
521 case 8: |
|
522 { |
|
523 imageInfo.iFrameDisplayMode = ( imageInfo.iFlags & TFrameInfo::EColor ) ? EColor16M : EGray256; |
|
524 break; |
|
525 } |
|
526 case 12: |
|
527 { |
|
528 imageInfo.iFrameDisplayMode = ( imageInfo.iFlags & TFrameInfo::EColor ) ? EColor4K : EGray256; |
|
529 break; |
|
530 } |
|
531 case 16: |
|
532 { |
|
533 imageInfo.iFrameDisplayMode = EColor64K; |
|
534 break; |
|
535 } |
|
536 case 24: |
|
537 { |
|
538 imageInfo.iFrameDisplayMode = EColor16M; |
|
539 break; |
|
540 } |
|
541 default: |
|
542 { |
|
543 imageInfo.iFrameDisplayMode = EColor64K; |
|
544 break; |
|
545 } |
|
546 } |
|
547 } |
|
548 } |
|
549 |
|
550 // ----------------------------------------------------------------------------- |
|
551 // CJp2kDecoder::ReadSignatureBoxL |
|
552 // Verify and process the Signature box. |
|
553 // (other items were commented in a header). |
|
554 // ----------------------------------------------------------------------------- |
|
555 // |
|
556 void CJp2kDecoder::ReadSignatureBoxL( ) |
|
557 { |
|
558 // Validate the Signature Box |
|
559 __ASSERT_ALWAYS( iLastRead == 0, Panic( EInvalidState ) ); |
|
560 |
|
561 // Read the Signature box + the next box's Length and Type |
|
562 ReadDataL( iLastRead, iBufferDes, KJ2kFileInformationSize ); |
|
563 |
|
564 if ( (TUint32)iBufferDes.Length() < KJ2kSigBoxLength ) |
|
565 { |
|
566 // Need more data from the ICL framework |
|
567 User::Leave( KErrUnderflow ); |
|
568 } |
|
569 |
|
570 iPtr = iBufferDes.Ptr(); |
|
571 |
|
572 if ( ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kSigBoxLength ) || |
|
573 ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kSigBoxType ) || |
|
574 ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kSigBoxContent ) ) |
|
575 { |
|
576 // Unrecognized signature box |
|
577 User::Leave( KErrCorrupt ); |
|
578 } |
|
579 |
|
580 // File Type box shall immediately follow the Signature box |
|
581 iLastRead = KJ2kSigBoxLength; |
|
582 iState = EStateInFileTypeBox; |
|
583 |
|
584 // JP2 file format |
|
585 iJ2kInfo.iOption |= TJ2kInfo::EJP2file; |
|
586 |
|
587 if ( iBufferDes.Length() < KJ2kFileInformationSize ) |
|
588 { |
|
589 // Need more data from the ICL framework |
|
590 User::Leave( KErrUnderflow ); |
|
591 } |
|
592 } |
|
593 |
|
594 // ----------------------------------------------------------------------------- |
|
595 // CJp2kDecoder::ReadFileTypeBoxL |
|
596 // Verify and process the File Type box. |
|
597 // (other items were commented in a header). |
|
598 // ----------------------------------------------------------------------------- |
|
599 // |
|
600 void CJp2kDecoder::ReadFileTypeBoxL() |
|
601 { |
|
602 // Validate the File Type Box's Length and Type |
|
603 if ( iCallFromFramework ) |
|
604 { |
|
605 __ASSERT_ALWAYS( iLastRead == KJ2kSigBoxLength, Panic( EInvalidState ) ); |
|
606 |
|
607 ReadDataL( iLastRead, iBufferDes, KJ2kBoxTypeLength ); |
|
608 |
|
609 if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength ) |
|
610 { |
|
611 // Need more data from the ICL framework |
|
612 User::Leave( KErrUnderflow ); |
|
613 } |
|
614 |
|
615 iPtr = iBufferDes.Ptr(); |
|
616 } |
|
617 |
|
618 iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
619 iBoxType = PtrReadUtil::ReadBigEndianUint32( iPtr ); |
|
620 |
|
621 if ( ( (TInt32)iBoxLength ) <= 0 || iBoxType != KJ2kFileTypeBox || iBoxLength > KJ2kFileTypeBoxMaxLength ) |
|
622 { |
|
623 // Unrecognized file type box or corrupted box length |
|
624 User::Leave( KErrCorrupt ); |
|
625 } |
|
626 |
|
627 TUint8 xlBoxExist = 0; |
|
628 if ( iBoxLength == 1 ) |
|
629 { |
|
630 // The XLBox shall exist and contains the actual length of the box |
|
631 // XLBox is 8 bytes width |
|
632 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength ); |
|
633 |
|
634 if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength ) |
|
635 { |
|
636 // Need more data from the ICL framework |
|
637 User::Leave( KErrUnderflow ); |
|
638 } |
|
639 |
|
640 iPtr = iBufferDes.Ptr(); |
|
641 iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
642 iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr ); |
|
643 xlBoxExist = 1; |
|
644 } |
|
645 |
|
646 if ( ( (TInt32)iBoxLength ) <= 0 || ( ( (TInt32)iBoxLength - 16 ) / 4 ) <= 0 ) |
|
647 { |
|
648 // Must include at least one CL field in the Compatibility list |
|
649 User::Leave( KErrCorrupt ); |
|
650 } |
|
651 |
|
652 // Read the File Type box + the next box's Length and Type |
|
653 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength ); |
|
654 |
|
655 if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength ) |
|
656 { |
|
657 // Need more data from the ICL framework |
|
658 User::Leave( KErrUnderflow ); |
|
659 } |
|
660 |
|
661 iPtr = iBufferDes.Ptr(); |
|
662 |
|
663 // Substract next box's KJ2kBoxTypeLength |
|
664 const TUint8 *ptrLimit = iPtr + iBoxLength - KJ2kBoxTypeLength; |
|
665 |
|
666 // Advance the pointer by 8 bytes if XLBox exists |
|
667 iPtr += ( xlBoxExist * KJ2kBoxTypeLength ); |
|
668 |
|
669 // Check Brand ( BR ) or Major Version |
|
670 if ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kFileTypeBrand ) |
|
671 { |
|
672 // It is ok at this point if Major Version does not match |
|
673 iPtr += 0; |
|
674 } |
|
675 |
|
676 // Check Minor Version ( MinV ) |
|
677 if ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kFileTypeMinV ) |
|
678 { |
|
679 // It is ok at this point if Minor Version does not match |
|
680 iPtr += 0; |
|
681 } |
|
682 |
|
683 // Check Compatibility List ( CL ) |
|
684 TBool clFound = EFalse; |
|
685 TUint32 clField = 0; |
|
686 while ( ( iPtr + 4 ) <= ptrLimit ) |
|
687 { |
|
688 clField = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
689 if ( clField == KJ2kFileTypeBrand ) |
|
690 { |
|
691 clFound = ETrue; |
|
692 } |
|
693 else if ( clField == KJ2kFileTypeProfile0 ) |
|
694 { |
|
695 iJ2kInfo.iOption |= TJ2kInfo::EProfile0; |
|
696 } |
|
697 else if ( clField == KJ2kFileTypeProfile1 ) |
|
698 { |
|
699 iJ2kInfo.iOption |= TJ2kInfo::EProfile1; |
|
700 } |
|
701 else |
|
702 { |
|
703 // other file types require no action |
|
704 } |
|
705 } |
|
706 |
|
707 if ( !clFound || iPtr != ptrLimit ) |
|
708 { |
|
709 // Unrecognized compatibility list or data misaligned |
|
710 User::Leave( KErrCorrupt ); |
|
711 } |
|
712 |
|
713 iLastRead += iBoxLength; |
|
714 iState = EStateInUnknown; |
|
715 |
|
716 if ( (TUint32)iBufferDes.Length() < iBoxLength ) |
|
717 { |
|
718 // Need more data from the ICL framework |
|
719 User::Leave( KErrUnderflow ); |
|
720 } |
|
721 } |
|
722 |
|
723 // ----------------------------------------------------------------------------- |
|
724 // CJp2kDecoder::ReadJp2HeaderBoxL |
|
725 // Verify and process the JP2 Header box ( superbox ). |
|
726 // (other items were commented in a header). |
|
727 // ----------------------------------------------------------------------------- |
|
728 // |
|
729 void CJp2kDecoder::ReadJp2HeaderBoxL() |
|
730 { |
|
731 // Since we are getting data from ICL framework |
|
732 // we have no control of when will be the EOF |
|
733 if ( iBoxLength == 0 ) |
|
734 { |
|
735 User::Leave( KErrCorrupt ); |
|
736 } |
|
737 |
|
738 TUint8 xlBoxExist = 0; |
|
739 if ( iBoxLength == 1 ) |
|
740 { |
|
741 // The XLBox shall exist and contains the actual length of the box |
|
742 // XLBox is 8 bytes width |
|
743 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength ); |
|
744 |
|
745 if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength ) |
|
746 { |
|
747 // Need more data from the ICL framework |
|
748 User::Leave( KErrUnderflow ); |
|
749 } |
|
750 |
|
751 iPtr = iBufferDes.Ptr(); |
|
752 iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
753 iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr ); |
|
754 xlBoxExist = 1; |
|
755 } |
|
756 |
|
757 // Corrupted box length |
|
758 if ( ( (TInt32)iBoxLength ) <= 0 ) |
|
759 { |
|
760 User::Leave( KErrCorrupt ); |
|
761 } |
|
762 |
|
763 // Validate the JP2 Header Super Box |
|
764 // Read the JP2 box + the next box's Length and Type |
|
765 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength ); |
|
766 |
|
767 if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength ) |
|
768 { |
|
769 // Need more data from the ICL framework |
|
770 User::Leave( KErrUnderflow ); |
|
771 } |
|
772 |
|
773 // Make sure that JP2 Header box contains enough data |
|
774 // for Image Header box |
|
775 if ( iBoxLength - KJ2kBoxTypeLength < KJ2kImageHeaderBoxLength ) |
|
776 { |
|
777 // Missing Image Header box |
|
778 User::Leave( KErrCorrupt ); |
|
779 } |
|
780 |
|
781 iPtr = iBufferDes.Ptr(); |
|
782 |
|
783 // Advance the pointer by 8 bytes if XLBox exists |
|
784 iPtr += ( xlBoxExist * KJ2kBoxTypeLength ); |
|
785 |
|
786 // Image Header box shall be the first box within JP2 Header box |
|
787 ReadImageHeaderBoxL(); |
|
788 |
|
789 TUint32 subBoxLength = 0; |
|
790 TUint32 subBoxType = 0; |
|
791 |
|
792 // Substract next box's Length and Type |
|
793 const TUint8 *ptrLimit = iPtr + iBoxLength - KJ2kBoxTypeLength - KJ2kImageHeaderBoxLength; |
|
794 TInt32 length = ptrLimit - iPtr; |
|
795 TBool csFound = EFalse; |
|
796 |
|
797 while ( length > 0 ) |
|
798 { |
|
799 if ( ( ptrLimit - iPtr ) < 8 ) |
|
800 { |
|
801 // Not enough room for box data |
|
802 User::Leave( KErrCorrupt ); |
|
803 } |
|
804 |
|
805 subBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
806 subBoxType = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
807 |
|
808 if ( subBoxLength == 1 ) |
|
809 { |
|
810 // The XLBox shall exist and contains the actual length of the box |
|
811 // XLBox is 8 bytes width |
|
812 subBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
813 subBoxLength += PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
814 length -= KJ2kBoxTypeLength; |
|
815 subBoxLength -= KJ2kBoxTypeLength; |
|
816 } |
|
817 |
|
818 if ( ( (TInt32)subBoxLength ) < 0 || ( subBoxLength <= 8 ) || ( ( iPtr + subBoxLength - KJ2kBoxTypeLength ) > ptrLimit ) ) |
|
819 { |
|
820 // Not enough room for subbox data or corrupted subbox length |
|
821 User::Leave( KErrCorrupt ); |
|
822 } |
|
823 |
|
824 switch ( subBoxType ) |
|
825 { |
|
826 case KJ2kColourSpecBoxType: |
|
827 { |
|
828 if ( !csFound ) |
|
829 { |
|
830 // Colour Spec Box |
|
831 ReadColorSpecBoxL( subBoxLength ); |
|
832 csFound = ETrue; |
|
833 } |
|
834 else |
|
835 { |
|
836 // Ignore the second Colour Spec Box, |
|
837 // just advance the iterator pointer |
|
838 iPtr += subBoxLength - KJ2kBoxTypeLength; |
|
839 } |
|
840 break; |
|
841 } |
|
842 case KJ2kResolutionBoxType: |
|
843 { |
|
844 // Resolution box ( superbox ) |
|
845 ReadResolutionBoxL( ptrLimit, subBoxLength ); |
|
846 break; |
|
847 } |
|
848 case KJ2kBitsPerCompBoxType: |
|
849 { |
|
850 // Bits Per Component Box |
|
851 ReadBitsPerCompBoxL( subBoxLength ); |
|
852 break; |
|
853 } |
|
854 case KJ2kPaletterBoxType: |
|
855 { |
|
856 // Palette Box |
|
857 ReadPaletteBoxL(); |
|
858 break; |
|
859 } |
|
860 case KJ2kComponentMapBoxType: |
|
861 { |
|
862 // Component Mapping Box |
|
863 ReadComponentMapBoxL( subBoxLength ); |
|
864 break; |
|
865 } |
|
866 case KJ2kChannelDefBoxType: |
|
867 { |
|
868 // Channel Definition Box |
|
869 ReadChannelDefBoxL( subBoxLength ); |
|
870 break; |
|
871 } |
|
872 default: |
|
873 { |
|
874 // Unrecognized Box |
|
875 User::Leave( KErrCorrupt ); |
|
876 break; |
|
877 } |
|
878 } |
|
879 length -= subBoxLength; |
|
880 } |
|
881 |
|
882 iLastRead += iBoxLength; |
|
883 iState = EStateInUnknown; |
|
884 |
|
885 // JP2 Header processed |
|
886 iJ2kInfo.iOption |= TJ2kInfo::EJP2Header; |
|
887 |
|
888 if ( (TUint32)iBufferDes.Length() < iBoxLength ) |
|
889 { |
|
890 // Need more data from the ICL framework |
|
891 User::Leave( KErrUnderflow ); |
|
892 } |
|
893 } |
|
894 |
|
895 // ----------------------------------------------------------------------------- |
|
896 // CJp2kDecoder::ReadImageHeaderBoxL |
|
897 // Verify and process the Image Header box ( in JP2 Header box ). |
|
898 // (other items were commented in a header). |
|
899 // ----------------------------------------------------------------------------- |
|
900 // |
|
901 void CJp2kDecoder::ReadImageHeaderBoxL() |
|
902 { |
|
903 // Validate the Image Header Box |
|
904 if ( ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kImageHeaderBoxLength ) || |
|
905 ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kImageHeaderBoxType ) ) |
|
906 { |
|
907 // Unrecognized Image Header box |
|
908 User::Leave( KErrCorrupt ); |
|
909 } |
|
910 |
|
911 iJ2kInfo.iImageSize.iHeight = (TInt)PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
912 iJ2kInfo.iImageSize.iWidth = (TInt)PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
913 iJ2kInfo.iNC = PtrReadUtil::ReadBigEndianUint16Inc( iPtr ); |
|
914 iJ2kInfo.iBPC = *iPtr++; |
|
915 |
|
916 if ( (iJ2kInfo.iImageSize.iHeight <= 0) || (iJ2kInfo.iImageSize.iWidth <= 0) || |
|
917 (iJ2kInfo.iNC == 0) || (iJ2kInfo.iBPC == 0) ) |
|
918 { |
|
919 // Corrupted image parameters |
|
920 User::Leave( KErrCorrupt ); |
|
921 } |
|
922 |
|
923 if ( *iPtr++ != KJ2kImageHeaderCompressionType ) |
|
924 { |
|
925 // Unrecognized compression type |
|
926 User::Leave( KErrCorrupt ); |
|
927 } |
|
928 |
|
929 // Check color space - UnkC |
|
930 TUint8 value = *iPtr++; |
|
931 if ( value == 0 || value == 1 ) |
|
932 { |
|
933 iJ2kInfo.iOption |= ( value == 0 ) ? TJ2kInfo::EColorSpec : 0; |
|
934 } |
|
935 else |
|
936 { |
|
937 // Unrecognized color space |
|
938 User::Leave( KErrCorrupt ); |
|
939 } |
|
940 |
|
941 // Check intellectual property - IPR |
|
942 value = *iPtr++; |
|
943 if ( value == 0 || value == 1 ) |
|
944 { |
|
945 iJ2kInfo.iOption |= value; |
|
946 } |
|
947 else |
|
948 { |
|
949 // Unrecognized intellectual property |
|
950 User::Leave( KErrCorrupt ); |
|
951 } |
|
952 } |
|
953 |
|
954 // ----------------------------------------------------------------------------- |
|
955 // CJp2kDecoder::ReadColorSpecBoxL |
|
956 // Verify and process the Colour Specification box ( in JP2 Header box ). |
|
957 // (other items were commented in a header). |
|
958 // ----------------------------------------------------------------------------- |
|
959 // |
|
960 void CJp2kDecoder::ReadColorSpecBoxL( const TUint32 aBoxLength ) |
|
961 { |
|
962 // Validate the Color Specification Box |
|
963 TUint8 method = *iPtr++; |
|
964 |
|
965 if ( method != 1 && method != 2 ) |
|
966 { |
|
967 // Unrecognized method |
|
968 User::Leave( KErrCorrupt ); |
|
969 } |
|
970 |
|
971 // Ignore the precedence |
|
972 iPtr++; |
|
973 |
|
974 // Ignore the approximation |
|
975 iPtr++; |
|
976 |
|
977 if ( method == 1 ) |
|
978 { |
|
979 // Method must be 1 if we reach this point |
|
980 iJ2kInfo.iEnumCS = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
981 switch ( iJ2kInfo.iEnumCS ) |
|
982 { |
|
983 case 16: |
|
984 case 17: |
|
985 case 18: |
|
986 case 21: |
|
987 case 22: |
|
988 { |
|
989 break; |
|
990 } |
|
991 default: |
|
992 { |
|
993 // Unrecognized colour specification |
|
994 User::Leave( KErrNotSupported ); |
|
995 break; |
|
996 } |
|
997 } |
|
998 } |
|
999 else |
|
1000 { |
|
1001 // ICC profile |
|
1002 TUint32 length = (TUint32)( aBoxLength - KJ2kBoxTypeLength - 3 ); |
|
1003 iJ2kInfo.iICCProfile = HBufC8::NewL( length ); |
|
1004 iJ2kInfo.iICCProfile->Des().Append( iPtr, length ); |
|
1005 iPtr += length; |
|
1006 } |
|
1007 } |
|
1008 |
|
1009 // ----------------------------------------------------------------------------- |
|
1010 // CJp2kDecoder::ReadBitsPerCompBoxL |
|
1011 // Verify and process the Bits Per Component box ( in JP2 Header box ). |
|
1012 // (other items were commented in a header). |
|
1013 // ----------------------------------------------------------------------------- |
|
1014 // |
|
1015 void CJp2kDecoder::ReadBitsPerCompBoxL( TUint32 aBoxLength ) |
|
1016 { |
|
1017 if ( iJ2kInfo.iBPC != KJ2kIsBPCBoxExist ) |
|
1018 { |
|
1019 // Should not happen but we just advance |
|
1020 // the iterator and ignore the whole box |
|
1021 iPtr += aBoxLength - KJ2kBoxTypeLength; |
|
1022 return; |
|
1023 } |
|
1024 |
|
1025 // Validate the Bits Per Component Box |
|
1026 if ( ( aBoxLength - KJ2kBoxTypeLength ) != iJ2kInfo.iNC ) |
|
1027 { |
|
1028 // Unrecognized number of components |
|
1029 User::Leave( KErrCorrupt ); |
|
1030 } |
|
1031 |
|
1032 while ( aBoxLength > KJ2kBoxTypeLength ) |
|
1033 { |
|
1034 User::LeaveIfError( iJ2kInfo.iBPCList.Append( *iPtr++ ) ); |
|
1035 |
|
1036 --aBoxLength; |
|
1037 } |
|
1038 } |
|
1039 |
|
1040 // ----------------------------------------------------------------------------- |
|
1041 // CJp2kDecoder::ReadResolutionBoxL |
|
1042 // Verify and process the Resolution box ( in JP2 Header box, |
|
1043 // (other items were commented in a header). |
|
1044 // ----------------------------------------------------------------------------- |
|
1045 // |
|
1046 void CJp2kDecoder::ReadResolutionBoxL( const TUint8 *aPtrLimit, TUint32 aBoxLength ) |
|
1047 { |
|
1048 TUint32 subBoxLength = 0; |
|
1049 TUint32 subBoxType = 0; |
|
1050 |
|
1051 aBoxLength -= KJ2kBoxTypeLength; |
|
1052 while ( aBoxLength > 0 ) |
|
1053 { |
|
1054 if ( (TUint32)( aPtrLimit - iPtr ) < KJ2kResSubBoxLength ) |
|
1055 { |
|
1056 // Not enough room for subbox data |
|
1057 User::Leave( KErrCorrupt ); |
|
1058 } |
|
1059 |
|
1060 subBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1061 subBoxType = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1062 |
|
1063 if ( subBoxLength == 1 ) |
|
1064 { |
|
1065 // The XLBox shall exist and contains the actual length of the box |
|
1066 // XLBox is 8 bytes width |
|
1067 subBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1068 subBoxLength += PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1069 aBoxLength -= KJ2kBoxTypeLength; |
|
1070 subBoxLength -= KJ2kBoxTypeLength; |
|
1071 } |
|
1072 |
|
1073 if ( subBoxLength != KJ2kResSubBoxLength ) |
|
1074 { |
|
1075 // Corrupted resolution box length, both sub boxes have length of 18 |
|
1076 User::Leave( KErrCorrupt ); |
|
1077 } |
|
1078 |
|
1079 if ( subBoxType == KJ2kCaptureResBoxType ) |
|
1080 { |
|
1081 ReadCaptureResBoxL( subBoxLength ); |
|
1082 } |
|
1083 else if ( subBoxType == KJ2kDisplayResBoxType ) |
|
1084 { |
|
1085 ReadDisplayResBoxL( ); |
|
1086 } |
|
1087 else |
|
1088 { |
|
1089 // Unrecognized box in Resolution super box |
|
1090 User::Leave( KErrCorrupt ); |
|
1091 } |
|
1092 aBoxLength -= subBoxLength; |
|
1093 } |
|
1094 } |
|
1095 |
|
1096 // ----------------------------------------------------------------------------- |
|
1097 // CJp2kDecoder::ReadDisplayResBoxL |
|
1098 // Verify and process the Default Display Resolution box ( in Resolution box ). |
|
1099 // (other items were commented in a header). |
|
1100 // ----------------------------------------------------------------------------- |
|
1101 // |
|
1102 void CJp2kDecoder::ReadDisplayResBoxL() |
|
1103 { |
|
1104 // Store default display resolution |
|
1105 TUint16 verNum = PtrReadUtil::ReadBigEndianUint16Inc( iPtr ); |
|
1106 TUint16 verDen = PtrReadUtil::ReadBigEndianUint16Inc( iPtr ); |
|
1107 TUint16 horNum = PtrReadUtil::ReadBigEndianUint16Inc( iPtr ); |
|
1108 TUint16 horDen = PtrReadUtil::ReadBigEndianUint16Inc( iPtr ); |
|
1109 TUint8 verExp = *iPtr++; |
|
1110 TUint8 horExp = *iPtr++; |
|
1111 TReal tenPow = 0.0; |
|
1112 |
|
1113 // Check the validity of the parameters |
|
1114 if((verNum == 0) || (verDen == 0) || (horNum == 0) || (horDen == 0)) |
|
1115 { |
|
1116 // Values corrupted, do not try to compute the SizeInTwips |
|
1117 return; |
|
1118 } |
|
1119 |
|
1120 User::LeaveIfError( Math::Pow10( tenPow, verExp ) ); |
|
1121 |
|
1122 TReal result = ( iJ2kInfo.iImageSize.iWidth / ( ( (TReal)verNum / verDen ) * tenPow ) ) / KJ2kTwipM; |
|
1123 iJ2kInfo.iImageSizeInTwips.iWidth = (TInt)result; |
|
1124 |
|
1125 User::LeaveIfError( Math::Pow10( tenPow,horExp ) ); |
|
1126 |
|
1127 result = ( iJ2kInfo.iImageSize.iHeight / ( ( (TReal)horNum / horDen ) * tenPow ) ) / KJ2kTwipM; |
|
1128 iJ2kInfo.iImageSizeInTwips.iHeight = (TInt)result; |
|
1129 } |
|
1130 |
|
1131 // ----------------------------------------------------------------------------- |
|
1132 // CJp2kDecoder::ReadCaptureResBoxL |
|
1133 // Verify and process the Capture Resolution box ( in Resolution box ). |
|
1134 // (other items were commented in a header). |
|
1135 // ----------------------------------------------------------------------------- |
|
1136 // |
|
1137 void CJp2kDecoder::ReadCaptureResBoxL( const TUint32 aBoxLength ) |
|
1138 { |
|
1139 // Ignore the capture resolution |
|
1140 iPtr += aBoxLength - KJ2kBoxTypeLength; |
|
1141 } |
|
1142 |
|
1143 // ----------------------------------------------------------------------------- |
|
1144 // CJp2kDecoder::ReadPaletteBoxL |
|
1145 // Verify and process the Palette box ( in JP2 Header box ). |
|
1146 // (other items were commented in a header). |
|
1147 // ----------------------------------------------------------------------------- |
|
1148 // |
|
1149 void CJp2kDecoder::ReadPaletteBoxL() |
|
1150 { |
|
1151 // Validate the Palette Box |
|
1152 TUint16 entries = PtrReadUtil::ReadBigEndianUint16Inc( iPtr ); |
|
1153 TUint8 npc = *iPtr++; |
|
1154 |
|
1155 if((entries > KMaxPaletteEntries) || (entries == 0)) |
|
1156 { |
|
1157 // Number of entries must be between 1 and 1024 |
|
1158 User::Leave( KErrCorrupt ); |
|
1159 } |
|
1160 |
|
1161 TInt rowIndex = 0; |
|
1162 TInt columnIndex = 0; |
|
1163 RArray<TUint> bpcInBytes; |
|
1164 TUint8 bpc = 0; |
|
1165 |
|
1166 for ( rowIndex = 0; rowIndex < npc; ++rowIndex ) |
|
1167 { |
|
1168 bpc = *iPtr++; |
|
1169 User::LeaveIfError( iJ2kInfo.iPalette.iBList.Append( bpc ) ); |
|
1170 |
|
1171 bpc = (TUint8)( ( 0x7f & bpc ) + 1 ); |
|
1172 User::LeaveIfError( bpcInBytes.Append( (TUint)( ( bpc % 8 ) ? bpc / 8 + 1 : bpc / 8 ) ) ); |
|
1173 } |
|
1174 |
|
1175 RArray<TUint> *cList; |
|
1176 CleanupClosePushL( bpcInBytes ); |
|
1177 |
|
1178 for ( rowIndex = 0; rowIndex < entries; ++rowIndex ) |
|
1179 { |
|
1180 cList = new ( ELeave ) RArray<TUint>( npc ); |
|
1181 CleanupStack::PushL( cList ); |
|
1182 CleanupClosePushL( *cList ); |
|
1183 |
|
1184 for ( columnIndex = 0; columnIndex < npc; ++columnIndex ) |
|
1185 { |
|
1186 switch ( bpcInBytes[columnIndex] ) |
|
1187 { |
|
1188 case 1: |
|
1189 { |
|
1190 User::LeaveIfError( cList->Append( (TUint)*iPtr++ ) ); |
|
1191 break; |
|
1192 } |
|
1193 case 2: |
|
1194 { |
|
1195 User::LeaveIfError( cList->Append( (TUint)PtrReadUtil::ReadBigEndianUint16Inc( iPtr ) ) ); |
|
1196 break; |
|
1197 } |
|
1198 case 3: |
|
1199 { |
|
1200 bpc = *iPtr++; |
|
1201 User::LeaveIfError( cList->Append( ( (TUint)bpc << 16 ) | PtrReadUtil::ReadBigEndianUint16Inc( iPtr ) ) ); |
|
1202 break; |
|
1203 } |
|
1204 case 4: |
|
1205 { |
|
1206 User::LeaveIfError( cList->Append( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) ) ); |
|
1207 break; |
|
1208 } |
|
1209 default: |
|
1210 { |
|
1211 // Unrecognized index |
|
1212 User::Leave( KErrCorrupt ); |
|
1213 break; |
|
1214 } |
|
1215 } |
|
1216 } |
|
1217 User::LeaveIfError( iJ2kInfo.iPalette.iC2DArray.Append( cList ) ); |
|
1218 CleanupStack::Pop(2); |
|
1219 } |
|
1220 CleanupStack::PopAndDestroy(); |
|
1221 } |
|
1222 |
|
1223 // ----------------------------------------------------------------------------- |
|
1224 // CJp2kDecoder::ReadComponentMapBoxL |
|
1225 // Verify and process the Component Mapping box ( in JP2 Header box ). |
|
1226 // (other items were commented in a header). |
|
1227 // ----------------------------------------------------------------------------- |
|
1228 // |
|
1229 void CJp2kDecoder::ReadComponentMapBoxL( TUint32 aBoxLength ) |
|
1230 { |
|
1231 // Validate the Component Mapping Box |
|
1232 if ( ( aBoxLength - KJ2kBoxTypeLength ) % 4 != 0 ) |
|
1233 { |
|
1234 // Misaligned Component Mapping box |
|
1235 User::Leave( KErrCorrupt ); |
|
1236 } |
|
1237 |
|
1238 TUint16 cmp = 0; |
|
1239 TUint8 mtyp = 0; |
|
1240 TUint8 pcol = 0; |
|
1241 |
|
1242 while ( aBoxLength > KJ2kBoxTypeLength ) |
|
1243 { |
|
1244 cmp = PtrReadUtil::ReadBigEndianUint16Inc( iPtr ); |
|
1245 |
|
1246 if(cmp > KMaxComponents) |
|
1247 { |
|
1248 // Illegal component index |
|
1249 User::Leave( KErrCorrupt ); |
|
1250 } |
|
1251 |
|
1252 mtyp = *iPtr++; |
|
1253 pcol = *iPtr++; |
|
1254 if ( mtyp == 0 || mtyp == 1 ) |
|
1255 { |
|
1256 if ( mtyp == 0 && pcol != 0 ) |
|
1257 { |
|
1258 // Unrecognized matching between MTYP and PCOL |
|
1259 User::Leave( KErrCorrupt ); |
|
1260 } |
|
1261 } |
|
1262 else |
|
1263 { |
|
1264 // Unrecognized MTYP |
|
1265 User::Leave( KErrCorrupt ); |
|
1266 } |
|
1267 |
|
1268 User::LeaveIfError( iJ2kInfo.iCMPList.Append( TComponentMap( cmp, mtyp, pcol ) ) ); |
|
1269 aBoxLength -= 4; |
|
1270 } |
|
1271 } |
|
1272 |
|
1273 // ----------------------------------------------------------------------------- |
|
1274 // CJp2kDecoder::ReadChannelDefBoxL |
|
1275 // Verify and process the Channel Definition box ( in JP2 Header box ). |
|
1276 // (other items were commented in a header). |
|
1277 // ----------------------------------------------------------------------------- |
|
1278 // |
|
1279 void CJp2kDecoder::ReadChannelDefBoxL( TUint32 aBoxLength ) |
|
1280 { |
|
1281 // Validate the Channel Definition Box |
|
1282 TUint16 entries = PtrReadUtil::ReadBigEndianUint16Inc( iPtr ); |
|
1283 if ( ( aBoxLength - KJ2kBoxTypeLength - 2 ) / 6 != entries ) |
|
1284 { |
|
1285 // Misaligned Channel Definition box |
|
1286 User::Leave( KErrCorrupt ); |
|
1287 } |
|
1288 |
|
1289 TUint16 cn = 0; |
|
1290 TUint16 typ = 0; |
|
1291 TUint16 asoc = 0; |
|
1292 |
|
1293 while ( entries != 0 ) |
|
1294 { |
|
1295 cn = PtrReadUtil::ReadBigEndianUint16Inc( iPtr ); |
|
1296 typ = PtrReadUtil::ReadBigEndianUint16Inc( iPtr ); |
|
1297 asoc = PtrReadUtil::ReadBigEndianUint16Inc( iPtr ); |
|
1298 User::LeaveIfError( iJ2kInfo.iCNList.Append( TChannelDefinition( cn, typ, asoc ) ) ); |
|
1299 --entries; |
|
1300 } |
|
1301 } |
|
1302 |
|
1303 // ----------------------------------------------------------------------------- |
|
1304 // CJp2kDecoder::ReadIPRBoxL |
|
1305 // Verify and process the IPR box . |
|
1306 // (other items were commented in a header). |
|
1307 // ----------------------------------------------------------------------------- |
|
1308 // |
|
1309 void CJp2kDecoder::ReadIPRBoxL() |
|
1310 { |
|
1311 // Check whether this IPR box is the last box in the file |
|
1312 if ( iBoxLength == 0 ) |
|
1313 { |
|
1314 // This IPR box is the last box in the file |
|
1315 if ( iJ2kInfo.iCSOffset != 0 ) |
|
1316 { |
|
1317 // CodeStream box has been recognized |
|
1318 // Since we are not able to read til the |
|
1319 // end of file/stream, we will skip this |
|
1320 // IPR box |
|
1321 iState = EStateInCodestreamBox; |
|
1322 return; |
|
1323 } |
|
1324 else |
|
1325 { |
|
1326 // The CodeStream box is missing from the file |
|
1327 // and nothing can be decoded |
|
1328 User::Leave( KErrCorrupt ); |
|
1329 } |
|
1330 } |
|
1331 |
|
1332 TUint xlBoxExist = 0; |
|
1333 if ( iBoxLength == 1 ) |
|
1334 { |
|
1335 // The XLBox shall exist and contains the actual length of the box |
|
1336 // XLBox is 8 bytes width |
|
1337 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength ); |
|
1338 |
|
1339 if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength ) |
|
1340 { |
|
1341 // Need more data from the ICL framework |
|
1342 User::Leave( KErrUnderflow ); |
|
1343 } |
|
1344 |
|
1345 iPtr = iBufferDes.Ptr(); |
|
1346 iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1347 iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr ); |
|
1348 xlBoxExist = 1; |
|
1349 } |
|
1350 |
|
1351 // Corrupted box length |
|
1352 if ( ( (TInt32)iBoxLength ) < 0 ) |
|
1353 { |
|
1354 User::Leave( KErrCorrupt ); |
|
1355 } |
|
1356 |
|
1357 // Check whether this IPR box is the last box in the file |
|
1358 if ( iBoxLength == 0 ) |
|
1359 { |
|
1360 // This IPR box is the last box in the file |
|
1361 if ( iJ2kInfo.iCSOffset != 0 ) |
|
1362 { |
|
1363 // CodeStream box has been recognized |
|
1364 // Since we are not able to read til the |
|
1365 // end of file/stream, we will skip this |
|
1366 // IPR box |
|
1367 iState = EStateInCodestreamBox; |
|
1368 return; |
|
1369 } |
|
1370 else |
|
1371 { |
|
1372 // The CodeStream box is missing from the file |
|
1373 // and nothing can be decoded |
|
1374 User::Leave( KErrCorrupt ); |
|
1375 } |
|
1376 } |
|
1377 |
|
1378 // Validate the IPR Box |
|
1379 // Read the IPR box + the next box's Length and Type |
|
1380 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength ); |
|
1381 |
|
1382 if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength ) |
|
1383 { |
|
1384 // Need more data from the ICL framework |
|
1385 User::Leave( KErrUnderflow ); |
|
1386 } |
|
1387 |
|
1388 iPtr = iBufferDes.Ptr(); |
|
1389 |
|
1390 // Advance the pointer by 8 bytes if XLBox exists |
|
1391 iPtr += ( xlBoxExist * KJ2kBoxTypeLength ); |
|
1392 |
|
1393 TInt length = iBoxLength - ( ( 1 + xlBoxExist ) * KJ2kBoxTypeLength ); |
|
1394 |
|
1395 HBufC8 *iprBuffer = HBufC8::NewLC( length ); |
|
1396 iprBuffer->Des().Append( iPtr, length ); |
|
1397 iPtr += length; |
|
1398 |
|
1399 User::LeaveIfError( iJ2kInfo.iIPRList.Append( iprBuffer ) ); |
|
1400 CleanupStack::Pop(); // iprBuffer |
|
1401 |
|
1402 iLastRead += iBoxLength; |
|
1403 iState = EStateInUnknown; |
|
1404 |
|
1405 if ( (TUint32)iBufferDes.Length() < iBoxLength ) |
|
1406 { |
|
1407 // Test the end of file/stream |
|
1408 ReadDataL( iLastRead, iBufferDes, 1 ); |
|
1409 if ( ( (TUint32)iBufferDes.Length() == 0 ) && |
|
1410 ( iJ2kInfo.iCSOffset != 0 ) ) |
|
1411 { |
|
1412 // CodeStream box has been recognized |
|
1413 iState = EStateInCodestreamBox; |
|
1414 } |
|
1415 else |
|
1416 { |
|
1417 // Need more data from the ICL framework |
|
1418 User::Leave( KErrUnderflow ); |
|
1419 } |
|
1420 } |
|
1421 } |
|
1422 |
|
1423 // ----------------------------------------------------------------------------- |
|
1424 // CJp2kDecoder::ReadXMLBoxL |
|
1425 // Verify and process the XML box. |
|
1426 // (other items were commented in a header). |
|
1427 // ----------------------------------------------------------------------------- |
|
1428 // |
|
1429 void CJp2kDecoder::ReadXMLBoxL() |
|
1430 { |
|
1431 // Check whether this XML box is the last box in the file |
|
1432 if ( iBoxLength == 0 ) |
|
1433 { |
|
1434 // This XML box is the last box in the file |
|
1435 if ( iJ2kInfo.iCSOffset != 0 ) |
|
1436 { |
|
1437 // CodeStream box has been recognized |
|
1438 // Since we are not able to read til the |
|
1439 // end of file/stream, we will skip this |
|
1440 // XML box |
|
1441 iState = EStateInCodestreamBox; |
|
1442 return; |
|
1443 } |
|
1444 else |
|
1445 { |
|
1446 // The CodeStream box is missing from the file |
|
1447 // and nothing can be decoded |
|
1448 User::Leave( KErrCorrupt ); |
|
1449 } |
|
1450 } |
|
1451 |
|
1452 TUint xlBoxExist = 0; |
|
1453 if ( iBoxLength == 1 ) |
|
1454 { |
|
1455 // The XLBox shall exist and contains the actual length of the box |
|
1456 // XLBox is 8 bytes width |
|
1457 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength ); |
|
1458 |
|
1459 if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength ) |
|
1460 { |
|
1461 // Need more data from the ICL framework |
|
1462 User::Leave( KErrUnderflow ); |
|
1463 } |
|
1464 |
|
1465 iPtr = iBufferDes.Ptr(); |
|
1466 iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1467 iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr ); |
|
1468 xlBoxExist = 1; |
|
1469 } |
|
1470 |
|
1471 // Corrupted box length |
|
1472 if ( ( (TInt32)iBoxLength ) < 0 ) |
|
1473 { |
|
1474 User::Leave( KErrCorrupt ); |
|
1475 } |
|
1476 |
|
1477 // Check whether this XML box is the last box in the file |
|
1478 if ( iBoxLength == 0 ) |
|
1479 { |
|
1480 // This XML box is the last box in the file |
|
1481 if ( iJ2kInfo.iCSOffset != 0 ) |
|
1482 { |
|
1483 // CodeStream box has been recognized |
|
1484 // Since we are not able to read til the |
|
1485 // end of file/stream, we will skip this |
|
1486 // XML box |
|
1487 iState = EStateInCodestreamBox; |
|
1488 return; |
|
1489 } |
|
1490 else |
|
1491 { |
|
1492 // The CodeStream box is missing from the file |
|
1493 // and nothing can be decoded |
|
1494 User::Leave( KErrCorrupt ); |
|
1495 } |
|
1496 } |
|
1497 |
|
1498 // Validate the XML Box |
|
1499 // Read the XML box + the next box's Length and Type |
|
1500 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength ); |
|
1501 |
|
1502 if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength ) |
|
1503 { |
|
1504 // Need more data from the ICL framework |
|
1505 User::Leave( KErrUnderflow ); |
|
1506 } |
|
1507 |
|
1508 iPtr = iBufferDes.Ptr(); |
|
1509 |
|
1510 // Advance the pointer by 8 bytes if XLBox exists |
|
1511 iPtr += ( xlBoxExist * KJ2kBoxTypeLength ); |
|
1512 |
|
1513 TInt length = iBoxLength - ( ( 1 + xlBoxExist ) * KJ2kBoxTypeLength ); |
|
1514 |
|
1515 HBufC8 *xmlBuffer = HBufC8::NewLC( length ); |
|
1516 xmlBuffer->Des().Append( iPtr, length ); |
|
1517 iPtr += length; |
|
1518 |
|
1519 User::LeaveIfError( iJ2kInfo.iXMLList.Append( xmlBuffer ) ); |
|
1520 CleanupStack::Pop(); // xmlBuffer |
|
1521 |
|
1522 iLastRead += iBoxLength; |
|
1523 iState = EStateInUnknown; |
|
1524 |
|
1525 if ( (TUint32)iBufferDes.Length() < iBoxLength ) |
|
1526 { |
|
1527 // Test the end of file |
|
1528 ReadDataL( iLastRead, iBufferDes, 1 ); |
|
1529 if ( ( (TUint32)iBufferDes.Length() == 0 ) && |
|
1530 ( iJ2kInfo.iCSOffset != 0 ) ) |
|
1531 { |
|
1532 // CodeStream box has been recognized |
|
1533 iState = EStateInCodestreamBox; |
|
1534 } |
|
1535 else |
|
1536 { |
|
1537 // Need more data from the ICL framework |
|
1538 User::Leave( KErrUnderflow ); |
|
1539 } |
|
1540 } |
|
1541 } |
|
1542 |
|
1543 // ----------------------------------------------------------------------------- |
|
1544 // CJp2kDecoder::ReadUUIDBoxL |
|
1545 // Verify and process UUID box. |
|
1546 // (other items were commented in a header). |
|
1547 // ----------------------------------------------------------------------------- |
|
1548 // |
|
1549 void CJp2kDecoder::ReadUUIDBoxL() |
|
1550 { |
|
1551 // Check whether this UUID box is the last box in the file |
|
1552 if ( iBoxLength == 0 ) |
|
1553 { |
|
1554 // This UUID box is the last box in the file |
|
1555 if ( iJ2kInfo.iCSOffset != 0 ) |
|
1556 { |
|
1557 // CodeStream box has been recognized |
|
1558 // Since we are not able to read til the |
|
1559 // end of file/stream, we will skip this |
|
1560 // UUID box |
|
1561 iState = EStateInCodestreamBox; |
|
1562 return; |
|
1563 } |
|
1564 else |
|
1565 { |
|
1566 // The CodeStream box is missing from the file |
|
1567 // and nothing can be decoded |
|
1568 User::Leave( KErrCorrupt ); |
|
1569 } |
|
1570 } |
|
1571 |
|
1572 TUint xlBoxExist = 0; |
|
1573 if ( iBoxLength == 1 ) |
|
1574 { |
|
1575 // The XLBox shall exist and contains the actual length of the box |
|
1576 // XLBox is 8 bytes width |
|
1577 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength ); |
|
1578 |
|
1579 if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength ) |
|
1580 { |
|
1581 // Need more data from the ICL framework |
|
1582 User::Leave( KErrUnderflow ); |
|
1583 } |
|
1584 |
|
1585 iPtr = iBufferDes.Ptr(); |
|
1586 iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1587 iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr ); |
|
1588 xlBoxExist = 1; |
|
1589 } |
|
1590 |
|
1591 // Corrupted box length |
|
1592 if ( ( (TInt32)iBoxLength ) < 0 ) |
|
1593 { |
|
1594 User::Leave( KErrCorrupt ); |
|
1595 } |
|
1596 |
|
1597 // Check whether this UUID box is the last box in the file |
|
1598 if ( iBoxLength == 0 ) |
|
1599 { |
|
1600 // This UUID box is the last box in the file |
|
1601 if ( iJ2kInfo.iCSOffset != 0 ) |
|
1602 { |
|
1603 // CodeStream box has been recognized |
|
1604 // Since we are not able to read til the |
|
1605 // end of file/stream, we will skip this |
|
1606 // UUID box |
|
1607 iState = EStateInCodestreamBox; |
|
1608 return; |
|
1609 } |
|
1610 else |
|
1611 { |
|
1612 // The CodeStream box is missing from the file |
|
1613 // and nothing can be decoded |
|
1614 User::Leave( KErrCorrupt ); |
|
1615 } |
|
1616 } |
|
1617 |
|
1618 // Validate the UUID Box |
|
1619 // Read the UUID box + the next box's Length and Type |
|
1620 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength ); |
|
1621 |
|
1622 if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength ) |
|
1623 { |
|
1624 // Need more data from the ICL framework |
|
1625 User::Leave( KErrUnderflow ); |
|
1626 } |
|
1627 |
|
1628 iPtr = iBufferDes.Ptr(); |
|
1629 |
|
1630 // Advance the pointer by 8 bytes if XLBox exists |
|
1631 iPtr += ( xlBoxExist * KJ2kBoxTypeLength ); |
|
1632 |
|
1633 TInt length = iBoxLength - ( ( 1 + xlBoxExist ) * KJ2kBoxTypeLength ); |
|
1634 |
|
1635 HBufC8 *uuidBuffer = HBufC8::NewLC( length ); |
|
1636 uuidBuffer->Des().Append( iPtr, length ); |
|
1637 iPtr += length; |
|
1638 |
|
1639 User::LeaveIfError( iJ2kInfo.iUUIDList.Append( uuidBuffer ) ); |
|
1640 CleanupStack::Pop(); // uuidBuffer |
|
1641 |
|
1642 iLastRead += iBoxLength; |
|
1643 iState = EStateInUnknown; |
|
1644 |
|
1645 if ( (TUint32)iBufferDes.Length() < iBoxLength ) |
|
1646 { |
|
1647 // Test the end of file |
|
1648 ReadDataL( iLastRead, iBufferDes, 1 ); |
|
1649 if ( ( (TUint32)iBufferDes.Length() == 0 ) && |
|
1650 ( iJ2kInfo.iCSOffset != 0 ) ) |
|
1651 { |
|
1652 // CodeStream box has been recognized |
|
1653 iState = EStateInCodestreamBox; |
|
1654 } |
|
1655 else |
|
1656 { |
|
1657 // Need more data from the ICL framework |
|
1658 User::Leave( KErrUnderflow ); |
|
1659 } |
|
1660 } |
|
1661 } |
|
1662 |
|
1663 // ----------------------------------------------------------------------------- |
|
1664 // CJp2kDecoder::ReadUUIDInfoBoxL |
|
1665 // Verify and process the UUID Info box ( superbox ). |
|
1666 // (other items were commented in a header). |
|
1667 // ----------------------------------------------------------------------------- |
|
1668 // |
|
1669 void CJp2kDecoder::ReadUUIDInfoBoxL() |
|
1670 { |
|
1671 // Check whether this UUIDInfo box is the last box in the file |
|
1672 if ( iBoxLength == 0 ) |
|
1673 { |
|
1674 // This UUIDInfo box is the last box in the file |
|
1675 if ( iJ2kInfo.iCSOffset != 0 ) |
|
1676 { |
|
1677 // CodeStream box has been recognized |
|
1678 // Since we are not able to read til the |
|
1679 // end of file/stream, we will skip this |
|
1680 // UUIDInfo box |
|
1681 iState = EStateInCodestreamBox; |
|
1682 return; |
|
1683 } |
|
1684 else |
|
1685 { |
|
1686 // The CodeStream box is missing from the file |
|
1687 // and nothing can be decoded |
|
1688 User::Leave( KErrCorrupt ); |
|
1689 } |
|
1690 } |
|
1691 |
|
1692 TUint xlBoxExist = 0; |
|
1693 if ( iBoxLength == 1 ) |
|
1694 { |
|
1695 // The XLBox shall exist and contains the actual length of the box |
|
1696 // XLBox is 8 bytes width |
|
1697 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength ); |
|
1698 |
|
1699 if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength ) |
|
1700 { |
|
1701 // Need more data from the ICL framework |
|
1702 User::Leave( KErrUnderflow ); |
|
1703 } |
|
1704 |
|
1705 iPtr = iBufferDes.Ptr(); |
|
1706 iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1707 iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr ); |
|
1708 xlBoxExist = 1; |
|
1709 } |
|
1710 |
|
1711 // Corrupted box length |
|
1712 if ( ( (TInt32)iBoxLength ) < 0 ) |
|
1713 { |
|
1714 User::Leave( KErrCorrupt ); |
|
1715 } |
|
1716 |
|
1717 // Check whether this UUIDInfo box is the last box in the file |
|
1718 if ( iBoxLength == 0 ) |
|
1719 { |
|
1720 // This UUIDInfo box is the last box in the file |
|
1721 if ( iJ2kInfo.iCSOffset != 0 ) |
|
1722 { |
|
1723 // CodeStream box has been recognized |
|
1724 // Since we are not able to read til the |
|
1725 // end of file/stream, we will skip this |
|
1726 // UUIDInfo box |
|
1727 iState = EStateInCodestreamBox; |
|
1728 return; |
|
1729 } |
|
1730 else |
|
1731 { |
|
1732 // The CodeStream box is missing from the file |
|
1733 // and nothing can be decoded |
|
1734 User::Leave( KErrCorrupt ); |
|
1735 } |
|
1736 } |
|
1737 |
|
1738 // Validate the UUIDInfo Box |
|
1739 // Read the UUIDInfo box + the next box's Length and Type |
|
1740 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength ); |
|
1741 |
|
1742 if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength ) |
|
1743 { |
|
1744 // Need more data from the ICL framework |
|
1745 User::Leave( KErrUnderflow ); |
|
1746 } |
|
1747 |
|
1748 iPtr = iBufferDes.Ptr(); |
|
1749 |
|
1750 // Substract next box's Length and Type |
|
1751 const TUint8 *ptrLimit = iPtr + iBoxLength - KJ2kBoxTypeLength; |
|
1752 |
|
1753 // Advance the pointer by 8 bytes if XLBox exists |
|
1754 iPtr += ( xlBoxExist * KJ2kBoxTypeLength ); |
|
1755 |
|
1756 TUint32 subBoxLength = 0; |
|
1757 TUint32 subBoxType = 0; |
|
1758 |
|
1759 TInt32 length = ptrLimit - iPtr; |
|
1760 TInt32 dataLength = 0; |
|
1761 TInt32 order = 0; |
|
1762 |
|
1763 HBufC8 *listBuffer = 0; |
|
1764 HBufC8 *urlBuffer = 0; |
|
1765 |
|
1766 while ( length > 0 ) |
|
1767 { |
|
1768 if ( ( ptrLimit - iPtr ) < 8 ) |
|
1769 { |
|
1770 // Not enough room for box data |
|
1771 User::Leave( KErrCorrupt ); |
|
1772 } |
|
1773 |
|
1774 subBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1775 subBoxType = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1776 |
|
1777 if ( subBoxLength == 1 ) |
|
1778 { |
|
1779 // The XLBox shall exist and contains the actual length of the box |
|
1780 // XLBox is 8 bytes width |
|
1781 subBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1782 subBoxLength += PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1783 length -= KJ2kBoxTypeLength; |
|
1784 subBoxLength -= KJ2kBoxTypeLength; |
|
1785 } |
|
1786 |
|
1787 if ( ( (TInt32)subBoxLength < 0 ) || ( subBoxLength <= 8 ) || ( ( iPtr + subBoxLength - KJ2kBoxTypeLength ) > ptrLimit ) ) |
|
1788 { |
|
1789 // Not enough room for subbox data or corrupted subbox length |
|
1790 User::Leave( KErrCorrupt ); |
|
1791 } |
|
1792 |
|
1793 switch ( subBoxType ) |
|
1794 { |
|
1795 case KJ2kUUIDListBoxType: |
|
1796 { |
|
1797 // Validate the UUIDInfo List box |
|
1798 // NU | ID-0 | ... | ID-n |
|
1799 // where NU is 2 bytes unsigned specifying the number of IDs |
|
1800 // ID is 16 bytes UUID |
|
1801 TUint16 nuField = PtrReadUtil::ReadBigEndianUint16( iPtr ); |
|
1802 if ( ( subBoxLength - ( 2 + KJ2kBoxTypeLength ) ) != |
|
1803 ( (TUint32)( nuField * KJ2KUuidIDSize ) ) ) |
|
1804 { |
|
1805 // UUIDInfo List box does not confirm to standard format |
|
1806 User::Leave( KErrCorrupt ); |
|
1807 } |
|
1808 |
|
1809 if ( listBuffer ) |
|
1810 { |
|
1811 // There should be one UUIDInfo List box |
|
1812 User::Leave( KErrCorrupt ); |
|
1813 } |
|
1814 |
|
1815 dataLength = subBoxLength - KJ2kBoxTypeLength; |
|
1816 listBuffer = HBufC8::NewLC( dataLength ); |
|
1817 listBuffer->Des().Append( iPtr, dataLength ); |
|
1818 iPtr += ( dataLength ); |
|
1819 |
|
1820 if ( order == 0 ) |
|
1821 { |
|
1822 // Increment the order if UUIDInfo List box come first |
|
1823 ++order; |
|
1824 } |
|
1825 break; |
|
1826 } |
|
1827 case KJ2kUUIDUrlBoxType: |
|
1828 { |
|
1829 // Validate the UUIDInfo Data Entry Url box |
|
1830 if ( urlBuffer ) |
|
1831 { |
|
1832 // There should be one UUIDInfo Data Entry Url box |
|
1833 User::Leave( KErrCorrupt ); |
|
1834 } |
|
1835 |
|
1836 dataLength = subBoxLength - KJ2kBoxTypeLength; |
|
1837 urlBuffer = HBufC8::NewLC( dataLength ); |
|
1838 urlBuffer->Des().Append( iPtr, dataLength ); |
|
1839 iPtr += ( dataLength ); |
|
1840 |
|
1841 if ( order == 0 ) |
|
1842 { |
|
1843 // Decrement the order if UUIDInfo Data Entry Url box come first |
|
1844 --order; |
|
1845 } |
|
1846 break; |
|
1847 } |
|
1848 default: |
|
1849 { |
|
1850 // Unrecognized Box |
|
1851 User::Leave( KErrCorrupt ); |
|
1852 break; |
|
1853 } |
|
1854 } |
|
1855 length -= subBoxLength; |
|
1856 } |
|
1857 |
|
1858 if ( listBuffer || urlBuffer ) |
|
1859 { |
|
1860 if ( !( listBuffer ) ) |
|
1861 { |
|
1862 // Create a dummy place holder |
|
1863 listBuffer = HBufC8::NewLC( 1 ); |
|
1864 } |
|
1865 |
|
1866 if ( !( urlBuffer ) ) |
|
1867 { |
|
1868 // Create a dummy place holder |
|
1869 urlBuffer = HBufC8::NewLC( 1 ); |
|
1870 } |
|
1871 |
|
1872 if ( order < 0 ) |
|
1873 { |
|
1874 // UUIDInfo Data Entry Url box come first |
|
1875 User::LeaveIfError( iJ2kInfo.iUUIDInfoListList.Append( listBuffer ) ); |
|
1876 CleanupStack::Pop( 1 ); // listBuffer |
|
1877 |
|
1878 User::LeaveIfError( iJ2kInfo.iUUIDInfoUrlList.Append( urlBuffer ) ); |
|
1879 CleanupStack::Pop( 1 ); // urlBuffer |
|
1880 } |
|
1881 else |
|
1882 { |
|
1883 // UUIDInfo List box come first |
|
1884 User::LeaveIfError( iJ2kInfo.iUUIDInfoUrlList.Append( urlBuffer ) ); |
|
1885 CleanupStack::Pop( 1 ); // urlBuffer |
|
1886 |
|
1887 User::LeaveIfError( iJ2kInfo.iUUIDInfoListList.Append( listBuffer ) ); |
|
1888 CleanupStack::Pop( 1 ); // listBuffer |
|
1889 } |
|
1890 } |
|
1891 else |
|
1892 { |
|
1893 // UUIDInfo box does not containing any |
|
1894 // UUIDInfo List box or UUIDInfo Data Entry Url box |
|
1895 User::Leave( KErrCorrupt ); |
|
1896 } |
|
1897 |
|
1898 iLastRead += iBoxLength; |
|
1899 iState = EStateInUnknown; |
|
1900 |
|
1901 if ( (TUint32)iBufferDes.Length() < iBoxLength ) |
|
1902 { |
|
1903 // Test the end of file |
|
1904 ReadDataL( iLastRead, iBufferDes, 1 ); |
|
1905 if ( ( (TUint32)iBufferDes.Length() == 0 ) && |
|
1906 ( iJ2kInfo.iCSOffset != 0 ) ) |
|
1907 { |
|
1908 // CodeStream box has been recognized |
|
1909 iState = EStateInCodestreamBox; |
|
1910 } |
|
1911 else |
|
1912 { |
|
1913 // Need more data from the ICL framework |
|
1914 User::Leave( KErrUnderflow ); |
|
1915 } |
|
1916 } |
|
1917 } |
|
1918 |
|
1919 // ----------------------------------------------------------------------------- |
|
1920 // CJp2kDecoder::IgnoreBoxL |
|
1921 // Ignore the content of the box and advance the iterator to the next box. |
|
1922 // (other items were commented in a header). |
|
1923 // ----------------------------------------------------------------------------- |
|
1924 // |
|
1925 void CJp2kDecoder::IgnoreBoxL() |
|
1926 { |
|
1927 // Check whether this box is the last box in the file |
|
1928 if ( iBoxLength == 0 ) |
|
1929 { |
|
1930 // This box is the last box in the file |
|
1931 if ( iJ2kInfo.iCSOffset != 0 ) |
|
1932 { |
|
1933 // CodeStream box has been recognized |
|
1934 // Since we are not able to read til the |
|
1935 // end of file/stream, we will skip this |
|
1936 // box |
|
1937 iState = EStateInCodestreamBox; |
|
1938 return; |
|
1939 } |
|
1940 else |
|
1941 { |
|
1942 // The CodeStream box is missing from the file |
|
1943 // and nothing can be decoded |
|
1944 User::Leave( KErrCorrupt ); |
|
1945 } |
|
1946 } |
|
1947 |
|
1948 if ( iBoxLength == 1 ) |
|
1949 { |
|
1950 // The XLBox shall exist and contains the actual length of the box |
|
1951 // XLBox is 8 bytes width |
|
1952 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength ); |
|
1953 |
|
1954 if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength ) |
|
1955 { |
|
1956 // Need more data from the ICL framework |
|
1957 User::Leave( KErrUnderflow ); |
|
1958 } |
|
1959 |
|
1960 iPtr = iBufferDes.Ptr(); |
|
1961 iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
1962 iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr ); |
|
1963 } |
|
1964 |
|
1965 // Corrupted box length |
|
1966 if ( ( (TInt32)iBoxLength ) < 0 ) |
|
1967 { |
|
1968 User::Leave( KErrCorrupt ); |
|
1969 } |
|
1970 |
|
1971 // Check whether this box is the last box in the file |
|
1972 if ( iBoxLength == 0 ) |
|
1973 { |
|
1974 // This box is the last box in the file |
|
1975 if ( iJ2kInfo.iCSOffset != 0 ) |
|
1976 { |
|
1977 // CodeStream box has been recognized |
|
1978 // Since we are not able to read til the |
|
1979 // end of file/stream, we will skip this |
|
1980 // box |
|
1981 iState = EStateInCodestreamBox; |
|
1982 return; |
|
1983 } |
|
1984 else |
|
1985 { |
|
1986 // The CodeStream box is missing from the file |
|
1987 // and nothing can be decoded |
|
1988 User::Leave( KErrCorrupt ); |
|
1989 } |
|
1990 } |
|
1991 |
|
1992 // Read and ignore the validation of the box |
|
1993 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength ); |
|
1994 |
|
1995 if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength ) |
|
1996 { |
|
1997 // Need more data from the ICL framework |
|
1998 User::Leave( KErrUnderflow ); |
|
1999 } |
|
2000 |
|
2001 iPtr = iBufferDes.Ptr(); |
|
2002 |
|
2003 iLastRead += iBoxLength; |
|
2004 iState = EStateInUnknown; |
|
2005 |
|
2006 iPtr += iBoxLength - KJ2kBoxTypeLength; |
|
2007 if ( (TUint32)iBufferDes.Length() < iBoxLength ) |
|
2008 { |
|
2009 // Test the end of file |
|
2010 ReadDataL( iLastRead, iBufferDes, 1 ); |
|
2011 if ( ( (TUint32)iBufferDes.Length() == 0 ) && |
|
2012 ( iJ2kInfo.iCSOffset != 0 ) ) |
|
2013 { |
|
2014 // CodeStream box has been recognized |
|
2015 iState = EStateInCodestreamBox; |
|
2016 } |
|
2017 else |
|
2018 { |
|
2019 // Need more data from the ICL framework |
|
2020 User::Leave( KErrUnderflow ); |
|
2021 } |
|
2022 } |
|
2023 } |
|
2024 |
|
2025 // ----------------------------------------------------------------------------- |
|
2026 // CJp2kDecoder::UpdateStateFromBoxTypeL |
|
2027 // Update the current state according to the box type |
|
2028 // (other items were commented in a header). |
|
2029 // ----------------------------------------------------------------------------- |
|
2030 // |
|
2031 void CJp2kDecoder::UpdateStateFromBoxTypeL() |
|
2032 { |
|
2033 switch ( iBoxType ) |
|
2034 { |
|
2035 case KJ2kSigBoxType: |
|
2036 { |
|
2037 iState = EStateInSignatureBox; |
|
2038 break; |
|
2039 } |
|
2040 case KJ2kJP2HeaderBoxType: |
|
2041 { |
|
2042 iState = EStateInJP2SuperBox; |
|
2043 break; |
|
2044 } |
|
2045 case KJ2kCodestreamBoxType: |
|
2046 { |
|
2047 if ( iJ2kInfo.iOption & TJ2kInfo::EJP2file ) |
|
2048 { |
|
2049 if ( !( iJ2kInfo.iOption & TJ2kInfo::EJP2Header ) ) |
|
2050 { |
|
2051 // In JP2 file format, CodeStream box |
|
2052 // can not come before JP2 Header box |
|
2053 User::Leave( KErrCorrupt ); |
|
2054 } |
|
2055 |
|
2056 // Save the CodeStream box's length |
|
2057 iJ2kInfo.iCSBoxLength = iBoxLength; |
|
2058 iJ2kInfo.iCSOffset = iLastRead; |
|
2059 |
|
2060 if ( iBoxLength == 0 ) |
|
2061 { |
|
2062 // CodeStream box is the last box in the file |
|
2063 iState = EStateInCodestreamBox; |
|
2064 } |
|
2065 else |
|
2066 { |
|
2067 // Continue checking any boxes after the CodeStream box |
|
2068 if ( iBoxLength == 1 ) |
|
2069 { |
|
2070 // The XLBox shall exist and contains the actual length of the box |
|
2071 // XLBox is 8 bytes width |
|
2072 ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength ); |
|
2073 |
|
2074 if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength ) |
|
2075 { |
|
2076 // Need more data from the ICL framework |
|
2077 User::Leave( KErrUnderflow ); |
|
2078 } |
|
2079 |
|
2080 iPtr = iBufferDes.Ptr(); |
|
2081 iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr ); |
|
2082 iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr ); |
|
2083 } |
|
2084 |
|
2085 // Corrupted box length |
|
2086 if ( ( (TInt32)iBoxLength ) < 0 ) |
|
2087 { |
|
2088 User::Leave( KErrCorrupt ); |
|
2089 } |
|
2090 |
|
2091 iLastRead += iBoxLength; |
|
2092 // Test the end of file |
|
2093 ReadDataL( iLastRead, iBufferDes, KJ2kBoxTypeLength ); |
|
2094 if ( (TUint32)iBufferDes.Length() == 0 ) |
|
2095 { |
|
2096 // CodeStream box is the last box in the file |
|
2097 iState = EStateInCodestreamBox; |
|
2098 } |
|
2099 else if ( (TUint32)iBufferDes.Length() == KJ2kBoxTypeLength ) |
|
2100 { |
|
2101 iPtr = iBufferDes.Ptr(); |
|
2102 } |
|
2103 else |
|
2104 { |
|
2105 // Need more data from the ICL framework |
|
2106 User::Leave( KErrUnderflow ); |
|
2107 } |
|
2108 } |
|
2109 } |
|
2110 else |
|
2111 { |
|
2112 // CodeStream box must exist in file format only |
|
2113 User::Leave( KErrCorrupt ); |
|
2114 } |
|
2115 break; |
|
2116 } |
|
2117 case KJ2kIPRBoxType: |
|
2118 { |
|
2119 iState = EStateInIPRBox; |
|
2120 break; |
|
2121 } |
|
2122 case KJ2kXMLBoxType: |
|
2123 { |
|
2124 iState = EStateInXMLBox; |
|
2125 break; |
|
2126 } |
|
2127 case KJ2kUUIDBoxType: |
|
2128 { |
|
2129 iState = EStateInUUIDBox; |
|
2130 break; |
|
2131 } |
|
2132 case KJ2kUUIDInfoBoxType: |
|
2133 { |
|
2134 iState = EStateInUUIDInfoBox; |
|
2135 break; |
|
2136 } |
|
2137 default: |
|
2138 { |
|
2139 // Check if the first 4 bytes read |
|
2140 // is SOC + SIZ |
|
2141 if ( iBoxLength == KJ2kSOCType ) |
|
2142 { |
|
2143 if ( iJ2kInfo.iOption & TJ2kInfo::EJP2file ) |
|
2144 { |
|
2145 // JP2 codestream shouldn't in JP2 file format |
|
2146 User::Leave( KErrCorrupt ); |
|
2147 } |
|
2148 |
|
2149 // SOC + SIZ marker - JP2 Codestream |
|
2150 iState = EStateInCodestreamBox; |
|
2151 iJ2kInfo.iCSOffset = iLastRead; |
|
2152 } |
|
2153 else |
|
2154 { |
|
2155 // Unrecognized box type |
|
2156 // there are two ways of handling this |
|
2157 // 1. stop parsing and Leave with an KErrCorrupt error |
|
2158 // User::Leave( KErrCorrupt ); |
|
2159 // 2. just ignore the box and continue on parsing the |
|
2160 // next box. |
|
2161 IgnoreBoxL(); |
|
2162 } |
|
2163 break; |
|
2164 } |
|
2165 } |
|
2166 } |
|
2167 |
|
2168 // ----------------------------------------------------------------------------- |
|
2169 // CJp2kDecoder::ScanDataL |
|
2170 // Called from ICL framework to instantiate decoder and parse header. |
|
2171 // (other items were commented in a header). |
|
2172 // ----------------------------------------------------------------------------- |
|
2173 // |
|
2174 void CJp2kDecoder::ScanDataL() |
|
2175 { |
|
2176 ReadFormatL(); |
|
2177 |
|
2178 ASSERT( ImageReadCodec() == NULL ); |
|
2179 |
|
2180 CJp2kReadCodec* imageReadCodec = CJp2kReadCodec::NewL( iJ2kInfo ); |
|
2181 SetImageReadCodec( imageReadCodec ); |
|
2182 |
|
2183 ReadFrameHeadersL(); |
|
2184 } |
|
2185 |
|
2186 // ========================== OTHER EXPORTED FUNCTIONS ========================= |
|
2187 |
|
2188 // ----------------------------------------------------------------------------- |
|
2189 // Global panic function, From JP2KImageClientMain.h |
|
2190 // ----------------------------------------------------------------------------- |
|
2191 // |
|
2192 GLDEF_C void Panic( TIclPanic aError ) //lint !e759 already in module |
|
2193 { |
|
2194 User::Panic( KJ2KPanicCategory, aError ); |
|
2195 } |
|
2196 |