@@ -417,32 +417,86 @@ IsoMCanonIad1Box::IsoMCanonIad1Box(const AbstractIsoMBox& base)
417
417
reserved3 = data.get <uint16_t >();
418
418
419
419
if (2 == ind) { // ind is 2 for big images
420
- sensorLeftBorder = data.get <uint16_t >();
421
- sensorTopBorder = data.get <uint16_t >();
422
- sensorRightBorder = data.get <uint16_t >();
423
- sensorBottomBorder = data.get <uint16_t >();
424
- data.skipBytes (2 * sizeof (uint16_t ));
425
- sensorBlackAreaLeft = data.get <uint16_t >();
426
- data.skipBytes (4 * sizeof (uint16_t ));
427
- sensorBlackAreaTop = data.get <uint16_t >();
420
+ cropLeftOffset = data.get <uint16_t >();
421
+ cropTopOffset = data.get <uint16_t >();
422
+ cropRightOffset = data.get <uint16_t >();
423
+ cropBottomOffset = data.get <uint16_t >();
424
+
425
+ leftOpticalBlackLeftOffset = data.get <uint16_t >();
426
+ leftOpticalBlackTopOffset = data.get <uint16_t >();
427
+ leftOpticalBlackRightOffset = data.get <uint16_t >();
428
+ leftOpticalBlackBottomOffset = data.get <uint16_t >();
429
+
430
+ topOpticalBlackLeftOffset = data.get <uint16_t >();
431
+ topOpticalBlackTopOffset = data.get <uint16_t >();
432
+ topOpticalBlackRightOffset = data.get <uint16_t >();
433
+ topOpticalBlackBottomOffset = data.get <uint16_t >();
434
+
435
+ activeAreaLeftOffset = data.get <uint16_t >();
436
+ activeAreaTopOffset = data.get <uint16_t >();
437
+ activeAreaRightOffset = data.get <uint16_t >();
438
+ activeAreaBottomOffset = data.get <uint16_t >();
439
+ } else {
440
+ // We hit a small image box?!
441
+ ThrowRDE (" IAD1 box contains small image information, but big image expected" );
428
442
}
429
443
430
444
writeLog (DEBUG_PRIO_EXTRA,
431
445
" IAD1 sensor width: %d, height: %d, crop: %u, %u, %u, %u, black "
432
446
" area left: %u, top: %u" ,
433
- sensorWidth, sensorHeight, sensorLeftBorder, sensorTopBorder ,
434
- sensorRightBorder, sensorBottomBorder, sensorBlackAreaLeft ,
435
- sensorBlackAreaTop );
447
+ sensorWidth, sensorHeight, cropLeftOffset, cropTopOffset ,
448
+ cropRightOffset, cropBottomOffset, leftOpticalBlackRightOffset ,
449
+ topOpticalBlackBottomOffset );
436
450
437
451
// Validate.
438
452
operator bool ();
439
453
}
440
454
441
455
IsoMCanonIad1Box::operator bool () const {
442
- // No fields yet to validate, IAD1 is unused for decoding.
456
+ if (!sensorWidth || !sensorHeight)
457
+ ThrowIPE (" IAD1 sensor size unknown" );
458
+ if (!cropRect ().isThisInside (sensorRect ()))
459
+ ThrowIPE (" IAD1 crop rect is outside sensor rect" );
443
460
return true ; // OK!
444
461
}
445
462
463
+ iRectangle2D IsoMCanonIad1Box::sensorRect () const {
464
+ return iRectangle2D (0 , 0 , sensorWidth, sensorHeight);
465
+ }
466
+
467
+ iRectangle2D IsoMCanonIad1Box::cropRect () const {
468
+ return iRectangle2D (
469
+ cropLeftOffset,
470
+ cropTopOffset,
471
+ (cropRightOffset+1 )-cropLeftOffset,
472
+ (cropBottomOffset+1 )-cropTopOffset);
473
+ }
474
+
475
+ iRectangle2D IsoMCanonIad1Box::leftOpticalBlackRect () const {
476
+ return iRectangle2D (
477
+ leftOpticalBlackLeftOffset,
478
+ leftOpticalBlackTopOffset,
479
+ (leftOpticalBlackRightOffset+1 )-leftOpticalBlackLeftOffset,
480
+ (leftOpticalBlackBottomOffset+1 )-leftOpticalBlackTopOffset);
481
+ }
482
+
483
+ iRectangle2D IsoMCanonIad1Box::topOpticalBlackRect () const {
484
+ return iRectangle2D (
485
+ topOpticalBlackLeftOffset,
486
+ topOpticalBlackTopOffset,
487
+ (topOpticalBlackRightOffset+1 )-topOpticalBlackLeftOffset,
488
+ (topOpticalBlackBottomOffset+1 )-topOpticalBlackTopOffset);
489
+ }
490
+
491
+ iRectangle2D IsoMCanonIad1Box::activeArea () const {
492
+ return iRectangle2D (
493
+ activeAreaLeftOffset,
494
+ activeAreaTopOffset,
495
+ (activeAreaRightOffset+1 )-activeAreaLeftOffset,
496
+ (activeAreaBottomOffset+1 )-activeAreaTopOffset);
497
+ }
498
+
499
+
446
500
CanonTimedMetadata::CanonTimedMetadata::Record::Record (ByteStream* bs) {
447
501
assert (bs->getByteOrder () == Endianness::little);
448
502
auto origPos = bs->getPosition ();
@@ -634,23 +688,34 @@ void Cr3Decoder::decodeMetaDataInternal(const CameraMetaData* meta) {
634
688
}
635
689
636
690
setMetaData (meta, camId.make , camId.model , mode, iso);
691
+ writeLog (DEBUG_PRIO_EXTRA, " blacklevel for ISO %d is %d" , mRaw ->metadata .isoSpeed , mRaw ->blackLevel );
637
692
638
- // IAD1 described sensor constraints
693
+ // IAD1 describes sensor constraints
639
694
const auto & iad1 = crawBox->CDI1 ()->IAD1 ();
640
695
641
696
if (mRaw ->blackAreas .empty ()) {
642
- mRaw ->blackAreas .push_back (BlackArea (0 , iad1->sensorBlackAreaLeft , true ));
643
- mRaw ->blackAreas .push_back (BlackArea (0 , iad1->sensorBlackAreaTop , false ));
697
+ // IAD1 stores the rectangles for black areas.
698
+ auto leftOpticalBlack = iad1->leftOpticalBlackRect ();
699
+ auto topOpticalBlack = iad1->topOpticalBlackRect ();
700
+ if (leftOpticalBlack.dim .x >= 12 +4 ) {
701
+ // if left optical black has >= 12+4 pixels, we reduce them by 12 as some
702
+ // models (EOS RP is known) has white pixels in this area.
703
+ // Yes, this is hacky, but IAD1 reports offset=0 which is either wrong or the white pixels
704
+ // are a camera bug and must be resolved in software.
705
+ leftOpticalBlack.pos .x += 12 ;
706
+ leftOpticalBlack.dim .x -= 12 ;
707
+ }
708
+ if (topOpticalBlack.dim .y >= 12 +4 ) {
709
+ // Same must be done for horizontal pixels
710
+ topOpticalBlack.pos .y += 12 ;
711
+ topOpticalBlack.dim .y -= 12 ;
712
+ }
713
+ mRaw ->blackAreas .push_back (BlackArea (leftOpticalBlack.pos .x , leftOpticalBlack.dim .x , true ));
714
+ mRaw ->blackAreas .push_back (BlackArea (topOpticalBlack.pos .y , topOpticalBlack.pos .y , false ));
644
715
}
645
716
646
717
if (applyCrop) {
647
- // IAD1 sensor parameters always crop one more pixel as needed.
648
- // We add back the missing pixels to match official specifications.
649
- iRectangle2D new_area (iad1->sensorLeftBorder , iad1->sensorTopBorder ,
650
- iad1->sensorRightBorder - iad1->sensorLeftBorder + 1 ,
651
- iad1->sensorBottomBorder - iad1->sensorTopBorder + 1 );
652
-
653
- mRaw ->subFrame (new_area);
718
+ mRaw ->subFrame (iad1->cropRect ());
654
719
}
655
720
}
656
721
0 commit comments