diff --git a/ui/package-lock.json b/ui/package-lock.json
index 3293b21652d276580c78897ee00c0d25a22ae4d0..eb0ce5cee7e783ecb44d18b2f9243a9b4082bcc8 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -16,6 +16,7 @@
         "@types/node": "^12.20.17",
         "@types/react": "^17.0.15",
         "@types/react-dom": "^17.0.9",
+        "mdi-material-ui": "^6.22.1",
         "react": "^17.0.2",
         "react-dom": "^17.0.2",
         "react-query": "^3.19.1",
@@ -13581,6 +13582,15 @@
         "safe-buffer": "^5.1.2"
       }
     },
+    "node_modules/mdi-material-ui": {
+      "version": "6.22.1",
+      "resolved": "https://registry.npmjs.org/mdi-material-ui/-/mdi-material-ui-6.22.1.tgz",
+      "integrity": "sha512-wndaFXJhoFr9g5kPw31TZajTa9uf/21jb2jD1rJ5Vi+sj2GZYnZz2BYbrfp1qFgd7tZz8XAcnpsSNMdLbe+dtw==",
+      "peerDependencies": {
+        "@material-ui/core": "^4.0.0",
+        "react": "^16.8.0 || ^17.0.0"
+      }
+    },
     "node_modules/mdn-data": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
@@ -32318,6 +32328,12 @@
         "safe-buffer": "^5.1.2"
       }
     },
+    "mdi-material-ui": {
+      "version": "6.22.1",
+      "resolved": "https://registry.npmjs.org/mdi-material-ui/-/mdi-material-ui-6.22.1.tgz",
+      "integrity": "sha512-wndaFXJhoFr9g5kPw31TZajTa9uf/21jb2jD1rJ5Vi+sj2GZYnZz2BYbrfp1qFgd7tZz8XAcnpsSNMdLbe+dtw==",
+      "requires": {}
+    },
     "mdn-data": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
diff --git a/ui/package.json b/ui/package.json
index 9f137687b4282c981bb2b661f0da172132165543..efbbf5d273e22be2afb0b5ea3875684d77f361ad 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -12,6 +12,7 @@
     "@types/node": "^12.20.17",
     "@types/react": "^17.0.15",
     "@types/react-dom": "^17.0.9",
+    "mdi-material-ui": "^6.22.1",
     "react": "^17.0.2",
     "react-dom": "^17.0.2",
     "react-query": "^3.19.1",
diff --git a/ui/src/components/ImageView.tsx b/ui/src/components/ImageView.tsx
index 9d57bc6f32a9ed88c09cbf0fc444a8aaddb44ee7..cf98f573538874b3c82d40c494dfa263ee117447 100644
--- a/ui/src/components/ImageView.tsx
+++ b/ui/src/components/ImageView.tsx
@@ -1,5 +1,5 @@
 import {Image} from "../api/model/Image";
-import React, {useMemo, useState} from "react";
+import React, {Fragment, useMemo, useState} from "react";
 import {useUpdateImage} from "../api/useUpdateImage";
 import {useDeleteImage} from "../api/useDeleteImage";
 import {parseMetadata, ratioToTime} from "../metadata/ImageMetadata";
@@ -13,6 +13,9 @@ import {SceneMode} from "../metadata/SceneMode";
 import {ContrastProcessing} from "../metadata/ContrastProcessing";
 import {SharpnessProcessing} from "../metadata/SharpnessProcessing";
 import {SubjectDistanceRange} from "../metadata/SubjectDistanceRange";
+import {BrightnessMedium, Camera, Copyright, Event, Exposure, PhotoCamera, ZoomIn} from "@material-ui/icons";
+import {AngleAcute, ArrowExpandHorizontal, Blur, CameraTimer, Flash, WhiteBalanceIncandescent} from "mdi-material-ui";
+import {FlashMode} from "../metadata/FlashMode";
 
 export interface ImageProps {
     image: Image
@@ -61,39 +64,92 @@ export default function ImageView({image}: ImageProps) {
             <p>{image.updated_at}</p>
             <p>{image.state}</p>
             <h3>Metadata</h3>
-            <p><b>Make</b>: {metadata.make}</p>
-            <p><b>Model</b>: {metadata.model}</p>
-            <p><b>Software</b>: {metadata.software}</p>
-            <p><b>Copyright</b>: {metadata.copyright}</p>
-            <p><b>DateTime Created</b>: {metadata.dateTimeCreated?.toISOString()}</p>
-            <p><b>DateTime Digitized</b>: {metadata.dateTimeDigitized?.toISOString()}</p>
-            <p><b>DateTime Original</b>: {metadata.dateTimeOriginal?.toISOString()}</p>
-            <p><b>Digital Zoom</b>: {ratioToFloat(metadata.digitalZoomRatio)}</p>
-            <p><b>Exposure</b>: {ratioToFloat(metadata.exposure)}</p>
-            <p><b>Exposure Mode</b>: {metadata.exposureMode !== undefined ?
-                ExposureMode[metadata.exposureMode] : "null"}</p>
-            <p><b>Exposure Program</b>: {metadata.exposureProgram !== undefined ?
-                ExposureProgram[metadata.exposureProgram] : "null"}</p>
-            <p><b>Exposure Time</b>: {ratioToTime(metadata.exposureTime)}</p>
-            <p><b>Aperture</b>: {ratioToFloat(metadata.aperture)}</p>
-            <p><b>Focal Length</b>: {ratioToFloat(metadata.focalLength)}</p>
-            <p><b>Focal Length (35mm equivalent)</b>: {ratioToFloat(metadata.focalLength35mm)}</p>
-            <p><b>ISO</b>: {metadata.isoSpeedRating}</p>
-            <p><b>Light source</b>: {metadata.lightSource !== undefined ?
-                LightSource[metadata.lightSource] : "null"}</p>
-            <p><b>Metering mode</b>: {metadata.meteringMode !== undefined ?
-                MeteringMode[metadata.meteringMode] : "null"}</p>
-            <p><b>White balance</b>: {metadata.whiteBalance !== undefined ?
-                WhiteBalance[metadata.whiteBalance] : "null"}</p>
-            <p><b>Scene Mode</b>: {metadata.sceneMode !== undefined ?
-                SceneMode[metadata.sceneMode] : "null"}</p>
-            <p><b>Contrast Processing</b>: {metadata.contrast !== undefined ?
-                ContrastProcessing[metadata.contrast] : "null"}</p>
-            <p><b>Sharpness Processing</b>: {metadata.sharpness !== undefined ?
-                SharpnessProcessing[metadata.sharpness] : "null"}</p>
-            <p><b>Subject Distance</b>: {metadata.subjectDistance}</p>
-            <p><b>Subject Distance Range</b>: {metadata.subjectDistanceRange !== undefined ?
-                SubjectDistanceRange[metadata.subjectDistanceRange] : "null"}</p>
+            {metadata.make !== undefined && (
+                <p><b>Make</b>: {metadata.make}</p>
+            )}
+            {metadata.model !== undefined && (
+                <p><PhotoCamera/><b>Model</b>: {metadata.model}</p>
+            )}
+            {metadata.software !== undefined && (
+                <p><b>Software</b>: {metadata.software}</p>
+            )}
+            {metadata.copyright !== undefined && (
+                <p><Copyright/><b>Copyright</b>: {metadata.copyright}</p>
+            )}
+            {metadata.dateTimeCreated !== undefined && (
+                <p><Event/><b>DateTime Created</b>: {metadata.dateTimeCreated?.toISOString()}</p>
+            )}
+            {metadata.dateTimeDigitized !== undefined && (
+                <p><Event/><b>DateTime Digitized</b>: {metadata.dateTimeDigitized?.toISOString()}</p>
+            )}
+            {metadata.dateTimeOriginal !== undefined && (
+                <p><Event/><b>DateTime Original</b>: {metadata.dateTimeOriginal?.toISOString()}</p>
+            )}
+            {metadata.digitalZoomRatio !== undefined && (
+                <p><ZoomIn/><b>Digital Zoom</b>: {ratioToFloat(metadata.digitalZoomRatio)}</p>
+            )}
+            {metadata.exposure !== undefined && (
+                <p><Exposure/><b>Exposure</b>: {ratioToFloat(metadata.exposure)}</p>
+            )}
+            {metadata.exposureMode !== undefined && (
+                <p><Exposure/><b>Exposure Mode</b>: {ExposureMode[metadata.exposureMode]}</p>
+            )}
+            {metadata.exposureProgram !== undefined && (
+                <p><Exposure/><b>Exposure Program</b>: {ExposureProgram[metadata.exposureProgram]}</p>
+            )}
+            {metadata.shutterSpeed !== undefined && (
+                <p><CameraTimer/><b>Shutter Speed</b>: {ratioToTime(metadata.shutterSpeed)}</p>
+            )}
+            {metadata.aperture !== undefined && (
+                <p><Camera/><b>Aperture</b>: {ratioToFloat(metadata.aperture)}</p>
+            )}
+            {metadata.focalLength !== undefined && (
+                <p><AngleAcute/><b>Focal Length</b>: {ratioToFloat(metadata.focalLength)}mm</p>
+            )}
+            {metadata.focalLength35mm !== undefined && (
+                <p><AngleAcute/><b>Focal Length (35mm equivalent)</b>: {ratioToFloat(metadata.focalLength35mm)}mm</p>
+            )}
+            {metadata.isoSpeedRating !== undefined && (
+                <p><b>ISO</b>: {metadata.isoSpeedRating}</p>
+            )}
+            {metadata.flash !== undefined && (
+                <Fragment>
+                    <p><Flash/><b>Flash</b></p>
+                    <p><b>Available</b>: {metadata.flash.available ? "Yes" : "No"}</p>
+                    <p><b>Fired</b>: {metadata.flash.fired ? "Yes" : "No"}</p>
+                    <p><b>Red Eye Reduction</b>: {metadata.flash.redEyeReduction ? "Yes" : "No"}</p>
+                    <p><b>Strobe Detection Available</b>: {metadata.flash.strobeDetection.available ? "Yes" : "No"}</p>
+                    <p><b>Strobe Detection Used</b>: {metadata.flash.strobeDetection.detected ? "Yes" : "No"}</p>
+                    {metadata.flash.mode !== undefined && (
+                        <p><b>Flash Mode</b>: {FlashMode[metadata.flash.mode]}</p>
+                    )}
+                </Fragment>
+            )}
+            {metadata.lightSource !== undefined && (
+                <p><WhiteBalanceIncandescent/><b>Light source</b>: {LightSource[metadata.lightSource]}</p>
+            )}
+            {metadata.meteringMode !== undefined && (
+                <p><b>Metering mode</b>: {MeteringMode[metadata.meteringMode]}</p>
+            )}
+            {metadata.whiteBalance !== undefined && (
+                <p><WhiteBalanceIncandescent/><b>White balance</b>: {WhiteBalance[metadata.whiteBalance]}</p>
+            )}
+            {metadata.sceneMode !== undefined && (
+                <p><b>Scene Mode</b>: {SceneMode[metadata.sceneMode]}</p>
+            )}
+            {metadata.contrast !== undefined && (
+                <p><BrightnessMedium/><b>Contrast Processing</b>: {ContrastProcessing[metadata.contrast]}</p>
+            )}
+            {metadata.sharpness !== undefined && (
+                <p><Blur/><b>Sharpness Processing</b>: {SharpnessProcessing[metadata.sharpness]}</p>
+            )}
+            {metadata.subjectDistance !== undefined && (
+                <p><ArrowExpandHorizontal/><b>Subject Distance</b>: {metadata.subjectDistance}</p>
+            )}
+            {metadata.subjectDistanceRange !== undefined && (
+                <p><ArrowExpandHorizontal/><b>Subject Distance
+                    Range</b>: {SubjectDistanceRange[metadata.subjectDistanceRange]}</p>
+            )}
             <img src={image.url + "t"} alt=""/>
             <br/>
             <input
diff --git a/ui/src/metadata/ContrastProcessing.ts b/ui/src/metadata/ContrastProcessing.ts
index 91405fb701cdbb9500ba8a3fb38df3edd87330b3..01b2e15092ad24b897c4b70692822a01090e5a68 100644
--- a/ui/src/metadata/ContrastProcessing.ts
+++ b/ui/src/metadata/ContrastProcessing.ts
@@ -1,5 +1,18 @@
+import {parseNumber} from "./ImageMetadata";
+
 export enum ContrastProcessing {
     NORMAL = 0,
     SOFT = 1,
     HARD = 2,
 }
+
+export function parseContrastProcessing(value: string | undefined): ContrastProcessing | undefined {
+    const numericValue = parseNumber(value);
+    if (numericValue === undefined) {
+        return undefined;
+    }
+    if (Object.values(ContrastProcessing).includes(numericValue)) {
+        return numericValue as ContrastProcessing;
+    }
+    return undefined;
+}
diff --git a/ui/src/metadata/ExposureMode.ts b/ui/src/metadata/ExposureMode.ts
index 2518b99022f968eb336e1d0cf0dfb4c2c82b1508..ce81dd4bc182710b861506749275ba9cedbb2933 100644
--- a/ui/src/metadata/ExposureMode.ts
+++ b/ui/src/metadata/ExposureMode.ts
@@ -1,5 +1,18 @@
+import {parseNumber} from "./ImageMetadata";
+
 export enum ExposureMode {
     AUTO = 0,
     MANUAL = 1,
     BRACKET = 2,
 }
+
+export function parseExposureMode(value: string | undefined): ExposureMode | undefined {
+    const numericValue = parseNumber(value)
+    if (numericValue === undefined) {
+        return undefined;
+    }
+    if (Object.values(ExposureMode).includes(numericValue)) {
+        return numericValue as ExposureMode;
+    }
+    return undefined;
+}
diff --git a/ui/src/metadata/ExposureProgram.ts b/ui/src/metadata/ExposureProgram.ts
index c0569270344e88f9fa4b204b4dff1aa690613529..8d5528d194cbad3779208059c7a64a0d571213b2 100644
--- a/ui/src/metadata/ExposureProgram.ts
+++ b/ui/src/metadata/ExposureProgram.ts
@@ -1,3 +1,5 @@
+import {parseNumber} from "./ImageMetadata";
+
 export enum ExposureProgram {
     MANUAL = 1,
     NORMAL = 2,
@@ -8,3 +10,14 @@ export enum ExposureProgram {
     PORTRAIT = 7,
     LANDSCAPE = 8,
 }
+
+export function parseExposureProgram(value: string | undefined): ExposureProgram | undefined {
+    const numericValue = parseNumber(value);
+    if (numericValue === undefined) {
+        return undefined;
+    }
+    if (Object.values(ExposureProgram).includes(numericValue)) {
+        return numericValue as ExposureProgram;
+    }
+    return undefined;
+}
diff --git a/ui/src/metadata/Flash.test.tsx b/ui/src/metadata/Flash.test.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..d561d69e8950a57c7b55ad3e215de92e1f5f181f
--- /dev/null
+++ b/ui/src/metadata/Flash.test.tsx
@@ -0,0 +1,291 @@
+import {parseFlash} from "./Flash";
+import {FlashMode} from "./FlashMode";
+
+describe("parseFlash", () => {
+    test("Flash did not fire", () => {
+        expect(parseFlash(0x00.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: false,
+            strobeDetection: {
+                available: false,
+                detected: false,
+            },
+            mode: undefined,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("Flash fired", () => {
+        expect(parseFlash(0x01.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: false,
+                detected: false,
+            },
+            mode: undefined,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("Strobe return light not detected", () => {
+        expect(parseFlash(0x05.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: true,
+                detected: false,
+            },
+            mode: undefined,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("Strobe return light detected", () => {
+        expect(parseFlash(0x07.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: true,
+                detected: true,
+            },
+            mode: undefined,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, compulsory flash mode", () => {
+        expect(parseFlash(0x09.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: false,
+                detected: false,
+            },
+            mode: FlashMode.ALWAYS_ON,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, compulsory flash mode, return light not detected", () => {
+        expect(parseFlash(0x0D.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: true,
+                detected: false,
+            },
+            mode: FlashMode.ALWAYS_ON,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, compulsory flash mode, return light detected", () => {
+        expect(parseFlash(0x0F.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: true,
+                detected: true,
+            },
+            mode: FlashMode.ALWAYS_ON,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("Flash did not fire, compulsory flash mode", () => {
+        expect(parseFlash(0x10.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: false,
+            strobeDetection: {
+                available: false,
+                detected: false,
+            },
+            mode: FlashMode.ALWAYS_OFF,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("Flash did not fire, auto mode", () => {
+        expect(parseFlash(0x18.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: false,
+            strobeDetection: {
+                available: false,
+                detected: false,
+            },
+            mode: FlashMode.AUTO,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, auto mode", () => {
+        expect(parseFlash(0x19.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: false,
+                detected: false,
+            },
+            mode: FlashMode.AUTO,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, auto mode, return light not detected", () => {
+        expect(parseFlash(0x1D.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: true,
+                detected: false,
+            },
+            mode: FlashMode.AUTO,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, auto mode, return light detected", () => {
+        expect(parseFlash(0x1F.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: true,
+                detected: true,
+            },
+            mode: FlashMode.AUTO,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("No flash function", () => {
+        expect(parseFlash(0x20.toString(), undefined)).toStrictEqual({
+            available: false,
+            fired: false,
+            strobeDetection: {
+                available: false,
+                detected: false,
+            },
+            mode: undefined,
+            redEyeReduction: false,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, red-eye reduction mode", () => {
+        expect(parseFlash(0x41.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: false,
+                detected: false,
+            },
+            mode: undefined,
+            redEyeReduction: true,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, red-eye reduction mode, return light not detected", () => {
+        expect(parseFlash(0x45.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: true,
+                detected: false,
+            },
+            mode: undefined,
+            redEyeReduction: true,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, red-eye reduction mode, return light detected", () => {
+        expect(parseFlash(0x47.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: true,
+                detected: true,
+            },
+            mode: undefined,
+            redEyeReduction: true,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, compulsory flash mode, red-eye reduction mode", () => {
+        expect(parseFlash(0x49.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: false,
+                detected: false,
+            },
+            mode: FlashMode.ALWAYS_ON,
+            redEyeReduction: true,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected", () => {
+        expect(parseFlash(0x4D.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: true,
+                detected: false,
+            },
+            mode: FlashMode.ALWAYS_ON,
+            redEyeReduction: true,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, compulsory flash mode, red-eye reduction mode, return light detected", () => {
+        expect(parseFlash(0x4F.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: true,
+                detected: true,
+            },
+            mode: FlashMode.ALWAYS_ON,
+            redEyeReduction: true,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, auto mode, red-eye reduction mode", () => {
+        expect(parseFlash(0x59.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: false,
+                detected: false,
+            },
+            mode: FlashMode.AUTO,
+            redEyeReduction: true,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, auto mode, return light not detected, red-eye reduction mode", () => {
+        expect(parseFlash(0x5D.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: true,
+                detected: false,
+            },
+            mode: FlashMode.AUTO,
+            redEyeReduction: true,
+            strength: undefined,
+        })
+    })
+    test("Flash fired, auto mode, return light detected, red-eye reduction mode", () => {
+        expect(parseFlash(0x5F.toString(), undefined)).toStrictEqual({
+            available: true,
+            fired: true,
+            strobeDetection: {
+                available: true,
+                detected: true,
+            },
+            mode: FlashMode.AUTO,
+            redEyeReduction: true,
+            strength: undefined,
+        })
+    })
+})
diff --git a/ui/src/metadata/Flash.ts b/ui/src/metadata/Flash.ts
index 2a966779caefecf93428f0b2bd6883a630d0eb49..e122ce0923a07fd73401dda54360308e48790c57 100644
--- a/ui/src/metadata/Flash.ts
+++ b/ui/src/metadata/Flash.ts
@@ -1,4 +1,6 @@
-import {FlashMode} from "./FlashMode";
+import {FlashMode, parseFlashMode} from "./FlashMode";
+import {parseRatio, Ratio} from "./Ratio";
+import {parseNumber} from "./ImageMetadata";
 
 export interface Flash {
     available: boolean,
@@ -7,6 +9,33 @@ export interface Flash {
         available: boolean,
         detected: boolean,
     },
-    mode: FlashMode | null,
+    mode: FlashMode | undefined,
     redEyeReduction: boolean,
+    strength: Ratio | undefined,
+}
+
+const MASK_FIRED = 0x0001;
+const MASK_STROBE_DETECTED = 0x0002;
+const MASK_STROBE_DETECTION_AVAILABLE = 0x0004;
+const MASK_MODE = 0x0003;
+const MASK_UNAVAILABLE = 0x0020;
+const MASK_REDEYE = 0x0040;
+
+export function parseFlash(flash: string | undefined, strength: string | undefined): Flash | undefined {
+    const value = parseNumber(flash);
+    if (value === undefined) {
+        return undefined;
+    }
+
+    return {
+        available: (value & MASK_UNAVAILABLE) === 0,
+        fired: (value & MASK_FIRED) !== 0,
+        strobeDetection: {
+            available: (value & MASK_STROBE_DETECTION_AVAILABLE) !== 0,
+            detected: (value & MASK_STROBE_DETECTED) !== 0,
+        },
+        redEyeReduction: (value & MASK_REDEYE) !== 0,
+        strength: parseRatio(strength),
+        mode: parseFlashMode((value >> 3) & MASK_MODE),
+    };
 }
diff --git a/ui/src/metadata/FlashMode.ts b/ui/src/metadata/FlashMode.ts
index 02f73791c3a43e45ca9004f6f7a2637509e96831..0330cc9af82863976924d619b72286fd0d8dbdc2 100644
--- a/ui/src/metadata/FlashMode.ts
+++ b/ui/src/metadata/FlashMode.ts
@@ -3,3 +3,11 @@ export enum FlashMode {
     ALWAYS_OFF = 2,
     AUTO = 3
 }
+
+export function parseFlashMode(value: number): FlashMode | undefined {
+    if (Object.values(FlashMode).includes(value)) {
+        return value as FlashMode;
+    } else {
+        return undefined;
+    }
+}
diff --git a/ui/src/metadata/ImageMetadata.ts b/ui/src/metadata/ImageMetadata.ts
index 12ff5d23c6b30d4dcd9f8b9dad4c4f2a6d8d3763..1ca8219a97cc5bd30d85b65ea9fcd493b791c56f 100644
--- a/ui/src/metadata/ImageMetadata.ts
+++ b/ui/src/metadata/ImageMetadata.ts
@@ -1,14 +1,14 @@
 import {parseRatio, Ratio} from "./Ratio";
-import {Flash} from "./Flash";
-import {ExposureMode} from "./ExposureMode";
-import {ExposureProgram} from "./ExposureProgram";
-import {LightSource} from "./LightSource";
-import {MeteringMode} from "./MeteringMode";
-import {WhiteBalance} from "./WhiteBalance";
-import {SceneMode} from "./SceneMode";
-import {ContrastProcessing} from "./ContrastProcessing";
-import {SharpnessProcessing} from "./SharpnessProcessing";
-import {SubjectDistanceRange} from "./SubjectDistanceRange";
+import {Flash, parseFlash} from "./Flash";
+import {ExposureMode, parseExposureMode} from "./ExposureMode";
+import {ExposureProgram, parseExposureProgram} from "./ExposureProgram";
+import {LightSource, parseLightSource} from "./LightSource";
+import {MeteringMode, parseMeteringMode} from "./MeteringMode";
+import {parseWhiteBalance, WhiteBalance} from "./WhiteBalance";
+import {parseSceneMode, SceneMode} from "./SceneMode";
+import {ContrastProcessing, parseContrastProcessing} from "./ContrastProcessing";
+import {parseSharpnessProcessing, SharpnessProcessing} from "./SharpnessProcessing";
+import {parseSubjectDistanceRange, SubjectDistanceRange} from "./SubjectDistanceRange";
 
 export interface ImageMetadata {
     make?: string,
@@ -22,7 +22,7 @@ export interface ImageMetadata {
     exposure?: Ratio,
     exposureMode?: ExposureMode,
     exposureProgram?: ExposureProgram,
-    exposureTime?: Ratio,
+    shutterSpeed?: Ratio,
     aperture?: Ratio,
     flash?: Flash,
     focalLength?: Ratio,
@@ -38,7 +38,7 @@ export interface ImageMetadata {
     subjectDistanceRange?: SubjectDistanceRange,
 }
 
-export function parseMetadata(metadata: { [key: string]: string }): ImageMetadata {
+export function parseMetadata(metadata: { [key: string]: string | undefined }): ImageMetadata {
     return {
         make: metadata["Make"],
         model: metadata["Model"],
@@ -51,9 +51,9 @@ export function parseMetadata(metadata: { [key: string]: string }): ImageMetadat
         exposure: parseRatio(metadata["ExposureBiasValue"]),
         exposureMode: parseExposureMode(metadata["ExposureMode"]),
         exposureProgram: parseExposureProgram(metadata["ExposureProgram"]),
-        exposureTime: parseRatio(metadata["ExposureTime"]),
+        shutterSpeed: parseRatio(metadata["ExposureTime"]),
         aperture: parseRatio(metadata["FNumber"]),
-        flash: undefined,
+        flash: parseFlash(metadata["Flash"], metadata["FlashEnergy"]),
         focalLength: parseRatio(metadata["FocalLength"]),
         focalLength35mm: parseRatio(metadata["FocalLengthIn35mmFilm"]),
         isoSpeedRating: parseNumber(metadata["ISOSpeedRatings"]),
@@ -68,7 +68,10 @@ export function parseMetadata(metadata: { [key: string]: string }): ImageMetadat
     }
 }
 
-export function parseDate(value: string): Date | undefined {
+export function parseDate(value: string | undefined): Date | undefined {
+    if (value === undefined) {
+        return undefined;
+    }
     const split = value.split(" ");
     if (split.length !== 2) {
         return undefined;
@@ -85,7 +88,10 @@ export function parseDate(value: string): Date | undefined {
     }
 }
 
-export function parseNumber(value: string): number | undefined {
+export function parseNumber(value: string | undefined): number | undefined {
+    if (value === undefined) {
+        return undefined;
+    }
     const number = parseInt(value);
     if (isNaN(number) || number === Infinity || number === -Infinity) {
         return undefined;
@@ -93,105 +99,6 @@ export function parseNumber(value: string): number | undefined {
     return number;
 }
 
-export function parseExposureMode(value: string): ExposureMode | undefined {
-    const numericValue = parseNumber(value)
-    if (numericValue === undefined) {
-        return undefined;
-    }
-    if (numericValue in Object.values(ExposureMode)) {
-        return numericValue as ExposureMode;
-    }
-    return undefined;
-}
-
-export function parseExposureProgram(value: string): ExposureProgram | undefined {
-    const numericValue = parseNumber(value);
-    if (numericValue === undefined) {
-        return undefined;
-    }
-    if (numericValue in Object.values(ExposureProgram)) {
-        return numericValue as ExposureProgram;
-    }
-    return undefined;
-}
-
-export function parseLightSource(value: string): LightSource | undefined {
-    const numericValue = parseNumber(value);
-    if (numericValue === undefined) {
-        return undefined;
-    }
-    if (numericValue in Object.values(LightSource)) {
-        return numericValue as LightSource;
-    }
-    return undefined;
-}
-
-export function parseMeteringMode(value: string): MeteringMode | undefined {
-    const numericValue = parseNumber(value);
-    if (numericValue === undefined) {
-        return undefined;
-    }
-    if (numericValue in Object.values(MeteringMode)) {
-        return numericValue as MeteringMode;
-    }
-    return undefined;
-}
-
-export function parseWhiteBalance(value: string): WhiteBalance | undefined {
-    const numericValue = parseNumber(value);
-    if (numericValue === undefined) {
-        return undefined;
-    }
-    if (numericValue in Object.values(WhiteBalance)) {
-        return numericValue as WhiteBalance;
-    }
-    return undefined;
-}
-
-export function parseSceneMode(value: string): SceneMode | undefined {
-    const numericValue = parseNumber(value);
-    if (numericValue === undefined) {
-        return undefined;
-    }
-    if (numericValue in Object.values(SceneMode)) {
-        return numericValue as SceneMode;
-    }
-    return undefined;
-}
-
-export function parseContrastProcessing(value: string): ContrastProcessing | undefined {
-    const numericValue = parseNumber(value);
-    if (numericValue === undefined) {
-        return undefined;
-    }
-    if (numericValue in Object.values(ContrastProcessing)) {
-        return numericValue as ContrastProcessing;
-    }
-    return undefined;
-}
-
-export function parseSharpnessProcessing(value: string): SharpnessProcessing | undefined {
-    const numericValue = parseNumber(value);
-    if (numericValue === undefined) {
-        return undefined;
-    }
-    if (numericValue in Object.values(SharpnessProcessing)) {
-        return numericValue as SharpnessProcessing;
-    }
-    return undefined;
-}
-
-export function parseSubjectDistanceRange(value: string): SubjectDistanceRange | undefined {
-    const numericValue = parseNumber(value);
-    if (numericValue === undefined) {
-        return undefined;
-    }
-    if (numericValue in Object.values(SubjectDistanceRange)) {
-        return numericValue as SubjectDistanceRange;
-    }
-    return undefined;
-}
-
 export function ratioToTime(value: Ratio | undefined): string | undefined {
     if (value === undefined) {
         return undefined;
diff --git a/ui/src/metadata/LightSource.ts b/ui/src/metadata/LightSource.ts
index 46d3c65bd6f85046cccc392b73e9e9e1e32f971f..c119a032297884120ae0bbd45067a5ecfea4ea5f 100644
--- a/ui/src/metadata/LightSource.ts
+++ b/ui/src/metadata/LightSource.ts
@@ -1,3 +1,5 @@
+import {parseNumber} from "./ImageMetadata";
+
 export enum LightSource {
     DAYLIGHT = 1,
     FLUORESCENT = 2,
@@ -19,3 +21,14 @@ export enum LightSource {
     D50 = 23,
     ISO_STUDIO_INCANDESCENT = 24,
 }
+
+export function parseLightSource(value: string | undefined): LightSource | undefined {
+    const numericValue = parseNumber(value);
+    if (numericValue === undefined) {
+        return undefined;
+    }
+    if (Object.values(LightSource).includes(numericValue)) {
+        return numericValue as LightSource;
+    }
+    return undefined;
+}
diff --git a/ui/src/metadata/MeteringMode.ts b/ui/src/metadata/MeteringMode.ts
index 38572e86564c9815a7deccb94de441b3c11a2f4f..2ac111b6dae7f4c3ad6447f5c1309e0f46649186 100644
--- a/ui/src/metadata/MeteringMode.ts
+++ b/ui/src/metadata/MeteringMode.ts
@@ -1,3 +1,5 @@
+import {parseNumber} from "./ImageMetadata";
+
 export enum MeteringMode {
     AVERAGE = 1,
     CENTER_WEIGHTED_AVERAGE = 2,
@@ -6,3 +8,14 @@ export enum MeteringMode {
     PATTERN = 5,
     PARTIAL = 6,
 }
+
+export function parseMeteringMode(value: string | undefined): MeteringMode | undefined {
+    const numericValue = parseNumber(value);
+    if (numericValue === undefined) {
+        return undefined;
+    }
+    if (Object.values(MeteringMode).includes(numericValue)) {
+        return numericValue as MeteringMode;
+    }
+    return undefined;
+}
diff --git a/ui/src/metadata/Ratio.ts b/ui/src/metadata/Ratio.ts
index f5a3c5e4594e27ddbb607d0a13043fd1247068ac..e91d22e5020a25d4ad7360b1f0c72e913fbf5fe2 100644
--- a/ui/src/metadata/Ratio.ts
+++ b/ui/src/metadata/Ratio.ts
@@ -3,7 +3,10 @@ export interface Ratio {
     denominator: number
 }
 
-export function parseRatio(value: string): Ratio | undefined {
+export function parseRatio(value: string | undefined): Ratio | undefined {
+    if (value === undefined) {
+        return undefined;
+    }
     const splitValues = value.split("/");
     if (splitValues.length < 1) {
         return undefined;
diff --git a/ui/src/metadata/SceneMode.ts b/ui/src/metadata/SceneMode.ts
index 9c04599239fd45be6d5418e5873fe349d1e20dfc..def728207103a32a0fc7fda3eb15b0b4699a1532 100644
--- a/ui/src/metadata/SceneMode.ts
+++ b/ui/src/metadata/SceneMode.ts
@@ -1,6 +1,19 @@
+import {parseNumber} from "./ImageMetadata";
+
 export enum SceneMode {
     STANDARD = 0,
     LANDSCAPE = 1,
     PORTRAIT = 2,
     NIGHT_SCENE = 3,
 }
+
+export function parseSceneMode(value: string | undefined): SceneMode | undefined {
+    const numericValue = parseNumber(value);
+    if (numericValue === undefined) {
+        return undefined;
+    }
+    if (Object.values(SceneMode).includes(numericValue)) {
+        return numericValue as SceneMode;
+    }
+    return undefined;
+}
diff --git a/ui/src/metadata/SharpnessProcessing.ts b/ui/src/metadata/SharpnessProcessing.ts
index f8d0a5fd96c3e0418fc98c0dd4ca1e5eb8db9ad6..8183930bc42386b7d7ef43498246dd4347533f78 100644
--- a/ui/src/metadata/SharpnessProcessing.ts
+++ b/ui/src/metadata/SharpnessProcessing.ts
@@ -1,5 +1,18 @@
+import {parseNumber} from "./ImageMetadata";
+
 export enum SharpnessProcessing {
     NORMAL = 0,
     SOFT = 1,
     HARD = 2,
 }
+
+export function parseSharpnessProcessing(value: string | undefined): SharpnessProcessing | undefined {
+    const numericValue = parseNumber(value);
+    if (numericValue === undefined) {
+        return undefined;
+    }
+    if (Object.values(SharpnessProcessing).includes(numericValue)) {
+        return numericValue as SharpnessProcessing;
+    }
+    return undefined;
+}
diff --git a/ui/src/metadata/SubjectDistanceRange.ts b/ui/src/metadata/SubjectDistanceRange.ts
index f28a4b7a9b97e0987fad2b7783a60458eb3de425..0bd4b465bf500388236e70a29f9a987e92598d75 100644
--- a/ui/src/metadata/SubjectDistanceRange.ts
+++ b/ui/src/metadata/SubjectDistanceRange.ts
@@ -1,5 +1,18 @@
+import {parseNumber} from "./ImageMetadata";
+
 export enum SubjectDistanceRange {
     MACRO = 1,
     CLOSE = 2,
     DISTANT = 3,
 }
+
+export function parseSubjectDistanceRange(value: string | undefined): SubjectDistanceRange | undefined {
+    const numericValue = parseNumber(value);
+    if (numericValue === undefined) {
+        return undefined;
+    }
+    if (Object.values(SubjectDistanceRange).includes(numericValue)) {
+        return numericValue as SubjectDistanceRange;
+    }
+    return undefined;
+}
diff --git a/ui/src/metadata/WhiteBalance.ts b/ui/src/metadata/WhiteBalance.ts
index 7b13f42f16a531bb7b88dc225c3bed79068809d4..86a22ad4a43e254a500ec29b060e212b0008929b 100644
--- a/ui/src/metadata/WhiteBalance.ts
+++ b/ui/src/metadata/WhiteBalance.ts
@@ -1,4 +1,17 @@
+import {parseNumber} from "./ImageMetadata";
+
 export enum WhiteBalance {
     AUTO = 0,
     MANUAL = 1,
 }
+
+export function parseWhiteBalance(value: string | undefined): WhiteBalance | undefined {
+    const numericValue = parseNumber(value);
+    if (numericValue === undefined) {
+        return undefined;
+    }
+    if (Object.values(WhiteBalance).includes(numericValue)) {
+        return numericValue as WhiteBalance;
+    }
+    return undefined;
+}