@@ -598,6 +598,10 @@ private boolean processMakernote(final int makernoteOffset,
598598 ReconyxUltraFireMakernoteDirectory directory = new ReconyxUltraFireMakernoteDirectory ();
599599 _metadata .addDirectory (directory );
600600 processReconyxUltraFireMakernote (directory , makernoteOffset , reader );
601+ } else if (firstNineChars .equalsIgnoreCase ("RECONYXH2" )) {
602+ ReconyxHyperFire2MakernoteDirectory directory = new ReconyxHyperFire2MakernoteDirectory ();
603+ _metadata .addDirectory (directory );
604+ processReconyxHyperFire2Makernote (directory , makernoteOffset , reader );
601605 } else if ("SAMSUNG" .equalsIgnoreCase (cameraMake )) {
602606 // Only handles Type2 notes correctly. Others aren't implemented, and it's complex to determine which ones to use
603607 pushDirectory (SamsungType2MakernoteDirectory .class );
@@ -798,6 +802,82 @@ private static void processReconyxHyperFireMakernote(@NotNull final ReconyxHyper
798802 directory .setString (ReconyxHyperFireMakernoteDirectory .TAG_USER_LABEL , reader .getNullTerminatedString (makernoteOffset + ReconyxHyperFireMakernoteDirectory .TAG_USER_LABEL , 44 , Charsets .UTF_8 ));
799803 }
800804
805+ private static void processReconyxHyperFire2Makernote (@ NotNull final ReconyxHyperFire2MakernoteDirectory directory , final int makernoteOffset , @ NotNull final RandomAccessReader reader ) throws IOException
806+ {
807+
808+ int major = reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_FIRMWARE_VERSION );
809+ int minor = reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_FIRMWARE_VERSION + 2 );
810+ int revision = reader .getUInt16 (makernoteOffset + ReconyxHyperFireMakernoteDirectory .TAG_FIRMWARE_VERSION + 4 );
811+ String buildYear = String .format ("%04X" , reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_FIRMWARE_VERSION + 6 ));
812+ String buildDate = String .format ("%04X" , reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_FIRMWARE_VERSION + 8 ));
813+ String buildYearAndDate = buildYear + buildDate ;
814+ Integer build ;
815+ try {
816+ build = Integer .parseInt (buildYearAndDate );
817+ } catch (NumberFormatException e ) {
818+ build = null ;
819+ }
820+
821+ if (build != null ) {
822+ directory .setString (ReconyxHyperFire2MakernoteDirectory .TAG_FIRMWARE_VERSION , String .format ("%d.%d.%d.%s" , major , minor , revision , build ));
823+ } else {
824+ directory .setString (ReconyxHyperFire2MakernoteDirectory .TAG_FIRMWARE_VERSION , String .format ("%d.%d.%d" , major , minor , revision ));
825+ directory .addError ("Error processing Reconyx HyperFire 2 makernote data: build '" + buildYearAndDate + "' is not in the expected format and will be omitted from Firmware Version." );
826+ }
827+
828+ directory .setIntArray (ReconyxHyperFire2MakernoteDirectory .TAG_SEQUENCE ,
829+ new int []
830+ {
831+ reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_SEQUENCE ),
832+ reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_SEQUENCE + 2 )
833+ });
834+
835+ int eventNumberHigh = reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_EVENT_NUMBER );
836+ int eventNumberLow = reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_EVENT_NUMBER + 2 );
837+ directory .setInt (ReconyxHyperFire2MakernoteDirectory .TAG_EVENT_NUMBER , (eventNumberHigh << 16 ) + eventNumberLow );
838+
839+ int seconds = reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_DATE_TIME_ORIGINAL );
840+ int minutes = reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_DATE_TIME_ORIGINAL + 2 );
841+ int hour = reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_DATE_TIME_ORIGINAL + 4 );
842+ int month = reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_DATE_TIME_ORIGINAL + 6 );
843+ int day = reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_DATE_TIME_ORIGINAL + 8 );
844+ int year = reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_DATE_TIME_ORIGINAL + 10 );
845+
846+ if ((seconds >= 0 && seconds < 60 ) &&
847+ (minutes >= 0 && minutes < 60 ) &&
848+ (hour >= 0 && hour < 24 ) &&
849+ (month >= 1 && month < 13 ) &&
850+ (day >= 1 && day < 32 ) &&
851+ (year >= 1 && year <= 9999 )) {
852+ directory .setString (ReconyxHyperFire2MakernoteDirectory .TAG_DATE_TIME_ORIGINAL ,
853+ String .format ("%4d:%2d:%2d %2d:%2d:%2d" , year , month , day , hour , minutes , seconds ));
854+ } else {
855+ directory .addError ("Error processing Reconyx HyperFire 2 makernote data: Date/Time Original " + year + "-" + month + "-" + day + " " + hour + ":" + minutes + ":" + seconds + " is not a valid date/time." );
856+ }
857+
858+ directory .setInt (ReconyxHyperFire2MakernoteDirectory .TAG_MOON_PHASE , reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_MOON_PHASE ));
859+ directory .setInt (ReconyxHyperFire2MakernoteDirectory .TAG_AMBIENT_TEMPERATURE_FAHRENHEIT , reader .getInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_AMBIENT_TEMPERATURE_FAHRENHEIT ));
860+ directory .setInt (ReconyxHyperFire2MakernoteDirectory .TAG_AMBIENT_TEMPERATURE , reader .getInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_AMBIENT_TEMPERATURE ));
861+
862+ directory .setInt (ReconyxHyperFire2MakernoteDirectory .TAG_CONTRAST , reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_CONTRAST ));
863+ directory .setInt (ReconyxHyperFire2MakernoteDirectory .TAG_BRIGHTNESS , reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_BRIGHTNESS ));
864+ directory .setInt (ReconyxHyperFire2MakernoteDirectory .TAG_SHARPNESS , reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_SHARPNESS ));
865+ directory .setInt (ReconyxHyperFire2MakernoteDirectory .TAG_SATURATION , reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_SATURATION ));
866+ directory .setInt (ReconyxHyperFire2MakernoteDirectory .TAG_FLASH , reader .getByte (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_FLASH ));
867+ directory .setInt (ReconyxHyperFire2MakernoteDirectory .TAG_AMBIENT_INFRARED , reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_AMBIENT_INFRARED ));
868+ directory .setInt (ReconyxHyperFire2MakernoteDirectory .TAG_AMBIENT_LIGHT , reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_AMBIENT_LIGHT ));
869+ directory .setInt (ReconyxHyperFire2MakernoteDirectory .TAG_MOTION_SENSITIVITY , reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_MOTION_SENSITIVITY ));
870+ directory .setDouble (ReconyxHyperFire2MakernoteDirectory .TAG_BATTERY_VOLTAGE , reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_BATTERY_VOLTAGE ) / 1000.0 );
871+ directory .setDouble (ReconyxHyperFire2MakernoteDirectory .TAG_BATTERY_VOLTAGE_AVG , reader .getUInt16 (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_BATTERY_VOLTAGE_AVG ) / 1000.0 );
872+
873+
874+ directory .setString (ReconyxHyperFireMakernoteDirectory .TAG_USER_LABEL , reader .getNullTerminatedString (makernoteOffset + ReconyxHyperFireMakernoteDirectory .TAG_USER_LABEL , 44 , Charsets .UTF_8 ));
875+ directory .setStringValue (ReconyxHyperFire2MakernoteDirectory .TAG_SERIAL_NUMBER , new StringValue (reader .getBytes (makernoteOffset + ReconyxHyperFire2MakernoteDirectory .TAG_SERIAL_NUMBER , 28 ), Charsets .UTF_16LE ));
876+ // two unread bytes: the serial number's terminating null
877+ }
878+
879+
880+
801881 private static void processReconyxUltraFireMakernote (@ NotNull final ReconyxUltraFireMakernoteDirectory directory , final int makernoteOffset , @ NotNull final RandomAccessReader reader ) throws IOException
802882 {
803883 directory .setString (ReconyxUltraFireMakernoteDirectory .TAG_LABEL , reader .getString (makernoteOffset , 9 , Charsets .UTF_8 ));
0 commit comments