diff --git a/src/h5schemas/load_utilities/projection.py b/src/h5schemas/load_utilities/projection.py
new file mode 100644
index 0000000000000000000000000000000000000000..d644d101f1f6af6d48a36fa1e8f6d1d181d6ebc3
--- /dev/null
+++ b/src/h5schemas/load_utilities/projection.py
@@ -0,0 +1,56 @@
+from h5schemas.load_utilities.projection_geometry import extract_projection_geometry, ProjectionGeometry
+from h5py import Group
+import numpy as np
+from typing import NamedTuple, ClassVar, Literal
+from dataclasses import dataclass
+
+
+@dataclass
+class GeomOptions:
+    PROJECTION_GEOMETRY: ClassVar[str] = "projection_geometry"
+    PROJECTION_GEOMETRY_NOMINAL: ClassVar[str] = "projection_geometry_nominal"
+
+
+DEFAULT = "projection_geometry"
+NOMINAL = "projection_geometry_nominal"
+GeomElement = Literal[DEFAULT, NOMINAL]
+
+
+class Projection(NamedTuple):
+    projection_geometry: ProjectionGeometry
+    image_array: np.ndarray
+
+    uuid: np.ndarray
+    timestamp: np.ndarray
+
+
+def extract_projection(h5_group: Group, indices: slice | int, projection_geometry_group: str = GeomOptions.PROJECTION_GEOMETRY, crop: list[slice] | None = None) -> Projection:
+    if crop is None:
+        crop = (slice(0, None, 1), slice(0, None, 1))
+    if len(crop) != 3 and isinstance(indices, slice):
+        crop = (slice(0, None), crop[0], crop[1])
+
+    projection_geometry = extract_projection_geometry(h5_group[projection_geometry_group], indices)
+    uuid = h5_group["image"]["header"]["uuid"][indices]
+    timestamp = h5_group["image"]["header"]["timestamp"][indices]
+    image = h5_group["image"]["image_array"][indices][crop]
+
+    return Projection(
+        projection_geometry,
+        image,
+        uuid,
+        timestamp,
+    )
+
+
+if __name__ == "__main__":
+    from h5py import File
+
+    test_file = File("./examples/projection.h5", "r")
+    projection = extract_projection(test_file, 1, GeomOptions.PROJECTION_GEOMETRY)
+    print(projection)
+    print(projection.image_array.shape)
+
+    projection = extract_projection(test_file, slice(0, 2), GeomOptions.PROJECTION_GEOMETRY, crop=(slice(20, 50), slice(50, 100)))
+    print(projection)
+    print(projection.image_array.shape)
diff --git a/src/h5schemas/load_utilities/projection_geometry.py b/src/h5schemas/load_utilities/projection_geometry.py
index 9d2a6472dc2dc50d6d6bc830ead175747c1b76a2..9fc22e490ffd3531b5cd0445a732115e30f91d1a 100644
--- a/src/h5schemas/load_utilities/projection_geometry.py
+++ b/src/h5schemas/load_utilities/projection_geometry.py
@@ -14,7 +14,7 @@ class ProjectionGeometry(NamedTuple):
     timestamp: np.ndarray
 
 
-def extract_projection_geometry(h5_group: Group, indices: slice) -> ProjectionGeometry:
+def extract_projection_geometry(h5_group: Group, indices: slice | int) -> ProjectionGeometry:
     detector_center_position_mm = extract_vector(
         h5_group["detector_center_position_mm"], indices, CommonVectors.XYZ
     )