takane
Validators for ArtifactDB file formats
Loading...
Searching...
No Matches
image_file.hpp
Go to the documentation of this file.
1#ifndef TAKANE_IMAGE_FILE_HPP
2#define TAKANE_IMAGE_FILE_HPP
3
4#include "utils_files.hpp"
5
6#include <filesystem>
7#include <stdexcept>
8#include <array>
9#include <string>
10
16namespace takane {
17
22namespace image_file {
23
27namespace internal {
28
29// Factored out for re-use in spatial_experiment::internal::validate_image.
30inline void validate_png(const std::filesystem::path& path) {
31 // Magic number from http://www.libpng.org/pub/png/spec/1.2/png-1.2-pdg.html#PNG-file-signature
32 constexpr std::array<unsigned char, 8> expected { 137, 80, 78, 71, 13, 10, 26, 10 };
33 internal_files::check_signature<byteme::RawFileReader>(path, expected.data(), expected.size(), "PNG");
34}
35
36inline void validate_tiff(const std::filesystem::path& path) {
37 std::array<unsigned char, 4> observed{};
38 internal_files::extract_signature(path, observed.data(), observed.size());
39 // Magic numbers from https://en.wikipedia.org/wiki/Magic_number_(programming)
40 constexpr std::array<unsigned char, 4> iisig { 0x49, 0x49, 0x2A, 0x00 };
41 constexpr std::array<unsigned char, 4> mmsig { 0x4D, 0x4D, 0x00, 0x2A };
42 if (observed != iisig && observed != mmsig) {
43 throw std::runtime_error("incorrect TIFF file signature for '" + path.string() + "'");
44 }
45}
46
47}
60inline void validate(const std::filesystem::path& path, const ObjectMetadata& metadata, Options& options) {
61 const std::string type_name = "image_file"; // use a separate variable to avoid dangling reference warnings from GCC.
62 const auto& obj = internal_json::extract_typed_object_from_metadata(metadata.other, type_name);
63
64 const std::string vname = "version";
65 const auto& vstring = internal_json::extract_string_from_typed_object(obj, vname, type_name);
66 auto version = ritsuko::parse_version_string(vstring.c_str(), vstring.size(), /* skip_patch = */ true);
67 if (version.major != 1) {
68 throw std::runtime_error("unsupported version string '" + vstring + "'");
69 }
70
71 const std::string format_name = "format";
72 const std::string& format = internal_json::extract_string(obj, format_name);
73 const std::string prefix = (path / "file").string();
74
75 if (format == "PNG") {
76 const std::filesystem::path ipath = prefix + ".png";
77 internal::validate_png(ipath);
78
79 } else if (format == "TIFF") {
80 const std::filesystem::path ipath = prefix + ".tif";
81 internal::validate_tiff(ipath);
82
83 } else if (format == "JPEG") {
84 auto ipath = prefix + ".jpg";
85 // Common prefix of the JPEG-related magic numbers from https://en.wikipedia.org/wiki/List_of_file_signatures
86 constexpr std::array<unsigned char, 2> expected { 0xFF, 0xD8 };
87 internal_files::check_signature<byteme::RawFileReader>(ipath, expected.data(), expected.size(), "JPEG");
88
89 } else if (format == "GIF") {
90 auto ipath = prefix + ".gif";
91 // Common prefix of the old and new magic numbers from https://en.wikipedia.org/wiki/GIF
92 constexpr std::array<unsigned char, 4> expected{ 0x47, 0x49, 0x46, 0x38 };
93 internal_files::check_signature<byteme::RawFileReader>(ipath, expected.data(), expected.size(), "GIF");
94
95 } else if (format == "WEBP") {
96 auto ipath = prefix + ".webp";
97 std::array<unsigned char, 12> observed;
98 internal_files::extract_signature(ipath, observed.data(), observed.size());
99 constexpr std::array<unsigned char, 4> first4 { 0x52, 0x49, 0x46, 0x46 };
100 constexpr std::array<unsigned char, 4> last4 { 0x57, 0x45, 0x42, 0x50 };
101 std::array<unsigned char, 4> observed_first, observed_last;
102 std::copy_n(observed.begin(), 4, observed_first.begin());
103 std::copy_n(observed.begin() + 8, 4, observed_last.begin());
104 if (observed_first != first4 || observed_last != last4) {
105 throw std::runtime_error("incorrect WEBP file signature for '" + ipath + "'");
106 }
107
108 } else {
109 throw std::runtime_error("unsupported format '" + format + "'");
110 }
111
112 if (options.image_file_strict_check) {
113 options.image_file_strict_check(path, metadata, options);
114 }
115}
116
117}
118
119}
120
121#endif
122
void validate(const std::filesystem::path &path, const ObjectMetadata &metadata, Options &options)
Definition image_file.hpp:60
takane validation functions.
Definition _derived_from.hpp:15
Object metadata, including the type and other fields.
Definition utils_public.hpp:26
std::unordered_map< std::string, std::shared_ptr< millijson::Base > > other
Definition utils_public.hpp:35
Validation options.
Definition utils_public.hpp:94
std::function< void(const std::filesystem::path &, const ObjectMetadata &, Options &)> image_file_strict_check
Definition utils_public.hpp:241