rawler-0.7.1/.cargo_vcs_info.json0000644000000001670000000000100123410ustar { "git": { "sha1": "2878c582de51c8f4cdf5dbb4ce7ae47a1de853ea", "dirty": true }, "path_in_vcs": "rawler" }rawler-0.7.1/.gitignore000064400000000000000000000000221046102023000131070ustar 00000000000000target Cargo.lock rawler-0.7.1/Cargo.lock0000644000001273360000000000100103240ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "addr2line" version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] name = "adler2" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "adler32" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] name = "ahash" version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", "once_cell", "version_check", "zerocopy", ] [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "alloc-no-stdlib" version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" dependencies = [ "alloc-no-stdlib", ] [[package]] name = "allocator-api2" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "anes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", "once_cell_polyfill", "windows-sys", ] [[package]] name = "anyhow" version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "approx" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" dependencies = [ "num-traits", ] [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", "windows-targets", ] [[package]] name = "bitflags" version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bitstream-io" version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b348c85aeb6d0bb7dee47de5506b587d9c6c17856d1314eb4695ad751edc7231" dependencies = [ "core2", ] [[package]] name = "brotli-decompressor" version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", ] [[package]] name = "bumpalo" version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "byteorder-lite" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" version = "1.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" dependencies = [ "shlex", ] [[package]] name = "cfg-if" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "chrono" version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", "windows-link", ] [[package]] name = "ciborium" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", "serde", ] [[package]] name = "ciborium-io" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", ] [[package]] name = "clap" version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", ] [[package]] name = "clap_lex" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "colorchoice" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core2" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" dependencies = [ "memchr", ] [[package]] name = "crc32fast" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "criterion" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" dependencies = [ "anes", "cast", "ciborium", "clap", "criterion-plot", "itertools 0.13.0", "num-traits", "oorandom", "plotters", "rayon", "regex", "serde", "serde_json", "tinytemplate", "walkdir", ] [[package]] name = "criterion-plot" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" dependencies = [ "cast", "itertools 0.13.0", ] [[package]] name = "crossbeam-deque" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "dary_heap" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04d2cd9c18b9f454ed67da600630b021a8a80bf33f8c95896ab33aaf1c26b728" [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "enumn" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "env_filter" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", "regex", ] [[package]] name = "env_logger" version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", "env_filter", "jiff", "log", ] [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "getrandom" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", "r-efi", "wasi", ] [[package]] name = "gimli" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "half" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ "cfg-if", "crunchy", ] [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", ] [[package]] name = "hashbrown" version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "iana-time-zone" version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "log", "wasm-bindgen", "windows-core", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ "cc", ] [[package]] name = "image" version = "0.25.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" dependencies = [ "bytemuck", "byteorder-lite", "num-traits", "zune-core", "zune-jpeg", ] [[package]] name = "indexmap" version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", ] [[package]] name = "indexmap" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown 0.15.4", ] [[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itertools" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" dependencies = [ "jiff-static", "log", "portable-atomic", "portable-atomic-util", "serde", ] [[package]] name = "jiff-static" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "js-sys" version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", ] [[package]] name = "jxl-bitstream" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda699770a7f4ea38f8eb21d91b545eb6448be28e540acc7ce84498bcead4903" dependencies = [ "tracing", ] [[package]] name = "jxl-coding" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6748ba8af69b87c68f8dcdf992de959c207962689bc28ddb7906abf4a0b786c9" dependencies = [ "jxl-bitstream", "tracing", ] [[package]] name = "jxl-color" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f316b1358c1711755b3ee8e8cb5c4a1dad12e796233088a7a513440782de80b2" dependencies = [ "jxl-bitstream", "jxl-coding", "jxl-grid", "jxl-image", "jxl-oxide-common", "jxl-threadpool", "tracing", ] [[package]] name = "jxl-frame" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f30587a9687223a602a408555db47803c907ea47700e1f28eb14cdb3bf1527a9" dependencies = [ "jxl-bitstream", "jxl-coding", "jxl-grid", "jxl-image", "jxl-modular", "jxl-oxide-common", "jxl-threadpool", "jxl-vardct", "tracing", ] [[package]] name = "jxl-grid" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335e4371396c5729ba80a42798746d198897d3b854ba4f3684efac5f4025d84f" dependencies = [ "tracing", ] [[package]] name = "jxl-image" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5f752d62577c702a94dbbce4045caf08cb58639e8a4d56464b40ecf33ffe565" dependencies = [ "jxl-bitstream", "jxl-grid", "jxl-oxide-common", "tracing", ] [[package]] name = "jxl-jbr" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ba39b083a82788a17717edbcc4b08160b51fdffc9fec640deba9e8268da1a" dependencies = [ "brotli-decompressor", "jxl-bitstream", "jxl-frame", "jxl-grid", "jxl-image", "jxl-modular", "jxl-oxide-common", "jxl-threadpool", "jxl-vardct", "tracing", ] [[package]] name = "jxl-modular" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f526ad8af8daea0d1cccce945f18c241f95b391d34443be018de2efbf28b44e" dependencies = [ "jxl-bitstream", "jxl-coding", "jxl-grid", "jxl-oxide-common", "jxl-threadpool", "tracing", ] [[package]] name = "jxl-oxide" version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e45ccb25d698cdcad3a5573a7181835842711fd951c98fe38986e3cb721e775" dependencies = [ "brotli-decompressor", "jxl-bitstream", "jxl-color", "jxl-frame", "jxl-grid", "jxl-image", "jxl-jbr", "jxl-oxide-common", "jxl-render", "jxl-threadpool", "tracing", ] [[package]] name = "jxl-oxide-common" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62394c5021b3a9e7e0dbb2d639d555d019090c9946c39f6d3b09d390db4157b" dependencies = [ "jxl-bitstream", ] [[package]] name = "jxl-render" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3f3fece78b2104450bd6d1bdbc48e3b6ef7442ef276be2a08e35b229eeff1a4" dependencies = [ "bytemuck", "jxl-bitstream", "jxl-coding", "jxl-color", "jxl-frame", "jxl-grid", "jxl-image", "jxl-modular", "jxl-oxide-common", "jxl-threadpool", "jxl-vardct", "tracing", ] [[package]] name = "jxl-threadpool" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25f15eb830aa77a7f21148d72e153562a26bfe570139bd4922eab1908dd499d3" dependencies = [ "rayon", "rayon-core", "tracing", ] [[package]] name = "jxl-vardct" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d48ad406543de5d6cd50aaaa8b87534f82991d684d848b3190228e8fa690fff" dependencies = [ "jxl-bitstream", "jxl-coding", "jxl-grid", "jxl-modular", "jxl-oxide-common", "jxl-threadpool", "tracing", ] [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libflate" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45d9dfdc14ea4ef0900c1cddbc8dcd553fbaacd8a4a282cf4018ae9dd04fb21e" dependencies = [ "adler32", "core2", "crc32fast", "dary_heap", "libflate_lz77", ] [[package]] name = "libflate_lz77" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e0d73b369f386f1c44abd9c570d5318f55ccde816ff4b562fa452e5182863d" dependencies = [ "core2", "hashbrown 0.14.5", "rle-decode-fast", ] [[package]] name = "linked-hash-map" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "log" version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "md5" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" [[package]] name = "memchr" version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memmap2" version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" dependencies = [ "libc", ] [[package]] name = "miniz_oxide" version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] [[package]] name = "multiversion" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edb7f0ff51249dfda9ab96b5823695e15a052dc15074c9dbf3d118afaf2c201" dependencies = [ "multiversion-macros", "target-features", ] [[package]] name = "multiversion-macros" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b093064383341eb3271f42e381cb8f10a01459478446953953c75d24bd339fc0" dependencies = [ "proc-macro2", "quote", "syn", "target-features", ] [[package]] name = "num" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", "num-integer", "num-iter", "num-rational", "num-traits", ] [[package]] name = "num-bigint" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", ] [[package]] name = "num-complex" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] [[package]] name = "num-integer" version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ "num-traits", ] [[package]] name = "num-iter" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-rational" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ "num-bigint", "num-integer", "num-traits", ] [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "num_enum" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" dependencies = [ "num_enum_derive", "rustversion", ] [[package]] name = "num_enum_derive" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", "syn", ] [[package]] name = "object" version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "oorandom" version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "pin-project-lite" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "plotters" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", "plotters-svg", "wasm-bindgen", "web-sys", ] [[package]] name = "plotters-backend" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] [[package]] name = "portable-atomic" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portable-atomic-util" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" dependencies = [ "portable-atomic", ] [[package]] name = "proc-macro-crate" version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" dependencies = [ "toml_edit", ] [[package]] name = "proc-macro2" version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rawler" version = "0.7.1" dependencies = [ "anyhow", "approx", "backtrace", "bitstream-io", "byteorder", "chrono", "clap", "criterion", "enumn", "env_logger", "glob", "hex", "image", "itertools 0.14.0", "jxl-oxide", "lazy_static", "libflate", "log", "md5", "memmap2", "multiversion", "num", "num_enum", "rayon", "rustc_version", "serde", "serde_yaml", "thiserror", "toml", "uuid", "weezl", "zerocopy", ] [[package]] name = "rayon" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] [[package]] name = "regex" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rle-decode-fast" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" [[package]] name = "rustc-demangle" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustversion" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "semver" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" dependencies = [ "itoa", "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] [[package]] name = "serde_yaml" version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ "indexmap 1.9.3", "ryu", "serde", "yaml-rust", ] [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "target-features" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1bbb9f3c5c463a01705937a24fdabc5047929ac764b2d5b9cf681c1f5041ed5" [[package]] name = "thiserror" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tinytemplate" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ "serde", "serde_json", ] [[package]] name = "toml" version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", "toml_datetime", "toml_edit", ] [[package]] name = "toml_datetime" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap 2.10.0", "serde", "serde_spanned", "toml_datetime", "toml_write", "winnow", ] [[package]] name = "toml_write" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tracing" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", ] [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ "getrandom", "js-sys", "serde", "wasm-bindgen", ] [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", ] [[package]] name = "wasi" version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] [[package]] name = "wasm-bindgen" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "weezl" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" [[package]] name = "winapi-util" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys", ] [[package]] name = "windows-core" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-implement" version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "windows-interface" version = "0.59.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "windows-link" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-result" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" dependencies = [ "memchr", ] [[package]] name = "wit-bindgen-rt" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ "bitflags", ] [[package]] name = "yaml-rust" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] [[package]] name = "zerocopy" version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "zune-core" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" [[package]] name = "zune-jpeg" version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c9e525af0a6a658e031e95f14b7f889976b74a11ba0eca5a5fc9ac8a1c43a6a" dependencies = [ "zune-core", ] rawler-0.7.1/Cargo.toml0000644000000057310000000000100103410ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2024" rust-version = "1.87" name = "rawler" version = "0.7.1" authors = [ "Daniel Vogelbacher ", "Pedro Côrte-Real ", ] build = "data/join.rs" autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "A library to extract images and metadata from camera raw formats" homepage = "https://github.com/dnglab/dnglab" readme = "README.md" keywords = [ "camera", "raw", ] categories = ["multimedia::images"] license = "LGPL-2.1" repository = "https://github.com/dnglab/dnglab" resolver = "2" [features] clap = ["dep:clap"] inspector = [] samplecheck = [] [lib] name = "rawler" path = "src/lib.rs" [[bin]] name = "benchmark" path = "src/bin/benchmark.rs" [[bin]] name = "identify" path = "src/bin/identify.rs" [[test]] name = "mod" path = "tests/mod.rs" [[bench]] name = "perf" path = "benches/perf.rs" harness = false [[bench]] name = "raw_decoder" path = "benches/raw_decoder.rs" harness = false [dependencies.backtrace] version = "0.3" [dependencies.bitstream-io] version = "4.1" [dependencies.byteorder] version = "1" [dependencies.chrono] version = "0.4" [dependencies.clap] version = "4.4.0" optional = true [dependencies.enumn] version = "0.1" [dependencies.hex] version = "0.4" [dependencies.image] version = "0.25" features = ["jpeg"] default-features = false [dependencies.itertools] version = "0.14" [dependencies.jxl-oxide] version = "0.12.2" [dependencies.lazy_static] version = "1" [dependencies.libflate] version = "2.0" [dependencies.log] version = "0.4" [dependencies.md5] version = "0.8" [dependencies.memmap2] version = "0.9.4" [dependencies.multiversion] version = "0.8" [dependencies.num] version = "0.4" [dependencies.num_enum] version = "0.7" [dependencies.rayon] version = "1" [dependencies.serde] version = "1.0" features = ["derive"] [dependencies.thiserror] version = "2.0" [dependencies.toml] version = "0.8" [dependencies.uuid] version = "1.0" features = [ "serde", "v4", ] [dependencies.weezl] version = "0.1.7" [dependencies.zerocopy] version = "0.8.26" features = ["derive"] [dev-dependencies.anyhow] version = "1.0" [dev-dependencies.approx] version = "0.5.1" [dev-dependencies.criterion] version = "0.7" features = ["html_reports"] [dev-dependencies.env_logger] version = "0.11" [dev-dependencies.serde_yaml] version = "=0.8" [build-dependencies.glob] version = "0.3" [build-dependencies.rustc_version] version = "0.4" [build-dependencies.toml] version = "=0.8" rawler-0.7.1/Cargo.toml.orig000064400000000000000000000036041046102023000140170ustar 00000000000000[package] authors = ["Daniel Vogelbacher ", "Pedro Côrte-Real "] categories = ["multimedia::images"] description = "A library to extract images and metadata from camera raw formats" readme = "README.md" edition = "2024" homepage = "https://github.com/dnglab/dnglab" keywords = ["camera", "raw"] license = "LGPL-2.1" name = "rawler" repository = "https://github.com/dnglab/dnglab" rust-version = "1.87" version = "0.7.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html build = "data/join.rs" [features] # This is a developer feature, it enabled deep inspection of algorithm execution stages clap = ["dep:clap"] #default = ["samplecheck"] inspector = [] samplecheck = [] [dependencies] backtrace = "0.3" bitstream-io = "4.1" byteorder = "1" chrono = "0.4" clap = { version = "4.4.0", optional = true } enumn = "0.1" hex = "0.4" image = { version = "0.25", default-features = false, features = ["jpeg"] } itertools = "0.14" lazy_static = "1" jxl-oxide = "0.12.2" libflate = "2.0" log = "0.4" md5 = "0.8" num = "0.4" multiversion = "0.8" num_enum = "0.7" rayon = "1" zerocopy = { version = "0.8.26", features = ["derive"] } serde = { version = "1.0", features = ["derive"] } thiserror = "2.0" toml = "0.8" uuid = { version = "1.0", features = ["serde", "v4"] } weezl = "0.1.7" memmap2 = "0.9.4" [dev-dependencies] criterion = { version = "0.7", features = ["html_reports"] } env_logger = "0.11" serde_yaml = "=0.8" # TODO - breaks camera tests, update to 0.9 when fixed anyhow = "1.0" approx = "0.5.1" [build-dependencies] glob = "0.3" rustc_version = "0.4" toml = "=0.8" # TODO - Updating breaks `join.rs` build script with message - Error parsing "data/cameras/apple/quicktake100.toml": message: "unexpected content, expected nothing", [[bench]] harness = false name = "perf" [[bench]] harness = false name = "raw_decoder" rawler-0.7.1/LICENSE000064400000000000000000000635121046102023000121410ustar 00000000000000GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. (This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.) Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {description} Copyright (C) {year} {fullname} This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. {signature of Ty Coon}, 1 April 1990 Ty Coon, President of Vice That's all there is to it!rawler-0.7.1/README.md000064400000000000000000000010531046102023000124030ustar 00000000000000# Rawler Digital camera raw format library ## What is Rawler? Rawler parses raw file formats and provides access to the pixels and all metadata. ## Why is it named rawler? It's a (c)rawler, just for raw file structures. ## Why another raw library? * There are libraries dealing with metadata (exiv2) and for pixels (rawspeed, libraw), but not for both. Each library ships their own file structure parsers. * rawloader, which is basically the fundament of this library, is a pretty good library, but lacks of support for metadata. * For fun. rawler-0.7.1/benches/perf.rs000064400000000000000000000027521046102023000140440ustar 00000000000000use criterion::{Criterion, criterion_group, criterion_main}; use rawler::ljpeg92::LjpegCompressor; use std::hint::black_box; fn generate_data(w: usize, h: usize, ncomp: usize) -> Vec { let mut img = vec![0; w * h * ncomp]; for (i, pix) in img.iter_mut().enumerate() { *pix = i as u16 % 4u16; } img } fn encode_ljpeg(img: &[u16], w: usize, h: usize, ncomp: usize) { let pred = 1; let bps = 16; let state = LjpegCompressor::new(img, w, h, ncomp, bps, pred, 0, 0).unwrap(); let _result = state.encode().unwrap(); } fn copy_data(img: &[u16], w: usize, h: usize) { let mut result = vec![0; w * h]; for (dst, src) in result.chunks_exact_mut(w).zip(img.chunks_exact(w)) { dst.copy_from_slice(src); } } fn criterion_benchmark(c: &mut Criterion) { let mut group = c.benchmark_group("ljpeg-encoder"); // Configure Criterion.rs to detect smaller differences and increase sample size to improve // precision and counteract the resulting noise. group.significance_level(0.1).sample_size(20); //.measurement_time(Duration::from_secs(10)); let x = generate_data(3000, 2000, 1); group.bench_with_input("encode_3000x2000", &x, |b, data| { b.iter(|| encode_ljpeg(black_box(data), black_box(3000), black_box(2000), black_box(1))) }); group.bench_with_input("copy_3000x2000", &x, |b, data| { b.iter(|| copy_data(black_box(data), black_box(3000), black_box(2000))) }); group.finish(); } criterion_group!(benches, criterion_benchmark); criterion_main!(benches); rawler-0.7.1/benches/raw_decoder.rs000064400000000000000000000064011046102023000153610ustar 00000000000000use criterion::{BenchmarkGroup, Criterion, criterion_group, criterion_main, measurement::WallTime}; use rawler::{decoders::RawDecodeParams, rawsource::RawSource}; use std::{hint::black_box, path::PathBuf, time::Duration}; fn rawdb_sample(sample: &str) -> PathBuf { let mut path = PathBuf::from(std::env::var("RAWLER_RAWDB").expect("RAWLER_RAWDB variable must be set in order to run RAW test!")); path.push(sample); if !path.exists() { eprintln!("Sample \"{}\" not found", path.display()); } path } fn bench_raw_image(group: &mut BenchmarkGroup<'_, WallTime>, name: &str, sample: &str) { let mut inner = || -> anyhow::Result<()> { let sample = rawdb_sample(sample); let rawfile = RawSource::new(&sample)?; let decoder = rawler::get_decoder(&rawfile)?; group.bench_with_input(name, &rawfile, |b, rawfile| { b.iter(|| { decoder .raw_image(black_box(rawfile), black_box(&RawDecodeParams::default()), black_box(false)) .expect("Decoder failed") }) }); Ok(()) }; if let Err(err) = inner() { eprintln!("Warning: Bench failed: {:?}", err); } } fn decoding_raw_frame(c: &mut Criterion) { let mut group = c.benchmark_group("decoding-raw-frame"); // Configure Criterion.rs to detect smaller differences and increase sample size to improve // precision and counteract the resulting noise. group.significance_level(0.1).sample_size(20).measurement_time(Duration::from_secs(10)); bench_raw_image( &mut group, "decode_canon_eos_5dmk3_raw", "cameras/Canon/EOS 5D Mark III/raw_modes/Canon EOS 5D Mark III_RAW_ISO_200.CR2", ); bench_raw_image( &mut group, "decode_canon_eos_5dmk3_sraw1", "cameras/Canon/EOS 5D Mark III/raw_modes/Canon EOS 5D Mark III_sRAW1_ISO_200.CR2", ); bench_raw_image( &mut group, "decode_canon_eos_5dmk3_sraw2", "cameras/Canon/EOS 5D Mark III/raw_modes/Canon EOS 5D Mark III_sRAW2_ISO_200.CR2", ); bench_raw_image( &mut group, "decode_canon_eos_r6_raw", "cameras/Canon/EOS R6/raw_modes/Canon EOS R6_RAW_ISO_100_nocrop_nodual.CR3", ); bench_raw_image( &mut group, "decode_canon_eos_r6_craw", "cameras/Canon/EOS R6/raw_modes/Canon EOS R6_CRAW_ISO_100_nocrop_nodual.CR3", ); bench_raw_image(&mut group, "decode_dng_ljpeg_tiles", "dng/compression-sets/ljpeg_tiles.dng"); bench_raw_image(&mut group, "decode_dng_10bit", "dng/compression-sets/10bit.dng"); bench_raw_image(&mut group, "decode_dng_12bit", "dng/compression-sets/12bit.dng"); bench_raw_image(&mut group, "decode_dng_16bit_be", "dng/compression-sets/16bit_bigend.dng"); bench_raw_image(&mut group, "decode_dng_8bit_lintable", "dng/compression-sets/8bit_lintable.dng"); bench_raw_image(&mut group, "decode_dng_ljpeg_singlestrip", "dng/compression-sets/ljpeg_singlestrip.dng"); bench_raw_image(&mut group, "decode_dng_lossy_jpeg_tiles", "dng/compression-sets/lossy_tiles.dng"); bench_raw_image( &mut group, "decode_dng_uncomp_multistrip_16rows", "dng/compression-sets/uncompressed_multistrip_16row.dng", ); bench_raw_image( &mut group, "decode_dng_uncomp_multistrip_1row", "dng/compression-sets/uncompressed_multistrip_1row.dng", ); group.finish(); } criterion_group!(benches, decoding_raw_frame); criterion_main!(benches); rawler-0.7.1/data/cameras/apple/quicktake100.toml000064400000000000000000000003641046102023000176540ustar 00000000000000make = "Apple" model = "QuickTake 100" clean_make = "Apple" clean_model = "QuickTake 100" blackpoint = 0 whitepoint = 1023 color_pattern = "GRBG" [cameras.color_matrix] D65 = [2.1392,-0.5653,-0.3353,0.2406,0.8010,-0.0415,0.7166,0.1427,0.2078] rawler-0.7.1/data/cameras/apple/quicktake150.toml000064400000000000000000000003651046102023000176620ustar 00000000000000make = "Apple" model = "QuickTake 150" clean_make = "Apple" clean_model = "QuickTake 150" blackpoint = 0 whitepoint = 16383 color_pattern = "GRBG" [cameras.color_matrix] D65 = [2.1392,-0.5653,-0.3353,0.2406,0.8010,-0.0415,0.7166,0.1427,0.2078] rawler-0.7.1/data/cameras/arri/alexa.toml000064400000000000000000000004561046102023000164020ustar 00000000000000make = "ARRI" model = "ALEXA" clean_make = "ARRI" clean_model = "ALEXA" blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" #crops = [0,0,0,0] # we don't have a matrix so use sRGB [cameras.color_matrix] D65 = [3.24045, -1.53713, -0.49853, -0.96926, 1.87601, 0.04155, 0.05564, -0.20402, 1.05722] rawler-0.7.1/data/cameras/arri/alexa_65.toml000064400000000000000000000004631046102023000167120ustar 00000000000000make = "ARRI" model = "ALEXA65" clean_make = "ARRI" clean_model = "ALEXA 65" blackpoint = 0 whitepoint = 4095 color_pattern = "GBRG" #crops = [0,0,0,0] # we don't have a matrix so use sRGB [cameras.color_matrix] D65 = [3.24045, -1.53713, -0.49853, -0.96926, 1.87601, 0.04155, 0.05564, -0.20402, 1.05722] rawler-0.7.1/data/cameras/arri/alexa_lf.toml000064400000000000000000000004631046102023000170610ustar 00000000000000make = "ARRI" model = "ALEXALF" clean_make = "ARRI" clean_model = "ALEXA LF" blackpoint = 0 whitepoint = 4095 color_pattern = "GBRG" #crops = [0,0,0,0] # we don't have a matrix so use sRGB [cameras.color_matrix] D65 = [3.24045, -1.53713, -0.49853, -0.96926, 1.87601, 0.04155, 0.05564, -0.20402, 1.05722] rawler-0.7.1/data/cameras/arri/alexa_mini.toml000064400000000000000000000004731046102023000174150ustar 00000000000000make = "ARRI" model = "A-MINI" clean_make = "ARRI" clean_model = "ALEXA Mini" blackpoint = 0 whitepoint = 4095 color_pattern = "BGGR" hints = ["little-endian"] # we don't have a matrix so use sRGB [cameras.color_matrix] D65 = [3.24045, -1.53713, -0.49853, -0.96926, 1.87601, 0.04155, 0.05564, -0.20402, 1.05722] rawler-0.7.1/data/cameras/canon/1000d.toml000064400000000000000000000011041046102023000161640ustar 00000000000000make = "Canon" model = "Canon EOS 1000D" clean_make = "Canon" clean_model = "EOS 1000D" model_aliases = [ ["Canon EOS DIGITAL REBEL XS", "Rebel XS"], ["Canon EOS REBEL XS", "Rebel XS"], ["Canon EOS Kiss Digital F", "Kiss F"], ["Canon EOS Kiss F", "Kiss F"], ] hints = ["invalid_blacklevel"] color_pattern = "RGGB" blackareav = [0, 41] active_area = [42, 18, 0, 2] [cameras.color_matrix] A = [0.7599, -0.2192, -0.0386, -0.6082, 1.2908, 0.3584, -0.0068, 0.0963, 0.7356] # TODO check both D65 = [0.6772, -0.0114, -0.0977, -0.7818, 1.5123, 0.2927, -0.1244, 0.1437, 0.7533] rawler-0.7.1/data/cameras/canon/100d.toml000064400000000000000000000010561046102023000161120ustar 00000000000000make = "Canon" model = "Canon EOS 100D" clean_make = "Canon" clean_model = "EOS 100D" model_aliases = [ ["Canon EOS DIGITAL REBEL SL1", "Rebel SL1"], ["Canon EOS REBEL SL1", "Rebel SL1"], ["Canon EOS Kiss Digital X7", "Kiss X7"], ["Canon EOS Kiss X7", "Kiss X7"], ] color_pattern = "RGGB" blackareav = [0, 72] blackareah = [8, 44] active_area = [72, 52, 0, 0] [cameras.color_matrix] A = [0.6985, -0.1611, -0.0397, -0.3596, 1.0749, 0.3295, -0.0349, 0.1136, 0.6512] D65 = [0.6602, -0.0841, -0.0939, -0.4472, 1.2458, 0.2247, -0.0975, 0.2039, 0.6148] rawler-0.7.1/data/cameras/canon/10d.toml000064400000000000000000000006131046102023000160300ustar 00000000000000# CRW make = "Canon" model = "Canon EOS 10D" clean_make = "Canon" clean_model = "EOS 10D" blackpoint = 124 whitepoint = 4000 color_pattern = "RGGB" active_area = [64, 12, 0, 0] [cameras.color_matrix] A = [0.912, -0.3127, -0.0453, -0.6868, 1.4138, 0.3011, -0.1708, 0.2368, 0.9501] D65 = [0.825, -0.2044, -0.1127, -0.8092, 1.5606, 0.2664, -0.2893, 0.3453, 0.8348] [cameras.params] wb_offset = 1 rawler-0.7.1/data/cameras/canon/1100d.toml000064400000000000000000000010331046102023000161660ustar 00000000000000make = "Canon" model = "Canon EOS 1100D" clean_make = "Canon" clean_model = "EOS 1100D" model_aliases = [ ["Canon EOS DIGITAL REBEL T3", "Rebel T3"], ["Canon EOS REBEL T3", "Rebel T3"], ["Canon EOS Kiss Digital X50", "Kiss X50"], ["Canon EOS Kiss X50", "Kiss X50"], ] color_pattern = "RGGB" blackareav = [0, 58] active_area = [62, 18, 0, 0] [cameras.color_matrix] A = [0.6873, -0.1696, -0.0529, -0.3659, 1.0795, 0.3313, -0.0362, 0.1165, 0.7234] D65 = [0.6444, -0.0904, -0.0893, -0.4563, 1.2308, 0.2535, -0.0903, 0.2016, 0.6728] rawler-0.7.1/data/cameras/canon/1200d.toml000064400000000000000000000010541046102023000161720ustar 00000000000000make = "Canon" model = "Canon EOS 1200D" clean_make = "Canon" clean_model = "EOS 1200D" model_aliases = [ ["Canon EOS DIGITAL REBEL T5", "Rebel T5"], ["Canon EOS REBEL T5", "Rebel T5"], ["Canon EOS Kiss Digital X70", "Kiss X70"], ["Canon EOS Kiss X70", "Kiss X70"], ] color_pattern = "GBRG" blackareav = [0, 140] blackareah = [4, 44] active_area = [142, 51, 0, 0] [cameras.color_matrix] A = [0.7164, -0.1916, -0.0431, -0.3361, 1.06, 0.32, -0.0272, 0.1058, 0.6442] D65 = [0.6461, -0.0907, -0.0882, -0.43, 1.2184, 0.2378, -0.0819, 0.1944, 0.5931] rawler-0.7.1/data/cameras/canon/1300d.toml000064400000000000000000000011051046102023000161700ustar 00000000000000make = "Canon" model = "Canon EOS 1300D" clean_make = "Canon" clean_model = "Canon EOS 1300D" model_aliases = [ ["Canon EOS DIGITAL REBEL T6", "Rebel T6"], ["Canon EOS REBEL T6", "Rebel T6"], ["Canon EOS Rebel T6", "Rebel T6"], ["Canon EOS Kiss Digital X80", "Kiss X80"], ["Canon EOS Kiss X80", "Kiss X80"], ] color_pattern = "GBRG" blackareav = [0,140] active_area = [142, 51, 0, 0] [cameras.color_matrix] A = [0.77, -0.2142, -0.0096, -0.3513, 1.1072, 0.2806, -0.044, 0.1286, 0.6707] D65 = [0.6939, -0.1016, -0.0866, -0.4428, 1.2473, 0.2177, -0.1175, 0.2178, 0.6162] rawler-0.7.1/data/cameras/canon/1d.toml000064400000000000000000000004151046102023000157500ustar 00000000000000make = "Canon" model = "Canon EOS-1D" clean_make = "Canon" clean_model = "EOS-1D" blackpoint = 0 whitepoint = 3588 color_pattern = "GRBG" hints = ["double_line"] [cameras.color_matrix] D65 = [0.6806, -0.0179, -0.1020, -0.8097, 1.6415, 0.1687, -0.3267, 0.4236, 0.7690] rawler-0.7.1/data/cameras/canon/1dm2.toml000064400000000000000000000006311046102023000162070ustar 00000000000000make = "Canon" model = "Canon EOS-1D Mark II" clean_make = "Canon" clean_model = "EOS-1D Mark II" whitepoint = 3700 color_pattern = "RGGB" active_area = [74, 12, 0, 0] blackareav = [0, 72] [cameras.params] wb_offset = 34 [cameras.color_matrix] A = [0.718, -0.1623, -0.0246, -0.6795, 1.4095, 0.2977, -0.0978, 0.1327, 0.8537] D65 = [0.6264, -0.0582, -0.0724, -0.8312, 1.5948, 0.2505, -0.1743, 0.1919, 0.8664] rawler-0.7.1/data/cameras/canon/1dm2n.toml000064400000000000000000000005711046102023000163700ustar 00000000000000make = "Canon" model = "Canon EOS-1D Mark II N" clean_make = "Canon" clean_model = "EOS-1D Mark II N" whitepoint = 3700 color_pattern = "RGGB" blackareav = [0, 72] active_area = [74, 12, 0, 0] [cameras.color_matrix] A = [0.7217, -0.159, -0.0328, -0.6635, 1.3903, 0.3024, -0.0902, 0.1206, 0.8113] D65 = [0.6241, -0.0466, -0.0822, -0.818, 1.5825, 0.25, -0.1801, 0.1937, 0.8042] rawler-0.7.1/data/cameras/canon/1dm3.toml000064400000000000000000000005671046102023000162200ustar 00000000000000make = "Canon" model = "Canon EOS-1D Mark III" clean_make = "Canon" clean_model = "EOS-1D Mark III" whitepoint = 15100 color_pattern = "RGGB" blackareav = [2, 74] active_area = [78, 20, 0, 2] [cameras.color_matrix] A = [0.7063, -0.1449, -0.0503, -0.6904, 1.4334, 0.2816, -0.0821, 0.109, 0.741] D65 = [0.629, -0.054, -0.0976, -0.835, 1.6145, 0.2311, -0.1714, 0.1858, 0.7326] rawler-0.7.1/data/cameras/canon/1dm4.toml000064400000000000000000000007161046102023000162150ustar 00000000000000make = "Canon" model = "Canon EOS-1D Mark IV" clean_make = "Canon" clean_model = "EOS-1D Mark IV" color_pattern = "GBRG" blackareav = [0, 140] active_area = [142, 45, 62, 0] [cameras.color_matrix] A = [0.9966, -0.4682, -0.0136, -0.28, 1.0398, 0.279, 0.0065, 0.0935, 0.643] D65 = [0.6014, -0.022, -0.0795, -0.4109, 1.2014, 0.2361, -0.0561, 0.1824, 0.5787] [[cameras.modes]] mode = "sRaw1" whitepoint = 65535 [[cameras.modes]] mode = "sRaw2" whitepoint = 65535 rawler-0.7.1/data/cameras/canon/1ds.toml000064400000000000000000000004161046102023000161340ustar 00000000000000make = "Canon" model = "Canon EOS-1DS" clean_make = "Canon" clean_model = "EOS-1Ds" blackpoint = 0 whitepoint = 3500 color_pattern = "GRBG" hints = ["double_line"] [cameras.color_matrix] D65 = [0.4374, 0.3631, -0.1743, -0.7520, 1.5212, 0.2472, -0.2892, 0.3632, 0.8161] rawler-0.7.1/data/cameras/canon/1dsm2.toml000064400000000000000000000006331046102023000163740ustar 00000000000000make = "Canon" model = "Canon EOS-1Ds Mark II" clean_make = "Canon" clean_model = "EOS-1Ds Mark II" whitepoint = 4060 color_pattern = "GBRG" blackareav = [0, 96] active_area = [98, 13, 0, 0] [cameras.params] wb_offset = 34 [cameras.color_matrix] A = [0.7565, -0.1791, -0.0273, -0.6727, 1.4066, 0.2934, -0.082, 0.1093, 0.7688] D65 = [0.6517, -0.0602, -0.0867, -0.8181, 1.5926, 0.2378, -0.1618, 0.1771, 0.7633] rawler-0.7.1/data/cameras/canon/1dsm3.toml000064400000000000000000000005521046102023000163750ustar 00000000000000make = "Canon" model = "Canon EOS-1Ds Mark III" clean_make = "Canon" clean_model = "EOS-1Ds Mark III" color_pattern = "RGGB" blackareav = [0, 60] active_area = [62, 20, 10, 2] [cameras.color_matrix] A = [0.6705, -0.1154, -0.0458, -0.6783, 1.4191, 0.2848, -0.0853, 0.1159, 0.749] D65 = [0.5858, -0.0211, -0.093, -0.8254, 1.6018, 0.2354, -0.1732, 0.1888, 0.7448] rawler-0.7.1/data/cameras/canon/1dx.toml000064400000000000000000000005571046102023000161470ustar 00000000000000make = "Canon" model = "Canon EOS-1D X" clean_make = "Canon" clean_model = "EOS-1D X" color_pattern = "RGGB" blackareav = [0, 120] blackareah = [0, 98] active_area = [126, 100, 0, 2] [cameras.color_matrix] A = [0.7151, -0.1143, -0.079, -0.3998, 1.14, 0.2975, -0.0477, 0.1398, 0.769] D65 = [0.6847, -0.0614, -0.1014, -0.4669, 1.2737, 0.2139, -0.1197, 0.2488, 0.6846] rawler-0.7.1/data/cameras/canon/1dxm2.toml000064400000000000000000000010761046102023000164030ustar 00000000000000make = "Canon" model = "Canon EOS-1D X Mark II" clean_make = "Canon" clean_model = "Canon EOS-1D X Mark II" color_pattern = "RGGB" active_area = [72, 38, 0, 0] blackareav = [0, 70] blackareah = [0, 36] [cameras.color_matrix] A = [0.8101, -0.2023, -0.0221, -0.3652, 1.0819, 0.3276, -0.0491, 0.1461, 0.6583] D65 = [0.7596, -0.0978, -0.0967, -0.4808, 1.2571, 0.2503, -0.1398, 0.2567, 0.5752] [[cameras.modes]] mode = "sRaw1" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 65535 [[cameras.modes]] mode = "sRaw2" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 65535 rawler-0.7.1/data/cameras/canon/1dxm3.toml000064400000000000000000000006311046102023000164000ustar 00000000000000make = "Canon" model = "Canon EOS-1D X Mark III" clean_make = "Canon" clean_model = "EOS-1D X Mark III" color_pattern = "RGGB" [cameras.color_matrix] A = [1.0968, -0.4933, 0.0126, -0.3738, 1.1155, 0.2969, -0.0177, 0.1024, 0.6636] D65 = [0.8971, -0.2022, -0.1242, -0.5405, 1.3249, 0.238, -0.128, 0.2483, 0.6072] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" [[cameras.modes]] mode = "crm" rawler-0.7.1/data/cameras/canon/2000d.toml000064400000000000000000000006441046102023000161750ustar 00000000000000make = "Canon" model = "Canon EOS 2000D" clean_make = "Canon" clean_model = "EOS 2000D" color_pattern = "GBRG" active_area = [88, 47, 0, 0] model_aliases = [ ["Canon EOS REBEL T7", "Rebel T7"], ["Canon EOS Rebel T7", "Rebel T7"] ] [cameras.color_matrix] A = [0.9488, -0.3999, -0.0193, -0.3863, 1.1393, 0.2826, -0.0273, 0.1161, 0.6066] D65 = [0.83, -0.211, -0.112, -0.4917, 1.2694, 0.2482, -0.0938, 0.2141, 0.5666] rawler-0.7.1/data/cameras/canon/200d.toml000064400000000000000000000007331046102023000161140ustar 00000000000000make = "Canon" model = "Canon EOS 200D" clean_make = "Canon" clean_model = "EOS 200D" model_aliases = [ ["Canon EOS Kiss X9", "EOS Kiss X9"], ["Canon EOS Rebel SL2", "EOS Rebel SL2"], ] color_pattern = "RGGB" blackareav = [0, 260] blackareah = [0, 30] active_area = [264, 36, 0, 0] [cameras.color_matrix] A = [0.7952, -0.1689, -0.0575, -0.3746, 1.0825, 0.3378, -0.0405, 0.1362, 0.612] D65 = [0.7377, -0.0742, -0.0998, -0.4235, 1.1981, 0.2549, -0.0673, 0.1918, 0.5538] rawler-0.7.1/data/cameras/canon/20d.toml000064400000000000000000000005731046102023000160360ustar 00000000000000make = "Canon" model = "Canon EOS 20D" clean_make = "Canon" clean_model = "EOS 20D" color_pattern = "RGGB" active_area = [74, 12, 0, 0] blackpoint = 126 whitepoint = 4095 blackareav = [4, 70] [cameras.color_matrix] A = [0.7565, -0.168, -0.0264, -0.6544, 1.3839, 0.2995, -0.0965, 0.1349, 0.7631] D65 = [0.6599, -0.0537, -0.0891, -0.8071, 1.5783, 0.2424, -0.1984, 0.2234, 0.7462] rawler-0.7.1/data/cameras/canon/250d.toml000064400000000000000000000006451046102023000161230ustar 00000000000000make = "Canon" model = "Canon EOS 250D" clean_make = "Canon" clean_model = "EOS 250D" color_pattern = "RGGB" model_aliases = [ ["Canon EOS Rebel SL3", "Rebel SL3"] ] [cameras.color_matrix] A = [1.0253, -0.3687, -0.0541, -0.3827, 1.1485, 0.2672, -0.0369, 0.1557, 0.572] D65 = [0.9079, -0.1923, -0.1236, -0.4677, 1.2454, 0.2492, -0.0922, 0.2319, 0.5565] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/300d.toml000064400000000000000000000011421046102023000161100ustar 00000000000000# CRW make = "Canon" model = "Canon EOS 300D DIGITAL" clean_make = "Canon" clean_model = "EOS 300D" model_aliases = [ ["Canon EOS 350D Digital", "EOS 350D"], ["Canon EOS DIGITAL REBEL", "Rebel"], ["Canon EOS REBEL", "Rebel"], ["Canon EOS Kiss Digital", "Kiss"], ["Canon EOS Kiss", "Kiss"], ] whitepoint = 4000 color_pattern = "RGGB" active_area = [64,12,0,0] blackareav = [0,60] [cameras.params] wb_offset = 13 [cameras.color_matrix] A = [0.912, -0.3127, -0.0453, -0.6868, 1.4138, 0.3011, -0.1708, 0.2368, 0.9501] D65 = [0.825, -0.2044, -0.1127, -0.8092, 1.5606, 0.2664, -0.2893, 0.3453, 0.8348] rawler-0.7.1/data/cameras/canon/30d.toml000064400000000000000000000005561046102023000160400ustar 00000000000000make = "Canon" model = "Canon EOS 30D" clean_make = "Canon" clean_model = "EOS 30D" color_pattern = "RGGB" active_area = [74, 12, 0, 0] # LTRB whitepoint = 3398 blackareav = [4, 70] [cameras.color_matrix] A = [0.7162, -0.134, -0.0464, -0.6462, 1.3802, 0.2944, -0.0838, 0.1147, 0.7183] D65 = [0.6256, -0.0303, -0.1, -0.7879, 1.5621, 0.2396, -0.1713, 0.1905, 0.7047] rawler-0.7.1/data/cameras/canon/350d.toml000064400000000000000000000011641046102023000161210ustar 00000000000000make = "Canon" model = "Canon EOS 350D DIGITAL" clean_make = "Canon" clean_model = "EOS 350D" model_aliases = [ ["Canon EOS 350D Digital", "EOS 350D"], ["Canon EOS DIGITAL REBEL XT", "Rebel XT"], ["Canon EOS REBEL XT", "Rebel XT"], ["Canon EOS Kiss Digital N", "Kiss N"], ["Canon EOS Kiss N", "Kiss N"], ] whitepoint = 4095 color_pattern = "RGGB" blackareav = [0, 40] active_area = [42, 14, 0, 0] [cameras.params] wb_offset = 25 [cameras.color_matrix] A = [0.616, -0.0945, -0.0745, -0.6847, 1.3563, 0.3684, -0.0802, 0.1086, 0.7554] D65 = [0.6019, -0.0617, -0.0966, -0.8645, 1.5882, 0.2975, -0.153, 0.1719, 0.7642] rawler-0.7.1/data/cameras/canon/4000d.toml000064400000000000000000000006561046102023000162020ustar 00000000000000make = "Canon" model = "Canon EOS 4000D" clean_make = "Canon" clean_model = "Canon EOS 4000D" color_pattern = "GBRG" active_area = [142, 51, 0, 0] model_aliases = [ ["Canon EOS Rebel T100", "Rebel T100"], ["Canon EOS 3000D", "EOS 3000D"] ] [cameras.color_matrix] A = [0.77, -0.2142, -0.0096, -0.3513, 1.1072, 0.2806, -0.044, 0.1286, 0.6707] D65 = [0.6939, -0.1016, -0.0866, -0.4428, 1.2473, 0.2177, -0.1175, 0.2178, 0.6162] rawler-0.7.1/data/cameras/canon/400d.toml000064400000000000000000000010551046102023000161140ustar 00000000000000make = "Canon" model = "Canon EOS 400D DIGITAL" clean_make = "Canon" clean_model = "EOS 400D" model_aliases = [ ["Canon EOS DIGITAL REBEL XTi", "Rebel XTi"], ["Canon EOS REBEL XTi", "Rebel XTi"], ["Canon EOS Kiss Digital X", "Kiss X"], ["Canon EOS Kiss X", "Kiss X"], ] whitepoint = 4058 color_pattern = "RGGB" blackareav = [0, 40] active_area = [42, 18, 0, 2] [cameras.color_matrix] A = [0.7623, -0.2223, -0.064, -0.6443, 1.3442, 0.3359, -0.0678, 0.0954, 0.7621] D65 = [0.7054, -0.1501, -0.099, -0.8156, 1.5544, 0.2812, -0.1278, 0.1414, 0.7797] rawler-0.7.1/data/cameras/canon/40d.toml000064400000000000000000000007441046102023000160400ustar 00000000000000make = "Canon" model = "Canon EOS 40D" clean_make = "Canon" clean_model = "EOS 40D" color_pattern = "RGGB" real_bps = 14 active_area = [30, 18, 6, 2] whitepoint = 13600 blackareav = [0, 28] blackareah = [4, 18] [cameras.color_matrix] A = [0.7104, -0.1999, -0.0206, -0.603, 1.3278, 0.3074, -0.1017, 0.1619, 0.741] D65 = [0.607, -0.0746, -0.0856, -0.7652, 1.5365, 0.2442, -0.2025, 0.2553, 0.7314] [[cameras.modes]] mode = "sRaw2" hints = ["sraw_40d"] real_bps = 16 whitepoint = 65535 rawler-0.7.1/data/cameras/canon/450d.toml000064400000000000000000000010041046102023000161130ustar 00000000000000make = "Canon" model = "Canon EOS 450D" clean_make = "Canon" clean_model = "EOS 450D" model_aliases = [ ["Canon EOS DIGITAL REBEL XSi", "Rebel XSi"], ["Canon EOS REBEL XSi", "Rebel XSi"], ["Canon EOS Kiss Digital X2", "Kiss X2"], ["Canon EOS Kiss X2", "Kiss X2"], ] color_pattern = "RGGB" active_area = [22, 18, 0, 2] [cameras.color_matrix] A = [0.6694, -0.1429, -0.0292, -0.5762, 1.2806, 0.3334, -0.1022, 0.1789, 0.7442] D65 = [0.5784, -0.0261, -0.0821, -0.7539, 1.5064, 0.2673, -0.1982, 0.2681, 0.7427] rawler-0.7.1/data/cameras/canon/500d.toml000064400000000000000000000010261046102023000161130ustar 00000000000000make = "Canon" model = "Canon EOS 500D" clean_make = "Canon" clean_model = "EOS 500D" model_aliases = [ ["Canon EOS DIGITAL REBEL T1i", "Rebel T1i"], ["Canon EOS REBEL T1i", "Rebel T1i"], ["Canon EOS Kiss Digital X3", "Kiss X3"], ["Canon EOS Kiss X3", "Kiss X3"], ] color_pattern = "RGGB" blackareav = [0, 58] active_area = [62, 26, 0, 0] [cameras.color_matrix] A = [0.566, -0.0436, -0.0088, -0.5034, 1.2093, 0.3347, -0.0926, 0.2289, 0.6588] D65 = [0.4763, 0.0712, -0.0646, -0.6821, 1.4399, 0.264, -0.1921, 0.3276, 0.6561] rawler-0.7.1/data/cameras/canon/50d.toml000064400000000000000000000007751046102023000160450ustar 00000000000000make = "Canon" model = "Canon EOS 50D" clean_make = "Canon" clean_model = "EOS 50D" color_pattern = "GBRG" real_bps = 14 active_area = [62,51,2,0] blackareav = [4, 42] blackareah = [0, 60] [cameras.color_matrix] A = [0.5852, -0.0578, -0.0042, -0.4691, 1.1696, 0.3427, -0.0886, 0.2323, 0.6879] D65 = [0.492, 0.0616, -0.0593, -0.6494, 1.3965, 0.2784, -0.1774, 0.3178, 0.7004] [[cameras.modes]] mode = "sRaw1" real_bps = 16 whitepoint = 53000 [[cameras.modes]] mode = "sRaw2" real_bps = 16 whitepoint = 53000 rawler-0.7.1/data/cameras/canon/550d.toml000064400000000000000000000010571046102023000161240ustar 00000000000000make = "Canon" model = "Canon EOS 550D" clean_make = "Canon" clean_model = "EOS 550D" model_aliases = [ ["Canon EOS DIGITAL REBEL T2i", "Rebel T2i"], ["Canon EOS REBEL T2i", "Rebel T2i"], ["Canon EOS Kiss Digital X4", "Kiss X4"], ["Canon EOS Kiss X4", "Kiss X4"], ] color_pattern = "GBRG" blackareav = [0, 140] blackareah = [4, 44] active_area = [142, 51, 0, 0] [cameras.color_matrix] A = [0.7755, -0.2449, -0.0349, -0.3106, 1.0222, 0.3362, -0.0156, 0.0986, 0.6409] D65 = [0.6941, -0.1164, -0.0857, -0.3825, 1.1597, 0.2534, -0.0416, 0.154, 0.6039] rawler-0.7.1/data/cameras/canon/5d.toml000064400000000000000000000005721046102023000157600ustar 00000000000000make = "Canon" model = "Canon EOS 5D" clean_make = "Canon" clean_model = "EOS 5D" color_pattern = "RGGB" active_area = [90,34,0,0] blackareav = [0, 88] blackareah = [2, 30] whitepoint = 3692 [cameras.color_matrix] A = [0.7284, -0.1569, -0.0425, -0.6726, 1.4016, 0.2993, -0.0926, 0.1258, 0.7774] D65 = [0.6347, -0.0479, -0.0972, -0.8297, 1.5954, 0.248, -0.1967, 0.2132, 0.7649] rawler-0.7.1/data/cameras/canon/5dmk2.toml000064400000000000000000000007421046102023000163710ustar 00000000000000make = "Canon" model = "Canon EOS 5D Mark II" clean_make = "Canon" clean_model = "EOS 5D Mark II" color_pattern = "GBRG" active_area = [158,51,0,0] blackareav = [0, 156] blackareah = [2, 48] [cameras.color_matrix] A = [0.5309, -0.0229, -0.0336, -0.6241, 1.3265, 0.3337, -0.0817, 0.1215, 0.6664] D65 = [0.4716, 0.0603, -0.083, -0.7798, 1.5474, 0.248, -0.1496, 0.1937, 0.6651] [[cameras.modes]] mode = "sRaw1" whitepoint = 64948 [[cameras.modes]] mode = "sRaw2" whitepoint = 64948 rawler-0.7.1/data/cameras/canon/5dmk3.toml000064400000000000000000000010601046102023000163640ustar 00000000000000make = "Canon" model = "Canon EOS 5D Mark III" clean_make = "Canon" clean_model = "EOS 5D Mark III" color_pattern = "RGGB" active_area = [122,80,2,0] blackareav = [0, 120] blackareah = [6, 78] [cameras.color_matrix] A = [0.7234, -0.1413, -0.06, -0.3631, 1.115, 0.285, -0.0382, 0.1335, 0.6437] D65 = [0.6722, -0.0635, -0.0963, -0.4287, 1.246, 0.2028, -0.0908, 0.2162, 0.5668] [[cameras.modes]] mode = "sRaw1" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 55128 [[cameras.modes]] mode = "sRaw2" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 55128 rawler-0.7.1/data/cameras/canon/5dmk4.toml000064400000000000000000000011131046102023000163640ustar 00000000000000make = "Canon" model = "Canon EOS 5D Mark IV" clean_make = "Canon" clean_model = "EOS 5D Mark IV" color_pattern = "RGGB" active_area = [136,42,0,0] blackareav = [2, 134] blackareah = [2, 40] hints = ["double_line"] [cameras.color_matrix] A = [0.6515, -0.0927, -0.0634, -0.4068, 1.1151, 0.3359, -0.0641, 0.1839, 0.7328] D65 = [0.6446, -0.0366, -0.0864, -0.4436, 1.2204, 0.2513, -0.0952, 0.2496, 0.6348] [[cameras.modes]] mode = "sRaw1" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 56032 [[cameras.modes]] mode = "sRaw2" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 56032 rawler-0.7.1/data/cameras/canon/5ds.toml000064400000000000000000000010751046102023000161420ustar 00000000000000make = "Canon" model = "Canon EOS 5DS" clean_make = "Canon" clean_model = "EOS 5DS" color_pattern = "RGGB" blackareav = [0, 150] blackareah = [4, 56] active_area = [160, 64, 0, 0] hints = ["double_line"] [cameras.color_matrix] A = [0.6848, -0.1661, -0.0221, -0.3904, 1.0931, 0.3434, -0.047, 0.1251, 0.6039] D65 = [0.625, -0.0711, -0.0808, -0.5153, 1.2794, 0.2636, -0.1249, 0.2198, 0.561] [[cameras.modes]] mode = "sRaw1" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 52000 [[cameras.modes]] mode = "sRaw2" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 52000 rawler-0.7.1/data/cameras/canon/5dsr.toml000064400000000000000000000012071046102023000163210ustar 00000000000000make = "Canon" model = "Canon EOS 5DS R" clean_make = "Canon" clean_model = "EOS 5DS R" color_pattern = "RGGB" blackareav = [0, 150] blackareah = [4, 56] active_area = [160, 64, 0, 0] hints = ["double_line"] [cameras.color_matrix] A = [0.6848, -0.1661, -0.0221, -0.3904, 1.0931, 0.3434, -0.047, 0.1251, 0.6039] D65 = [0.625, -0.0711, -0.0808, -0.5153, 1.2794, 0.2636, -0.1249, 0.2198, 0.561] [[cameras.modes]] mode = "sRaw1" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 52000 # seems to be incorrect for ISO 50 [[cameras.modes]] mode = "sRaw2" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 52000 # seems to be incorrect for ISO 50 rawler-0.7.1/data/cameras/canon/600d.toml000064400000000000000000000010521046102023000161130ustar 00000000000000make = "Canon" model = "Canon EOS 600D" clean_make = "Canon" clean_model = "EOS 600D" model_aliases = [ ["Canon EOS DIGITAL REBEL T3i", "Rebel T3i"], ["Canon EOS REBEL T3i", "Rebel T3i"], ["Canon EOS Kiss Digital X5", "Kiss X5"], ["Canon EOS Kiss X5", "Kiss X5"], ] color_pattern = "GBRG" blackareav = [0, 140] blackareah = [4, 44] active_area = [142, 51, 0, 0] [cameras.color_matrix] A = [0.7164, -0.1916, -0.0431, -0.3361, 1.06, 0.32, -0.0272, 0.1058, 0.6442] D65 = [0.6461, -0.0907, -0.0882, -0.43, 1.2184, 0.2378, -0.0819, 0.1944, 0.5931] rawler-0.7.1/data/cameras/canon/60d.toml000064400000000000000000000010021046102023000160260ustar 00000000000000make = "Canon" model = "Canon EOS 60D" clean_make = "Canon" clean_model = "EOS 60D" color_pattern = "GBRG" real_bps = 14 active_area = [142,51,0,0] blackareav = [2, 140] blackareah = [10, 48] [cameras.color_matrix] A = [0.7428, -0.1897, -0.0491, -0.3505, 1.0963, 0.2929, -0.0337, 0.1242, 0.6413] D65 = [0.6719, -0.0994, -0.0925, -0.4408, 1.2426, 0.2211, -0.0887, 0.2129, 0.6051] [[cameras.modes]] mode = "sRaw1" real_bps = 16 whitepoint = 65535 [[cameras.modes]] mode = "sRaw2" real_bps = 16 whitepoint = 65535 rawler-0.7.1/data/cameras/canon/650d.toml000064400000000000000000000010621046102023000161210ustar 00000000000000make = "Canon" model = "Canon EOS 650D" clean_make = "Canon" clean_model = "EOS 650D" model_aliases = [ ["Canon EOS DIGITAL REBEL T4i", "Rebel T4i"], ["Canon EOS REBEL T4i", "Rebel T4i"], ["Canon EOS Kiss Digital X6i", "Kiss X6i"], ["Canon EOS Kiss X6i", "Kiss X6i"], ] color_pattern = "RGGB" blackareav = [0, 70] blackareah = [4, 44] active_area = [72, 52, 0, 0] [cameras.color_matrix] A = [0.6985, -0.1611, -0.0397, -0.3596, 1.0749, 0.3295, -0.0349, 0.1136, 0.6512] D65 = [0.6602, -0.0841, -0.0939, -0.4472, 1.2458, 0.2247, -0.0975, 0.2039, 0.6148] rawler-0.7.1/data/cameras/canon/6d.toml000064400000000000000000000010421046102023000157520ustar 00000000000000make = "Canon" model = "Canon EOS 6D" clean_make = "Canon" clean_model = "EOS 6D" color_pattern = "RGGB" blackareav = [0, 68] blackareah = [2, 36] active_area = [74, 40, 0, 2] [cameras.color_matrix] A = [0.7546, -0.1435, -0.0929, -0.3846, 1.1488, 0.2692, -0.0332, 0.1209, 0.637] D65 = [0.7034, -0.0804, -0.1014, -0.442, 1.2564, 0.2058, -0.0851, 0.1994, 0.5758] [[cameras.modes]] mode = "sRaw1" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 48664 [[cameras.modes]] mode = "sRaw2" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 48664 rawler-0.7.1/data/cameras/canon/6dmk2.toml000064400000000000000000000011471046102023000163720ustar 00000000000000make = "Canon" model = "Canon EOS 6D Mark II" clean_make = "Canon" clean_model = "EOS 6D Mark II" color_pattern = "RGGB" hints = ["double_line"] blackareav = [0, 110] blackareah = [0, 40] active_area = [120, 44, 0, 0] [cameras.color_matrix] A = [0.7295, -0.1664, -0.0669, -0.4871, 1.2238, 0.298, -0.0585, 0.1356, 0.6696] D65 = [0.6875, -0.097, -0.0932, -0.4691, 1.2459, 0.2501, -0.0874, 0.1953, 0.5809] [[cameras.modes]] mode = "sRaw1" hints = ["invert_sraw_wb", "sraw_new"] active_area = [0, 3, 0, 0] whitepoint = 65000 [[cameras.modes]] mode = "sRaw2" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 65000 rawler-0.7.1/data/cameras/canon/700d.toml000064400000000000000000000010621046102023000161150ustar 00000000000000make = "Canon" model = "Canon EOS 700D" clean_make = "Canon" clean_model = "EOS 700D" model_aliases = [ ["Canon EOS DIGITAL REBEL T5i", "Rebel T5i"], ["Canon EOS REBEL T5i", "Rebel T5i"], ["Canon EOS Kiss Digital X7i", "Kiss X7i"], ["Canon EOS Kiss X7i", "Kiss X7i"], ] color_pattern = "RGGB" blackareav = [0, 70] blackareah = [4, 50] active_area = [72, 52, 0, 0] [cameras.color_matrix] A = [0.6985, -0.1611, -0.0397, -0.3596, 1.0749, 0.3295, -0.0349, 0.1136, 0.6512] D65 = [0.6602, -0.0841, -0.0939, -0.4472, 1.2458, 0.2247, -0.0975, 0.2039, 0.6148] rawler-0.7.1/data/cameras/canon/70d.toml000064400000000000000000000011131046102023000160320ustar 00000000000000make = "Canon" model = "Canon EOS 70D" clean_make = "Canon" clean_model = "EOS 70D" color_pattern = "RGGB" real_bps = 14 active_area = [72,38,0,0] blackareav = [4, 70] blackareah = [4, 36] [cameras.color_matrix] A = [0.7546, -0.1435, -0.0929, -0.3846, 1.1488, 0.2692, -0.0332, 0.1209, 0.637] D65 = [0.7034, -0.0804, -0.1014, -0.442, 1.2564, 0.2058, -0.0851, 0.1994, 0.5758] [[cameras.modes]] mode = "sRaw1" hints = ["invert_sraw_wb", "sraw_new"] real_bps = 16 whitepoint = 53000 [[cameras.modes]] mode = "sRaw2" hints = ["invert_sraw_wb", "sraw_new"] real_bps = 16 whitepoint = 53000 rawler-0.7.1/data/cameras/canon/750d.toml000064400000000000000000000011051046102023000161200ustar 00000000000000make = "Canon" model = "Canon EOS 750D" clean_make = "Canon" clean_model = "EOS 750D" model_aliases = [ ["Canon EOS DIGITAL REBEL T6i", "Rebel T6i"], ["Canon EOS REBEL T6i", "Rebel T6i"], ["Canon EOS Rebel T6i", "Rebel T6i"], ["Canon EOS Kiss Digital X8i", "Kiss X8i"], ["Canon EOS Kiss X8i", "Kiss X8i"], ] color_pattern = "RGGB" active_area = [72, 34, 0, 0] blackareav = [0, 68] [cameras.color_matrix] A = [0.6671, -0.1668, -0.0272, -0.3729, 1.0665, 0.3552, -0.0409, 0.1271, 0.6293] D65 = [0.6362, -0.0823, -0.0847, -0.4426, 1.2109, 0.2616, -0.0743, 0.1857, 0.5635] rawler-0.7.1/data/cameras/canon/760d.toml000064400000000000000000000007551046102023000161330ustar 00000000000000make = "Canon" model = "Canon EOS 760D" clean_make = "Canon" clean_model = "EOS 760D" model_aliases = [ ["Canon EOS DIGITAL REBEL T6s", "Rebel T6s"], ["Canon EOS Rebel T6s", "Rebel T6s"], ["Canon EOS 8000D", "EOS 8000D"], ] color_pattern = "RGGB" active_area = [72, 34, 0, 0] blackareav = [0, 50] [cameras.color_matrix] A = [0.6671, -0.1668, -0.0272, -0.3729, 1.0665, 0.3552, -0.0409, 0.1271, 0.6293] D65 = [0.6362, -0.0823, -0.0847, -0.4426, 1.2109, 0.2616, -0.0743, 0.1857, 0.5635] rawler-0.7.1/data/cameras/canon/77d.toml000064400000000000000000000005631046102023000160510ustar 00000000000000make = "Canon" model = "Canon EOS 77D" clean_make = "Canon" clean_model = "Canon EOS 77D" color_pattern = "RGGB" blackareav = [0,260] blackareah = [0,30] active_area = [264, 34, 0, 0] [cameras.color_matrix] A = [0.7952, -0.1689, -0.0575, -0.3746, 1.0825, 0.3378, -0.0405, 0.1362, 0.612] D65 = [0.7377, -0.0742, -0.0998, -0.4235, 1.1981, 0.2549, -0.0673, 0.1918, 0.5538] rawler-0.7.1/data/cameras/canon/7d.toml000064400000000000000000000006771046102023000157700ustar 00000000000000make = "Canon" model = "Canon EOS 7D" clean_make = "Canon" clean_model = "EOS 7D" color_pattern = "GBRG" blackareav = [8, 156] active_area = [158, 51, 0, 0] [cameras.color_matrix] A = [1.162, -0.635, 0.0005, -0.2558, 1.0146, 0.2813, 0.0024, 0.0858, 0.6926] D65 = [0.6844, -0.0996, -0.0856, -0.3876, 1.1761, 0.2396, -0.0593, 0.1772, 0.6198] [[cameras.modes]] mode = "sRaw1" whitepoint = 30000 [[cameras.modes]] mode = "sRaw2" whitepoint = 30000 rawler-0.7.1/data/cameras/canon/7dmk2.toml000064400000000000000000000010371046102023000163710ustar 00000000000000make = "Canon" model = "Canon EOS 7D Mark II" clean_make = "Canon" clean_model = "EOS 7D Mark II" color_pattern = "RGGB" blackareav = [4, 64] active_area = [72, 38, 0, 0] [cameras.color_matrix] A = [0.7795, -0.2196, -0.0251, -0.3391, 1.0273, 0.3632, -0.0373, 0.1283, 0.6613] D65 = [0.7268, -0.1082, -0.0969, -0.4186, 1.1839, 0.2663, -0.0825, 0.2029, 0.5839] [[cameras.modes]] mode = "sRaw1" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 30000 [[cameras.modes]] mode = "sRaw2" hints = ["invert_sraw_wb", "sraw_new"] whitepoint = 30000 rawler-0.7.1/data/cameras/canon/800d.toml000064400000000000000000000007351046102023000161240ustar 00000000000000make = "Canon" model = "Canon EOS 800D" clean_make = "Canon" clean_model = "EOS 800D" model_aliases = [ ["Canon EOS REBEL T7i", "EOS Rebel T7i"], ["Canon EOS Rebel T7i", "EOS Rebel T7i"] ] color_pattern = "RGGB" blackareav = [0, 250] blackareah = [0, 30] active_area = [264, 34, 0, 0] [cameras.color_matrix] A = [0.7539, -0.1435, -0.0601, -0.3828, 1.0863, 0.3428, -0.042, 0.1357, 0.6196] D65 = [0.697, -0.0512, -0.0968, -0.4425, 1.2161, 0.2553, -0.0739, 0.1982, 0.5601] rawler-0.7.1/data/cameras/canon/80d.toml000064400000000000000000000011151046102023000160350ustar 00000000000000make = "Canon" model = "Canon EOS 80D" clean_make = "Canon" clean_model = "EOS 80D" color_pattern = "RGGB" real_bps = 14 active_area = [264,34,2,0] blackareav = [4, 260] blackareah = [0, 30] [cameras.color_matrix] A = [0.832, -0.1998, -0.0078, -0.3476, 1.0481, 0.348, -0.0384, 0.1349, 0.5901] D65 = [0.7457, -0.0671, -0.0937, -0.4849, 1.2495, 0.2643, -0.1213, 0.2354, 0.5492] [[cameras.modes]] mode = "sRaw1" hints = ["invert_sraw_wb", "sraw_new"] real_bps = 16 whitepoint = 58832 [[cameras.modes]] mode = "sRaw2" hints = ["invert_sraw_wb", "sraw_new"] real_bps = 16 whitepoint = 58832 rawler-0.7.1/data/cameras/canon/850d.toml000064400000000000000000000006511046102023000161260ustar 00000000000000make = "Canon" model = "Canon EOS 850D" model_aliases = [ ["Canon EOS Rebel T8i", "EOS Rebel T8i"], ] clean_make = "Canon" clean_model = "EOS 850D" color_pattern = "RGGB" [cameras.color_matrix] A = [1.0253, -0.3687, -0.0541, -0.3827, 1.1485, 0.2672, -0.0369, 0.1557, 0.572] D65 = [0.9079, -0.1923, -0.1236, -0.4677, 1.2454, 0.2492, -0.0922, 0.2319, 0.5565] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/90d.toml000064400000000000000000000005501046102023000160400ustar 00000000000000make = "Canon" model = "Canon EOS 90D" clean_make = "Canon" clean_model = "EOS 90D" color_pattern = "RGGB" [cameras.color_matrix] A = [1.4683, -0.7448, -0.0905, -0.4609, 1.3134, 0.1588, -0.0324, 0.1195, 0.6559] D65 = [1.1498, -0.3759, -0.1516, -0.5073, 1.2954, 0.2349, -0.0892, 0.1867, 0.6118] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/a3300is.toml000064400000000000000000000005521046102023000165300ustar 00000000000000# CRW make = "Canon" model = "PowerShot A3300 IS" clean_make = "Canon" clean_model = "PowerShot A3300 IS" blackpoint = 127 whitepoint = 4095 color_pattern = "GBRG" active_area = [16,16,56,8] filesize = 24724224 raw_width = 4704 raw_height = 3504 [cameras.color_matrix] D65 = [130.1431, -46.9837, -10.2652, -20.0195, 96.1551, 23.8645, -1.6441, 14.2319, 37.5979] rawler-0.7.1/data/cameras/canon/a610.toml000064400000000000000000000005361046102023000161170ustar 00000000000000# CRW make = "Canon" model = "PowerShot A610" clean_make = "Canon" clean_model = "PowerShot A610" whitepoint = 1023 color_pattern = "RGGB" filesize = 6573120 raw_width = 2672 raw_height = 1968 blackareav = [2632,40] active_area = [12, 8,44,0] [cameras.color_matrix] D65 = [1.5591, -0.6402, -0.1592, -0.5365, 1.3198, 0.2168, -0.1300, 0.1824, 0.5075] rawler-0.7.1/data/cameras/canon/a620.toml000064400000000000000000000005311046102023000161130ustar 00000000000000# CRW make = "Canon" model = "PowerShot A620" clean_make = "Canon" clean_model = "PowerShot A620" whitepoint = 1023 color_pattern = "RGGB" active_area = [36,12,4,0] filesize = 9219600 raw_width = 3152 raw_height = 2340 blackareav = [0,30] [cameras.color_matrix] D65 = [1.5265, -0.6193, -0.1558, -0.4125, 1.2116, 0.2010, -0.0888, 0.1639, 0.5220]rawler-0.7.1/data/cameras/canon/a630.toml000064400000000000000000000005331046102023000161160ustar 00000000000000# CRW make = "Canon" model = "PowerShot A630" clean_make = "Canon" clean_model = "PowerShot A630" whitepoint = 1023 color_pattern = "RGGB" active_area = [12, 6,44,6] filesize = 10383120 raw_width = 3344 raw_height = 2484 blackareav = [0,30] [cameras.color_matrix] D65 = [1.4201, -0.5308, -0.1757, -0.6087, 1.4472, 0.1617, -0.2191, 0.3105, 0.5348]rawler-0.7.1/data/cameras/canon/a640.toml000064400000000000000000000005361046102023000161220ustar 00000000000000# CRW make = "Canon" model = "PowerShot A640" clean_make = "Canon" clean_model = "PowerShot A640" whitepoint = 1023 color_pattern = "RGGB" active_area = [12, 6,52,6] filesize = 12945240 raw_width = 3736 raw_height = 2772 blackareav = [3686,50] [cameras.color_matrix] D65 = [1.3124, -0.5329, -0.1390, -0.3602, 1.1658, 0.1944, -0.1612, 0.2863, 0.4885]rawler-0.7.1/data/cameras/canon/a650.toml000064400000000000000000000005361046102023000161230ustar 00000000000000# CRW make = "Canon" model = "PowerShot A650" clean_make = "Canon" clean_model = "PowerShot A650" whitepoint = 1023 color_pattern = "RGGB" active_area = [48,12,24,12] filesize = 15636240 raw_width = 4104 raw_height = 3048 blackareav = [0, 45] [cameras.color_matrix] D65 = [0.9427, -0.3036, -0.0959, -0.2581, 1.0671, 0.1911, -0.1039, 0.1982, 0.4430] rawler-0.7.1/data/cameras/canon/a720is.toml000064400000000000000000000005431046102023000164530ustar 00000000000000# CRW make = "Canon" model = "PowerShot A720 IS" clean_make = "Canon" clean_model = "PowerShot A720 IS" whitepoint = 1023 color_pattern = "GBRG" active_area = [6,5,32,3] filesize = 10341600 raw_width = 3336 raw_height = 2480 blackareav = [3306,30] [cameras.color_matrix] D65 = [1.4573, -0.5482, -0.1546, -0.1266, 0.9799, 0.1468, -0.1040, 0.1912, 0.3810] rawler-0.7.1/data/cameras/canon/d10.toml000064400000000000000000000005441046102023000160330ustar 00000000000000# CRW make = "Canon" model = "Canon PowerShot D10" clean_make = "Canon" clean_model = "PowerShot D10" whitepoint = 4095 color_pattern = "GBRG" active_area = [25,22,81,8] filesize = 18763488 raw_width = 4104 raw_height = 3048 blackareav = [4074, 28] [cameras.color_matrix] D65 = [0.9427, -0.3036, -0.0959, -0.2581, 1.0671, 0.1911, -0.1039, 0.1982, 0.4430] rawler-0.7.1/data/cameras/canon/d2000c.toml000064400000000000000000000004561046102023000163410ustar 00000000000000make = "Canon" model = "EOS D2000C" clean_make = "Canon" clean_model = "EOS D2000C" blackpoint = 96 whitepoint = 4095 color_pattern = "GRBG" active_area = [0, 0, 0, 0] hints = ["linearization"] [cameras.color_matrix] D65 = [2.4542, -1.0860, -0.3401, -0.1490, 1.1370, -0.0297, 0.2858, -0.0605, 0.3225] rawler-0.7.1/data/cameras/canon/d30.toml000064400000000000000000000006001046102023000160260ustar 00000000000000# CRW make = "Canon" model = "Canon EOS D30" clean_make = "Canon" clean_model = "EOS D30" whitepoint = 4095 color_pattern = "RGGB" blackareav = [0,46] hints = ["nocinfo2"] active_area = [48, 6, 0, 0] [cameras.color_matrix] A = [1.0869, -0.3665, -0.0951, -0.6503, 1.4172, 0.2543, -0.0891, 0.1236, 0.9482] D65 = [0.99, -0.2771, -0.1324, -0.7072, 1.4229, 0.314, -0.279, 0.3344, 0.8861] rawler-0.7.1/data/cameras/canon/d60.toml000064400000000000000000000006161046102023000160400ustar 00000000000000# CRW make = "Canon" model = "Canon EOS D60" clean_make = "Canon" clean_model = "EOS D60" whitepoint = 4000 color_pattern = "RGGB" blackareav = [0,60] active_area = [64, 12, 0, 0] [cameras.params] wb_offset = 1 [cameras.color_matrix] A = [0.6385, -0.1668, -0.0631, -0.6948, 1.3734, 0.3595, -0.1629, 0.223, 0.896] D65 = [0.6211, -0.1358, -0.0896, -0.8557, 1.5766, 0.3012, -0.3001, 0.3507, 0.8567] rawler-0.7.1/data/cameras/canon/g1.toml000064400000000000000000000007201046102023000157520ustar 00000000000000# CRW make = "Canon" model = "Canon PowerShot G1" clean_make = "Canon" clean_model = "PowerShot G1" whitepoint = 1023 color_pattern = "GMYC" plane_color = "GMCY" active_area = [4,8,52,2] hints = ["nolowbits"] blackareav = [2094,50] [cameras.color_matrix] A = [-0.4194, 0.8516, 0.277, 0.4745, -0.1228, 0.406, -0.4529, 0.8983, 0.6526, -0.1032, 0.9664, 0.1108] D65 = [-0.5686, 1.03, 0.2223, 0.4725, -0.1157, 0.4383, -0.6128, 1.0783, 0.6163, -0.2688, 1.2093, 0.0604] rawler-0.7.1/data/cameras/canon/g10.toml000064400000000000000000000005411046102023000160330ustar 00000000000000make = "Canon" model = "Canon PowerShot G10" clean_make = "Canon" clean_model = "PowerShot G10" whitepoint = 4095 color_pattern = "GBRG" active_area = [12, 13, 36, 12] [cameras.color_matrix] A = [1.3591, -0.6592, 0.0324, -0.344, 1.0533, 0.3374, -0.0169, 0.1008, 0.5612] D65 = [1.1093, -0.3906, -0.1028, -0.5047, 1.2492, 0.2879, -0.1003, 0.175, 0.5561] rawler-0.7.1/data/cameras/canon/g11.toml000064400000000000000000000005661046102023000160430ustar 00000000000000make = "Canon" model = "Canon PowerShot G11" clean_make = "Canon" clean_model = "PowerShot G11" whitepoint = 4095 color_pattern = "RGGB" blackareav = [3696, 48] active_area = [8, 16, 52, 8] [cameras.color_matrix] A = [1.9754, -1.3549, 0.0792, 0.0164, 0.8013, 0.2216, 0.0314, 0.0224, 0.5145] D65 = [1.2177, -0.4817, -0.1069, -0.1612, 0.9864, 0.2049, -0.0098, 0.085, 0.4471] rawler-0.7.1/data/cameras/canon/g12.toml000064400000000000000000000005641046102023000160420ustar 00000000000000make = "Canon" model = "Canon PowerShot G12" clean_make = "Canon" clean_model = "PowerShot G12" whitepoint = 4000 color_pattern = "RGGB" blackareav = [0, 50] active_area = [52, 12, 8, 12] [cameras.color_matrix] A = [1.4105, -0.7096, -0.0274, -0.1073, 0.9014, 0.245, 0.005, 0.0536, 0.5097] D65 = [1.3244, -0.5501, -0.1248, -0.1508, 0.9858, 0.1935, -0.027, 0.1083, 0.4366] rawler-0.7.1/data/cameras/canon/g15.toml000064400000000000000000000006201046102023000160360ustar 00000000000000make = "Canon" model = "Canon PowerShot G15" clean_make = "Canon" clean_model = "PowerShot G15" whitepoint = 4000 color_pattern = "GBRG" blackareav = [0, 100] blackareah = [3062, 60] active_area = [104, 11, 8, 65] [cameras.color_matrix] A = [0.8204, -0.3475, 0.0326, -0.2919, 0.9461, 0.4065, 0.0159, 0.0225, 0.4291] D65 = [0.7474, -0.2301, -0.0567, -0.4056, 1.1456, 0.2975, -0.0222, 0.0716, 0.4181] rawler-0.7.1/data/cameras/canon/g16.toml000064400000000000000000000005701046102023000160430ustar 00000000000000make = "Canon" model = "Canon PowerShot G16" clean_make = "Canon" clean_model = "PowerShot G16" whitepoint = 4000 color_pattern = "RGGB" blackareav = [0, 80] active_area = [120, 18, 48, 13] [cameras.color_matrix] A = [0.9249, -0.4361, 0.0549, -0.2474, 0.9924, 0.2983, -0.0142, 0.0935, 0.6104] D65 = [0.802, -0.2687, -0.0682, -0.3704, 1.1879, 0.2052, -0.0965, 0.1921, 0.5556] rawler-0.7.1/data/cameras/canon/g1x.toml000064400000000000000000000006201046102023000161410ustar 00000000000000make = "Canon" model = "Canon PowerShot G1 X" clean_make = "Canon" clean_model = "PowerShot G1 X" whitepoint = 16000 color_pattern = "RGGB" blackareav = [0, 68] blackareah = [0, 46] active_area = [80, 52, 12, 4] [cameras.color_matrix] A = [0.8138, -0.2281, -0.0659, -0.3453, 1.1006, 0.2816, -0.0297, 0.1118, 0.6471] D65 = [0.7378, -0.1255, -0.1043, -0.4088, 1.2251, 0.2048, -0.0876, 0.1946, 0.5805] rawler-0.7.1/data/cameras/canon/g1xm2.toml000064400000000000000000000006371046102023000164100ustar 00000000000000make = "Canon" model = "Canon PowerShot G1 X Mark II" clean_make = "Canon" clean_model = "PowerShot G1 X Mark II" whitepoint = 16000 color_pattern = "RGGB" blackareav = [0, 68] blackareah = [0, 46] active_area = [80, 50, 0, 0] [cameras.color_matrix] A = [0.8138, -0.2281, -0.0659, -0.3453, 1.1006, 0.2816, -0.0297, 0.1118, 0.6471] D65 = [0.7378, -0.1255, -0.1043, -0.4088, 1.2251, 0.2048, -0.0876, 0.1946, 0.5805] rawler-0.7.1/data/cameras/canon/g1xm3.toml000064400000000000000000000006171046102023000164070ustar 00000000000000make = "Canon" model = "Canon PowerShot G1 X Mark III" clean_make = "Canon" clean_model = "PowerShot G1 X Mark III" color_pattern = "RGGB" blackareav = [0, 250] blackareah = [0, 30] active_area = [264, 36, 0, 0] [cameras.color_matrix] A = [0.9094, -0.1794, -0.0591, -0.4192, 1.1372, 0.3236, -0.0569, 0.1747, 0.8061] D65 = [0.8532, -0.0701, -0.1167, -0.4095, 1.1879, 0.2508, -0.0797, 0.2424, 0.701] rawler-0.7.1/data/cameras/canon/g2.toml000064400000000000000000000006151046102023000157560ustar 00000000000000# CRW make = "Canon" model = "Canon PowerShot G2" clean_make = "Canon" clean_model = "PowerShot G2" whitepoint = 1023 color_pattern = "RGGB" active_area = [12,6,52,2] hints = ["nolowbits"] blackareav = [2326,50] [cameras.color_matrix] A = [1.0745, -0.45, -0.0146, -0.6812, 1.4094, 0.2999, -0.1481, 0.2054, 0.8234] D65 = [0.9194, -0.2787, -0.1059, -0.8098, 1.5657, 0.2608, -0.261, 0.3064, 0.7867] rawler-0.7.1/data/cameras/canon/g3.toml000064400000000000000000000006211046102023000157540ustar 00000000000000make = "Canon" model = "Canon PowerShot G3" clean_make = "Canon" clean_model = "PowerShot G3" whitepoint = 4095 color_pattern = "RGGB" active_area = [12,6,52,2] blackareav = [2326,50] [cameras.params] wb_offset = 60 [cameras.color_matrix] A = [1.0899, -0.4654, -0.0172, -0.6668, 1.3907, 0.3058, -0.1456, 0.2032, 0.8278] D65 = [0.9326, -0.2882, -0.1084, -0.794, 1.5447, 0.2677, -0.262, 0.309, 0.774] rawler-0.7.1/data/cameras/canon/g3x.toml000064400000000000000000000005701046102023000161470ustar 00000000000000make = "Canon" model = "Canon PowerShot G3 X" clean_make = "Canon" clean_model = "PowerShot G3 X" whitepoint = 16000 color_pattern = "RGGB" blackareav = [0, 90] active_area = [96, 18, 0, 0] [cameras.color_matrix] A = [1.1216, -0.6046, 0.0645, -0.2008, 0.9648, 0.2774, 0.0005, 0.0793, 0.5779] D65 = [0.9701, -0.3857, -0.0921, -0.3149, 1.1537, 0.1817, -0.0786, 0.1817, 0.5147] rawler-0.7.1/data/cameras/canon/g5.toml000064400000000000000000000006241046102023000157610ustar 00000000000000make = "Canon" model = "Canon PowerShot G5" clean_make = "Canon" clean_model = "PowerShot G5" whitepoint = 4095 color_pattern = "RGGB" active_area = [12,6,44,2] blackareav = [2632,40] [cameras.params] wb_offset = 60 [cameras.color_matrix] A = [1.5457, -0.7339, 0.0248, -0.4556, 1.2507, 0.2287, -0.0947, 0.1851, 0.5501] D65 = [0.9869, -0.2972, -0.0942, -0.7314, 1.5098, 0.2369, -0.1898, 0.2536, 0.7282] rawler-0.7.1/data/cameras/canon/g5x.toml000064400000000000000000000005701046102023000161510ustar 00000000000000make = "Canon" model = "Canon PowerShot G5 X" clean_make = "Canon" clean_model = "PowerShot G5 X" whitepoint = 16000 color_pattern = "RGGB" active_area = [96, 18, 0, 0] blackareav = [0, 78] [cameras.color_matrix] A = [1.1125, -0.5937, 0.0355, -0.2979, 1.0926, 0.236, -0.0116, 0.0835, 0.6064] D65 = [0.9602, -0.3823, -0.0937, -0.2984, 1.1495, 0.1675, -0.0407, 0.1415, 0.5049] rawler-0.7.1/data/cameras/canon/g5xmk2.toml000064400000000000000000000006001046102023000165550ustar 00000000000000make = "Canon" model = "Canon PowerShot G5 X Mark II" clean_make = "Canon" clean_model = "PowerShot G5 X Mark II" color_pattern = "RGGB" [cameras.color_matrix] A = [1.4076, -0.93, 0.1481, -0.1849, 0.9861, 0.233, 0.0229, 0.0399, 0.5916] D65 = [1.1629, -0.5713, -0.0914, -0.2706, 1.109, 0.1842, -0.0206, 0.1225, 0.5515] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/g6.toml000064400000000000000000000006471046102023000157670ustar 00000000000000make = "Canon" model = "Canon PowerShot G6" clean_make = "Canon" clean_model = "PowerShot G6" whitepoint = 4095 color_pattern = "RGGB" active_area = [44,12,4,4] hints = ["wb_mangle"] blackareav = [0,40] [cameras.params] wb_offset = 48 [cameras.color_matrix] A = [1.1775, -0.5782, 0.0232, -0.5747, 1.2842, 0.3272, -0.0695, 0.0984, 0.7174] D65 = [0.9876, -0.3774, -0.0871, -0.7613, 1.4807, 0.3071, -0.1448, 0.1305, 0.7485] rawler-0.7.1/data/cameras/canon/g7x.toml000064400000000000000000000005751046102023000161600ustar 00000000000000# CRW make = "Canon" model = "Canon PowerShot G7 X" clean_make = "Canon" clean_model = "PowerShot G7 X" whitepoint = 4000 color_pattern = "RGGB" active_area = [96, 17, 0, 0] blackareav = [0, 94] [cameras.color_matrix] A = [1.1125, -0.5937, 0.0355, -0.2979, 1.0926, 0.236, -0.0116, 0.0835, 0.6064] D65 = [0.9602, -0.3823, -0.0937, -0.2984, 1.1495, 0.1675, -0.0407, 0.1415, 0.5049] rawler-0.7.1/data/cameras/canon/g7x_crw.toml000064400000000000000000000005021046102023000170210ustar 00000000000000make = "Canon" model = "Canon PowerShot G7 X CRW" clean_make = "Canon" clean_model = "PowerShot G7 X" blackpoint = 511 whitepoint = 4000 color_pattern = "RGGB" filesize = 31342080 raw_width = 5632 raw_height = 3710 [cameras.color_matrix] D65 = [0.9602, -0.3823, -0.0937, -0.2984, 1.1495, 0.1675, -0.0407, 0.1415, 0.5049] rawler-0.7.1/data/cameras/canon/g7xm2.toml000064400000000000000000000005731046102023000164150ustar 00000000000000make = "Canon" model = "Canon PowerShot G7 X Mark II" clean_make = "Canon" clean_model = "Canon PowerShot G7 X Mark II" color_pattern = "RGGB" active_area = [96, 17, 0, 0] blackareav = [0, 70] [cameras.color_matrix] A = [1.1125, -0.5937, 0.0355, -0.2979, 1.0926, 0.236, -0.0116, 0.0835, 0.6064] D65 = [0.9602, -0.3823, -0.0937, -0.2984, 1.1495, 0.1675, -0.0407, 0.1415, 0.5049] rawler-0.7.1/data/cameras/canon/g7xmk3.toml000064400000000000000000000006021046102023000165620ustar 00000000000000make = "Canon" model = "Canon PowerShot G7 X Mark III" clean_make = "Canon" clean_model = "PowerShot G7 X Mark III" color_pattern = "RGGB" [cameras.color_matrix] A = [1.4076, -0.93, 0.1481, -0.1849, 0.9861, 0.233, 0.0229, 0.0399, 0.5916] D65 = [1.1629, -0.5713, -0.0914, -0.2706, 1.109, 0.1842, -0.0206, 0.1225, 0.5515] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/g9.toml000064400000000000000000000006151046102023000157650ustar 00000000000000make = "Canon" model = "Canon PowerShot G9" clean_make = "Canon" clean_model = "PowerShot G9" whitepoint = 4095 color_pattern = "RGGB" blackareav = [0, 46] active_area = [48, 12, 24, 12] [cameras.color_matrix] A = [0.8796, -0.377, 0.0311, -0.4148, 1.1362, 0.3197, -0.0598, 0.0983, 0.588] #TODO check, maybe wrong D65 = [0.7368, -0.2141, -0.0598, -0.5621, 1.3254, 0.2625, -0.1419, 0.1696, 0.5743] rawler-0.7.1/data/cameras/canon/g9x.toml000064400000000000000000000006151046102023000161550ustar 00000000000000make = "Canon" model = "Canon PowerShot G9 X" clean_make = "Canon" clean_model = "PowerShot G9 X" whitepoint = 16000 color_pattern = "RGGB" active_area = [96, 17, 0, 0] blackareav = [0, 70] blackareah = [0, 16] [cameras.color_matrix] A = [1.1125, -0.5937, 0.0355, -0.2979, 1.0926, 0.236, -0.0116, 0.0835, 0.6064] D65 = [0.9602, -0.3823, -0.0937, -0.2984, 1.1495, 0.1675, -0.0407, 0.1415, 0.5049] rawler-0.7.1/data/cameras/canon/g9xm2.toml000064400000000000000000000006121046102023000164110ustar 00000000000000make = "Canon" model = "Canon PowerShot G9 X Mark II" clean_make = "Canon" clean_model = "PowerShot G9 X Mark II" color_pattern = "RGGB" blackareav = [0, 70] blackareah = [0, 15] active_area = [96, 17, 0, 0] [cameras.color_matrix] A = [1.2216, -0.665, 0.0271, -0.3245, 1.1715, 0.1714, -0.0119, 0.0888, 0.6204] D65 = [1.0056, -0.4131, -0.0944, -0.2576, 1.1143, 0.1625, -0.0238, 0.1294, 0.5179] rawler-0.7.1/data/cameras/canon/ixy220f.toml000064400000000000000000000006571046102023000166570ustar 00000000000000make = "Canon" model = "Canon IXY 220F" clean_make = "Canon" clean_model = "IXY 220F" whitepoint = 4095 color_pattern = "RGGB" active_area = [96,17,8,1] filesize = 25230816 raw_width = 4784 raw_height = 3516 blackareav = [0, 94] [cameras.color_matrix] Daylight = [0.54480, -0.1740, -0.0803, -0.0750, 0.44044, 0.01136, -0.0058, 0.07158, 0.11891] D65 = [0.5307, -0.1727, -0.0741, -0.0846, 0.4464, 0.0142, -0.0022, 0.0786, 0.1405] rawler-0.7.1/data/cameras/canon/m.toml000064400000000000000000000005521046102023000157020ustar 00000000000000make = "Canon" model = "Canon EOS M" clean_make = "Canon" clean_model = "EOS M" color_pattern = "RGGB" blackareav = [0, 70] blackareah = [4, 44] active_area = [72, 52, 0, 0] [cameras.color_matrix] A = [0.6985, -0.1611, -0.0397, -0.3596, 1.0749, 0.3295, -0.0349, 0.1136, 0.6512] D65 = [0.6602, -0.0841, -0.0939, -0.4472, 1.2458, 0.2247, -0.0975, 0.2039, 0.6148] rawler-0.7.1/data/cameras/canon/m10.toml000064400000000000000000000005761046102023000160510ustar 00000000000000make = "Canon" model = "Canon EOS M10" clean_make = "Canon" clean_model = "EOS M10" whitepoint = 16000 color_pattern = "RGGB" blackareav = [0, 60] blackareah = [0, 40] active_area = [72, 52, 0, 0] [cameras.color_matrix] A = [0.9599, -0.3684, -0.0398, -0.3364, 1.1398, 0.2237, -0.0709, 0.1722, 0.6487] D65 = [0.64, -0.048, -0.0888, -0.5294, 1.3416, 0.2047, -0.1296, 0.2203, 0.6137] rawler-0.7.1/data/cameras/canon/m100.toml000064400000000000000000000005611046102023000161230ustar 00000000000000make = "Canon" model = "Canon EOS M100" clean_make = "Canon" clean_model = "EOS M100" color_pattern = "RGGB" blackareav = [0, 250] blackareah = [0, 30] active_area = [264, 34, 0, 0] [cameras.color_matrix] A = [0.9094, -0.1794, -0.0591, -0.4192, 1.1372, 0.3236, -0.0569, 0.1747, 0.8061] D65 = [0.8532, -0.0701, -0.1167, -0.4095, 1.1879, 0.2508, -0.0797, 0.2424, 0.701] rawler-0.7.1/data/cameras/canon/m2.toml000064400000000000000000000005511046102023000157630ustar 00000000000000make = "Canon" model = "Canon EOS M2" clean_make = "Canon" clean_model = "EOS M2" color_pattern = "RGGB" blackareav = [0, 70] blackareah = [4, 44] active_area = [72, 52, 0, 0] [cameras.color_matrix] A = [0.9599, -0.3684, -0.0398, -0.3364, 1.1398, 0.2237, -0.0709, 0.1722, 0.6487] D65 = [0.64, -0.048, -0.0888, -0.5294, 1.3416, 0.2047, -0.1296, 0.2203, 0.6137] rawler-0.7.1/data/cameras/canon/m200.toml000064400000000000000000000004401046102023000161200ustar 00000000000000make = "Canon" model = "Canon EOS M200" clean_make = "Canon" clean_model = "EOS M200" color_pattern = "RGGB" [cameras.color_matrix] D65 = [1.0463, -0.2173, -0.1437, -0.4856, 1.2635, 0.2482, -0.1216, 0.2915, 0.7237] # TODO [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/m3.toml000064400000000000000000000005771046102023000157740ustar 00000000000000make = "Canon" model = "Canon EOS M3" clean_make = "Canon" clean_model = "EOS M3" whitepoint = 16000 color_pattern = "RGGB" blackareav = [2, 68] blackareah = [2, 30] active_area = [72, 34, 0, 0] [cameras.color_matrix] A = [0.6671, -0.1668, -0.0272, -0.3729, 1.0665, 0.3552, -0.0409, 0.1271, 0.6293] D65 = [0.6362, -0.0823, -0.0847, -0.4426, 1.2109, 0.2616, -0.0743, 0.1857, 0.5635] rawler-0.7.1/data/cameras/canon/m5.toml000064400000000000000000000005611046102023000157670ustar 00000000000000make = "Canon" model = "Canon EOS M5" clean_make = "Canon" clean_model = "Canon EOS M5" color_pattern = "RGGB" blackareav = [0,260] blackareah = [0,30] active_area = [264, 34, 0, 0] [cameras.color_matrix] A = [0.9094, -0.1794, -0.0591, -0.4192, 1.1372, 0.3236, -0.0569, 0.1747, 0.8061] D65 = [0.8532, -0.0701, -0.1167, -0.4095, 1.1879, 0.2508, -0.0797, 0.2424, 0.701] rawler-0.7.1/data/cameras/canon/m50.toml000064400000000000000000000006771046102023000160570ustar 00000000000000make = "Canon" model = "Canon EOS M50" model_aliases = [ ["Canon EOS KISS M", "EOS KISS M"], ] clean_make = "Canon" clean_model = "EOS M50" color_pattern = "RGGB" active_area = [276, 48, 0, 0] [cameras.color_matrix] A = [0.9094, -0.1794, -0.0591, -0.4192, 1.1372, 0.3236, -0.0569, 0.1747, 0.8061] D65 = [0.8532, -0.0701, -0.1167, -0.4095, 1.1879, 0.2508, -0.0797, 0.2424, 0.701] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/m50mk2.toml000064400000000000000000000005611046102023000164610ustar 00000000000000make = "Canon" model = "Canon EOS M50m2" clean_make = "Canon" clean_model = "EOS M50 Mark II" color_pattern = "RGGB" [cameras.color_matrix] A = [1.2356, -0.4649, -0.0678, -0.391, 1.1644, 0.2577, -0.0455, 0.1934, 0.7348] D65 = [1.0463, -0.2173, -0.1437, -0.4856, 1.2635, 0.2482, -0.1216, 0.2915, 0.7237] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/m6.toml000064400000000000000000000005611046102023000157700ustar 00000000000000make = "Canon" model = "Canon EOS M6" clean_make = "Canon" clean_model = "Canon EOS M6" color_pattern = "RGGB" blackareav = [0,260] blackareah = [0,30] active_area = [264, 34, 0, 0] [cameras.color_matrix] A = [0.9094, -0.1794, -0.0591, -0.4192, 1.1372, 0.3236, -0.0569, 0.1747, 0.8061] D65 = [0.8532, -0.0701, -0.1167, -0.4095, 1.1879, 0.2508, -0.0797, 0.2424, 0.701] rawler-0.7.1/data/cameras/canon/m6mk2.toml000064400000000000000000000005661046102023000164070ustar 00000000000000make = "Canon" model = "Canon EOS M6 Mark II" clean_make = "Canon" clean_model = "EOS M6 Mark II" color_pattern = "RGGB" [cameras.color_matrix] A = [1.4683, -0.7448, -0.0905, -0.4609, 1.3134, 0.1588, -0.0324, 0.1195, 0.6559] D65 = [1.1498, -0.3759, -0.1516, -0.5073, 1.2954, 0.2349, -0.0892, 0.1867, 0.6118] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/pro1.toml000064400000000000000000000005541046102023000163310ustar 00000000000000make = "Canon" model = "Canon PowerShot Pro1" clean_make = "Canon" clean_model = "PowerShot Pro1" whitepoint = 4095 color_pattern = "RGGB" hints = ["wb_mangle"] blackareav = [3294,50] [cameras.color_matrix] A = [1.2248, -0.6026, 0.044, -0.6091, 1.3201, 0.324, -0.047, 0.0647, 0.7059] D65 = [1.0062, -0.3522, -0.1, -0.7643, 1.5117, 0.273, -0.0765, 0.0817, 0.7322] rawler-0.7.1/data/cameras/canon/pro70.toml.unsupp000064400000000000000000000007401046102023000177450ustar 00000000000000make = "Canon" model = "Canon PowerShot Pro70" clean_make = "Canon" clean_model = "PowerShot Pro70" blackpoint = 34 whitepoint = 990 color_pattern = "EBGRBERGEBRGBEGR" #crops = [0,0,0,0] #active_area = [0, 0, -16, 0] ##crop_area = [8, 0, -8, 0] [cameras.color_matrix] A = [-0.3134, 0.8164, 0.1796, 0.4059, -0.0318, 0.3818, -0.4285, 0.8509, 0.6816, -0.0731, 0.8024, 0.2184] D65 = [-0.5106, 1.0695, 0.1576, 0.382, 0.0053, 0.4566, -0.6497, 1.0736, 0.6701, -0.3336, 1.1887, 0.1394] rawler-0.7.1/data/cameras/canon/r.toml000064400000000000000000000005431046102023000157070ustar 00000000000000make = "Canon" model = "Canon EOS R" clean_make = "Canon" clean_model = "EOS R" color_pattern = "RGGB" [cameras.color_matrix] A = [0.9605, -0.3678, -0.015, -0.4268, 1.2125, 0.2412, -0.0364, 0.1578, 0.6818] D65 = [0.8293, -0.1789, -0.1094, -0.5025, 1.2925, 0.2327, -0.1199, 0.2769, 0.6108] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/r10.toml000064400000000000000000000005471046102023000160540ustar 00000000000000make = "Canon" model = "Canon EOS R10" clean_make = "Canon" clean_model = "EOS R10" color_pattern = "RGGB" [cameras.color_matrix] A = [1.1329, -0.4571, -0.0594, -0.3571, 1.1254, 0.2655, -0.0244, 0.1447, 0.5672] D65 = [0.9269, -0.2012, -0.1107, -0.399, 1.1762, 0.2527, -0.0569, 0.2093, 0.4913] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/r100.toml000064400000000000000000000005511046102023000161270ustar 00000000000000make = "Canon" model = "Canon EOS R100" clean_make = "Canon" clean_model = "EOS R100" color_pattern = "RGGB" [cameras.color_matrix] A = [0.9879, -0.3657, -0.0385, -0.3747, 1.1454, 0.2617, -0.0298, 0.1416, 0.5519] D65 = [0.823, -0.1515, -0.1032, -0.4179, 1.2005, 0.2454, -0.0649, 0.2076, 0.4711] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/r3.toml000064400000000000000000000005441046102023000157730ustar 00000000000000make = "Canon" model = "Canon EOS R3" clean_make = "Canon" clean_model = "EOS R3" color_pattern = "RGGB" [cameras.color_matrix] A = [1.1029, -0.5523, 0.0088, -0.411, 1.1671, 0.2778, -0.0165, 0.0658, 0.6438] D65 = [0.9423, -0.2839, -0.1195, -0.4532, 1.2377, 0.2415, -0.0483, 0.1374, 0.5276] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/r5.toml000064400000000000000000000006711046102023000157760ustar 00000000000000make = "Canon" model = "Canon EOS R5" clean_make = "Canon" clean_model = "EOS R5" color_pattern = "RGGB" remark = "support for CRM raw movie frame extraction" [cameras.color_matrix] A = [1.16, -0.6048, 0.0405, -0.3331, 1.0643, 0.3113, -0.0007, 0.0513, 0.6109] D65 = [0.9766, -0.2953, -0.1254, -0.4276, 1.2116, 0.2433, -0.0437, 0.1336, 0.5131] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" [[cameras.modes]] mode = "crm" rawler-0.7.1/data/cameras/canon/r50.toml000064400000000000000000000005471046102023000160600ustar 00000000000000make = "Canon" model = "Canon EOS R50" clean_make = "Canon" clean_model = "EOS R50" color_pattern = "RGGB" [cameras.color_matrix] A = [1.1329, -0.4571, -0.0594, -0.3571, 1.1254, 0.2655, -0.0244, 0.1447, 0.5672] D65 = [0.9269, -0.2012, -0.1107, -0.399, 1.1762, 0.2527, -0.0569, 0.2093, 0.4913] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/r5c.toml000064400000000000000000000006751046102023000161450ustar 00000000000000make = "Canon" model = "Canon EOS R5 C" clean_make = "Canon" clean_model = "EOS R5 C" color_pattern = "RGGB" remark = "support for CRM raw movie frame extraction" [cameras.color_matrix] A = [1.16, -0.6048, 0.0405, -0.3331, 1.0643, 0.3113, -0.0007, 0.0513, 0.6109] D65 = [0.9766, -0.2953, -0.1254, -0.4276, 1.2116, 0.2433, -0.0437, 0.1336, 0.5131] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" [[cameras.modes]] mode = "crm" rawler-0.7.1/data/cameras/canon/r5m2.toml000064400000000000000000000007041046102023000162320ustar 00000000000000make = "Canon" model = "Canon EOS R5m2" clean_make = "Canon" clean_model = "EOS R5 Mark II" color_pattern = "RGGB" remark = "support for CRM raw movie frame extraction" [cameras.color_matrix] A = [1.1261, -0.5701, 0.0384, -0.3524, 1.0833, 0.311, -0.0024, 0.0612, 0.7273] D65 = [0.9396, -0.2598, -0.1207, -0.4408, 1.2296, 0.2369, -0.0505, 0.1575, 0.6077] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" [[cameras.modes]] mode = "crm" rawler-0.7.1/data/cameras/canon/r6.toml000064400000000000000000000005441046102023000157760ustar 00000000000000make = "Canon" model = "Canon EOS R6" clean_make = "Canon" clean_model = "EOS R6" color_pattern = "RGGB" [cameras.color_matrix] A = [1.0492, -0.481, 0.0274, -0.3519, 1.0911, 0.3009, -0.0143, 0.1025, 0.6822] D65 = [0.8293, -0.1611, -0.1132, -0.4759, 1.2711, 0.2275, -0.1013, 0.2415, 0.5509] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/r6m2.toml000064400000000000000000000005561046102023000162400ustar 00000000000000make = "Canon" model = "Canon EOS R6m2" clean_make = "Canon" clean_model = "EOS R6 Mark II" color_pattern = "RGGB" [cameras.color_matrix] A = [1.1292, -0.5791, 0.0292, -0.323, 1.0487, 0.3185, -0.0083, 0.0959, 0.7099] D65 = [0.9539, -0.2795, -0.1224, -0.4175, 1.1998, 0.2458, -0.0465, 0.1755, 0.6048] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/r7.toml000064400000000000000000000005411046102023000157740ustar 00000000000000make = "Canon" model = "Canon EOS R7" clean_make = "Canon" clean_model = "EOS R7" color_pattern = "RGGB" [cameras.color_matrix] A = [1.2649, -0.646, -0.0013, -0.3506, 1.0855, 0.3061, -0.01, 0.0741, 0.7311] D65 = [1.0424, -0.3138, -0.13, -0.4221, 1.1938, 0.2584, -0.0547, 0.1658, 0.6183] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/r8.toml000064400000000000000000000005441046102023000160000ustar 00000000000000make = "Canon" model = "Canon EOS R8" clean_make = "Canon" clean_model = "EOS R8" color_pattern = "RGGB" [cameras.color_matrix] A = [1.1292, -0.5791, 0.0292, -0.323, 1.0487, 0.3185, -0.0083, 0.0959, 0.7099] D65 = [0.9539, -0.2795, -0.1224, -0.4175, 1.1998, 0.2458, -0.0465, 0.1755, 0.6048] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/rp.toml000064400000000000000000000005771046102023000160760ustar 00000000000000make = "Canon" model = "Canon EOS RP" clean_make = "Canon" clean_model = "EOS RP" color_pattern = "RGGB" hints = ["bogus_blackarea"] [cameras.color_matrix] A = [0.9665, -0.4042, -0.0053, -0.399, 1.1404, 0.2962, -0.022, 0.0939, 0.6291] D65 = [0.8608, -0.2097, -0.1178, -0.5425, 1.3265, 0.2383, -0.1149, 0.2238, 0.568] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/s100.toml000064400000000000000000000006211046102023000161260ustar 00000000000000make = "Canon" model = "Canon PowerShot S100" clean_make = "Canon" clean_model = "PowerShot S100" whitepoint = 4000 color_pattern = "GBRG" blackareav = [0, 100] blackareah = [3062, 60] active_area = [104, 11, 8, 65] [cameras.color_matrix] A = [0.9118, -0.3882, -0.0248, -0.2564, 0.9818, 0.3218, 0.0349, 0.0317, 0.4547] D65 = [0.7968, -0.2565, -0.0636, -0.2873, 1.0697, 0.2513, 0.018, 0.0667, 0.4211] rawler-0.7.1/data/cameras/canon/s100_crw.toml000064400000000000000000000005361046102023000170060ustar 00000000000000make = "Canon" model = "Canon PowerShot S100 CRW" clean_make = "Canon" clean_model = "PowerShot S100" whitepoint = 4000 color_pattern = "GBRG" blackareav = [0, 100] blackareah = [3062, 60] filesize = 19493760 raw_width = 4160 raw_height = 3124 [cameras.color_matrix] D65 = [0.7968, -0.2565, -0.0636, -0.2873, 1.0697, 0.2513, 0.0180, 0.0667, 0.4211] rawler-0.7.1/data/cameras/canon/s100v.toml000064400000000000000000000006231046102023000163160ustar 00000000000000make = "Canon" model = "Canon PowerShot S100V" clean_make = "Canon" clean_model = "PowerShot S100V" whitepoint = 4000 color_pattern = "GBRG" blackareav = [0, 100] blackareah = [3062, 60] active_area = [104, 11, 8, 65] [cameras.color_matrix] A = [0.9118, -0.3882, -0.0248, -0.2564, 0.9818, 0.3218, 0.0349, 0.0317, 0.4547] D65 = [0.7968, -0.2565, -0.0636, -0.2873, 1.0697, 0.2513, 0.018, 0.0667, 0.4211] rawler-0.7.1/data/cameras/canon/s110.toml000064400000000000000000000006141046102023000161310ustar 00000000000000make = "Canon" model = "Canon PowerShot S110" clean_make = "Canon" clean_model = "PowerShot S110" whitepoint = 4000 color_pattern = "GBRG" blackareav = [0, 100] blackareah = [3062, 60] active_area = [104, 11, 8, 65] [cameras.color_matrix] A = [0.9063, -0.411, 0.024, -0.2713, 0.9326, 0.3987, 0.014, 0.0247, 0.4262] D65 = [0.8039, -0.2643, -0.0654, -0.3783, 1.123, 0.293, -0.0206, 0.069, 0.4194] rawler-0.7.1/data/cameras/canon/s120.toml000064400000000000000000000005731046102023000161360ustar 00000000000000make = "Canon" model = "Canon PowerShot S120" clean_make = "Canon" clean_model = "PowerShot S120" whitepoint = 4000 color_pattern = "RGGB" blackareav = [0, 74] active_area = [120, 28, 48, 14] [cameras.color_matrix] A = [1.0392, -0.5112, 0.0132, -0.2477, 1.0648, 0.2109, -0.0488, 0.1587, 0.5753] D65 = [0.6961, -0.1685, -0.0695, -0.4625, 1.2945, 0.1836, -0.1114, 0.2152, 0.5518] rawler-0.7.1/data/cameras/canon/s2is.toml000064400000000000000000000004101046102023000163170ustar 00000000000000make = "Canon" model = "Canon PowerShot S2 IS" clean_make = "Canon" clean_model = "PowerShot S2 IS" color_pattern = "RGGB" active_area = [14, 10, 46, 2] [cameras.color_matrix] Daylight = [1.0416, -0.2728, -0.1887, -0.3553, 1.2627, 0.0969, -0.011, 0.1506, 0.5078] rawler-0.7.1/data/cameras/canon/s30.toml000064400000000000000000000006171046102023000160550ustar 00000000000000# CRW make = "Canon" model = "Canon PowerShot S30" clean_make = "Canon" clean_model = "PowerShot S30" whitepoint = 1023 color_pattern = "RGGB" active_area = [4,8,52,2] hints = ["nolowbits"] blackareav = [2094,50] [cameras.color_matrix] A = [1.2994, -0.6269, 0.022, -0.6794, 1.4578, 0.2391, -0.1337, 0.1824, 0.8313] D65 = [1.0744, -0.3813, -0.1142, -0.7962, 1.5966, 0.2075, -0.2492, 0.2805, 0.7744] rawler-0.7.1/data/cameras/canon/s3is.toml000064400000000000000000000005331046102023000163260ustar 00000000000000# CRW make = "Canon" model = "PowerShot S3 IS" clean_make = "Canon" clean_model = "PowerShot S3 IS" whitepoint = 1023 color_pattern = "RGGB" active_area = [44,8,4,0] filesize = 7710960 raw_width = 2888 raw_height = 2136 blackareav = [0,40] [cameras.color_matrix] D65 = [1.4062, -0.5199, -0.1446, -0.4712, 1.2470, 0.2243, -0.1286, 0.2028, 0.4836] rawler-0.7.1/data/cameras/canon/s40.toml000064400000000000000000000006611046102023000160550ustar 00000000000000# CRW make = "Canon" model = "Canon PowerShot S40" clean_make = "Canon" clean_model = "PowerShot S40" whitepoint = 1023 color_pattern = "RGGB" active_area = [12,6,52,2] hints = ["nolowbits"] blackareav = [2326,50] [cameras.params] wb_offset = 60 [cameras.color_matrix] A = [1.0021, -0.4192, -0.0066, -0.6784, 1.3755, 0.3378, -0.1543, 0.2132, 0.9431] D65 = [0.8606, -0.2573, -0.0949, -0.8237, 1.5489, 0.2974, -0.2649, 0.3076, 0.91] rawler-0.7.1/data/cameras/canon/s45.toml000064400000000000000000000006321046102023000160600ustar 00000000000000# CRW make = "Canon" model = "Canon PowerShot S45" clean_make = "Canon" clean_model = "PowerShot S45" whitepoint = 4095 color_pattern = "RGGB" active_area = [12,6,52,2] blackareav = [2326,50] [cameras.params] wb_offset = 60 [cameras.color_matrix] A = [0.9599, -0.3924, -0.0147, -0.6733, 1.3806, 0.3256, -0.1407, 0.1945, 0.8503] D65 = [0.8251, -0.241, -0.0964, -0.8047, 1.543, 0.2823, -0.238, 0.2824, 0.8119] rawler-0.7.1/data/cameras/canon/s50.toml000064400000000000000000000006321046102023000160540ustar 00000000000000# CRW make = "Canon" model = "Canon PowerShot S50" clean_make = "Canon" clean_model = "PowerShot S50" whitepoint = 4095 color_pattern = "RGGB" active_area = [12,6,44,2] blackareav = [2632,40] [cameras.params] wb_offset = 60 [cameras.color_matrix] A = [1.0191, -0.4276, 0.0059, -0.5606, 1.278, 0.3182, -0.0989, 0.1613, 0.6658] D65 = [0.8979, -0.2658, -0.0871, -0.7721, 1.55, 0.2357, -0.1773, 0.2366, 0.6634] rawler-0.7.1/data/cameras/canon/s60.toml000064400000000000000000000006621046102023000160600ustar 00000000000000# CRW make = "Canon" model = "Canon PowerShot S60" clean_make = "Canon" clean_model = "PowerShot S60" whitepoint = 4095 color_pattern = "RGGB" active_area = [12,6,44,2] hints = ["wb_mangle"] blackareav = [2632,40] [cameras.params] wb_offset = 48 [cameras.color_matrix] A = [1.0024, -0.4055, 0.0044, -0.5712, 1.2773, 0.3314, -0.0894, 0.1521, 0.6816] D65 = [0.8794, -0.2482, -0.0797, -0.7804, 1.5403, 0.2572, -0.1422, 0.1996, 0.7083] rawler-0.7.1/data/cameras/canon/s70.toml000064400000000000000000000006551046102023000160630ustar 00000000000000# CRW make = "Canon" model = "Canon PowerShot S70" clean_make = "Canon" clean_model = "PowerShot S70" whitepoint = 4095 color_pattern = "RGGB" active_area = [44,12,4,4] hints = ["wb_mangle"] blackareav = [0,40] [cameras.params] wb_offset = 48 [cameras.color_matrix] A = [1.2155, -0.614, 0.0388, -0.5537, 1.2581, 0.3343, -0.0569, 0.0834, 0.7498] D65 = [0.9976, -0.381, -0.0832, -0.7115, 1.4463, 0.2906, -0.0902, 0.0989, 0.7889] rawler-0.7.1/data/cameras/canon/s90.toml000064400000000000000000000005661046102023000160660ustar 00000000000000make = "Canon" model = "Canon PowerShot S90" clean_make = "Canon" clean_model = "PowerShot S90" whitepoint = 4095 color_pattern = "RGGB" active_area = [8, 16, 52, 8] blackareav = [3694, 50] [cameras.color_matrix] A = [2.038, -1.4279, 0.0975, 0.0145, 0.7942, 0.2325, 0.0374, 0.0172, 0.5441] D65 = [1.2374, -0.5016, -0.1049, -0.1677, 0.9902, 0.2078, -0.0083, 0.0852, 0.4683] rawler-0.7.1/data/cameras/canon/s95.toml000064400000000000000000000005661046102023000160730ustar 00000000000000make = "Canon" model = "Canon PowerShot S95" clean_make = "Canon" clean_model = "PowerShot S95" whitepoint = 4000 color_pattern = "RGGB" active_area = [64, 21, 16, 12] blackareav = [0, 50] [cameras.color_matrix] A = [1.5419, -0.8268, -0.0232, -0.0656, 0.8621, 0.2437, 0.0163, 0.0404, 0.5172] D65 = [1.344, -0.5896, -0.1279, -0.1236, 0.9598, 0.1931, -0.018, 0.1001, 0.4651] rawler-0.7.1/data/cameras/canon/sx110is.toml000064400000000000000000000005461046102023000166610ustar 00000000000000# CRW make = "Canon" model = "PowerShot SX110 IS" clean_make = "Canon" clean_model = "PowerShot SX110 IS" whitepoint = 4095 color_pattern = "RGGB" active_area = [6,12,30,0] filesize = 15467760 raw_width = 3720 raw_height = 2772 blackareav = [3690,30] [cameras.color_matrix] D65 = [1.4134, -0.5576, -0.1527, -0.1991, 1.0719, 0.1273, -0.1158, 0.1929, 0.3581] rawler-0.7.1/data/cameras/canon/sx150is.toml000064400000000000000000000005541046102023000166640ustar 00000000000000make = "Canon" model = "Canon PowerShot SX150 IS" clean_make = "Canon" clean_model = "PowerShot SX150 IS" whitepoint = 4095 color_pattern = "GBRG" filesize = 21936096 raw_width = 4464 raw_height = 3276 blackareav = [4396, 60] active_area = [25, 10, 73, 12] [cameras.color_matrix] D65 = [1.3481, -0.4867, -0.1063, -0.2074, 0.9960, 0.2472, -0.0170, 0.1474, 0.3894] rawler-0.7.1/data/cameras/canon/sx1is.toml000064400000000000000000000005721046102023000165170ustar 00000000000000make = "Canon" model = "Canon PowerShot SX1 IS" clean_make = "Canon" clean_model = "PowerShot SX1 IS" whitepoint = 4095 color_pattern = "RGGB" blackareav = [0, 188] active_area = [192, 12, 0, 0] [cameras.color_matrix] A = [0.786, -0.1783, 0.0256, -0.3961, 1.0537, 0.3978, 0.0062, 0.0771, 0.4698] D65 = [0.6578, -0.0259, -0.0502, -0.5974, 1.303, 0.3309, -0.0308, 0.1058, 0.497] rawler-0.7.1/data/cameras/canon/sx220hs.toml000064400000000000000000000005521046102023000166570ustar 00000000000000# CRW make = "Canon" model = "Canon PowerShot SX220 HS" clean_make = "Canon" clean_model = "PowerShot SX220 HS" whitepoint = 4095 color_pattern = "RGGB" active_area = [96,16,8,0] filesize = 19131120 raw_width = 4168 raw_height = 3060 blackareav = [0, 94] [cameras.color_matrix] D65 = [1.2432, -0.4753, -0.1247, -0.2110, 1.0691, 0.1629, -0.0412, 0.1623, 0.4926] rawler-0.7.1/data/cameras/canon/sx260hs.toml000064400000000000000000000005211046102023000166570ustar 00000000000000make = "Canon" model = "Canon PowerShot SX260 HS" clean_make = "Canon" clean_model = "PowerShot SX260 HS" whitepoint = 4095 color_pattern = "RGGB" filesize = 19167840 # todo raw_width = 4176 raw_height = 3060 blackareav = [0, 94] [cameras.color_matrix] D65 = [1.2432, -0.4753, -0.1247, -0.2110, 1.0691, 0.1629, -0.0412, 0.1623, 0.4926] rawler-0.7.1/data/cameras/canon/sx40hs.toml000064400000000000000000000005451046102023000166010ustar 00000000000000make = "Canon" model = "Canon PowerShot SX40 HS" clean_make = "Canon" clean_model = "PowerShot SX40 HS" whitepoint = 4095 color_pattern = "RGGB" active_area = [96, 16, 8, 0] filesize = 19167840 raw_width = 4176 raw_height = 3060 blackareav = [0, 94] [cameras.color_matrix] D65 = [1.2432, -0.4753, -0.1247, -0.2110, 1.0691, 0.1629, -0.0412, 0.1623, 0.4926] rawler-0.7.1/data/cameras/canon/sx50.toml000064400000000000000000000005711046102023000162460ustar 00000000000000make = "Canon" model = "Canon PowerShot SX50 HS" clean_make = "Canon" clean_model = "PowerShot SX50 HS" whitepoint = 4000 color_pattern = "RGGB" blackareav = [6, 70] active_area = [96, 18, 8, 0] [cameras.color_matrix] A = [1.3587, -0.6819, 0.06, -0.1159, 0.855, 0.3112, 0.0241, 0.0672, 0.5343] D65 = [1.2432, -0.4753, -0.1247, -0.211, 1.0691, 0.1629, -0.0412, 0.1623, 0.4926] rawler-0.7.1/data/cameras/canon/sx60hs.toml000064400000000000000000000006771046102023000166110ustar 00000000000000make = "Canon" model = "Canon PowerShot SX60 HS" clean_make = "Canon" clean_model = "PowerShot SX60 HS" whitepoint = 4000 color_pattern = "RGGB" blackareav = [0, 70] active_area = [96, 16, 0, 0] [cameras.params] fixed_lens_key = "canon_powershot_sx60hs_lens" [cameras.color_matrix] A = [1.5686, -0.8326, -0.0246, -0.1888, 1.0463, 0.1645, 0.0286, 0.0708, 0.6145] D65 = [1.3161, -0.5451, -0.1344, -0.1989, 1.0654, 0.1531, -0.0047, 0.1271, 0.4955] rawler-0.7.1/data/cameras/canon/sx70_hs.toml000064400000000000000000000006721046102023000167440ustar 00000000000000make = "Canon" model = "Canon PowerShot SX70 HS" clean_make = "Canon" clean_model = "PowerShot SX70 HS" color_pattern = "RGGB" [cameras.params] fixed_lens_key = "canon_powershot_sx70hs_lens" [cameras.color_matrix] A = [1.8214, -1.0357, 0.0257, -0.0756, 0.9461, 0.1536, 0.1018, 0.0228, 0.5656] D65 = [1.8285, -0.8907, -0.1951, -0.1845, 1.0688, 0.1323, 0.0364, 0.1101, 0.5139] [[cameras.modes]] mode = "raw" [[cameras.modes]] mode = "craw" rawler-0.7.1/data/cameras/canon/sx710hs.toml000064400000000000000000000005211046102023000166570ustar 00000000000000make = "Canon" model = "Canon PowerShot SX710 HS" clean_make = "Canon" clean_model = "PowerShot SX710 HS" whitepoint = 4095 color_pattern = "RGGB" filesize = 31663200 # todo raw_width = 4176 raw_height = 3060 blackareav = [0, 94] [cameras.color_matrix] D65 = [1.2432, -0.4753, -0.1247, -0.2110, 1.0691, 0.1629, -0.0412, 0.1623, 0.4926] rawler-0.7.1/data/cameras/epson/r-d1.toml000064400000000000000000000004241046102023000162350ustar 00000000000000make = "SEIKO EPSON CORP." model = "R-D1" clean_make = "Epson" clean_model = "R-D1" #blackpoint = 63 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] [cameras.color_matrix] D65 = [0.6827, -0.1878, -0.0732, -0.8429, 1.6012, 0.2564, -0.0704, 0.0592, 0.7145] rawler-0.7.1/data/cameras/epson/r-d1s.toml000064400000000000000000000004261046102023000164220ustar 00000000000000make = "SEIKO EPSON CORP." model = "R-D1s" clean_make = "Epson" clean_model = "R-D1s" #blackpoint = 63 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] [cameras.color_matrix] D65 = [0.6827, -0.1878, -0.0732, -0.8429, 1.6012, 0.2564, -0.0704, 0.0592, 0.7145] rawler-0.7.1/data/cameras/epson/r-d1x.toml000064400000000000000000000004261046102023000164270ustar 00000000000000make = "SEIKO EPSON CORP." model = "R-D1x" clean_make = "Epson" clean_model = "R-D1x" #blackpoint = 63 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] [cameras.color_matrix] D65 = [0.6827, -0.1878, -0.0732, -0.8429, 1.6012, 0.2564, -0.0704, 0.0592, 0.7145] rawler-0.7.1/data/cameras/fuji/dbp_gx680.toml000064400000000000000000000004751046102023000170120ustar 00000000000000make = "FUJIFILM" model = "DBP for GX680" clean_make = "Fujifilm" clean_model = "DBP for GX680" blackpoint = 128 whitepoint = 4095 color_pattern = "GBRG" active_area = [0, 0, 0, 0] hints = ["fuji_rotation_alt"] [cameras.color_matrix] D65 = [1.2407, -0.5222, -0.1086, -0.2971, 1.1116, 0.212, -0.0294, 0.1029, 0.5284] rawler-0.7.1/data/cameras/fuji/e550.toml000064400000000000000000000006461046102023000157670ustar 00000000000000make = "FUJIFILM" model = "FinePix E550" clean_make = "Fujifilm" clean_model = "FinePix E550" blackpoint = 0 whitepoint = 15875 color_pattern = "GBRG" hints = ["fuji_rotation"] active_area = [0, 0, 0, 0] #crop_area = [20, 12, 20, 12] [cameras.color_matrix] A = [1.2997, -0.6125, 0.0222, -0.5472, 1.2852, 0.2939, -0.0796, 0.1547, 0.7921] D65 = [1.1044, -0.3888, -0.112, -0.7248, 1.5167, 0.2208, -0.1531, 0.2276, 0.8069] rawler-0.7.1/data/cameras/fuji/e900.toml000064400000000000000000000006421046102023000157620ustar 00000000000000make = "FUJIFILM" model = "FinePix E900" clean_make = "Fujifilm" clean_model = "FinePix E900" blackpoint = 0 whitepoint = 15564 color_pattern = "GBRG" hints = ["fuji_rotation"] active_area = [0, 0, 0, 0] crop_area = [20, 7, 20, 7] [cameras.color_matrix] A = [0.9959, -0.3669, -0.0433, -0.5419, 1.2525, 0.3273, -0.1267, 0.184, 0.8407] D65 = [0.9183, -0.2526, -0.1078, -0.7461, 1.5071, 0.2574, -0.2023, 0.244, 0.8638] rawler-0.7.1/data/cameras/fuji/f550exr.toml000064400000000000000000000005631046102023000165050ustar 00000000000000make = "FUJIFILM" model = "FinePix F550EXR" clean_make = "Fujifilm" clean_model = "FinePix F550EXR" #blackpoint = 256 whitepoint = 3900 color_pattern = "RGGB" active_area = [34, 0, 32, 0] [cameras.color_matrix] A = [1.4143, -0.6562, -0.059, -0.2896, 1.0673, 0.2569, 0.0255, 0.0893, 0.5002] D65 = [1.369, -0.5358, -0.1474, -0.3369, 1.16, 0.1998, -0.0132, 0.1554, 0.4395] rawler-0.7.1/data/cameras/fuji/f600exr.toml000064400000000000000000000005631046102023000165010ustar 00000000000000make = "FUJIFILM" model = "FinePix F600EXR" clean_make = "Fujifilm" clean_model = "FinePix F600EXR" #blackpoint = 256 whitepoint = 3900 color_pattern = "RGGB" active_area = [34, 0, 32, 0] [cameras.color_matrix] A = [1.4143, -0.6562, -0.059, -0.2896, 1.0673, 0.2569, 0.0255, 0.0893, 0.5002] D65 = [1.369, -0.5358, -0.1474, -0.3369, 1.16, 0.1998, -0.0132, 0.1554, 0.4395] rawler-0.7.1/data/cameras/fuji/f700.toml000064400000000000000000000006651046102023000157660ustar 00000000000000make = "FUJIFILM" model = "FinePix F700" clean_make = "Fujifilm" clean_model = "FinePix F700" blackpoint = 0 whitepoint = 16383 color_pattern = "GBRG" hints = ["fuji_rotation", "double_width"] active_area = [0, 0, 0, 0] crop_area = [20, 12, 20, 12] [cameras.color_matrix] A = [1.0887, -0.455, -0.0422, -0.5779, 1.3398, 0.2635, -0.1202, 0.1834, 0.8233] D65 = [1.0004, -0.3219, -0.1201, -0.7036, 1.5047, 0.2107, -0.1863, 0.2565, 0.7735] rawler-0.7.1/data/cameras/fuji/f770exr.toml000064400000000000000000000005631046102023000165110ustar 00000000000000make = "FUJIFILM" model = "FinePix F770EXR" clean_make = "Fujifilm" clean_model = "FinePix F770EXR" #blackpoint = 256 whitepoint = 3900 color_pattern = "RGGB" active_area = [34, 0, 32, 0] [cameras.color_matrix] A = [1.4143, -0.6562, -0.059, -0.2896, 1.0673, 0.2569, 0.0255, 0.0893, 0.5002] D65 = [1.369, -0.5358, -0.1474, -0.3369, 1.16, 0.1998, -0.0132, 0.1554, 0.4395] rawler-0.7.1/data/cameras/fuji/f900exr.toml000064400000000000000000000005641046102023000165050ustar 00000000000000make = "FUJIFILM" model = "FinePix F900EXR" clean_make = "Fujifilm" clean_model = "FinePix F900EXR" #blackpoint = 256 whitepoint = 3900 color_pattern = "BGGR" active_area = [0, 0, 64, 0] [cameras.color_matrix] A = [1.4011, -0.711, 0.1221, -0.2726, 1.0617, 0.2439, 0.0329, 0.1008, 0.5535] D65 = [1.2085, -0.4727, -0.0953, -0.3257, 1.1489, 0.2002, -0.0511, 0.2046, 0.4592] rawler-0.7.1/data/cameras/fuji/gfx100.toml000064400000000000000000000005001046102023000163030ustar 00000000000000make = "FUJIFILM" model = "GFX 100" clean_make = "Fujifilm" clean_model = "GFX 100" color_pattern = "RGGB" active_area = [0, 4, 144, 2] [cameras.color_matrix] A = [1.7191, -1.1, 0.1278, -0.3574, 1.1733, 0.2076, -0.0003, 0.0497, 0.654] D65 = [1.6212, -0.8423, -0.1583, -0.4336, 1.2583, 0.1937, -0.0195, 0.0726, 0.6199] rawler-0.7.1/data/cameras/fuji/gfx100mk2.toml000064400000000000000000000004101046102023000167150ustar 00000000000000make = "FUJIFILM" model = "GFX100 II" clean_make = "Fujifilm" clean_model = "GFX 100 II" color_pattern = "RGGB" active_area = [0, 2, 144, 4] [cameras.color_matrix] D65 = [1.2806, -0.5779, -0.1110, -0.3546, 1.1507, 0.2318, -0.0177, 0.0996, 0.5715] #TODO: A matrix rawler-0.7.1/data/cameras/fuji/gfx100rf.toml000064400000000000000000000005041046102023000166370ustar 00000000000000make = "FUJIFILM" model = "GFX100RF" clean_make = "Fujifilm" clean_model = "GFX 100RF" color_pattern = "RGGB" active_area = [0, 0, 144, 4] [cameras.color_matrix] A = [1.5656, -1.0088, 0.1263, -0.2871, 1.0498, 0.2752, 0.0065, 0.0436, 0.6714] D65 = [1.2806, -0.5779, -0.111, -0.3546, 1.1507, 0.2318, -0.0177, 0.0996, 0.5715] rawler-0.7.1/data/cameras/fuji/gfx100s.toml000064400000000000000000000005001046102023000164660ustar 00000000000000make = "FUJIFILM" model = "GFX100S" clean_make = "Fujifilm" clean_model = "GFX 100S" color_pattern = "RGGB" active_area = [0, 4, 144, 2] [cameras.color_matrix] A = [1.7191, -1.1, 0.1278, -0.3574, 1.1733, 0.2076, -0.0003, 0.0497, 0.654] D65 = [1.6212, -0.8423, -0.1583, -0.4336, 1.2583, 0.1937, -0.0195, 0.0726, 0.6199] rawler-0.7.1/data/cameras/fuji/gfx100smk2.toml000064400000000000000000000005101046102023000171010ustar 00000000000000make = "FUJIFILM" model = "GFX100S II" clean_make = "Fujifilm" clean_model = "GFX 100S II" color_pattern = "RGGB" active_area = [0, 0, 144, 4] [cameras.color_matrix] A = [1.5656, -1.0088, 0.1263, -0.2871, 1.0498, 0.2752, 0.0065, 0.0436, 0.6714] D65 = [1.2806, -0.5779, -0.111, -0.3546, 1.1507, 0.2318, -0.0177, 0.0996, 0.5715] rawler-0.7.1/data/cameras/fuji/gfx50r.toml000064400000000000000000000005041046102023000164150ustar 00000000000000make = "FUJIFILM" model = "GFX 50R" clean_make = "Fujifilm" clean_model = "GFX 50R" color_pattern = "RGGB" active_area = [0, 0, 936, 2] [cameras.color_matrix] A = [1.4263, -0.7628, 0.0628, -0.3694, 1.1552, 0.2436, -0.0287, 0.1086, 0.7339] D65 = [1.1756, -0.4754, -0.0874, -0.3056, 1.1045, 0.2305, -0.0381, 0.1457, 0.6006] rawler-0.7.1/data/cameras/fuji/gfx50s.toml000064400000000000000000000005031046102023000164150ustar 00000000000000make = "FUJIFILM" model = "GFX 50S" clean_make = "Fujifilm" clean_model = "GFX 50S" color_pattern = "RGGB" active_area = [0, 0, 936, 2] [cameras.color_matrix] A = [1.4263, -0.7628, 0.0628, -0.3694, 1.1552, 0.2436, -0.0287, 0.1086, 0.7339] D65 = [1.1756, -0.4754, -0.0874, -0.3056, 1.1045, 0.2305, -0.0381, 0.1457, 0.6006] rawler-0.7.1/data/cameras/fuji/gfx50smk2.toml000064400000000000000000000005101046102023000170250ustar 00000000000000make = "FUJIFILM" model = "GFX50S II" clean_make = "Fujifilm" clean_model = "GFX 50S II" color_pattern = "RGGB" active_area = [0, 0, 192, 2] [cameras.color_matrix] A = [1.4263, -0.7628, 0.0628, -0.3694, 1.1552, 0.2436, -0.0287, 0.1086, 0.7339] D65 = [1.1756, -0.4754, -0.0874, -0.3056, 1.1045, 0.2305, -0.0381, 0.1457, 0.6006] rawler-0.7.1/data/cameras/fuji/hs10.toml000064400000000000000000000006451046102023000160630ustar 00000000000000make = "FUJIFILM" model = "FinePix HS10 HS11" clean_make = "Fujifilm" clean_model = "FinePix HS10 HS11" #blackpoint = 50 whitepoint = 3900 color_pattern = "BGGR" hints = ["jpeg32"] active_area = [0, 0, 0, 0] crop_area = [0, 0, 16, 6] [cameras.color_matrix] A = [1.2397, -0.4533, -0.0514, -0.0873, 0.9115, 0.2093, 0.0217, 0.1135, 0.4851] D65 = [1.244, -0.3954, -0.1183, -0.1123, 0.9674, 0.1708, -0.0083, 0.1614, 0.4086] rawler-0.7.1/data/cameras/fuji/hs20exr.toml000064400000000000000000000005631046102023000166020ustar 00000000000000make = "FUJIFILM" model = "FinePix HS20EXR" clean_make = "Fujifilm" clean_model = "FinePix HS20EXR" #blackpoint = 256 whitepoint = 3900 color_pattern = "RGGB" active_area = [34, 0, 32, 0] [cameras.color_matrix] A = [1.4143, -0.6562, -0.059, -0.2896, 1.0673, 0.2569, 0.0255, 0.0893, 0.5002] D65 = [1.369, -0.5358, -0.1474, -0.3369, 1.16, 0.1998, -0.0132, 0.1554, 0.4395] rawler-0.7.1/data/cameras/fuji/hs30exr.toml000064400000000000000000000005631046102023000166030ustar 00000000000000make = "FUJIFILM" model = "FinePix HS30EXR" clean_make = "Fujifilm" clean_model = "FinePix HS30EXR" #blackpoint = 256 whitepoint = 3900 color_pattern = "RGGB" active_area = [34, 0, 32, 0] [cameras.color_matrix] A = [1.4143, -0.6562, -0.059, -0.2896, 1.0673, 0.2569, 0.0255, 0.0893, 0.5002] D65 = [1.369, -0.5358, -0.1474, -0.3369, 1.16, 0.1998, -0.0132, 0.1554, 0.4395] rawler-0.7.1/data/cameras/fuji/hs33exr.toml000064400000000000000000000005631046102023000166060ustar 00000000000000make = "FUJIFILM" model = "FinePix HS33EXR" clean_make = "Fujifilm" clean_model = "FinePix HS33EXR" #blackpoint = 256 whitepoint = 3900 color_pattern = "RGGB" active_area = [34, 0, 32, 0] [cameras.color_matrix] A = [1.4143, -0.6562, -0.059, -0.2896, 1.0673, 0.2569, 0.0255, 0.0893, 0.5002] D65 = [1.369, -0.5358, -0.1474, -0.3369, 1.16, 0.1998, -0.0132, 0.1554, 0.4395] rawler-0.7.1/data/cameras/fuji/hs50exr.toml000064400000000000000000000005641046102023000166060ustar 00000000000000make = "FUJIFILM" model = "FinePix HS50EXR" clean_make = "Fujifilm" clean_model = "FinePix HS50EXR" #blackpoint = 256 whitepoint = 3900 color_pattern = "BGGR" active_area = [0, 0, 64, 0] [cameras.color_matrix] A = [1.4011, -0.711, 0.1221, -0.2726, 1.0617, 0.2439, 0.0329, 0.1008, 0.5535] D65 = [1.2085, -0.4727, -0.0953, -0.3257, 1.1489, 0.2002, -0.0511, 0.2046, 0.4592] rawler-0.7.1/data/cameras/fuji/s1.toml000064400000000000000000000005741046102023000156340ustar 00000000000000make = "FUJIFILM" model = "FinePix S1" clean_make = "FUJIFILM" clean_model = "FinePix S1" #blackpoint = 200 whitepoint = 4095 color_pattern = "RGGB" hints = ["jpeg32"] active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [1.3564, -0.6721, 0.0263, -0.2155, 1.0316, 0.2135, 0.0164, 0.0821, 0.5853] D65 = [1.2297, -0.4882, -0.1202, -0.2106, 1.0691, 0.1623, -0.0088, 0.1312, 0.479] rawler-0.7.1/data/cameras/fuji/s100fs.toml000064400000000000000000000006551046102023000163250ustar 00000000000000make = "FUJIFILM" model = "FinePix S100FS" clean_make = "Fujifilm" clean_model = "FinePix S100FS" blackpoint = 519 whitepoint = 16250 color_pattern = "GBRG" hints = ["fuji_rotation_alt"] active_area = [0, 0, 0, 0] crop_area = [16, 10, 16, 10] [cameras.color_matrix] A = [1.2958, -0.6344, 0.0202, -0.4492, 1.1187, 0.381, -0.0658, 0.1223, 0.6067] D65 = [1.1521, -0.4355, -0.1065, -0.6524, 1.3768, 0.3059, -0.1466, 0.1984, 0.6045] rawler-0.7.1/data/cameras/fuji/s200exr.toml000064400000000000000000000005661046102023000165150ustar 00000000000000make = "FUJIFILM" model = "FinePix S200EXR" clean_make = "Fujifilm" clean_model = "FinePix S200EXR" blackpoint = 519 whitepoint = 16250 color_pattern = "RGGB" active_area = [28, 0, 28, 0] [cameras.color_matrix] A = [1.2079, -0.5911, -0.0534, -0.3912, 1.0806, 0.3595, -0.0286, 0.07, 0.6474] D65 = [1.1401, -0.4498, -0.1312, -0.5088, 1.2751, 0.2613, -0.0838, 0.1568, 0.5941] rawler-0.7.1/data/cameras/fuji/s2pro.toml000064400000000000000000000006471046102023000163570ustar 00000000000000make = "FUJIFILM" model = "FinePixS2Pro" clean_make = "Fujifilm" clean_model = "FinePix S2Pro" blackpoint = 126 whitepoint = 4095 color_pattern = "GBRG" hints = ["fuji_rotation_alt"] active_area = [0, 0, 0, 0] crop_area = [18, 7, 14, 8] [cameras.color_matrix] A = [1.4449, -0.7082, -0.0021, -0.7007, 1.4807, 0.2364, -0.0943, 0.1521, 0.7891] D65 = [1.2741, -0.4916, -0.142, -0.851, 1.6791, 0.1715, -0.1767, 0.2302, 0.7771] rawler-0.7.1/data/cameras/fuji/s3pro.toml000064400000000000000000000006771046102023000163630ustar 00000000000000make = "FUJIFILM" model = "FinePix S3Pro" clean_make = "Fujifilm" clean_model = "FinePix S3Pro" blackpoint = 0 whitepoint = 16383 #color_pattern = "GBRG" color_pattern = "RGGB" hints = ["fuji_rotation_alt"] active_area = [0, 0, 2, 0] crop_area = [17, 9, 15, 7] [cameras.color_matrix] A = [1.4029, -0.7216, 0.0172, -0.7176, 1.4717, 0.2669, -0.1088, 0.1769, 0.8187] D65 = [1.1808, -0.4612, -0.1294, -0.8927, 1.6969, 0.1988, -0.212, 0.2742, 0.8006] rawler-0.7.1/data/cameras/fuji/s5000.toml000064400000000000000000000006451046102023000160570ustar 00000000000000make = "FUJIFILM" model = "FinePix S5000" clean_make = "Fujifilm" clean_model = "FinePix S5000" blackpoint = 0 whitepoint = 15866 color_pattern = "GBRG" hints = ["fuji_rotation"] active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] [cameras.color_matrix] A = [0.9623, -0.3885, -0.0342, -0.549, 1.2863, 0.2947, -0.0959, 0.1637, 0.6933] D65 = [0.8754, -0.2733, -0.1019, -0.7204, 1.5069, 0.2276, -0.1702, 0.2334, 0.6982] rawler-0.7.1/data/cameras/fuji/s5200.toml000064400000000000000000000006471046102023000160630ustar 00000000000000make = "FUJIFILM" model = "FinePix S5200" clean_make = "Fujifilm" clean_model = "FinePix S5200" blackpoint = 0 whitepoint = 15564 color_pattern = "GBRG" hints = ["fuji_rotation"] active_area = [0, 0, 0, 0] crop_area = [20, 10, 20, 10] [cameras.color_matrix] A = [1.0677, -0.4331, -0.0085, -0.5352, 1.2433, 0.3305, -0.1078, 0.1735, 0.8502] D65 = [0.9635, -0.2804, -0.0988, -0.7442, 1.504, 0.2589, -0.1803, 0.2312, 0.8621] rawler-0.7.1/data/cameras/fuji/s5500.toml000064400000000000000000000005551046102023000160640ustar 00000000000000make = "FUJIFILM" model = "FinePix S5500" clean_make = "Fujifilm" clean_model = "FinePix S5500" blackpoint = 0 whitepoint = 15880 color_pattern = "RGGB" active_area = [0, 6, 0, 0] [cameras.color_matrix] A = [1.4498, -0.7039, -0.0003, -0.5606, 1.2976, 0.2945, -0.0629, 0.09, 0.7207] D65 = [1.194, -0.4431, -0.1255, -0.6766, 1.4428, 0.2542, -0.0994, 0.1165, 0.7421] rawler-0.7.1/data/cameras/fuji/s5600.toml000064400000000000000000000006471046102023000160670ustar 00000000000000make = "FUJIFILM" model = "FinePix S5600" clean_make = "Fujifilm" clean_model = "FinePix S5600" blackpoint = 0 whitepoint = 15564 color_pattern = "GBRG" hints = ["fuji_rotation"] active_area = [0, 0, 0, 0] crop_area = [20, 10, 20, 10] [cameras.color_matrix] A = [1.0677, -0.4331, -0.0085, -0.5352, 1.2433, 0.3305, -0.1078, 0.1735, 0.8502] D65 = [0.9635, -0.2804, -0.0988, -0.7442, 1.504, 0.2589, -0.1803, 0.2312, 0.8621] rawler-0.7.1/data/cameras/fuji/s5pro.toml000064400000000000000000000006131046102023000163530ustar 00000000000000make = "FUJIFILM" model = "FinePix S5Pro" clean_make = "Fujifilm" clean_model = "FinePix S5Pro" blackpoint = 0 whitepoint = 16383 color_pattern = "RGGB" hints = ["fuji_rotation_alt"] active_area = [0, 0, 2, 0] [cameras.color_matrix] A = [1.4832, -0.7948, 0.0156, -0.7246, 1.4742, 0.2722, -0.1011, 0.1555, 0.8257] D65 = [1.2301, -0.5111, -0.1305, -0.9117, 1.7143, 0.1997, -0.1947, 0.2449, 0.81] rawler-0.7.1/data/cameras/fuji/s6500fd.toml000064400000000000000000000006211046102023000163710ustar 00000000000000make = "FUJIFILM" model = "FinePix S6500fd" clean_make = "Fujifilm" clean_model = "FinePix S6500fd" blackpoint = 0 whitepoint = 15564 color_pattern = "GBRG" hints = ["fuji_rotation_alt"] active_area = [64, 0, 64, 0] [cameras.color_matrix] A = [1.5156, -0.778, 0.0205, -0.5075, 1.2816, 0.2519, -0.1162, 0.1898, 0.7127] D65 = [1.2628, -0.4886, -0.1401, -0.686, 1.4997, 0.1962, -0.2198, 0.2782, 0.7091] rawler-0.7.1/data/cameras/fuji/s7000.toml000064400000000000000000000006441046102023000160600ustar 00000000000000make = "FUJIFILM" model = "FinePix S7000" clean_make = "Fujifilm" clean_model = "FinePix S7000" blackpoint = 0 whitepoint = 15564 color_pattern = "GBRG" hints = ["fuji_rotation"] active_area = [0, 0, 0, 0] crop_area = [20, 12, 20, 12] [cameras.color_matrix] A = [1.1722, -0.5492, -0.022, -0.5383, 1.2732, 0.298, -0.1296, 0.1807, 0.7597] D65 = [1.019, -0.3506, -0.1312, -0.7153, 1.5051, 0.2238, -0.2004, 0.2398, 0.7505] rawler-0.7.1/data/cameras/fuji/s9500.toml000064400000000000000000000006461046102023000160710ustar 00000000000000make = "FUJIFILM" model = "FinePix S9500" clean_make = "Fujifilm" clean_model = "FinePix S9500" blackpoint = 0 whitepoint = 15564 color_pattern = "GBRG" hints = ["fuji_rotation"] active_area = [0, 0, 0, 0] crop_area = [20, 7, 20, 7] [cameras.color_matrix] A = [1.1954, -0.5328, -0.0113, -0.5294, 1.2402, 0.3275, -0.1124, 0.1711, 0.8553] D65 = [1.0491, -0.3423, -0.1145, -0.7385, 1.5027, 0.2539, -0.1809, 0.2275, 0.8692] rawler-0.7.1/data/cameras/fuji/s9600.toml000064400000000000000000000006051046102023000160650ustar 00000000000000make = "FUJIFILM" model = "FinePix S9600" clean_make = "Fujifilm" clean_model = "FinePix S9600" blackpoint = 0 whitepoint = 15564 color_pattern = "GBRG" hints = ["fuji_rotation"] active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [1.435, -0.7185, 0.0234, -0.5042, 1.2247, 0.317, -0.1026, 0.1757, 0.8848] D65 = [1.2343, -0.4515, -0.1285, -0.7165, 1.49, 0.2435, -0.1895, 0.2496, 0.8801] rawler-0.7.1/data/cameras/fuji/sl1000.toml000064400000000000000000000006131046102023000162220ustar 00000000000000make = "FUJIFILM" model = "FinePix SL1000" clean_make = "FUJIFILM" clean_model = "FinePix SL1000" whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 7, 8, 7] hints = ["jpeg32"] [cameras.color_matrix] A = [1.3562, -0.6728, 0.0798, -0.1328, 0.9244, 0.2468, 0.024, 0.0784, 0.5548] D65 = [1.1705, -0.4262, -0.1107, -0.2282, 1.0791, 0.1709, -0.0555, 0.1713, 0.4945] rawler-0.7.1/data/cameras/fuji/x-a1.toml000064400000000000000000000005351046102023000160540ustar 00000000000000make = "FUJIFILM" model = "X-A1" clean_make = "Fujifilm" clean_model = "X-A1" #blackpoint = 256 whitepoint = 4094 color_pattern = "RGGB" active_area = [0, 0, 168, 0] [cameras.color_matrix] A = [1.3008, -0.6975, 0.105, -0.2611, 0.9857, 0.3225, -0.0214, 0.0644, 0.664] D65 = [1.1086, -0.4555, -0.0839, -0.3512, 1.131, 0.2517, -0.0815, 0.1341, 0.594] rawler-0.7.1/data/cameras/fuji/x-a10.toml000064400000000000000000000005251046102023000161330ustar 00000000000000make = "FUJIFILM" model = "X-A10" clean_make = "Fujifilm" clean_model = "X-A10" #blackpoint = 0 whitepoint = 4096 color_pattern = "RGGB" hints = ["jpeg32"] [cameras.color_matrix] A = [1.4157, -0.7885, 0.044, -0.3477, 1.1409, 0.2355, -0.0315, 0.0784, 0.6655] D65 = [1.154, -0.4999, -0.0991, -0.2949, 1.0963, 0.2278, -0.0382, 0.1049, 0.5605] rawler-0.7.1/data/cameras/fuji/x-a2.toml000064400000000000000000000005351046102023000160550ustar 00000000000000make = "FUJIFILM" model = "X-A2" clean_make = "Fujifilm" clean_model = "X-A2" #blackpoint = 256 whitepoint = 4094 color_pattern = "RGGB" active_area = [0, 0, 168, 0] [cameras.color_matrix] A = [1.2721, -0.69, 0.032, -0.3619, 1.1376, 0.2562, -0.0342, 0.0808, 0.6972] D65 = [1.0763, -0.456, -0.0917, -0.3346, 1.1311, 0.2322, -0.0475, 0.1135, 0.5843] rawler-0.7.1/data/cameras/fuji/x-a3.toml000064400000000000000000000005251046102023000160550ustar 00000000000000make = "FUJIFILM" model = "X-A3" clean_make = "Fujifilm" clean_model = "X-A3" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RGGB" hints = ["jpeg32"] [cameras.color_matrix] A = [1.4906, -0.8074, 0.0423, -0.3589, 1.165, 0.2195, -0.0217, 0.074, 0.637] D65 = [1.2407, -0.5222, -0.1086, -0.2971, 1.1116, 0.212, -0.0294, 0.1029, 0.5284] rawler-0.7.1/data/cameras/fuji/x-a5.toml000064400000000000000000000005271046102023000160610ustar 00000000000000make = "FUJIFILM" model = "X-A5" clean_make = "Fujifilm" clean_model = "X-A5" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RGGB" hints = ["jpeg32"] [cameras.color_matrix] A = [1.4259, -0.8049, 0.1087, -0.2249, 0.9662, 0.3037, 0.0053, 0.0427, 0.6328] D65 = [1.1673, -0.476, -0.1041, -0.3988, 1.2058, 0.2166, -0.0771, 0.1417, 0.5569] rawler-0.7.1/data/cameras/fuji/x-a7.toml000064400000000000000000000005261046102023000160620ustar 00000000000000make = "FUJIFILM" model = "X-A7" clean_make = "Fujifilm" clean_model = "X-A7" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RGGB" hints = ["jpeg32"] [cameras.color_matrix] A = [2.2235, -1.5902, 0.0516, -0.3091, 1.1246, 0.2102, 0.0018, 0.047, 0.6638] D65 = [1.5055, -0.7391, -0.1274, -0.4062, 1.2071, 0.2238, -0.061, 0.1217, 0.6147] rawler-0.7.1/data/cameras/fuji/x-e1.toml000064400000000000000000000006001046102023000160510ustar 00000000000000make = "FUJIFILM" model = "X-E1" clean_make = "Fujifilm" clean_model = "X-E1" #blackpoint = 256 whitepoint = 4094 color_pattern = "GGRGGBGGBGGRBRGRBGGGBGGRGGRGGBRBGBRG" active_area = [0, 0, 168, 0] [cameras.color_matrix] A = [1.2049, -0.5867, -0.0192, -0.3063, 1.0541, 0.2923, -0.0228, 0.0797, 0.6882] D65 = [1.0413, -0.3996, -0.0993, -0.3721, 1.164, 0.2361, -0.0733, 0.154, 0.6011] rawler-0.7.1/data/cameras/fuji/x-e2.toml000064400000000000000000000005771046102023000160670ustar 00000000000000make = "FUJIFILM" model = "X-E2" clean_make = "Fujifilm" clean_model = "X-E2" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [0, 0, 52, 0] [cameras.color_matrix] A = [1.267, -0.66, 0.0088, -0.2824, 1.0665, 0.2495, -0.0842, 0.1988, 0.7109] D65 = [0.8458, -0.2451, -0.0855, -0.4597, 1.2447, 0.2407, -0.1475, 0.2482, 0.6526] rawler-0.7.1/data/cameras/fuji/x-e2s.toml000064400000000000000000000006031046102023000162400ustar 00000000000000make = "FUJIFILM" model = "X-E2S" clean_make = "Fujifilm" clean_model = "X-E2S" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [0, 0, 52, 0] [cameras.color_matrix] A = [1.3789, -0.7728, 0.0646, -0.3128, 1.0855, 0.262, -0.0281, 0.1061, 0.7321] D65 = [1.1562, -0.5118, -0.0961, -0.3022, 1.1007, 0.2311, -0.0525, 0.1569, 0.6097] rawler-0.7.1/data/cameras/fuji/x-e3.toml000064400000000000000000000006011046102023000160540ustar 00000000000000make = "FUJIFILM" model = "X-E3" clean_make = "Fujifilm" clean_model = "X-E3" ##blackpoint = 1023 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [0, 0, 130, 0] [cameras.color_matrix] A = [1.339, -0.731, 0.0216, -0.3983, 1.1994, 0.2238, -0.0435, 0.1035, 0.6328] D65 = [1.1434, -0.4948, -0.121, -0.3746, 1.2042, 0.1903, -0.0666, 0.1479, 0.5235] rawler-0.7.1/data/cameras/fuji/x-e4.toml000064400000000000000000000005771046102023000160710ustar 00000000000000make = "FUJIFILM" model = "X-E4" clean_make = "Fujifilm" clean_model = "X-E4" #blackpoint = 1023 whitepoint = 16383 color_pattern = "GGRGGBGGBGGRBRGRBGGGBGGRGGRGGBRBGBRG" active_area = [0, 5, 132, 1] [cameras.color_matrix] A = [1.6064, -0.9942, 0.112, -0.376, 1.2096, 0.1853, -0.0007, 0.0545, 0.6654] D65 = [1.3426, -0.6334, -0.1177, -0.4244, 1.2136, 0.2371, -0.058, 0.1303, 0.598] rawler-0.7.1/data/cameras/fuji/x-e5.toml000064400000000000000000000005551046102023000160660ustar 00000000000000make = "FUJIFILM" model = "X-E5" clean_make = "Fujifilm" clean_model = "X-E5" whitepoint = 16383 color_pattern = "GRBGBRBGGRGGRGGBGGGBRGRBRGGBGGBGGRGG" active_area = [0, 5, 120, 7] [cameras.color_matrix] A = [1.324, -0.8203, 0.1401, -0.2281, 0.9572, 0.3184, 0.0329, 0.0141, 0.679] D65 = [1.1809, -0.5358, -0.1141, -0.4248, 1.2164, 0.2343, -0.0514, 0.1097, 0.5848] rawler-0.7.1/data/cameras/fuji/x-h1.toml000064400000000000000000000005771046102023000160710ustar 00000000000000make = "FUJIFILM" model = "X-H1" clean_make = "Fujifilm" clean_model = "X-H1" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [0, 6, 18, 6] [cameras.color_matrix] A = [1.339, -0.731, 0.0216, -0.3983, 1.1994, 0.2238, -0.0435, 0.1035, 0.6328] D65 = [1.1434, -0.4948, -0.121, -0.3746, 1.2042, 0.1903, -0.0666, 0.1479, 0.5235] rawler-0.7.1/data/cameras/fuji/x-h2.toml000064400000000000000000000006121046102023000160600ustar 00000000000000make = "FUJIFILM" model = "X-H2" clean_make = "Fujifilm" clean_model = "X-H2" whitepoint = 16383 color_pattern = "GGRGGBGGBGGRBRGRGBGGBGGRGGRGGBRBGBRG" active_area = [0, 5, 120, 7] crop_area = [6, 13, 126, 15] [cameras.color_matrix] A = [1.324, -0.8203, 0.1401, -0.2281, 0.9572, 0.3184, 0.0329, 0.0141, 0.679] D65 = [1.1809, -0.5358, -0.1141, -0.4248, 1.2164, 0.2343, -0.0514, 0.1097, 0.5848] rawler-0.7.1/data/cameras/fuji/x-h2s.toml000064400000000000000000000006361046102023000162510ustar 00000000000000make = "FUJIFILM" model = "X-H2S" clean_make = "Fujifilm" clean_model = "X-H2S" #blackpoint = 1024 whitepoint = 16383 color_pattern = "GGRGGBGGBGGRBRGRGBGGBGGRGGRGGBRBGBRG" active_area = [0, 5, 72, 7] #crop_area = [6, 9, 78, 15] [cameras.color_matrix] A = [1.6344, -1.0648, 0.1184, -0.2749, 1.0771, 0.2278, 0.0152, 0.0417, 0.6427] D65 = [1.2836, -0.5909, -0.1032, -0.3087, 1.1132, 0.2236, -0.0035, 0.0872, 0.533] rawler-0.7.1/data/cameras/fuji/x-m1.toml000064400000000000000000000006001046102023000160610ustar 00000000000000make = "FUJIFILM" model = "X-M1" clean_make = "Fujifilm" clean_model = "X-M1" #blackpoint = 256 whitepoint = 4094 color_pattern = "GGRGGBGGBGGRBRGRBGGGBGGRGGRGGBRBGBRG" active_area = [0, 0, 168, 0] [cameras.color_matrix] A = [1.2049, -0.5867, -0.0192, -0.3063, 1.0541, 0.2923, -0.0228, 0.0797, 0.6882] D65 = [1.0413, -0.3996, -0.0993, -0.3721, 1.164, 0.2361, -0.0733, 0.154, 0.6011] rawler-0.7.1/data/cameras/fuji/x-m5.toml000064400000000000000000000005551046102023000160760ustar 00000000000000make = "FUJIFILM" model = "X-M5" clean_make = "Fujifilm" clean_model = "X-M5" whitepoint = 16383 color_pattern = "GGRGGBGGBGGRBRGRBGGGBGGRGGRGGBRBGBRG" active_area = [0, 5, 84, 1] [cameras.color_matrix] A = [1.6344, -1.0648, 0.1184, -0.2749, 1.0771, 0.2278, 0.0152, 0.0417, 0.6427] D65 = [1.2836, -0.5909, -0.1032, -0.3087, 1.1132, 0.2236, -0.0035, 0.0872, 0.533] rawler-0.7.1/data/cameras/fuji/x-pro1.toml000064400000000000000000000006041046102023000164310ustar 00000000000000make = "FUJIFILM" model = "X-Pro1" clean_make = "Fujifilm" clean_model = "X-Pro1" #blackpoint = 256 whitepoint = 4094 color_pattern = "GGRGGBGGBGGRBRGRBGGGBGGRGGRGGBRBGBRG" active_area = [0, 0, 168, 0] [cameras.color_matrix] A = [1.2049, -0.5867, -0.0192, -0.3063, 1.0541, 0.2923, -0.0228, 0.0797, 0.6882] D65 = [1.0413, -0.3996, -0.0993, -0.3721, 1.164, 0.2361, -0.0733, 0.154, 0.6011] rawler-0.7.1/data/cameras/fuji/x-pro2.toml000064400000000000000000000006041046102023000164320ustar 00000000000000make = "FUJIFILM" model = "X-Pro2" clean_make = "Fujifilm" clean_model = "X-Pro2" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [0, 0, 128, 0] [cameras.color_matrix] A = [1.339, -0.731, 0.0216, -0.3983, 1.1994, 0.2238, -0.0435, 0.1035, 0.6328] D65 = [1.1434, -0.4948, -0.121, -0.3746, 1.2042, 0.1903, -0.0666, 0.1479, 0.5235] rawler-0.7.1/data/cameras/fuji/x-pro3.toml000064400000000000000000000006031046102023000164320ustar 00000000000000make = "FUJIFILM" model = "X-Pro3" clean_make = "Fujifilm" clean_model = "X-Pro3" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [0, 5, 132, 1] [cameras.color_matrix] A = [1.6064, -0.9942, 0.112, -0.376, 1.2096, 0.1853, -0.0007, 0.0545, 0.6654] D65 = [1.3426, -0.6334, -0.1177, -0.4244, 1.2136, 0.2371, -0.058, 0.1303, 0.598] rawler-0.7.1/data/cameras/fuji/x-s1.toml000064400000000000000000000005371046102023000161000ustar 00000000000000make = "FUJIFILM" model = "X-S1" clean_make = "Fujifilm" clean_model = "X-S1" #blackpoint = 256 whitepoint = 4000 color_pattern = "BGGR" active_area = [48, 0, 48, 0] [cameras.color_matrix] A = [1.5085, -0.8567, 0.0639, -0.3644, 1.1226, 0.2773, 0.0352, 0.0518, 0.5791] D65 = [1.3509, -0.6199, -0.1254, -0.443, 1.2733, 0.1865, -0.0331, 0.1441, 0.5022] rawler-0.7.1/data/cameras/fuji/x-s10.toml000064400000000000000000000006001046102023000161470ustar 00000000000000make = "FUJIFILM" model = "X-S10" clean_make = "Fujifilm" clean_model = "X-S10" #blackpoint = 256 whitepoint = 16382 color_pattern = "GGRGGBGGBGGRBRGRBGGGBGGRGGRGGBRBGBRG" active_area = [0, 5, 132, 1] [cameras.color_matrix] A = [1.6064, -0.9942, 0.112, -0.376, 1.2096, 0.1853, -0.0007, 0.0545, 0.6654] D65 = [1.3426, -0.6334, -0.1177, -0.4244, 1.2136, 0.2371, -0.058, 0.1303, 0.598] rawler-0.7.1/data/cameras/fuji/x-s20.toml000064400000000000000000000005571046102023000161630ustar 00000000000000make = "FUJIFILM" model = "X-S20" clean_make = "FUJIFILM" clean_model = "X-S20" whitepoint = 16383 color_pattern = "GGRGGBGGBGGRBRGRBGGGBGGRGGRGGBRBGBRG" active_area = [0, 6, 90, 6] [cameras.color_matrix] A = [1.6344, -1.0648, 0.1184, -0.2749, 1.0771, 0.2278, 0.0152, 0.0417, 0.6427] D65 = [1.2836, -0.5909, -0.1032, -0.3087, 1.1132, 0.2236, -0.0035, 0.0872, 0.533] rawler-0.7.1/data/cameras/fuji/x-t1.toml000064400000000000000000000005771046102023000161050ustar 00000000000000make = "FUJIFILM" model = "X-T1" clean_make = "Fujifilm" clean_model = "X-T1" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [4, 0, 52, 0] [cameras.color_matrix] A = [1.267, -0.66, 0.0088, -0.2824, 1.0665, 0.2495, -0.0842, 0.1988, 0.7109] D65 = [0.8458, -0.2451, -0.0855, -0.4597, 1.2447, 0.2407, -0.1475, 0.2482, 0.6526] rawler-0.7.1/data/cameras/fuji/x-t10.toml000064400000000000000000000006011046102023000161510ustar 00000000000000make = "FUJIFILM" model = "X-T10" clean_make = "Fujifilm" clean_model = "X-T10" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [0, 0, 52, 0] [cameras.color_matrix] A = [1.267, -0.66, 0.0088, -0.2824, 1.0665, 0.2495, -0.0842, 0.1988, 0.7109] D65 = [0.8458, -0.2451, -0.0855, -0.4597, 1.2447, 0.2407, -0.1475, 0.2482, 0.6526] rawler-0.7.1/data/cameras/fuji/x-t100.toml000064400000000000000000000005661046102023000162430ustar 00000000000000make = "FUJIFILM" model = "X-T100" clean_make = "Fujifilm" clean_model = "X-T100" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RGGB" hints = ["jpeg32"] active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [1.4259, -0.8049, 0.1087, -0.2249, 0.9662, 0.3037, 0.0053, 0.0427, 0.6328] D65 = [1.1673, -0.476, -0.1041, -0.3988, 1.2058, 0.2166, -0.0771, 0.1417, 0.5569] rawler-0.7.1/data/cameras/fuji/x-t2.toml000064400000000000000000000006001046102023000160710ustar 00000000000000make = "FUJIFILM" model = "X-T2" clean_make = "Fujifilm" clean_model = "X-T2" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [0, 0, 128, 0] [cameras.color_matrix] A = [1.339, -0.731, 0.0216, -0.3983, 1.1994, 0.2238, -0.0435, 0.1035, 0.6328] D65 = [1.1434, -0.4948, -0.121, -0.3746, 1.2042, 0.1903, -0.0666, 0.1479, 0.5235] rawler-0.7.1/data/cameras/fuji/x-t20.toml000064400000000000000000000006021046102023000161530ustar 00000000000000make = "FUJIFILM" model = "X-T20" clean_make = "Fujifilm" clean_model = "X-T20" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [0, 0, 128, 0] [cameras.color_matrix] A = [1.339, -0.731, 0.0216, -0.3983, 1.1994, 0.2238, -0.0435, 0.1035, 0.6328] D65 = [1.1434, -0.4948, -0.121, -0.3746, 1.2042, 0.1903, -0.0666, 0.1479, 0.5235] rawler-0.7.1/data/cameras/fuji/x-t200.toml000064400000000000000000000005651046102023000162430ustar 00000000000000make = "FUJIFILM" model = "X-T200" clean_make = "Fujifilm" clean_model = "X-T200" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RGGB" hints = ["jpeg32"] active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [2.2235, -1.5902, 0.0516, -0.3091, 1.1246, 0.2102, 0.0018, 0.047, 0.6638] D65 = [1.5055, -0.7391, -0.1274, -0.4062, 1.2071, 0.2238, -0.061, 0.1217, 0.6147] rawler-0.7.1/data/cameras/fuji/x-t3.toml000064400000000000000000000005771046102023000161070ustar 00000000000000make = "FUJIFILM" model = "X-T3" clean_make = "Fujifilm" clean_model = "X-T3" #blackpoint = 1024 whitepoint = 16383 color_pattern = "GGRGGBGGBGGRBRGRBGGGBGGRGGRGGBRBGBRG" active_area = [0, 5, 132, 1] [cameras.color_matrix] A = [1.6064, -0.9942, 0.112, -0.376, 1.2096, 0.1853, -0.0007, 0.0545, 0.6654] D65 = [1.3426, -0.6334, -0.1177, -0.4244, 1.2136, 0.2371, -0.058, 0.1303, 0.598] rawler-0.7.1/data/cameras/fuji/x-t30.toml000064400000000000000000000006011046102023000161530ustar 00000000000000make = "FUJIFILM" model = "X-T30" clean_make = "Fujifilm" clean_model = "X-T30" #blackpoint = 1024 whitepoint = 16383 color_pattern = "GGRGGBGGBGGRBRGRBGGGBGGRGGRGGBRBGBRG" active_area = [0, 5, 132, 1] [cameras.color_matrix] A = [1.6064, -0.9942, 0.112, -0.376, 1.2096, 0.1853, -0.0007, 0.0545, 0.6654] D65 = [1.3426, -0.6334, -0.1177, -0.4244, 1.2136, 0.2371, -0.058, 0.1303, 0.598] rawler-0.7.1/data/cameras/fuji/x-t30mk2.toml000064400000000000000000000006071046102023000165730ustar 00000000000000make = "FUJIFILM" model = "X-T30 II" clean_make = "Fujifilm" clean_model = "X-T30 II" #blackpoint = 1024 whitepoint = 16383 color_pattern = "GGRGGBGGBGGRBRGRBGGGBGGRGGRGGBRBGBRG" active_area = [0, 5, 132, 1] [cameras.color_matrix] A = [1.6064, -0.9942, 0.112, -0.376, 1.2096, 0.1853, -0.0007, 0.0545, 0.6654] D65 = [1.3426, -0.6334, -0.1177, -0.4244, 1.2136, 0.2371, -0.058, 0.1303, 0.598] rawler-0.7.1/data/cameras/fuji/x-t4.toml000064400000000000000000000005771046102023000161100ustar 00000000000000make = "FUJIFILM" model = "X-T4" clean_make = "Fujifilm" clean_model = "X-T4" #blackpoint = 1024 whitepoint = 16383 color_pattern = "GGRGGBGGBGGRBRGRBGGGBGGRGGRGGBRBGBRG" active_area = [0, 5, 132, 1] [cameras.color_matrix] A = [1.6064, -0.9942, 0.112, -0.376, 1.2096, 0.1853, -0.0007, 0.0545, 0.6654] D65 = [1.3426, -0.6334, -0.1177, -0.4244, 1.2136, 0.2371, -0.058, 0.1303, 0.598] rawler-0.7.1/data/cameras/fuji/x-t5.toml000064400000000000000000000005551046102023000161050ustar 00000000000000make = "FUJIFILM" model = "X-T5" clean_make = "Fujifilm" clean_model = "X-T5" whitepoint = 16383 color_pattern = "GGRGGBGGBGGRBRGRGBGGBGGRGGRGGBRBGBRG" active_area = [0, 5, 120, 7] [cameras.color_matrix] A = [1.324, -0.8203, 0.1401, -0.2281, 0.9572, 0.3184, 0.0329, 0.0141, 0.679] D65 = [1.1809, -0.5358, -0.1141, -0.4248, 1.2164, 0.2343, -0.0514, 0.1097, 0.5848] rawler-0.7.1/data/cameras/fuji/x-t50.toml000064400000000000000000000005571046102023000161670ustar 00000000000000make = "FUJIFILM" model = "X-T50" clean_make = "Fujifilm" clean_model = "X-T50" whitepoint = 16383 color_pattern = "GGRGGBGGBGGRBRGRGBGGBGGRGGRGGBRBGBRG" active_area = [0, 5, 120, 7] [cameras.color_matrix] A = [1.324, -0.8203, 0.1401, -0.2281, 0.9572, 0.3184, 0.0329, 0.0141, 0.679] D65 = [1.1809, -0.5358, -0.1141, -0.4248, 1.2164, 0.2343, -0.0514, 0.1097, 0.5848] rawler-0.7.1/data/cameras/fuji/x10.toml000064400000000000000000000005451046102023000157170ustar 00000000000000make = "FUJIFILM" model = "X10" clean_make = "Fujifilm" clean_model = "FinePix X10" #blackpoint = 256 whitepoint = 4000 color_pattern = "BGGR" active_area = [48, 0, 48, 0] [cameras.color_matrix] A = [1.5085, -0.8567, 0.0639, -0.3644, 1.1226, 0.2773, 0.0352, 0.0518, 0.5791] D65 = [1.3509, -0.6199, -0.1254, -0.443, 1.2733, 0.1865, -0.0331, 0.1441, 0.5022] rawler-0.7.1/data/cameras/fuji/x100.toml000064400000000000000000000005601046102023000157740ustar 00000000000000make = "FUJIFILM" model = "FinePix X100" clean_make = "Fujifilm" clean_model = "FinePix X100" #blackpoint = 254 whitepoint = 4000 color_pattern = "RGGB" active_area = [68, 0, 70, 0] [cameras.color_matrix] A = [1.3589, -0.6494, -0.0148, -0.4182, 1.1567, 0.2988, -0.0277, 0.0888, 0.7616] D65 = [1.2161, -0.4457, -0.1069, -0.5034, 1.2874, 0.24, -0.0795, 0.1724, 0.6904] rawler-0.7.1/data/cameras/fuji/x100f.toml000064400000000000000000000006011046102023000161360ustar 00000000000000make = "FUJIFILM" model = "X100F" clean_make = "Fujifilm" clean_model = "X100F" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [0, 6, 18, 6] [cameras.color_matrix] A = [1.339, -0.731, 0.0216, -0.3983, 1.1994, 0.2238, -0.0435, 0.1035, 0.6328] D65 = [1.1434, -0.4948, -0.121, -0.3746, 1.2042, 0.1903, -0.0666, 0.1479, 0.5235] rawler-0.7.1/data/cameras/fuji/x100s.toml000064400000000000000000000006011046102023000161530ustar 00000000000000make = "FUJIFILM" model = "X100S" clean_make = "Fujifilm" clean_model = "X100S" #blackpoint = 0 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [4, 0, 56, 0] [cameras.color_matrix] A = [1.2147, -0.6103, -0.0062, -0.2748, 1.0145, 0.3036, -0.0222, 0.1111, 0.7347] D65 = [1.0592, -0.4262, -0.1008, -0.3514, 1.1355, 0.2465, -0.087, 0.2025, 0.6386] rawler-0.7.1/data/cameras/fuji/x100t.toml000064400000000000000000000006041046102023000161570ustar 00000000000000make = "FUJIFILM" model = "X100T" clean_make = "Fujifilm" clean_model = "X100T" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [4, 0, 56, 0] [cameras.color_matrix] A = [1.2147, -0.6103, -0.0062, -0.2748, 1.0145, 0.3036, -0.0222, 0.1111, 0.7347] D65 = [1.0592, -0.4262, -0.1008, -0.3514, 1.1355, 0.2465, -0.087, 0.2025, 0.6386] rawler-0.7.1/data/cameras/fuji/x100v.toml000064400000000000000000000006011046102023000161560ustar 00000000000000make = "FUJIFILM" model = "X100V" clean_make = "Fujifilm" clean_model = "X100V" #blackpoint = 1024 whitepoint = 16383 color_pattern = "GGRGGBGGBGGRBRGRBGGGBGGRGGRGGBRBGBRG" active_area = [0, 5, 132, 1] [cameras.color_matrix] A = [1.7835, -1.1702, 0.1616, -0.2581, 1.0513, 0.2395, 0.0196, 0.032, 0.6444] D65 = [1.3717, -0.649, -0.1154, -0.4348, 1.2266, 0.2335, -0.069, 0.1286, 0.6134] rawler-0.7.1/data/cameras/fuji/x100vi.toml000064400000000000000000000004001046102023000163240ustar 00000000000000make = "FUJIFILM" model = "X100VI" clean_make = "Fujifilm" clean_model = "X100VI" whitepoint = 16383 active_area = [0, 12, 120, 12] [cameras.color_matrix] D65 = [1.1809, -0.5358, -0.1141, -0.4248, 1.2164, 0.2343, -0.0514, 0.1097, 0.5848] # TODO: A matrix rawler-0.7.1/data/cameras/fuji/x20.toml000064400000000000000000000005741046102023000157220ustar 00000000000000make = "FUJIFILM" model = "X20" clean_make = "Fujifilm" clean_model = "X20" #blackpoint = 257 whitepoint = 4094 color_pattern = "GBGGRGRGRBGBGBGGRGGRGGBGBGBRGRGRGGBG" active_area = [0, 0, 64, 0] [cameras.color_matrix] A = [1.2997, -0.6851, 0.0572, -0.4031, 1.1287, 0.3151, 0.0241, 0.0731, 0.5309] D65 = [1.1768, -0.4971, -0.1133, -0.4904, 1.2927, 0.2183, -0.048, 0.1723, 0.4605] rawler-0.7.1/data/cameras/fuji/x30.toml000064400000000000000000000005741046102023000157230ustar 00000000000000make = "FUJIFILM" model = "X30" clean_make = "Fujifilm" clean_model = "X30" #blackpoint = 257 whitepoint = 4094 color_pattern = "GBGGRGRGRBGBGBGGRGGRGGBGBGBRGRGRGGBG" active_area = [0, 0, 64, 0] [cameras.color_matrix] A = [1.4499, -0.7943, 0.0564, -0.5442, 1.374, 0.1827, -0.0061, 0.1006, 0.571] D65 = [1.2328, -0.5256, -0.1144, -0.4469, 1.2927, 0.1675, -0.0087, 0.1291, 0.4351] rawler-0.7.1/data/cameras/fuji/x70.toml000064400000000000000000000005741046102023000157270ustar 00000000000000make = "FUJIFILM" model = "X70" clean_make = "Fujifilm" clean_model = "X70" #blackpoint = 1024 whitepoint = 16383 color_pattern = "RBGBRGGGRGGBGGBGGRBRGRBGGGBGGRGGRGGB" active_area = [4, 0, 52, 0] [cameras.color_matrix] A = [1.2688, -0.6851, 0.0469, -0.3833, 1.16, 0.254, -0.0406, 0.1143, 0.7752] D65 = [1.045, -0.4329, -0.0878, -0.3217, 1.1105, 0.2421, -0.0752, 0.1758, 0.6519] rawler-0.7.1/data/cameras/fuji/xf1.toml000064400000000000000000000005351046102023000160040ustar 00000000000000make = "FUJIFILM" model = "XF1" clean_make = "Fujifilm" clean_model = "XF1" #blackpoint = 257 whitepoint = 4000 color_pattern = "BGGR" active_area = [48, 0, 48, 0] [cameras.color_matrix] A = [1.5085, -0.8567, 0.0639, -0.3644, 1.1226, 0.2773, 0.0352, 0.0518, 0.5791] D65 = [1.3509, -0.6199, -0.1254, -0.443, 1.2733, 0.1865, -0.0331, 0.1441, 0.5022] rawler-0.7.1/data/cameras/fuji/xf10.toml000064400000000000000000000005611046102023000160630ustar 00000000000000make = "FUJIFILM" model = "XF10" clean_make = "Fujifilm" clean_model = "XF10" #blackpoint = 257 whitepoint = 16383 color_pattern = "RGGB" hints = ["jpeg32"] active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [1.4259, -0.8049, 0.1087, -0.2249, 0.9662, 0.3037, 0.0053, 0.0427, 0.6328] D65 = [1.1673, -0.476, -0.1041, -0.3988, 1.2058, 0.2166, -0.0771, 0.1417, 0.5569] rawler-0.7.1/data/cameras/fuji/xq1.toml000064400000000000000000000005711046102023000160170ustar 00000000000000make = "FUJIFILM" model = "XQ1" clean_make = "Fujifilm" clean_model = "XQ1" #blackpoint = 257 whitepoint = 4094 color_pattern = "GBGGRGRGRBGBGBGGRGGRGGBGBGBRGRGRGGBG" active_area = [0, 0, 64, 0] [cameras.color_matrix] A = [1.3888, -0.749, 0.0484, -0.4247, 1.2445, 0.2, -0.0325, 0.158, 0.5017] D65 = [0.9252, -0.2704, -0.1064, -0.5893, 1.4265, 0.1717, -0.1101, 0.2341, 0.4349] rawler-0.7.1/data/cameras/fuji/xq2.toml000064400000000000000000000005711046102023000160200ustar 00000000000000make = "FUJIFILM" model = "XQ2" clean_make = "Fujifilm" clean_model = "XQ2" #blackpoint = 257 whitepoint = 4094 color_pattern = "GBGGRGRGRBGBGBGGRGGRGGBGBGBRGRGRGGBG" active_area = [0, 0, 64, 0] [cameras.color_matrix] A = [1.3888, -0.749, 0.0484, -0.4247, 1.2445, 0.2, -0.0325, 0.158, 0.5017] D65 = [0.9252, -0.2704, -0.1064, -0.5893, 1.4265, 0.1717, -0.1101, 0.2341, 0.4349] rawler-0.7.1/data/cameras/hasselblad/cfv.toml000064400000000000000000000004711046102023000172300ustar 00000000000000make = "Hasselblad" model = "Hasselblad 500 mech." clean_make = "Hasselblad" clean_model = "CFV" blackpoint = 0 whitepoint = 31456 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 4, 4, 4] [cameras.color_matrix] D65 = [0.8519, -0.3260, -0.0280, -0.5081, 1.3459, 0.1738, -0.1449, 0.2960, 0.7809] rawler-0.7.1/data/cameras/hasselblad/cfv_50.toml000064400000000000000000000004041046102023000175300ustar 00000000000000make = "Hasselblad" model = "Hasselblad CFV-50" clean_make = "Hasselblad" clean_model = "CFV-50" #blackpoint = 0 #whitepoint = 65535 color_pattern = "RGGB" [cameras.color_matrix] D65 = [0.528, -0.0614, 0.0039, -0.495, 1.2426, 0.2843, -0.0939, 0.2434, 0.5968] rawler-0.7.1/data/cameras/hasselblad/h3d.toml000064400000000000000000000004661046102023000171340ustar 00000000000000make = "Hasselblad" model = "Hasselblad H3D" clean_make = "Hasselblad" clean_model = "H4D-H3D" blackpoint = 0 whitepoint = 62914 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 4, 4, 4] [cameras.color_matrix] D65 = [0.3857, 0.0452, -0.0046, -0.6008, 1.4477, 0.1596, -0.2627, 0.4481, 0.5718] rawler-0.7.1/data/cameras/hasselblad/h4d_40.toml000064400000000000000000000004731046102023000174360ustar 00000000000000make = "Hasselblad" model = "Hasselblad H4D-40" clean_make = "Hasselblad" clean_model = "H4D-40" #blackpoint = 0 #whitepoint = 62914 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 4, 4, 4] [cameras.color_matrix] D65 = [0.5656, -0.0659, -0.0346, -0.3923, 1.2306, 0.1791, -0.1602, 0.3509, 0.5442] rawler-0.7.1/data/cameras/hasselblad/h4d_50.toml000064400000000000000000000004041046102023000174310ustar 00000000000000make = "Hasselblad" model = "Hasselblad H4D-50" clean_make = "Hasselblad" clean_model = "H4D-50" #blackpoint = 0 #whitepoint = 65535 color_pattern = "RGGB" [cameras.color_matrix] D65 = [0.528, -0.0614, 0.0039, -0.495, 1.2426, 0.2843, -0.0939, 0.2434, 0.5968] rawler-0.7.1/data/cameras/hasselblad/h5d_40.toml000064400000000000000000000004751046102023000174410ustar 00000000000000make = "Hasselblad" model = "Hasselblad H5D-40" clean_make = "Hasselblad" clean_model = "H5D-40" #blackpoint = 256 #whitepoint = 62914 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 4, 4, 4] [cameras.color_matrix] D65 = [0.5963, -0.1357, -0.0172, -0.5439, 1.2762, 0.3007, -0.0964, 0.2222, 0.7172] rawler-0.7.1/data/cameras/hasselblad/h5d_50c.toml000064400000000000000000000004741046102023000176040ustar 00000000000000make = "Hasselblad" model = "Hasselblad H5D-50c" clean_make = "Hasselblad" clean_model = "H5D-50c" #blackpoint = 0 #whitepoint = 62914 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 4, 4, 4] [cameras.color_matrix] D65 = [0.5002, -0.0878, 0.0111, -0.4856, 1.1929, 0.3338, -0.1183, 0.2041, 0.7022] rawler-0.7.1/data/cameras/hasselblad/h6d_100cms.toml000064400000000000000000000005031046102023000202120ustar 00000000000000make = "Hasselblad" model = "Hasselblad H6D-100cMS" clean_make = "Hasselblad" clean_model = "H6D-100cMS" #blackpoint = 0 #whitepoint = 62914 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 4, 4, 4] [cameras.color_matrix] D65 = [0.5656, -0.0659, -0.0346, -0.3923, 1.2306, 0.1791, -0.1602, 0.3509, 0.5442] rawler-0.7.1/data/cameras/hasselblad/x1d.toml000064400000000000000000000004701046102023000171450ustar 00000000000000make = "Hasselblad" model = "Hasselblad X1D" clean_make = "Hasselblad" clean_model = "X1D" #blackpoint = 0 #whitepoint = 65535 color_pattern = "RGGB" hints = ["uncompressed"] active_area = [46, 96, 58, 0] [cameras.color_matrix] D65 = [0.5002, -0.0878, 0.0111, -0.4856, 1.1929, 0.3338, -0.1183, 0.2041, 0.7022] rawler-0.7.1/data/cameras/hasselblad/x1d2.toml000064400000000000000000000004731046102023000172320ustar 00000000000000make = "Hasselblad" model = "X1D II 50C" clean_make = "Hasselblad" clean_model = "X1D II 50C" #blackpoint = 0 #whitepoint = 65535 color_pattern = "RGGB" hints = ["uncompressed"] active_area = [46, 96, 58, 0] [cameras.color_matrix] D65 = [0.5002, -0.0878, 0.0111, -0.4856, 1.1929, 0.3338, -0.1183, 0.2041, 0.7022] rawler-0.7.1/data/cameras/hasselblad/x2d_100c.toml000064400000000000000000000005711046102023000176730ustar 00000000000000make = "Hasselblad" model = "X2D 100C" clean_make = "Hasselblad" clean_model = "X2D 100C" color_pattern = "RGGB" hints = ["uncompressed"] model_aliases = [ ["Hasselblad X2D 100C", "X2D 100C"], ["Hasselblad CFV 100C", "CFV 100C"], ["CFV 100C/907X", "CFV 100C"], ] [cameras.color_matrix] D65 = [0.6468, -0.1899, -0.0545, -0.4526, 1.2267, 0.2542, -0.0388, 0.1276, 0.6096] rawler-0.7.1/data/cameras/kodak/dc120.toml000064400000000000000000000006301046102023000162470ustar 00000000000000make = "Eastman Kodak Company" model = "Kodak DC120 ZOOM Digital Camera" clean_make = "Kodak" clean_model = "DC120" blackpoint = 0 whitepoint = 255 # sRGB for lack of a better one color_pattern = "GRBG" active_area = [0, 0, 0, 0] default_scale = [[80, 52], [1, 1]] crop_area = [8, 8, 8, 8] [cameras.color_matrix] D65 = [3.24045, -1.53713, -0.49853, -0.96926, 1.87601, 0.04155, 0.05564, -0.20402, 1.05722] rawler-0.7.1/data/cameras/kodak/dc50.toml000064400000000000000000000005171046102023000161750ustar 00000000000000make = "Eastman Kodak Company" model = "Kodak Digital Science DC50 Zoom Camera" clean_make = "Kodak" clean_model = "DC50" blackpoint = 0 whitepoint = 16383 raw_width = 768 raw_height = 512 color_pattern = "GRBG" crop_area = [6, 4, 6, 4] [cameras.color_matrix] D65 = [2.1392,-0.5653,-0.3353,0.2406,0.8010,-0.0415,0.7166,0.1427,0.2078] rawler-0.7.1/data/cameras/kodak/dcs1.toml000064400000000000000000000006111046102023000162670ustar 00000000000000make = "KODAK" model = "EOSDCS1B FILE VERSION 3" clean_make = "Kodak" clean_model = "EOS DCS 1" blackpoint = 0 whitepoint = 7638 color_pattern = "GRBG" active_area = [2, 0, 2, 0] crop_area = [6, 4, 6, 4] [cameras.color_matrix] A = [1.467, -0.6487, 0.0942, -0.0696, 1.0135, 0.065, 0.3312, -0.0461, 0.1805] D65 = [1.0592, -0.2206, -0.0967, -0.1944, 1.1685, 0.023, 0.2206, 0.067, 0.1273] rawler-0.7.1/data/cameras/kodak/dcs3.toml000064400000000000000000000006121046102023000162720ustar 00000000000000make = "KODAK" model = "EOSDCS3C FILE VERSION 3" clean_make = "Kodak" clean_model = "EOS DCS 3" blackpoint = 0 whitepoint = 7855 color_pattern = "GRBG" active_area = [2, 0, 2, 0] crop_area = [6, 4, 6, 4] [cameras.color_matrix] A = [1.4143, -0.7401, 0.0611, -0.1262, 1.0758, 0.0551, 0.3121, -0.0585, 0.1486] D65 = [0.9898, -0.27, -0.094, -0.2478, 1.2219, 0.0206, 0.1985, 0.0634, 0.1031] rawler-0.7.1/data/cameras/kodak/dcs460d.toml000064400000000000000000000004401046102023000166040ustar 00000000000000make = "KODAK" model = "DCS460D FILE VERSION 3" clean_make = "Kodak" clean_model = "DCS460D" blackpoint = 7 whitepoint = 6664 color_pattern = "GRBG" active_area = [3, 0, 3, 0] [cameras.color_matrix] D65 = [1.0592, -0.2206, -0.0967, -0.1944, 1.1685, 0.023, 0.2206, 0.067, 0.1273] rawler-0.7.1/data/cameras/kodak/dcs560c.toml000064400000000000000000000004451046102023000166110ustar 00000000000000make = "Kodak" model = "DCS560C" clean_make = "Kodak" clean_model = "DCS560C" blackpoint = 0 whitepoint = 4095 color_pattern = "GRBG" active_area = [0, 0, 0, 0] hints = ["linearization"] [cameras.color_matrix] D65 = [2.0482, -0.7172, -0.3125, -0.1033, 1.041, -0.0285, 0.2542, 0.0226, 0.3136] rawler-0.7.1/data/cameras/kodak/dcs760c.toml000064400000000000000000000005621046102023000166130ustar 00000000000000make = "Kodak" model = "DCS760C" clean_make = "Kodak" clean_model = "DCS760C" blackpoint = 0 whitepoint = 3500 color_pattern = "GRBG" active_area = [0, 0, 0, 0] crop_area = [4, 4, 4, 4] [cameras.color_matrix] A = [2.212, -1.2779, 0.1755, -0.243, 1.1072, 0.0804, 0.2884, -0.0521, 0.2863] D65 = [1.6623, -0.6309, -0.1411, -0.4344, 1.3923, 0.0323, 0.2285, 0.0274, 0.2926] rawler-0.7.1/data/cameras/kodak/dcs_pro14n.toml000064400000000000000000000005721046102023000174170ustar 00000000000000make = "Kodak" model = "DCS Pro 14N" clean_make = "Kodak" clean_model = "DCS Pro 14N" blackpoint = 0 whitepoint = 3700 color_pattern = "GRBG" active_area = [0, 0, 0, 0] crop_area = [8, 6, 8, 6] [cameras.color_matrix] A = [0.9181, 0.1395, -0.03, -0.6828, 1.4271, 0.2389, -0.1561, 0.3258, 0.6068] D65 = [0.7791, 0.3128, -0.0776, -0.8588, 1.6458, 0.2039, -0.2455, 0.4006, 0.6198] rawler-0.7.1/data/cameras/kodak/dcs_pro14nx.toml000064400000000000000000000005721046102023000176070ustar 00000000000000make = "Kodak" model = "DCS Pro 14nx" clean_make = "Kodak" clean_model = "DCS Pro 14nx" blackpoint = 0 whitepoint = 3700 color_pattern = "GRBG" active_area = [0, 0, 0, 0] crop_area = [8, 6, 8, 6] [cameras.color_matrix] A = [0.6395, 0.1163, 0.0312, -0.4753, 1.1798, 0.3375, -0.107, 0.3184, 0.547] D65 = [0.5494, 0.2393, -0.0232, -0.6427, 1.385, 0.2846, -0.1876, 0.3997, 0.5445] rawler-0.7.1/data/cameras/kodak/dcs_pro_slrc.toml000064400000000000000000000005741046102023000201210ustar 00000000000000make = "Kodak" model = "DCS Pro SLR/c" clean_make = "Kodak" clean_model = "DCS Pro SLR/c" blackpoint = 0 whitepoint = 3700 color_pattern = "GRBG" active_area = [0, 0, 0, 0] crop_area = [8, 6, 8, 6] [cameras.color_matrix] A = [0.6395, 0.1163, 0.0312, -0.4753, 1.1798, 0.3375, -0.107, 0.3184, 0.547] D65 = [0.5494, 0.2393, -0.0232, -0.6427, 1.385, 0.2846, -0.1876, 0.3997, 0.5445] rawler-0.7.1/data/cameras/kodak/dcs_pro_slrn.toml000064400000000000000000000005741046102023000201340ustar 00000000000000make = "Kodak" model = "DCS Pro SLR/n" clean_make = "Kodak" clean_model = "DCS Pro SLR/n" blackpoint = 0 whitepoint = 4095 color_pattern = "GRBG" active_area = [0, 0, 0, 0] crop_area = [8, 6, 8, 6] [cameras.color_matrix] A = [0.6395, 0.1163, 0.0312, -0.4753, 1.1798, 0.3375, -0.107, 0.3184, 0.547] D65 = [0.5494, 0.2393, -0.0232, -0.6427, 1.385, 0.2846, -0.1876, 0.3997, 0.5445] rawler-0.7.1/data/cameras/kodak/p712.toml000064400000000000000000000006311046102023000161300ustar 00000000000000make = "EASTMAN KODAK COMPANY" model = "KODAK P712 ZOOM DIGITAL CAMERA" clean_make = "Kodak" clean_model = "P712" blackpoint = 0 whitepoint = 4030 color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [8, 3, 8, 3] [cameras.color_matrix] A = [1.1274, -0.5086, 0.0132, -0.3983, 1.1231, 0.3163, -0.0734, 0.1304, 0.6096] D65 = [0.9658, -0.3314, -0.0823, -0.5163, 1.2695, 0.2768, -0.1342, 0.1843, 0.6044] rawler-0.7.1/data/cameras/kodak/p880.toml000064400000000000000000000006271046102023000161430ustar 00000000000000make = "EASTMAN KODAK COMPANY" model = "KODAK P880 ZOOM DIGITAL CAMERA" clean_make = "Kodak" clean_model = "P880" blackpoint = 0 whitepoint = 4095 color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [8, 3, 8, 3] [cameras.color_matrix] A = [1.5463, -0.7578, 0.0196, -0.5835, 1.3172, 0.2976, -0.0626, 0.1273, 0.8044] D65 = [1.2805, -0.4662, -0.1376, -0.748, 1.5267, 0.236, -0.1626, 0.2194, 0.7904] rawler-0.7.1/data/cameras/kodak/z1015.toml000064400000000000000000000007171046102023000162240ustar 00000000000000make = "EASTMAN KODAK COMPANY" model = "KODAK EASYSHARE Z1015 IS DIGITAL CAMERA" clean_make = "Kodak" clean_model = "EasyShare Z1015 IS" blackpoint = 0 whitepoint = 4095 color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [8, 2, 8, 3] hints = ["easyshare_offset_hack"] [cameras.color_matrix] A = [1.394, -0.6915, 0.0184, -0.3009, 1.063, 0.2754, -0.0133, 0.0852, 0.5331] D65 = [1.1265, -0.4286, -0.0992, -0.4694, 1.2343, 0.2647, -0.109, 0.1523, 0.5447] rawler-0.7.1/data/cameras/kodak/z981.toml000064400000000000000000000007061046102023000161550ustar 00000000000000make = "EASTMAN KODAK COMPANY" model = "KODAK EasyShare Z981 Digital Camera" clean_make = "Kodak" clean_model = "EasyShare Z981" blackpoint = 0 whitepoint = 4000 color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [8, 2, 8, 3] hints = ["easyshare_offset_hack"] [cameras.color_matrix] A = [1.3493, -0.6094, -0.048, -0.1155, 0.8622, 0.302, 0.0493, 0.0467, 0.4726] D65 = [1.2729, -0.4717, -0.1188, -0.1367, 0.9187, 0.2582, 0.0274, 0.086, 0.4411] rawler-0.7.1/data/cameras/kodak/z990.toml000064400000000000000000000007071046102023000161560ustar 00000000000000make = "EASTMAN KODAK COMPANY" model = "KODAK EasyShare Z990 Digital Camera" clean_make = "Kodak" clean_model = "EasyShare Z990" blackpoint = 0 whitepoint = 4000 color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [8, 3, 8, 4] hints = ["easyshare_offset_hack"] [cameras.color_matrix] A = [1.2413, -0.527, -0.0613, -0.1204, 0.9387, 0.215, 0.027, 0.0824, 0.4992] D65 = [1.1749, -0.4048, -0.1309, -0.1867, 1.0572, 0.1489, -0.0138, 0.1449, 0.4522] rawler-0.7.1/data/cameras/leaf/aptus22.toml000064400000000000000000000005721046102023000165610ustar 00000000000000make = "Leaf" model = "Leaf Aptus 22" clean_make = "Leaf" clean_model = "Aptus 22" blackpoint = 0 whitepoint = 15000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 4, 4, 4] [cameras.color_matrix] A = [0.8036, 0.1309, -0.1134, -0.6259, 1.3352, 0.3252, -0.1977, 0.4003, 0.6418] D65 = [0.8236, 0.1746, -0.1313, -0.8251, 1.5953, 0.2428, -0.3672, 0.5786, 0.5771] rawler-0.7.1/data/cameras/leaf/aptus75.toml000064400000000000000000000004251046102023000165660ustar 00000000000000make = "Leaf" model = "Leaf Aptus 75" clean_make = "Leaf" clean_model = "Aptus 75" blackpoint = 0 whitepoint = 16191 color_pattern = "RGGB" #active_area = [36, 6, 16, 46] [cameras.color_matrix] D65 = [0.8236, 0.1746, -0.1314, -0.8251, 1.5953, 0.2428, -0.3673, 0.5786, 0.5771] rawler-0.7.1/data/cameras/leaf/credo40.toml000064400000000000000000000005361046102023000165210ustar 00000000000000make = "Leaf" model = "Credo 40" clean_make = "Leaf" clean_model = "Credo 40" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" #active_area = [36, 6, 16, 46] [cameras.color_matrix] A = [0.7756, 0.0244, -0.0761, -0.53, 1.2774, 0.2832, -0.0881, 0.2622, 0.5858] D65 = [0.8035, 0.0435, -0.0962, -0.6001, 1.3872, 0.232, -0.1159, 0.3065, 0.5434] rawler-0.7.1/data/cameras/leaf/credo50.toml000064400000000000000000000004241046102023000165160ustar 00000000000000make = "Leaf" model = "Credo 50" clean_make = "Leaf" clean_model = "Credo 50" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" [cameras.color_matrix] A = [0.5233, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.1869] Flash = [0.3984, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.7666] rawler-0.7.1/data/cameras/leaf/credo60.toml000064400000000000000000000005361046102023000165230ustar 00000000000000make = "Leaf" model = "Credo 60" clean_make = "Leaf" clean_model = "Credo 60" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" #active_area = [36, 6, 16, 46] [cameras.color_matrix] A = [0.7756, 0.0244, -0.0761, -0.53, 1.2774, 0.2832, -0.0881, 0.2622, 0.5858] D65 = [0.8035, 0.0435, -0.0962, -0.6001, 1.3872, 0.232, -0.1159, 0.3065, 0.5434] rawler-0.7.1/data/cameras/leaf/credo80.toml000064400000000000000000000005411046102023000165210ustar 00000000000000make = "Leaf" model = "Credo 80" clean_make = "Leaf" clean_model = "Credo 80" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" #active_area = [36, 6, 16, 46] [cameras.color_matrix] A = [0.5644, 0.1137, -0.0804, -0.4702, 1.2262, 0.2753, -0.0636, 0.1861, 0.5419] D65 = [0.6294, 0.0686, -0.0712, -0.5435, 1.3417, 0.2211, -0.1006, 0.2435, 0.5042] rawler-0.7.1/data/cameras/leica/c112.toml000064400000000000000000000007001046102023000160660ustar 00000000000000make = "LEICA" model = "C (Typ 112)" clean_make = "Leica" clean_model = "C (Typ 112)" #blackpoint = 146 whitepoint = 3956 color_pattern = "RGGB" [cameras.color_matrix] A = [1.0884, -0.5276, 0.0776, -0.2257, 0.994, 0.2711, -0.01, 0.098, 0.6119] D65 = [0.9379, -0.3267, -0.0816, -0.3227, 1.156, 0.1881, -0.0926, 0.1928, 0.534] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 130, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 130, 0] rawler-0.7.1/data/cameras/leica/clux.toml000064400000000000000000000006041046102023000163760ustar 00000000000000make = "LEICA CAMERA AG" model = "C-Lux" clean_make = "Leica" clean_model = "C-Lux" #blackpoint = 140 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8468, -0.3758, -0.0141, -0.3463, 1.1363, 0.2395, -0.0363, 0.1118, 0.6076] D65 = [0.779, -0.2736, -0.0755, -0.3452, 1.187, 0.1769, -0.0628, 0.1647, 0.4898] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/leica/digilux2.toml000064400000000000000000000005751046102023000171610ustar 00000000000000make = "LEICA" model = "DIGILUX 2" clean_make = "Leica" clean_model = "Digilux 2" #blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" [cameras.color_matrix] A = [1.3619, -0.6641, 0.02, -0.6485, 1.3898, 0.2856, -0.1523, 0.2069, 0.8403] D65 = [1.134, -0.4069, -0.1276, -0.7555, 1.5265, 0.2448, -0.296, 0.3426, 0.7686] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/leica/digilux3.toml000064400000000000000000000006001046102023000171470ustar 00000000000000make = "LEICA" model = "DIGILUX 3" clean_make = "Leica" clean_model = "Digilux 3" #blackpoint = 0 whitepoint = 3986 color_pattern = "RGGB" [cameras.color_matrix] A = [0.8248, -0.2304, -0.0642, -0.7029, 1.4754, 0.2453, -0.1491, 0.2353, 0.815] D65 = [0.8054, -0.1886, -0.1025, -0.8348, 1.6367, 0.204, -0.2805, 0.3542, 0.763] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 12, 2] rawler-0.7.1/data/cameras/leica/dlux109.toml000064400000000000000000000011031046102023000166240ustar 00000000000000make = "LEICA" model = "D-LUX (Typ 109)" clean_make = "Leica" clean_model = "D-LUX (Typ 109)" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9867, -0.4849, 0.0039, -0.4644, 1.2563, 0.2321, -0.0614, 0.141, 0.6834] D65 = [0.8844, -0.3538, -0.0768, -0.3709, 1.1762, 0.22, -0.0698, 0.1792, 0.522] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 80, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 16, 0] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 144, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 96, 0] rawler-0.7.1/data/cameras/leica/dlux3.toml000064400000000000000000000005771046102023000164730ustar 00000000000000make = "LEICA" model = "D-LUX 3" clean_make = "Leica" clean_model = "D-LUX 3" #blackpoint = 0 whitepoint = 3986 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9781, -0.4779, 0.0376, -0.4711, 1.1427, 0.3777, -0.073, 0.1393, 0.7137] D65 = [0.8047, -0.281, -0.0624, -0.6449, 1.3519, 0.3272, -0.1701, 0.2146, 0.705] [[cameras.modes]] mode = "16:9" active_area = [18, 18, 66, 24] rawler-0.7.1/data/cameras/leica/dlux4.toml000064400000000000000000000005731046102023000164700ustar 00000000000000make = "LEICA" model = "D-LUX 4" clean_make = "Leica" clean_model = "D-LUX 4" #blackpoint = 0 whitepoint = 3986 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9946, -0.4716, 0.043, -0.444, 1.1224, 0.3705, -0.0676, 0.1538, 0.6348] D65 = [0.8128, -0.2668, -0.0655, -0.6134, 1.3307, 0.3161, -0.1782, 0.2568, 0.6083] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/leica/dlux5.toml000064400000000000000000000010631046102023000164640ustar 00000000000000make = "LEICA" model = "D-LUX 5" clean_make = "Leica" clean_model = "D-LUX 5" #blackpoint = 150 whitepoint = 3986 color_pattern = "GRBG" [cameras.color_matrix] A = [1.2034, -0.6088, 0.003, -0.0465, 0.7861, 0.3136, 0.064, 0.0751, 0.544] D65 = [1.0909, -0.4295, -0.0948, -0.1333, 0.9306, 0.2399, 0.0022, 0.1738, 0.4582] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 104, 4] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 200, 4] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 74, 4] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 220, 4] rawler-0.7.1/data/cameras/leica/dlux7.toml000064400000000000000000000010741046102023000164700ustar 00000000000000make = "LEICA CAMERA AG" model = "D-Lux 7" clean_make = "Leica" clean_model = "D-Lux 7" #blackpoint = 0 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9994, -0.49, 0.0018, -0.4363, 1.3152, 0.1279, -0.0328, 0.0965, 0.5835] D65 = [0.8585, -0.3127, -0.0833, -0.4005, 1.225, 0.1953, -0.065, 0.1494, 0.4862] [[cameras.modes]] mode = "4:3" active_area = [10, 6, 60, 4] [[cameras.modes]] mode = "1:1" active_area = [0, 6, 130, 4] [[cameras.modes]] mode = "16:9" active_area = [10, 0, 90, 0] [[cameras.modes]] mode = "3:2" active_area = [4, 0, 90, 0] rawler-0.7.1/data/cameras/leica/vlux1.toml000064400000000000000000000006701046102023000165050ustar 00000000000000make = "LEICA" model = "V-LUX 1" clean_make = "Leica" clean_model = "V-LUX 1" #blackpoint = 0 whitepoint = 3986 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9649, -0.4671, 0.0453, -0.446, 1.1161, 0.3805, -0.0752, 0.1529, 0.6811] D65 = [0.7906, -0.2709, -0.0594, -0.6231, 1.3352, 0.322, -0.1923, 0.2631, 0.6538] [[cameras.modes]] mode = "3:2" active_area = [4, 0, 14, 4] [[cameras.modes]] mode = "4:3" active_area = [4, 0, 14, 4] rawler-0.7.1/data/cameras/leica/vlux114.toml000064400000000000000000000011031046102023000166420ustar 00000000000000make = "LEICA" model = "V-LUX (Typ 114)" clean_make = "LEICA" clean_model = "V-LUX (Typ 114)" #blackpoint = 143 whitepoint = 3956 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8393, -0.3595, -0.0084, -0.396, 1.1894, 0.2333, -0.0445, 0.1208, 0.6062] D65 = [0.783, -0.2696, -0.0763, -0.3325, 1.1667, 0.1866, -0.0641, 0.1712, 0.4824] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 162, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 34, 0] rawler-0.7.1/data/cameras/leica/vlux4.toml000064400000000000000000000005701046102023000165070ustar 00000000000000make = "LEICA" model = "V-LUX 4" clean_make = "LEICA" clean_model = "V-LUX 4" #blackpoint = 0 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8452, -0.35, 0.0533, -0.2458, 0.9488, 0.3493, -0.016, 0.0993, 0.549] D65 = [0.8112, -0.2563, -0.074, -0.373, 1.1784, 0.2197, -0.0941, 0.2075, 0.4933] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/leica/vlux5.toml000064400000000000000000000006141046102023000165070ustar 00000000000000make = "LEICA CAMERA AG" model = "V-Lux 5" clean_make = "LEICA" clean_model = "V-Lux 5" #blackpoint = 143 whitepoint = 3956 color_pattern = "GBRG" [cameras.color_matrix] A = [1.0745, -0.6036, 0.0459, -0.2974, 1.1274, 0.1932, -0.0078, 0.0806, 0.5819] D65 = [0.9803, -0.4185, -0.0992, -0.4066, 1.2578, 0.1628, -0.0838, 0.1824, 0.5288] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 3] rawler-0.7.1/data/cameras/mamiya/zd.toml000064400000000000000000000005771046102023000162510ustar 00000000000000make = "Mamiya-OP Co.,Ltd." model = "MAMIYA ZD" clean_make = "Mamiya" clean_model = "ZD" blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] #crop_area = [4, 4, 4, 4] [cameras.color_matrix] A = [0.6943, 0.3052, -0.1765, -0.7012, 1.4669, 0.2535, -0.2173, 0.4452, 0.654] D65 = [0.7645, 0.2579, -0.1363, -0.8689, 1.6717, 0.2014, -0.3712, 0.5941, 0.5961] rawler-0.7.1/data/cameras/minolta/7.toml000064400000000000000000000005521046102023000161610ustar 00000000000000make = "Minolta Co., Ltd." model = "DiMAGE 7" clean_make = "Minolta" clean_model = "DiMAGE 7" blackpoint = 0 whitepoint = 3965 color_pattern = "RGGB" active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [1.1235, -0.4957, 0.0074, -0.6536, 1.401, 0.2778, -0.1482, 0.2109, 0.8323] D65 = [0.9258, -0.2879, -0.1008, -0.8076, 1.5847, 0.2351, -0.2806, 0.328, 0.7821] rawler-0.7.1/data/cameras/minolta/7hi.toml000064400000000000000000000005551046102023000165050ustar 00000000000000make = "Minolta Co., Ltd." model = "DiMAGE 7Hi" clean_make = "Minolta" clean_model = "DiMAGE 7Hi" blackpoint = 0 whitepoint = 3965 color_pattern = "RGGB" active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [1.4427, -0.7083, 0.0151, -0.6676, 1.4169, 0.2749, -0.151, 0.214, 0.7902] D65 = [1.1555, -0.4064, -0.1256, -0.7903, 1.5633, 0.2409, -0.2811, 0.332, 0.7358] rawler-0.7.1/data/cameras/minolta/7i.toml000064400000000000000000000005531046102023000163330ustar 00000000000000make = "Minolta Co., Ltd." model = "DiMAGE 7i" clean_make = "Minolta" clean_model = "DiMAGE 7i" blackpoint = 0 whitepoint = 3965 color_pattern = "RGGB" active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [1.3524, -0.6449, 0.0058, -0.6721, 1.417, 0.2802, -0.1556, 0.2194, 0.8265] D65 = [1.105, -0.3791, -0.1199, -0.7875, 1.5585, 0.2434, -0.2797, 0.3359, 0.756] rawler-0.7.1/data/cameras/minolta/a1.toml000064400000000000000000000005531046102023000163150ustar 00000000000000make = "Minolta Co., Ltd." model = "DiMAGE A1" clean_make = "Minolta" clean_model = "DiMAGE A1" blackpoint = 0 whitepoint = 3965 color_pattern = "RGGB" active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [0.9978, -0.3187, -0.0814, -0.7374, 1.532, 0.2169, -0.1369, 0.195, 0.8705] D65 = [0.9274, -0.2548, -0.1167, -0.822, 1.6324, 0.1943, -0.2273, 0.2721, 0.834] rawler-0.7.1/data/cameras/minolta/a2.toml000064400000000000000000000005701046102023000163150ustar 00000000000000make = "Konica Minolta Camera, Inc." model = "DiMAGE A2" clean_make = "Minolta" clean_model = "DiMAGE A2" blackpoint = 0 whitepoint = 3965 color_pattern = "RGGB" active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [1.0002, -0.3955, -0.0245, -0.6658, 1.3766, 0.3218, -0.0589, 0.074, 0.7797] D65 = [0.9097, -0.2726, -0.1052, -0.8074, 1.5506, 0.2762, -0.0966, 0.0982, 0.7763] rawler-0.7.1/data/cameras/minolta/a200.toml000064400000000000000000000006031046102023000164520ustar 00000000000000make = "KONICA MINOLTA" model = "DiMAGE A200" clean_make = "Minolta" clean_model = "DiMAGE A200" blackpoint = 0 whitepoint = 3965 color_pattern = "GBRG" active_area = [0, 0, 0, 0] hints = ["swapped_wb"] [cameras.color_matrix] A = [0.9678, -0.3757, -0.029, -0.6691, 1.38, 0.3215, -0.0718, 0.0954, 0.7673] D65 = [0.856, -0.2487, -0.0986, -0.8111, 1.5535, 0.2771, -0.1209, 0.1324, 0.7742] rawler-0.7.1/data/cameras/minolta/alpha7.toml000064400000000000000000000005251046102023000171670ustar 00000000000000make = "KONICA MINOLTA" model = "ALPHA-7 DIGITAL" clean_make = "Minolta" clean_model = "ALPHA-7" blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" [cameras.color_matrix] A = [1.2036, -0.4955, -0.0076, -0.7019, 1.4449, 0.2811, -0.0513, 0.0636, 0.6839] D65 = [1.0239, -0.3104, -0.1099, -0.8037, 1.5727, 0.2452, -0.0928, 0.0926, 0.6871] rawler-0.7.1/data/cameras/minolta/dynax_7d.toml000064400000000000000000000005171046102023000175310ustar 00000000000000make = "KONICA MINOLTA" model = "DYNAX 7D" clean_make = "Minolta" clean_model = "DYNAX 7D" blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" [cameras.color_matrix] A = [1.2036, -0.4955, -0.0076, -0.7019, 1.4449, 0.2811, -0.0513, 0.0636, 0.6839] D65 = [1.0239, -0.3104, -0.1099, -0.8037, 1.5727, 0.2452, -0.0928, 0.0926, 0.6871] rawler-0.7.1/data/cameras/minolta/g600.toml000064400000000000000000000007231046102023000164670ustar 00000000000000make = "Konica Minolta Photo Imaging, Inc." model = "DiMAGE G600" clean_make = "Konica Minolta" clean_model = "DiMAGE G600" blackpoint = 0 whitepoint = 65353 color_pattern = "RGGB" active_area = [16, 12, 16, 12] raw_width = 2848 raw_height = 2136 [cameras.params] offset_corr = 14 [cameras.color_matrix] A = [1.1235, -0.4957, 0.0074, -0.6536, 1.401, 0.2778, -0.1482, 0.2109, 0.8323] D65 = [0.9258, -0.2879, -0.1008, -0.8076, 1.5847, 0.2351, -0.2806, 0.328, 0.7821] rawler-0.7.1/data/cameras/minolta/maxxum_7d.toml000064400000000000000000000005211046102023000177200ustar 00000000000000make = "KONICA MINOLTA" model = "MAXXUM 7D" clean_make = "Minolta" clean_model = "MAXXUM 7D" blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" [cameras.color_matrix] A = [1.2036, -0.4955, -0.0076, -0.7019, 1.4449, 0.2811, -0.0513, 0.0636, 0.6839] D65 = [1.0239, -0.3104, -0.1099, -0.8037, 1.5727, 0.2452, -0.0928, 0.0926, 0.6871] rawler-0.7.1/data/cameras/nikon/1aw1.toml000064400000000000000000000006431046102023000162400ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON 1 AW1" clean_make = "Nikon" clean_model = "1 AW1" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [6, 6, 6, 6] [cameras.color_matrix] A = [0.692, -0.1829, 0.0018, -0.2514, 0.9725, 0.3272, 0.0146, 0.1316, 0.5566] D65 = [0.6588, -0.1305, -0.0693, -0.3277, 1.0987, 0.2634, -0.0355, 0.2016, 0.5106] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3300 rawler-0.7.1/data/cameras/nikon/1j1.toml000064400000000000000000000006411046102023000160600ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON 1 J1" clean_make = "Nikon" clean_model = "1 J1" color_pattern = "RGGB" active_area = [0, 0, 0, 2] crop_area = [12, 6, 20, 8] [cameras.color_matrix] A = [0.9398, -0.351, 0.018, -0.375, 1.0884, 0.3311, -0.0022, 0.0872, 0.6669] D65 = [0.8994, -0.2667, -0.0865, -0.4594, 1.2324, 0.2552, -0.0699, 0.1786, 0.626] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/1j2.toml000064400000000000000000000006411046102023000160610ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON 1 J2" clean_make = "Nikon" clean_model = "1 J2" color_pattern = "RGGB" active_area = [0, 0, 0, 2] crop_area = [12, 6, 20, 8] [cameras.color_matrix] A = [0.9398, -0.351, 0.018, -0.375, 1.0884, 0.3311, -0.0022, 0.0872, 0.6669] D65 = [0.8994, -0.2667, -0.0865, -0.4594, 1.2324, 0.2552, -0.0699, 0.1786, 0.626] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3300 rawler-0.7.1/data/cameras/nikon/1j3.toml000064400000000000000000000006411046102023000160620ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON 1 J3" clean_make = "Nikon" clean_model = "1 J3" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [6, 6, 6, 6] [cameras.color_matrix] A = [0.692, -0.1829, 0.0018, -0.2514, 0.9725, 0.3272, 0.0146, 0.1316, 0.5566] D65 = [0.6588, -0.1305, -0.0693, -0.3277, 1.0987, 0.2634, -0.0355, 0.2016, 0.5106] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3300 rawler-0.7.1/data/cameras/nikon/1j5.toml000064400000000000000000000006451046102023000160700ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON 1 J5" clean_make = "Nikon" clean_model = "1 J5" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 7, 8, 7] [cameras.color_matrix] A = [0.8097, -0.3404, -0.0074, -0.3897, 1.1673, 0.2527, -0.0634, 0.1625, 0.7974] D65 = [0.752, -0.2518, -0.0645, -0.3844, 1.2102, 0.1945, -0.0913, 0.2249, 0.6835] [[cameras.modes]] mode = "12bit" blackpoint = 200 whitepoint = 3800 rawler-0.7.1/data/cameras/nikon/1s2.toml000064400000000000000000000006461046102023000160770ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON 1 S2" clean_make = "Nikon" clean_model = "1 S2" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 4, 8, 4] [cameras.color_matrix] A = [0.6773, -0.1848, -0.0176, -0.3602, 1.0862, 0.3165, -0.0153, 0.1459, 0.6044] D65 = [0.6612, -0.1342, -0.0618, -0.3338, 1.1055, 0.2623, -0.0174, 0.1792, 0.5075] [[cameras.modes]] mode = "12bit" blackpoint = 200 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/1v1.toml000064400000000000000000000006411046102023000160740ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON 1 V1" clean_make = "Nikon" clean_model = "1 V1" color_pattern = "RGGB" active_area = [0, 0, 0, 2] crop_area = [12, 6, 20, 8] [cameras.color_matrix] A = [0.9398, -0.351, 0.018, -0.375, 1.0884, 0.3311, -0.0022, 0.0872, 0.6669] D65 = [0.8994, -0.2667, -0.0865, -0.4594, 1.2324, 0.2552, -0.0699, 0.1786, 0.626] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/1v2.toml000064400000000000000000000006411046102023000160750ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON 1 V2" clean_make = "Nikon" clean_model = "1 V2" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [6, 6, 6, 6] [cameras.color_matrix] A = [0.692, -0.1829, 0.0018, -0.2514, 0.9725, 0.3272, 0.0146, 0.1316, 0.5566] D65 = [0.6588, -0.1305, -0.0693, -0.3277, 1.0987, 0.2634, -0.0355, 0.2016, 0.5106] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/1v3.toml000064400000000000000000000006441046102023000161010ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON 1 V3" clean_make = "Nikon" clean_model = "1 V3" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [0.6514, -0.235, -0.0042, -0.3026, 0.998, 0.3561, -0.0052, 0.0882, 0.5473] D65 = [0.5958, -0.1559, -0.0571, -0.4021, 1.1453, 0.2939, -0.0634, 0.1548, 0.5087] [[cameras.modes]] mode = "12bit" blackpoint = 200 whitepoint = 4000 rawler-0.7.1/data/cameras/nikon/coolpix_a.toml000064400000000000000000000006521046102023000174440ustar 00000000000000make = "NIKON CORPORATION" model = "COOLPIX A" clean_make = "Nikon" clean_model = "Coolpix A" color_pattern = "RGGB" active_area = [0, 0, 44, 0] crop_area = [8, 8, 56, 8] [cameras.color_matrix] A = [0.8642, -0.3058, -0.0243, -0.3999, 1.1033, 0.3422, -0.0453, 0.1099, 0.7814] D65 = [0.8198, -0.2239, -0.0724, -0.4871, 1.2389, 0.2798, -0.1043, 0.205, 0.7181] [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15892 rawler-0.7.1/data/cameras/nikon/coolpix_a1000.toml000064400000000000000000000006711046102023000177460ustar 00000000000000make = "NIKON CORPORATION" model = "COOLPIX A1000" clean_make = "Nikon" clean_model = "Coolpix A1000" color_pattern = "RGGB" active_area = [0, 0, 0, 0] hints = ["unpacked", "little_endian"] [cameras.color_matrix] A = [1.208, -0.5684, 0.0231, -0.1505, 0.9256, 0.2661, 0.0163, 0.0792, 0.6183] D65 = [1.0601, -0.3487, -0.1127, -0.2931, 1.1443, 0.1676, -0.0587, 0.174, 0.5278] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/coolpix_b700.toml000064400000000000000000000006631046102023000176760ustar 00000000000000make = "NIKON" model = "COOLPIX B700" clean_make = "Nikon" clean_model = "Coolpix B700" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 7, 8, 7] hints = ["msb32"] [cameras.color_matrix] A = [1.5847, -0.8464, 0.0823, -0.0966, 0.8876, 0.2491, 0.0778, 0.0498, 0.5707] D65 = [1.4387, -0.6014, -0.1299, -0.1357, 0.9975, 0.1616, 0.0467, 0.1047, 0.4744] [[cameras.modes]] mode = "12bit" blackpoint = 200 whitepoint = 4000 rawler-0.7.1/data/cameras/nikon/coolpix_e8800.toml000064400000000000000000000006631046102023000177720ustar 00000000000000make = "NIKON" model = "E8800" clean_make = "Nikon" clean_model = "Coolpix E8800" color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [5, 1, 11, 5] hints = ["coolpixsplit"] [cameras.color_matrix] A = [0.9106, -0.3664, -0.0105, -0.6701, 1.3632, 0.343, -0.0681, 0.0905, 0.7683] D65 = [0.797, -0.2314, -0.0913, -0.8452, 1.5762, 0.2894, -0.1442, 0.1521, 0.761] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/coolpix_p1000.toml000064400000000000000000000007021046102023000177600ustar 00000000000000make = "NIKON CORPORATION" model = "COOLPIX P1000" clean_make = "Nikon" clean_model = "Coolpix P1000" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 7, 8, 7] hints = ["msb32"] [cameras.color_matrix] A = [1.6347, -0.9081, 0.1262, -0.0089, 0.7722, 0.2866, 0.0735, 0.0259, 0.5565] D65 = [1.4294, -0.6116, -0.1333, -0.1628, 1.0219, 0.1637, -0.0014, 0.1158, 0.5022] [[cameras.modes]] mode = "12bit" blackpoint = 200 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/coolpix_p330.toml000064400000000000000000000007061046102023000177110ustar 00000000000000make = "NIKON" model = "COOLPIX P330" clean_make = "Nikon" clean_model = "Coolpix P330" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 12, 16, 12] hints = ["unpacked", "big_endian"] [cameras.color_matrix] A = [1.1837, -0.6034, 0.0378, -0.1762, 0.9255, 0.2962, 0.0124, 0.0748, 0.5931] D65 = [1.0321, -0.392, -0.0931, -0.275, 1.1146, 0.1824, -0.0442, 0.1545, 0.5539] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 65000 rawler-0.7.1/data/cameras/nikon/coolpix_p340.toml000064400000000000000000000006731046102023000177150ustar 00000000000000make = "NIKON" model = "COOLPIX P340" clean_make = "Nikon" clean_model = "Coolpix P340" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 12, 16, 12] hints = ["big_endian"] [cameras.color_matrix] A = [1.1837, -0.6034, 0.0378, -0.1762, 0.9255, 0.2962, 0.0124, 0.0748, 0.5931] D65 = [1.0321, -0.392, -0.0931, -0.275, 1.1146, 0.1824, -0.0442, 0.1545, 0.5539] [[cameras.modes]] mode = "12bit" blackpoint = 200 whitepoint = 3800 rawler-0.7.1/data/cameras/nikon/coolpix_p6000.toml000064400000000000000000000006651046102023000177750ustar 00000000000000make = "NIKON" model = "COOLPIX P6000" clean_make = "Nikon" clean_model = "Coolpix P6000" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [9, 2, 7, 4] hints = ["msb32"] [cameras.color_matrix] A = [1.1622, -0.5381, 0.0125, -0.3637, 1.1297, 0.2679, -0.0428, 0.0694, 0.5723] D65 = [0.9698, -0.3367, -0.0914, -0.4706, 1.2584, 0.2368, -0.0837, 0.0968, 0.5801] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/coolpix_p7000.toml000064400000000000000000000006651046102023000177760ustar 00000000000000make = "NIKON" model = "COOLPIX P7000" clean_make = "Nikon" clean_model = "Coolpix P7000" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [7, 2, 9, 4] hints = ["msb32"] [cameras.color_matrix] A = [1.2795, -0.5406, -0.0006, -0.2222, 1.0126, 0.2445, -0.0188, 0.0738, 0.4943] D65 = [1.1432, -0.3679, -0.1111, -0.3169, 1.1239, 0.2202, -0.0791, 0.138, 0.4455] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/coolpix_p7100.toml000064400000000000000000000006661046102023000200000ustar 00000000000000make = "NIKON" model = "COOLPIX P7100" clean_make = "Nikon" clean_model = "Coolpix P7100" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [7, 4, 9, 4] hints = ["msb32"] [cameras.color_matrix] A = [1.1915, -0.5606, 0.0261, -0.1558, 0.9187, 0.2806, -0.0102, 0.0644, 0.5065] D65 = [1.1053, -0.4269, -0.1024, -0.1976, 1.0182, 0.2088, -0.0526, 0.1263, 0.4469] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3800 rawler-0.7.1/data/cameras/nikon/coolpix_p7800.toml000064400000000000000000000007141046102023000200010ustar 00000000000000make = "NIKON" model = "COOLPIX P7800" clean_make = "Nikon" clean_model = "Coolpix P7800" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 12, 16, 12] hints = ["unpacked", "big_endian"] [cameras.color_matrix] A = [1.1837, -0.6034, 0.0378, -0.1762, 0.9255, 0.2962, 0.0124, 0.0748, 0.5931] D65 = [1.0321, -0.392, -0.0931, -0.275, 1.1146, 0.1824, -0.0442, 0.1545, 0.5539] [[cameras.modes]] mode = "12bit" blackpoint = 3195 whitepoint = 65000 rawler-0.7.1/data/cameras/nikon/coolpix_p950.toml000064400000000000000000000006761046102023000177270ustar 00000000000000make = "NIKON CORPORATION" model = "COOLPIX P950" clean_make = "Nikon" clean_model = "Coolpix P950" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 7, 8, 7] hints = ["msb32"] [cameras.color_matrix] A = [1.5101, -0.8261, 0.1066, -0.0643, 0.8241, 0.2883, 0.055, 0.0456, 0.5677] D65 = [1.3307, -0.5641, -0.129, -0.2048, 1.0581, 0.1689, -0.0064, 0.1222, 0.5176] [[cameras.modes]] mode = "12bit" blackpoint = 200 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/d1.toml000064400000000000000000000006401046102023000157700ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D1" clean_make = "Nikon" clean_model = "D1" color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [6, 6, 6, 6] [cameras.color_matrix] A = [0.8452, -0.3021, -0.0439, -0.8003, 1.5752, 0.2382, -0.1568, 0.215, 0.8985] D65 = [0.7637, -0.2199, -0.0974, -0.9109, 1.7099, 0.2043, -0.2822, 0.3306, 0.8372] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/d100.toml000064400000000000000000000006501046102023000161310ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D100" clean_make = "Nikon" clean_model = "D100" color_pattern = "GRBG" active_area = [0, 0, 8, 0] crop_area = [11, 12, 21, 12] [cameras.color_matrix] A = [0.6408, -0.1391, -0.0554, -0.7732, 1.5177, 0.2762, -0.0663, 0.0833, 0.6678] D65 = [0.5902, -0.0933, -0.0782, -0.8982, 1.6719, 0.2354, -0.1402, 0.1455, 0.6464] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/d1x.toml000064400000000000000000000007411046102023000161620ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D1X" clean_make = "Nikon" clean_model = "D1X" color_pattern = "BGGR" active_area = [0, 0, 4, 0] crop_area = [5, 6, 11, 10] default_scale = [[3, 4], [3, 2]] best_quality_scale = [4, 3] [cameras.color_matrix] A = [0.8782, -0.3307, -0.0369, -0.8013, 1.5872, 0.2248, -0.1397, 0.1883, 0.9065] D65 = [0.7702, -0.2244, -0.0975, -0.9114, 1.7242, 0.1875, -0.2679, 0.3055, 0.8522] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/d200.toml000064400000000000000000000006501046102023000161320ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D200" clean_make = "Nikon" clean_model = "D200" color_pattern = "GRBG" active_area = [0, 0, 4, 0] crop_area = [15, 12, 17, 12] [cameras.color_matrix] A = [0.9483, -0.3452, -0.0142, -0.7374, 1.4683, 0.2942, -0.0723, 0.0859, 0.8369] D65 = [0.8367, -0.2248, -0.0763, -0.8758, 1.6447, 0.2422, -0.1528, 0.1551, 0.8053] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d2h.toml000064400000000000000000000006431046102023000161440ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D2H" clean_make = "Nikon" clean_model = "D2H" color_pattern = "GBRG" active_area = [6, 0, 8, 0] crop_area = [15, 8, 17, 8] [cameras.color_matrix] A = [0.6562, -0.1792, -0.0314, -0.6967, 1.4736, 0.2402, -0.1709, 0.2719, 0.7642] D65 = [0.5733, -0.0911, -0.0629, -0.7967, 1.5987, 0.2055, -0.305, 0.4013, 0.7048] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d2hs.toml000064400000000000000000000006451046102023000163310ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D2Hs" clean_make = "Nikon" clean_model = "D2Hs" color_pattern = "GBRG" active_area = [6, 0, 8, 0] crop_area = [16, 9, 16, 7] [cameras.color_matrix] A = [0.6562, -0.1792, -0.0314, -0.6967, 1.4736, 0.2402, -0.1709, 0.2719, 0.7642] D65 = [0.5733, -0.0911, -0.0629, -0.7967, 1.5987, 0.2055, -0.305, 0.4013, 0.7048] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d2x.toml000064400000000000000000000006421046102023000161630ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D2X" clean_make = "Nikon" clean_model = "D2X" color_pattern = "RGGB" active_area = [0, 0, 8, 0] crop_area = [16, 10, 16, 10] [cameras.color_matrix] A = [1.0996, -0.3606, -0.0715, -0.7096, 1.441, 0.2947, -0.046, 0.0487, 0.7018] D65 = [1.0231, -0.2768, -0.1254, -0.8302, 1.59, 0.2551, -0.0797, 0.0681, 0.7148] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d2xs.toml000064400000000000000000000006441046102023000163500ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D2Xs" clean_make = "Nikon" clean_model = "D2Xs" color_pattern = "RGGB" active_area = [0, 0, 8, 0] crop_area = [16, 10, 16, 10] [cameras.color_matrix] A = [1.0996, -0.3606, -0.0715, -0.7096, 1.441, 0.2947, -0.046, 0.0487, 0.7018] D65 = [1.0231, -0.2768, -0.1254, -0.8302, 1.59, 0.2551, -0.0797, 0.0681, 0.7148] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d3.toml000064400000000000000000000007451046102023000160000ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D3" clean_make = "Nikon" clean_model = "D3" color_pattern = "RGGB" active_area = [2, 0, 2, 0] crop_area = [15, 6, 17, 6] [cameras.color_matrix] A = [0.9336, -0.3405, 0.0014, -0.7321, 1.4779, 0.2764, -0.0914, 0.1171, 0.8248] D65 = [0.8139, -0.2171, -0.0664, -0.8748, 1.6541, 0.2296, -0.1924, 0.2008, 0.8093] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3972 [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15892 rawler-0.7.1/data/cameras/nikon/d300.toml000064400000000000000000000007521046102023000161360ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D300" clean_make = "Nikon" clean_model = "D300" color_pattern = "RGGB" active_area = [0, 0, 32, 0] crop_area = [15, 10, 49, 10] [cameras.color_matrix] A = [1.0354, -0.3401, 0.0054, -0.7111, 1.4628, 0.2702, -0.135, 0.2011, 0.8528] D65 = [0.903, -0.1992, -0.0716, -0.8465, 1.6302, 0.2256, -0.2689, 0.3217, 0.8069] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3808 [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15236 rawler-0.7.1/data/cameras/nikon/d3000.toml000064400000000000000000000006501046102023000162130ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D3000" clean_make = "Nikon" clean_model = "D3000" color_pattern = "GBRG" active_area = [0, 0, 4, 4] crop_area = [14, 9, 18, 15] [cameras.color_matrix] A = [0.9768, -0.3578, -0.0263, -0.7716, 1.5197, 0.272, -0.0601, 0.0671, 0.8454] D65 = [0.8736, -0.2458, -0.0935, -0.9075, 1.6894, 0.2251, -0.1354, 0.1242, 0.8263] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d300s.toml000064400000000000000000000007541046102023000163230ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D300S" clean_make = "Nikon" clean_model = "D300S" color_pattern = "RGGB" active_area = [0, 0, 32, 0] crop_area = [15, 10, 49, 10] [cameras.color_matrix] A = [1.0354, -0.3401, 0.0054, -0.7111, 1.4628, 0.2702, -0.135, 0.2011, 0.8528] D65 = [0.903, -0.1992, -0.0716, -0.8465, 1.6302, 0.2256, -0.2689, 0.3217, 0.8069] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3808 [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15236 rawler-0.7.1/data/cameras/nikon/d3100.toml000064400000000000000000000006451046102023000162200ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D3100" clean_make = "Nikon" clean_model = "D3100" color_pattern = "GBRG" active_area = [6, 0, 22, 0] crop_area = [24, 6, 40, 6] [cameras.color_matrix] A = [0.8306, -0.282, -0.041, -0.455, 1.1949, 0.2955, -0.0675, 0.1472, 0.8632] D65 = [0.7911, -0.2167, -0.0813, -0.5327, 1.315, 0.2408, -0.1288, 0.2483, 0.7968] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d3200.toml000064400000000000000000000006451046102023000162210ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D3200" clean_make = "Nikon" clean_model = "D3200" color_pattern = "RGGB" active_area = [0, 0, 46, 0] crop_area = [8, 6, 56, 6] [cameras.color_matrix] A = [0.7179, -0.1985, 0.0103, -0.4102, 1.0944, 0.3649, -0.0609, 0.1585, 0.8185] D65 = [0.7013, -0.1408, -0.0635, -0.5268, 1.2902, 0.264, -0.147, 0.2801, 0.7379] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d3300.toml000064400000000000000000000006451046102023000162220ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D3300" clean_make = "Nikon" clean_model = "D3300" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [0.9672, -0.4153, 0.0064, -0.412, 1.1852, 0.2571, -0.094, 0.1812, 0.7894] D65 = [0.6988, -0.1384, -0.0714, -0.5631, 1.341, 0.2447, -0.1485, 0.2204, 0.7318] [[cameras.modes]] mode = "12bit" #blackpoint = 150 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d3400.toml000064400000000000000000000006451046102023000162230ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D3400" clean_make = "Nikon" clean_model = "D3400" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [0.9672, -0.4153, 0.0064, -0.412, 1.1852, 0.2571, -0.094, 0.1812, 0.7894] D65 = [0.6988, -0.1384, -0.0714, -0.5631, 1.341, 0.2447, -0.1485, 0.2204, 0.7318] [[cameras.modes]] mode = "12bit" #blackpoint = 150 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d3500.toml000064400000000000000000000006501046102023000162200ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D3500" clean_make = "Nikon" clean_model = "D3500" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [0.9659, -0.3972, -0.0266, -0.4733, 1.2653, 0.2316, -0.0649, 0.1302, 0.8287] D65 = [0.8821, -0.2938, -0.0785, -0.4178, 1.2142, 0.2287, -0.0824, 0.1651, 0.686] [[cameras.modes]] mode = "12bit" #blackpoint = 150 whitepoint = 3972 rawler-0.7.1/data/cameras/nikon/d3s.toml000064400000000000000000000007461046102023000161640ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D3S" clean_make = "Nikon" clean_model = "D3S" color_pattern = "RGGB" active_area = [2, 0, 2, 0] crop_area = [15, 6, 17, 6] [cameras.color_matrix] A = [1.3623, -0.8096, 0.0478, -0.3863, 1.1393, 0.2827, -0.0202, 0.0707, 0.8616] D65 = [0.8828, -0.2406, -0.0694, -0.4874, 1.2603, 0.2541, -0.066, 0.1509, 0.7587] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/d3x.toml000064400000000000000000000006431046102023000161650ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D3X" clean_make = "Nikon" clean_model = "D3X" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [15, 6, 17, 6] [cameras.color_matrix] A = [0.8213, -0.3151, 0.0011, -0.6594, 1.3688, 0.3236, -0.1101, 0.1577, 0.7803] D65 = [0.7171, -0.1986, -0.0648, -0.8085, 1.5555, 0.2718, -0.217, 0.2512, 0.7457] [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15892 rawler-0.7.1/data/cameras/nikon/d4.toml000064400000000000000000000007461046102023000160020ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D4" clean_make = "Nikon" clean_model = "D4" color_pattern = "RGGB" active_area = [2, 0, 50, 0] crop_area = [8, 6, 56, 6] [cameras.color_matrix] A = [0.9033, -0.3555, -0.0287, -0.4881, 1.2214, 0.3022, -0.0459, 0.0926, 0.7932] D65 = [0.8598, -0.2848, -0.0857, -0.5618, 1.3606, 0.2195, -0.1002, 0.1773, 0.7137] [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15520 [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d40.toml000064400000000000000000000006421046102023000160550ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D40" clean_make = "Nikon" clean_model = "D40" color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [15, 7, 17, 7] [cameras.color_matrix] A = [0.7943, -0.2691, -0.0166, -0.708, 1.4377, 0.2969, -0.0477, 0.0561, 0.7879] D65 = [0.6992, -0.1667, -0.0806, -0.8138, 1.5748, 0.2543, -0.0874, 0.085, 0.7896] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d40x.toml000064400000000000000000000006471046102023000162520ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D40X" clean_make = "Nikon" clean_model = "D40X" color_pattern = "GBRG" active_area = [0, 0, 4, 0] crop_area = [14, 9, 18, 12] [cameras.color_matrix] A = [1.0031, -0.3797, -0.0207, -0.7735, 1.5316, 0.2598, -0.0603, 0.0667, 0.8673] D65 = [0.8819, -0.2543, -0.0911, -0.9025, 1.6928, 0.2151, -0.1329, 0.1213, 0.8449] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d4s.toml000064400000000000000000000007521046102023000161620ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D4S" clean_make = "Nikon" clean_model = "D4S" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 4, 4, 4] [cameras.color_matrix] A = [0.9033, -0.3555, -0.0287, -0.4881, 1.2214, 0.3022, -0.0459, 0.0926, 0.7932] D65 = [0.8598, -0.2848, -0.0857, -0.5618, 1.3606, 0.2195, -0.1002, 0.1773, 0.7137] [[cameras.modes]] mode = "14bit" blackpoint = 768 whitepoint = 15520 [[cameras.modes]] mode = "12bit" blackpoint = 192 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d5.toml000064400000000000000000000006401046102023000157740ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D5" clean_make = "Nikon" clean_model = "D5" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [0.9792, -0.4494, -0.0473, -0.561, 1.3249, 0.2619, -0.0441, 0.1014, 0.729] D65 = [0.92, -0.3522, -0.0992, -0.5755, 1.3803, 0.2117, -0.0753, 0.1486, 0.6338] [[cameras.modes]] mode = "14bit" #blackpoint = 400 whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/d50.toml000064400000000000000000000006401046102023000160540ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D50" clean_make = "Nikon" clean_model = "D50" color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [15, 7, 17, 7] [cameras.color_matrix] A = [0.9505, -0.4311, 0.022, -0.6712, 1.4078, 0.2902, -0.0318, 0.042, 0.7267] D65 = [0.7732, -0.2421, -0.0789, -0.8238, 1.5883, 0.2498, -0.0859, 0.0783, 0.733] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/d500.toml000064400000000000000000000010641046102023000161350ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D500" clean_make = "Nikon" clean_model = "D500" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] # TODO: This camera has Large/Medium/Small format with different crop [cameras.color_matrix] A = [0.9376, -0.4139, -0.0394, -0.4687, 1.2495, 0.2454, -0.0699, 0.1378, 0.7486] D65 = [0.8813, -0.321, -0.1036, -0.4703, 1.2868, 0.2021, -0.1054, 0.194, 0.6129] [[cameras.modes]] mode = "14bit" #blackpoint = 400 whitepoint = 15520 [[cameras.modes]] mode = "12bit" #blackpoint = 100 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d5000.toml000064400000000000000000000006461046102023000162220ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D5000" clean_make = "Nikon" clean_model = "D5000" color_pattern = "GBRG" active_area = [0, 0, 42, 0] crop_area = [11, 10, 53, 10] [cameras.color_matrix] A = [0.8437, -0.2581, 0.0132, -0.6948, 1.4143, 0.31, -0.1215, 0.1778, 0.83] D65 = [0.7309, -0.1403, -0.0519, -0.8474, 1.6008, 0.2622, -0.2433, 0.2826, 0.8064] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3767 rawler-0.7.1/data/cameras/nikon/d5100.toml000064400000000000000000000006501046102023000162160ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D5100" clean_make = "Nikon" clean_model = "D5100" color_pattern = "RGGB" active_area = [0, 0, 44, 0] crop_area = [8, 8, 56, 8] [cameras.color_matrix] A = [0.8642, -0.3058, -0.0243, -0.3999, 1.1033, 0.3422, -0.0453, 0.1099, 0.7814] D65 = [0.8198, -0.2239, -0.0724, -0.4871, 1.2389, 0.2798, -0.1043, 0.205, 0.7181] [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15892 rawler-0.7.1/data/cameras/nikon/d5200.toml000064400000000000000000000006531046102023000162220ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D5200" clean_make = "Nikon" clean_model = "D5200" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [18, 10, 18, 10] [cameras.color_matrix] A = [0.8693, -0.3745, -0.0467, -0.5349, 1.2601, 0.3098, -0.0367, 0.0752, 0.7041] D65 = [0.8322, -0.3112, -0.1047, -0.6367, 1.4342, 0.2179, -0.0988, 0.1638, 0.6394] [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15892 rawler-0.7.1/data/cameras/nikon/d5300.toml000064400000000000000000000007541046102023000162250ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D5300" clean_make = "Nikon" clean_model = "D5300" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [0.9672, -0.4153, 0.0064, -0.412, 1.1852, 0.2571, -0.094, 0.1812, 0.7894] D65 = [0.6988, -0.1384, -0.0714, -0.5631, 1.341, 0.2447, -0.1485, 0.2204, 0.7318] [[cameras.modes]] mode = "12bit" #blackpoint = 150 whitepoint = 3972 [[cameras.modes]] mode = "14bit" #blackpoint = 600 whitepoint = 15892 rawler-0.7.1/data/cameras/nikon/d5500.toml000064400000000000000000000007571046102023000162320ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D5500" clean_make = "Nikon" clean_model = "D5500" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [0.9659, -0.3972, -0.0266, -0.4733, 1.2653, 0.2316, -0.0649, 0.1302, 0.8287] D65 = [0.8821, -0.2938, -0.0785, -0.4178, 1.2142, 0.2287, -0.0824, 0.1651, 0.686] [[cameras.modes]] mode = "14bit" #blackpoint = 600 whitepoint = 15892 [[cameras.modes]] mode = "12bit" #blackpoint = 150 whitepoint = 3972 rawler-0.7.1/data/cameras/nikon/d5600.toml000064400000000000000000000007571046102023000162330ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D5600" clean_make = "Nikon" clean_model = "D5600" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [0.9659, -0.3972, -0.0266, -0.4733, 1.2653, 0.2316, -0.0649, 0.1302, 0.8287] D65 = [0.8821, -0.2938, -0.0785, -0.4178, 1.2142, 0.2287, -0.0824, 0.1651, 0.686] [[cameras.modes]] mode = "14bit" #blackpoint = 600 whitepoint = 15892 [[cameras.modes]] mode = "12bit" #blackpoint = 150 whitepoint = 3972 rawler-0.7.1/data/cameras/nikon/d6.toml000064400000000000000000000007531046102023000160020ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D6" clean_make = "Nikon" clean_model = "D6" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [1.0069, -0.4889, -0.0308, -0.4631, 1.2025, 0.2957, -0.0149, 0.0673, 0.7522] D65 = [0.9028, -0.3423, -0.1035, -0.6321, 1.4265, 0.2217, -0.1013, 0.1683, 0.6928] [[cameras.modes]] mode = "12bit" #blackpoint = 252 whitepoint = 3880 [[cameras.modes]] mode = "14bit" #blackpoint = 1008 whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/d60.toml000064400000000000000000000006441046102023000160610ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D60" clean_make = "Nikon" clean_model = "D60" color_pattern = "GBRG" active_area = [0, 0, 4, 4] crop_area = [14, 9, 18, 15] [cameras.color_matrix] A = [0.9768, -0.3578, -0.0263, -0.7716, 1.5197, 0.272, -0.0601, 0.0671, 0.8454] D65 = [0.8736, -0.2458, -0.0935, -0.9075, 1.6894, 0.2251, -0.1354, 0.1242, 0.8263] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d600.toml000064400000000000000000000007511046102023000161400ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D600" clean_make = "Nikon" clean_model = "D600" color_pattern = "RGGB" active_area = [0, 0, 46, 0] crop_area = [8, 6, 56, 6] [cameras.color_matrix] A = [0.8508, -0.2966, 0.0171, -0.3991, 1.0849, 0.3635, -0.0467, 0.1053, 0.8072] D65 = [0.8178, -0.2245, -0.0609, -0.4857, 1.2394, 0.2776, -0.1207, 0.2086, 0.7298] [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15520 [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d610.toml000064400000000000000000000007511046102023000161410ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D610" clean_make = "Nikon" clean_model = "D610" color_pattern = "RGGB" active_area = [0, 0, 46, 0] crop_area = [8, 6, 56, 6] [cameras.color_matrix] A = [0.8508, -0.2966, 0.0171, -0.3991, 1.0849, 0.3635, -0.0467, 0.1053, 0.8072] D65 = [0.8178, -0.2245, -0.0609, -0.4857, 1.2394, 0.2776, -0.1207, 0.2086, 0.7298] [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15520 [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d70.toml000064400000000000000000000006401046102023000160560ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D70" clean_make = "Nikon" clean_model = "D70" color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [15, 7, 17, 7] [cameras.color_matrix] A = [0.9505, -0.4311, 0.022, -0.6712, 1.4078, 0.2902, -0.0318, 0.042, 0.7267] D65 = [0.7732, -0.2421, -0.0789, -0.8238, 1.5883, 0.2498, -0.0859, 0.0783, 0.733] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/d700.toml000064400000000000000000000007511046102023000161410ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D700" clean_make = "Nikon" clean_model = "D700" color_pattern = "RGGB" active_area = [2, 0, 2, 0] crop_area = [15, 6, 17, 6] [cameras.color_matrix] A = [0.9336, -0.3405, 0.0014, -0.7321, 1.4779, 0.2764, -0.0914, 0.1171, 0.8248] D65 = [0.8139, -0.2171, -0.0664, -0.8748, 1.6541, 0.2296, -0.1924, 0.2008, 0.8093] [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15892 [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3972 rawler-0.7.1/data/cameras/nikon/d7000.toml000064400000000000000000000007531046102023000162230ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D7000" clean_make = "Nikon" clean_model = "D7000" color_pattern = "RGGB" active_area = [0, 0, 44, 0] crop_area = [8, 8, 56, 8] [cameras.color_matrix] A = [0.8642, -0.3058, -0.0243, -0.3999, 1.1033, 0.3422, -0.0453, 0.1099, 0.7814] D65 = [0.8198, -0.2239, -0.0724, -0.4871, 1.2389, 0.2798, -0.1043, 0.205, 0.7181] [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15892 [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3972 rawler-0.7.1/data/cameras/nikon/d70s.toml000064400000000000000000000006421046102023000162430ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D70s" clean_make = "Nikon" clean_model = "D70s" color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [15, 7, 17, 7] [cameras.color_matrix] A = [0.9505, -0.4311, 0.022, -0.6712, 1.4078, 0.2902, -0.0318, 0.042, 0.7267] D65 = [0.7732, -0.2421, -0.0789, -0.8238, 1.5883, 0.2498, -0.0859, 0.0783, 0.733] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/d7100.toml000064400000000000000000000007561046102023000162270ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D7100" clean_make = "Nikon" clean_model = "D7100" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [18, 10, 18, 10] [cameras.color_matrix] A = [0.8693, -0.3745, -0.0467, -0.5349, 1.2601, 0.3098, -0.0367, 0.0752, 0.7041] D65 = [0.8322, -0.3112, -0.1047, -0.6367, 1.4342, 0.2179, -0.0988, 0.1638, 0.6394] [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15892 [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3972 rawler-0.7.1/data/cameras/nikon/d7200.toml000064400000000000000000000007601046102023000162230ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D7200" clean_make = "Nikon" clean_model = "D7200" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [0.8693, -0.3745, -0.0467, -0.5349, 1.2601, 0.3098, -0.0367, 0.0752, 0.7041] D65 = [0.8322, -0.3112, -0.1047, -0.6367, 1.4342, 0.2179, -0.0988, 0.1638, 0.6394] [[cameras.modes]] mode = "14bit" #blackpoint = 600 whitepoint = 15892 [[cameras.modes]] mode = "12bit" #blackpoint = 150 whitepoint = 3972 rawler-0.7.1/data/cameras/nikon/d750.toml000064400000000000000000000007521046102023000161470ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D750" clean_make = "Nikon" clean_model = "D750" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [1.0019, -0.42, -0.0032, -0.4773, 1.2481, 0.2572, -0.0643, 0.1409, 0.8486] D65 = [0.902, -0.289, -0.0715, -0.4535, 1.2436, 0.2348, -0.0934, 0.1919, 0.7086] [[cameras.modes]] mode = "14bit" #blackpoint = 600 whitepoint = 15520 [[cameras.modes]] mode = "12bit" #blackpoint = 150 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d7500.toml000064400000000000000000000010021046102023000162140ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D7500" clean_make = "NIKON CORPORATION" clean_model = "NIKON D7500" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] [cameras.color_matrix] A = [0.9376, -0.4139, -0.0394, -0.4687, 1.2495, 0.2454, -0.0699, 0.1378, 0.7486] D65 = [0.8813, -0.321, -0.1036, -0.4703, 1.2868, 0.2021, -0.1054, 0.194, 0.6129] [[cameras.modes]] mode = "12bit" #blackpoint = 100 whitepoint = 3880 [[cameras.modes]] mode = "14bit" #blackpoint = 400 whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/d780.toml000064400000000000000000000007551046102023000161550ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D780" clean_make = "Nikon" clean_model = "D780" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [1.1395, -0.5115, 0.0263, -0.4486, 1.2207, 0.2568, -0.045, 0.1207, 0.8802] D65 = [0.9943, -0.3269, -0.0839, -0.5323, 1.3269, 0.2259, -0.1198, 0.2083, 0.7557] [[cameras.modes]] mode = "14bit" #blackpoint = 1008 whitepoint = 15520 [[cameras.modes]] mode = "12bit" #blackpoint = 251 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d80.toml000064400000000000000000000007451046102023000160650ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D80" clean_make = "Nikon" clean_model = "D80" color_pattern = "GBRG" active_area = [0, 0, 4, 4] crop_area = [14, 9, 18, 15] [cameras.color_matrix] A = [0.9875, -0.3671, -0.0203, -0.7719, 1.5276, 0.2626, -0.0648, 0.0723, 0.8706] D65 = [0.8628, -0.241, -0.0883, -0.9055, 1.694, 0.2171, -0.1491, 0.1363, 0.852] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 [[cameras.modes]] mode = "16bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/d800.toml000064400000000000000000000010311046102023000161320ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D800" clean_make = "Nikon" clean_model = "D800" model_aliases = [ ["NIKON D800E", "D800E"], ] color_pattern = "RGGB" active_area = [0, 0, 46, 0] crop_area = [8, 6, 56, 6] [cameras.color_matrix] A = [0.8437, -0.3046, 0.0228, -0.397, 1.0927, 0.3516, -0.0444, 0.1049, 0.825] D65 = [0.7866, -0.2108, -0.0555, -0.4869, 1.2483, 0.2681, -0.1176, 0.2069, 0.7501] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/d810.toml000064400000000000000000000007551046102023000161470ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D810" clean_make = "Nikon" clean_model = "D810" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 8, 8, 8] [cameras.color_matrix] A = [1.0354, -0.4532, 0.0031, -0.5168, 1.2906, 0.2518, -0.0733, 0.1407, 0.8361] D65 = [0.9369, -0.3195, -0.0791, -0.4488, 1.243, 0.2301, -0.0893, 0.1796, 0.6872] [[cameras.modes]] mode = "12bit" #blackpoint = 150 whitepoint = 3880 [[cameras.modes]] mode = "14bit" #blackpoint = 600 whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/d850.toml000064400000000000000000000011051046102023000161410ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D850" clean_make = "NIKON CORPORATION" clean_model = "NIKON D850" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] # TODO: This camera has Large/Medium/Small format with different crop [cameras.color_matrix] A = [1.1284, -0.4911, -0.0608, -0.6062, 1.4228, 0.196, -0.0877, 0.1605, 0.8117] D65 = [1.0405, -0.3755, -0.127, -0.5461, 1.3787, 0.1793, -0.104, 0.2015, 0.6785] [[cameras.modes]] mode = "12bit" #blackpoint = 100 whitepoint = 3880 [[cameras.modes]] mode = "14bit" #blackpoint = 400 whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/d90.toml000064400000000000000000000006421046102023000160620ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON D90" clean_make = "Nikon" clean_model = "D90" color_pattern = "GBRG" active_area = [0, 0, 42, 0] crop_area = [11, 10, 53, 10] [cameras.color_matrix] A = [0.8437, -0.2581, 0.0132, -0.6948, 1.4143, 0.31, -0.1215, 0.1778, 0.83] D65 = [0.7309, -0.1403, -0.0519, -0.8474, 1.6008, 0.2622, -0.2433, 0.2826, 0.8064] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3767 rawler-0.7.1/data/cameras/nikon/df.toml000064400000000000000000000007461046102023000160640ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Df" clean_make = "Nikon" clean_model = "Df" color_pattern = "RGGB" active_area = [2, 0, 50, 0] crop_area = [8, 6, 56, 6] [cameras.color_matrix] A = [0.9033, -0.3555, -0.0287, -0.4881, 1.2214, 0.3022, -0.0459, 0.0926, 0.7932] D65 = [0.8598, -0.2848, -0.0857, -0.5618, 1.3606, 0.2195, -0.1002, 0.1773, 0.7137] [[cameras.modes]] mode = "14bit" blackpoint = 0 whitepoint = 15520 [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 3880 rawler-0.7.1/data/cameras/nikon/e5400.toml000064400000000000000000000006531046102023000162250ustar 00000000000000make = "NIKON" model = "E5400" clean_make = "Nikon" clean_model = "E5400" color_pattern = "BGGR" hints = ["coolpixsplit"] active_area = [0, 0, 0, 0] crop_area = [8, 2, 8, 4] [cameras.color_matrix] A = [1.0761, -0.4766, 0.0061, -0.5795, 1.3064, 0.3059, -0.1058, 0.1707, 0.7019] D65 = [0.9349, -0.2988, -0.1001, -0.7918, 1.5766, 0.2266, -0.2097, 0.268, 0.6839] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/e5700.toml000064400000000000000000000007641046102023000162330ustar 00000000000000make = "NIKON" model = "E5700" clean_make = "Nikon" clean_model = "E5700" color_pattern = "RGEB" # TODO: unsupported active_area = [0, 0, 0, 0] crop_area = [8, 2, 8, 2] hints = ["coolpixsplit", "nowb"] [cameras.color_matrix] A = [-0.4675, 1.021, 0.3078, 0.666, -0.1633, 0.3746, -0.4208, 0.8856, 0.6304, 0.157, 0.7288, 0.1099] D65 = [-0.6475, 1.2496, 0.2428, 0.5409, -0.0016, 0.318, -0.5965, 1.0912, 0.5866, -0.0177, 0.9918, 0.0248] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/e8400.toml000064400000000000000000000006551046102023000162320ustar 00000000000000make = "NIKON" model = "E8400" clean_make = "Nikon" clean_model = "E8400" color_pattern = "BGGR" hints = ["coolpixsplit"] active_area = [0, 0, 0, 0] crop_area = [5, 1, 11, 5] [cameras.color_matrix] A = [0.8578, -0.3296, -0.0237, -0.6914, 1.3965, 0.3274, -0.0621, 0.0808, 0.7863] D65 = [0.7842, -0.2319, -0.0992, -0.8154, 1.5719, 0.2599, -0.1098, 0.1342, 0.756] [[cameras.modes]] mode = "12bit" blackpoint = 0 whitepoint = 4095 rawler-0.7.1/data/cameras/nikon/z30.toml000064400000000000000000000007101046102023000160760ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z 30" clean_make = "Nikon" clean_model = "Z 30" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] [cameras.color_matrix] A = [1.1924, -0.638, 0.0632, -0.3999, 1.173, 0.2577, -0.0297, 0.0908, 0.8341] D65 = [1.0339, -0.3822, -0.089, -0.4183, 1.2023, 0.2436, -0.0671, 0.1638, 0.7049] [[cameras.modes]] mode = "12bit" whitepoint = 3972 [[cameras.modes]] mode = "14bit" whitepoint = 15892 rawler-0.7.1/data/cameras/nikon/z5.toml000064400000000000000000000007101046102023000160200ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z 5" clean_make = "Nikon" clean_model = "Z 5" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 8, 12, 8] [cameras.color_matrix] A = [1.0236, -0.4532, 0.0397, -0.3403, 1.0623, 0.3223, -0.0242, 0.0968, 0.853] D65 = [0.8695, -0.2558, -0.0648, -0.5015, 1.2711, 0.2575, -0.1279, 0.2215, 0.7514] [[cameras.modes]] mode = "12bit" whitepoint = 3880 [[cameras.modes]] mode = "14bit" whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/z50.toml000064400000000000000000000007061046102023000161050ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z 50" clean_make = "Nikon" clean_model = "Z 50" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] [cameras.color_matrix] A = [1.3247, -0.7357, 0.0658, -0.4296, 1.227, 0.2269, -0.0237, 0.08, 0.7992] D65 = [1.164, -0.4829, -0.1079, -0.5107, 1.3006, 0.2325, -0.0972, 0.1711, 0.738] [[cameras.modes]] mode = "12bit" whitepoint = 3880 [[cameras.modes]] mode = "14bit" whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/z50_mk2.toml000064400000000000000000000005731046102023000166600ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z50_2" clean_make = "Nikon" clean_model = "Z 50 II" color_pattern = "RGGB" active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [1.3247, -0.7357, 0.0658, -0.4296, 1.227, 0.2269, -0.0237, 0.08, 0.7992] D65 = [1.164, -0.4829, -0.1079, -0.5107, 1.3006, 0.2325, -0.0972, 0.1711, 0.738] [[cameras.modes]] mode = "14bit" whitepoint = 15892 rawler-0.7.1/data/cameras/nikon/z5_mk2.toml000064400000000000000000000005741046102023000166010ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z5_2" clean_make = "Nikon" clean_model = "Z 5 II" color_pattern = "RGGB" active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [1.2583, -0.6925, 0.1406, -0.3319, 1.0489, 0.3286, -0.0088, 0.0801, 0.8495] D65 = [1.3133, -0.5542, -0.128, -0.4325, 1.2543, 0.1972, 0.0034, 0.0792, 0.7662] [[cameras.modes]] mode = "14bit" whitepoint = 15892 rawler-0.7.1/data/cameras/nikon/z6.toml000064400000000000000000000007061046102023000160260ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z 6" clean_make = "Nikon" clean_model = "Z 6" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [1.1395, -0.5115, 0.0263, -0.4486, 1.2207, 0.2568, -0.045, 0.1207, 0.8802] D65 = [0.9943, -0.3269, -0.0839, -0.5323, 1.3269, 0.2259, -0.1198, 0.2083, 0.7557] [[cameras.modes]] mode = "12bit" whitepoint = 3880 [[cameras.modes]] mode = "14bit" whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/z6_mk2.toml000064400000000000000000000007111046102023000165730ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z 6_2" clean_make = "Nikon" clean_model = "Z 6 2" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [1.1395, -0.5115, 0.0263, -0.4486, 1.2207, 0.2568, -0.045, 0.1207, 0.8802] D65 = [0.9943, -0.3269, -0.0839, -0.5323, 1.3269, 0.2259, -0.1198, 0.2083, 0.7557] [[cameras.modes]] mode = "12bit" whitepoint = 3880 [[cameras.modes]] mode = "14bit" whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/z6_mk3.toml000064400000000000000000000005731046102023000166020ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z6_3" clean_make = "Nikon" clean_model = "Z 6 3" color_pattern = "RGGB" active_area = [0, 0, 0, 0] [cameras.color_matrix] A = [1.3528, -0.7602, 0.0739, -0.4587, 1.2543, 0.228, -0.0273, 0.088, 0.8666] D65 = [1.1206, -0.4286, -0.0941, -0.4879, 1.2847, 0.2251, -0.0745, 0.1654, 0.7374] [[cameras.modes]] mode = "14bit" whitepoint = 15892 rawler-0.7.1/data/cameras/nikon/z7.toml000064400000000000000000000007041046102023000160250ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z 7" clean_make = "Nikon" clean_model = "Z 7" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] [cameras.color_matrix] A = [1.4496, -0.8028, 0.0682, -0.465, 1.2681, 0.2185, -0.021, 0.0781, 0.8334] D65 = [1.3705, -0.6004, -0.14, -0.5464, 1.3568, 0.2062, -0.094, 0.1706, 0.7618] [[cameras.modes]] mode = "12bit" whitepoint = 3880 [[cameras.modes]] mode = "14bit" whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/z7_mk2.toml000064400000000000000000000007101046102023000165730ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z 7_2" clean_make = "Nikon" clean_model = "Z 7 2" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] [cameras.color_matrix] A = [1.4496, -0.8028, 0.0682, -0.465, 1.2681, 0.2185, -0.021, 0.0781, 0.8334] D65 = [1.3705, -0.6004, -0.14, -0.5464, 1.3568, 0.2062, -0.094, 0.1706, 0.7618] [[cameras.modes]] mode = "12bit" whitepoint = 3880 [[cameras.modes]] mode = "14bit" whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/z8.toml000064400000000000000000000006241046102023000160270ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z 8" clean_make = "Nikon" clean_model = "Z 8" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 8, 12, 8] [cameras.color_matrix] A = [1.3998, -0.8092, 0.0284, -0.4723, 1.2772, 0.2159, -0.0164, 0.0624, 0.8674] D65 = [1.1423, -0.4564, -0.1123, -0.4816, 1.2895, 0.2119, -0.021, 0.1061, 0.7282] [[cameras.modes]] mode = "14bit" whitepoint = 15892 rawler-0.7.1/data/cameras/nikon/z9.toml000064400000000000000000000007061046102023000160310ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z 9" clean_make = "Nikon" clean_model = "Z 9" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 8, 12, 8] [cameras.color_matrix] A = [1.4555, -0.8995, 0.0329, -0.3898, 1.1249, 0.3042, 0.0018, 0.0402, 0.8473] D65 = [1.3389, -0.6049, -0.1441, -0.4544, 1.2757, 0.1969, 0.0229, 0.0498, 0.739] [[cameras.modes]] mode = "12bit" whitepoint = 3880 [[cameras.modes]] mode = "14bit" whitepoint = 15520 rawler-0.7.1/data/cameras/nikon/z_f.toml000064400000000000000000000007301046102023000162420ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z f" clean_make = "NIKON CORPORATION" clean_model = "NIKON Z f" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 4, 8, 4] [cameras.color_matrix] A = [1.3904, -0.7947, 0.0654, -0.432, 1.2105, 0.2497, -0.0235, 0.083, 0.9243] D65 = [1.1607, -0.4491, -0.0977, -0.4522, 1.246, 0.2304, -0.0458, 0.1519, 0.7616] #[[cameras.modes]] #mode = "12bit" #whitepoint = 3880 [[cameras.modes]] mode = "14bit" whitepoint = 15892rawler-0.7.1/data/cameras/nikon/z_fc.toml000064400000000000000000000007061046102023000164100ustar 00000000000000make = "NIKON CORPORATION" model = "NIKON Z fc" clean_make = "Nikon" clean_model = "Z fc" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] [cameras.color_matrix] A = [1.3247, -0.7357, 0.0658, -0.4296, 1.227, 0.2269, -0.0237, 0.08, 0.7992] D65 = [1.164, -0.4829, -0.1079, -0.5107, 1.3006, 0.2325, -0.0972, 0.1711, 0.738] [[cameras.modes]] mode = "12bit" whitepoint = 3880 [[cameras.modes]] mode = "14bit" whitepoint = 15520 rawler-0.7.1/data/cameras/olympus/c5050z.toml000064400000000000000000000006331046102023000170060ustar 00000000000000make = "OLYMPUS OPTICAL CO.,LTD" model = "C5050Z" clean_make = "Olympus" clean_model = "C5050Z" blackpoint = 0 whitepoint = 4095 color_pattern = "BGGR" hints = ["interlaced"] active_area = [0, 0, 0, 0] crop_area = [8, 2, 8, 3] [cameras.color_matrix] A = [1.0898, -0.3993, -0.0545, -0.579, 1.3418, 0.2624, -0.1043, 0.1685, 0.6538] D65 = [1.0633, -0.3234, -0.1285, -0.746, 1.557, 0.1967, -0.1917, 0.251, 0.6299] rawler-0.7.1/data/cameras/olympus/c5060wz.toml000064400000000000000000000006341046102023000171770ustar 00000000000000make = "OLYMPUS CORPORATION" model = "C5060WZ" clean_make = "Olympus" clean_model = "C5060WZ" blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" hints = ["interlaced"] active_area = [0, 0, 0, 0] crop_area = [8, 2, 8, 3] [cameras.color_matrix] A = [1.1025, -0.4139, -0.0743, -0.6922, 1.4707, 0.2385, -0.063, 0.0755, 0.7949] D65 = [1.0445, -0.3361, -0.1307, -0.7662, 1.5691, 0.2058, -0.1135, 0.1175, 0.7602] rawler-0.7.1/data/cameras/olympus/c7070wz.toml000064400000000000000000000006361046102023000172040ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "C7070WZ" clean_make = "Olympus" clean_model = "C7070WZ" blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" hints = ["interlaced"] active_area = [0, 0, 0, 0] crop_area = [11, 2, 5, 3] [cameras.color_matrix] A = [1.1496, -0.4922, -0.0234, -0.5988, 1.3406, 0.2871, -0.0781, 0.113, 0.6516] D65 = [1.0252, -0.3531, -0.1095, -0.7114, 1.485, 0.2436, -0.1451, 0.1723, 0.6365] rawler-0.7.1/data/cameras/olympus/c8080.toml000064400000000000000000000006351046102023000166240ustar 00000000000000make = "OLYMPUS CORPORATION" model = "C8080WZ" clean_make = "Olympus" clean_model = "C8080WZ" #blackpoint = 0 whitepoint = 4095 color_pattern = "BGGR" hints = ["interlaced"] active_area = [0, 0, 0, 0] crop_area = [8, 2, 8, 3] [cameras.color_matrix] A = [1.0044, -0.4054, -0.0359, -0.6743, 1.3949, 0.3095, -0.0571, 0.0733, 0.7617] D65 = [0.8606, -0.2508, -0.1014, -0.8238, 1.5714, 0.2703, -0.0943, 0.0979, 0.776] rawler-0.7.1/data/cameras/olympus/e-1.toml000064400000000000000000000006001046102023000164340ustar 00000000000000make = "OLYMPUS CORPORATION" model = "E-1" clean_make = "Olympus" clean_model = "E-1" blackpoint = 65 whitepoint = 4095 color_pattern = "GRBG" active_area = [0, 0, 0, 0] crop_area = [32, 23, 32, 23] [cameras.color_matrix] A = [1.6228, -0.9341, 0.1289, -0.625, 1.487, 0.1403, -0.1358, 0.2842, 0.9053] D65 = [1.1847, -0.4767, -0.0945, -0.7027, 1.5878, 0.1089, -0.2699, 0.4123, 0.8312] rawler-0.7.1/data/cameras/olympus/e-10.toml000064400000000000000000000006031046102023000165170ustar 00000000000000make = "OLYMPUS OPTICAL CO.,LTD" model = "E-10" clean_make = "Olympus" clean_model = "E-10" blackpoint = 64 whitepoint = 3604 color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [8, 2, 8, 2] [cameras.color_matrix] A = [1.5278, -0.709, -0.0038, -0.6867, 1.5094, 0.1851, -0.1124, 0.1476, 0.7298] D65 = [1.297, -0.4703, -0.1433, -0.7466, 1.5843, 0.1644, -0.2191, 0.2451, 0.6668] rawler-0.7.1/data/cameras/olympus/e-20.toml000064400000000000000000000006151046102023000165230ustar 00000000000000make = "OLYMPUS OPTICAL CO.,LTD" model = "E-20,E-20N,E-20P" clean_make = "Olympus" clean_model = "E-20" blackpoint = 0 whitepoint = 4092 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [2, 2, 2, 2] [cameras.color_matrix] A = [1.6014, -0.7793, 0.0104, -0.6329, 1.4215, 0.2288, -0.1264, 0.1705, 0.7772] D65 = [1.3414, -0.495, -0.1517, -0.7166, 1.5293, 0.196, -0.2325, 0.2664, 0.7212] rawler-0.7.1/data/cameras/olympus/e-3.toml000064400000000000000000000006001046102023000164360ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-3" clean_make = "Olympus" clean_model = "E-3" #blackpoint = 0 whitepoint = 4015 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [54, 22, 18, 42] [cameras.color_matrix] A = [1.1004, -0.4441, -0.0232, -0.6299, 1.407, 0.2428, -0.087, 0.1459, 0.7422] D65 = [0.9487, -0.2875, -0.1115, -0.7533, 1.5606, 0.201, -0.1618, 0.21, 0.7389] rawler-0.7.1/data/cameras/olympus/e-30.toml000064400000000000000000000006071046102023000165250ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-30" clean_make = "Olympus" clean_model = "E-30" #blackpoint = 64 whitepoint = 4015 color_pattern = "BGGR" active_area = [0, 0, 4, 0] crop_area = [30, 26, 38, 34] [cameras.color_matrix] A = [0.8571, -0.2319, -0.0686, -0.6812, 1.456, 0.2434, -0.1131, 0.1799, 0.7831] D65 = [0.8144, -0.1861, -0.1111, -0.7763, 1.5894, 0.1929, -0.1865, 0.2542, 0.7607] rawler-0.7.1/data/cameras/olympus/e-300.toml000064400000000000000000000006041046102023000166020ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-300" clean_make = "Olympus" clean_model = "E-300" blackpoint = 63 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 20, 0] crop_area = [12, 28, 84, 28] [cameras.color_matrix] A = [1.0264, -0.4404, 0.0983, -0.468, 1.27, 0.2197, -0.145, 0.3152, 0.7115] D65 = [0.7828, -0.1761, -0.0348, -0.5788, 1.4071, 0.183, -0.2853, 0.4518, 0.6557] rawler-0.7.1/data/cameras/olympus/e-330.toml000064400000000000000000000006071046102023000166100ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-330" clean_make = "Olympus" clean_model = "E-330" blackpoint = 70 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 30, 0] crop_area = [52, 60, 92, 38] [cameras.color_matrix] A = [0.9692, -0.3364, -0.0423, -0.678, 1.4465, 0.2512, -0.1321, 0.2118, 0.8545] D65 = [0.8962, -0.2473, -0.1084, -0.798, 1.599, 0.2067, -0.2319, 0.3035, 0.8249] rawler-0.7.1/data/cameras/olympus/e-400.toml000064400000000000000000000006071046102023000166060ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-400" clean_make = "Olympus" clean_model = "E-400" blackpoint = 95 whitepoint = 4095 color_pattern = "GRBG" active_area = [0, 0, 0, 0] crop_area = [44, 50, 76, 54] [cameras.color_matrix] A = [0.7384, -0.2887, 0.0762, -0.6219, 1.3713, 0.2768, -0.1789, 0.2616, 0.8961] D65 = [0.6169, -0.1482, -0.0021, -0.7107, 1.476, 0.2536, -0.2904, 0.3581, 0.8568] rawler-0.7.1/data/cameras/olympus/e-410.toml000064400000000000000000000006101046102023000166010ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-410" clean_make = "Olympus" clean_model = "E-410" #blackpoint = 73 whitepoint = 3500 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [34, 38, 38, 26] [cameras.color_matrix] A = [1.009, -0.3864, -0.0358, -0.6375, 1.409, 0.2493, -0.1032, 0.1728, 0.7556] D65 = [0.8856, -0.2582, -0.1026, -0.7761, 1.5767, 0.2081, -0.2009, 0.2576, 0.7469] rawler-0.7.1/data/cameras/olympus/e-420.toml000064400000000000000000000006111046102023000166030ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-420" clean_make = "Olympus" clean_model = "E-420" #blackpoint = 39 whitepoint = 4015 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [40, 14, 32, 50] [cameras.color_matrix] A = [0.9858, -0.3499, -0.0522, -0.6448, 1.4182, 0.2467, -0.1001, 0.1624, 0.7418] D65 = [0.8745, -0.2425, -0.1095, -0.7594, 1.5613, 0.2073, -0.178, 0.2309, 0.7416] rawler-0.7.1/data/cameras/olympus/e-450.toml000064400000000000000000000006111046102023000166060ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-450" clean_make = "Olympus" clean_model = "E-450" #blackpoint = 69 whitepoint = 4015 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [54, 30, 18, 34] [cameras.color_matrix] A = [0.9858, -0.3499, -0.0522, -0.6448, 1.4182, 0.2467, -0.1001, 0.1624, 0.7418] D65 = [0.8745, -0.2425, -0.1095, -0.7594, 1.5613, 0.2073, -0.178, 0.2309, 0.7416] rawler-0.7.1/data/cameras/olympus/e-5.toml000064400000000000000000000006021046102023000164420ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-5" clean_make = "Olympus" clean_model = "E-5" #blackpoint = 64 whitepoint = 3604 color_pattern = "BGGR" active_area = [0, 0, 4, 0] crop_area = [42, 24, 26, 36] [cameras.color_matrix] A = [1.1449, -0.473, -0.0612, -0.3883, 1.1437, 0.2796, -0.0342, 0.1156, 0.805] D65 = [1.12, -0.3783, -0.1325, -0.4576, 1.2593, 0.2206, -0.0695, 0.1742, 0.7504] rawler-0.7.1/data/cameras/olympus/e-500.toml000064400000000000000000000006111046102023000166020ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-500" clean_make = "Olympus" clean_model = "E-500" blackpoint = 63 whitepoint = 3967 color_pattern = "RGGB" active_area = [0, 0, 20, 0] crop_area = [18, 44, 78, 12] [cameras.color_matrix] A = [1.0858, -0.4915, 0.1151, -0.4315, 1.2355, 0.2188, -0.1239, 0.2963, 0.7051] D65 = [0.8136, -0.1968, -0.0299, -0.5481, 1.3742, 0.1871, -0.2556, 0.4205, 0.6631] rawler-0.7.1/data/cameras/olympus/e-510.toml000064400000000000000000000006031046102023000166040ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-510" clean_make = "Olympus" clean_model = "E-510" #blackpoint = 73 whitepoint = 3500 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [34, 38, 38, 26] [cameras.color_matrix] A = [0.9871, -0.3613, -0.0344, -0.6469, 1.413, 0.2555, -0.1, 0.1613, 0.781] D65 = [0.8785, -0.2528, -0.1033, -0.7639, 1.5624, 0.2112, -0.1782, 0.23, 0.7817] rawler-0.7.1/data/cameras/olympus/e-520.toml000064400000000000000000000006101046102023000166030ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-520" clean_make = "Olympus" clean_model = "E-520" #blackpoint = 69 whitepoint = 4015 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 46, 60, 18] [cameras.color_matrix] A = [0.9534, -0.349, -0.0417, -0.6423, 1.4193, 0.2424, -0.0964, 0.1588, 0.7287] D65 = [0.8343, -0.2322, -0.102, -0.7596, 1.5635, 0.2048, -0.1748, 0.2269, 0.7287] rawler-0.7.1/data/cameras/olympus/e-600.toml000064400000000000000000000006061046102023000166070ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-600" clean_make = "Olympus" clean_model = "E-600" #blackpoint = 0 whitepoint = 4015 color_pattern = "BGGR" active_area = [0, 0, 4, 0] crop_area = [30, 30, 38, 30] [cameras.color_matrix] A = [0.8857, -0.28, -0.0553, -0.6587, 1.4222, 0.2581, -0.1089, 0.1743, 0.817] D65 = [0.8453, -0.2198, -0.1092, -0.7609, 1.5681, 0.2008, -0.1725, 0.2337, 0.7824] rawler-0.7.1/data/cameras/olympus/e-620.toml000064400000000000000000000006071046102023000166120ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-620" clean_make = "Olympus" clean_model = "E-620" #blackpoint = 65 whitepoint = 4015 color_pattern = "BGGR" active_area = [0, 0, 4, 0] crop_area = [30, 28, 38, 32] [cameras.color_matrix] A = [0.8857, -0.28, -0.0553, -0.6587, 1.4222, 0.2581, -0.1089, 0.1743, 0.817] D65 = [0.8453, -0.2198, -0.1092, -0.7609, 1.5681, 0.2008, -0.1725, 0.2337, 0.7824] rawler-0.7.1/data/cameras/olympus/e-m1.toml000064400000000000000000000006041046102023000166150ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-M1" clean_make = "Olympus" clean_model = "E-M1" #blackpoint = 255 whitepoint = 4000 color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [1.1528, -0.5742, 0.0118, -0.2453, 1.0205, 0.2619, -0.0751, 0.189, 0.6539] D65 = [0.7687, -0.1984, -0.0606, -0.4327, 1.1928, 0.2721, -0.1381, 0.2339, 0.6452] rawler-0.7.1/data/cameras/olympus/e-m10.toml000064400000000000000000000006021046102023000166730ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-M10" clean_make = "Olympus" clean_model = "E-M10" #blackpoint = 252 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [0.9033, -0.3597, 0.026, -0.2351, 0.97, 0.3111, -0.0181, 0.0807, 0.5838] D65 = [0.838, -0.263, -0.0639, -0.2887, 1.0725, 0.2496, -0.0627, 0.1427, 0.5438] rawler-0.7.1/data/cameras/olympus/e-m10mk2.toml000064400000000000000000000006141046102023000173100ustar 00000000000000make = "OLYMPUS CORPORATION" model = "E-M10MarkII" clean_make = "Olympus" clean_model = "E-M10 Mark II" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [0.9033, -0.3597, 0.026, -0.2351, 0.97, 0.3111, -0.0181, 0.0807, 0.5838] D65 = [0.838, -0.263, -0.0639, -0.2887, 1.0725, 0.2496, -0.0627, 0.1427, 0.5438] rawler-0.7.1/data/cameras/olympus/e-m10mk3.toml000064400000000000000000000006361046102023000173150ustar 00000000000000make = "OLYMPUS CORPORATION" model = "E-M10 Mark III" clean_make = "OLYMPUS CORPORATION" clean_model = "E-M10 Mark III" #blackpoint = 254 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [0.9033, -0.3597, 0.026, -0.2351, 0.97, 0.3111, -0.0181, 0.0807, 0.5838] D65 = [0.838, -0.263, -0.0639, -0.2887, 1.0725, 0.2496, -0.0627, 0.1427, 0.5438] rawler-0.7.1/data/cameras/olympus/e-m10mk3s.toml000064400000000000000000000006351046102023000174770ustar 00000000000000make = "OLYMPUS CORPORATION" model = "E-M10MarkIIIS" clean_make = "OLYMPUS CORPORATION" clean_model = "E-M10 Mark III S" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [0.9033, -0.3597, 0.026, -0.2351, 0.97, 0.3111, -0.0181, 0.0807, 0.5838] D65 = [0.838, -0.263, -0.0639, -0.2887, 1.0725, 0.2496, -0.0627, 0.1427, 0.5438] rawler-0.7.1/data/cameras/olympus/e-m10mk4.toml000064400000000000000000000006341046102023000173140ustar 00000000000000make = "OLYMPUS CORPORATION" model = "E-M10MarkIV" clean_make = "OLYMPUS CORPORATION" clean_model = "E-M10 Mark IV" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] [cameras.color_matrix] A = [1.086, -0.4649, -0.0085, -0.3404, 1.1881, 0.1698, -0.0368, 0.1072, 0.6281] D65 = [0.9476, -0.3182, -0.0765, -0.2613, 1.0958, 0.1893, -0.0449, 0.1315, 0.5268] rawler-0.7.1/data/cameras/olympus/e-m1mk2.toml000064400000000000000000000007271046102023000172350ustar 00000000000000make = "OLYMPUS CORPORATION" model = "E-M1MarkII" clean_make = "OLYMPUS CORPORATION" clean_model = "E-M1MarkII" #blackpoint = 254 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] highres_width = 10000 [cameras.color_matrix] A = [1.0881, -0.4662, -0.0158, -0.3528, 1.2064, 0.1622, -0.0322, 0.0955, 0.6189] D65 = [0.9383, -0.317, -0.0763, -0.2457, 1.0702, 0.202, -0.0384, 0.1236, 0.5552] [[cameras.modes]] mode = "highres" active_area = [0, 0, 10, 0] rawler-0.7.1/data/cameras/olympus/e-m1mk3.toml000064400000000000000000000007301046102023000172300ustar 00000000000000make = "OLYMPUS CORPORATION" model = "E-M1MarkIII" clean_make = "OLYMPUS CORPORATION" clean_model = "E-M1MarkIII" #blackpoint = 254 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] highres_width = 10000 [cameras.color_matrix] A = [1.3782, -0.7726, 0.0645, -0.3366, 1.2336, 0.1103, -0.0082, 0.0624, 0.5955] D65 = [1.1896, -0.511, -0.1076, -0.3181, 1.1378, 0.2048, -0.0519, 0.1224, 0.5166] [[cameras.modes]] mode = "highres" active_area = [0, 0, 10, 0] rawler-0.7.1/data/cameras/olympus/e-m1x.toml000064400000000000000000000006051046102023000170060ustar 00000000000000make = "OLYMPUS CORPORATION" model = "E-M1X" clean_make = "Olympus" clean_model = "E-M1X" #blackpoint = 0 whitepoint = 4000 color_pattern = "BGGR" active_area = [0, 0, 0, 0] crop_area = [12, 12, 44, 12] [cameras.color_matrix] A = [1.3782, -0.7726, 0.0645, -0.3366, 1.2336, 0.1103, -0.0082, 0.0624, 0.5955] D65 = [1.1896, -0.511, -0.1076, -0.3181, 1.1378, 0.2048, -0.0519, 0.1224, 0.5166] rawler-0.7.1/data/cameras/olympus/e-m5.toml000064400000000000000000000005761046102023000166310ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-M5" clean_make = "Olympus" clean_model = "E-M5" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [0.9033, -0.3597, 0.026, -0.2351, 0.97, 0.3111, -0.0181, 0.0807, 0.5838] D65 = [0.838, -0.263, -0.0639, -0.2887, 1.0725, 0.2496, -0.0627, 0.1427, 0.5438] rawler-0.7.1/data/cameras/olympus/e-m5mk2.toml000064400000000000000000000007071046102023000172370ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-M5MarkII" clean_make = "Olympus" clean_model = "E-M5 Mark II" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] highres_width = 9280 [cameras.color_matrix] A = [1.0666, -0.4647, 0.0038, -0.3405, 1.1699, 0.192, -0.0415, 0.1123, 0.6411] D65 = [0.9422, -0.3258, -0.0711, -0.2655, 1.0898, 0.2015, -0.0512, 0.1354, 0.5512] [[cameras.modes]] mode = "highres" color_pattern = "GRBG" rawler-0.7.1/data/cameras/olympus/e-m5mk3.toml000064400000000000000000000007071046102023000172400ustar 00000000000000make = "OLYMPUS CORPORATION" model = "E-M5MarkIII" clean_make = "Olympus" clean_model = "E-M5 Mark III" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] highres_width = 9280 [cameras.color_matrix] A = [1.3782, -0.7726, 0.0645, -0.3366, 1.2336, 0.1103, -0.0082, 0.0624, 0.5955] D65 = [1.1896, -0.511, -0.1076, -0.3181, 1.1378, 0.2048, -0.0519, 0.1224, 0.5166] [[cameras.modes]] mode = "highres" color_pattern = "RGGB" rawler-0.7.1/data/cameras/olympus/e-p1.toml000064400000000000000000000006061046102023000166220ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-P1" clean_make = "Olympus" clean_model = "E-P1" #blackpoint = 64 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 4, 0] crop_area = [28, 30, 40, 30] [cameras.color_matrix] A = [0.8873, -0.2728, -0.0574, -0.6505, 1.4211, 0.2498, -0.1065, 0.1726, 0.8029] D65 = [0.8343, -0.205, -0.1021, -0.7715, 1.5705, 0.2103, -0.1831, 0.238, 0.8235] rawler-0.7.1/data/cameras/olympus/e-p2.toml000064400000000000000000000006101046102023000166160ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-P2" clean_make = "Olympus" clean_model = "E-P2" #blackpoint = 64 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 4, 0] crop_area = [30, 198, 38, 198] [cameras.color_matrix] A = [0.8873, -0.2728, -0.0574, -0.6505, 1.4211, 0.2498, -0.1065, 0.1726, 0.8029] D65 = [0.8343, -0.205, -0.1021, -0.7715, 1.5705, 0.2103, -0.1831, 0.238, 0.8235] rawler-0.7.1/data/cameras/olympus/e-p3.toml000064400000000000000000000006041046102023000166220ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-P3" clean_make = "Olympus" clean_model = "E-P3" #blackpoint = 64 whitepoint = 3843 color_pattern = "RGGB" active_area = [0, 0, 24, 0] crop_area = [8, 8, 40, 8] [cameras.color_matrix] A = [0.7726, -0.2728, 0.0476, -0.2861, 0.9864, 0.3509, -0.0782, 0.195, 0.6453] D65 = [0.7575, -0.2159, -0.0571, -0.3722, 1.1341, 0.2725, -0.1434, 0.2819, 0.6271] rawler-0.7.1/data/cameras/olympus/e-p5.toml000064400000000000000000000006001046102023000166200ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-P5" clean_make = "Olympus" clean_model = "E-P5" #blackpoint = 255 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [0.9033, -0.3597, 0.026, -0.2351, 0.97, 0.3111, -0.0181, 0.0807, 0.5838] D65 = [0.838, -0.263, -0.0639, -0.2887, 1.0725, 0.2496, -0.0627, 0.1427, 0.5438] rawler-0.7.1/data/cameras/olympus/e-pl1.toml000064400000000000000000000006111046102023000167720ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-PL1" clean_make = "Olympus" clean_model = "E-PL1" #blackpoint = 64 whitepoint = 3604 color_pattern = "RGGB" active_area = [0, 0, 4, 0] crop_area = [30, 30, 38, 30] [cameras.color_matrix] A = [1.2643, -0.6149, -0.0291, -0.3331, 1.0834, 0.2883, -0.0234, 0.1074, 0.787] D65 = [1.1408, -0.4289, -0.1215, -0.4286, 1.2385, 0.2118, -0.0387, 0.1467, 0.7787] rawler-0.7.1/data/cameras/olympus/e-pl10.toml000064400000000000000000000006161046102023000170570ustar 00000000000000make = "OLYMPUS CORPORATION" model = "E-PL10" clean_make = "OLYMPUS CORPORATION" clean_model = "E-PL10" #blackpoint = 254 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [1.0496, -0.4598, 0.0061, -0.321, 1.1502, 0.1931, -0.036, 0.1006, 0.6394] D65 = [0.9197, -0.319, -0.0659, -0.2606, 1.083, 0.2039, -0.0458, 0.125, 0.5458] rawler-0.7.1/data/cameras/olympus/e-pl2.toml000064400000000000000000000006051046102023000167760ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-PL2" clean_make = "Olympus" clean_model = "E-PL2" #blackpoint = 0 whitepoint = 3604 color_pattern = "RGGB" active_area = [0, 0, 4, 0] crop_area = [30, 30, 38, 30] [cameras.color_matrix] A = [1.5432, -0.659, -0.1015, -0.3512, 1.1506, 0.2224, -0.028, 0.1124, 0.7494] D65 = [1.503, -0.5552, -0.1806, -0.3987, 1.2387, 0.1767, -0.0592, 0.167, 0.7023] rawler-0.7.1/data/cameras/olympus/e-pl3.toml000064400000000000000000000006061046102023000170000ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-PL3" clean_make = "Olympus" clean_model = "E-PL3" #blackpoint = 64 whitepoint = 3700 color_pattern = "RGGB" active_area = [0, 0, 24, 0] crop_area = [8, 8, 40, 8] [cameras.color_matrix] A = [0.7726, -0.2728, 0.0476, -0.2861, 0.9864, 0.3509, -0.0782, 0.195, 0.6453] D65 = [0.7575, -0.2159, -0.0571, -0.3722, 1.1341, 0.2725, -0.1434, 0.2819, 0.6271] rawler-0.7.1/data/cameras/olympus/e-pl5.toml000064400000000000000000000006001046102023000167740ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-PL5" clean_make = "Olympus" clean_model = "E-PL5" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [0.9033, -0.3597, 0.026, -0.2351, 0.97, 0.3111, -0.0181, 0.0807, 0.5838] D65 = [0.838, -0.263, -0.0639, -0.2887, 1.0725, 0.2496, -0.0627, 0.1427, 0.5438] rawler-0.7.1/data/cameras/olympus/e-pl6.toml000064400000000000000000000006001046102023000167750ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-PL6" clean_make = "Olympus" clean_model = "E-PL6" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [0.9033, -0.3597, 0.026, -0.2351, 0.97, 0.3111, -0.0181, 0.0807, 0.5838] D65 = [0.838, -0.263, -0.0639, -0.2887, 1.0725, 0.2496, -0.0627, 0.1427, 0.5438] rawler-0.7.1/data/cameras/olympus/e-pl7.toml000064400000000000000000000006001046102023000167760ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-PL7" clean_make = "Olympus" clean_model = "E-PL7" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [1.0496, -0.4598, 0.0061, -0.321, 1.1502, 0.1931, -0.036, 0.1006, 0.6394] D65 = [0.9197, -0.319, -0.0659, -0.2606, 1.083, 0.2039, -0.0458, 0.125, 0.5458] rawler-0.7.1/data/cameras/olympus/e-pl8.toml000064400000000000000000000006121046102023000170020ustar 00000000000000make = "OLYMPUS CORPORATION" model = "E-PL8" clean_make = "OLYMPUS CORPORATION" clean_model = "E-PL8" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [1.0496, -0.4598, 0.0061, -0.321, 1.1502, 0.1931, -0.036, 0.1006, 0.6394] D65 = [0.9197, -0.319, -0.0659, -0.2606, 1.083, 0.2039, -0.0458, 0.125, 0.5458] rawler-0.7.1/data/cameras/olympus/e-pl9.toml000064400000000000000000000006121046102023000170030ustar 00000000000000make = "OLYMPUS CORPORATION" model = "E-PL9" clean_make = "OLYMPUS CORPORATION" clean_model = "E-PL9" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [0.9033, -0.3597, 0.026, -0.2351, 0.97, 0.3111, -0.0181, 0.0807, 0.5838] D65 = [0.838, -0.263, -0.0639, -0.2887, 1.0725, 0.2496, -0.0627, 0.1427, 0.5438] rawler-0.7.1/data/cameras/olympus/e-pm1.toml000064400000000000000000000006051046102023000167760ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-PM1" clean_make = "Olympus" clean_model = "E-PM1" #blackpoint = 0 whitepoint = 4011 color_pattern = "RGGB" active_area = [0, 0, 24, 0] crop_area = [8, 8, 40, 8] [cameras.color_matrix] A = [0.7726, -0.2728, 0.0476, -0.2861, 0.9864, 0.3509, -0.0782, 0.195, 0.6453] D65 = [0.7575, -0.2159, -0.0571, -0.3722, 1.1341, 0.2725, -0.1434, 0.2819, 0.6271] rawler-0.7.1/data/cameras/olympus/e-pm2.toml000064400000000000000000000006001046102023000167720ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "E-PM2" clean_make = "Olympus" clean_model = "E-PM2" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [0.9033, -0.3597, 0.026, -0.2351, 0.97, 0.3111, -0.0181, 0.0807, 0.5838] D65 = [0.838, -0.263, -0.0639, -0.2887, 1.0725, 0.2496, -0.0627, 0.1427, 0.5438] rawler-0.7.1/data/cameras/olympus/penf.toml000064400000000000000000000006731046102023000170140ustar 00000000000000make = "OLYMPUS CORPORATION" model = "PEN-F" clean_make = "Olympus" clean_model = "PEN-F" #blackpoint = 242 whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] highres_width = 5201 [cameras.color_matrix] A = [1.086, -0.4649, -0.0085, -0.3404, 1.1881, 0.1698, -0.0368, 0.1072, 0.6281] D65 = [0.9476, -0.3182, -0.0765, -0.2613, 1.0958, 0.1893, -0.0449, 0.1315, 0.5268] [[cameras.modes]] mode = "highres" color_pattern = "GRBG" rawler-0.7.1/data/cameras/olympus/sh-2.toml000064400000000000000000000006201046102023000166250ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "SH-2" clean_make = "OLYMPUS IMAGING CORP." clean_model = "SH-2" #blackpoint = 0 whitepoint = 4000 color_pattern = "GRBG" active_area = [0, 0, 0, 0] crop_area = [7, 6, 9, 8] [cameras.color_matrix] A = [1.0759, -0.4534, -0.0363, -0.2229, 1.0227, 0.2329, -0.0039, 0.1035, 0.6008] D65 = [1.0156, -0.3425, -0.1077, -0.2611, 1.1177, 0.1624, -0.0385, 0.1592, 0.508] rawler-0.7.1/data/cameras/olympus/sp320.toml000064400000000000000000000004331046102023000167250ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "SP320" clean_make = "Olympus" clean_model = "SP320" #blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] [cameras.color_matrix] D65 = [1.1766, -0.4445, -0.1067, -0.6901, 1.4421, 0.2707, -0.1029, 0.1217, 0.7572] rawler-0.7.1/data/cameras/olympus/sp350.toml000064400000000000000000000005131046102023000167270ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "SP350" clean_make = "Olympus" clean_model = "SP350" #blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" hints = ["interlaced"] active_area = [0, 0, 0, 0] crop_area = [8, 2, 8, 3] [cameras.color_matrix] D65 = [1.2078, -0.4836, -0.1069, -0.6671, 1.4306, 0.2578, -0.0786, 0.0939, 0.7418] rawler-0.7.1/data/cameras/olympus/sp500uz.toml000064400000000000000000000005161046102023000173060ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "SP500UZ" clean_make = "Olympus" clean_model = "SP500UZ" #blackpoint = 0 whitepoint = 4095 color_pattern = "GBRG" hints = ["interlaced"] active_area = [0, 0, 0, 0] crop_area = [8, 2, 8, 3] [cameras.color_matrix] D65 = [0.9493, -0.3415, -0.0666, -0.5211, 1.2334, 0.326, -0.1548, 0.2262, 0.6482] rawler-0.7.1/data/cameras/olympus/sp510uz.toml000064400000000000000000000005331046102023000173060ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "SP510UZ" clean_make = "OLYMPUS IMAGING CORP." clean_model = "SP510UZ" #blackpoint = 0 whitepoint = 4095 color_pattern = "GBRG" hints = ["interlaced"] active_area = [0, 0, 0, 0] crop_area = [8, 2, 8, 3] [cameras.color_matrix] D65 = [1.0593, -0.3607, -0.101, -0.5881, 1.3127, 0.3084, -0.12, 0.1805, 0.6721] rawler-0.7.1/data/cameras/olympus/sp565uz.toml000064400000000000000000000005331046102023000173200ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "SP565UZ" clean_make = "OLYMPUS IMAGING CORP." clean_model = "SP565UZ" #blackpoint = 0 whitepoint = 4095 color_pattern = "BGGR" hints = ["interlaced"] active_area = [0, 0, 0, 0] crop_area = [10, 3, 6, 2] [cameras.color_matrix] D65 = [1.0593, -0.3607, -0.101, -0.5881, 1.3127, 0.3084, -0.12, 0.1805, 0.6721] rawler-0.7.1/data/cameras/olympus/sp570uz.toml000064400000000000000000000006211046102023000173120ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "SP570UZ" clean_make = "OLYMPUS IMAGING CORP." clean_model = "SP570UZ" whitepoint = 4095 color_pattern = "BGGR" hints = ["interlaced"] active_area = [0, 0, 0, 0] crop_area = [10, 3, 6, 2] [cameras.color_matrix] A = [1.3836, -0.6519, 0.0167, -0.3332, 1.0426, 0.3378, -0.0195, 0.1092, 0.6062] D65 = [350.0, -63.0, -30.0, -75.0, 396.0, -64.0, 49.0, -162.0, 369.0] rawler-0.7.1/data/cameras/olympus/stylus1-1.toml000064400000000000000000000006131046102023000176400ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "STYLUS1,1s" clean_make = "Olympus" clean_model = "Stylus1" #blackpoint = 200 whitepoint = 3900 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [0.8088, -0.2367, 0.0056, -0.2972, 1.0966, 0.2302, -0.0617, 0.1704, 0.5228] D65 = [0.836, -0.242, -0.088, -0.3928, 1.2353, 0.1739, -0.1381, 0.2416, 0.5173] rawler-0.7.1/data/cameras/olympus/stylus1.toml000064400000000000000000000004371046102023000175060ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "STYLUS1" clean_make = "Olympus" clean_model = "Stylus1" #blackpoint = 200 whitepoint = 3900 color_pattern = "RGGB" active_area = [0, 0, 14, 0] [cameras.color_matrix] D65 = [0.836, -0.242, -0.088, -0.3928, 1.2353, 0.1739, -0.1381, 0.2416, 0.5173] rawler-0.7.1/data/cameras/olympus/tg-4.toml000064400000000000000000000006001046102023000166250ustar 00000000000000make = "OLYMPUS CORPORATION" model = "TG-4" clean_make = "Olympus" clean_model = "TG-4" #blackpoint = 255 whitepoint = 4000 color_pattern = "GRBG" active_area = [0, 0, 0, 0] crop_area = [8, 8, 24, 8] [cameras.color_matrix] A = [1.2823, -0.6212, 0.0038, -0.179, 0.9648, 0.2519, 0.0129, 0.0749, 0.6077] D65 = [1.1426, -0.4159, -0.1126, -0.2066, 1.0678, 0.1593, -0.012, 0.1327, 0.4998] rawler-0.7.1/data/cameras/olympus/tg-5.toml000064400000000000000000000006161046102023000166350ustar 00000000000000make = "OLYMPUS CORPORATION" model = "TG-5" clean_make = "OLYMPUS CORPORATION" clean_model = "TG-5" #blackpoint = 0 whitepoint = 4000 color_pattern = "GRBG" active_area = [0, 0, 6, 0] crop_area = [8, 8, 32, 8] [cameras.color_matrix] A = [1.1639, -0.4924, -0.0113, -0.2585, 1.0857, 0.1983, -0.0157, 0.1043, 0.6335] D65 = [1.0899, -0.3833, -0.1082, -0.2112, 1.0736, 0.1575, -0.0267, 0.1452, 0.5269] rawler-0.7.1/data/cameras/olympus/tg-6.toml000064400000000000000000000006201046102023000166310ustar 00000000000000make = "OLYMPUS CORPORATION" model = "TG-6" clean_make = "OLYMPUS CORPORATION" clean_model = "TG-6" #blackpoint = 256 whitepoint = 4000 color_pattern = "GRBG" active_area = [0, 0, 6, 0] crop_area = [8, 8, 32, 8] [cameras.color_matrix] A = [1.1639, -0.4924, -0.0113, -0.2585, 1.0857, 0.1983, -0.0157, 0.1043, 0.6335] D65 = [1.0899, -0.3833, -0.1082, -0.2112, 1.0736, 0.1575, -0.0267, 0.1452, 0.5269] rawler-0.7.1/data/cameras/olympus/xz-1.toml000064400000000000000000000006041046102023000166550ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "XZ-1" clean_make = "Olympus" clean_model = "XZ-1" #blackpoint = 0 whitepoint = 3900 color_pattern = "RGGB" active_area = [0, 0, 0, 1] crop_area = [8, 8, 24, 16] [cameras.color_matrix] A = [1.1283, -0.5046, -0.0307, -0.0843, 0.8485, 0.2822, 0.0272, 0.0824, 0.5672] D65 = [1.0901, -0.4095, -0.1074, -0.1141, 0.9208, 0.2293, -0.0062, 0.1417, 0.5158] rawler-0.7.1/data/cameras/olympus/xz-10.toml000064400000000000000000000006031046102023000167340ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "XZ-10" clean_make = "Olympus" clean_model = "XZ-10" #blackpoint = 200 whitepoint = 3900 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 7, 8, 7] [cameras.color_matrix] A = [1.0013, -0.4366, 0.0358, -0.2138, 0.953, 0.3068, -0.0064, 0.0872, 0.5399] D65 = [0.9777, -0.3483, -0.0925, -0.2886, 1.1297, 0.18, -0.0602, 0.1663, 0.5134] rawler-0.7.1/data/cameras/olympus/xz-2.toml000064400000000000000000000006021046102023000166540ustar 00000000000000make = "OLYMPUS IMAGING CORP." model = "XZ-2" clean_make = "Olympus" clean_model = "XZ-2" #blackpoint = 200 whitepoint = 3900 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 10, 8, 0] [cameras.color_matrix] A = [1.0013, -0.4366, 0.0358, -0.2138, 0.953, 0.3068, -0.0064, 0.0872, 0.5399] D65 = [0.9777, -0.3483, -0.0925, -0.2886, 1.1297, 0.18, -0.0602, 0.1663, 0.5134] rawler-0.7.1/data/cameras/omdigital/om_1.toml000064400000000000000000000007561046102023000171620ustar 00000000000000make = "OM Digital Solutions" model = "OM-1" clean_make = "OM Digital Solutions" clean_model = "OM-1" whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 24, 12] highres_width = 8180 [cameras.color_matrix] A = [1.1345, -0.6856, 0.0888, -0.2931, 1.0978, 0.224, 0.0075, 0.0408, 0.7003] D65 = [0.9488, -0.3984, -0.0714, -0.2887, 1.0945, 0.2229, -0.0137, 0.096, 0.5786] [[cameras.modes]] mode = "highres" active_area = [0, 0, 10, 0] crop_area = [0, 0, 10, 0] rawler-0.7.1/data/cameras/omdigital/om_1mk2.toml000064400000000000000000000007751046102023000175750ustar 00000000000000make = "OM Digital Solutions" model = "OM-1MarkII" clean_make = "OM Digital Solutions" clean_model = "OM-1 Mark II" whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 24, 12] highres_width = 8180 [cameras.color_matrix] A = [1.0602, -0.5977, 0.0574, -0.3109, 1.1296, 0.2063, 0.0002, 0.0521, 0.6609] D65 = [0.909, -0.3591, -0.0756, -0.3252, 1.1396, 0.2109, -0.0318, 0.1059, 0.5606] [[cameras.modes]] mode = "highres" active_area = [0, 0, 10, 0] crop_area = [0, 0, 10, 0] rawler-0.7.1/data/cameras/omdigital/om_3.toml000064400000000000000000000007571046102023000171650ustar 00000000000000make = "OM Digital Solutions" model = "OM-3" clean_make = "OM Digital Solutions" clean_model = "OM-3" whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 24, 12] highres_width = 8180 [cameras.color_matrix] A = [1.0602, -0.5977, 0.0574, -0.3109, 1.1296, 0.2063, 0.0002, 0.0521, 0.6609] D65 = [0.909, -0.3591, -0.0756, -0.3252, 1.1396, 0.2109, -0.0318, 0.1059, 0.5606] [[cameras.modes]] mode = "highres" active_area = [0, 0, 10, 0] crop_area = [0, 0, 10, 0] rawler-0.7.1/data/cameras/omdigital/om_5.toml000064400000000000000000000006711046102023000171620ustar 00000000000000make = "OM Digital Solutions" model = "OM-5" clean_make = "OM Digital Solutions" clean_model = "OM-5" whitepoint = 4000 color_pattern = "RGGB" active_area = [0, 0, 0, 0] highres_width = 10400 [cameras.color_matrix] A = [1.3782, -0.7726, 0.0645, -0.3366, 1.2336, 0.1103, -0.0082, 0.0624, 0.5955] D65 = [1.1896, -0.511, -0.1076, -0.3181, 1.1378, 0.2048, -0.0519, 0.1224, 0.5166] [[cameras.modes]] mode = "highres" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/omdigital/tg-7.toml000064400000000000000000000006001046102023000170710ustar 00000000000000make = "OM Digital Solutions" model = "TG-7" clean_make = "OM Digital Solutions" clean_model = "TG-7" whitepoint = 4000 color_pattern = "GRBG" active_area = [0, 0, 6, 0] crop_area = [8, 8, 32, 8] [cameras.color_matrix] A = [1.1639, -0.4924, -0.0113, -0.2585, 1.0857, 0.1983, -0.0157, 0.1043, 0.6335] D65 = [1.0899, -0.3833, -0.1082, -0.2112, 1.0736, 0.1575, -0.0267, 0.1452, 0.5269] rawler-0.7.1/data/cameras/panasonic/cm1.toml000064400000000000000000000010731046102023000170020ustar 00000000000000make = "Panasonic" model = "DMC-CM1" clean_make = "Panasonic" clean_model = "DMC-CM1" #blackpoint = 142 whitepoint = 4095 color_pattern = "RGGB" [cameras.color_matrix] A = [0.9347, -0.4045, -0.0074, -0.3563, 1.1512, 0.2331, -0.0395, 0.1153, 0.5667] D65 = [0.877, -0.3194, -0.082, -0.2871, 1.1281, 0.1803, -0.0513, 0.1552, 0.4434] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 160, 0] rawler-0.7.1/data/cameras/panasonic/fx150.toml000064400000000000000000000006371046102023000171720ustar 00000000000000make = "Panasonic" model = "DMC-FX150" clean_make = "Panasonic" clean_model = "DMC-FX150" whitepoint = 3986 color_pattern = "BGGR" [cameras.color_matrix] A = [1.0669, -0.4715, 0.0083, -0.4339, 1.1185, 0.3634, -0.0621, 0.1527, 0.5906] D65 = [0.9082, -0.2907, -0.0925, -0.6119, 1.3377, 0.3058, -0.1797, 0.2641, 0.5609] [[cameras.modes]] mode = "4:3" [[cameras.modes]] mode = "3:2" [[cameras.modes]] mode = "16:9" rawler-0.7.1/data/cameras/panasonic/fz100.toml000064400000000000000000000011021046102023000171530ustar 00000000000000make = "Panasonic" model = "DMC-FZ100" clean_make = "Panasonic" clean_model = "DMC-FZ100" #blackpoint = 142 whitepoint = 3986 color_pattern = "GBRG" [cameras.color_matrix] A = [1.8481, -0.9335, -0.0326, -0.1155, 0.8936, 0.2639, 0.1226, 0.0924, 0.624] D65 = [1.6197, -0.6146, -0.1761, -0.2393, 1.0765, 0.1869, 0.0366, 0.2238, 0.5248] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 16, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/fz1000.toml000064400000000000000000000011011046102023000172320ustar 00000000000000make = "Panasonic" model = "DMC-FZ1000" clean_make = "Panasonic" clean_model = "DMC-FZ1000" #blackpoint = 143 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8393, -0.3595, -0.0084, -0.396, 1.1894, 0.2333, -0.0445, 0.1208, 0.6062] D65 = [0.783, -0.2696, -0.0763, -0.3325, 1.1667, 0.1866, -0.0641, 0.1712, 0.4824] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 160, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/panasonic/fz10002.toml000064400000000000000000000011731046102023000173250ustar 00000000000000make = "Panasonic" model = "DMC-FZ10002" clean_make = "Panasonic" clean_model = "DMC-FZ1000 II" #blackpoint = 0 whitepoint = 4095 color_pattern = "GBRG" model_aliases = [ ["DC-FZ10002", "DC-FZ10002"], ] [cameras.color_matrix] A = [1.0745, -0.6036, 0.0459, -0.2974, 1.1274, 0.1932, -0.0078, 0.0806, 0.5819] D65 = [0.9803, -0.4185, -0.0992, -0.4066, 1.2578, 0.1628, -0.0838, 0.1824, 0.5288] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 160, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/panasonic/fz150.toml000064400000000000000000000011011046102023000171570ustar 00000000000000make = "Panasonic" model = "DMC-FZ150" clean_make = "Panasonic" clean_model = "DMC-FZ150" #blackpoint = 142 whitepoint = 3956 color_pattern = "GBRG" [cameras.color_matrix] A = [1.346, -0.6952, 0.0669, -0.1081, 0.8584, 0.2979, 0.046, 0.0543, 0.4924] D65 = [1.1904, -0.4541, -0.1189, -0.2355, 1.0899, 0.1662, -0.0296, 0.1586, 0.4289] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 16, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/fz18.toml000064400000000000000000000010011046102023000171010ustar 00000000000000make = "Panasonic" model = "DMC-FZ18" clean_make = "Panasonic" clean_model = "DMC-FZ18" #blackpoint = 0 whitepoint = 3986 color_pattern = "BGGR" [cameras.color_matrix] A = [1.1813, -0.5165, 0.0259, -0.4292, 1.1413, 0.3304, -0.0317, 0.1261, 0.5773] D65 = [0.9932, -0.3059, -0.0936, -0.5809, 1.333, 0.2752, -0.1267, 0.2155, 0.5575] [[cameras.modes]] mode = "4:3" active_area = [10, 0, 30, 1] [[cameras.modes]] mode = "3:2" active_area = [9, 0, 31, 0] [[cameras.modes]] mode = "16:9" active_area = [9, 0, 31, 0] rawler-0.7.1/data/cameras/panasonic/fz200.toml000064400000000000000000000010761046102023000171660ustar 00000000000000make = "Panasonic" model = "DMC-FZ200" clean_make = "Panasonic" clean_model = "DMC-FZ200" #blackpoint = 142 whitepoint = 3971 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8452, -0.35, 0.0533, -0.2458, 0.9488, 0.3493, -0.016, 0.0993, 0.549] D65 = [0.8112, -0.2563, -0.074, -0.373, 1.1784, 0.2197, -0.0941, 0.2075, 0.4933] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 16, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 128, 4] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/fz2000.toml000064400000000000000000000005221046102023000172410ustar 00000000000000make = "Panasonic" model = "DMC-FZ2000" clean_make = "Panasonic" clean_model = "DMC-FZ2000" #blackpoint = 142 whitepoint = 2095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.772, -0.3126, -0.0163, -0.3867, 1.1799, 0.2339, -0.0433, 0.1183, 0.5996] D65 = [0.7386, -0.2443, -0.0743, -0.3437, 1.1864, 0.1757, -0.0608, 0.166, 0.4766] rawler-0.7.1/data/cameras/panasonic/fz2500.toml000064400000000000000000000007021046102023000172460ustar 00000000000000make = "Panasonic" model = "DMC-FZ2500" clean_make = "Panasonic" clean_model = "DMC-FZ2500" model_aliases = [ ["DMC-FZ2000", "DMC-FZ2000"], ] #blackpoint = 141 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.772, -0.3126, -0.0163, -0.3867, 1.1799, 0.2339, -0.0433, 0.1183, 0.5996] D65 = [0.7386, -0.2443, -0.0743, -0.3437, 1.1864, 0.1757, -0.0608, 0.166, 0.4766] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/panasonic/fz28.toml000064400000000000000000000010001046102023000171010ustar 00000000000000make = "Panasonic" model = "DMC-FZ28" clean_make = "Panasonic" clean_model = "DMC-FZ28" #blackpoint = 15 whitepoint = 3986 color_pattern = "BGGR" [cameras.color_matrix] A = [1.2346, -0.5884, 0.0233, -0.3747, 1.0806, 0.3402, -0.0239, 0.1145, 0.576] D65 = [1.0109, -0.3488, -0.0993, -0.5412, 1.2812, 0.2916, -0.1305, 0.214, 0.5543] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 56, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 56, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 56, 0] rawler-0.7.1/data/cameras/panasonic/fz30.toml000064400000000000000000000006031046102023000171020ustar 00000000000000make = "Panasonic" model = "DMC-FZ30" clean_make = "Panasonic" clean_model = "DMC-FZ30" #blackpoint = 0 whitepoint = 3971 color_pattern = "RGGB" [cameras.color_matrix] A = [1.3336, -0.6687, 0.0365, -0.579, 1.2816, 0.3354, -0.0593, 0.1134, 0.8093] D65 = [1.0977, -0.403, -0.1142, -0.7918, 1.549, 0.26, -0.1669, 0.2072, 0.8246] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 16, 0] rawler-0.7.1/data/cameras/panasonic/fz300.toml000064400000000000000000000006141046102023000171640ustar 00000000000000make = "Panasonic" model = "DMC-FZ300" clean_make = "Panasonic" clean_model = "DMC-FZ300" #blackpoint = 143 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.9263, -0.3981, 0.0028, -0.3588, 1.1615, 0.2237, -0.0364, 0.1328, 0.5749] D65 = [0.8378, -0.2798, -0.0769, -0.3068, 1.141, 0.1877, -0.0538, 0.1792, 0.4623] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/fz330.toml000064400000000000000000000006121046102023000171650ustar 00000000000000make = "Panasonic" model = "DMC-FZ330" clean_make = "Panasonic" clean_model = "DMC-FZ330" #blackpoint = 0 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.9263, -0.3981, 0.0028, -0.3588, 1.1615, 0.2237, -0.0364, 0.1328, 0.5749] D65 = [0.8378, -0.2798, -0.0769, -0.3068, 1.141, 0.1877, -0.0538, 0.1792, 0.4623] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 126, 0] rawler-0.7.1/data/cameras/panasonic/fz38.toml000064400000000000000000000010571046102023000171160ustar 00000000000000make = "Panasonic" model = "DMC-FZ38" clean_make = "Panasonic" clean_model = "DMC-FZ38" model_aliases = [ ["DMC-FZ35", "DMC-FZ35"], ] #blackpoint = 143 whitepoint = 3986 color_pattern = "BGGR" [cameras.color_matrix] A = [1.2081, -0.5143, 0.0429, -0.3176, 1.0594, 0.2993, -0.003, 0.1266, 0.496] D65 = [0.9938, -0.278, -0.089, -0.4604, 1.2393, 0.248, -0.1117, 0.2304, 0.462] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 42, 4] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 42, 4] rawler-0.7.1/data/cameras/panasonic/fz45.toml000064400000000000000000000011521046102023000171100ustar 00000000000000make = "Panasonic" model = "DMC-FZ45" clean_make = "Panasonic" clean_model = "DMC-FZ45" #blackpoint = 143 whitepoint = 3986 color_pattern = "GBRG" model_aliases = [ ["DC-FZ45", "DC-FZ45"], ] [cameras.color_matrix] A = [1.5103, -0.7784, -0.0173, -0.0776, 0.8139, 0.3163, 0.0879, 0.025, 0.4804] D65 = [1.3639, -0.5535, -0.1371, -0.1698, 0.9633, 0.243, 0.0316, 0.1152, 0.4108] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 58, 10] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 62, 0] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/panasonic/fz50.toml000064400000000000000000000010001046102023000170740ustar 00000000000000make = "Panasonic" model = "DMC-FZ50" clean_make = "Panasonic" clean_model = "DMC-FZ50" #blackpoint = 0 whitepoint = 3986 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9649, -0.4671, 0.0453, -0.446, 1.1161, 0.3805, -0.0752, 0.1529, 0.6811] D65 = [0.7906, -0.2709, -0.0594, -0.6231, 1.3352, 0.322, -0.1923, 0.2631, 0.6538] [[cameras.modes]] mode = "4:3" active_area = [20, 8, 16, 5] [[cameras.modes]] mode = "3:2" active_area = [3, 0, 17, 5] [[cameras.modes]] mode = "16:9" active_area = [3, 0, 15, 5] rawler-0.7.1/data/cameras/panasonic/fz70.toml000064400000000000000000000011001046102023000170770ustar 00000000000000make = "Panasonic" model = "DMC-FZ70" clean_make = "Panasonic" clean_model = "DMC-FZ70" #blackpoint = 163 whitepoint = 3941 color_pattern = "RGGB" [cameras.color_matrix] A = [1.3073, -0.6466, 0.0777, -0.1375, 0.9113, 0.2682, 0.0211, 0.0726, 0.5158] D65 = [1.1532, -0.4324, -0.1066, -0.2375, 1.0847, 0.1749, -0.0564, 0.1699, 0.4351] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 182, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 182, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 182, 0] rawler-0.7.1/data/cameras/panasonic/fz72.toml000064400000000000000000000011001046102023000171010ustar 00000000000000make = "Panasonic" model = "DMC-FZ72" clean_make = "Panasonic" clean_model = "DMC-FZ72" #blackpoint = 144 whitepoint = 3956 color_pattern = "RGGB" [cameras.color_matrix] A = [1.3073, -0.6466, 0.0777, -0.1375, 0.9113, 0.2682, 0.0211, 0.0726, 0.5158] D65 = [1.1532, -0.4324, -0.1066, -0.2375, 1.0847, 0.1749, -0.0564, 0.1699, 0.4351] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 182, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 182, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 182, 0] rawler-0.7.1/data/cameras/panasonic/fz8.toml000064400000000000000000000006041046102023000170300ustar 00000000000000make = "Panasonic" model = "DMC-FZ8" clean_make = "Panasonic" clean_model = "DMC-FZ8" #blackpoint = 0 whitepoint = 3986 color_pattern = "RGGB" [cameras.color_matrix] A = [1.0596, -0.4575, 0.0184, -0.4765, 1.1633, 0.359, -0.0495, 0.122, 0.6576] D65 = [0.8986, -0.2756, -0.0801, -0.6341, 1.3576, 0.3077, -0.1476, 0.2144, 0.6379] [[cameras.modes]] mode = "4:3" active_area = [5, 0, 31, 1] rawler-0.7.1/data/cameras/panasonic/fz80.toml000064400000000000000000000006071046102023000171130ustar 00000000000000make = "Panasonic" model = "DC-FZ80" clean_make = "Panasonic" clean_model = "DC-FZ80" #blackpoint = 0 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [1.3073, -0.6466, 0.0777, -0.1375, 0.9113, 0.2682, 0.0211, 0.0726, 0.5158] D65 = [1.1532, -0.4324, -0.1066, -0.2375, 1.0847, 0.1749, -0.0564, 0.1699, 0.4351] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 126, 0] rawler-0.7.1/data/cameras/panasonic/fz82.toml000064400000000000000000000006101046102023000171070ustar 00000000000000make = "Panasonic" model = "DC-FZ82" clean_make = "Panasonic" clean_model = "DC-FZ82" #blackpoint = 40 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [1.3073, -0.6466, 0.0777, -0.1375, 0.9113, 0.2682, 0.0211, 0.0726, 0.5158] D65 = [1.1532, -0.4324, -0.1066, -0.2375, 1.0847, 0.1749, -0.0564, 0.1699, 0.4351] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/g1.toml000064400000000000000000000007761046102023000166420ustar 00000000000000make = "Panasonic" model = "DMC-G1" clean_make = "Panasonic" clean_model = "DMC-G1" #blackpoint = 15 whitepoint = 3986 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8929, -0.2933, -0.0601, -0.6823, 1.4629, 0.2363, -0.1271, 0.2024, 0.7792] D65 = [0.8199, -0.2065, -0.1056, -0.8124, 1.6156, 0.2033, -0.2458, 0.3022, 0.722] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 42, 0] rawler-0.7.1/data/cameras/panasonic/g10.toml000064400000000000000000000010711046102023000167070ustar 00000000000000make = "Panasonic" model = "DMC-G10" clean_make = "Panasonic" clean_model = "DMC-G10" #blackpoint = 15 whitepoint = 3900 color_pattern = "GBRG" [cameras.color_matrix] A = [1.0433, -0.455, -0.0301, -0.3842, 1.1107, 0.3148, -0.0349, 0.1097, 0.7668] D65 = [1.0113, -0.34, -0.1114, -0.4765, 1.2683, 0.2317, -0.0377, 0.1437, 0.671] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 44, 0] rawler-0.7.1/data/cameras/panasonic/g100.toml000064400000000000000000000006641046102023000167760ustar 00000000000000make = "Panasonic" model = "DC-G100" clean_make = "Panasonic" clean_model = "DC-G100" model_aliases = [ ["DC-G110", "DC-G110"], ] #blackpoint = 0 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [1.0298, -0.5719, 0.0794, -0.2932, 1.0855, 0.2391, -0.0095, 0.0718, 0.6037] D65 = [0.837, -0.2869, -0.071, -0.3389, 1.1372, 0.2298, -0.064, 0.1599, 0.4887] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/g2.toml000064400000000000000000000010741046102023000166330ustar 00000000000000make = "Panasonic" model = "DMC-G2" clean_make = "Panasonic" clean_model = "DMC-G2" #blackpoint = 143 whitepoint = 3900 color_pattern = "GRBG" [cameras.color_matrix] A = [1.0433, -0.455, -0.0301, -0.3842, 1.1107, 0.3148, -0.0349, 0.1097, 0.7668] D65 = [1.0113, -0.34, -0.1114, -0.4765, 1.2683, 0.2317, -0.0377, 0.1437, 0.671] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 200, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 152, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 168, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 168, 0] rawler-0.7.1/data/cameras/panasonic/g3.toml000064400000000000000000000011001046102023000166220ustar 00000000000000make = "Panasonic" model = "DMC-G3" clean_make = "Panasonic" clean_model = "DMC-G3" #blackpoint = 143 whitepoint = 3956 color_pattern = "GRBG" [cameras.color_matrix] A = [0.6677, -0.2053, -0.0634, -0.3371, 1.0566, 0.3253, -0.0725, 0.1551, 0.6614] D65 = [0.6763, -0.1919, -0.0863, -0.3868, 1.1515, 0.2684, -0.1216, 0.2387, 0.5879] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 200, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 152, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 168, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 168, 0] rawler-0.7.1/data/cameras/panasonic/g5.toml000064400000000000000000000010731046102023000166350ustar 00000000000000make = "Panasonic" model = "DMC-G5" clean_make = "Panasonic" clean_model = "DMC-G5" #blackpoint = 143 whitepoint = 3956 color_pattern = "BGGR" [cameras.color_matrix] A = [0.8087, -0.311, -0.0172, -0.3294, 1.0463, 0.3289, -0.0401, 0.1311, 0.629] D65 = [0.7798, -0.2562, -0.074, -0.3879, 1.1584, 0.2613, -0.1055, 0.2248, 0.5434] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 192, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 192, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 192, 0] rawler-0.7.1/data/cameras/panasonic/g6.toml000064400000000000000000000010721046102023000166350ustar 00000000000000make = "Panasonic" model = "DMC-G6" clean_make = "Panasonic" clean_model = "DMC-G6" #blackpoint = 142 whitepoint = 3971 color_pattern = "BGGR" [cameras.color_matrix] A = [0.89, -0.3755, 0.027, -0.3407, 1.0753, 0.3068, -0.0599, 0.1555, 0.6269] D65 = [0.8294, -0.2891, -0.0651, -0.3869, 1.159, 0.2595, -0.1183, 0.2267, 0.5352] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 194, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 194, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 194, 0] rawler-0.7.1/data/cameras/panasonic/g7.toml000064400000000000000000000010731046102023000166370ustar 00000000000000make = "Panasonic" model = "DMC-G7" clean_make = "Panasonic" clean_model = "DMC-G7" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.8239, -0.3692, 0.0251, -0.3913, 1.1077, 0.3267, -0.0631, 0.1486, 0.7468] D65 = [0.761, -0.278, -0.0576, -0.4614, 1.2195, 0.2733, -0.1375, 0.2393, 0.649] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/g70.toml000064400000000000000000000010751046102023000167210ustar 00000000000000make = "Panasonic" model = "DMC-G70" clean_make = "Panasonic" clean_model = "DMC-G70" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.8239, -0.3692, 0.0251, -0.3913, 1.1077, 0.3267, -0.0631, 0.1486, 0.7468] D65 = [0.761, -0.278, -0.0576, -0.4614, 1.2195, 0.2733, -0.1375, 0.2393, 0.649] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/g80.toml000064400000000000000000000007161046102023000167230ustar 00000000000000make = "Panasonic" model = "DMC-G80" clean_make = "Panasonic" clean_model = "DMC-G80" model_aliases = [ ["DMC-G85", "DMC-G85"], ["DMC-G81", "DMC-G81"], ] #blackpoint = 0 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.8239, -0.3692, 0.0251, -0.3913, 1.1077, 0.3267, -0.0631, 0.1486, 0.7468] D65 = [0.761, -0.278, -0.0576, -0.4614, 1.2195, 0.2733, -0.1375, 0.2393, 0.649] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/g9.toml000064400000000000000000000005751046102023000166470ustar 00000000000000make = "Panasonic" model = "DC-G9" clean_make = "Panasonic" clean_model = "DC-G9" #blackpoint = 143 whitepoint = 4095 color_pattern = "RGGB" [cameras.color_matrix] A = [0.884, -0.403, 0.0594, -0.241, 0.9742, 0.3129, -0.008, 0.0672, 0.6014] D65 = [0.7685, -0.2375, -0.0634, -0.3687, 1.17, 0.2249, -0.0748, 0.1546, 0.5111] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/panasonic/g90.toml000064400000000000000000000007161046102023000167240ustar 00000000000000make = "Panasonic" model = "DC-G90" clean_make = "Panasonic" clean_model = "DC-G90" model_aliases = [ ["DC-G95", "DC-G95"], ["DC-G91", "DC-G91"], ] #blackpoint = 140 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [1.1794, -0.6983, 0.1102, -0.2819, 1.0936, 0.2161, -0.0028, 0.0638, 0.5793] D65 = [0.9657, -0.3963, -0.0748, -0.3361, 1.1378, 0.2258, -0.0568, 0.1415, 0.5158] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/g9mk2.toml000064400000000000000000000005311046102023000172510ustar 00000000000000make = "Panasonic" model = "DC-G9M2" clean_make = "Panasonic" clean_model = "DC-G9 II" whitepoint = 65535 color_pattern = "RGGB" [cameras.color_matrix] A = [0.9611, -0.5821, 0.0792, -0.3241, 1.0382, 0.3325, -0.022, 0.1513, 0.7211] D65 = [0.8325, -0.3456, -0.0623, -0.433, 1.2089, 0.2528, -0.086, 0.2646, 0.5984] [[cameras.modes]] mode = "4:3" rawler-0.7.1/data/cameras/panasonic/gf1.toml000064400000000000000000000010741046102023000170000ustar 00000000000000make = "Panasonic" model = "DMC-GF1" clean_make = "Panasonic" clean_model = "DMC-GF1" #blackpoint = 15 whitepoint = 3986 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8329, -0.2548, -0.0472, -0.6882, 1.4563, 0.2514, -0.1226, 0.1911, 0.7837] D65 = [0.7888, -0.1902, -0.1011, -0.8106, 1.6085, 0.2099, -0.2353, 0.2866, 0.733] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 44, 0] rawler-0.7.1/data/cameras/panasonic/gf10.toml000064400000000000000000000010751046102023000170610ustar 00000000000000make = "Panasonic" model = "DC-GF10" clean_make = "Panasonic" clean_model = "DC-GF10" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.8239, -0.3692, 0.0251, -0.3913, 1.1077, 0.3267, -0.0631, 0.1486, 0.7468] D65 = [0.761, -0.278, -0.0576, -0.4614, 1.2195, 0.2733, -0.1375, 0.2393, 0.649] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/gf2.toml000064400000000000000000000010741046102023000170010ustar 00000000000000make = "Panasonic" model = "DMC-GF2" clean_make = "Panasonic" clean_model = "DMC-GF2" #blackpoint = 15 whitepoint = 3986 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8329, -0.2548, -0.0472, -0.6882, 1.4563, 0.2514, -0.1226, 0.1911, 0.7837] D65 = [0.7888, -0.1902, -0.1011, -0.8106, 1.6085, 0.2099, -0.2353, 0.2866, 0.733] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 44, 0] rawler-0.7.1/data/cameras/panasonic/gf3.toml000064400000000000000000000010751046102023000170030ustar 00000000000000make = "Panasonic" model = "DMC-GF3" clean_make = "Panasonic" clean_model = "DMC-GF3" #blackpoint = 143 whitepoint = 3956 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8881, -0.2735, -0.0864, -0.4505, 1.2138, 0.2675, -0.0602, 0.1511, 0.7893] D65 = [0.9051, -0.2468, -0.1204, -0.5212, 1.3276, 0.2121, -0.1197, 0.251, 0.689] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 184, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 72, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 72, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 72, 0] rawler-0.7.1/data/cameras/panasonic/gf5.toml000064400000000000000000000010761046102023000170060ustar 00000000000000make = "Panasonic" model = "DMC-GF5" clean_make = "Panasonic" clean_model = "DMC-GF5" #blackpoint = 143 whitepoint = 3956 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8404, -0.3597, 0.0312, -0.3368, 1.0478, 0.3357, -0.0498, 0.1353, 0.6882] D65 = [0.8228, -0.2945, -0.066, -0.3938, 1.1792, 0.243, -0.1094, 0.2278, 0.5793] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 16, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/gf6.toml000064400000000000000000000010731046102023000170040ustar 00000000000000make = "Panasonic" model = "DMC-GF6" clean_make = "Panasonic" clean_model = "DMC-GF6" #blackpoint = 143 whitepoint = 3956 color_pattern = "GRBG" [cameras.color_matrix] A = [0.8514, -0.3399, -0.0455, -0.3, 1.0247, 0.3207, -0.0665, 0.157, 0.6769] D65 = [0.813, -0.2801, -0.0946, -0.352, 1.1289, 0.2552, -0.1314, 0.2511, 0.5791] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/gf7.toml000064400000000000000000000010751046102023000170070ustar 00000000000000make = "Panasonic" model = "DMC-GF7" clean_make = "Panasonic" clean_model = "DMC-GF7" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.8239, -0.3692, 0.0251, -0.3913, 1.1077, 0.3267, -0.0631, 0.1486, 0.7468] D65 = [0.761, -0.278, -0.0576, -0.4614, 1.2195, 0.2733, -0.1375, 0.2393, 0.649] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/gf8.toml000064400000000000000000000010751046102023000170100ustar 00000000000000make = "Panasonic" model = "DMC-GF8" clean_make = "Panasonic" clean_model = "DMC-GF8" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.8239, -0.3692, 0.0251, -0.3913, 1.1077, 0.3267, -0.0631, 0.1486, 0.7468] D65 = [0.761, -0.278, -0.0576, -0.4614, 1.2195, 0.2733, -0.1375, 0.2393, 0.649] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/gh1.toml000064400000000000000000000010741046102023000170020ustar 00000000000000make = "Panasonic" model = "DMC-GH1" clean_make = "Panasonic" clean_model = "DMC-GH1" #blackpoint = 15 whitepoint = 3986 color_pattern = "GBRG" [cameras.color_matrix] A = [0.6928, -0.2146, -0.0114, -0.5228, 1.2283, 0.3343, -0.123, 0.2111, 0.6223] D65 = [0.6299, -0.1466, -0.0532, -0.6535, 1.3852, 0.2969, -0.2331, 0.3112, 0.5984] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 28, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 28, 0] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 44, 0] rawler-0.7.1/data/cameras/panasonic/gh2.toml000064400000000000000000000010711046102023000170000ustar 00000000000000make = "Panasonic" model = "DMC-GH2" clean_make = "Panasonic" clean_model = "DMC-GH2" #blackpoint = 15 whitepoint = 3800 color_pattern = "BGGR" [cameras.color_matrix] A = [0.797, -0.2864, -0.0409, -0.3281, 1.062, 0.3083, -0.05, 0.1504, 0.605] D65 = [0.778, -0.241, -0.0806, -0.3913, 1.1724, 0.2484, -0.1018, 0.239, 0.5298] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 168, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 136, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 216, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 216, 0] rawler-0.7.1/data/cameras/panasonic/gh3.toml000064400000000000000000000010761046102023000170060ustar 00000000000000make = "Panasonic" model = "DMC-GH3" clean_make = "Panasonic" clean_model = "DMC-GH3" #blackpoint = 142 whitepoint = 3956 color_pattern = "GBRG" [cameras.color_matrix] A = [0.6721, -0.2283, 0.0393, -0.2946, 0.9993, 0.3452, -0.0312, 0.0974, 0.5864] D65 = [0.6559, -0.1752, -0.0491, -0.3672, 1.1407, 0.2586, -0.0962, 0.1875, 0.513] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 194, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 194, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 194, 0] rawler-0.7.1/data/cameras/panasonic/gh4.toml000064400000000000000000000010771046102023000170100ustar 00000000000000make = "Panasonic" model = "DMC-GH4" clean_make = "Panasonic" clean_model = "DMC-GH4" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.7726, -0.2915, 0.0118, -0.4213, 1.2198, 0.2259, -0.0476, 0.1114, 0.6346] D65 = [0.7122, -0.2108, -0.0512, -0.3155, 1.1201, 0.2231, -0.0541, 0.1423, 0.5045] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 0, 0] [[cameras.modes]] mode = "4:3" active_area = [8, 8, 200, 8] [[cameras.modes]] mode = "3:2" active_area = [8, 8, 200, 8] [[cameras.modes]] mode = "16:9" active_area = [8, 8, 200, 8] rawler-0.7.1/data/cameras/panasonic/gh5.toml000064400000000000000000000006071046102023000170070ustar 00000000000000make = "Panasonic" model = "DC-GH5" clean_make = "Panasonic" clean_model = "DC-GH5" #blackpoint = 144 whitepoint = 4095 color_pattern = "RGGB" [cameras.color_matrix] A = [0.8471, -0.3191, -0.0133, -0.4102, 1.2327, 0.1974, -0.0411, 0.1065, 0.6206] D65 = [0.7641, -0.2336, -0.0605, -0.3218, 1.1299, 0.2187, -0.0485, 0.1338, 0.5121] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 56, 0] rawler-0.7.1/data/cameras/panasonic/gh5m2.toml000064400000000000000000000006111046102023000172410ustar 00000000000000make = "Panasonic" model = "DC-GH5M2" clean_make = "Panasonic" clean_model = "DC-GH5 II" #blackpoint = 144 whitepoint = 4088 color_pattern = "RGGB" [cameras.color_matrix] A = [0.5705, -0.1725, -0.0368, -0.4945, 1.3285, 0.1798, -0.0413, 0.0984, 0.8129] D65 = [0.93, -0.3659, -0.0755, -0.2981, 1.0988, 0.2287, -0.019, 0.1077, 0.5016] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 56, 0] rawler-0.7.1/data/cameras/panasonic/gh5s.toml000064400000000000000000000010751046102023000171720ustar 00000000000000make = "Panasonic" model = "DC-GH5S" clean_make = "Panasonic" clean_model = "DC-GH5S" #blackpoint = 144 whitepoint = 8000 color_pattern = "RGGB" [cameras.color_matrix] A = [0.7718, -0.3541, 0.0141, -0.2768, 1.0432, 0.2711, -0.0242, 0.0926, 0.6051] D65 = [0.6929, -0.2355, -0.0708, -0.4192, 1.2534, 0.1828, -0.1097, 0.1989, 0.5195] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 56, 0] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 56, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 56, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 56, 0] rawler-0.7.1/data/cameras/panasonic/gh6.toml000064400000000000000000000006711046102023000170110ustar 00000000000000make = "Panasonic" model = "DC-GH6" clean_make = "Panasonic" clean_model = "DC-GH6" whitepoint = 65535 color_pattern = "RGGB" [cameras.color_matrix] A = [0.9619, -0.6021, 0.0569, -0.2909, 1.0935, 0.2266, -0.0149, 0.0883, 0.6246] D65 = [0.7949, -0.3491, -0.071, -0.3435, 1.1681, 0.1977, -0.0503, 0.1622, 0.5065] [[cameras.modes]] mode = "4:3" [[cameras.modes]] mode = "1:1" [[cameras.modes]] mode = "16:9" [[cameras.modes]] mode = "3:2" rawler-0.7.1/data/cameras/panasonic/gh7.toml000064400000000000000000000006721046102023000170130ustar 00000000000000make = "Panasonic" model = "DC-GH7" clean_make = "Panasonic" clean_model = "DC-GH7" whitepoint = 65535 color_pattern = "RGGB" [cameras.color_matrix] A = [0.9858, -0.6012, 0.0868, -0.2993, 1.0167, 0.3295, -0.0141, 0.1371, 0.7194] D65 = [0.8573, -0.3575, -0.0678, -0.4252, 1.2079, 0.2451, -0.0808, 0.2524, 0.5936] [[cameras.modes]] mode = "4:3" [[cameras.modes]] mode = "1:1" [[cameras.modes]] mode = "16:9" [[cameras.modes]] mode = "3:2" rawler-0.7.1/data/cameras/panasonic/gm1.toml000064400000000000000000000010761046102023000170110ustar 00000000000000make = "Panasonic" model = "DMC-GM1" clean_make = "Panasonic" clean_model = "DMC-GM1" #blackpoint = 143 whitepoint = 3956 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9784, -0.4995, 0.003, -0.3625, 1.1454, 0.2475, -0.0961, 0.2097, 0.6377] D65 = [0.677, -0.1895, -0.0744, -0.5232, 1.3145, 0.2303, -0.1664, 0.2691, 0.5703] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 206, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 206, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 206, 0] rawler-0.7.1/data/cameras/panasonic/gm1s.toml000064400000000000000000000006111046102023000171660ustar 00000000000000make = "Panasonic" model = "DMC-GM1S" clean_make = "Panasonic" clean_model = "DMC-GM1S" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9784, -0.4995, 0.003, -0.3625, 1.1454, 0.2475, -0.0961, 0.2097, 0.6377] D65 = [0.677, -0.1895, -0.0744, -0.5232, 1.3145, 0.2303, -0.1664, 0.2691, 0.5703] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/gm5.toml000064400000000000000000000010771046102023000170160ustar 00000000000000make = "Panasonic" model = "DMC-GM5" clean_make = "Panasonic" clean_model = "DMC-GM5" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9475, -0.482, 0.0198, -0.459, 1.2217, 0.2677, -0.0627, 0.1475, 0.7536] D65 = [0.8238, -0.3244, -0.0679, -0.3921, 1.1814, 0.2384, -0.0836, 0.2022, 0.5852] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 224, 16] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 224, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 224, 0] rawler-0.7.1/data/cameras/panasonic/gx1.toml000064400000000000000000000011021046102023000170120ustar 00000000000000make = "Panasonic" model = "DMC-GX1" clean_make = "Panasonic" clean_model = "DMC-GX1" #blackpoint = 143 whitepoint = 3956 color_pattern = "GRBG" [cameras.color_matrix] A = [0.6677, -0.2053, -0.0634, -0.3371, 1.0566, 0.3253, -0.0725, 0.1551, 0.6614] D65 = [0.6763, -0.1919, -0.0863, -0.3868, 1.1515, 0.2684, -0.1216, 0.2387, 0.5879] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 198, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 154, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 170, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 170, 0] rawler-0.7.1/data/cameras/panasonic/gx7.toml000064400000000000000000000010751046102023000170310ustar 00000000000000make = "Panasonic" model = "DMC-GX7" clean_make = "Panasonic" clean_model = "DMC-GX7" #blackpoint = 143 whitepoint = 3956 color_pattern = "BGGR" [cameras.color_matrix] A = [0.8239, -0.3692, 0.0251, -0.3913, 1.1077, 0.3267, -0.0631, 0.1486, 0.7468] D65 = [0.761, -0.278, -0.0576, -0.4614, 1.2195, 0.2733, -0.1375, 0.2393, 0.649] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/gx7mk2.toml000064400000000000000000000011041046102023000174340ustar 00000000000000make = "Panasonic" model = "DMC-GX7MK2" clean_make = "Panasonic" clean_model = "DMC-GX7 II" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.8795, -0.4348, 0.0193, -0.4128, 1.1726, 0.2733, -0.0567, 0.1447, 0.7409] D65 = [0.7771, -0.302, -0.0629, -0.4029, 1.195, 0.2345, -0.0821, 0.1977, 0.6119] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/gx7mk3.toml000064400000000000000000000011001046102023000174310ustar 00000000000000make = "Panasonic" model = "DC-GX7MK3" clean_make = "Panasonic" clean_model = "DC-GX7 III" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.7419, -0.2235, -0.0375, -0.3414, 1.17, 0.193, -0.04, 0.1107, 0.5954] D65 = [0.7564, -0.2263, -0.0606, -0.3148, 1.1239, 0.2177, -0.054, 0.1435, 0.4853] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 32, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 208, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/gx8.toml000064400000000000000000000006031046102023000170260ustar 00000000000000make = "Panasonic" model = "DMC-GX8" clean_make = "Panasonic" clean_model = "DMC-GX8" #blackpoint = 144 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.7419, -0.2235, -0.0375, -0.3414, 1.17, 0.193, -0.04, 0.1107, 0.5954] D65 = [0.7564, -0.2263, -0.0606, -0.3148, 1.1239, 0.2177, -0.054, 0.1435, 0.4853] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 64, 0] rawler-0.7.1/data/cameras/panasonic/gx80.toml000064400000000000000000000006731046102023000171150ustar 00000000000000make = "Panasonic" model = "DMC-GX80" clean_make = "Panasonic" clean_model = "DMC-GX80" model_aliases = [ ["DMC-GX85", "DMC-GX85"], ] #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.8795, -0.4348, 0.0193, -0.4128, 1.1726, 0.2733, -0.0567, 0.1447, 0.7409] D65 = [0.7771, -0.302, -0.0629, -0.4029, 1.195, 0.2345, -0.0821, 0.1977, 0.6119] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/gx800.toml000064400000000000000000000006721046102023000171740ustar 00000000000000make = "Panasonic" model = "DC-GX800" clean_make = "Panasonic" clean_model = "DC-GX800" model_aliases = [ ["DC-GX850", "DC-GX850"], ] #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.8239, -0.3692, 0.0251, -0.3913, 1.1077, 0.3267, -0.0631, 0.1486, 0.7468] D65 = [0.761, -0.278, -0.0576, -0.4614, 1.2195, 0.2733, -0.1375, 0.2393, 0.649] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/gx880.toml000064400000000000000000000006131046102023000171770ustar 00000000000000make = "Panasonic" model = "DC-GX880" clean_make = "Panasonic" clean_model = "DC-GX880" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.8239, -0.3692, 0.0251, -0.3913, 1.1077, 0.3267, -0.0631, 0.1486, 0.7468] D65 = [0.761, -0.278, -0.0576, -0.4614, 1.2195, 0.2733, -0.1375, 0.2393, 0.649] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 208, 0] rawler-0.7.1/data/cameras/panasonic/gx9.toml000064400000000000000000000006011046102023000170250ustar 00000000000000make = "Panasonic" model = "DC-GX9" clean_make = "Panasonic" clean_model = "DC-GX9" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.7419, -0.2235, -0.0375, -0.3414, 1.17, 0.193, -0.04, 0.1107, 0.5954] D65 = [0.7564, -0.2263, -0.0606, -0.3148, 1.1239, 0.2177, -0.054, 0.1435, 0.4853] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 64, 0] rawler-0.7.1/data/cameras/panasonic/l1.toml000064400000000000000000000006021046102023000166330ustar 00000000000000make = "Panasonic" model = "DMC-L1" clean_make = "Panasonic" clean_model = "DMC-L1" #blackpoint = 0 whitepoint = 3986 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8248, -0.2304, -0.0642, -0.7029, 1.4754, 0.2453, -0.1491, 0.2353, 0.815] D65 = [0.8054, -0.1886, -0.1025, -0.8348, 1.6367, 0.204, -0.2805, 0.3542, 0.763] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 11, 1] rawler-0.7.1/data/cameras/panasonic/l10.toml000064400000000000000000000006031046102023000167140ustar 00000000000000make = "Panasonic" model = "DMC-L10" clean_make = "Panasonic" clean_model = "DMC-L10" #blackpoint = 0 whitepoint = 3986 color_pattern = "GBRG" [cameras.color_matrix] A = [0.848, -0.2392, -0.0731, -0.6737, 1.4436, 0.2497, -0.1211, 0.1885, 0.7462] D65 = [0.8026, -0.1942, -0.105, -0.7919, 1.5904, 0.21, -0.2456, 0.3004, 0.704] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 28, 1] rawler-0.7.1/data/cameras/panasonic/lf1.toml000064400000000000000000000010721046102023000170030ustar 00000000000000make = "Panasonic" model = "DMC-LF1" clean_make = "Panasonic" clean_model = "DMC-LF1" #blackpoint = 143 whitepoint = 3971 color_pattern = "RGGB" [cameras.color_matrix] A = [1.0884, -0.5276, 0.0776, -0.2257, 0.994, 0.2711, -0.01, 0.098, 0.6119] D65 = [0.9379, -0.3267, -0.0816, -0.3227, 1.156, 0.1881, -0.0926, 0.1928, 0.534] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 16, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 126, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 126, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 126, 0] rawler-0.7.1/data/cameras/panasonic/lx1.toml000064400000000000000000000006051046102023000170260ustar 00000000000000make = "Panasonic" model = "DMC-LX1" clean_make = "Panasonic" clean_model = "DMC-LX1" #blackpoint = 0 whitepoint = 3971 color_pattern = "RGGB" [cameras.color_matrix] A = [1.2679, -0.6394, -0.0077, -0.651, 1.3697, 0.3128, -0.0364, 0.0551, 0.8614] D65 = [1.0704, -0.4187, -0.123, -0.8314, 1.5953, 0.2501, -0.092, 0.0945, 0.8927] [[cameras.modes]] mode = "16:9" active_area = [6, 0, 16, 0] rawler-0.7.1/data/cameras/panasonic/lx10.toml000064400000000000000000000006721046102023000171120ustar 00000000000000make = "Panasonic" model = "DMC-LX10" clean_make = "Panasonic" clean_model = "DMC-LX10" model_aliases = [ ["DMC-LX15", "DMC-LX15"], ] #blackpoint = 143 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8468, -0.3758, -0.0141, -0.3463, 1.1363, 0.2395, -0.0363, 0.1118, 0.6076] D65 = [0.779, -0.2736, -0.0755, -0.3452, 1.187, 0.1769, -0.0628, 0.1647, 0.4898] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/panasonic/lx100.toml000064400000000000000000000010761046102023000171710ustar 00000000000000make = "Panasonic" model = "DMC-LX100" clean_make = "Panasonic" clean_model = "DMC-LX100" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9867, -0.4849, 0.0039, -0.4644, 1.2563, 0.2321, -0.0614, 0.141, 0.6834] D65 = [0.8844, -0.3538, -0.0768, -0.3709, 1.1762, 0.22, -0.0698, 0.1792, 0.522] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 144, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 16, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 80, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 96, 0] rawler-0.7.1/data/cameras/panasonic/lx100m2.toml000064400000000000000000000011001046102023000174140ustar 00000000000000make = "Panasonic" model = "DC-LX100M2" clean_make = "Panasonic" clean_model = "DC-LX100M2" #blackpoint = 143 whitepoint = 4095 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9994, -0.49, 0.0018, -0.4363, 1.3152, 0.1279, -0.0328, 0.0965, 0.5835] D65 = [0.8585, -0.3127, -0.0833, -0.4005, 1.225, 0.1953, -0.065, 0.1494, 0.4862] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 144, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 16, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 80, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 96, 0] rawler-0.7.1/data/cameras/panasonic/lx2.toml000064400000000000000000000006041046102023000170260ustar 00000000000000make = "Panasonic" model = "DMC-LX2" clean_make = "Panasonic" clean_model = "DMC-LX2" #blackpoint = 0 whitepoint = 3986 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9781, -0.4779, 0.0376, -0.4711, 1.1427, 0.3777, -0.073, 0.1393, 0.7137] D65 = [0.8047, -0.281, -0.0624, -0.6449, 1.3519, 0.3272, -0.1701, 0.2146, 0.705] [[cameras.modes]] mode = "16:9" active_area = [4, 0, 38, 3] rawler-0.7.1/data/cameras/panasonic/lx3.toml000064400000000000000000000010721046102023000170270ustar 00000000000000make = "Panasonic" model = "DMC-LX3" clean_make = "Panasonic" clean_model = "DMC-LX3" #blackpoint = 15 whitepoint = 3986 color_pattern = "BGGR" [cameras.color_matrix] A = [0.9946, -0.4716, 0.043, -0.444, 1.1224, 0.3705, -0.0676, 0.1538, 0.6348] D65 = [0.8128, -0.2668, -0.0655, -0.6134, 1.3307, 0.3161, -0.1782, 0.2568, 0.6083] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 74, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 58, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 44, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 70, 0] rawler-0.7.1/data/cameras/panasonic/lx5.toml000064400000000000000000000010731046102023000170320ustar 00000000000000make = "Panasonic" model = "DMC-LX5" clean_make = "Panasonic" clean_model = "DMC-LX5" #blackpoint = 143 whitepoint = 3986 color_pattern = "GRBG" [cameras.color_matrix] A = [1.2034, -0.6088, 0.003, -0.0465, 0.7861, 0.3136, 0.064, 0.0751, 0.544] D65 = [1.0909, -0.4295, -0.0948, -0.1333, 0.9306, 0.2399, 0.0022, 0.1738, 0.4582] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 220, 4] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 200, 4] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 74, 4] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 104, 4] rawler-0.7.1/data/cameras/panasonic/lx7.toml000064400000000000000000000010751046102023000170360ustar 00000000000000make = "Panasonic" model = "DMC-LX7" clean_make = "Panasonic" clean_model = "DMC-LX7" #blackpoint = 142 whitepoint = 3971 color_pattern = "GRBG" [cameras.color_matrix] A = [1.1127, -0.5386, 0.041, -0.1849, 0.9339, 0.2962, 0.0066, 0.0807, 0.5378] D65 = [1.0148, -0.3743, -0.0991, -0.2837, 1.1366, 0.1659, -0.0701, 0.1893, 0.4899] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 48, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 34, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 160, 0] rawler-0.7.1/data/cameras/panasonic/s1.toml000064400000000000000000000006041046102023000166440ustar 00000000000000make = "Panasonic" model = "DC-S1" clean_make = "Panasonic" clean_model = "DC-S1" #blackpoint = 142 whitepoint = 16380 color_pattern = "RGGB" [cameras.color_matrix] A = [1.1598, -0.6406, 0.0627, -0.4876, 1.3241, 0.177, -0.0306, 0.0922, 0.6741] D65 = [0.9744, -0.3905, -0.0779, -0.4899, 1.2807, 0.2324, -0.0798, 0.163, 0.5827] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/s1h.toml000064400000000000000000000006101046102023000170110ustar 00000000000000make = "Panasonic" model = "DC-S1H" clean_make = "Panasonic" clean_model = "DC-S1H" #blackpoint = 142 whitepoint = 16380 color_pattern = "RGGB" [cameras.color_matrix] A = [1.1335, -0.6469, 0.0804, -0.4415, 1.2413, 0.2235, -0.0223, 0.0804, 0.6653] D65 = [0.9397, -0.3719, -0.0805, -0.5425, 1.3326, 0.2309, -0.0972, 0.1715, 0.6034] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/s1r.toml000064400000000000000000000006071046102023000170310ustar 00000000000000make = "Panasonic" model = "DC-S1R" clean_make = "Panasonic" clean_model = "DC-S1R" #blackpoint = 142 whitepoint = 16380 color_pattern = "RGGB" [cameras.color_matrix] A = [1.4113, -0.8165, 0.0413, -0.5716, 1.5256, 0.031, -0.0048, 0.0467, 0.7624] D65 = [1.1822, -0.5321, -0.1249, -0.5958, 1.5114, 0.0766, -0.0614, 0.1264, 0.7043] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/s1rm2.toml000064400000000000000000000005351046102023000172700ustar 00000000000000make = "Panasonic" model = "DC-S1RM2" clean_make = "Panasonic" clean_model = "DC-S1RM2" whitepoint = 16380 color_pattern = "RGGB" [cameras.color_matrix] A = [1.1913, -0.699, 0.0497, -0.3422, 1.1123, 0.2638, -0.0144, 0.0722, 0.6537] D65 = [0.9941, -0.4056, -0.0871, -0.3745, 1.1604, 0.2433, -0.0254, 0.1132, 0.5526] [[cameras.modes]] mode = "3:2" rawler-0.7.1/data/cameras/panasonic/s5.toml000064400000000000000000000006041046102023000166500ustar 00000000000000make = "Panasonic" model = "DC-S5" clean_make = "Panasonic" clean_model = "DC-S5" #blackpoint = 142 whitepoint = 16380 color_pattern = "RGGB" [cameras.color_matrix] A = [1.1598, -0.6406, 0.0627, -0.4876, 1.3241, 0.177, -0.0306, 0.0922, 0.6741] D65 = [0.9744, -0.3905, -0.0779, -0.4899, 1.2807, 0.2324, -0.0798, 0.163, 0.5827] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/s5m2.toml000064400000000000000000000006151046102023000171110ustar 00000000000000make = "Panasonic" model = "DC-S5M2" clean_make = "Panasonic" clean_model = "DC-S5M2" whitepoint = 16383 color_pattern = "RGGB" model_aliases = [ ["DC-S5M2X", "DC-S5M2X"], ] [cameras.color_matrix] A = [1.3022, -0.817, 0.1348, -0.3478, 1.0901, 0.2974, 0.0031, 0.0471, 0.7057] D65 = [1.0308, -0.4206, -0.0783, -0.4088, 1.2102, 0.2229, -0.0125, 0.1051, 0.5912] [[cameras.modes]] mode = "3:2" rawler-0.7.1/data/cameras/panasonic/s9.toml000064400000000000000000000005221046102023000166530ustar 00000000000000make = "Panasonic" model = "DC-S9" clean_make = "Panasonic" clean_model = "DC-S9" whitepoint = 4095 color_pattern = "RGGB" [cameras.color_matrix] A = [1.2599, -0.7524, 0.072, -0.4116, 1.1989, 0.2399, -0.0184, 0.076, 0.698] D65 = [0.9983, -0.389, -0.0841, -0.418, 1.2164, 0.2263, -0.0249, 0.1139, 0.5766] [[cameras.modes]] mode = "3:2" rawler-0.7.1/data/cameras/panasonic/tz100.toml000064400000000000000000000010621046102023000171760ustar 00000000000000make = "Panasonic" model = "DMC-TZ100" clean_make = "Panasonic" clean_model = "DMC-TZ100" model_aliases = [ ["DMC-TZ101", "DMC-TZ101"], ["DMC-TZ110", "DMC-TZ110"], ["DMC-ZS100", "DMC-ZS100"], ["DMC-ZS110", "DMC-ZS110"], ["DMC-TX1", "DMC-TX1"], ] #blackpoint = 141 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8468, -0.3758, -0.0141, -0.3463, 1.1363, 0.2395, -0.0363, 0.1118, 0.6076] D65 = [0.779, -0.2736, -0.0755, -0.3452, 1.187, 0.1769, -0.0628, 0.1647, 0.4898] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/panasonic/tz202.toml000064400000000000000000000012441046102023000172030ustar 00000000000000make = "Panasonic" model = "DC-TZ202" clean_make = "Panasonic" clean_model = "DC-TZ202" model_aliases = [ ["DC-TZ202D", "DC-TZ202D"], ["DC-TZ200", "DC-TZ200"], ["DC-TZ220", "DC-TZ220"], ["DC-ZS200", "DC-ZS200"], ["DC-ZS220", "DC-ZS220"], ["DC-TZ200D", "DC-TZ200D"], ["DC-TZ220D", "DC-TZ220D"], ["DC-ZS200D", "DC-ZS200D"], ["DC-ZS220D", "DC-ZS220D"], ] #blackpoint = 141 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.8468, -0.3758, -0.0141, -0.3463, 1.1363, 0.2395, -0.0363, 0.1118, 0.6076] D65 = [0.779, -0.2736, -0.0755, -0.3452, 1.187, 0.1769, -0.0628, 0.1647, 0.4898] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 0, 0] rawler-0.7.1/data/cameras/panasonic/tz60.toml000064400000000000000000000012131046102023000171210ustar 00000000000000make = "Panasonic" model = "DMC-TZ60" clean_make = "Panasonic" clean_model = "DMC-TZ60" model_aliases = [ ["DMC-ZS40", "DMC-ZS40"], ["DMC-ZS60", "DMC-ZS60"], ] #blackpoint = 145 whitepoint = 3956 color_pattern = "RGGB" [cameras.color_matrix] A = [0.9694, -0.4422, 0.0423, -0.2524, 0.9988, 0.2964, 0.0026, 0.1012, 0.5939] D65 = [0.8607, -0.2822, -0.0808, -0.3755, 1.193, 0.2049, -0.082, 0.206, 0.5224] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 8, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/tz61.toml000064400000000000000000000010751046102023000171300ustar 00000000000000make = "Panasonic" model = "DMC-TZ61" clean_make = "Panasonic" clean_model = "DMC-TZ61" #blackpoint = 145 whitepoint = 3971 color_pattern = "RGGB" [cameras.color_matrix] A = [0.9694, -0.4422, 0.0423, -0.2524, 0.9988, 0.2964, 0.0026, 0.1012, 0.5939] D65 = [0.8607, -0.2822, -0.0808, -0.3755, 1.193, 0.2049, -0.082, 0.206, 0.5224] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 8, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 126, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 126, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 126, 0] rawler-0.7.1/data/cameras/panasonic/tz70.toml000064400000000000000000000011621046102023000171250ustar 00000000000000make = "Panasonic" model = "DMC-TZ70" clean_make = "Panasonic" clean_model = "DMC-TZ70" model_aliases = [ ["DMC-ZS50", "DMC-ZS50"], ] #blackpoint = 143 whitepoint = 3971 color_pattern = "RGGB" [cameras.color_matrix] A = [0.9863, -0.4626, 0.0222, -0.2892, 1.0667, 0.2572, -0.0234, 0.1167, 0.5981] D65 = [0.8802, -0.3135, -0.0789, -0.3151, 1.1468, 0.1904, -0.055, 0.1745, 0.481] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 16, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/tz71.toml000064400000000000000000000011001046102023000171160ustar 00000000000000make = "Panasonic" model = "DMC-TZ71" clean_make = "Panasonic" clean_model = "DMC-TZ71" #blackpoint = 142 whitepoint = 3956 color_pattern = "RGGB" [cameras.color_matrix] A = [0.9863, -0.4626, 0.0222, -0.2892, 1.0667, 0.2572, -0.0234, 0.1167, 0.5981] D65 = [0.8802, -0.3135, -0.0789, -0.3151, 1.1468, 0.1904, -0.055, 0.1745, 0.481] [[cameras.modes]] mode = "1:1" active_area = [0, 0, 16, 0] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "3:2" active_area = [0, 0, 128, 0] [[cameras.modes]] mode = "16:9" active_area = [0, 0, 128, 0] rawler-0.7.1/data/cameras/panasonic/tz80.toml000064400000000000000000000006721046102023000171330ustar 00000000000000make = "Panasonic" model = "DMC-TZ80" clean_make = "Panasonic" clean_model = "DMC-TZ80" model_aliases = [ ["DMC-TZ81", "DMC-TZ81"], ] #blackpoint = 154 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.9036, -0.3699, -0.0251, -0.349, 1.141, 0.2371, -0.019, 0.1207, 0.5737] D65 = [0.855, -0.2908, -0.0842, -0.3195, 1.1529, 0.1881, -0.0338, 0.1603, 0.4631] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 126, 0] rawler-0.7.1/data/cameras/panasonic/tz90.toml000064400000000000000000000006071046102023000171320ustar 00000000000000make = "Panasonic" model = "DC-TZ90" clean_make = "Panasonic" clean_model = "DC-TZ90" #blackpoint = 139 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.9708, -0.4136, -0.0164, -0.3559, 1.1435, 0.2421, -0.0135, 0.1147, 0.5867] D65 = [0.9052, -0.3117, -0.0883, -0.3045, 1.1346, 0.1927, -0.0205, 0.152, 0.473] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 64, 0] rawler-0.7.1/data/cameras/panasonic/tz91.toml000064400000000000000000000006071046102023000171330ustar 00000000000000make = "Panasonic" model = "DC-TZ91" clean_make = "Panasonic" clean_model = "DC-TZ91" #blackpoint = 139 whitepoint = 4095 color_pattern = "GBRG" [cameras.color_matrix] A = [0.9708, -0.4136, -0.0164, -0.3559, 1.1435, 0.2421, -0.0135, 0.1147, 0.5867] D65 = [0.9052, -0.3117, -0.0883, -0.3045, 1.1346, 0.1927, -0.0205, 0.152, 0.473] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 64, 0] rawler-0.7.1/data/cameras/panasonic/tz95.toml000064400000000000000000000007521046102023000171400ustar 00000000000000make = "Panasonic" model = "DC-TZ95" clean_make = "Panasonic" clean_model = "DC-TZ95" #blackpoint = 139 whitepoint = 4095 color_pattern = "GBRG" model_aliases = [ ["DC-TZ95D", "DC-TZ95D"], ["DC-TZ96", "DC-TZ96"], ["DC-ZS80", "DC-ZS80"], ] [cameras.color_matrix] A = [1.1584, -0.5864, 0.0034, -0.2454, 1.0558, 0.2191, 0.0354, 0.0729, 0.5581] D65 = [1.2194, -0.534, -0.1329, -0.3035, 1.1394, 0.1858, -0.005, 0.1418, 0.5219] [[cameras.modes]] mode = "4:3" active_area = [0, 0, 64, 0] rawler-0.7.1/data/cameras/pentax/645d.toml000064400000000000000000000004621046102023000163310ustar 00000000000000make = "PENTAX" model = "PENTAX 645D" clean_make = "Pentax" clean_model = "645D" #blackpoint = 0 whitepoint = 15767 color_pattern = "BGGR" active_area = [48, 29, 48, 21] crop_area = [80, 59, 80, 53] [cameras.color_matrix] D65 = [1.0646, -0.3593, -0.1158, -0.3329, 1.1699, 0.1831, -0.0667, 0.2874, 0.6287] rawler-0.7.1/data/cameras/pentax/645z.toml000064400000000000000000000005031046102023000163530ustar 00000000000000make = "RICOH IMAGING COMPANY, LTD." model = "PENTAX 645Z" clean_make = "Pentax" clean_model = "645Z" #blackpoint = 1 whitepoint = 16316 color_pattern = "RGGB" active_area = [58, 8, 70, 8] crop_area = [58, 8, 70, 8] [cameras.color_matrix] D65 = [0.9519, -0.3591, -0.0664, -0.4074, 1.1725, 0.2671, -0.0624, 0.1501, 0.6653] rawler-0.7.1/data/cameras/pentax/istD.toml000064400000000000000000000004761046102023000165570ustar 00000000000000make = "PENTAX Corporation" model = "PENTAX *ist D" clean_make = "Pentax" clean_model = "*ist D" #blackpoint = 128 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [19, 11, 13, 5] [cameras.color_matrix] D65 = [0.9651, -0.2059, -0.1189, -0.8881, 1.6512, 0.2487, -0.1460, 0.1345, 1.0687] rawler-0.7.1/data/cameras/pentax/istDL.toml000064400000000000000000000004771046102023000166740ustar 00000000000000make = "PENTAX Corporation" model = "PENTAX *ist DL" clean_make = "Pentax" clean_model = "*ist DL" #blackpoint = 128 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] [cameras.color_matrix] D65 = [1.0829, -0.2838, -0.1115, -0.8339, 1.5817, 0.2696, -0.0837, 0.0680, 1.1939] rawler-0.7.1/data/cameras/pentax/istDL2.toml000064400000000000000000000005011046102023000167420ustar 00000000000000make = "PENTAX Corporation" model = "PENTAX *ist DL2" clean_make = "Pentax" clean_model = "*ist DL2" #blackpoint = 127 whitepoint = 3950 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] [cameras.color_matrix] D65 = [1.0504, -0.2438, -0.1189, -0.8603, 1.6207, 0.2531, -0.1022, 0.0863, 1.2242] rawler-0.7.1/data/cameras/pentax/istDS.toml000064400000000000000000000004771046102023000167030ustar 00000000000000make = "PENTAX Corporation" model = "PENTAX *ist DS" clean_make = "Pentax" clean_model = "*ist DS" #blackpoint = 128 whitepoint = 3950 color_pattern = "RGGB" active_area = [0, 0, 0, 2] crop_area = [16, 8, 16, 8] [cameras.color_matrix] D65 = [1.0371, -0.2333, -0.1206, -0.8688, 1.6231, 0.2602, -0.1230, 0.1116, 1.1282] rawler-0.7.1/data/cameras/pentax/k-1.toml000064400000000000000000000005401046102023000162340ustar 00000000000000make = "RICOH IMAGING COMPANY, LTD." model = "PENTAX K-1" clean_make = "RICOH IMAGING COMPANY, LTD." clean_model = "PENTAX K-1" #blackpoint = 64 whitepoint = 16316 color_pattern = "RGGB" active_area = [6, 18, 10, 0] crop_area = [14, 28, 18, 10] [cameras.color_matrix] D65 = [0.8596, -0.2981, -0.0639, -0.4202, 1.2046, 0.2431, -0.0685, 0.1424, 0.6122] rawler-0.7.1/data/cameras/pentax/k-1II.toml000064400000000000000000000005601046102023000164600ustar 00000000000000make = "RICOH IMAGING COMPANY, LTD." model = "PENTAX K-1 Mark II" clean_make = "RICOH IMAGING COMPANY, LTD." clean_model = "PENTAX K-1 Mark II" #blackpoint = 64 whitepoint = 16315 color_pattern = "RGGB" active_area = [6, 18, 10, 0] crop_area = [14, 28, 18, 10] [cameras.color_matrix] D65 = [0.8952, -0.2869, -0.1256, -0.3612, 1.2204, 0.1550, -0.0934, 0.1757, 0.6549] rawler-0.7.1/data/cameras/pentax/k-3.toml000064400000000000000000000005031046102023000162350ustar 00000000000000make = "RICOH IMAGING COMPANY, LTD." model = "PENTAX K-3" clean_make = "Pentax" clean_model = "K-3" #blackpoint = 1 whitepoint = 16315 color_pattern = "RGGB" active_area = [10, 4, 42, 4] crop_area = [16, 16, 48, 16] [cameras.color_matrix] D65 = [0.7415, -0.2052, -0.0721, -0.5186, 1.2788, 0.2682, -0.1446, 0.2157, 0.6773] rawler-0.7.1/data/cameras/pentax/k-3II.toml000064400000000000000000000005111046102023000164560ustar 00000000000000make = "RICOH IMAGING COMPANY, LTD." model = "PENTAX K-3 II" clean_make = "Pentax" clean_model = "K-3 II" #blackpoint = 0 whitepoint = 16253 color_pattern = "RGGB" active_area = [10, 4, 42, 4] crop_area = [16, 16, 48, 16] [cameras.color_matrix] D65 = [0.7415, -0.2052, -0.0721, -0.5186, 1.2788, 0.2682, -0.1446, 0.2157, 0.6773] rawler-0.7.1/data/cameras/pentax/k-3III.toml000064400000000000000000000006331046102023000165740ustar 00000000000000make = "RICOH IMAGING COMPANY, LTD." model = "PENTAX K-3 Mark III" clean_make = "Ricoh" clean_model = "PENTAX K-3 Mark III" whitepoint = 16375 color_pattern = "RGGB" active_area = [26, 34, 54, 30] crop_area = [54, 58, 58, 38] [cameras.color_matrix] A = [1.1154, -0.6711, 0.0521, -0.4126, 1.1956, 0.2451, -0.029, 0.0795, 0.6802] D65 = [0.9251, -0.3817, -0.1069, -0.4627, 1.2667, 0.2175, -0.0798, 0.166, 0.5633] rawler-0.7.1/data/cameras/pentax/k-3III_monochrome.toml000064400000000000000000000003321046102023000210160ustar 00000000000000make = "RICOH IMAGING COMPANY, LTD." model = "PENTAX K-3 Mark III Monochrome" clean_make = "Ricoh" clean_model = "K-3 Mark III Monochrome" whitepoint = 16378 active_area = [26, 34, 54, 30] crop_area = [54, 58, 58, 38] rawler-0.7.1/data/cameras/pentax/k-5.toml000064400000000000000000000004601046102023000162410ustar 00000000000000make = "PENTAX" model = "PENTAX K-5" clean_make = "Pentax" clean_model = "K-5" #blackpoint = 512 whitepoint = 15866 color_pattern = "BGGR" active_area = [0, 0, 32, 0] crop_area = [22, 10, 42, 10] [cameras.color_matrix] D65 = [0.8713, -0.2833, -0.0743, -0.4342, 1.1900, 0.2772, -0.0722, 0.1543, 0.6247] rawler-0.7.1/data/cameras/pentax/k-5II.toml000064400000000000000000000004661046102023000164710ustar 00000000000000make = "PENTAX" model = "PENTAX K-5 II" clean_make = "Pentax" clean_model = "K-5 II" #blackpoint = 256 whitepoint = 16124 color_pattern = "BGGR" active_area = [10, 0, 32, 0] crop_area = [22, 10, 42, 10] [cameras.color_matrix] D65 = [0.8170, -0.2725, -0.0639, -0.4440, 1.2017, 0.2744, -0.0771, 0.1465, 0.6599] rawler-0.7.1/data/cameras/pentax/k-5IIs.toml000064400000000000000000000004721046102023000166510ustar 00000000000000make = "PENTAX" model = "PENTAX K-5 II s" clean_make = "Pentax" clean_model = "K-5 II s" #blackpoint = 129 whitepoint = 16253 color_pattern = "BGGR" active_area = [10, 0, 32, 0] crop_area = [22, 10, 42, 10] [cameras.color_matrix] D65 = [0.8170, -0.2725, -0.0639, -0.4440, 1.2017, 0.2744, -0.0771, 0.1465, 0.6599] rawler-0.7.1/data/cameras/pentax/k-7.toml000064400000000000000000000004551046102023000162470ustar 00000000000000make = "PENTAX" model = "PENTAX K-7" clean_make = "Pentax" clean_model = "K-7" #blackpoint = 0 whitepoint = 4095 color_pattern = "BGGR" active_area = [0, 2, 52, 12] crop_area = [10, 10, 54, 22] [cameras.color_matrix] D65 = [0.9142, -0.2947, -0.0678, -0.8648, 1.6967, 0.1663, -0.2224, 0.2898, 0.8615] rawler-0.7.1/data/cameras/pentax/k-70.toml000064400000000000000000000005431046102023000163250ustar 00000000000000make = "RICOH IMAGING COMPANY, LTD." model = "PENTAX K-70" clean_make = "RICOH IMAGING COMPANY, LTD." clean_model = "PENTAX K-70" #blackpoint = 64 whitepoint = 16315 color_pattern = "RGGB" active_area = [58, 28, 0, 12] crop_area = [66, 32, 14, 32] [cameras.color_matrix] D65 = [0.8766, -0.3149, -0.0747, -0.3976, 1.1943, 0.2292, -0.0517, 0.1259, 0.5552] rawler-0.7.1/data/cameras/pentax/k-m.toml000064400000000000000000000004521046102023000163320ustar 00000000000000make = "PENTAX" model = "PENTAX K-m" clean_make = "Pentax" clean_model = "K-m" #blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 40, 8] crop_area = [8, 8, 56, 24] [cameras.color_matrix] D65 = [1.1057, -0.3604, -0.1155, -0.5152, 1.3046, 0.2329, -0.0282, 0.0375, 0.8104] rawler-0.7.1/data/cameras/pentax/k-r.toml000064400000000000000000000004561046102023000163430ustar 00000000000000make = "PENTAX" model = "PENTAX K-r" clean_make = "Pentax" clean_model = "K-r" #blackpoint = 129 whitepoint = 3964 color_pattern = "BGGR" active_area = [0, 0, 42, 0] crop_area = [10, 10, 54, 10] [cameras.color_matrix] D65 = [0.9895, -0.3077, -0.0850, -0.5304, 1.3035, 0.2521, -0.0883, 0.1768, 0.6936] rawler-0.7.1/data/cameras/pentax/k-s1.toml000064400000000000000000000005031046102023000164160ustar 00000000000000make = "RICOH IMAGING COMPANY, LTD." model = "PENTAX K-S1" clean_make = "Pentax" clean_model = "K-S1" #blackpoint = 32 whitepoint = 4062 color_pattern = "RGGB" active_area = [0, 0, 12, 0] crop_area = [10, 4, 22, 12] [cameras.color_matrix] D65 = [0.8512, -0.3211, -0.0787, -0.4167, 1.1966, 0.2487, -0.0638, 0.1288, 0.6054] rawler-0.7.1/data/cameras/pentax/k-s2.toml000064400000000000000000000005031046102023000164170ustar 00000000000000make = "RICOH IMAGING COMPANY, LTD." model = "PENTAX K-S2" clean_make = "Pentax" clean_model = "K-S2" #blackpoint = 16 whitepoint = 4079 color_pattern = "RGGB" active_area = [0, 0, 12, 0] crop_area = [10, 4, 22, 12] [cameras.color_matrix] D65 = [5.2900, -1.6627, -0.7529, -2.5443, 8.0936, 1.1071, -0.5585, 0.9879, 4.1775] rawler-0.7.1/data/cameras/pentax/k-x.toml000064400000000000000000000004551046102023000163500ustar 00000000000000make = "PENTAX" model = "PENTAX K-x" clean_make = "Pentax" clean_model = "K-x" #blackpoint = 48 whitepoint = 4095 color_pattern = "BGGR" active_area = [0, 0, 42, 0] crop_area = [10, 10, 54, 10] [cameras.color_matrix] D65 = [0.8843, -0.2837, -0.0625, -0.5025, 1.2644, 0.2668, -0.0411, 0.1234, 0.7410] rawler-0.7.1/data/cameras/pentax/k100d.toml000064400000000000000000000004731046102023000164700ustar 00000000000000make = "PENTAX Corporation" model = "PENTAX K100D" clean_make = "Pentax" clean_model = "K100D" #blackpoint = 128 whitepoint = 3950 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] [cameras.color_matrix] D65 = [1.1095, -0.3157, -0.1324, -0.8377, 1.5834, 0.2720, -0.1108, 0.0947, 1.1688] rawler-0.7.1/data/cameras/pentax/k100dsuper.toml000064400000000000000000000005071046102023000175450ustar 00000000000000make = "PENTAX Corporation" model = "PENTAX K100D Super" clean_make = "Pentax" clean_model = "K100D Super" #blackpoint = 127 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] [cameras.color_matrix] D65 = [1.1095, -0.3157, -0.1324, -0.8377, 1.5834, 0.2720, -0.1108, 0.0947, 1.1688] rawler-0.7.1/data/cameras/pentax/k10d.toml000064400000000000000000000004721046102023000164070ustar 00000000000000make = "PENTAX Corporation" model = "PENTAX K10D" clean_make = "Pentax" clean_model = "K10D" #blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 48, 16] crop_area = [8, 8, 56, 24] [cameras.color_matrix] D65 = [0.9566, -0.2863, -0.0803, -0.7170, 1.5172, 0.2112, -0.0818, 0.0803, 0.9705] rawler-0.7.1/data/cameras/pentax/k110d.toml000064400000000000000000000004731046102023000164710ustar 00000000000000make = "PENTAX Corporation" model = "PENTAX K110D" clean_make = "Pentax" clean_model = "K110D" #blackpoint = 127 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [16, 8, 16, 8] [cameras.color_matrix] D65 = [1.1095, -0.3157, -0.1324, -0.8377, 1.5834, 0.2720, -0.1108, 0.0947, 1.1688] rawler-0.7.1/data/cameras/pentax/k200d.toml000064400000000000000000000004561046102023000164720ustar 00000000000000make = "PENTAX" model = "PENTAX K200D" clean_make = "Pentax" clean_model = "K200D" #blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 40, 8] crop_area = [8, 8, 56, 24] [cameras.color_matrix] D65 = [0.9186, -0.2678, -0.0907, -0.8693, 1.6517, 0.2260, -0.1129, 0.1094, 0.8524] rawler-0.7.1/data/cameras/pentax/k20d.toml000064400000000000000000000004571046102023000164130ustar 00000000000000make = "PENTAX" model = "PENTAX K20D" clean_make = "Pentax" clean_model = "K20D" #blackpoint = 0 whitepoint = 4095 color_pattern = "BGGR" active_area = [0, 0, 176, 12] crop_area = [8, 8, 184, 24] [cameras.color_matrix] D65 = [0.9427, -0.2714, -0.0868, -0.7493, 1.6092, 0.1373, -0.2199, 0.3264, 0.7180] rawler-0.7.1/data/cameras/pentax/kf.toml000064400000000000000000000006101046102023000162420ustar 00000000000000make = "RICOH IMAGING COMPANY, LTD." model = "PENTAX KF" clean_make = "Ricoh" clean_model = "PENTAX KF" whitepoint = 16319 color_pattern = "RGGB" active_area = [58, 28, 0, 12] crop_area = [66, 32, 14, 32] [cameras.color_matrix] A = [0.9924, -0.4631, 0.0135, -0.4397, 1.2147, 0.2537, -0.0376, 0.0886, 0.6752] D65 = [0.8766, -0.3149, -0.0747, -0.3976, 1.1943, 0.2292, -0.0517, 0.1259, 0.5552] rawler-0.7.1/data/cameras/pentax/kp.toml000064400000000000000000000005041046102023000162560ustar 00000000000000make = "RICOH IMAGING COMPANY, LTD." model = "PENTAX KP" clean_make = "Pentax" clean_model = "KP" #blackpoint = 128 whitepoint = 16254 color_pattern = "RGGB" active_area = [54, 28, 30, 0] crop_area = [60, 44, 36, 16] [cameras.color_matrix] D65 = [0.8617, -0.3228, -0.1034, -0.4674, 1.2821, 0.2044, -0.0803, 0.1577, 0.5728] rawler-0.7.1/data/cameras/phase_one/h25.toml000064400000000000000000000006061046102023000167070ustar 00000000000000make = "Phase One A/S" model = "H 25" clean_make = "Phase One" clean_model = "H 25" #blackpoint = 1024 whitepoint = 65535 color_pattern = "GBRG" active_area = [28, 22, 12, 12] crop_area = [32, 26, 12, 12] [cameras.color_matrix] A = [0.3311, 0.0333, 0.0008, -0.7783, 1.6217, 0.1561, -0.1919, 0.3244, 0.8188] D65 = [0.2905, 0.0732, -0.0237, -0.8135, 1.6626, 0.1476, -0.3038, 0.4253, 0.7517] rawler-0.7.1/data/cameras/phase_one/iq140.toml000064400000000000000000000005451046102023000171510ustar 00000000000000make = "Phase One A/S" model = "IQ140" clean_make = "Phase One" clean_model = "IQ140" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" active_area = [36, 6, 16, 46] [cameras.color_matrix] A = [0.7756, 0.0244, -0.0761, -0.53, 1.2774, 0.2832, -0.0881, 0.2622, 0.5858] D65 = [0.8035, 0.0435, -0.0962, -0.6001, 1.3872, 0.232, -0.1159, 0.3065, 0.5434] rawler-0.7.1/data/cameras/phase_one/iq150.toml000064400000000000000000000004721046102023000171510ustar 00000000000000make = "Phase One A/S" model = "IQ150" clean_make = "Phase One" clean_model = "IQ150" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" active_area = [92, 108, 0, 0] [cameras.color_matrix] A = [0.5233, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.1869] Flash = [0.3984, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.7666] rawler-0.7.1/data/cameras/phase_one/iq180.toml000064400000000000000000000005501046102023000171510ustar 00000000000000make = "Phase One A/S" model = "IQ180" clean_make = "Phase One" clean_model = "IQ180" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" active_area = [36, 8, 16, 48] [cameras.color_matrix] A = [0.5644, 0.1137, -0.0804, -0.4702, 1.2262, 0.2753, -0.0636, 0.1861, 0.5419] D65 = [0.6294, 0.0686, -0.0712, -0.5435, 1.3417, 0.2211, -0.1006, 0.2435, 0.5042] rawler-0.7.1/data/cameras/phase_one/iq3_100mp.toml000064400000000000000000000005121046102023000177160ustar 00000000000000make = "Phase One A/S" model = "IQ3 100MP" clean_make = "Phase One" clean_model = "IQ3 100MP" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" active_area = [148, 120, 220, 24] [cameras.color_matrix] D55 = [0.3101, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.8063] D75 = [0.2423, 0.0, 0.0, 0.0, 0.9901, 0.0, 0.0, 0.0, 0.7989] rawler-0.7.1/data/cameras/phase_one/iq3_100mp_trichr.toml000064400000000000000000000005331046102023000212740ustar 00000000000000make = "Phase One A/S" model = "IQ3 100MP Trichr" clean_make = "Phase One" clean_model = "IQ3 100MP Trichr" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" active_area = [148, 120, 220, 24] [cameras.color_matrix] Flash = [0.4138, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.9769] Tungsten = [0.5184, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.1134] rawler-0.7.1/data/cameras/phase_one/iq4_150mp.toml000064400000000000000000000005561046102023000177340ustar 00000000000000make = "Phase One" model = "IQ4 150MP" clean_make = "Phase One" clean_model = "IQ4 150MP" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" active_area = [102, 106, 2, 2] [cameras.color_matrix] A = [0.7544, -0.3679, 0.0063, -0.4823, 1.2655, 0.2418, -0.0351, 0.0831, 0.6898] D65 = [0.6644, -0.2257, -0.0804, -0.6459, 1.4562, 0.2019, -0.1221, 0.1876, 0.6411] rawler-0.7.1/data/cameras/phase_one/ixm_100.toml000064400000000000000000000004311046102023000174620ustar 00000000000000make = "Phase One" model = "iXM-100" clean_make = "Phase One" clean_model = "iXM-100" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" active_area = [100, 104, 0, 0] [cameras.color_matrix] D65 = [0.8035, 0.0435, -0.0962, -0.6001, 1.3872, 0.2320, -0.1159, 0.3065, 0.5434] rawler-0.7.1/data/cameras/phase_one/ixm_rs150f.toml000064400000000000000000000004741046102023000202110ustar 00000000000000make = "Phase One" model = "iXM-RS150F" clean_make = "Phase One" clean_model = "iXM-RS150F" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" active_area = [100, 104, 0, 0] crop_area = [102, 106, 2, 2] [cameras.color_matrix] D65 = [0.8035, 0.0435, -0.0962, -0.6001, 1.3872, 0.2320, -0.1159, 0.3065, 0.5434] rawler-0.7.1/data/cameras/phase_one/ixu180.toml000064400000000000000000000004321046102023000173440ustar 00000000000000make = "Phase One A/S" model = "iXU180" clean_make = "Phase One" clean_model = "iXU180" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" active_area = [36, 8, 16, 48] [cameras.color_matrix] D65 = [0.8035, 0.0435, -0.0962, -0.6001, 1.3872, 0.2320, -0.1159, 0.3065, 0.5434] rawler-0.7.1/data/cameras/phase_one/ixu_rs1000_nir.toml000064400000000000000000000005141046102023000207710ustar 00000000000000make = "Phase One A/S" model = "iXU-RS1000 NIR" clean_make = "Phase One" clean_model = "iXU-RS1000 NIR" whitepoint = 65535 color_pattern = "RGGB" active_area = [148, 120, 220, 24] [cameras.color_matrix] # matrix not verified, but no other available D65 = [0.8035, 0.0435, -0.0962, -0.6001, 1.3872, 0.2320, -0.1159, 0.3065, 0.5434] rawler-0.7.1/data/cameras/phase_one/p20.toml000064400000000000000000000005531046102023000167130ustar 00000000000000make = "Phase One A/S" model = "P20+" clean_make = "Phase One A/S" clean_model = "P20+" #blackpoint = 0 whitepoint = 65535 color_pattern = "GRBG" active_area = [26, 20, 10, 10] [cameras.color_matrix] A = [0.3311, 0.0333, 0.0008, -0.7783, 1.6217, 0.1561, -0.1919, 0.3244, 0.8188] D65 = [0.2905, 0.0732, -0.0237, -0.8135, 1.6626, 0.1476, -0.3038, 0.4253, 0.7517] rawler-0.7.1/data/cameras/phase_one/p25.toml000064400000000000000000000006351046102023000167210ustar 00000000000000make = "Phase One A/S" model = "P25" clean_make = "Phase One A/S" clean_model = "P25" whitepoint = 65535 color_pattern = "GBRG" active_area = [26, 20, 10, 10] crop_area = [36, 31, 18, 21] model_aliases = [ ["P25+", "P25+"], ] [cameras.color_matrix] A = [0.3311, 0.0333, 0.0008, -0.7783, 1.6217, 0.1561, -0.1919, 0.3244, 0.8188] D65 = [0.2905, 0.0732, -0.0237, -0.8135, 1.6626, 0.1476, -0.3038, 0.4253, 0.7517] rawler-0.7.1/data/cameras/phase_one/p30.toml000064400000000000000000000005511046102023000167120ustar 00000000000000make = "Phase One A/S" model = "P30" clean_make = "Phase One A/S" clean_model = "P30" #blackpoint = 0 whitepoint = 65535 color_pattern = "GRBG" active_area = [40, 22, 20, 28] [cameras.color_matrix] A = [0.5667, -0.1528, 0.0568, -0.5993, 1.3742, 0.2468, -0.1825, 0.3327, 0.7711] D65 = [0.4516, -0.0244, -0.0036, -0.702, 1.4976, 0.2174, -0.3206, 0.467, 0.7087] rawler-0.7.1/data/cameras/phase_one/p45.toml000064400000000000000000000006341046102023000167220ustar 00000000000000make = "Phase One A/S" model = "P45" clean_make = "Phase One A/S" clean_model = "P45" whitepoint = 65535 color_pattern = "GRBG" active_area = [40, 22, 20, 28] crop_area = [56, 38, 36, 44] model_aliases = [ ["P45+", "P45+"], ] [cameras.color_matrix] A = [0.6469, -0.148, 0.0583, -0.513, 1.3435, 0.1832, -0.1503, 0.3446, 0.6389] D65 = [0.5053, -0.0024, -0.0117, -0.5685, 1.4077, 0.1703, -0.2619, 0.4491, 0.585] rawler-0.7.1/data/cameras/phase_one/p65.toml000064400000000000000000000005511046102023000167220ustar 00000000000000make = "Phase One A/S" model = "P65+" clean_make = "Phase One A/S" clean_model = "P65+" #blackpoint = 0 whitepoint = 65535 color_pattern = "RGGB" active_area = [36, 6, 16, 46] [cameras.color_matrix] A = [0.7756, 0.0244, -0.0761, -0.53, 1.2774, 0.2832, -0.0881, 0.2622, 0.5858] D65 = [0.8035, 0.0435, -0.0962, -0.6001, 1.3872, 0.2320, -0.1159, 0.3065, 0.5434] rawler-0.7.1/data/cameras/samsung/ex1.toml000064400000000000000000000005701046102023000165220ustar 00000000000000make = "SAMSUNG" model = "EX1" clean_make = "Samsung" clean_model = "EX1" #blackpoint = 0 whitepoint = 15600 color_pattern = "RGGB" active_area = [0, 2, 6, 18] crop_area = [16, 18, 24, 26] [cameras.color_matrix] A = [0.9379, -0.3215, -0.0445, -0.2366, 1.0377, 0.2308, -0.0233, 0.0843, 0.4835] D65 = [0.8898, -0.2498, -0.0994, -0.3144, 1.1328, 0.2066, -0.076, 0.1381, 0.4576] rawler-0.7.1/data/cameras/samsung/ex2f.toml000064400000000000000000000005731046102023000166740ustar 00000000000000make = "SAMSUNG" model = "EX2F" clean_make = "Samsung" clean_model = "EX2F" #blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 106, 12] crop_area = [44, 34, 132, 24] [cameras.color_matrix] A = [1.0403, -0.4669, 0.0771, -0.1188, 0.8362, 0.3373, 0.0179, 0.0636, 0.5147] D65 = [1.0648, -0.3897, -0.1055, -0.2022, 1.0573, 0.1668, -0.0492, 0.1611, 0.4742] rawler-0.7.1/data/cameras/samsung/nx1.toml000064400000000000000000000005721046102023000165350ustar 00000000000000make = "SAMSUNG" model = "NX1" clean_make = "Samsung" clean_model = "NX1" #blackpoint = 128 whitepoint = 16100 color_pattern = "GRBG" active_area = [0, 0, 16, 16] crop_area = [0, 0, 16, 16] [cameras.color_matrix] A = [1.3298, -0.6099, -0.0296, -0.5243, 1.6153, -0.1235, -0.0508, 0.122, 0.7758] D65 = [1.0686, -0.4042, -0.1052, -0.3595, 1.3238, 0.0276, -0.0464, 0.1259, 0.5931] rawler-0.7.1/data/cameras/samsung/nx100.toml000064400000000000000000000005721046102023000166750ustar 00000000000000make = "SAMSUNG" model = "NX100" clean_make = "Samsung" clean_model = "NX100" #blackpoint = 3 whitepoint = 3750 color_pattern = "BGGR" active_area = [8, 4, 8, 0] crop_area = [22, 14, 90, 54] [cameras.color_matrix] A = [1.1681, -0.4928, -0.0648, -0.5013, 1.3274, 0.1891, -0.0444, 0.1358, 0.9125] D65 = [1.0332, -0.3234, -0.1168, -0.6111, 1.4639, 0.152, -0.1352, 0.2647, 0.8331] rawler-0.7.1/data/cameras/samsung/nx1000.toml000064400000000000000000000006331046102023000167530ustar 00000000000000make = "SAMSUNG" model = "NX1000" clean_make = "Samsung" clean_model = "NX1000" #blackpoint = 0 whitepoint = 3750 color_pattern = "GRBG" active_area = [46, 2, 58, 48] crop_area = [81, 17, 79, 55] hints = ["little_endian"] [cameras.color_matrix] A = [0.7824, -0.3107, -0.0673, -0.4586, 1.2734, 0.2046, -0.0398, 0.1084, 0.6592] D65 = [0.6933, -0.2268, -0.0753, -0.4921, 1.3387, 0.1647, -0.0803, 0.1641, 0.6096] rawler-0.7.1/data/cameras/samsung/nx1100.toml000064400000000000000000000006321046102023000167530ustar 00000000000000make = "SAMSUNG" model = "NX1100" clean_make = "Samsung" clean_model = "NX1100" #blackpoint = 0 whitepoint = 3750 color_pattern = "GRBG" active_area = [46, 2, 58, 48] crop_area = [81, 17, 79, 55] hints = ["little_endian"] [cameras.color_matrix] A = [0.7824, -0.3107, -0.0673, -0.4586, 1.2734, 0.2046, -0.0398, 0.1084, 0.6592] D65 = [0.6933, -0.2268, -0.0753, -0.4921, 1.3387, 0.1647, -0.0803, 0.1641, 0.6096] rawler-0.7.1/data/cameras/samsung/nx20.toml000064400000000000000000000006261046102023000166160ustar 00000000000000make = "SAMSUNG" model = "NX20" clean_make = "Samsung" clean_model = "NX20" #blackpoint = 0 whitepoint = 3750 color_pattern = "GRBG" active_area = [46, 2, 58, 48] crop_area = [81, 17, 79, 55] hints = ["little_endian"] [cameras.color_matrix] A = [0.7824, -0.3107, -0.0673, -0.4586, 1.2734, 0.2046, -0.0398, 0.1084, 0.6592] D65 = [0.6933, -0.2268, -0.0753, -0.4921, 1.3387, 0.1647, -0.0803, 0.1641, 0.6096] rawler-0.7.1/data/cameras/samsung/nx200.toml000064400000000000000000000006301046102023000166710ustar 00000000000000make = "SAMSUNG" model = "NX200" clean_make = "Samsung" clean_model = "NX200" #blackpoint = 0 whitepoint = 3750 color_pattern = "GRBG" active_area = [46, 2, 58, 48] crop_area = [81, 17, 79, 55] hints = ["little_endian"] [cameras.color_matrix] A = [0.7824, -0.3107, -0.0673, -0.4586, 1.2734, 0.2046, -0.0398, 0.1084, 0.6592] D65 = [0.6933, -0.2268, -0.0753, -0.4921, 1.3387, 0.1647, -0.0803, 0.1641, 0.6096] rawler-0.7.1/data/cameras/samsung/nx2000.toml000064400000000000000000000005721046102023000167560ustar 00000000000000make = "SAMSUNG" model = "NX2000" clean_make = "Samsung" clean_model = "NX2000" #blackpoint = 0 whitepoint = 4095 color_pattern = "GRBG" active_area = [0, 0, 0, 18] crop_area = [52, 28, 12, 38] [cameras.color_matrix] A = [0.8306, -0.3396, -0.0291, -0.4093, 1.1851, 0.254, -0.04, 0.1133, 0.5868] D65 = [0.7557, -0.2522, -0.0739, -0.4679, 1.2949, 0.1894, -0.084, 0.1777, 0.5311] rawler-0.7.1/data/cameras/samsung/nx210.toml000064400000000000000000000006301046102023000166720ustar 00000000000000make = "SAMSUNG" model = "NX210" clean_make = "Samsung" clean_model = "NX210" #blackpoint = 0 whitepoint = 3750 color_pattern = "GRBG" active_area = [46, 2, 58, 48] crop_area = [81, 17, 79, 55] hints = ["little_endian"] [cameras.color_matrix] A = [0.7824, -0.3107, -0.0673, -0.4586, 1.2734, 0.2046, -0.0398, 0.1084, 0.6592] D65 = [0.6933, -0.2268, -0.0753, -0.4921, 1.3387, 0.1647, -0.0803, 0.1641, 0.6096] rawler-0.7.1/data/cameras/samsung/nx30.toml000064400000000000000000000005661046102023000166220ustar 00000000000000make = "SAMSUNG" model = "NX30" clean_make = "Samsung" clean_model = "NX30" #blackpoint = 0 whitepoint = 4095 color_pattern = "GRBG" active_area = [0, 0, 0, 18] crop_area = [52, 28, 22, 38] [cameras.color_matrix] A = [0.8306, -0.3396, -0.0291, -0.4093, 1.1851, 0.254, -0.04, 0.1133, 0.5868] D65 = [0.7557, -0.2522, -0.0739, -0.4679, 1.2949, 0.1894, -0.084, 0.1777, 0.5311] rawler-0.7.1/data/cameras/samsung/nx300.toml000064400000000000000000000005701046102023000166750ustar 00000000000000make = "SAMSUNG" model = "NX300" clean_make = "Samsung" clean_model = "NX300" #blackpoint = 0 whitepoint = 4095 color_pattern = "GRBG" active_area = [0, 0, 0, 18] crop_area = [52, 28, 22, 38] [cameras.color_matrix] A = [0.8306, -0.3396, -0.0291, -0.4093, 1.1851, 0.254, -0.04, 0.1133, 0.5868] D65 = [0.7557, -0.2522, -0.0739, -0.4679, 1.2949, 0.1894, -0.084, 0.1777, 0.5311] rawler-0.7.1/data/cameras/samsung/nx3000.toml000064400000000000000000000005751046102023000167620ustar 00000000000000make = "SAMSUNG" model = "NX3000" clean_make = "Samsung" clean_model = "NX3000" #blackpoint = 0 whitepoint = 4095 color_pattern = "GRBG" active_area = [64, 18, 32, 24] crop_area = [96, 42, 32, 24] [cameras.color_matrix] A = [0.9174, -0.4272, -0.005, -0.4962, 1.3161, 0.1969, -0.0507, 0.1152, 0.6086] D65 = [0.806, -0.2933, -0.0761, -0.4504, 1.289, 0.1762, -0.063, 0.1489, 0.5227] rawler-0.7.1/data/cameras/samsung/nx300m.toml000064400000000000000000000005721046102023000170540ustar 00000000000000make = "SAMSUNG" model = "NX300M" clean_make = "Samsung" clean_model = "NX300M" #blackpoint = 0 whitepoint = 4095 color_pattern = "GRBG" active_area = [0, 0, 0, 18] crop_area = [52, 28, 22, 38] [cameras.color_matrix] A = [0.8306, -0.3396, -0.0291, -0.4093, 1.1851, 0.254, -0.04, 0.1133, 0.5868] D65 = [0.7557, -0.2522, -0.0739, -0.4679, 1.2949, 0.1894, -0.084, 0.1777, 0.5311] rawler-0.7.1/data/cameras/samsung/nx3300.toml000064400000000000000000000005751046102023000167650ustar 00000000000000make = "SAMSUNG" model = "NX3300" clean_make = "Samsung" clean_model = "NX3300" #blackpoint = 0 whitepoint = 4095 color_pattern = "GRBG" active_area = [64, 18, 32, 24] crop_area = [96, 42, 32, 24] [cameras.color_matrix] A = [0.9174, -0.4272, -0.005, -0.4962, 1.3161, 0.1969, -0.0507, 0.1152, 0.6086] D65 = [0.806, -0.2933, -0.0761, -0.4504, 1.289, 0.1762, -0.063, 0.1489, 0.5227] rawler-0.7.1/data/cameras/samsung/nx500.toml000064400000000000000000000005741046102023000167030ustar 00000000000000make = "SAMSUNG" model = "NX500" clean_make = "Samsung" clean_model = "NX500" #blackpoint = 0 whitepoint = 16100 color_pattern = "GRBG" active_area = [0, 0, 16, 16] crop_area = [0, 0, 16, 16] [cameras.color_matrix] A = [1.3298, -0.6099, -0.0296, -0.5243, 1.6153, -0.1235, -0.0508, 0.122, 0.7758] D65 = [1.0686, -0.4042, -0.1052, -0.3595, 1.3238, 0.0276, -0.0464, 0.1259, 0.5931] rawler-0.7.1/data/cameras/samsung/nx_mini.toml000064400000000000000000000006031046102023000174630ustar 00000000000000make = "SAMSUNG" model = "NX mini" clean_make = "Samsung" clean_model = "NX mini" #blackpoint = 0 whitepoint = 4000 color_pattern = "RGGB" active_area = [120, 28, 48, 10] crop_area = [132, 40, 60, 22] [cameras.color_matrix] A = [0.5555, -0.1798, -0.0086, -0.3853, 1.1227, 0.3016, -0.0553, 0.1311, 0.6446] D65 = [0.5222, -0.1196, -0.055, -0.654, 1.4649, 0.2009, -0.1666, 0.2819, 0.5657] rawler-0.7.1/data/cameras/samsung/wb2000.toml000064400000000000000000000006251046102023000167400ustar 00000000000000make = "SAMSUNG" model = "WB2000" clean_make = "Samsung" clean_model = "WB2000" #blackpoint = 0 whitepoint = 3700 color_pattern = "RGGB" active_area = [0, 2, 10, 1] crop_area = [36, 368, 44, 365] hints = ["little_endian"] [cameras.color_matrix] A = [1.2389, -0.4375, -0.038, -0.0566, 0.8728, 0.2203, 0.0308, 0.1234, 0.4957] D65 = [1.2093, -0.3557, -0.1155, -0.1, 0.9534, 0.1733, -0.0022, 0.1787, 0.4576] rawler-0.7.1/data/cameras/sony/a1.toml000064400000000000000000000005111046102023000156340ustar 00000000000000make = "SONY" model = "ILCE-1" clean_make = "Sony" clean_model = "ILCE-1" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.8933, -0.4409, 0.02, -0.4637, 1.2364, 0.2554, -0.0304, 0.0803, 0.7616] D65 = [0.8161, -0.2947, -0.0739, -0.4811, 1.2668, 0.2389, -0.0437, 0.1229, 0.6524] rawler-0.7.1/data/cameras/sony/a100.toml000064400000000000000000000006001046102023000157730ustar 00000000000000make = "SONY" model = "DSLR-A100" clean_make = "Sony" clean_model = "DSLR-A100" blackpoint = 0 whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [0, 4, 0, 4] bps = 8 [cameras.color_matrix] A = [1.0336, -0.3752, -0.0202, -0.7347, 1.4918, 0.2626, -0.0433, 0.0478, 0.7015] D65 = [0.9437, -0.2812, -0.0774, -0.8405, 1.6215, 0.2291, -0.0709, 0.0596, 0.7181] rawler-0.7.1/data/cameras/sony/a200.toml000064400000000000000000000006221046102023000160000ustar 00000000000000make = "SONY" model = "DSLR-A200" clean_make = "Sony" clean_model = "DSLR-A200" ##blackpoint = 0 #whitepoint = 4095 color_pattern = "RGGB" #correct? TODO active_area = [0, 0, 0, 0] crop_area = [4, 8, 4, 8] bps = 8 [cameras.color_matrix] A = [1.1085, -0.4387, -0.0219, -0.7253, 1.4836, 0.2615, -0.0415, 0.0458, 0.6948] D65 = [0.9847, -0.3091, -0.0929, -0.8485, 1.6346, 0.2225, -0.0714, 0.0595, 0.7103] rawler-0.7.1/data/cameras/sony/a230.toml000064400000000000000000000006031046102023000160020ustar 00000000000000make = "SONY" model = "DSLR-A230" clean_make = "Sony" clean_model = "DSLR-A230" ##blackpoint = 0 #whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 8, 4, 8] bps = 8 [cameras.color_matrix] A = [1.1085, -0.4387, -0.0219, -0.7253, 1.4836, 0.2615, -0.0415, 0.0458, 0.6948] D65 = [0.9847, -0.3091, -0.0929, -0.8485, 1.6346, 0.2225, -0.0714, 0.0595, 0.7103] rawler-0.7.1/data/cameras/sony/a290.toml000064400000000000000000000006031046102023000160100ustar 00000000000000make = "SONY" model = "DSLR-A290" clean_make = "Sony" clean_model = "DSLR-A290" ##blackpoint = 0 #whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 8, 4, 8] bps = 8 [cameras.color_matrix] A = [0.6459, -0.1991, -0.0211, -0.7683, 1.4944, 0.2987, -0.0408, 0.0428, 0.7224] D65 = [0.6038, -0.1484, -0.0579, -0.9145, 1.6746, 0.2512, -0.0875, 0.0746, 0.7218] rawler-0.7.1/data/cameras/sony/a300.toml000064400000000000000000000005731046102023000160060ustar 00000000000000make = "SONY" model = "DSLR-A300" clean_make = "Sony" clean_model = "DSLR-A300" ##blackpoint = 0 #whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 8, 4, 8] [cameras.color_matrix] A = [1.1085, -0.4387, -0.0219, -0.7253, 1.4836, 0.2615, -0.0415, 0.0458, 0.6948] D65 = [0.9847, -0.3091, -0.0929, -0.8485, 1.6346, 0.2225, -0.0714, 0.0595, 0.7103] rawler-0.7.1/data/cameras/sony/a3000.toml000064400000000000000000000006101046102023000160560ustar 00000000000000make = "SONY" model = "ILCE-3000" clean_make = "Sony" clean_model = "ILCE-3000" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 34, 0] crop_area = [8, 12, 40, 12] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/a33.toml000064400000000000000000000006021046102023000157220ustar 00000000000000make = "SONY" model = "SLT-A33" clean_make = "Sony" clean_model = "SLT-A33" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] bps = 8 [cameras.color_matrix] A = [0.5988, -0.1393, -0.0128, -0.4585, 1.1727, 0.3265, -0.0652, 0.1446, 0.7403] D65 = [0.6069, -0.1221, -0.0366, -0.5221, 1.2779, 0.2734, -0.1024, 0.2066, 0.6834] rawler-0.7.1/data/cameras/sony/a330.toml000064400000000000000000000006031046102023000160030ustar 00000000000000make = "SONY" model = "DSLR-A330" clean_make = "Sony" clean_model = "DSLR-A330" ##blackpoint = 0 #whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 8, 4, 8] bps = 8 [cameras.color_matrix] A = [1.1085, -0.4387, -0.0219, -0.7253, 1.4836, 0.2615, -0.0415, 0.0458, 0.6948] D65 = [0.9847, -0.3091, -0.0929, -0.8485, 1.6346, 0.2225, -0.0714, 0.0595, 0.7103] rawler-0.7.1/data/cameras/sony/a35.toml000064400000000000000000000005771046102023000157370ustar 00000000000000make = "SONY" model = "SLT-A35" clean_make = "Sony" clean_model = "SLT-A35" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] bps = 8 [cameras.color_matrix] A = [0.6247, -0.2128, -0.011, -0.3884, 1.0696, 0.3696, -0.0388, 0.0927, 0.7231] D65 = [0.5986, -0.1618, -0.0415, -0.4557, 1.182, 0.312, -0.0681, 0.1404, 0.6971] rawler-0.7.1/data/cameras/sony/a350.toml000064400000000000000000000006031046102023000160050ustar 00000000000000make = "SONY" model = "DSLR-A350" clean_make = "Sony" clean_model = "DSLR-A350" ##blackpoint = 0 #whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 8, 4, 8] bps = 8 [cameras.color_matrix] A = [0.6459, -0.1991, -0.0211, -0.7683, 1.4944, 0.2987, -0.0408, 0.0428, 0.7224] D65 = [0.6038, -0.1484, -0.0579, -0.9145, 1.6746, 0.2512, -0.0875, 0.0746, 0.7218] rawler-0.7.1/data/cameras/sony/a3500.toml000064400000000000000000000006101046102023000160630ustar 00000000000000make = "SONY" model = "ILCE-3500" clean_make = "Sony" clean_model = "ILCE-3500" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 34, 0] crop_area = [6, 12, 42, 12] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/a37.toml000064400000000000000000000006011046102023000157250ustar 00000000000000make = "SONY" model = "SLT-A37" clean_make = "Sony" clean_model = "SLT-A37" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 6, 12, 6] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/a380.toml000064400000000000000000000006031046102023000160100ustar 00000000000000make = "SONY" model = "DSLR-A380" clean_make = "Sony" clean_model = "DSLR-A380" ##blackpoint = 0 #whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 8, 4, 8] bps = 8 [cameras.color_matrix] A = [0.6459, -0.1991, -0.0211, -0.7683, 1.4944, 0.2987, -0.0408, 0.0428, 0.7224] D65 = [0.6038, -0.1484, -0.0579, -0.9145, 1.6746, 0.2512, -0.0875, 0.0746, 0.7218] rawler-0.7.1/data/cameras/sony/a390.toml000064400000000000000000000006031046102023000160110ustar 00000000000000make = "SONY" model = "DSLR-A390" clean_make = "Sony" clean_model = "DSLR-A390" ##blackpoint = 0 #whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 8, 4, 8] bps = 8 [cameras.color_matrix] A = [0.6459, -0.1991, -0.0211, -0.7683, 1.4944, 0.2987, -0.0408, 0.0428, 0.7224] D65 = [0.6038, -0.1484, -0.0579, -0.9145, 1.6746, 0.2512, -0.0875, 0.0746, 0.7218] rawler-0.7.1/data/cameras/sony/a450.toml000064400000000000000000000006021046102023000160050ustar 00000000000000make = "SONY" model = "DSLR-A450" clean_make = "Sony" clean_model = "DSLR-A450" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] bps = 8 [cameras.color_matrix] A = [0.7702, -0.3694, 0.0411, -0.4124, 1.1197, 0.337, -0.0219, 0.0739, 0.7934] D65 = [0.495, -0.058, -0.0103, -0.5228, 1.2542, 0.3029, -0.0709, 0.1435, 0.7371] rawler-0.7.1/data/cameras/sony/a500.toml000064400000000000000000000006041046102023000160030ustar 00000000000000make = "SONY" model = "DSLR-A500" clean_make = "Sony" clean_model = "DSLR-A500" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 7, 8, 3] bps = 8 [cameras.color_matrix] A = [0.9548, -0.5128, 0.0467, -0.4471, 1.1739, 0.3117, -0.0177, 0.0673, 0.832] D65 = [0.6046, -0.1127, -0.0278, -0.5574, 1.3076, 0.2786, -0.0691, 0.1419, 0.7625] rawler-0.7.1/data/cameras/sony/a5000.toml000064400000000000000000000006101046102023000160600ustar 00000000000000make = "SONY" model = "ILCE-5000" clean_make = "Sony" clean_model = "ILCE-5000" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 34, 0] crop_area = [8, 12, 40, 12] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/a5100.toml000064400000000000000000000006111046102023000160620ustar 00000000000000make = "SONY" model = "ILCE-5100" clean_make = "Sony" clean_model = "ILCE-5100" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 26, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/a55.toml000064400000000000000000000006631046102023000157350ustar 00000000000000make = "SONY" model = "SLT-A55" clean_make = "Sony" clean_model = "SLT-A55" model_aliases = [ ["SLT-A55V", "SLT-A55V"], ] ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] bps = 8 [cameras.color_matrix] A = [0.6031, -0.178, -0.0178, -0.4219, 1.1316, 0.3336, -0.0501, 0.1133, 0.7046] D65 = [0.5932, -0.1492, -0.0411, -0.4813, 1.2285, 0.2856, -0.0741, 0.1524, 0.6739] rawler-0.7.1/data/cameras/sony/a550.toml000064400000000000000000000006021046102023000160060ustar 00000000000000make = "SONY" model = "DSLR-A550" clean_make = "Sony" clean_model = "DSLR-A550" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] bps = 8 [cameras.color_matrix] A = [0.7702, -0.3694, 0.0411, -0.4124, 1.1197, 0.337, -0.0219, 0.0739, 0.7934] D65 = [0.495, -0.058, -0.0103, -0.5228, 1.2542, 0.3029, -0.0709, 0.1435, 0.7371] rawler-0.7.1/data/cameras/sony/a560.toml000064400000000000000000000006021046102023000160070ustar 00000000000000make = "SONY" model = "DSLR-A560" clean_make = "Sony" clean_model = "DSLR-A560" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] bps = 8 [cameras.color_matrix] A = [0.7702, -0.3694, 0.0411, -0.4124, 1.1197, 0.337, -0.0219, 0.0739, 0.7934] D65 = [0.495, -0.058, -0.0103, -0.5228, 1.2542, 0.3029, -0.0709, 0.1435, 0.7371] rawler-0.7.1/data/cameras/sony/a57.toml000064400000000000000000000006011046102023000157270ustar 00000000000000make = "SONY" model = "SLT-A57" clean_make = "Sony" clean_model = "SLT-A57" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 6, 12, 6] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/a58.toml000064400000000000000000000006041046102023000157330ustar 00000000000000make = "SONY" model = "SLT-A58" clean_make = "Sony" clean_model = "SLT-A58" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 36, 0] crop_area = [6, 12, 42, 12] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/a580.toml000064400000000000000000000006111046102023000160110ustar 00000000000000make = "SONY" model = "DSLR-A580" clean_make = "Sony" clean_model = "DSLR-A580" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 2, 2] crop_area = [8, 260, 8, 260] bps = 8 [cameras.color_matrix] A = [0.6031, -0.178, -0.0178, -0.4219, 1.1316, 0.3336, -0.0501, 0.1133, 0.7046] D65 = [0.5932, -0.1492, -0.0411, -0.4813, 1.2285, 0.2856, -0.0741, 0.1524, 0.6739] rawler-0.7.1/data/cameras/sony/a6000.toml000064400000000000000000000006111046102023000160620ustar 00000000000000make = "SONY" model = "ILCE-6000" clean_make = "Sony" clean_model = "ILCE-6000" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 28, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/a6001.toml000064400000000000000000000006111046102023000160630ustar 00000000000000make = "SONY" model = "ILCE-6001" clean_make = "Sony" clean_model = "ILCE-6001" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 28, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/a6100.toml000064400000000000000000000006101046102023000160620ustar 00000000000000make = "SONY" model = "ILCE-6100" clean_make = "SONY" clean_model = "ILCE-6100" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.921, -0.4777, 0.0345, -0.4492, 1.3117, 0.1471, -0.0345, 0.0879, 0.6708] D65 = [0.7657, -0.2847, -0.0607, -0.4083, 1.1966, 0.2389, -0.0684, 0.1418, 0.5844] rawler-0.7.1/data/cameras/sony/a6300.toml000064400000000000000000000006111046102023000160650ustar 00000000000000make = "SONY" model = "ILCE-6300" clean_make = "SONY" clean_model = "ILCE-6300" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.6502, -0.2407, 0.0023, -0.3899, 1.1688, 0.2511, -0.0469, 0.1068, 0.6781] D65 = [0.5973, -0.1695, -0.0419, -0.3826, 1.1797, 0.2293, -0.0639, 0.1398, 0.5789] rawler-0.7.1/data/cameras/sony/a6400.toml000064400000000000000000000006101046102023000160650ustar 00000000000000make = "SONY" model = "ILCE-6400" clean_make = "SONY" clean_model = "ILCE-6400" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.921, -0.4777, 0.0345, -0.4492, 1.3117, 0.1471, -0.0345, 0.0879, 0.6708] D65 = [0.7657, -0.2847, -0.0607, -0.4083, 1.1966, 0.2389, -0.0684, 0.1418, 0.5844] rawler-0.7.1/data/cameras/sony/a65.toml000064400000000000000000000006701046102023000157340ustar 00000000000000make = "SONY" model = "SLT-A65" clean_make = "Sony" clean_model = "SLT-A65" model_aliases = [ ["SLT-A65V", "SLT-A65V"], ] ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 30, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.5644, -0.1547, -0.0028, -0.4237, 1.1032, 0.3701, -0.046, 0.1056, 0.7676] D65 = [0.5491, -0.1192, -0.0363, -0.4951, 1.2342, 0.2948, -0.0911, 0.1722, 0.7192] rawler-0.7.1/data/cameras/sony/a6500.toml000064400000000000000000000006111046102023000160670ustar 00000000000000make = "SONY" model = "ILCE-6500" clean_make = "SONY" clean_model = "ILCE-6500" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.6502, -0.2407, 0.0023, -0.3899, 1.1688, 0.2511, -0.0469, 0.1068, 0.6781] D65 = [0.5973, -0.1695, -0.0419, -0.3826, 1.1797, 0.2293, -0.0639, 0.1398, 0.5789] rawler-0.7.1/data/cameras/sony/a6600.toml000064400000000000000000000005201046102023000160670ustar 00000000000000make = "SONY" model = "ILCE-6600" clean_make = "SONY" clean_model = "ILCE-6600" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.921, -0.4777, 0.0345, -0.4492, 1.3117, 0.1471, -0.0345, 0.0879, 0.6708] D65 = [0.7657, -0.2847, -0.0607, -0.4083, 1.1966, 0.2389, -0.0684, 0.1418, 0.5844] rawler-0.7.1/data/cameras/sony/a6700.toml000064400000000000000000000004441046102023000160750ustar 00000000000000make = "SONY" model = "ILCE-6700" clean_make = "Sony" clean_model = "ILCE-6700" color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.793, -0.406, 0.0417, -0.374, 1.1119, 0.3015, -0.0202, 0.0741, 0.6896] D65 = [0.6972, -0.2408, -0.06, -0.433, 1.2101, 0.2515, -0.0388, 0.1277, 0.5847] rawler-0.7.1/data/cameras/sony/a68.toml000064400000000000000000000006021046102023000157320ustar 00000000000000make = "SONY" model = "ILCA-68" clean_make = "Sony" clean_model = "ILCA-68" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 32, 0] crop_area = [8, 8, 40, 8] bps = 8 [cameras.color_matrix] A = [0.6746, -0.2409, -0.0219, -0.4896, 1.243, 0.2776, -0.0553, 0.1083, 0.7198] D65 = [0.6435, -0.1903, -0.0536, -0.4722, 1.2449, 0.255, -0.0663, 0.1363, 0.6517] rawler-0.7.1/data/cameras/sony/a7.toml000064400000000000000000000006041046102023000156450ustar 00000000000000make = "SONY" model = "ILCE-7" clean_make = "Sony" clean_model = "ILCE-7" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 26, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.7491, -0.3027, 0.0351, -0.4231, 1.1579, 0.3031, -0.0818, 0.1721, 0.7466] D65 = [0.5271, -0.0712, -0.0347, -0.6153, 1.3653, 0.2763, -0.1601, 0.2366, 0.7242] rawler-0.7.1/data/cameras/sony/a700.toml000064400000000000000000000005761046102023000160150ustar 00000000000000make = "SONY" model = "DSLR-A700" clean_make = "Sony" clean_model = "DSLR-A700" ##blackpoint = 512 #whitepoint = 16383 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 4, 12, 4] [cameras.color_matrix] A = [0.615, -0.1189, -0.0137, -0.7291, 1.4699, 0.2826, -0.1103, 0.1608, 0.7414] D65 = [0.5775, -0.0805, -0.0359, -0.8573, 1.6294, 0.2391, -0.1943, 0.2342, 0.7249] rawler-0.7.1/data/cameras/sony/a77.toml000064400000000000000000000006701046102023000157370ustar 00000000000000make = "SONY" model = "SLT-A77" clean_make = "Sony" clean_model = "SLT-A77" model_aliases = [ ["SLT-A77V", "SLT-A77V"], ] ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 28, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.5644, -0.1547, -0.0028, -0.4237, 1.1032, 0.3701, -0.046, 0.1056, 0.7676] D65 = [0.5491, -0.1192, -0.0363, -0.4951, 1.2342, 0.2948, -0.0911, 0.1722, 0.7192] rawler-0.7.1/data/cameras/sony/a77m2.toml000064400000000000000000000006101046102023000161700ustar 00000000000000make = "SONY" model = "ILCA-77M2" clean_make = "Sony" clean_model = "ILCA-77M2" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 26, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.6425, -0.2411, 0.0035, -0.3975, 1.1576, 0.2736, -0.0454, 0.1038, 0.6909] D65 = [0.5991, -0.1732, -0.0443, -0.41, 1.1989, 0.2381, -0.0704, 0.1467, 0.5992] rawler-0.7.1/data/cameras/sony/a7c.toml000064400000000000000000000006051046102023000160110ustar 00000000000000make = "SONY" model = "ILCE-7C" clean_make = "Sony" clean_model = "ILCE-7C" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.8664, -0.4056, 0.0403, -0.4565, 1.2378, 0.2453, -0.0301, 0.0889, 0.7157] D65 = [0.7374, -0.2389, -0.0551, -0.5435, 1.3162, 0.2519, -0.1006, 0.1795, 0.6552] rawler-0.7.1/data/cameras/sony/a7cm2.toml000064400000000000000000000005031046102023000162450ustar 00000000000000make = "SONY" model = "ILCE-7CM2" clean_make = "Sony" clean_model = "ILCE-7CM2" color_pattern = "RGGB" active_area = [0, 0, 0, 0] bps = 8 [cameras.color_matrix] A = [0.8784, -0.4791, 0.1177, -0.3468, 1.0693, 0.3213, 0.0009, 0.0507, 0.7395] D65 = [0.746, -0.2365, -0.0588, -0.5687, 1.3442, 0.2474, -0.0624, 0.1156, 0.6584] rawler-0.7.1/data/cameras/sony/a7cr.toml000064400000000000000000000005011046102023000161660ustar 00000000000000make = "SONY" model = "ILCE-7CR" clean_make = "Sony" clean_model = "ILCE-7CR" color_pattern = "RGGB" active_area = [0, 0, 0, 0] bps = 8 [cameras.color_matrix] A = [0.9185, -0.4857, 0.0505, -0.3651, 1.1061, 0.2982, -0.0161, 0.0698, 0.6769] D65 = [0.82, -0.2976, -0.0719, -0.4296, 1.2053, 0.2532, -0.0429, 0.1282, 0.5774] rawler-0.7.1/data/cameras/sony/a7m2.toml000064400000000000000000000006101046102023000161010ustar 00000000000000make = "SONY" model = "ILCE-7M2" clean_make = "Sony" clean_model = "ILCE-7M2" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 26, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.7491, -0.3027, 0.0351, -0.4231, 1.1579, 0.3031, -0.0818, 0.1721, 0.7466] D65 = [0.5271, -0.0712, -0.0347, -0.6153, 1.3653, 0.2763, -0.1601, 0.2366, 0.7242] rawler-0.7.1/data/cameras/sony/a7m3.toml000064400000000000000000000006071046102023000161100ustar 00000000000000make = "SONY" model = "ILCE-7M3" clean_make = "Sony" clean_model = "ILCE-7M3" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.8664, -0.4056, 0.0403, -0.4565, 1.2378, 0.2453, -0.0301, 0.0889, 0.7157] D65 = [0.7374, -0.2389, -0.0551, -0.5435, 1.3162, 0.2519, -0.1006, 0.1795, 0.6552] rawler-0.7.1/data/cameras/sony/a7m4.toml000064400000000000000000000004321046102023000161050ustar 00000000000000make = "SONY" model = "ILCE-7M4" clean_make = "Sony" clean_model = "ILCE-7M4" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] bps = 8 [cameras.color_matrix] D65 = [0.7374, -0.2389, -0.0551, -0.5435, 1.3162, 0.2519, -0.1006, 0.1795, 0.6552] rawler-0.7.1/data/cameras/sony/a7r.toml000064400000000000000000000006011046102023000160240ustar 00000000000000make = "SONY" model = "ILCE-7R" clean_make = "Sony" clean_model = "ILCE-7R" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 26, 0] crop_area = [4, 4, 28, 4] bps = 8 [cameras.color_matrix] A = [0.7216, -0.2921, 0.035, -0.4204, 1.1461, 0.3143, -0.0767, 0.1485, 0.7418] D65 = [0.4913, -0.0541, -0.0202, -0.613, 1.3513, 0.2906, -0.1564, 0.2151, 0.7183] rawler-0.7.1/data/cameras/sony/a7rm2.toml000064400000000000000000000006051046102023000162670ustar 00000000000000make = "SONY" model = "ILCE-7RM2" clean_make = "Sony" clean_model = "ILCE-7RM2" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 32, 0] crop_area = [8, 8, 40, 8] bps = 8 [cameras.color_matrix] A = [0.6985, -0.2168, -0.0419, -0.5016, 1.3246, 0.1928, -0.0408, 0.0981, 0.7177] D65 = [0.6629, -0.19, -0.0483, -0.4618, 1.2349, 0.255, -0.0622, 0.1381, 0.6514] rawler-0.7.1/data/cameras/sony/a7rm3.toml000064400000000000000000000005161046102023000162710ustar 00000000000000make = "SONY" model = "ILCE-7RM3" clean_make = "Sony" clean_model = "ILCE-7RM3" ##blackpoint = 512 #whitepoint = 16380 color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.7683, -0.3276, 0.0299, -0.363, 1.0892, 0.3161, -0.0162, 0.0671, 0.7133] D65 = [0.664, -0.1847, -0.0503, -0.5238, 1.301, 0.2474, -0.0993, 0.1673, 0.6527] rawler-0.7.1/data/cameras/sony/a7rm3a.toml000064400000000000000000000005201046102023000164250ustar 00000000000000make = "SONY" model = "ILCE-7RM3A" clean_make = "Sony" clean_model = "ILCE-7RM3A" ##blackpoint = 512 #whitepoint = 16380 color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.7683, -0.3276, 0.0299, -0.363, 1.0892, 0.3161, -0.0162, 0.0671, 0.7133] D65 = [0.664, -0.1847, -0.0503, -0.5238, 1.301, 0.2474, -0.0993, 0.1673, 0.6527] rawler-0.7.1/data/cameras/sony/a7rm4.toml000064400000000000000000000006061046102023000162720ustar 00000000000000make = "SONY" model = "ILCE-7RM4" clean_make = "Sony" clean_model = "ILCE-7RM4" ##blackpoint = 512 #whitepoint = 16380 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [32, 20, 64, 20] bps = 8 [cameras.color_matrix] A = [0.9054, -0.4504, 0.0215, -0.4751, 1.2611, 0.2388, -0.0296, 0.0802, 0.6816] D65 = [0.7662, -0.2686, -0.066, -0.524, 1.2965, 0.253, -0.0796, 0.1508, 0.6167] rawler-0.7.1/data/cameras/sony/a7rm4a.toml000064400000000000000000000005201046102023000164260ustar 00000000000000make = "SONY" model = "ILCE-7RM4A" clean_make = "Sony" clean_model = "ILCE-7RM4A" ##blackpoint = 512 #whitepoint = 16380 color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.9054, -0.4504, 0.0215, -0.4751, 1.2611, 0.2388, -0.0296, 0.0802, 0.6816] D65 = [0.7662, -0.2686, -0.066, -0.524, 1.2965, 0.253, -0.0796, 0.1508, 0.6167] rawler-0.7.1/data/cameras/sony/a7rm5.toml000064400000000000000000000004501046102023000162700ustar 00000000000000make = "SONY" model = "ILCE-7RM5" clean_make = "Sony" clean_model = "ILCE-7RM5" color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.9185, -0.4857, 0.0505, -0.3651, 1.1061, 0.2982, -0.0161, 0.0698, 0.6769] D65 = [0.82, -0.2976, -0.0719, -0.4296, 1.2053, 0.2532, -0.0429, 0.1282, 0.5774] rawler-0.7.1/data/cameras/sony/a7s.toml000064400000000000000000000006041046102023000160300ustar 00000000000000make = "SONY" model = "ILCE-7S" clean_make = "Sony" clean_model = "ILCE-7S" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 32, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.6263, -0.1964, 0.0102, -0.4375, 1.2428, 0.2171, -0.066, 0.1559, 0.7146] D65 = [0.5838, -0.143, -0.0246, -0.3497, 1.1477, 0.2297, -0.0748, 0.1885, 0.5778] rawler-0.7.1/data/cameras/sony/a7sm2.toml000064400000000000000000000006041046102023000162670ustar 00000000000000make = "SONY" model = "ILCE-7SM2" clean_make = "Sony" clean_model = "ILCE-7SM2" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 40, 8] bps = 8 [cameras.color_matrix] A = [0.6263, -0.1964, 0.0102, -0.4375, 1.2428, 0.2171, -0.066, 0.1559, 0.7146] D65 = [0.5838, -0.143, -0.0246, -0.3497, 1.1477, 0.2297, -0.0748, 0.1885, 0.5778] rawler-0.7.1/data/cameras/sony/a7sm3.toml000064400000000000000000000005161046102023000162720ustar 00000000000000make = "SONY" model = "ILCE-7SM3" clean_make = "Sony" clean_model = "ILCE-7SM3" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.7785, -0.3873, 0.0752, -0.367, 1.0738, 0.3395, -0.0209, 0.0881, 0.752] D65 = [0.6912, -0.2127, -0.0469, -0.447, 1.2175, 0.2587, -0.0398, 0.1478, 0.6492] rawler-0.7.1/data/cameras/sony/a850.toml000064400000000000000000000005751046102023000160220ustar 00000000000000make = "SONY" model = "DSLR-A850" clean_make = "Sony" clean_model = "DSLR-A850" ##blackpoint = 128 #whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 8, 20, 8] [cameras.color_matrix] A = [0.8236, -0.4393, 0.0195, -0.4619, 1.1797, 0.3221, -0.0145, 0.0534, 0.8908] D65 = [0.5413, -0.1162, -0.0365, -0.5665, 1.3098, 0.2866, -0.0608, 0.1179, 0.844] rawler-0.7.1/data/cameras/sony/a9.toml000064400000000000000000000005101046102023000156430ustar 00000000000000make = "SONY" model = "ILCE-9" clean_make = "Sony" clean_model = "ILCE-9" ##blackpoint = 512 #whitepoint = 16383 color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.6886, -0.2314, -0.0094, -0.5285, 1.2967, 0.258, -0.0681, 0.129, 0.7468] D65 = [0.6389, -0.1703, -0.0378, -0.4562, 1.2265, 0.2587, -0.067, 0.1489, 0.655] rawler-0.7.1/data/cameras/sony/a900.toml000064400000000000000000000005721046102023000160130ustar 00000000000000make = "SONY" model = "DSLR-A900" clean_make = "Sony" clean_model = "DSLR-A900" ##blackpoint = 128 #whitepoint = 4095 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 8, 20, 8] [cameras.color_matrix] A = [0.56, -0.1508, -0.016, -0.7208, 1.412, 0.343, -0.0919, 0.1251, 0.8534] D65 = [0.5209, -0.1072, -0.0397, -0.8845, 1.6121, 0.2919, -0.1618, 0.1802, 0.8654] rawler-0.7.1/data/cameras/sony/a99.toml000064400000000000000000000006701046102023000157430ustar 00000000000000make = "SONY" model = "SLT-A99" clean_make = "Sony" clean_model = "SLT-A99" model_aliases = [ ["SLT-A99V", "SLT-A99V"], ] ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [22, 12, 26, 12] bps = 8 [cameras.color_matrix] A = [0.6637, -0.2083, -0.0145, -0.4384, 1.1498, 0.3308, -0.0459, 0.1154, 0.7567] D65 = [0.6344, -0.1612, -0.0462, -0.4863, 1.2477, 0.2681, -0.0865, 0.1786, 0.6899] rawler-0.7.1/data/cameras/sony/a99m2.toml000064400000000000000000000006031046102023000161760ustar 00000000000000make = "SONY" model = "ILCA-99M2" clean_make = "Sony" clean_model = "ILCA-99M2" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 40, 8] bps = 8 [cameras.color_matrix] A = [0.7268, -0.2668, -0.0104, -0.516, 1.287, 0.2552, -0.0585, 0.1176, 0.728] D65 = [0.666, -0.1918, -0.0471, -0.4613, 1.2398, 0.2485, -0.0649, 0.1433, 0.6447] rawler-0.7.1/data/cameras/sony/a9m2.toml000064400000000000000000000005141046102023000161060ustar 00000000000000make = "SONY" model = "ILCE-9M2" clean_make = "Sony" clean_model = "ILCE-9M2" ##blackpoint = 512 #whitepoint = 16383 color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.6886, -0.2314, -0.0094, -0.5285, 1.2967, 0.258, -0.0681, 0.129, 0.7468] D65 = [0.6389, -0.1703, -0.0378, -0.4562, 1.2265, 0.2587, -0.067, 0.1489, 0.655] rawler-0.7.1/data/cameras/sony/a9m3.toml000064400000000000000000000004451046102023000161120ustar 00000000000000make = "SONY" model = "ILCE-9M3" clean_make = "Sony" clean_model = "ILCE-9M3" color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [1.2059, -0.7647, 0.1737, -0.2825, 0.9927, 0.3391, 0.0126, 0.0346, 0.7026] D65 = [0.9811, -0.3908, -0.0752, -0.3704, 1.1577, 0.2417, -0.0073, 0.095, 0.598] rawler-0.7.1/data/cameras/sony/f828.toml000064400000000000000000000007021046102023000160240ustar 00000000000000make = "SONY" model = "DSC-F828" clean_make = "Sony" clean_model = "DSC-F828" blackpoint = 495 whitepoint = 16383 color_pattern = "ERBG" plane_color = "RGBE" active_area = [5, 0, 67, 0] crop_area = [16, 6, 80, 6] [cameras.color_matrix] A = [0.8771, -0.3148, -0.0125, -0.5926, 1.2567, 0.3815, -0.0871, 0.1575, 0.6633, -0.4678, 0.8486, 0.4548] D65 = [0.7925, -0.191, -0.0776, -0.8227, 1.5459, 0.2998, -0.1517, 0.2198, 0.6817, -0.7241, 1.1401, 0.3481] rawler-0.7.1/data/cameras/sony/fx3.toml000064400000000000000000000005331046102023000160370ustar 00000000000000make = "SONY" model = "ILME-FX3" clean_make = "SONY" clean_model = "ILME-FX3" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 8, 36, 8] bps = 8 [cameras.color_matrix] A = [0.7785, -0.3873, 0.0752, -0.367, 1.0738, 0.3395, -0.0209, 0.0881, 0.752] D65 = [0.6912, -0.2127, -0.0469, -0.447, 1.2175, 0.2587, -0.0398, 0.1478, 0.6492] rawler-0.7.1/data/cameras/sony/fx30.toml000064400000000000000000000004441046102023000161200ustar 00000000000000make = "SONY" model = "ILME-FX30" clean_make = "Sony" clean_model = "ILME-FX30" color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.793, -0.406, 0.0417, -0.374, 1.1119, 0.3015, -0.0202, 0.0741, 0.6896] D65 = [0.6972, -0.2408, -0.06, -0.433, 1.2101, 0.2515, -0.0388, 0.1277, 0.5847] rawler-0.7.1/data/cameras/sony/hx95.toml000064400000000000000000000006071046102023000161360ustar 00000000000000make = "SONY" model = "DSC-HX95" clean_make = "SONY" clean_model = "DSC-HX95" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 18, 20, 18] bps = 8 [cameras.color_matrix] A = [1.4883, -0.7877, -0.0463, -0.2977, 1.2186, 0.083, 0.0494, -0.0022, 0.5367] D65 = [1.3076, -0.5686, -0.1481, -0.4027, 1.2851, 0.1251, -0.0167, 0.0725, 0.4937] rawler-0.7.1/data/cameras/sony/hx99.toml000064400000000000000000000006071046102023000161420ustar 00000000000000make = "SONY" model = "DSC-HX99" clean_make = "SONY" clean_model = "DSC-HX99" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 18, 20, 18] bps = 8 [cameras.color_matrix] A = [1.4883, -0.7877, -0.0463, -0.2977, 1.2186, 0.083, 0.0494, -0.0022, 0.5367] D65 = [1.3076, -0.5686, -0.1481, -0.4027, 1.2851, 0.1251, -0.0167, 0.0725, 0.4937] rawler-0.7.1/data/cameras/sony/nex3.toml000064400000000000000000000005731046102023000162200ustar 00000000000000make = "SONY" model = "NEX-3" clean_make = "Sony" clean_model = "NEX-3" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] bps = 8 [cameras.color_matrix] A = [0.671, -0.1934, -0.0172, -0.4303, 1.1507, 0.3202, -0.0527, 0.1307, 0.7431] D65 = [0.6549, -0.155, -0.0436, -0.488, 1.2435, 0.2753, -0.0854, 0.1868, 0.6976] rawler-0.7.1/data/cameras/sony/nex3n.toml000064400000000000000000000005761046102023000164010ustar 00000000000000make = "SONY" model = "NEX-3N" clean_make = "Sony" clean_model = "NEX-3N" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 10, 0] crop_area = [4, 6, 12, 6] bps = 8 [cameras.color_matrix] A = [0.6442, -0.2082, 0.001, -0.4194, 1.1154, 0.3502, -0.0458, 0.0986, 0.7206] D65 = [0.6129, -0.1545, -0.0418, -0.493, 1.249, 0.2743, -0.0977, 0.1693, 0.6615] rawler-0.7.1/data/cameras/sony/nex5.toml000064400000000000000000000005731046102023000162220ustar 00000000000000make = "SONY" model = "NEX-5" clean_make = "Sony" clean_model = "NEX-5" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] bps = 8 [cameras.color_matrix] A = [0.671, -0.1934, -0.0172, -0.4303, 1.1507, 0.3202, -0.0527, 0.1307, 0.7431] D65 = [0.6549, -0.155, -0.0436, -0.488, 1.2435, 0.2753, -0.0854, 0.1868, 0.6976] rawler-0.7.1/data/cameras/sony/nex5n.toml000064400000000000000000000006001046102023000163670ustar 00000000000000make = "SONY" model = "NEX-5N" clean_make = "Sony" clean_model = "NEX-5N" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 12, 0] crop_area = [4, 6, 12, 6] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/nex5r.toml000064400000000000000000000005761046102023000164070ustar 00000000000000make = "SONY" model = "NEX-5R" clean_make = "Sony" clean_model = "NEX-5R" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 12, 0] crop_area = [4, 6, 12, 6] bps = 8 [cameras.color_matrix] A = [0.6442, -0.2082, 0.001, -0.4194, 1.1154, 0.3502, -0.0458, 0.0986, 0.7206] D65 = [0.6129, -0.1545, -0.0418, -0.493, 1.249, 0.2743, -0.0977, 0.1693, 0.6615] rawler-0.7.1/data/cameras/sony/nex5t.toml000064400000000000000000000005761046102023000164110ustar 00000000000000make = "SONY" model = "NEX-5T" clean_make = "Sony" clean_model = "NEX-5T" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 12, 0] crop_area = [4, 6, 12, 6] bps = 8 [cameras.color_matrix] A = [0.6442, -0.2082, 0.001, -0.4194, 1.1154, 0.3502, -0.0458, 0.0986, 0.7206] D65 = [0.6129, -0.1545, -0.0418, -0.493, 1.249, 0.2743, -0.0977, 0.1693, 0.6615] rawler-0.7.1/data/cameras/sony/nex6.toml000064400000000000000000000005731046102023000162230ustar 00000000000000make = "SONY" model = "NEX-6" clean_make = "Sony" clean_model = "NEX-6" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 6, 12, 6] bps = 8 [cameras.color_matrix] A = [0.6442, -0.2082, 0.001, -0.4194, 1.1154, 0.3502, -0.0458, 0.0986, 0.7206] D65 = [0.6129, -0.1545, -0.0418, -0.493, 1.249, 0.2743, -0.0977, 0.1693, 0.6615] rawler-0.7.1/data/cameras/sony/nex7.toml000064400000000000000000000006021046102023000162150ustar 00000000000000make = "SONY" model = "NEX-7" clean_make = "Sony" clean_model = "NEX-7" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 26, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.5644, -0.1547, -0.0028, -0.4237, 1.1032, 0.3701, -0.046, 0.1056, 0.7676] D65 = [0.5491, -0.1192, -0.0363, -0.4951, 1.2342, 0.2948, -0.0911, 0.1722, 0.7192] rawler-0.7.1/data/cameras/sony/nexc3.toml000064400000000000000000000005761046102023000163660ustar 00000000000000make = "SONY" model = "NEX-C3" clean_make = "Sony" clean_model = "NEX-C3" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 8, 8, 8] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/nexf3.toml000064400000000000000000000005771046102023000163720ustar 00000000000000make = "SONY" model = "NEX-F3" clean_make = "Sony" clean_model = "NEX-F3" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [4, 6, 12, 6] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/qx1.toml000064400000000000000000000006051046102023000160500ustar 00000000000000make = "SONY" model = "ILCE-QX1" clean_make = "SONY" clean_model = "ILCE-QX1" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [8, 12, 40, 12] bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/r1.toml000064400000000000000000000005731046102023000156650ustar 00000000000000make = "SONY" model = "DSC-R1" clean_make = "Sony" clean_model = "DSC-R1" blackpoint = 511 whitepoint = 16383 color_pattern = "GRBG" active_area = [0, 0, 60, 0] crop_area = [16, 8, 80, 8] bps = 8 [cameras.color_matrix] A = [1.0011, -0.4237, 0.0183, -0.6596, 1.3898, 0.2984, -0.094, 0.137, 0.7491] D65 = [0.8512, -0.2641, -0.0694, -0.8041, 1.567, 0.2526, -0.182, 0.2117, 0.7414] rawler-0.7.1/data/cameras/sony/rx0.toml000064400000000000000000000006051046102023000160500ustar 00000000000000make = "SONY" model = "DSC-RX0" clean_make = "Sony" clean_model = "DSC-RX0" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 20, 12] bps = 8 [cameras.color_matrix] A = [1.061, -0.4761, -0.0215, -0.3192, 1.1711, 0.1657, -0.0264, 0.1026, 0.5904] D65 = [0.9396, -0.3507, -0.0843, -0.2497, 1.1111, 0.1572, -0.0343, 0.1355, 0.5089] rawler-0.7.1/data/cameras/sony/rx0m2.toml000064400000000000000000000006111046102023000163040ustar 00000000000000make = "SONY" model = "DSC-RX0M2" clean_make = "Sony" clean_model = "DSC-RX0M2" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 20, 12] bps = 8 [cameras.color_matrix] A = [1.061, -0.4761, -0.0215, -0.3192, 1.1711, 0.1657, -0.0264, 0.1026, 0.5904] D65 = [0.9396, -0.3507, -0.0843, -0.2497, 1.1111, 0.1572, -0.0343, 0.1355, 0.5089] rawler-0.7.1/data/cameras/sony/rx1.toml000064400000000000000000000006071046102023000160530ustar 00000000000000make = "SONY" model = "DSC-RX1" clean_make = "Sony" clean_model = "DSC-RX1" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 16, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.6637, -0.2083, -0.0145, -0.4384, 1.1498, 0.3308, -0.0459, 0.1154, 0.7567] D65 = [0.6344, -0.1612, -0.0462, -0.4863, 1.2477, 0.2681, -0.0865, 0.1786, 0.6899] rawler-0.7.1/data/cameras/sony/rx10.toml000064400000000000000000000006051046102023000161310ustar 00000000000000make = "SONY" model = "DSC-RX10" clean_make = "Sony" clean_model = "DSC-RX10" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 8, 0] crop_area = [12, 12, 20, 12] bps = 8 [cameras.color_matrix] A = [0.6486, -0.1903, -0.0025, -0.3661, 1.1315, 0.2685, -0.07, 0.1611, 0.5382] D65 = [0.6679, -0.1825, -0.0745, -0.5047, 1.3256, 0.1953, -0.158, 0.2422, 0.5183] rawler-0.7.1/data/cameras/sony/rx100.toml000064400000000000000000000006101046102023000162050ustar 00000000000000make = "SONY" model = "DSC-RX100" clean_make = "Sony" clean_model = "DSC-RX100" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 12, 0] crop_area = [12, 12, 20, 12] bps = 8 [cameras.color_matrix] A = [0.9105, -0.3443, -0.0742, -0.303, 1.108, 0.2233, -0.008, 0.0639, 0.5008] D65 = [0.8651, -0.2754, -0.1057, -0.3464, 1.2207, 0.1373, -0.0568, 0.1398, 0.4434] rawler-0.7.1/data/cameras/sony/rx100m2.toml000064400000000000000000000006141046102023000164500ustar 00000000000000make = "SONY" model = "DSC-RX100M2" clean_make = "Sony" clean_model = "DSC-RX100M2" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 12, 0] crop_area = [12, 12, 20, 12] bps = 8 [cameras.color_matrix] A = [0.7366, -0.3213, 0.038, -0.3609, 1.1127, 0.2852, -0.0218, 0.0694, 0.5821] D65 = [0.6596, -0.2079, -0.0562, -0.4782, 1.3016, 0.1933, -0.097, 0.1581, 0.5181] rawler-0.7.1/data/cameras/sony/rx100m3.toml000064400000000000000000000006131046102023000164500ustar 00000000000000make = "SONY" model = "DSC-RX100M3" clean_make = "Sony" clean_model = "DSC-RX100M3" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 20, 12] bps = 8 [cameras.color_matrix] A = [0.7366, -0.3213, 0.038, -0.3609, 1.1127, 0.2852, -0.0218, 0.0694, 0.5821] D65 = [0.6596, -0.2079, -0.0562, -0.4782, 1.3016, 0.1933, -0.097, 0.1581, 0.5181] rawler-0.7.1/data/cameras/sony/rx100m4.toml000064400000000000000000000006131046102023000164510ustar 00000000000000make = "SONY" model = "DSC-RX100M4" clean_make = "Sony" clean_model = "DSC-RX100M4" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 20, 12] bps = 8 [cameras.color_matrix] A = [0.7366, -0.3213, 0.038, -0.3609, 1.1127, 0.2852, -0.0218, 0.0694, 0.5821] D65 = [0.6596, -0.2079, -0.0562, -0.4782, 1.3016, 0.1933, -0.097, 0.1581, 0.5181] rawler-0.7.1/data/cameras/sony/rx100m5.toml000064400000000000000000000006131046102023000164520ustar 00000000000000make = "SONY" model = "DSC-RX100M5" clean_make = "SONY" clean_model = "DSC-RX100M5" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 20, 12] bps = 8 [cameras.color_matrix] A = [0.7366, -0.3213, 0.038, -0.3609, 1.1127, 0.2852, -0.0218, 0.0694, 0.5821] D65 = [0.6596, -0.2079, -0.0562, -0.4782, 1.3016, 0.1933, -0.097, 0.1581, 0.5181] rawler-0.7.1/data/cameras/sony/rx100m5a.toml000064400000000000000000000005241046102023000166140ustar 00000000000000make = "SONY" model = "DSC-RX100M5A" clean_make = "SONY" clean_model = "DSC-RX100M5A" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [1.1677, -0.6599, 0.0772, -0.3394, 1.1999, 0.1544, 0.0001, 0.0793, 0.6843] D65 = [1.1176, -0.47, -0.0965, -0.4004, 1.2184, 0.2032, -0.0763, 0.1726, 0.5876] rawler-0.7.1/data/cameras/sony/rx100m6.toml000064400000000000000000000005251046102023000164550ustar 00000000000000make = "SONY" model = "DSC-RX100M6" clean_make = "SONY" clean_model = "DSC-RX100M6" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.8627, -0.4051, 0.0557, -0.2452, 1.0166, 0.2665, -0.0043, 0.0764, 0.5883] D65 = [0.7325, -0.2321, -0.0596, -0.3494, 1.1674, 0.2055, -0.0668, 0.1562, 0.5031] rawler-0.7.1/data/cameras/sony/rx100m7.toml000064400000000000000000000006151046102023000164560ustar 00000000000000make = "SONY" model = "DSC-RX100M7" clean_make = "SONY" clean_model = "DSC-RX100M7" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" bps = 8 model_aliases = [ ["DSC-RX100M7A", "DSC-RX100M7A"], ] [cameras.color_matrix] A = [1.2129, -0.7065, 0.0755, -0.3743, 1.1594, 0.2442, -0.0012, 0.0647, 0.6561] D65 = [1.0315, -0.439, -0.0937, -0.4859, 1.2734, 0.2365, -0.0734, 0.1537, 0.5997] rawler-0.7.1/data/cameras/sony/rx10m2.toml000064400000000000000000000006111046102023000163650ustar 00000000000000make = "SONY" model = "DSC-RX10M2" clean_make = "Sony" clean_model = "DSC-RX10M2" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 8, 0] crop_area = [12, 12, 20, 12] bps = 8 [cameras.color_matrix] A = [0.6486, -0.1903, -0.0025, -0.3661, 1.1315, 0.2685, -0.07, 0.1611, 0.5382] D65 = [0.6679, -0.1825, -0.0745, -0.5047, 1.3256, 0.1953, -0.158, 0.2422, 0.5183] rawler-0.7.1/data/cameras/sony/rx10m3.toml000064400000000000000000000006111046102023000163660ustar 00000000000000make = "SONY" model = "DSC-RX10M3" clean_make = "SONY" clean_model = "DSC-RX10M3" ##blackpoint = 800 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 20, 12] bps = 8 [cameras.color_matrix] A = [0.6486, -0.1903, -0.0025, -0.3661, 1.1315, 0.2685, -0.07, 0.1611, 0.5382] D65 = [0.6679, -0.1825, -0.0745, -0.5047, 1.3256, 0.1953, -0.158, 0.2422, 0.5183] rawler-0.7.1/data/cameras/sony/rx10m4.toml000064400000000000000000000005231046102023000163710ustar 00000000000000make = "SONY" model = "DSC-RX10M4" clean_make = "Sony" clean_model = "DSC-RX10M4" ##blackpoint = 800 #whitepoint = 16380 color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.8852, -0.3765, -0.0028, -0.3758, 1.2219, 0.1702, -0.0297, 0.1042, 0.6023] D65 = [0.7699, -0.2566, -0.0629, -0.2967, 1.127, 0.1928, -0.0378, 0.1286, 0.4807] rawler-0.7.1/data/cameras/sony/rx1r.toml000064400000000000000000000006111046102023000162300ustar 00000000000000make = "SONY" model = "DSC-RX1R" clean_make = "Sony" clean_model = "DSC-RX1R" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 16, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.6637, -0.2083, -0.0145, -0.4384, 1.1498, 0.3308, -0.0459, 0.1154, 0.7567] D65 = [0.6344, -0.1612, -0.0462, -0.4863, 1.2477, 0.2681, -0.0865, 0.1786, 0.6899] rawler-0.7.1/data/cameras/sony/rx1rm2.toml000064400000000000000000000006071046102023000164740ustar 00000000000000make = "SONY" model = "DSC-RX1RM2" clean_make = "Sony" clean_model = "DSC-RX1RM2" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 16, 0] crop_area = [8, 8, 40, 8] bps = 8 [cameras.color_matrix] A = [0.6985, -0.2168, -0.0419, -0.5016, 1.3246, 0.1928, -0.0408, 0.0981, 0.7177] D65 = [0.6629, -0.19, -0.0483, -0.4618, 1.2349, 0.255, -0.0622, 0.1381, 0.6514] rawler-0.7.1/data/cameras/sony/umc-r10c.toml000064400000000000000000000004471046102023000166720ustar 00000000000000make = "SONY" model = "UMC-R10C" clean_make = "Sony" clean_model = "UMC-R10C" color_pattern = "RGGB" bps = 8 [cameras.color_matrix] A = [0.6123, -0.1803, -0.0213, -0.4145, 1.1075, 0.3541, -0.041, 0.0927, 0.7033] D65 = [0.5991, -0.1456, -0.0455, -0.4764, 1.2135, 0.298, -0.0707, 0.1425, 0.6701] rawler-0.7.1/data/cameras/sony/zv1.toml000064400000000000000000000005731046102023000160630ustar 00000000000000make = "SONY" model = "ZV-1" clean_make = "SONY" clean_model = "ZV-1" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 12, 12] bps = 8 [cameras.color_matrix] A = [1.014, -0.5797, 0.0815, -0.2925, 1.0962, 0.2252, 0.0042, 0.0642, 0.6456] D65 = [0.828, -0.2987, -0.0703, -0.3531, 1.1645, 0.2133, -0.055, 0.1542, 0.5312] rawler-0.7.1/data/cameras/sony/zve1.toml000064400000000000000000000005151046102023000162240ustar 00000000000000make = "SONY" model = "ZV-E1" clean_make = "SONY" clean_model = "ZV-E1" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 8, 10, 8] [cameras.color_matrix] A = [0.7785, -0.3873, 0.0752, -0.367, 1.0738, 0.3395, -0.0209, 0.0881, 0.752] D65 = [0.6912, -0.2127, -0.0469, -0.447, 1.2175, 0.2587, -0.0398, 0.1478, 0.6492] rawler-0.7.1/data/cameras/sony/zve10.toml000064400000000000000000000005771046102023000163140ustar 00000000000000make = "SONY" model = "ZV-E10" clean_make = "SONY" clean_model = "ZV-E10" ##blackpoint = 512 #whitepoint = 16300 color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.7565, -0.4028, 0.0657, -0.3254, 1.0746, 0.2898, -0.014, 0.0571, 0.6635] D65 = [0.6355, -0.2067, -0.049, -0.3653, 1.1542, 0.24, -0.0406, 0.1258, 0.5506] rawler-0.7.1/data/cameras/sony/zve10m2.toml000064400000000000000000000005321046102023000165420ustar 00000000000000make = "SONY" model = "ZV-E10M2" clean_make = "SONY" clean_model = "ZV-E10M2" color_pattern = "RGGB" active_area = [0, 0, 0, 0] crop_area = [12, 12, 36, 12] bps = 8 [cameras.color_matrix] A = [0.793, -0.406, 0.0417, -0.374, 1.1119, 0.3015, -0.0202, 0.0741, 0.6896] D65 = [0.6972, -0.2408, -0.06, -0.433, 1.2101, 0.2515, -0.0388, 0.1277, 0.5847] rawler-0.7.1/data/join.rs000064400000000000000000000045241046102023000133500ustar 00000000000000use std::env; use std::fs::File; use std::io::prelude::*; use std::path::Path; extern crate glob; use self::glob::glob; extern crate toml; use toml::Value; extern crate rustc_version; use rustc_version::{Version, version}; fn main() { join_cameras(); join_lenses(); } fn join_cameras() { let out_dir = env::var("OUT_DIR").expect("Missing ENV OUT_DIR"); let dest_path = Path::new(&out_dir).join("cameras.toml"); let mut out = File::create(dest_path).expect("Unable to create output file"); for entry in glob("./data/cameras/*/**/*.toml").expect("Failed to read glob pattern") { out.write_all(b"[[cameras]]\n").expect("Failed to write camera TOML"); let path = entry.expect("Invalid glob entry"); let mut f = File::open(&path).expect("failed to open camera definition file"); let mut toml = String::new(); f.read_to_string(&mut toml).expect("Failed to read camera definition file"); { match toml.parse::() { Ok(_) => {} Err(e) => panic!("Error parsing {:?}: {:?}", path, e), }; } out.write_all(&toml.into_bytes()).expect("Failed to write"); out.write_all(b"\n").expect("Failed to write"); } // Check for a minimum version if version().expect("version failed") < Version::parse("1.31.0").expect("version parse failed") { println!("cargo:rustc-cfg=needs_chunks_exact"); } } fn join_lenses() { let out_dir = env::var("OUT_DIR").expect("Missing ENV OUT_DIR"); let dest_path = Path::new(&out_dir).join("lenses.toml"); let mut out = File::create(dest_path).expect("Unable to create output file"); for entry in glob("./data/lenses/*/**/*.toml").expect("Failed to read glob pattern") { let path = entry.expect("Invalid glob entry"); let mut f = File::open(&path).expect("failed to open lens definition file"); let mut toml = String::new(); f.read_to_string(&mut toml).expect("Failed to read lens definition file"); { match toml.parse::() { Ok(_) => {} Err(e) => panic!("Error parsing {:?}: {:?}", path, e), }; } out.write_all(&toml.into_bytes()).expect("Failed to write"); out.write_all(b"\n").expect("Failed to write"); } // Check for a minimum version if version().expect("version failed") < Version::parse("1.31.0").expect("version parse failed") { println!("cargo:rustc-cfg=needs_chunks_exact"); } } rawler-0.7.1/data/lenses/README.md000064400000000000000000000002531046102023000146060ustar 00000000000000# Lens database Each lens is listed for a specific mount. If a lens model is available for multiple mounts like Sigma lenses, the lens must be specified for each mount. rawler-0.7.1/data/lenses/e_mount/laowa.toml000064400000000000000000000002501046102023000167720ustar 00000000000000[[lenses]] mount = "e-mount" lens_id = 61569 make = "Laowa" model = "FFII 10mm F2.8 C&D Dreamer" focal_range = [[10, 1], [10, 1]] aperture_range = [[28, 10], [28, 10]] rawler-0.7.1/data/lenses/e_mount/samyang.toml000064400000000000000000000056671046102023000173470ustar 00000000000000[[lenses]] mount = "e-mount" lens_id = 32789 make = "Samyang" model = "AF 50mm F1.4" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 32790 make = "Samyang" model = "AF 14mm F2.8" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32794 make = "Samyang" model = "AF 24mm F2.8" focal_range = [[24, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32794 make = "Samyang" model = "AF 35mm F2.8" focal_range = [[35, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32823 make = "Samyang" model = "AF 85mm F1.4" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 51504 make = "Samyang" model = "AF 50mm F1.4" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 51505 make = "Samyang" model = "AF 14mm F2.8" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 51505 make = "Samyang" model = "AF 35mm F2.8" focal_range = [[35, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 51507 make = "Samyang" model = "AF 35mm F1.4" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 51508 make = "Samyang" model = "AF 45mm F1.8" focal_range = [[45, 1], [45, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 51510 make = "Samyang" model = "AF 18mm F2.8" focal_range = [[18, 1], [18, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 51510 make = "Samyang" model = "AF 35mm F1.8" focal_range = [[35, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 51512 make = "Samyang" model = "AF 75mm F1.8" focal_range = [[75, 1], [75, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 51513 make = "Samyang" model = "AF 35mm F1.8" focal_range = [[35, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 51514 make = "Samyang" model = "AF 24mm F1.8" focal_range = [[24, 1], [24, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 51515 make = "Samyang" model = "AF 12mm F2.0" focal_range = [[12, 1], [12, 1]] aperture_range = [[20, 10], [20, 10]] [[lenses]] mount = "e-mount" lens_id = 51516 make = "Samyang" model = "AF 24-70mm F2.8" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 51517 make = "Samyang" model = "AF 50mm F1.4 II" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 51518 make = "Samyang" model = "Samyang AF 135mm F1.8" focal_range = [[135, 1], [135, 1]] aperture_range = [[18, 10], [18, 10]] rawler-0.7.1/data/lenses/e_mount/sigma.toml000064400000000000000000000222101046102023000167670ustar 00000000000000[[lenses]] mount = "e-mount" lens_id = 50480 make = "Sigma" model = "30mm F1.4 DC DN | C" focal_range = [[30, 1], [30, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50481 make = "Sigma" model = "50mm F1.4 DG HSM | A" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50482 make = "Sigma" model = "18-300mm F3.5-6.3 DC MACRO OS HSM | C + MC-11" focal_range = [[18, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 50483 make = "Sigma" model = "18-35mm F1.8 DC HSM | A + MC-11" focal_range = [[18, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 50484 make = "Sigma" model = "24-35mm F2 DG HSM | A + MC-11" focal_range = [[24, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 50485 make = "Sigma" model = "24mm F1.4 DG HSM | A + MC-11" focal_range = [[24, 1], [24, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50486 make = "Sigma" model = "150-600mm F5-6.3 DG OS HSM | C + MC-11" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 50487 make = "Sigma" model = "20mm F1.4 DG HSM | A + MC-11" focal_range = [[20, 1], [20, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50488 make = "Sigma" model = "35mm F1.4 DG HSM | A" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50489 make = "Sigma" model = "150-600mm F5-6.3 DG OS HSM | S + MC-11" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 50490 make = "Sigma" model = "120-300mm F2.8 DG OS HSM | S + MC-11" focal_range = [[120, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50492 make = "Sigma" model = "24-105mm F4 DG OS HSM | A + MC-11" focal_range = [[24, 1], [105, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 50493 make = "Sigma" model = "17-70mm F2.8-4 DC MACRO OS HSM | C + MC-11" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 50495 make = "Sigma" model = "50-100mm F1.8 DC HSM | A + MC-11" focal_range = [[50, 1], [100, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 50499 make = "Sigma" model = "85mm F1.4 DG HSM | A" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50501 make = "Sigma" model = "100-400mm F5-6.3 DG OS HSM | C + MC-11" focal_range = [[100, 1], [400, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 50503 make = "Sigma" model = "16mm F1.4 DC DN | C" focal_range = [[16, 1], [16, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50507 make = "Sigma" model = "105mm F1.4 DG HSM | A" focal_range = [[105, 1], [105, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50508 make = "Sigma" model = "56mm F1.4 DC DN | C" focal_range = [[56, 1], [56, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50512 make = "Sigma" model = "70-200mm F2.8 DG OS HSM | S + MC-11" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50513 make = "Sigma" model = "70mm F2.8 DG MACRO | A" focal_range = [[70, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50514 make = "Sigma" model = "45mm F2.8 DG DN | C" focal_range = [[45, 1], [45, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50515 make = "Sigma" model = "35mm F1.2 DG DN | A" focal_range = [[35, 1], [35, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "e-mount" lens_id = 50516 make = "Sigma" model = "14-24mm F2.8 DG DN | A" focal_range = [[14, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50517 make = "Sigma" model = "24-70mm F2.8 DG DN | A" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50518 make = "Sigma" model = "100-400mm F5-6.3 DG DN OS | C" focal_range = [[100, 1], [400, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 50521 make = "Sigma" model = "85mm F1.4 DG DN | A" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50522 make = "Sigma" model = "105mm F2.8 DG DN MACRO | A" focal_range = [[105, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50523 make = "Sigma" model = "65mm F2 DG DN | C" focal_range = [[65, 1], [65, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 50524 make = "Sigma" model = "35mm F2 DG DN | C" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 50525 make = "Sigma" model = "24mm F3.5 DG DN | C" focal_range = [[24, 1], [24, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "e-mount" lens_id = 50526 make = "Sigma" model = "28-70mm F2.8 DG DN | C" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50527 make = "Sigma" model = "150-600mm F5-6.3 DG DN OS | S" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 50528 make = "Sigma" model = "35mm F1.4 DG DN | A" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50529 make = "Sigma" model = "90mm F2.8 DG DN | C" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50530 make = "Sigma" model = "24mm F2 DG DN | C" focal_range = [[24, 1], [24, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 50531 make = "Sigma" model = "18-50mm F2.8 DC DN | C" focal_range = [[18, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50532 make = "Sigma" model = "20mm F2 DG DN | C" focal_range = [[20, 1], [20, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 50533 make = "Sigma" model = "16-28mm F2.8 DG DN | C" focal_range = [[16, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50534 make = "Sigma" model = "20mm F1.4 DG DN | A" focal_range = [[20, 1], [20, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50535 make = "Sigma" model = "24mm F1.4 DG DN | A" focal_range = [[24, 1], [24, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50536 make = "Sigma" model = "60-600mm F4.5-6.3 DG DN OS | S" focal_range = [[60, 1], [600, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 50537 make = "Sigma" model = "50mm F2 DG DN | C" focal_range = [[50, 1], [50, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 50538 make = "Sigma" model = "17mm F4 DG DN | C" focal_range = [[17, 1], [17, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 50539 make = "Sigma" model = "50mm F1.4 DG DN | A" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50540 make = "Sigma" model = "14mm F1.4 DG DN | A" focal_range = [[14, 1], [14, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50543 make = "Sigma" model = "70-200mm F2.8 DG DN OS | S" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50544 make = "Sigma" model = "23mm F1.4 DC DN | C" focal_range = [[23, 1], [23, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50545 make = "Sigma" model = "24-70mm F2.8 DG DN II | A" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50546 make = "Sigma" model = "500mm F5.6 DG DN OS | S" focal_range = [[500, 1], [500, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 50547 make = "Sigma" model = "10-18mm F2.8 DC DN | C" focal_range = [[10, 1], [18, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50548 make = "Sigma" model = "15mm F1.4 DG DN DIAGONAL FISHEYE | A" focal_range = [[15, 1], [15, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50549 make = "Sigma" model = "50mm F1.2 DG DN | A" focal_range = [[50, 1], [50, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "e-mount" lens_id = 50550 make = "Sigma" model = "28-105mm F2.8 DG DN | A" focal_range = [[28, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 50551 make = "Sigma" model = "28-45mm F1.8 DG DN | A" focal_range = [[28, 1], [45, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 50553 make = "Sigma" model = "300-600mm F4 DG OS | S" focal_range = [[300, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] rawler-0.7.1/data/lenses/e_mount/sony.toml000064400000000000000000000325451046102023000166730ustar 00000000000000[[lenses]] mount = "e-mount" lens_id = 32784 make = "Sony" model = "E 16mm F2.8" focal_range = [[16, 1], [16, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32785 make = "Sony" model = "E 18-55mm F3.5-5.6 OSS" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 32786 make = "Sony" model = "E 55-210mm F4.5-6.3 OSS" focal_range = [[55, 1], [210, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 32787 make = "Sony" model = "E 18-200mm F3.5-6.3 OSS" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 32788 make = "Sony" model = "E 30mm F3.5 Macro" focal_range = [[30, 1], [30, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "e-mount" lens_id = 32789 make = "Sony" model = "E 24mm F1.8 ZA" focal_range = [[24, 1], [24, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 32790 make = "Sony" model = "E 50mm F1.8 OSS" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 32791 make = "Sony" model = "E 16-70mm F4 ZA OSS" focal_range = [[16, 1], [70, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 32792 make = "Sony" model = "E 10-18mm F4 OSS" focal_range = [[10, 1], [18, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 32793 make = "Sony" model = "E PZ 16-50mm F3.5-5.6 OSS" focal_range = [[16, 1], [50, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 32794 make = "Sony" model = "FE 35mm F2.8 ZA" focal_range = [[35, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32795 make = "Sony" model = "FE 24-70mm F4 ZA OSS" focal_range = [[24, 1], [70, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 32796 make = "Sony" model = "FE 85mm F1.8" focal_range = [[85, 1], [85, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 32797 make = "Sony" model = "E 18-200mm F3.5-6.3 OSS LE" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 32798 make = "Sony" model = "E 20mm F2.8" focal_range = [[20, 1], [20, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32799 make = "Sony" model = "E 35mm F1.8 OSS" focal_range = [[35, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 32800 make = "Sony" model = "E PZ 18-105mm F4 G OSS" focal_range = [[18, 1], [105, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 32801 make = "Sony" model = "FE 12-24mm F4 G" focal_range = [[12, 1], [24, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 32802 make = "Sony" model = "FE 90mm F2.8 Macro G OSS" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32803 make = "Sony" model = "E 18-50mm F4-5.6" focal_range = [[18, 1], [50, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 32804 make = "Sony" model = "FE 24mm F1.4 GM" focal_range = [[24, 1], [24, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 32805 make = "Sony" model = "FE 24-105mm F4 G OSS" focal_range = [[24, 1], [105, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 32807 make = "Sony" model = "E PZ 18-200mm F3.5-6.3 OSS" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 32808 make = "Sony" model = "FE 55mm F1.8 ZA" focal_range = [[55, 1], [55, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 32810 make = "Sony" model = "FE 70-200mm F4 G OSS" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 32811 make = "Sony" model = "FE 16-35mm F4 ZA OSS" focal_range = [[16, 1], [35, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 32812 make = "Sony" model = "FE 50mm F2.8 Macro" focal_range = [[50, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32813 make = "Sony" model = "FE 28-70mm F3.5-5.6 OSS" focal_range = [[28, 1], [70, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 32814 make = "Sony" model = "FE 35mm F1.4 ZA" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 32815 make = "Sony" model = "FE 24-240mm F3.5-6.3 OSS" focal_range = [[24, 1], [240, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 32816 make = "Sony" model = "FE 28mm F2" focal_range = [[28, 1], [28, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 32817 make = "Sony" model = "FE PZ 28-135mm F4 G OSS" focal_range = [[28, 1], [135, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 32819 make = "Sony" model = "FE 100mm F2.8 STF GM OSS" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32820 make = "Sony" model = "E PZ 18-110mm F4 G OSS" focal_range = [[18, 1], [110, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 32821 make = "Sony" model = "FE 24-70mm F2.8 GM" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32822 make = "Sony" model = "FE 50mm F1.4 ZA" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 32823 make = "Sony" model = "FE 85mm F1.4 GM" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 32824 make = "Sony" model = "FE 50mm F1.8" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 32826 make = "Sony" model = "FE 21mm F2.8 (SEL28F20 + SEL075UWC)" focal_range = [[21, 1], [21, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32827 make = "Sony" model = "FE 16mm F3.5 Fisheye (SEL28F20 + SEL057FEC)" focal_range = [[16, 1], [16, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "e-mount" lens_id = 32828 make = "Sony" model = "FE 70-300mm F4.5-5.6 G OSS" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 32829 make = "Sony" model = "FE 100-400mm F4.5-5.6 GM OSS" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 32830 make = "Sony" model = "FE 70-200mm F2.8 GM OSS" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32831 make = "Sony" model = "FE 16-35mm F2.8 GM" focal_range = [[16, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32848 make = "Sony" model = "FE 400mm F2.8 GM OSS" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32849 make = "Sony" model = "E 18-135mm F3.5-5.6 OSS" focal_range = [[18, 1], [135, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 32850 make = "Sony" model = "FE 135mm F1.8 GM" focal_range = [[135, 1], [135, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 32851 make = "Sony" model = "FE 200-600mm F5.6-6.3 G OSS" focal_range = [[200, 1], [600, 1]] aperture_range = [[56, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 32852 make = "Sony" model = "FE 600mm F4 GM OSS" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 32853 make = "Sony" model = "E 16-55mm F2.8 G" focal_range = [[16, 1], [55, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32854 make = "Sony" model = "E 70-350mm F4.5-6.3 G OSS" focal_range = [[70, 1], [350, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 32855 make = "Sony" model = "FE C 16-35mm T3.1 G" focal_range = [[16, 1], [35, 1]] aperture_range = [[31, 10], [31, 10]] [[lenses]] mount = "e-mount" lens_id = 32858 make = "Sony" model = "FE 35mm F1.8" focal_range = [[35, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 32859 make = "Sony" model = "FE 20mm F1.8 G" focal_range = [[20, 1], [20, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 32860 make = "Sony" model = "FE 12-24mm F2.8 GM" focal_range = [[12, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32862 make = "Sony" model = "FE 50mm F1.2 GM" focal_range = [[50, 1], [50, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "e-mount" lens_id = 32863 make = "Sony" model = "FE 14mm F1.8 GM" focal_range = [[14, 1], [14, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 32864 make = "Sony" model = "FE 28-60mm F4-5.6" focal_range = [[28, 1], [60, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 32865 make = "Sony" model = "FE 35mm F1.4 GM" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 32866 make = "Sony" model = "FE 24mm F2.8 G" focal_range = [[24, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 32867 make = "Sony" model = "FE 40mm F2.5 G" focal_range = [[40, 1], [40, 1]] aperture_range = [[25, 10], [25, 10]] [[lenses]] mount = "e-mount" lens_id = 32868 make = "Sony" model = "FE 50mm F2.5 G" focal_range = [[50, 1], [50, 1]] aperture_range = [[25, 10], [25, 10]] [[lenses]] mount = "e-mount" lens_id = 32874 make = "Sony" model = "FE 70-200mm F2.8 GM OSS II" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 33072 make = "Sony" model = "FE 70-200mm F2.8 GM OSS + 1.4X Teleconverter" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 33073 make = "Sony" model = "FE 70-200mm F2.8 GM OSS + 2X Teleconverter" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 33076 make = "Sony" model = "FE 100mm F2.8 STF GM OSS (macro mode)" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 33077 make = "Sony" model = "FE 100-400mm F4.5-5.6 GM OSS + 1.4X Teleconverter" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 33078 make = "Sony" model = "FE 100-400mm F4.5-5.6 GM OSS + 2X Teleconverter" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 33079 make = "Sony" model = "FE 400mm F2.8 GM OSS + 1.4X Teleconverter" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 33080 make = "Sony" model = "FE 400mm F2.8 GM OSS + 2X Teleconverter" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 33081 make = "Sony" model = "FE 200-600mm F5.6-6.3 G OSS + 1.4X Teleconverter" focal_range = [[200, 1], [600, 1]] aperture_range = [[56, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 33082 make = "Sony" model = "FE 200-600mm F5.6-6.3 G OSS + 2X Teleconverter" focal_range = [[200, 1], [600, 1]] aperture_range = [[56, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 33083 make = "Sony" model = "FE 600mm F4 GM OSS + 1.4X Teleconverter" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 33084 make = "Sony" model = "FE 600mm F4 GM OSS + 2X Teleconverter" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 33085 make = "Sony" model = "FE 70-200mm F2.8 GM OSS II + 1.4X Teleconverter" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 33086 make = "Sony" model = "FE 70-200mm F2.8 GM OSS II + 2X Teleconverter" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 33087 make = "Sony" model = "FE 70-200mm F4 Macro G OSS II + 1.4X Teleconverter" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 33088 make = "Sony" model = "FE 70-200mm F4 Macro G OSS II + 2X Teleconverter" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "e-mount" lens_id = 33089 make = "Sony" model = "FE 300mm F2.8 GM OSS + 1.4X Teleconverter" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 33090 make = "Sony" model = "FE 300mm F2.8 GM OSS + 2X Teleconverter" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 33091 make = "Sony" model = "FE 400-800mm F6.3-8 G OSS + 1.4X Teleconverter" focal_range = [[400, 1], [800, 1]] aperture_range = [[63, 10], [8, 1]] [[lenses]] mount = "e-mount" lens_id = 33092 make = "Sony" model = "FE 400-800mm F6.3-8 G OSS + 2X Teleconverter" focal_range = [[400, 1], [800, 1]] aperture_range = [[63, 10], [8, 1]] rawler-0.7.1/data/lenses/e_mount/tamron.toml000064400000000000000000000055221046102023000171760ustar 00000000000000[[lenses]] mount = "e-mount" lens_id = 49457 make = "Tamron" model = "28-75mm F2.8 Di III RXD" focal_range = [[28, 1], [75, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49458 make = "Tamron" model = "17-28mm F2.8 Di III RXD" focal_range = [[17, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49459 make = "Tamron" model = "35mm F2.8 Di III OSD M1:2" focal_range = [[35, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49460 make = "Tamron" model = "24mm F2.8 Di III OSD M1:2" focal_range = [[24, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49461 make = "Tamron" model = "20mm F2.8 Di III OSD M1:2" focal_range = [[20, 1], [20, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49462 make = "Tamron" model = "70-180mm F2.8 Di III VXD" focal_range = [[70, 1], [180, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49463 make = "Tamron" model = "28-200mm F2.8-5.6 Di III RXD" focal_range = [[28, 1], [200, 1]] aperture_range = [[28, 10], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 49464 make = "Tamron" model = "70-300mm F4.5-6.3 Di III RXD" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 49465 make = "Tamron" model = "17-70mm F2.8 Di III-A VC RXD" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49466 make = "Tamron" model = "150-500mm F5-6.7 Di III VC VXD" focal_range = [[150, 1], [500, 1]] aperture_range = [[5, 1], [67, 10]] [[lenses]] mount = "e-mount" lens_id = 49467 make = "Tamron" model = "11-20mm F2.8 Di III-A RXD" focal_range = [[11, 1], [20, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49468 make = "Tamron" model = "18-300mm F3.5-6.3 Di III-A VC VXD" focal_range = [[18, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 49469 make = "Tamron" model = "35-150mm F2-F2.8 Di III VXD" focal_range = [[35, 1], [150, 1]] aperture_range = [[2, 1], [0, 1]] [[lenses]] mount = "e-mount" lens_id = 49470 make = "Tamron" model = "28-75mm F2.8 Di III VXD G2" focal_range = [[28, 1], [75, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49471 make = "Tamron" model = "50-400mm F4.5-6.3 Di III VC VXD" focal_range = [[50, 1], [400, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "e-mount" lens_id = 49472 make = "Tamron" model = "20-40mm F2.8 Di III VXD" focal_range = [[20, 1], [40, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49473 make = "Tamron" model = "Tamron 17-50mm F4 Di III VXD2" focal_range = [[17, 1], [50, 1]] aperture_range = [[4, 1], [4, 1]] rawler-0.7.1/data/lenses/e_mount/tokina.toml000064400000000000000000000012171046102023000171600ustar 00000000000000[[lenses]] mount = "e-mount" lens_id = 49473 make = "Tokina" model = "atx-m 85mm F1.8 FE" focal_range = [[85, 1], [85, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 49712 make = "Tokina" model = "FiRIN 20mm F2 FE AF" focal_range = [[20, 1], [20, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 49713 make = "Tokina" model = "FiRIN 100mm F2.8 FE MACRO" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49714 make = "Tokina" model = "atx-m 11-18mm F2.8 E" focal_range = [[11, 1], [18, 1]] aperture_range = [[28, 10], [28, 10]] rawler-0.7.1/data/lenses/e_mount/viltrox.toml000064400000000000000000000011671046102023000174060ustar 00000000000000[[lenses]] mount = "e-mount" lens_id = 32796 make = "Viltrox" model = "PFU RBMH 85mm F1.8" focal_range = [[85, 1], [85, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 49473 make = "Viltrox" model = "23mm F1.4 E" focal_range = [[23, 1], [23, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 49473 make = "Viltrox" model = "56mm F1.4 E" focal_range = [[56, 1], [56, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 61761 make = "Viltrox" model = "28mm F4.5 FE" focal_range = [[28, 1], [28, 1]] aperture_range = [[45, 10], [45, 10]] rawler-0.7.1/data/lenses/e_mount/voigtlander.toml000064400000000000000000000054151046102023000202150ustar 00000000000000[[lenses]] mount = "e-mount" lens_id = 50992 make = "Voigtlander" model = "SUPER WIDE-HELIAR 15mm F4.5 III" focal_range = [[15, 1], [15, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "e-mount" lens_id = 50993 make = "Voigtlander" model = "HELIAR-HYPER WIDE 10mm F5.6" focal_range = [[10, 1], [10, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 50994 make = "Voigtlander" model = "ULTRA WIDE-HELIAR 12mm F5.6 III" focal_range = [[12, 1], [12, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "e-mount" lens_id = 50995 make = "Voigtlander" model = "MACRO APO-LANTHAR 65mm F2 Aspherical" focal_range = [[65, 1], [65, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 50996 make = "Voigtlander" model = "NOKTON 40mm F1.2 Aspherical" focal_range = [[40, 1], [40, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "e-mount" lens_id = 50997 make = "Voigtlander" model = "NOKTON classic 35mm F1.4" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 50998 make = "Voigtlander" model = "MACRO APO-LANTHAR 110mm F2.5" focal_range = [[110, 1], [110, 1]] aperture_range = [[25, 10], [25, 10]] [[lenses]] mount = "e-mount" lens_id = 50999 make = "Voigtlander" model = "COLOR-SKOPAR 21mm F3.5 Aspherical" focal_range = [[21, 1], [21, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "e-mount" lens_id = 51000 make = "Voigtlander" model = "NOKTON 50mm F1.2 Aspherical" focal_range = [[50, 1], [50, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "e-mount" lens_id = 51001 make = "Voigtlander" model = "NOKTON 21mm F1.4 Aspherical" focal_range = [[21, 1], [21, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 51002 make = "Voigtlander" model = "APO-LANTHAR 50mm F2 Aspherical" focal_range = [[50, 1], [50, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 51003 make = "Voigtlander" model = "NOKTON 35mm F1.2 Aspherical SE" focal_range = [[35, 1], [35, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "e-mount" lens_id = 51006 make = "Voigtlander" model = "APO-LANTHAR 35mm F2 Aspherical" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 51007 make = "Voigtlander" model = "NOKTON 50mm F1 Aspherical" focal_range = [[50, 1], [50, 1]] aperture_range = [[1, 1], [1, 1]] [[lenses]] mount = "e-mount" lens_id = 51008 make = "Voigtlander" model = "NOKTON 75mm F1.5 Aspherical" focal_range = [[75, 1], [75, 1]] aperture_range = [[15, 10], [15, 10]] [[lenses]] mount = "e-mount" lens_id = 51009 make = "Voigtlander" model = "NOKTON 28mm F1.5 Aspherical" focal_range = [[28, 1], [28, 1]] aperture_range = [[15, 10], [15, 10]] rawler-0.7.1/data/lenses/e_mount/zeiss.toml000064400000000000000000000044711046102023000170350ustar 00000000000000[[lenses]] mount = "e-mount" lens_id = 49201 make = "Zeiss" model = "Touit 12mm F2.8" focal_range = [[12, 1], [12, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49202 make = "Zeiss" model = "Touit 32mm F1.8" focal_range = [[32, 1], [32, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 49203 make = "Zeiss" model = "Touit 50mm F2.8 Macro" focal_range = [[50, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49216 make = "Zeiss" model = "Batis 25mm F2" focal_range = [[25, 1], [25, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 49217 make = "Zeiss" model = "Batis 85mm F1.8" focal_range = [[85, 1], [85, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "e-mount" lens_id = 49218 make = "Zeiss" model = "Batis 18mm F2.8" focal_range = [[18, 1], [18, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49219 make = "Zeiss" model = "Batis 135mm F2.8" focal_range = [[135, 1], [135, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49220 make = "Zeiss" model = "Batis 40mm F2 CF" focal_range = [[40, 1], [40, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 49232 make = "Zeiss" model = "Loxia 50mm F2" focal_range = [[50, 1], [50, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 49233 make = "Zeiss" model = "Loxia 35mm F2" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "e-mount" lens_id = 49234 make = "Zeiss" model = "Loxia 21mm F2.8" focal_range = [[21, 1], [21, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "e-mount" lens_id = 49235 make = "Zeiss" model = "Loxia 85mm F2.4" focal_range = [[85, 1], [85, 1]] aperture_range = [[24, 10], [24, 10]] [[lenses]] mount = "e-mount" lens_id = 49236 make = "Zeiss" model = "Loxia 25mm F2.4" focal_range = [[25, 1], [25, 1]] aperture_range = [[24, 10], [24, 10]] [[lenses]] mount = "e-mount" lens_id = 51072 make = "Zeiss" model = "Otus ML 50mm F1.4" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "e-mount" lens_id = 51073 make = "Zeiss" model = "Otus ML 85mm F1.4" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] rawler-0.7.1/data/lenses/ef_mount/canon.toml000064400000000000000000001104131046102023000171360ustar 00000000000000[[lenses]] mount = "ef-mount" lens_id = 1 make = "Canon" model = "EF 50mm f/1.8" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 2 make = "Canon" model = "EF 28mm f/2.8" focal_range = [[28, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 3 make = "Canon" model = "EF 135mm f/2.8 Soft" focal_range = [[135, 1], [135, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 4 make = "Canon" model = "EF 35-105mm f/3.5-4.5" focal_range = [[35, 1], [105, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 5 make = "Canon" model = "EF 35-70mm f/3.5-4.5" focal_range = [[35, 1], [70, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 6 make = "Canon" model = "EF 28-70mm f/3.5-4.5" focal_range = [[28, 1], [70, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 7 make = "Canon" model = "EF 100-300mm f/5.6L" focal_range = [[100, 1], [300, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 8 make = "Canon" model = "EF 100-300mm f/5.6" focal_range = [[100, 1], [300, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 8 make = "Canon" model = "EF 70-210mm f/4" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 10 make = "Canon" model = "EF 50mm f/2.5 Macro" focal_range = [[50, 1], [50, 1]] aperture_range = [[25, 10], [25, 10]] [[lenses]] mount = "ef-mount" lens_id = 11 make = "Canon" model = "EF 35mm f/2" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 13 make = "Canon" model = "EF 15mm f/2.8 Fisheye" focal_range = [[15, 1], [15, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 14 make = "Canon" model = "EF 50-200mm f/3.5-4.5L" focal_range = [[50, 1], [200, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 15 make = "Canon" model = "EF 50-200mm f/3.5-4.5" focal_range = [[50, 1], [200, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 16 make = "Canon" model = "EF 35-135mm f/3.5-4.5" focal_range = [[35, 1], [135, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 17 make = "Canon" model = "EF 35-70mm f/3.5-4.5A" focal_range = [[35, 1], [70, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 18 make = "Canon" model = "EF 28-70mm f/3.5-4.5" focal_range = [[28, 1], [70, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 20 make = "Canon" model = "EF 100-200mm f/4.5A" focal_range = [[100, 1], [200, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 21 make = "Canon" model = "EF 80-200mm f/2.8L" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 22 make = "Canon" model = "EF 20-35mm f/2.8L" focal_range = [[20, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 23 make = "Canon" model = "EF 35-105mm f/3.5-4.5" focal_range = [[35, 1], [105, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 24 make = "Canon" model = "EF 35-80mm f/4-5.6 Power Zoom" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 25 make = "Canon" model = "EF 35-80mm f/4-5.6 Power Zoom" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 26 make = "Canon" model = "EF 100mm f/2.8 Macro" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 27 make = "Canon" model = "EF 35-80mm f/4-5.6" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 28 make = "Canon" model = "EF 80-200mm f/4.5-5.6" focal_range = [[80, 1], [200, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 29 make = "Canon" model = "EF 50mm f/1.8 II" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 30 make = "Canon" model = "EF 35-105mm f/4.5-5.6" focal_range = [[35, 1], [105, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 31 make = "Canon" model = "EF 75-300mm f/4-5.6" focal_range = [[75, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 32 make = "Canon" model = "EF 24mm f/2.8" focal_range = [[24, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 35 make = "Canon" model = "EF 35-80mm f/4-5.6" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 36 make = "Canon" model = "EF 38-76mm f/4.5-5.6" focal_range = [[38, 1], [76, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 37 make = "Canon" model = "EF 35-80mm f/4-5.6" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 38 make = "Canon" model = "EF 80-200mm f/4.5-5.6 II" focal_range = [[80, 1], [200, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 39 make = "Canon" model = "EF 75-300mm f/4-5.6" focal_range = [[75, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 40 make = "Canon" model = "EF 28-80mm f/3.5-5.6" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 41 make = "Canon" model = "EF 28-90mm f/4-5.6" focal_range = [[28, 1], [90, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 42 make = "Canon" model = "EF 28-200mm f/3.5-5.6" focal_range = [[28, 1], [200, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 43 make = "Canon" model = "EF 28-105mm f/4-5.6" focal_range = [[28, 1], [105, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 44 make = "Canon" model = "EF 90-300mm f/4.5-5.6" focal_range = [[90, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 45 make = "Canon" model = "EF-S 18-55mm f/3.5-5.6 [II]" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 46 make = "Canon" model = "EF 28-90mm f/4-5.6" focal_range = [[28, 1], [90, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" key = "EF-S18-55mm f/3.5-5.6 IS" lens_id = 48 make = "Canon" model = "EF-S 18-55mm f/3.5-5.6 IS" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 49 make = "Canon" model = "EF-S 55-250mm f/4-5.6 IS" focal_range = [[55, 1], [250, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 50 make = "Canon" model = "EF-S 18-200mm f/3.5-5.6 IS" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 51 make = "Canon" model = "EF-S 18-135mm f/3.5-5.6 IS" focal_range = [[18, 1], [135, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 52 make = "Canon" model = "EF-S 18-55mm f/3.5-5.6 IS II" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 53 make = "Canon" model = "EF-S 18-55mm f/3.5-5.6 III" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 54 make = "Canon" model = "EF-S 55-250mm f/4-5.6 IS II" focal_range = [[55, 1], [250, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 80 make = "Canon" model = "TS-E 50mm f/2.8L Macro" focal_range = [[50, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 81 make = "Canon" model = "TS-E 90mm f/2.8L Macro" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 82 make = "Canon" model = "TS-E 135mm f/4L Macro" focal_range = [[135, 1], [135, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 94 make = "Canon" model = "TS-E 17mm f/4L" focal_range = [[17, 1], [17, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 95 make = "Canon" model = "TS-E 24mm f/3.5L II" focal_range = [[24, 1], [24, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "ef-mount" lens_id = 124 make = "Canon" model = "MP-E 65mm f/2.8 1-5x Macro Photo" focal_range = [[65, 1], [65, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 125 make = "Canon" model = "TS-E 24mm f/3.5L" focal_range = [[24, 1], [24, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "ef-mount" lens_id = 126 make = "Canon" model = "TS-E 45mm f/2.8" focal_range = [[45, 1], [45, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 127 make = "Canon" model = "TS-E 90mm f/2.8" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 129 make = "Canon" model = "EF 300mm f/2.8L USM" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 130 make = "Canon" model = "EF 50mm f/1.0L USM" focal_range = [[50, 1], [50, 1]] aperture_range = [[10, 10], [10, 10]] [[lenses]] mount = "ef-mount" lens_id = 131 make = "Canon" model = "EF 28-80mm f/2.8-4L USM" focal_range = [[28, 1], [80, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 132 make = "Canon" model = "EF 1200mm f/5.6L USM" focal_range = [[1200, 1], [1200, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 134 make = "Canon" model = "EF 600mm f/4L IS USM" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 135 make = "Canon" model = "EF 200mm f/1.8L USM" focal_range = [[200, 1], [200, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 136 make = "Canon" model = "EF 300mm f/2.8L USM" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Canon" model = "EF 85mm f/1.2L USM" focal_range = [[85, 1], [85, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "ef-mount" lens_id = 138 make = "Canon" model = "EF 28-80mm f/2.8-4L" focal_range = [[28, 1], [80, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 139 make = "Canon" model = "EF 400mm f/2.8L USM" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 140 make = "Canon" model = "EF 500mm f/4.5L USM" focal_range = [[500, 1], [500, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 141 make = "Canon" model = "EF 500mm f/4.5L USM" focal_range = [[500, 1], [500, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 142 make = "Canon" model = "EF 300mm f/2.8L IS USM" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 143 make = "Canon" model = "EF 500mm f/4L IS USM" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 144 make = "Canon" model = "EF 35-135mm f/4-5.6 USM" focal_range = [[35, 1], [135, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 145 make = "Canon" model = "EF 100-300mm f/4.5-5.6 USM" focal_range = [[100, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 146 make = "Canon" model = "EF 70-210mm f/3.5-4.5 USM" focal_range = [[70, 1], [210, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 147 make = "Canon" model = "EF 35-135mm f/4-5.6 USM" focal_range = [[35, 1], [135, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 148 make = "Canon" model = "EF 28-80mm f/3.5-5.6 USM" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 149 make = "Canon" model = "EF 100mm f/2 USM" focal_range = [[100, 1], [100, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 150 make = "Canon" model = "EF 14mm f/2.8L USM" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 151 make = "Canon" model = "EF 200mm f/2.8L USM" focal_range = [[200, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 152 make = "Canon" model = "EF 300mm f/4L IS USM" focal_range = [[300, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 153 make = "Canon" model = "EF 35-350mm f/3.5-5.6L USM" focal_range = [[35, 1], [350, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 154 make = "Canon" model = "EF 20mm f/2.8 USM" focal_range = [[20, 1], [20, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" key = "EF85mm f/1.8 USM" lens_id = 155 make = "Canon" model = "EF 85mm f/1.8 USM" focal_range = [[85, 1], [85, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 156 make = "Canon" model = "EF 28-105mm f/3.5-4.5 USM" focal_range = [[28, 1], [105, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 160 make = "Canon" model = "EF 20-35mm f/3.5-4.5 USM" focal_range = [[20, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 161 make = "Canon" model = "EF 28-70mm f/2.8L USM" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 162 make = "Canon" model = "EF 200mm f/2.8L USM" focal_range = [[200, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 163 make = "Canon" model = "EF 300mm f/4L" focal_range = [[300, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 164 make = "Canon" model = "EF 400mm f/5.6L" focal_range = [[400, 1], [400, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 165 make = "Canon" model = "EF 70-200mm f/2.8L USM" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 166 make = "Canon" model = "EF 70-200mm f/2.8L USM + 1.4x" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 167 make = "Canon" model = "EF 70-200mm f/2.8L USM + 2x" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 168 make = "Canon" model = "EF 28mm f/1.8 USM" focal_range = [[28, 1], [28, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 169 make = "Canon" model = "EF 17-35mm f/2.8L USM" focal_range = [[17, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 170 make = "Canon" model = "EF 200mm f/2.8L II USM" focal_range = [[200, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 171 make = "Canon" model = "EF 300mm f/4L USM" focal_range = [[300, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 172 make = "Canon" model = "EF 400mm f/5.6L USM" focal_range = [[400, 1], [400, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 173 make = "Canon" model = "EF 180mm Macro f/3.5L USM" focal_range = [[180, 1], [180, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "ef-mount" lens_id = 174 make = "Canon" model = "EF 135mm f/2L USM" focal_range = [[135, 1], [135, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 175 make = "Canon" model = "EF 400mm f/2.8L USM" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" key = "EF24-85mm f/3.5-4.5 USM" lens_id = 176 make = "Canon" model = "EF 24-85mm f/3.5-4.5 USM" focal_range = [[24, 1], [85, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 177 make = "Canon" model = "EF 300mm f/4L IS USM" focal_range = [[300, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 178 make = "Canon" model = "EF 28-135mm f/3.5-5.6 IS" focal_range = [[28, 1], [135, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 179 make = "Canon" model = "EF 24mm f/1.4L USM" focal_range = [[24, 1], [24, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 180 make = "Canon" model = "EF 35mm f/1.4L USM" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 181 make = "Canon" model = "EF 100-400mm f/4.5-5.6L IS USM + 1.4x" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 182 make = "Canon" model = "EF 100-400mm f/4.5-5.6L IS USM + 2x" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 183 make = "Canon" model = "EF 100-400mm f/4.5-5.6L IS USM" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 184 make = "Canon" model = "EF 400mm f/2.8L USM + 2x" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 185 make = "Canon" model = "EF 600mm f/4L IS USM" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 186 make = "Canon" model = "EF 70-200mm f/4L USM" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 187 make = "Canon" model = "EF 70-200mm f/4L USM + 1.4x" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 188 make = "Canon" model = "EF 70-200mm f/4L USM + 2x" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 189 make = "Canon" model = "EF 70-200mm f/4L USM + 2.8x" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 190 make = "Canon" model = "EF 100mm f/2.8 Macro USM" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 191 make = "Canon" model = "EF 400mm f/4 DO IS" focal_range = [[400, 1], [400, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 193 make = "Canon" model = "EF 35-80mm f/4-5.6 USM" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 194 make = "Canon" model = "EF 80-200mm f/4.5-5.6 USM" focal_range = [[80, 1], [200, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 195 make = "Canon" model = "EF 35-105mm f/4.5-5.6 USM" focal_range = [[35, 1], [105, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 196 make = "Canon" model = "EF 75-300mm f/4-5.6 USM" focal_range = [[75, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 197 make = "Canon" model = "EF 75-300mm f/4-5.6 IS USM" focal_range = [[75, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" key = "EF50mm f/1.4 USM" lens_id = 198 make = "Canon" model = "EF 50mm f/1.4 USM" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 199 make = "Canon" model = "EF 28-80mm f/3.5-5.6 USM" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 200 make = "Canon" model = "EF 75-300mm f/4-5.6 USM" focal_range = [[75, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 201 make = "Canon" model = "EF 28-80mm f/3.5-5.6 USM" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 202 make = "Canon" model = "EF 28-80mm f/3.5-5.6 USM IV" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 208 make = "Canon" model = "EF 22-55mm f/4-5.6 USM" focal_range = [[22, 1], [55, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 209 make = "Canon" model = "EF 55-200mm f/4.5-5.6" focal_range = [[55, 1], [200, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 210 make = "Canon" model = "EF 28-90mm f/4-5.6 USM" focal_range = [[28, 1], [90, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 211 make = "Canon" model = "EF 28-200mm f/3.5-5.6 USM" focal_range = [[28, 1], [200, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 212 make = "Canon" model = "EF 28-105mm f/4-5.6 USM" focal_range = [[28, 1], [105, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 213 make = "Canon" model = "EF 90-300mm f/4.5-5.6 USM" focal_range = [[90, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 214 make = "Canon" model = "EF-S 18-55mm f/3.5-5.6 USM" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 215 make = "Canon" model = "EF 55-200mm f/4.5-5.6 II USM" focal_range = [[55, 1], [200, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 224 make = "Canon" model = "EF 70-200mm f/2.8L IS USM" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 225 make = "Canon" model = "EF 70-200mm f/2.8L IS USM + 1.4x" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 226 make = "Canon" model = "EF 70-200mm f/2.8L IS USM + 2x" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 227 make = "Canon" model = "EF 70-200mm f/2.8L IS USM + 2.8x" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 228 make = "Canon" model = "EF 28-105mm f/3.5-4.5 USM" focal_range = [[28, 1], [105, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" key = "EF16-35mm f/2.8L USM" lens_id = 229 make = "Canon" model = "EF 16-35mm f/2.8L USM" focal_range = [[16, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 230 make = "Canon" model = "EF 24-70mm f/2.8L USM" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 231 make = "Canon" model = "EF 17-40mm f/4L USM" focal_range = [[17, 1], [40, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 232 make = "Canon" model = "EF 70-300mm f/4.5-5.6 DO IS USM" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 233 make = "Canon" model = "EF 28-300mm f/3.5-5.6L IS USM" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 234 make = "Canon" model = "EF-S 17-85mm f/4-5.6 IS USM" focal_range = [[17, 1], [85, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 235 make = "Canon" model = "EF-S 10-22mm f/3.5-4.5 USM" focal_range = [[10, 1], [22, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 236 make = "Canon" model = "EF-S 60mm f/2.8 Macro USM" focal_range = [[60, 1], [60, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 237 make = "Canon" model = "EF 24-105mm f/4L IS USM" focal_range = [[24, 1], [105, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 238 make = "Canon" model = "EF 70-300mm f/4-5.6 IS USM" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 239 make = "Canon" model = "EF 85mm f/1.2L II USM" focal_range = [[85, 1], [85, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "ef-mount" key = "EF-S17-55mm f/2.8 IS USM" lens_id = 240 make = "Canon" model = "EF-S 17-55mm f/2.8 IS USM" focal_range = [[17, 1], [55, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 241 make = "Canon" model = "EF 50mm f/1.2L USM" focal_range = [[50, 1], [50, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "ef-mount" lens_id = 242 make = "Canon" model = "EF 70-200mm f/4L IS USM" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 243 make = "Canon" model = "EF 70-200mm f/4L IS USM + 1.4x" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 244 make = "Canon" model = "EF 70-200mm f/4L IS USM + 2x" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 245 make = "Canon" model = "EF 70-200mm f/4L IS USM + 2.8x" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" key = "EF16-35mm f/2.8L II USM" lens_id = 246 make = "Canon" model = "EF 16-35mm f/2.8L II USM" focal_range = [[16, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 247 make = "Canon" model = "EF 14mm f/2.8L II USM" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 248 make = "Canon" model = "EF 200mm f/2L IS USM" focal_range = [[200, 1], [200, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 249 make = "Canon" model = "EF 800mm f/5.6L IS USM" focal_range = [[800, 1], [800, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 250 make = "Canon" model = "EF 24mm f/1.4L II USM" focal_range = [[24, 1], [24, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" key = "EF70-200mm f/2.8L IS II USM" lens_id = 251 make = "Canon" model = "EF 70-200mm f/2.8L IS II USM" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 251 make = "Canon" model = "EF 70-200mm f/2.8L IS III USM" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 252 make = "Canon" model = "EF 70-200mm f/2.8L IS II USM + 1.4x" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 252 make = "Canon" model = "EF 70-200mm f/2.8L IS III USM + 1.4x" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 253 make = "Canon" model = "EF 70-200mm f/2.8L IS II USM + 2x" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 253 make = "Canon" model = "EF 70-200mm f/2.8L IS III USM + 2x" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 254 make = "Canon" model = "EF 100mm f/2.8L Macro IS USM" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 488 make = "Canon" model = "EF-S 15-85mm f/3.5-5.6 IS USM" focal_range = [[15, 1], [85, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 489 make = "Canon" model = "EF 70-300mm f/4-5.6L IS USM" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 490 make = "Canon" model = "EF 8-15mm f/4L Fisheye USM" focal_range = [[8, 1], [15, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 491 make = "Canon" model = "EF 300mm f/2.8L IS II USM" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" key = "EF400mm f/2.8L IS II USM" lens_id = 492 make = "Canon" model = "EF 400mm f/2.8L IS II USM" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 493 make = "Canon" model = "EF 500mm f/4L IS II USM" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 493 make = "Canon" model = "EF 24-105mm f/4L IS USM" focal_range = [[24, 1], [105, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 494 make = "Canon" model = "EF 600mm f/4L IS II USM" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" key = "EF24-70mm f/2.8L II USM" lens_id = 495 make = "Canon" model = "EF 24-70mm f/2.8L II USM" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 496 make = "Canon" model = "EF 200-400mm f/4L IS USM" focal_range = [[200, 1], [400, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 499 make = "Canon" model = "EF 200-400mm f/4L IS USM + 1.4x" focal_range = [[200, 1], [400, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 502 make = "Canon" model = "EF 28mm f/2.8 IS USM" focal_range = [[28, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 503 make = "Canon" model = "EF 24mm f/2.8 IS USM" focal_range = [[24, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" key = "EF24-70mm f/4L IS USM" lens_id = 504 make = "Canon" model = "EF 24-70mm f/4L IS USM" focal_range = [[24, 1], [70, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 505 make = "Canon" model = "EF 35mm f/2 IS USM" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 506 make = "Canon" model = "EF 400mm f/4 DO IS II USM" focal_range = [[400, 1], [400, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" key = "EF16-35mm f/4L IS USM" lens_id = 507 make = "Canon" model = "EF 16-35mm f/4L IS USM" focal_range = [[16, 1], [35, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 508 make = "Canon" model = "EF 11-24mm f/4L USM" focal_range = [[11, 1], [24, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" key = "EF100-400mm f/4.5-5.6L IS II USM" lens_id = 747 make = "Canon" model = "EF 100-400mm f/4.5-5.6L IS II USM" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 748 make = "Canon" model = "EF 100-400mm f/4.5-5.6L IS II USM + 1.4x" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 750 make = "Canon" model = "EF 35mm f/1.4L II USM" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" key = "EF16-35mm f/2.8L III USM" lens_id = 751 make = "Canon" model = "EF 16-35mm f/2.8L III USM" focal_range = [[16, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 752 make = "Canon" model = "EF 24-105mm f/4L IS II USM" focal_range = [[24, 1], [105, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 753 make = "Canon" model = "EF 85mm f/1.4L IS USM" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 754 make = "Canon" model = "EF 70-200mm f/4L IS II USM" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 757 make = "Canon" model = "EF 400mm f/2.8L IS III USM" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 758 make = "Canon" model = "EF 600mm f/4L IS III USM" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" key = "EF-S18-135mm f/3.5-5.6 IS STM" lens_id = 4142 make = "Canon" model = "EF-S 18-135mm f/3.5-5.6 IS STM" focal_range = [[18, 1], [135, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 4143 make = "Canon" model = "EF-M 18-55mm f/3.5-5.6 IS STM" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 4144 make = "Canon" model = "EF 40mm f/2.8 STM" focal_range = [[40, 1], [40, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" key = "EF-M22mm f/2 STM" lens_id = 4145 make = "Canon" model = "EF-M 22mm f/2 STM" focal_range = [[22, 1], [22, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 4146 make = "Canon" model = "EF-S 18-55mm f/3.5-5.6 IS STM" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" key = "EF-M11-22mm f/4-5.6 IS STM" lens_id = 4147 make = "Canon" model = "EF-M 11-22mm f/4-5.6 IS STM" focal_range = [[11, 1], [22, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 4148 make = "Canon" model = "EF-S 55-250mm f/4-5.6 IS STM" focal_range = [[55, 1], [250, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" key = "EF-M55-200mm f/4.5-6.3 IS STM" lens_id = 4149 make = "Canon" model = "EF-M 55-200mm f/4.5-6.3 IS STM" focal_range = [[55, 1], [200, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 4150 make = "Canon" model = "EF-S 10-18mm f/4.5-5.6 IS STM" focal_range = [[10, 1], [18, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 4152 make = "Canon" model = "EF 24-105mm f/3.5-5.6 IS STM" focal_range = [[24, 1], [105, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" key = "EF-M15-45mm f/3.5-6.3 IS STM" lens_id = 4153 make = "Canon" model = "EF-M 15-45mm f/3.5-6.3 IS STM" focal_range = [[15, 1], [45, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" key = "EF-S24mm f/2.8 STM" lens_id = 4154 make = "Canon" model = "EF-S 24mm f/2.8 STM" focal_range = [[24, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 4155 make = "Canon" model = "EF-M 28mm f/3.5 Macro IS STM" focal_range = [[28, 1], [28, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "ef-mount" key = "EF50mm f/1.8 STM" lens_id = 4156 make = "Canon" model = "EF 50mm f/1.8 STM" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" key = "EF-M18-150mm f/3.5-6.3 IS STM" lens_id = 4157 make = "Canon" model = "EF-M 18-150mm f/3.5-6.3 IS STM" focal_range = [[18, 1], [150, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 4158 make = "Canon" model = "EF-S 18-55mm f/4-5.6 IS STM" focal_range = [[18, 1], [55, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" key = "EF-M32mm f/1.4 STM" lens_id = 4159 make = "Canon" model = "EF-M 32mm f/1.4 STM" focal_range = [[32, 1], [32, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 4160 make = "Canon" model = "EF-S 35mm f/2.8 Macro IS STM" focal_range = [[35, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 36910 make = "Canon" model = "EF 70-300mm f/4-5.6 IS II USM" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" key = "EF-S18-135mm f/3.5-5.6 IS USM" lens_id = 36912 make = "Canon" model = "EF-S 18-135mm f/3.5-5.6 IS USM" focal_range = [[18, 1], [135, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 61491 make = "Canon" model = "CN-E 14mm T3.1 L F" focal_range = [[14, 1], [14, 1]] aperture_range = [[31, 10], [31, 10]] [[lenses]] mount = "ef-mount" lens_id = 61492 make = "Canon" model = "CN-E 24mm T1.5 L F" focal_range = [[24, 1], [24, 1]] aperture_range = [[15, 10], [15, 10]] [[lenses]] mount = "ef-mount" lens_id = 61494 make = "Canon" model = "CN-E 85mm T1.3 L F" focal_range = [[85, 1], [85, 1]] aperture_range = [[13, 10], [13, 10]] [[lenses]] mount = "ef-mount" lens_id = 61495 make = "Canon" model = "CN-E 135mm T2.2 L F" focal_range = [[135, 1], [135, 1]] aperture_range = [[22, 10], [22, 10]] [[lenses]] mount = "ef-mount" lens_id = 61496 make = "Canon" model = "CN-E 35mm T1.5 L F" focal_range = [[35, 1], [35, 1]] aperture_range = [[15, 10], [15, 10]] rawler-0.7.1/data/lenses/ef_mount/cosina.toml000064400000000000000000000002421046102023000173120ustar 00000000000000[[lenses]] mount = "ef-mount" lens_id = 26 make = "Cosina" model = "100mm f/3.5 Macro AF" focal_range = [[100, 1], [100, 1]] aperture_range = [[35, 10], [35, 1]] rawler-0.7.1/data/lenses/ef_mount/irix.toml000064400000000000000000000002171046102023000170130ustar 00000000000000[[lenses]] mount = "ef-mount" lens_id = 60 make = "Irix" model = "11mm f/4" focal_range = [[11, 1], [11, 1]] aperture_range = [[4, 1], [4, 1]] rawler-0.7.1/data/lenses/ef_mount/rokinon.toml000064400000000000000000000012031046102023000175130ustar 00000000000000[[lenses]] mount = "ef-mount" lens_id = 103 make = "Rokinon" model = "SP 14mm f/2.4" focal_range = [[14, 1], [14, 1]] aperture_range = [[24, 10], [24, 10]] [[lenses]] mount = "ef-mount" lens_id = 103 make = "Rokinon" model = "AF 14mm f/2.8 EF" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 106 make = "Rokinon" model = "SP / Samyang XP 35mm f/1.2" focal_range = [[35, 1], [35, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "ef-mount" lens_id = 239 make = "Rokinon" model = "SP 85mm f/1.2" focal_range = [[85, 1], [85, 1]] aperture_range = [[12, 10], [12, 10]] rawler-0.7.1/data/lenses/ef_mount/samyang.toml000064400000000000000000000002371046102023000175010ustar 00000000000000[[lenses]] mount = "ef-mount" lens_id = 103 make = "Samyang" model = "AF 14mm f/2.8 EF" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] rawler-0.7.1/data/lenses/ef_mount/sigma.toml000064400000000000000000000516151046102023000171500ustar 00000000000000[[lenses]] mount = "ef-mount" lens_id = 2 make = "Sigma" model = "24mm f/2.8 Super Wide II" focal_range = [[24, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 4 make = "Sigma" model = "UC Zoom 35-135mm f/4-5.6" focal_range = [[35, 1], [135, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 6 make = "Sigma" model = "18-50mm f/3.5-5.6 DC" focal_range = [[18, 1], [50, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 6 make = "Sigma" model = "18-125mm f/3.5-5.6 DC IF ASP" focal_range = [[18, 1], [125, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 6 make = "Sigma" model = "28-80mm f/3.5-5.6 II Macro" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 6 make = "Sigma" model = "28-300mm f/3.5-6.3 DG Macro" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 8 make = "Sigma" model = "70-300mm f/4-5.6 [APO] DG Macro" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 9 make = "Sigma" model = "55-200mm f/4-5.6 DC" focal_range = [[55, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 10 make = "Sigma" model = "50mm f/2.8 EX" focal_range = [[50, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 10 make = "Sigma" model = "28mm f/1.8" focal_range = [[28, 1], [28, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 10 make = "Sigma" model = "105mm f/2.8 Macro EX" focal_range = [[105, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 10 make = "Sigma" model = "70mm f/2.8 EX DG Macro EF" focal_range = [[70, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 32 make = "Sigma" model = "15mm f/2.8 EX Fisheye" focal_range = [[15, 1], [15, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 112 make = "Sigma" model = "28mm f/1.5 FF High-speed Prime" focal_range = [[28, 1], [28, 1]] aperture_range = [[15, 10], [15, 10]] [[lenses]] mount = "ef-mount" lens_id = 112 make = "Sigma" model = "40mm f/1.5 FF High-speed Prime" focal_range = [[40, 1], [40, 1]] aperture_range = [[15, 10], [15, 10]] [[lenses]] mount = "ef-mount" lens_id = 112 make = "Sigma" model = "105mm f/1.5 FF High-speed Prime" focal_range = [[105, 1], [105, 1]] aperture_range = [[15, 10], [15, 10]] [[lenses]] mount = "ef-mount" lens_id = 131 make = "Sigma" model = "8mm f/3.5 EX DG Circular Fisheye" focal_range = [[8, 1], [8, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "ef-mount" lens_id = 131 make = "Sigma" model = "17-35mm f/2.8-4 EX DG Aspherical HSM" focal_range = [[17, 1], [35, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 131 make = "Sigma" model = "17-70mm f/2.8-4.5 DC Macro" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 131 make = "Sigma" model = "APO 50-150mm f/2.8 [II] EX DC HSM" focal_range = [[50, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 131 make = "Sigma" model = "APO 120-300mm f/2.8 EX DG HSM" focal_range = [[120, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 131 make = "Sigma" model = "4.5mm f/2.8 EX DC HSM Circular Fisheye" focal_range = [[45, 10], [45, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 131 make = "Sigma" model = "70-200mm f/2.8 APO EX HSM" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 131 make = "Sigma" model = "28-70mm f/2.8-4 DG" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "18-50mm f/2.8-4.5 DC OS HSM" focal_range = [[18, 1], [50, 1]] aperture_range = [[28, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "50-200mm f/4-5.6 DC OS HSM" focal_range = [[50, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "18-250mm f/3.5-6.3 DC OS HSM" focal_range = [[18, 1], [250, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "24-70mm f/2.8 IF EX DG HSM" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "18-125mm f/3.8-5.6 DC OS HSM" focal_range = [[18, 1], [125, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "17-70mm f/2.8-4 DC Macro OS HSM | C" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "17-50mm f/2.8 OS HSM" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "18-200mm f/3.5-6.3 DC OS HSM [II]" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "8-16mm f/4.5-5.6 DC HSM" focal_range = [[8, 1], [16, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "10-20mm f/3.5 EX DC HSM" focal_range = [[10, 1], [20, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "18-35mm f/1.8 DC HSM" focal_range = [[18, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "12-24mm f/4.5-5.6 DG HSM II" focal_range = [[12, 1], [24, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Sigma" model = "70-300mm f/4-5.6 DG OS" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 143 make = "Sigma" model = "17-70mm f/2.8-4 DC Macro OS HSM" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 150 make = "Sigma" model = "20mm EX f/1.8" focal_range = [[20, 1], [20, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" key = "30mm F1.4 DC HSM | Art 013" lens_id = 150 make = "Sigma" model = "30mm f/1.4 DC HSM | A" focal_range = [[30, 1], [30, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 150 make = "Sigma" model = "24mm f/1.8 DG Macro EX" focal_range = [[24, 1], [24, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 150 make = "Sigma" model = "28mm f/1.8 DG Macro EX" focal_range = [[28, 1], [28, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 150 make = "Sigma" model = "18-35mm f/1.8 DC HSM | A" focal_range = [[18, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 152 make = "Sigma" model = "12-24mm f/4.5-5.6 EX DG ASPHERICAL HSM" focal_range = [[12, 1], [24, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 152 make = "Sigma" model = "14mm f/2.8 EX Aspherical HSM" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 152 make = "Sigma" model = "10-20mm f/4-5.6" focal_range = [[10, 1], [20, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 152 make = "Sigma" model = "100-300mm f/4" focal_range = [[100, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 152 make = "Sigma" model = "300-800mm f/5.6 APO EX DG HSM" focal_range = [[300, 1], [800, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 153 make = "Sigma" model = "50-500mm f/4-6.3 APO HSM EX" focal_range = [[50, 1], [500, 1]] aperture_range = [[4, 1], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 155 make = "Sigma" model = "14mm f/1.8 DG HSM | A" focal_range = [[14, 1], [14, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 161 make = "Sigma" model = "24-70mm f/2.8 EX" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 161 make = "Sigma" model = "28-70mm f/2.8 EX" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 161 make = "Sigma" model = "24-60mm f/2.8 EX DG" focal_range = [[24, 1], [60, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 168 make = "Sigma" model = "50-100mm f/1.8 DC HSM | A" focal_range = [[50, 1], [100, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 169 make = "Sigma" model = "18-200mm f/3.5-6.3 DC OS" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 169 make = "Sigma" model = "15-30mm f/3.5-4.5 EX DG Aspherical" focal_range = [[15, 1], [30, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 169 make = "Sigma" model = "18-50mm f/2.8 Macro" focal_range = [[18, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 169 make = "Sigma" model = "50mm f/1.4 EX DG HSM" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 169 make = "Sigma" model = "85mm f/1.4 EX DG HSM" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 169 make = "Sigma" model = "30mm f/1.4 EX DC HSM" focal_range = [[30, 1], [30, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 169 make = "Sigma" model = "35mm f/1.4 DG HSM" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 169 make = "Sigma" model = "35mm f/1.5 FF High-Speed Prime | 017" focal_range = [[35, 1], [35, 1]] aperture_range = [[15, 10], [15, 10]] [[lenses]] mount = "ef-mount" lens_id = 169 make = "Sigma" model = "70mm f/2.8 Macro EX DG" focal_range = [[70, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 170 make = "Sigma" model = "300mm f/2.8 APO EX DG HSM" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 170 make = "Sigma" model = "800mm f/5.6 APO EX DG HSM" focal_range = [[800, 1], [800, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 172 make = "Sigma" model = "150-600mm f/5-6.3 DG OS HSM | S" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 172 make = "Sigma" model = "500mm f/4.5 APO EX DG HSM" focal_range = [[500, 1], [500, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 173 make = "Sigma" model = "180mm EX HSM Macro f/3.5" focal_range = [[180, 1], [180, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "ef-mount" lens_id = 173 make = "Sigma" model = "APO Macro 150mm f/2.8 EX DG HSM" focal_range = [[150, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 173 make = "Sigma" model = "10mm f/2.8 EX DC Fisheye" focal_range = [[10, 1], [10, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 173 make = "Sigma" model = "15mm f/2.8 EX DG Diagonal Fisheye" focal_range = [[15, 1], [15, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 174 make = "Sigma" model = "70-200mm f/2.8 EX DG APO OS HSM" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 174 make = "Sigma" model = "50-500mm f/4.5-6.3 APO DG OS HSM" focal_range = [[50, 1], [500, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 174 make = "Sigma" model = "150-500mm f/5-6.3 APO DG OS HSM" focal_range = [[150, 1], [500, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 174 make = "Sigma" model = "APO 50-150mm f/2.8 EX DC OS HSM" focal_range = [[50, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 174 make = "Sigma" model = "APO 120-300mm f/2.8 EX DG OS HSM" focal_range = [[120, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 174 make = "Sigma" model = "120-300mm f/2.8 DG OS HSM S013" focal_range = [[120, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 174 make = "Sigma" model = "120-400mm f/4.5-5.6 APO DG OS HSM" focal_range = [[120, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 174 make = "Sigma" model = "200-500mm f/2.8 APO EX DG" focal_range = [[200, 1], [500, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" key = "50mm F1.4 DG HSM | Art 014" lens_id = 180 make = "Sigma" model = "50mm f/1.4 DG HSM | A" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 180 make = "Sigma" model = "24mm f/1.4 DG HSM | A" focal_range = [[24, 1], [24, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 180 make = "Sigma" model = "24mm f/1.5 FF High-Speed Prime | 017" focal_range = [[24, 1], [24, 1]] aperture_range = [[15, 10], [15, 10]] [[lenses]] mount = "ef-mount" lens_id = 180 make = "Sigma" model = "50mm f/1.5 FF High-Speed Prime | 017" focal_range = [[50, 1], [50, 1]] aperture_range = [[15, 10], [15, 10]] [[lenses]] mount = "ef-mount" lens_id = 180 make = "Sigma" model = "85mm f/1.5 FF High-Speed Prime | 017" focal_range = [[85, 1], [85, 1]] aperture_range = [[15, 10], [15, 10]] [[lenses]] mount = "ef-mount" lens_id = 180 make = "Sigma" model = "20mm f/1.4 DG HSM | A" focal_range = [[20, 1], [20, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 181 make = "Sigma" model = "150-600mm f/5-6.3 DG OS HSM | S + 1.4x" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 182 make = "Sigma" model = "150-600mm f/5-6.3 DG OS HSM | S + 2x" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 183 make = "Sigma" model = "150mm f/2.8 EX DG OS HSM APO Macro" focal_range = [[150, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 183 make = "Sigma" model = "105mm f/2.8 EX DG OS HSM Macro" focal_range = [[105, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 183 make = "Sigma" model = "180mm f/2.8 EX DG OS HSM APO Macro" focal_range = [[180, 1], [180, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" key = "150-600mm F5-6.3 DG OS HSM | Contemporary 015" lens_id = 183 make = "Sigma" model = "150-600mm f/5-6.3 DG OS HSM | C" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 183 make = "Sigma" model = "150-600mm f/5-6.3 DG OS HSM | S" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 183 make = "Sigma" model = "100-400mm f/5-6.3 DG OS HSM" focal_range = [[100, 1], [400, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 183 make = "Sigma" model = "180mm f/3.5 APO Macro EX DG IF HSM" focal_range = [[180, 1], [180, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "ef-mount" lens_id = 191 make = "Sigma" model = "500mm f/4 DG OS HSM" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" key = "18-300mm F3.5-6.3 DC MACRO OS HSM | Contemporary 014" lens_id = 197 make = "Sigma" model = "18-300mm f/3.5-6.3 DC MACRO OS HSM | C" focal_range = [[18, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 231 make = "Sigma" model = "12-24mm f/4 DG HSM A016" focal_range = [[12, 1], [24, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 240 make = "Sigma" model = "17-50mm f/2.8 EX DC OS HSM" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 248 make = "Sigma" model = "24-35mm f/2 DG HSM | A" focal_range = [[24, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 248 make = "Sigma" model = "135mm f/2 FF High-Speed Prime | 017" focal_range = [[135, 1], [135, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 248 make = "Sigma" model = "24-35mm f/2.2 FF Zoom | 017" focal_range = [[24, 1], [35, 1]] aperture_range = [[22, 10], [22, 10]] [[lenses]] mount = "ef-mount" lens_id = 248 make = "Sigma" model = "135mm f/1.8 DG HSM A017" focal_range = [[135, 1], [135, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 250 make = "Sigma" model = "20mm f/1.4 DG HSM | A" focal_range = [[20, 1], [20, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 250 make = "Sigma" model = "20mm f/1.5 FF High-Speed Prime | 017" focal_range = [[20, 1], [20, 1]] aperture_range = [[15, 10], [15, 10]] [[lenses]] mount = "ef-mount" lens_id = 250 make = "Sigma" model = "85mm f/1.4 DG HSM A016" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 255 make = "Sigma" model = "24-105mm f/4 DG OS HSM | A" focal_range = [[24, 1], [105, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 255 make = "Sigma" model = "180mm f/2.8 EX DG OS HSM APO Macro" focal_range = [[180, 1], [180, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 368 make = "Sigma" model = "14-24mm f/2.8 DG HSM | A" focal_range = [[14, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 368 make = "Sigma" model = "20mm f/1.4 DG HSM | A" focal_range = [[20, 1], [20, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 368 make = "Sigma" model = "50mm f/1.4 DG HSM | A" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 368 make = "Sigma" model = "40mm f/1.4 DG HSM | A" focal_range = [[40, 1], [40, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 368 make = "Sigma" model = "60-600mm f/4.5-6.3 DG OS HSM | S" focal_range = [[60, 1], [600, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 368 make = "Sigma" model = "28mm f/1.4 DG HSM | A" focal_range = [[28, 1], [28, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" key = "150-600mm F5-6.3 DG OS HSM | Sports 014" lens_id = 368 make = "Sigma" model = "150-600mm f/5-6.3 DG OS HSM | S" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 368 make = "Sigma" model = "85mm f/1.4 DG HSM | A" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 368 make = "Sigma" model = "105mm f/1.4 DG HSM" focal_range = [[105, 1], [105, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 368 make = "Sigma" model = "14-24mm f/2.8 DG HSM" focal_range = [[14, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 368 make = "Sigma" model = "35mm f/1.4 DG HSM | A" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 368 make = "Sigma" model = "70mm f/2.8 DG Macro" focal_range = [[70, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 368 make = "Sigma" model = "18-35mm f/1.8 DC HSM | A" focal_range = [[18, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 495 make = "Sigma" model = "24-70mm f/2.8 DG OS HSM | A" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 624 make = "Sigma" model = "70-200mm f/2.8 DG OS HSM | S" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 624 make = "Sigma" model = "150-600mm f/5-6.3 | C" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 1136 make = "Sigma" model = "24-70mm f/2.8 DG OS HSM | A" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 4208 make = "Sigma" model = "56mm f/1.4 DC DN | C" focal_range = [[56, 1], [56, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 4208 make = "Sigma" model = "30mm F1.4 DC DN | C" focal_range = [[30, 1], [30, 1]] aperture_range = [[14, 10], [14, 10]] rawler-0.7.1/data/lenses/ef_mount/tamron.toml000064400000000000000000000224111046102023000173400ustar 00000000000000[[lenses]] mount = "ef-mount" lens_id = 26 make = "Tamron" model = "SP AF 90mm f/2.8 Di Macro" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 26 make = "Tamron" model = "SP AF 180mm f/3.5 Di Macro" focal_range = [[180, 1], [180, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "ef-mount" lens_id = 28 make = "Tamron" model = "SP AF 28-105mm f/2.8 LD Aspherical IF" focal_range = [[28, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 28 make = "Tamron" model = "SP AF 28-75mm f/2.8 XR Di LD Aspherical [IF] Macro" focal_range = [[28, 1], [75, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 28 make = "Tamron" model = "AF 70-300mm f/4.5-5.6 Di LD 1:2 Macro Zoom" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 28 make = "Tamron" model = "AF 70-300mm f/4-5.6 Di LD 1:2 Macro" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 28 make = "Tamron" model = "AF Aspherical 28-200mm f/3.8-5.6" focal_range = [[28, 1], [200, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 31 make = "Tamron" model = "SP AF 300mm f/2.8 LD IF" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 42 make = "Tamron" model = "AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical [IF] Macro (A20)" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 117 make = "Tamron" model = "35-150mm f/2.8-4.0 Di VC OSD (A043)" focal_range = [[35, 1], [150, 1]] aperture_range = [[28, 10], [40, 10]] [[lenses]] mount = "ef-mount" lens_id = 117 make = "Tamron" model = "SP 35mm f/1.4 Di USD (F045)" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 127 make = "Tamron" model = "18-200mm f/3.5-6.3 Di II VC (B018)" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 136 make = "Tamron" model = "SP 15-30mm f/2.8 Di VC USD (A012)" focal_range = [[15, 1], [30, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Tamron" model = "AF 18-270mm f/3.5-6.3 Di II VC PZD (B008)" focal_range = [[18, 1], [270, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Tamron" model = "SP 17-50mm f/2.8 XR Di II VC (B005)" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Tamron" model = "SP 60mm f/2 Macro Di II (G005)" focal_range = [[60, 1], [60, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 137 make = "Tamron" model = "SP 24-70mm f/2.8 Di VC USD" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 153 make = "Tamron" model = "AF 28-300mm f/3.5-6.3 XR LD Aspherical [IF] Macro" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 153 make = "Tamron" model = "AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical [IF] Macro (A14)" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 153 make = "Tamron" model = "18-250mm f/3.5-6.3 Di II LD Aspherical [IF] Macro" focal_range = [[18, 1], [250, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 156 make = "Tamron" model = "SP 70-300mm f/4-5.6 Di VC USD (A005)" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 156 make = "Tamron" model = "SP AF 28-105mm f/2.8 LD Aspherical IF (176D)" focal_range = [[28, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 160 make = "Tamron" model = "AF 19-35mm f/3.5-4.5" focal_range = [[19, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 161 make = "Tamron" model = "AF 17-50mm f/2.8 Di-II LD Aspherical" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 161 make = "Tamron" model = "90mm f/2.8" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 161 make = "Tamron" model = "SP AF 17-35mm f/2.8-4 Di LD Aspherical IF (A05)" focal_range = [[17, 1], [35, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "ef-mount" #lens_id = ??? key = "TAMRON 17-35mm F/2.8-4 Di OSD A037" model = "17-35mm F/2.8-4 Di OSD A037" make = "Tamron" focal_range = [[17, 1], [35, 1]] aperture_range = [[28, 10], [40, 10]] [[lenses]] mount = "ef-mount" #lens_id = ??? key = "TAMRON 28-300mm F/3.5-6.3 Di VC PZD A010" model = "28-300mm f/3.5-6.3 Di VC PZD" make = "Tamron" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 161 make = "Tamron" model = "SP AF 28-75mm f/2.8 XR Di LD Aspherical [IF] Macro" focal_range = [[28, 1], [75, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 213 make = "Tamron" model = "SP 150-600mm f/5-6.3 Di VC USD (A011)" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 213 make = "Tamron" model = "16-300mm f/3.5-6.3 Di II VC PZD Macro (B016)" focal_range = [[16, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 213 make = "Tamron" model = "SP 35mm f/1.8 Di VC USD (F012)" focal_range = [[35, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 213 make = "Tamron" model = "SP 45mm f/1.8 Di VC USD (F013)" focal_range = [[45, 1], [45, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 217 make = "Tamron" model = "AF 18-270mm f/3.5-6.3 Di II VC PZD" focal_range = [[18, 1], [270, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 253 make = "Tamron" model = "SP 70-200mm f/2.8 Di VC USD G2 (A025) + 2x" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 254 key = "TAMRON SP 90mm F/2.8 Di VC USD MACRO1:1 F004" make = "Tamron" model = "SP 90mm F/2.8 Di VC USD Macro 1:1 F004" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 255 make = "Tamron" model = "SP 70-200mm f/2.8 Di VC USD" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 491 make = "Tamron" model = "SP 70-200mm f/2.8 Di VC USD G2 (A025)" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 491 make = "Tamron" model = "18-400mm f/3.5-6.3 Di II VC HLD (B028)" focal_range = [[18, 1], [400, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 491 make = "Tamron" model = "100-400mm f/4.5-6.3 Di VC USD (A035)" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 491 make = "Tamron" model = "70-210mm f/4 Di VC USD (A034)" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 491 make = "Tamron" model = "70-210mm f/4 Di VC USD (A034) + 1.4x" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 491 make = "Tamron" model = "SP 24-70mm f/2.8 Di VC USD G2 (A032)" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 502 make = "Tamron" model = "35mm f/1.8 Di VC USD (F012)" focal_range = [[35, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" key = "TAMRON 10-24mm F/3.5-4.5 Di II VC HLD B023" lens_id = 508 make = "Tamron" model = "10-24mm f/3.5-4.5 Di II VC HLD (B023)" focal_range = [[10, 1], [24, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 747 make = "Tamron" model = "SP 150-600mm f/5-6.3 Di VC USD G2" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 748 make = "Tamron" model = "100-400mm f/4.5-6.3 Di VC USD A035E + 1.4x" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 748 make = "Tamron" model = "70-210mm f/4 Di VC USD (A034) + 2x" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 749 make = "Tamron" model = "100-400mm f/4.5-6.3 Di VC USD A035E + 2x" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 750 make = "Tamron" model = "SP 85mm f/1.8 Di VC USD (F016)" focal_range = [[85, 1], [85, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 750 make = "Tamron" model = "SP 45mm f/1.8 Di VC USD (F013)" focal_range = [[45, 1], [45, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "ef-mount" lens_id = 4143 make = "Tamron" model = "18-200mm f/3.5-6.3 Di III VC" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] rawler-0.7.1/data/lenses/ef_mount/tokina.toml000064400000000000000000000051571046102023000173350ustar 00000000000000[[lenses]] mount = "ef-mount" lens_id = 6 make = "Tokina" model = "AF 193-2 19-35mm f/3.5-4.5" focal_range = [[19, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 8 make = "Tokina" model = "AT-X 242 AF 24-200mm f/3.5-5.6" focal_range = [[24, 1], [200, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "ef-mount" lens_id = 22 make = "Tokina" model = "AT-X 280 AF Pro 28-80mm f/2.8 Aspherical" focal_range = [[28, 1], [80, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 37 make = "Tamron" model = "70-200mm f/2.8 Di LD IF Macro" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 37 make = "Tamron" model = "AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical [IF] Macro (A20)" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 37 make = "Tamron" model = "SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical [IF]" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 37 make = "Tamron" model = "AF 18-270mm f/3.5-6.3 Di II VC LD Aspherical [IF] Macro" focal_range = [[18, 1], [270, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "ef-mount" lens_id = 160 make = "Tokina" model = "AT-X 124 AF Pro DX 12-24mm f/4" focal_range = [[12, 1], [24, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 160 make = "Tokina" model = "AT-X 107 AF DX 10-17mm f/3.5-4.5 Fisheye" focal_range = [[10, 1], [17, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "ef-mount" lens_id = 160 make = "Tokina" model = "AT-X 116 AF Pro DX 11-16mm f/2.8" focal_range = [[11, 1], [16, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 160 make = "Tokina" model = "AT-X 11-20 F2.8 PRO DX Aspherical 11-20mm f/2.8" focal_range = [[11, 1], [20, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 161 make = "Tokina" model = "AT-X 24-70mm f/2.8 PRO FX (IF)" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 180 make = "Tokina" model = "Opera 50mm f/1.4 FF" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 234 make = "Tokina" model = "AT-X 12-28 PRO DX 12-28mm f/4" focal_range = [[12, 1], [28, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "ef-mount" lens_id = 250 make = "Tokina" model = "Opera 16-28mm f/2.8 FF" focal_range = [[16, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] rawler-0.7.1/data/lenses/ef_mount/venus.toml000064400000000000000000000003371046102023000172030ustar 00000000000000[[lenses]] mount = "ef-mount" key = "LAOWA 100mm F2.8 CA-Dreamer Macro 2x" lens_id = 173 make = "Venus" model = "Laowa 100mm F2.8 2X Ultra Macro APO" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] rawler-0.7.1/data/lenses/ef_mount/voigtlander.toml000064400000000000000000000013251046102023000203570ustar 00000000000000[[lenses]] mount = "ef-mount" lens_id = 26 make = "Voigtlander" model = "APO Lanthar 125mm F2.5 SL Macro" focal_range = [[125, 1], [125, 1]] aperture_range = [[25, 10], [25, 10]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Voigtlander" model = "Ultron 40mm f/2 SLII Aspherical" focal_range = [[40, 1], [40, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Voigtlander" model = "Color Skopar 20mm f/3.5 SLII Aspherical" focal_range = [[20, 1], [20, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Voigtlander" model = "APO-Lanthar 90mm f/3.5 SLII Close Focus" focal_range = [[90, 1], [90, 1]] aperture_range = [[35, 10], [35, 10]] rawler-0.7.1/data/lenses/ef_mount/yongnuo.toml000064400000000000000000000004651046102023000175430ustar 00000000000000 [[lenses]] mount = "ef-mount" lens_id = 198 make = "Yongnuo" model = "YN 35mm f/2" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 220 make = "Yongnuo" model = "YN 50mm f/1.8" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] rawler-0.7.1/data/lenses/ef_mount/zeiss.toml000064400000000000000000000112311046102023000171730ustar 00000000000000 [[lenses]] mount = "ef-mount" lens_id = 26 make = "Carl Zeiss" model = "Planar T* 50mm f/1.4" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 26 make = "Carl Zeiss" model = "Planar T 85mm f/1.4 ZE" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 27 make = "Carl Zeiss" model = "Distagon T* 28mm f/2 ZF" focal_range = [[28, 1], [28, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Carl Zeiss" model = "Distagon T* 15mm f/2.8 ZE" focal_range = [[15, 1], [15, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Carl Zeiss" model = "Distagon T* 18mm f/3.5 ZE" focal_range = [[18, 1], [18, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Carl Zeiss" model = "Distagon T* 21mm f/2.8 ZE" focal_range = [[21, 1], [21, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Carl Zeiss" model = "Distagon T* 25mm f/2 ZE" focal_range = [[25, 1], [25, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Carl Zeiss" model = "Distagon T* 28mm f/2 ZE" focal_range = [[28, 1], [28, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Carl Zeiss" model = "Distagon T* 35mm f/2 ZE" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Carl Zeiss" model = "Distagon T* 35mm f/1.4 ZE" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Carl Zeiss" model = "Planar T* 50mm f/1.4 ZE" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Carl Zeiss" model = "Makro-Planar T* 50mm f/2 ZE" focal_range = [[50, 1], [50, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Carl Zeiss" model = "Makro-Planar T* 100mm f/2 ZE" focal_range = [[100, 1], [100, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 33 make = "Carl Zeiss" model = "Apo-Sonnar T* 135mm f/2 ZE" focal_range = [[135, 1], [135, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 47 make = "Zeiss" model = "Milvus 35mm f/2" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 47 make = "Zeiss" model = "Milvus 50mm f/2 Makro" focal_range = [[50, 1], [50, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 47 make = "Zeiss" model = "Milvus 135mm f/2 ZE" focal_range = [[135, 1], [135, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 154 make = "Zeiss" model = "Milvus 21mm f/2.8" focal_range = [[21, 1], [21, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 154 make = "Zeiss" model = "Milvus 15mm f/2.8 ZE" focal_range = [[15, 1], [15, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 154 make = "Zeiss" model = "Milvus 18mm f/2.8 ZE" focal_range = [[18, 1], [18, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "ef-mount" lens_id = 174 make = "Zeiss" model = "Milvus 100mm f/2 Makro" focal_range = [[100, 1], [100, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "ef-mount" lens_id = 180 make = "Zeiss" model = "Milvus 50mm f/1.4" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 180 make = "Zeiss" model = "Milvus 85mm f/1.4" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 180 make = "Zeiss" model = "Otus 28mm f/1.4 ZE" focal_range = [[28, 1], [28, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 198 make = "Zeiss" model = "Otus 55mm f/1.4 ZE" focal_range = [[55, 1], [55, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 198 make = "Zeiss" model = "Otus 85mm f/1.4 ZE" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 198 make = "Zeiss" model = "Milvus 25mm f/1.4" focal_range = [[25, 1], [25, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 198 make = "Zeiss" model = "Otus 100mm f/1.4" focal_range = [[100, 1], [100, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "ef-mount" lens_id = 198 make = "Zeiss" model = "Milvus 35mm f/1.4 ZE" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] rawler-0.7.1/data/lenses/f_mount/cosina.toml000064400000000000000000000022331046102023000171470ustar 00000000000000[[lenses]] mount = "F-mount" nikon_id = "06 3F 68 68 2C 2C 06 00" make = "Cosina" model = "AF 100mm F3.5 Macro" focal_range = [[100, 1], [100, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "07 36 3D 5F 2C 3C 03 00" make = "Cosina" model = "AF Zoom 28-80mm F3.5-5.6 MC Macro" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "07 46 3D 6A 25 2F 03 00" make = "Cosina" model = "AF Zoom 28-105mm F2.8-3.8 MC" focal_range = [[28, 1], [105, 1]] aperture_range = [[28, 10], [38, 10]] [[lenses]] mount = "F-mount" nikon_id = "12 36 5C 81 35 3D 09 00" make = "Cosina" model = "AF Zoom 70-210mm F4.5-5.6 MC Macro" focal_range = [[70, 1], [210, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "12 39 5C 8E 34 3D 08 02" make = "Cosina" model = "AF Zoom 70-300mm F4.5-5.6 MC Macro" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "12 3B 68 8D 3D 43 09 02" make = "Cosina" model = "AF Zoom 100-300mm F5.6-6.7 MC Macro" focal_range = [[100, 1], [300, 1]] aperture_range = [[56, 10], [67, 10]] rawler-0.7.1/data/lenses/f_mount/misc.toml000064400000000000000000000054721046102023000166360ustar 00000000000000 [[lenses]] mount = "F-mount" nikon_id = "12 38 69 97 35 42 09 02" make = "Promaster" model = "Spectrum 7 100-400mm F4.5-6.7" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [67, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 54 56 56 30 30 00 00" make = "Coastal" model = "Optical Systems 60mm 1:4 UV-VIS-IR Macro Apo" focal_range = [[60, 1], [60, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "BF 4E 26 26 1E 1E 01 04" make = "Irix" model = "15mm f/2.4 Firefly" focal_range = [[15, 1], [15, 1]] aperture_range = [[24, 10], [24, 10]] [[lenses]] mount = "F-mount" nikon_id = "BF 3C 1B 1B 30 30 01 04" make = "Irix" model = "11mm f/4 Firefly" focal_range = [[11, 1], [11, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "9A 4C 50 50 14 14 9C 06" make = "Yongnuo" model = "YN50mm F1.8N" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "9F 48 48 48 24 24 A1 06" make = "Yongnuo" model = "YN40mm F2.8N" focal_range = [[40, 1], [40, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "9F 54 68 68 18 18 A2 06" make = "Yongnuo" model = "YN100mm F2N" focal_range = [[100, 1], [100, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "02 40 44 5C 2C 34 02 00" make = "Exakta" model = "AF 35-70mm 1:3.5-4.5 MC" focal_range = [[35, 1], [70, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "07 3E 30 43 2D 35 03 00" make = "Soligor" model = "AF Zoom 19-35mm 1:3.5-4.5 MC" focal_range = [[19, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "03 43 5C 81 35 35 02 00" make = "Soligor" model = "AF C/D Zoom UMCS 70-210mm 1:4.5" focal_range = [[70, 1], [210, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "12 4A 5C 81 31 3D 09 00" make = "Soligor" model = "AF C/D Auto Zoom+Macro 70-210mm 1:4-5.6 UMCS" focal_range = [[70, 1], [210, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "12 36 69 97 35 42 09 00" make = "Soligor" model = "AF Zoom 100-400mm 1:4.5-6.7 MC" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [67, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 00 48 48 53 53 00 01" make = "Loreo" model = "40mm F11-22 3D Lens in a Cap 9005" focal_range = [[40, 1], [40, 1]] aperture_range = [[11, 1], [22, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 58 64 64 20 20 00 00" make = "Soligor" model = "C/D Macro MC 90mm f/2.5" focal_range = [[90, 1], [90, 1]] aperture_range = [[25, 10], [25, 10]] [[lenses]] mount = "F-mount" nikon_id = "4A 58 30 30 14 0C 4D 02" make = "Rokinon" model = "20mm f/1.8 ED AS UMC" focal_range = [[20, 1], [20, 1]] aperture_range = [[18, 10], [18, 10]] rawler-0.7.1/data/lenses/f_mount/nikon.toml000064400000000000000000001404001046102023000170100ustar 00000000000000[[lenses]] mount = "F-mount" nikon_id = "01 58 50 50 14 14 02 00" make = "Nikon" model = "AF Nikkor 50mm f/1.8" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "01 58 50 50 14 14 05 00" make = "Nikon" model = "AF Nikkor 50mm f/1.8" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 42 44 5C 2A 34 02 00" make = "Nikon" model = "AF Zoom-Nikkor 35-70mm f/3.3-4.5" focal_range = [[35, 1], [70, 1]] aperture_range = [[33, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 42 44 5C 2A 34 08 00" make = "Nikon" model = "AF Zoom-Nikkor 35-70mm f/3.3-4.5" focal_range = [[35, 1], [70, 1]] aperture_range = [[33, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "03 48 5C 81 30 30 02 00" make = "Nikon" model = "AF Zoom-Nikkor 70-210mm f/4" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "04 48 3C 3C 24 24 03 00" make = "Nikon" model = "AF Nikkor 28mm f/2.8" focal_range = [[28, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "05 54 50 50 0C 0C 04 00" make = "Nikon" model = "AF Nikkor 50mm f/1.4" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "06 54 53 53 24 24 06 00" make = "Nikon" model = "AF Micro-Nikkor 55mm f/2.8" focal_range = [[55, 1], [55, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "07 40 3C 62 2C 34 03 00" make = "Nikon" model = "AF Zoom-Nikkor 28-85mm f/3.5-4.5" focal_range = [[28, 1], [85, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "08 40 44 6A 2C 34 04 00" make = "Nikon" model = "AF Zoom-Nikkor 35-105mm f/3.5-4.5" focal_range = [[35, 1], [105, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "09 48 37 37 24 24 04 00" make = "Nikon" model = "AF Nikkor 24mm f/2.8" focal_range = [[24, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "0A 48 8E 8E 24 24 03 00" make = "Nikon" model = "AF Nikkor 300mm f/2.8 IF-ED" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "0A 48 8E 8E 24 24 05 00" make = "Nikon" model = "AF Nikkor 300mm f/2.8 IF-ED N" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "0B 48 7C 7C 24 24 05 00" make = "Nikon" model = "AF Nikkor 180mm f/2.8 IF-ED" focal_range = [[180, 1], [180, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "0D 40 44 72 2C 34 07 00" make = "Nikon" model = "AF Zoom-Nikkor 35-135mm f/3.5-4.5" focal_range = [[35, 1], [135, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "0E 48 5C 81 30 30 05 00" make = "Nikon" model = "AF Zoom-Nikkor 70-210mm f/4" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "0F 58 50 50 14 14 05 00" make = "Nikon" model = "AF Nikkor 50mm f/1.8 N" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "10 48 8E 8E 30 30 08 00" make = "Nikon" model = "AF Nikkor 300mm f/4 IF-ED" focal_range = [[300, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "11 48 44 5C 24 24 08 00" make = "Nikon" model = "AF Zoom-Nikkor 35-70mm f/2.8" focal_range = [[35, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "11 48 44 5C 24 24 15 00" make = "Nikon" model = "AF Zoom-Nikkor 35-70mm f/2.8" focal_range = [[35, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "12 48 5C 81 30 3C 09 00" make = "Nikon" model = "AF Nikkor 70-210mm f/4-5.6" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "13 42 37 50 2A 34 0B 00" make = "Nikon" model = "AF Zoom-Nikkor 24-50mm f/3.3-4.5" focal_range = [[24, 1], [50, 1]] aperture_range = [[33, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "14 48 60 80 24 24 0B 00" make = "Nikon" model = "AF Zoom-Nikkor 80-200mm f/2.8 ED" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "15 4C 62 62 14 14 0C 00" make = "Nikon" model = "AF Nikkor 85mm f/1.8" focal_range = [[85, 1], [85, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "17 3C A0 A0 30 30 0F 00" make = "Nikon" model = "Nikkor 500mm f/4 P ED IF" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "17 3C A0 A0 30 30 11 00" make = "Nikon" model = "Nikkor 500mm f/4 P ED IF" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "18 40 44 72 2C 34 0E 00" make = "Nikon" model = "AF Zoom-Nikkor 35-135mm f/3.5-4.5 N" focal_range = [[35, 1], [135, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "1A 54 44 44 18 18 11 00" make = "Nikon" model = "AF Nikkor 35mm f/2" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "1B 44 5E 8E 34 3C 10 00" make = "Nikon" model = "AF Zoom-Nikkor 75-300mm f/4.5-5.6" focal_range = [[75, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "1C 48 30 30 24 24 12 00" make = "Nikon" model = "AF Nikkor 20mm f/2.8" focal_range = [[20, 1], [20, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "1D 42 44 5C 2A 34 12 00" make = "Nikon" model = "AF Zoom-Nikkor 35-70mm f/3.3-4.5 N" focal_range = [[35, 1], [70, 1]] aperture_range = [[33, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "1E 54 56 56 24 24 13 00" make = "Nikon" model = "AF Micro-Nikkor 60mm f/2.8" focal_range = [[60, 1], [60, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "1F 54 6A 6A 24 24 14 00" make = "Nikon" model = "AF Micro-Nikkor 105mm f/2.8" focal_range = [[105, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "20 48 60 80 24 24 15 00" make = "Nikon" model = "AF Zoom-Nikkor 80-200mm f/2.8 ED" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "21 40 3C 5C 2C 34 16 00" make = "Nikon" model = "AF Zoom-Nikkor 28-70mm f/3.5-4.5" focal_range = [[28, 1], [70, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "22 48 72 72 18 18 16 00" make = "Nikon" model = "AF DC-Nikkor 135mm f/2" focal_range = [[135, 1], [135, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "23 30 BE CA 3C 48 17 00" make = "Nikon" model = "Zoom-Nikkor 1200-1700mm f/5.6-8 P ED IF" focal_range = [[1200, 1], [1700, 1]] aperture_range = [[56, 10], [8, 1]] [[lenses]] mount = "F-mount" nikon_id = "24 48 60 80 24 24 1A 02" make = "Nikon" model = "AF Zoom-Nikkor 80-200mm f/2.8D ED" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "25 48 44 5C 24 24 1B 02" make = "Nikon" model = "AF Zoom-Nikkor 35-70mm f/2.8D" focal_range = [[35, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "25 48 44 5C 24 24 3A 02" make = "Nikon" model = "AF Zoom-Nikkor 35-70mm f/2.8D" focal_range = [[35, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "25 48 44 5C 24 24 52 02" make = "Nikon" model = "AF Zoom-Nikkor 35-70mm f/2.8D" focal_range = [[35, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 3C 5C 2C 34 1C 02" make = "Nikon" model = "AF Zoom-Nikkor 28-70mm f/3.5-4.5D" focal_range = [[28, 1], [70, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "27 48 8E 8E 24 24 1D 02" make = "Nikon" model = "AF-I Nikkor 300mm f/2.8D IF-ED" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "27 48 8E 8E 24 24 F1 02" make = "Nikon" model = "AF-I Nikkor 300mm f/2.8D IF-ED + TC-14E" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "27 48 8E 8E 24 24 E1 02" make = "Nikon" model = "AF-I Nikkor 300mm f/2.8D IF-ED + TC-17E" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "27 48 8E 8E 24 24 F2 02" make = "Nikon" model = "AF-I Nikkor 300mm f/2.8D IF-ED + TC-20E" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "28 3C A6 A6 30 30 1D 02" make = "Nikon" model = "AF-I Nikkor 600mm f/4D IF-ED" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "28 3C A6 A6 30 30 F1 02" make = "Nikon" model = "AF-I Nikkor 600mm f/4D IF-ED + TC-14E" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "28 3C A6 A6 30 30 E1 02" make = "Nikon" model = "AF-I Nikkor 600mm f/4D IF-ED + TC-17E" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "28 3C A6 A6 30 30 F2 02" make = "Nikon" model = "AF-I Nikkor 600mm f/4D IF-ED + TC-20E" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "2A 54 3C 3C 0C 0C 26 02" make = "Nikon" model = "AF Nikkor 28mm f/1.4D" focal_range = [[28, 1], [28, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "2B 3C 44 60 30 3C 1F 02" make = "Nikon" model = "AF Zoom-Nikkor 35-80mm f/4-5.6D" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "2C 48 6A 6A 18 18 27 02" make = "Nikon" model = "AF DC-Nikkor 105mm f/2D" focal_range = [[105, 1], [105, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "2D 48 80 80 30 30 21 02" make = "Nikon" model = "AF Micro-Nikkor 200mm f/4D IF-ED" focal_range = [[200, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "2E 48 5C 82 30 3C 22 02" make = "Nikon" model = "AF Nikkor 70-210mm f/4-5.6D" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "2E 48 5C 82 30 3C 28 02" make = "Nikon" model = "AF Nikkor 70-210mm f/4-5.6D" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "2F 48 30 44 24 24 29 02.1" make = "Nikon" model = "AF Zoom-Nikkor 20-35mm f/2.8D IF" focal_range = [[20, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "30 48 98 98 24 24 24 02" make = "Nikon" model = "AF-I Nikkor 400mm f/2.8D IF-ED" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "30 48 98 98 24 24 F1 02" make = "Nikon" model = "AF-I Nikkor 400mm f/2.8D IF-ED + TC-14E" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "30 48 98 98 24 24 E1 02" make = "Nikon" model = "AF-I Nikkor 400mm f/2.8D IF-ED + TC-17E" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "30 48 98 98 24 24 F2 02" make = "Nikon" model = "AF-I Nikkor 400mm f/2.8D IF-ED + TC-20E" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "31 54 56 56 24 24 25 02" make = "Nikon" model = "AF Micro-Nikkor 60mm f/2.8D" focal_range = [[60, 1], [60, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "32 54 6A 6A 24 24 35 02.1" make = "Nikon" model = "AF Micro-Nikkor 105mm f/2.8D" focal_range = [[105, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "33 48 2D 2D 24 24 31 02" make = "Nikon" model = "AF Nikkor 18mm f/2.8D" focal_range = [[18, 1], [18, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "34 48 29 29 24 24 32 02" make = "Nikon" model = "AF Fisheye Nikkor 16mm f/2.8D" focal_range = [[16, 1], [16, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "35 3C A0 A0 30 30 33 02" make = "Nikon" model = "AF-I Nikkor 500mm f/4D IF-ED" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "35 3C A0 A0 30 30 F1 02" make = "Nikon" model = "AF-I Nikkor 500mm f/4D IF-ED + TC-14E" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "35 3C A0 A0 30 30 E1 02" make = "Nikon" model = "AF-I Nikkor 500mm f/4D IF-ED + TC-17E" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "35 3C A0 A0 30 30 F2 02" make = "Nikon" model = "AF-I Nikkor 500mm f/4D IF-ED + TC-20E" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "36 48 37 37 24 24 34 02" make = "Nikon" model = "AF Nikkor 24mm f/2.8D" focal_range = [[24, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "37 48 30 30 24 24 36 02" make = "Nikon" model = "AF Nikkor 20mm f/2.8D" focal_range = [[20, 1], [20, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "38 4C 62 62 14 14 37 02" make = "Nikon" model = "AF Nikkor 85mm f/1.8D" focal_range = [[85, 1], [85, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "3A 40 3C 5C 2C 34 39 02" make = "Nikon" model = "AF Zoom-Nikkor 28-70mm f/3.5-4.5D" focal_range = [[28, 1], [70, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "3B 48 44 5C 24 24 3A 02" make = "Nikon" model = "AF Zoom-Nikkor 35-70mm f/2.8D N" focal_range = [[35, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "3C 48 60 80 24 24 3B 02" make = "Nikon" model = "AF Zoom-Nikkor 80-200mm f/2.8D ED" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "3D 3C 44 60 30 3C 3E 02" make = "Nikon" model = "AF Zoom-Nikkor 35-80mm f/4-5.6D" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "3E 48 3C 3C 24 24 3D 02" make = "Nikon" model = "AF Nikkor 28mm f/2.8D" focal_range = [[28, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "3F 40 44 6A 2C 34 45 02" make = "Nikon" model = "AF Zoom-Nikkor 35-105mm f/3.5-4.5D" focal_range = [[35, 1], [105, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "41 48 7C 7C 24 24 43 02" make = "Nikon" model = "AF Nikkor 180mm f/2.8D IF-ED" focal_range = [[180, 1], [180, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "42 54 44 44 18 18 44 02" make = "Nikon" model = "AF Nikkor 35mm f/2D" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "43 54 50 50 0C 0C 46 02" make = "Nikon" model = "AF Nikkor 50mm f/1.4D" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "44 44 60 80 34 3C 47 02" make = "Nikon" model = "AF Zoom-Nikkor 80-200mm f/4.5-5.6D" focal_range = [[80, 1], [200, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "45 40 3C 60 2C 3C 48 02" make = "Nikon" model = "AF Zoom-Nikkor 28-80mm f/3.5-5.6D" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "46 3C 44 60 30 3C 49 02" make = "Nikon" model = "AF Zoom-Nikkor 35-80mm f/4-5.6D N" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "47 42 37 50 2A 34 4A 02" make = "Nikon" model = "AF Zoom-Nikkor 24-50mm f/3.3-4.5D" focal_range = [[24, 1], [50, 1]] aperture_range = [[33, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 48 8E 8E 24 24 4B 02" make = "Nikon" model = "AF-S Nikkor 300mm f/2.8D IF-ED" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 48 8E 8E 24 24 F1 02" make = "Nikon" model = "AF-S Nikkor 300mm f/2.8D IF-ED + TC-14E" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 48 8E 8E 24 24 E1 02" make = "Nikon" model = "AF-S Nikkor 300mm f/2.8D IF-ED + TC-17E" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 48 8E 8E 24 24 F2 02" make = "Nikon" model = "AF-S Nikkor 300mm f/2.8D IF-ED + TC-20E" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "49 3C A6 A6 30 30 4C 02" make = "Nikon" model = "AF-S Nikkor 600mm f/4D IF-ED" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "49 3C A6 A6 30 30 F1 02" make = "Nikon" model = "AF-S Nikkor 600mm f/4D IF-ED + TC-14E" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "49 3C A6 A6 30 30 E1 02" make = "Nikon" model = "AF-S Nikkor 600mm f/4D IF-ED + TC-17E" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "49 3C A6 A6 30 30 F2 02" make = "Nikon" model = "AF-S Nikkor 600mm f/4D IF-ED + TC-20E" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "4A 54 62 62 0C 0C 4D 02" make = "Nikon" model = "AF Nikkor 85mm f/1.4D IF" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "4B 3C A0 A0 30 30 4E 02" make = "Nikon" model = "AF-S Nikkor 500mm f/4D IF-ED" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "4B 3C A0 A0 30 30 F1 02" make = "Nikon" model = "AF-S Nikkor 500mm f/4D IF-ED + TC-14E" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "4B 3C A0 A0 30 30 E1 02" make = "Nikon" model = "AF-S Nikkor 500mm f/4D IF-ED + TC-17E" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "4B 3C A0 A0 30 30 F2 02" make = "Nikon" model = "AF-S Nikkor 500mm f/4D IF-ED + TC-20E" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "4C 40 37 6E 2C 3C 4F 02" make = "Nikon" model = "AF Zoom-Nikkor 24-120mm f/3.5-5.6D IF" focal_range = [[24, 1], [120, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "4D 40 3C 80 2C 3C 62 02" make = "Nikon" model = "AF Zoom-Nikkor 28-200mm f/3.5-5.6D IF" focal_range = [[28, 1], [200, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "4E 48 72 72 18 18 51 02" make = "Nikon" model = "AF DC-Nikkor 135mm f/2D" focal_range = [[135, 1], [135, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "4F 40 37 5C 2C 3C 53 06" make = "Nikon" model = "IX-Nikkor 24-70mm f/3.5-5.6" focal_range = [[24, 1], [70, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "50 48 56 7C 30 3C 54 06" make = "Nikon" model = "IX-Nikkor 60-180mm f/4-5.6" focal_range = [[60, 1], [180, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "53 48 60 80 24 24 57 02" make = "Nikon" model = "AF Zoom-Nikkor 80-200mm f/2.8D ED" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "53 48 60 80 24 24 60 02" make = "Nikon" model = "AF Zoom-Nikkor 80-200mm f/2.8D ED" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "54 44 5C 7C 34 3C 58 02" make = "Nikon" model = "AF Zoom-Micro Nikkor 70-180mm f/4.5-5.6D ED" focal_range = [[70, 1], [180, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "54 44 5C 7C 34 3C 61 02" make = "Nikon" model = "AF Zoom-Micro Nikkor 70-180mm f/4.5-5.6D ED" focal_range = [[70, 1], [180, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "56 48 5C 8E 30 3C 5A 02" make = "Nikon" model = "AF Zoom-Nikkor 70-300mm f/4-5.6D ED" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "59 48 98 98 24 24 5D 02" make = "Nikon" model = "AF-S Nikkor 400mm f/2.8D IF-ED" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "59 48 98 98 24 24 F1 02" make = "Nikon" model = "AF-S Nikkor 400mm f/2.8D IF-ED + TC-14E" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "59 48 98 98 24 24 E1 02" make = "Nikon" model = "AF-S Nikkor 400mm f/2.8D IF-ED + TC-17E" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "59 48 98 98 24 24 F2 02" make = "Nikon" model = "AF-S Nikkor 400mm f/2.8D IF-ED + TC-20E" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "5A 3C 3E 56 30 3C 5E 06" make = "Nikon" model = "IX-Nikkor 30-60mm f/4-5.6" focal_range = [[30, 1], [60, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "5B 44 56 7C 34 3C 5F 06" make = "Nikon" model = "IX-Nikkor 60-180mm f/4.5-5.6" focal_range = [[60, 1], [180, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "5D 48 3C 5C 24 24 63 02" make = "Nikon" model = "AF-S Zoom-Nikkor 28-70mm f/2.8D IF-ED" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "5E 48 60 80 24 24 64 02" make = "Nikon" model = "AF-S Zoom-Nikkor 80-200mm f/2.8D IF-ED" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "5F 40 3C 6A 2C 34 65 02" make = "Nikon" model = "AF Zoom-Nikkor 28-105mm f/3.5-4.5D IF" focal_range = [[28, 1], [105, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "60 40 3C 60 2C 3C 66 02" make = "Nikon" model = "AF Zoom-Nikkor 28-80mm f/3.5-5.6D" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "61 44 5E 86 34 3C 67 02" make = "Nikon" model = "AF Zoom-Nikkor 75-240mm f/4.5-5.6D" focal_range = [[75, 1], [240, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "63 48 2B 44 24 24 68 02" make = "Nikon" model = "AF-S Nikkor 17-35mm f/2.8D IF-ED" focal_range = [[17, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "64 00 62 62 24 24 6A 02" make = "Nikon" model = "PC Micro-Nikkor 85mm f/2.8D" focal_range = [[85, 1], [85, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "65 44 60 98 34 3C 6B 0A" make = "Nikon" model = "AF VR Zoom-Nikkor 80-400mm f/4.5-5.6D ED" focal_range = [[80, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "66 40 2D 44 2C 34 6C 02" make = "Nikon" model = "AF Zoom-Nikkor 18-35mm f/3.5-4.5D IF-ED" focal_range = [[18, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "67 48 37 62 24 30 6D 02" make = "Nikon" model = "AF Zoom-Nikkor 24-85mm f/2.8-4D IF" focal_range = [[24, 1], [85, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "68 42 3C 60 2A 3C 6E 06" make = "Nikon" model = "AF Zoom-Nikkor 28-80mm f/3.3-5.6G" focal_range = [[28, 1], [80, 1]] aperture_range = [[33, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "69 48 5C 8E 30 3C 6F 06" make = "Nikon" model = "AF Zoom-Nikkor 70-300mm f/4-5.6G" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "6A 48 8E 8E 30 30 70 02" make = "Nikon" model = "AF-S Nikkor 300mm f/4D IF-ED" focal_range = [[300, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "6B 48 24 24 24 24 71 02" make = "Nikon" model = "AF Nikkor ED 14mm f/2.8D" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "6D 48 8E 8E 24 24 73 02" make = "Nikon" model = "AF-S Nikkor 300mm f/2.8D IF-ED II" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "6E 48 98 98 24 24 74 02" make = "Nikon" model = "AF-S Nikkor 400mm f/2.8D IF-ED II" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "6F 3C A0 A0 30 30 75 02" make = "Nikon" model = "AF-S Nikkor 500mm f/4D IF-ED II" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "70 3C A6 A6 30 30 76 02" make = "Nikon" model = "AF-S Nikkor 600mm f/4D IF-ED II" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "72 48 4C 4C 24 24 77 00" make = "Nikon" model = "Nikkor 45mm f/2.8 P" focal_range = [[45, 1], [45, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "74 40 37 62 2C 34 78 06" make = "Nikon" model = "AF-S Zoom-Nikkor 24-85mm f/3.5-4.5G IF-ED" focal_range = [[24, 1], [85, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "75 40 3C 68 2C 3C 79 06" make = "Nikon" model = "AF Zoom-Nikkor 28-100mm f/3.5-5.6G" focal_range = [[28, 1], [100, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "76 58 50 50 14 14 7A 02" make = "Nikon" model = "AF Nikkor 50mm f/1.8D" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "77 48 5C 80 24 24 7B 0E" make = "Nikon" model = "AF-S VR Zoom-Nikkor 70-200mm f/2.8G IF-ED" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "78 40 37 6E 2C 3C 7C 0E" make = "Nikon" model = "AF-S VR Zoom-Nikkor 24-120mm f/3.5-5.6G IF-ED" focal_range = [[24, 1], [120, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "79 40 3C 80 2C 3C 7F 06" make = "Nikon" model = "AF Zoom-Nikkor 28-200mm f/3.5-5.6G IF-ED" focal_range = [[28, 1], [200, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "7A 3C 1F 37 30 30 7E 06.1" make = "Nikon" model = "AF-S DX Zoom-Nikkor 12-24mm f/4G IF-ED" focal_range = [[12, 1], [24, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "7B 48 80 98 30 30 80 0E" make = "Nikon" model = "AF-S VR Zoom-Nikkor 200-400mm f/4G IF-ED" focal_range = [[200, 1], [400, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "7D 48 2B 53 24 24 82 06" make = "Nikon" model = "AF-S DX Zoom-Nikkor 17-55mm f/2.8G IF-ED" focal_range = [[17, 1], [55, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "7F 40 2D 5C 2C 34 84 06" make = "Nikon" model = "AF-S DX Zoom-Nikkor 18-70mm f/3.5-4.5G IF-ED" focal_range = [[18, 1], [70, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "80 48 1A 1A 24 24 85 06" make = "Nikon" model = "AF DX Fisheye-Nikkor 10.5mm f/2.8G ED" focal_range = [[105, 10], [105, 10]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "81 54 80 80 18 18 86 0E" make = "Nikon" model = "AF-S VR Nikkor 200mm f/2G IF-ED" focal_range = [[200, 1], [200, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "82 48 8E 8E 24 24 87 0E" make = "Nikon" model = "AF-S VR Nikkor 300mm f/2.8G IF-ED" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "83 00 B0 B0 5A 5A 88 04" make = "Nikon" model = "FSA-L2, EDG 65, 800mm F13 G" focal_range = [[800, 1], [800, 1]] aperture_range = [[13, 1], [13, 1]] [[lenses]] mount = "F-mount" nikon_id = "89 3C 53 80 30 3C 8B 06" make = "Nikon" model = "AF-S DX Zoom-Nikkor 55-200mm f/4-5.6G ED" focal_range = [[55, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "8A 54 6A 6A 24 24 8C 0E" make = "Nikon" model = "AF-S VR Micro-Nikkor 105mm f/2.8G IF-ED" focal_range = [[105, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "8B 40 2D 80 2C 3C 8D 0E" make = "Nikon" model = "AF-S DX VR Zoom-Nikkor 18-200mm f/3.5-5.6G IF-ED" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "8B 40 2D 80 2C 3C FD 0E" make = "Nikon" model = "AF-S DX VR Zoom-Nikkor 18-200mm f/3.5-5.6G IF-ED [II]" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "8C 40 2D 53 2C 3C 8E 06" make = "Nikon" model = "AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G ED" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "8D 44 5C 8E 34 3C 8F 0E" make = "Nikon" model = "AF-S VR Zoom-Nikkor 70-300mm f/4.5-5.6G IF-ED" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "8F 40 2D 72 2C 3C 91 06" make = "Nikon" model = "AF-S DX Zoom-Nikkor 18-135mm f/3.5-5.6G IF-ED" focal_range = [[18, 1], [135, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "90 3B 53 80 30 3C 92 0E" make = "Nikon" model = "AF-S DX VR Zoom-Nikkor 55-200mm f/4-5.6G IF-ED" focal_range = [[55, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "92 48 24 37 24 24 94 06" make = "Nikon" model = "AF-S Zoom-Nikkor 14-24mm f/2.8G ED" focal_range = [[14, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "93 48 37 5C 24 24 95 06" make = "Nikon" model = "AF-S Zoom-Nikkor 24-70mm f/2.8G ED" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "94 40 2D 53 2C 3C 96 06" make = "Nikon" model = "AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G ED II" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "95 4C 37 37 2C 2C 97 02" make = "Nikon" model = "PC-E Nikkor 24mm f/3.5D ED" focal_range = [[24, 1], [24, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "95 00 37 37 2C 2C 97 06" make = "Nikon" model = "PC-E Nikkor 24mm f/3.5D ED" focal_range = [[24, 1], [24, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "96 48 98 98 24 24 98 0E" make = "Nikon" model = "AF-S VR Nikkor 400mm f/2.8G ED" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "97 3C A0 A0 30 30 99 0E" make = "Nikon" model = "AF-S VR Nikkor 500mm f/4G ED" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "98 3C A6 A6 30 30 9A 0E" make = "Nikon" model = "AF-S VR Nikkor 600mm f/4G ED" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "99 40 29 62 2C 3C 9B 0E" make = "Nikon" model = "AF-S DX VR Zoom-Nikkor 16-85mm f/3.5-5.6G ED" focal_range = [[16, 1], [85, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "9A 40 2D 53 2C 3C 9C 0E" make = "Nikon" model = "AF-S DX VR Zoom-Nikkor 18-55mm f/3.5-5.6G" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "9B 54 4C 4C 24 24 9D 02" make = "Nikon" model = "PC-E Micro Nikkor 45mm f/2.8D ED" focal_range = [[45, 1], [45, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "9B 00 4C 4C 24 24 9D 06" make = "Nikon" model = "PC-E Micro Nikkor 45mm f/2.8D ED" focal_range = [[45, 1], [45, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "9C 54 56 56 24 24 9E 06" make = "Nikon" model = "AF-S Micro Nikkor 60mm f/2.8G ED" focal_range = [[60, 1], [60, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "9D 54 62 62 24 24 9F 02" make = "Nikon" model = "PC-E Micro Nikkor 85mm f/2.8D" focal_range = [[85, 1], [85, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "9D 00 62 62 24 24 9F 06" make = "Nikon" model = "PC-E Micro Nikkor 85mm f/2.8D" focal_range = [[85, 1], [85, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "9E 40 2D 6A 2C 3C A0 0E" make = "Nikon" model = "AF-S DX VR Zoom-Nikkor 18-105mm f/3.5-5.6G ED" focal_range = [[18, 1], [105, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "9F 58 44 44 14 14 A1 06" make = "Nikon" model = "AF-S DX Nikkor 35mm f/1.8G" focal_range = [[35, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "A0 54 50 50 0C 0C A2 06" make = "Nikon" model = "AF-S Nikkor 50mm f/1.4G" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "A1 40 18 37 2C 34 A3 06" make = "Nikon" model = "AF-S DX Nikkor 10-24mm f/3.5-4.5G ED" focal_range = [[10, 1], [24, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "A1 40 2D 53 2C 3C CB 86" make = "Nikon" model = "AF-P DX Nikkor 18-55mm f/3.5-5.6G" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "A2 48 5C 80 24 24 A4 0E" make = "Nikon" model = "AF-S Nikkor 70-200mm f/2.8G ED VR II" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "A3 3C 29 44 30 30 A5 0E" make = "Nikon" model = "AF-S Nikkor 16-35mm f/4G ED VR" focal_range = [[16, 1], [35, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "A4 54 37 37 0C 0C A6 06" make = "Nikon" model = "AF-S Nikkor 24mm f/1.4G ED" focal_range = [[24, 1], [24, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "A5 40 3C 8E 2C 3C A7 0E" make = "Nikon" model = "AF-S Nikkor 28-300mm f/3.5-5.6G ED VR" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "A6 48 8E 8E 24 24 A8 0E" make = "Nikon" model = "AF-S Nikkor 300mm f/2.8G IF-ED VR II" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "A7 4B 62 62 2C 2C A9 0E" make = "Nikon" model = "AF-S DX Micro Nikkor 85mm f/3.5G ED VR" focal_range = [[85, 1], [85, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "A8 48 80 98 30 30 AA 0E" make = "Nikon" model = "AF-S Zoom-Nikkor 200-400mm f/4G IF-ED VR II" focal_range = [[200, 1], [400, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "A9 54 80 80 18 18 AB 0E" make = "Nikon" model = "AF-S Nikkor 200mm f/2G ED VR II" focal_range = [[200, 1], [200, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "AA 3C 37 6E 30 30 AC 0E" make = "Nikon" model = "AF-S Nikkor 24-120mm f/4G ED VR" focal_range = [[24, 1], [120, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "AC 38 53 8E 34 3C AE 0E" make = "Nikon" model = "AF-S DX Nikkor 55-300mm f/4.5-5.6G ED VR" focal_range = [[55, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "AD 3C 2D 8E 2C 3C AF 0E" make = "Nikon" model = "AF-S DX Nikkor 18-300mm f/3.5-5.6G ED VR" focal_range = [[18, 1], [300, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "AE 54 62 62 0C 0C B0 06" make = "Nikon" model = "AF-S Nikkor 85mm f/1.4G" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "AF 54 44 44 0C 0C B1 06" make = "Nikon" model = "AF-S Nikkor 35mm f/1.4G" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "B0 4C 50 50 14 14 B2 06" make = "Nikon" model = "AF-S Nikkor 50mm f/1.8G" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "B1 48 48 48 24 24 B3 06" make = "Nikon" model = "AF-S DX Micro Nikkor 40mm f/2.8G" focal_range = [[40, 1], [40, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "B2 48 5C 80 30 30 B4 0E" make = "Nikon" model = "AF-S Nikkor 70-200mm f/4G ED VR" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "B3 4C 62 62 14 14 B5 06" make = "Nikon" model = "AF-S Nikkor 85mm f/1.8G" focal_range = [[85, 1], [85, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "B4 40 37 62 2C 34 B6 0E" make = "Nikon" model = "AF-S Zoom-Nikkor 24-85mm f/3.5-4.5G IF-ED VR" focal_range = [[24, 1], [85, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "B5 4C 3C 3C 14 14 B7 06" make = "Nikon" model = "AF-S Nikkor 28mm f/1.8G" focal_range = [[28, 1], [28, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "B6 3C B0 B0 3C 3C B8 0E" make = "Nikon" model = "AF-S VR Nikkor 800mm f/5.6E FL ED" focal_range = [[800, 1], [800, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "B6 3C B0 B0 3C 3C B8 4E" make = "Nikon" model = "AF-S VR Nikkor 800mm f/5.6E FL ED" focal_range = [[800, 1], [800, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "B7 44 60 98 34 3C B9 0E" make = "Nikon" model = "AF-S Nikkor 80-400mm f/4.5-5.6G ED VR" focal_range = [[80, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "B8 40 2D 44 2C 34 BA 06" make = "Nikon" model = "AF-S Nikkor 18-35mm f/3.5-4.5G ED" focal_range = [[18, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "A0 40 2D 74 2C 3C BB 0E" make = "Nikon" model = "AF-S DX Nikkor 18-140mm f/3.5-5.6G ED VR" focal_range = [[18, 1], [140, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "A1 54 55 55 0C 0C BC 06" make = "Nikon" model = "AF-S Nikkor 58mm f/1.4G" focal_range = [[58, 1], [58, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "A1 48 6E 8E 24 24 DB 4E" make = "Nikon" model = "AF-S Nikkor 120-300mm f/2.8E FL ED SR VR" focal_range = [[120, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "A2 40 2D 53 2C 3C BD 0E" make = "Nikon" model = "AF-S DX Nikkor 18-55mm f/3.5-5.6G VR II" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "A4 40 2D 8E 2C 40 BF 0E" make = "Nikon" model = "AF-S DX Nikkor 18-300mm f/3.5-6.3G ED VR" focal_range = [[18, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "A5 4C 44 44 14 14 C0 06" make = "Nikon" model = "AF-S Nikkor 35mm f/1.8G ED" focal_range = [[35, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "A6 48 98 98 24 24 C1 0E" make = "Nikon" model = "AF-S Nikkor 400mm f/2.8E FL ED VR" focal_range = [[400, 1], [400, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "A7 3C 53 80 30 3C C2 0E" make = "Nikon" model = "AF-S DX Nikkor 55-200mm f/4-5.6G ED VR II" focal_range = [[55, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "A8 48 8E 8E 30 30 C3 4E" make = "Nikon" model = "AF-S Nikkor 300mm f/4E PF ED VR" focal_range = [[300, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "A8 48 8E 8E 30 30 C3 0E" make = "Nikon" model = "AF-S Nikkor 300mm f/4E PF ED VR" focal_range = [[300, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "A9 4C 31 31 14 14 C4 06" make = "Nikon" model = "AF-S Nikkor 20mm f/1.8G ED" focal_range = [[20, 1], [20, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "AA 48 37 5C 24 24 C5 4E" make = "Nikon" model = "AF-S Nikkor 24-70mm f/2.8E ED VR" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "AA 48 37 5C 24 24 C5 0E" make = "Nikon" model = "AF-S Nikkor 24-70mm f/2.8E ED VR" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "AB 3C A0 A0 30 30 C6 4E" make = "Nikon" model = "AF-S Nikkor 500mm f/4E FL ED VR" focal_range = [[500, 1], [500, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "AC 3C A6 A6 30 30 C7 4E" make = "Nikon" model = "AF-S Nikkor 600mm f/4E FL ED VR" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "AD 48 28 60 24 30 C8 4E" make = "Nikon" model = "AF-S DX Nikkor 16-80mm f/2.8-4E ED VR" focal_range = [[16, 1], [80, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "AD 48 28 60 24 30 C8 0E" make = "Nikon" model = "AF-S DX Nikkor 16-80mm f/2.8-4E ED VR" focal_range = [[16, 1], [80, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "AE 3C 80 A0 3C 3C C9 4E" make = "Nikon" model = "AF-S Nikkor 200-500mm f/5.6E ED VR" focal_range = [[200, 1], [500, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "AE 3C 80 A0 3C 3C C9 0E" make = "Nikon" model = "AF-S Nikkor 200-500mm f/5.6E ED VR" focal_range = [[200, 1], [500, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "A0 40 2D 53 2C 3C CA 8E" make = "Nikon" model = "AF-P DX Nikkor 18-55mm f/3.5-5.6G" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "A0 40 2D 53 2C 3C CA 0E" make = "Nikon" model = "AF-P DX Nikkor 18-55mm f/3.5-5.6G VR" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "AF 4C 37 37 14 14 CC 06" make = "Nikon" model = "AF-S Nikkor 24mm f/1.8G ED" focal_range = [[24, 1], [24, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "A2 38 5C 8E 34 40 CD 86" make = "Nikon" model = "AF-P DX Nikkor 70-300mm f/4.5-6.3G VR" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "A3 38 5C 8E 34 40 CE 8E" make = "Nikon" model = "AF-P DX Nikkor 70-300mm f/4.5-6.3G ED VR" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "A3 38 5C 8E 34 40 CE 0E" make = "Nikon" model = "AF-P DX Nikkor 70-300mm f/4.5-6.3G ED" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "A4 48 5C 80 24 24 CF 4E" make = "Nikon" model = "AF-S Nikkor 70-200mm f/2.8E FL ED VR" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "A4 48 5C 80 24 24 CF 0E" make = "Nikon" model = "AF-S Nikkor 70-200mm f/2.8E FL ED VR" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "A5 54 6A 6A 0C 0C D0 46" make = "Nikon" model = "AF-S Nikkor 105mm f/1.4E ED" focal_range = [[105, 1], [105, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "A5 54 6A 6A 0C 0C D0 06" make = "Nikon" model = "AF-S Nikkor 105mm f/1.4E ED" focal_range = [[105, 1], [105, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "A6 48 2F 2F 30 30 D1 46" make = "Nikon" model = "PC Nikkor 19mm f/4E ED" focal_range = [[19, 1], [19, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "A6 48 2F 2F 30 30 D1 06" make = "Nikon" model = "PC Nikkor 19mm f/4E ED" focal_range = [[19, 1], [19, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "A7 40 11 26 2C 34 D2 46" make = "Nikon" model = "AF-S Fisheye Nikkor 8-15mm f/3.5-4.5E ED" focal_range = [[8, 1], [15, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "A7 40 11 26 2C 34 D2 06" make = "Nikon" model = "AF-S Fisheye Nikkor 8-15mm f/3.5-4.5E ED" focal_range = [[8, 1], [15, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "A8 38 18 30 34 3C D3 8E" make = "Nikon" model = "AF-P DX Nikkor 10-20mm f/4.5-5.6G VR" focal_range = [[10, 1], [20, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "A8 38 18 30 34 3C D3 0E" make = "Nikon" model = "AF-P DX Nikkor 10-20mm f/4.5-5.6G VR" focal_range = [[10, 1], [20, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "A9 48 7C 98 30 30 D4 4E" make = "Nikon" model = "AF-S Nikkor 180-400mm f/4E TC1.4 FL ED VR" focal_range = [[180, 1], [400, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "A9 48 7C 98 30 30 D4 0E" make = "Nikon" model = "AF-S Nikkor 180-400mm f/4E TC1.4 FL ED VR" focal_range = [[180, 1], [400, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "AA 48 88 A4 3C 3C D5 4E" make = "Nikon" model = "AF-S Nikkor 180-400mm f/4E TC1.4 FL ED VR + 1.4x TC" focal_range = [[180, 1], [400, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "AA 48 88 A4 3C 3C D5 0E" make = "Nikon" model = "AF-S Nikkor 180-400mm f/4E TC1.4 FL ED VR + 1.4x TC" focal_range = [[180, 1], [400, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "AB 44 5C 8E 34 3C D6 CE" make = "Nikon" model = "AF-P Nikkor 70-300mm f/4.5-5.6E ED VR" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "AB 44 5C 8E 34 3C D6 0E" make = "Nikon" model = "AF-P Nikkor 70-300mm f/4.5-5.6E ED VR" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "AB 44 5C 8E 34 3C D6 4E" make = "Nikon" model = "AF-P Nikkor 70-300mm f/4.5-5.6E ED VR" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "AC 54 3C 3C 0C 0C D7 46" make = "Nikon" model = "AF-S Nikkor 28mm f/1.4E ED" focal_range = [[28, 1], [28, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "AC 54 3C 3C 0C 0C D7 06" make = "Nikon" model = "AF-S Nikkor 28mm f/1.4E ED" focal_range = [[28, 1], [28, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "AD 3C A0 A0 3C 3C D8 0E" make = "Nikon" model = "AF-S Nikkor 500mm f/5.6E PF ED VR" focal_range = [[500, 1], [500, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "AD 3C A0 A0 3C 3C D8 4E" make = "Nikon" model = "AF-S Nikkor 500mm f/5.6E PF ED VR" focal_range = [[500, 1], [500, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 47 10 10 24 24 00 00" make = "Nikon" model = "Fisheye Nikkor 8mm f/2.8 AiS" focal_range = [[8, 1], [8, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 47 3C 3C 24 24 00 00" make = "Nikon" model = "Nikkor 28mm f/2.8 AiS" focal_range = [[28, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 54 44 44 0C 0C 00 00" make = "Nikon" model = "Nikkor 35mm f/1.4 AiS" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 57 50 50 14 14 00 00" make = "Nikon" model = "Nikkor 50mm f/1.8 AI" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 48 50 50 18 18 00 00" make = "Nikon" model = "Nikkor H 50mm f/2" focal_range = [[50, 1], [50, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 48 68 68 24 24 00 00" make = "Nikon" model = "Series E 100mm f/2.8" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 4C 6A 6A 20 20 00 00" make = "Nikon" model = "Nikkor 105mm f/2.5 AiS" focal_range = [[105, 1], [105, 1]] aperture_range = [[25, 10], [25, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 48 80 80 30 30 00 00" make = "Nikon" model = "Nikkor 200mm f/4 AiS" focal_range = [[200, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] rawler-0.7.1/data/lenses/f_mount/samyang.toml000064400000000000000000000035251046102023000173370ustar 00000000000000[[lenses]] mount = "F-mount" nikon_id = "4A 40 11 11 2C 0C 4D 02" make = "Samyang" model = "8mm f/3.5 Fish-Eye CS" focal_range = [[8, 1], [8, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "4A 48 24 24 24 0C 4D 02.1" make = "Samyang" model = "10mm f/2.8 ED AS NCS CS" focal_range = [[10, 1], [10, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "4A 48 1E 1E 24 0C 4D 02" make = "Samyang" model = "12mm f/2.8 ED AS NCS Fish-Eye" focal_range = [[12, 1], [12, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "4A 48 24 24 24 0C 4D 02.2" make = "Samyang" model = "AE 14mm f/2.8 ED AS IF UMC" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "4A 4C 24 24 1E 6C 4D 06" make = "Samyang" model = "14mm f/2.4 Premium" focal_range = [[14, 1], [14, 1]] aperture_range = [[24, 10], [24, 10]] [[lenses]] mount = "F-mount" nikon_id = "4A 54 29 29 18 0C 4D 02" make = "Samyang" model = "16mm f/2.0 ED AS UMC CS" focal_range = [[16, 1], [16, 1]] aperture_range = [[20, 10], [20, 10]] [[lenses]] mount = "F-mount" nikon_id = "4A 60 36 36 0C 0C 4D 02" make = "Samyang" model = "24mm f/1.4 ED AS UMC" focal_range = [[24, 1], [24, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "4A 60 44 44 0C 0C 4D 02" make = "Samyang" model = "35mm f/1.4 AS UMC" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "4A 60 62 62 0C 0C 4D 02" make = "Samyang" model = "AE 85mm f/1.4 AS IF UMC" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 40 11 11 2C 2C 00 00" make = "Samyang" model = "8mm f/3.5 Fish-Eye" focal_range = [[8, 1], [8, 1]] aperture_range = [[35, 10], [35, 10]] rawler-0.7.1/data/lenses/f_mount/sigma.toml000064400000000000000000000743171046102023000170070ustar 00000000000000[[lenses]] mount = "F-mount" nikon_id = "FE 47 00 00 24 24 4B 06" make = "Sigma" model = "4.5mm F2.8 EX DC HSM Circular Fisheye" focal_range = [[45, 10], [45, 10]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 48 11 11 30 30 1C 02" make = "Sigma" model = "8mm F4 EX Circular Fisheye" focal_range = [[8, 1], [8, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "79 40 11 11 2C 2C 1C 06" make = "Sigma" model = "8mm F3.5 EX Circular Fisheye" focal_range = [[8, 1], [8, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "DB 40 11 11 2C 2C 1C 06" make = "Sigma" model = "8mm F3.5 EX DG Circular Fisheye" focal_range = [[8, 1], [8, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "DC 48 19 19 24 24 4B 06" make = "Sigma" model = "10mm F2.8 EX DC HSM Fisheye" focal_range = [[10, 1], [10, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "C2 4C 24 24 14 14 4B 06" make = "Sigma" model = "14mm F1.8 DG HSM | A" focal_range = [[14, 1], [14, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 48 24 24 24 24 4B 02" make = "Sigma" model = "14mm F2.8 EX Aspherical HSM" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 3F 24 24 2C 2C 02 00" make = "Sigma" model = "14mm F3.5" focal_range = [[14, 1], [14, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 48 27 27 24 24 1C 02" make = "Sigma" model = "15mm F2.8 EX Diagonal Fisheye" focal_range = [[15, 1], [15, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "EA 48 27 27 24 24 1C 02" make = "Sigma" model = "15mm F2.8 EX Diagonal Fisheye" focal_range = [[15, 1], [15, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 58 31 31 14 14 1C 02" make = "Sigma" model = "20mm F1.8 EX DG Aspherical RF" focal_range = [[20, 1], [20, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "79 54 31 31 0C 0C 4B 06" make = "Sigma" model = "20mm F1.4 DG HSM | A" focal_range = [[20, 1], [20, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 58 37 37 14 14 1C 02" make = "Sigma" model = "24mm F1.8 EX DG Aspherical Macro" focal_range = [[24, 1], [24, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "E1 58 37 37 14 14 1C 02" make = "Sigma" model = "24mm F1.8 EX DG Aspherical Macro" focal_range = [[24, 1], [24, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 46 37 37 25 25 02 00" make = "Sigma" model = "24mm F2.8 Super Wide II Macro" focal_range = [[24, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 58 3C 3C 14 14 1C 02" make = "Sigma" model = "28mm F1.8 EX DG Aspherical Macro" focal_range = [[28, 1], [28, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 54 3E 3E 0C 0C 4B 06" make = "Sigma" model = "30mm F1.4 EX DC HSM" focal_range = [[30, 1], [30, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "F8 54 3E 3E 0C 0C 4B 06" make = "Sigma" model = "30mm F1.4 EX DC HSM" focal_range = [[30, 1], [30, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "91 54 44 44 0C 0C 4B 06" make = "Sigma" model = "35mm F1.4 DG HSM" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "DE 54 50 50 0C 0C 4B 06" make = "Sigma" model = "50mm F1.4 EX DG HSM" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "88 54 50 50 0C 0C 4B 06" make = "Sigma" model = "50mm F1.4 DG HSM | A" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 48 50 50 24 24 02 00" make = "Sigma" model = "Macro 50mm F2.8" focal_range = [[50, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "32 54 50 50 24 24 35 02" make = "Sigma" model = "Macro 50mm F2.8 EX DG" focal_range = [[50, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "E3 54 50 50 24 24 35 02" make = "Sigma" model = "Macro 50mm F2.8 EX DG" focal_range = [[50, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "79 48 5C 5C 24 24 1C 06" make = "Sigma" model = "Macro 70mm F2.8 EX DG" focal_range = [[70, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "9B 54 62 62 0C 0C 4B 06" make = "Sigma" model = "85mm F1.4 EX DG HSM" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "C8 54 62 62 0C 0C 4B 46" make = "Sigma" model = "85mm F1.4 DG HSM | A" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "C8 54 62 62 0C 0C 4B 06" make = "Sigma" model = "85mm F1.4 DG HSM | A" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 48 65 65 24 24 02 00" make = "Sigma" model = "Macro 90mm F2.8" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "32 54 6A 6A 24 24 35 02.2" make = "Sigma" model = "Macro 105mm F2.8 EX DG" focal_range = [[105, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "E5 54 6A 6A 24 24 35 02" make = "Sigma" model = "Macro 105mm F2.8 EX DG" focal_range = [[105, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "97 48 6A 6A 24 24 4B 0E" make = "Sigma" model = "Macro 105mm F2.8 EX DG OS HSM" focal_range = [[105, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 48 76 76 24 24 4B 06" make = "Sigma" model = "APO Macro 150mm F2.8 EX DG HSM" focal_range = [[150, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "F5 48 76 76 24 24 4B 06" make = "Sigma" model = "APO Macro 150mm F2.8 EX DG HSM" focal_range = [[150, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "99 48 76 76 24 24 4B 0E" make = "Sigma" model = "APO Macro 150mm F2.8 EX DG OS HSM" focal_range = [[150, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 4C 7C 7C 2C 2C 4B 02" make = "Sigma" model = "APO Macro 180mm F3.5 EX DG HSM" focal_range = [[180, 1], [180, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 4C 7D 7D 2C 2C 4B 02" make = "Sigma" model = "APO Macro 180mm F3.5 EX DG HSM" focal_range = [[180, 1], [180, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "F4 4C 7C 7C 2C 2C 4B 02" make = "Sigma" model = "APO Macro 180mm F3.5 EX DG HSM" focal_range = [[180, 1], [180, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "94 48 7C 7C 24 24 4B 0E" make = "Sigma" model = "APO Macro 180mm F2.8 EX DG OS HSM" focal_range = [[180, 1], [180, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 54 8E 8E 24 24 4B 02" make = "Sigma" model = "APO 300mm F2.8 EX DG HSM" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "FB 54 8E 8E 24 24 4B 02" make = "Sigma" model = "APO 300mm F2.8 EX DG HSM" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 48 8E 8E 30 30 1C 02" make = "Sigma" model = "APO Tele Macro 300mm F4" focal_range = [[300, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "02 2F 98 98 3D 3D 02 00" make = "Sigma" model = "APO 400mm F5.6" focal_range = [[400, 1], [400, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 3C 98 98 3C 3C 1C 02" make = "Sigma" model = "APO Tele Macro 400mm F5.6" focal_range = [[400, 1], [400, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 37 A0 A0 34 34 02 00" make = "Sigma" model = "APO 500mm F4.5" focal_range = [[500, 1], [500, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 44 A0 A0 34 34 4B 02" make = "Sigma" model = "APO 500mm F4.5 EX HSM" focal_range = [[500, 1], [500, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "F1 44 A0 A0 34 34 4B 02" make = "Sigma" model = "APO 500mm F4.5 EX DG HSM" focal_range = [[500, 1], [500, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 34 A0 A0 44 44 02 00" make = "Sigma" model = "APO 500mm F7.2" focal_range = [[500, 1], [500, 1]] aperture_range = [[72, 10], [72, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 3C B0 B0 3C 3C 02 00" make = "Sigma" model = "APO 800mm F5.6" focal_range = [[800, 1], [800, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 3C B0 B0 3C 3C 4B 02" make = "Sigma" model = "APO 800mm F5.6 EX HSM" focal_range = [[800, 1], [800, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "9E 38 11 29 34 3C 4B 06" make = "Sigma" model = "8-16mm F4.5-5.6 DC HSM" focal_range = [[8, 1], [16, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "A1 41 19 31 2C 2C 4B 06" make = "Sigma" model = "10-20mm F3.5 EX DC HSM" focal_range = [[10, 1], [20, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 3C 19 31 30 3C 4B 06" make = "Sigma" model = "10-20mm F4-5.6 EX DC HSM" focal_range = [[10, 1], [20, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "F9 3C 19 31 30 3C 4B 06" make = "Sigma" model = "10-20mm F4-5.6 EX DC HSM" focal_range = [[10, 1], [20, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 38 1F 37 34 3C 4B 06" make = "Sigma" model = "12-24mm F4.5-5.6 EX DG Aspherical HSM" focal_range = [[12, 1], [24, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "F0 38 1F 37 34 3C 4B 06" make = "Sigma" model = "12-24mm F4.5-5.6 EX DG Aspherical HSM" focal_range = [[12, 1], [24, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "96 38 1F 37 34 3C 4B 06" make = "Sigma" model = "12-24mm F4.5-5.6 II DG HSM" focal_range = [[12, 1], [24, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "CA 3C 1F 37 30 30 4B 46" make = "Sigma" model = "12-24mm F4 DG HSM | A" focal_range = [[12, 1], [24, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "C1 48 24 37 24 24 4B 46" make = "Sigma" model = "14-24mm F2.8 DG HSM | A" focal_range = [[14, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 27 3F 2C 34 1C 02" make = "Sigma" model = "15-30mm F3.5-4.5 EX DG Aspherical DF" focal_range = [[15, 1], [30, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 48 2B 44 24 30 4B 06" make = "Sigma" model = "17-35mm F2.8-4 EX DG Aspherical HSM" focal_range = [[17, 1], [35, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "26 54 2B 44 24 30 1C 02" make = "Sigma" model = "17-35mm F2.8-4 EX Aspherical" focal_range = [[17, 1], [35, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "9D 48 2B 50 24 24 4B 0E" make = "Sigma" model = "17-50mm F2.8 EX DC OS HSM" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "8F 48 2B 50 24 24 4B 0E" make = "Sigma" model = "17-50mm F2.8 EX DC OS HSM" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "7A 47 2B 5C 24 34 4B 06" make = "Sigma" model = "17-70mm F2.8-4.5 DC Macro Asp. IF HSM" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "7A 48 2B 5C 24 34 4B 06" make = "Sigma" model = "17-70mm F2.8-4.5 DC Macro Asp. IF HSM" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "7F 48 2B 5C 24 34 1C 06" make = "Sigma" model = "17-70mm F2.8-4.5 DC Macro Asp. IF" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "8E 3C 2B 5C 24 30 4B 0E" make = "Sigma" model = "17-70mm F2.8-4 DC Macro OS HSM | C" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "A0 48 2A 5C 24 30 4B 0E" make = "Sigma" model = "17-70mm F2.8-4 DC Macro OS HSM" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "8B 4C 2D 44 14 14 4B 06" make = "Sigma" model = "18-35mm F1.8 DC HSM" focal_range = [[18, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 2D 44 2B 34 1C 02" make = "Sigma" model = "18-35mm F3.5-4.5 Aspherical" focal_range = [[18, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 48 2D 50 24 24 1C 06" make = "Sigma" model = "18-50mm F2.8 EX DC" focal_range = [[18, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "7F 48 2D 50 24 24 1C 06" make = "Sigma" model = "18-50mm F2.8 EX DC Macro" focal_range = [[18, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "7A 48 2D 50 24 24 4B 06" make = "Sigma" model = "18-50mm F2.8 EX DC Macro" focal_range = [[18, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "F6 48 2D 50 24 24 4B 06" make = "Sigma" model = "18-50mm F2.8 EX DC Macro" focal_range = [[18, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "A4 47 2D 50 24 34 4B 0E" make = "Sigma" model = "18-50mm F2.8-4.5 DC OS HSM" focal_range = [[18, 1], [50, 1]] aperture_range = [[28, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 2D 50 2C 3C 1C 06" make = "Sigma" model = "18-50mm F3.5-5.6 DC" focal_range = [[18, 1], [50, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "7A 40 2D 50 2C 3C 4B 06" make = "Sigma" model = "18-50mm F3.5-5.6 DC HSM" focal_range = [[18, 1], [50, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 2D 70 2B 3C 1C 06" make = "Sigma" model = "18-125mm F3.5-5.6 DC" focal_range = [[18, 1], [125, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "CD 3D 2D 70 2E 3C 4B 0E" make = "Sigma" model = "18-125mm F3.8-5.6 DC OS HSM" focal_range = [[18, 1], [125, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 2D 80 2C 40 1C 06" make = "Sigma" model = "18-200mm F3.5-6.3 DC" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "FF 40 2D 80 2C 40 4B 06" make = "Sigma" model = "18-200mm F3.5-6.3 DC" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "7A 40 2D 80 2C 40 4B 0E" make = "Sigma" model = "18-200mm F3.5-6.3 DC OS HSM" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "ED 40 2D 80 2C 40 4B 0E" make = "Sigma" model = "18-200mm F3.5-6.3 DC OS HSM" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "90 40 2D 80 2C 40 4B 0E" make = "Sigma" model = "18-200mm F3.5-6.3 II DC OS HSM" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "89 30 2D 80 2C 40 4B 0E" make = "Sigma" model = "18-200mm F3.5-6.3 DC Macro OS HS | C" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "A5 40 2D 88 2C 40 4B 0E" make = "Sigma" model = "18-250mm F3.5-6.3 DC OS HSM" focal_range = [[18, 1], [250, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "92 2C 2D 88 2C 40 4B 0E" make = "Sigma" model = "18-250mm F3.5-6.3 DC Macro OS HSM" focal_range = [[18, 1], [250, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "87 2C 2D 8E 2C 40 4B 0E" make = "Sigma" model = "18-300mm F3.5-6.3 DC Macro HSM" focal_range = [[18, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 48 31 49 24 24 1C 02" make = "Sigma" model = "20-40mm F2.8" focal_range = [[20, 1], [40, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "7B 48 37 44 18 18 4B 06" make = "Sigma" model = "24-35mm F2.0 DG HSM | A" focal_range = [[24, 1], [35, 1]] aperture_range = [[20, 10], [20, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 3A 37 50 31 3D 02 00" make = "Sigma" model = "24-50mm F4-5.6 UC" focal_range = [[24, 1], [50, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 48 37 56 24 24 1C 02" make = "Sigma" model = "24-60mm F2.8 EX DG" focal_range = [[24, 1], [60, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "B6 48 37 56 24 24 1C 02" make = "Sigma" model = "24-60mm F2.8 EX DG" focal_range = [[24, 1], [60, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "A6 48 37 5C 24 24 4B 06" make = "Sigma" model = "24-70mm F2.8 IF EX DG HSM" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "C9 48 37 5C 24 24 4B 4E" make = "Sigma" model = "24-70mm F2.8 DG OS HSM | A" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 54 37 5C 24 24 1C 02" make = "Sigma" model = "24-70mm F2.8 EX DG Macro" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "67 54 37 5C 24 24 1C 02" make = "Sigma" model = "24-70mm F2.8 EX DG Macro" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "E9 54 37 5C 24 24 1C 02" make = "Sigma" model = "24-70mm F2.8 EX DG Macro" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 37 5C 2C 3C 1C 02" make = "Sigma" model = "24-70mm F3.5-5.6 Aspherical HF" focal_range = [[24, 1], [70, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "8A 3C 37 6A 30 30 4B 0E" make = "Sigma" model = "24-105mm F4 DG OS HSM" focal_range = [[24, 1], [105, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "26 54 37 73 24 34 1C 02" make = "Sigma" model = "24-135mm F2.8-4.5" focal_range = [[24, 1], [135, 1]] aperture_range = [[28, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 46 3C 5C 25 25 02 00" make = "Sigma" model = "28-70mm F2.8" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 54 3C 5C 24 24 1C 02" make = "Sigma" model = "28-70mm F2.8 EX" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 48 3C 5C 24 24 1C 06" make = "Sigma" model = "28-70mm F2.8 EX DG" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "79 48 3C 5C 24 24 1C 06" make = "Sigma" model = "28-70mm F2.8 EX DG" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 48 3C 5C 24 30 1C 02" make = "Sigma" model = "28-70mm F2.8-4 DG" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "02 3F 3C 5C 2D 35 02 00" make = "Sigma" model = "28-70mm F3.5-4.5 UC" focal_range = [[28, 1], [70, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 3C 60 2C 3C 1C 02" make = "Sigma" model = "28-80mm F3.5-5.6 Mini Zoom Macro II Aspherical" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 3C 65 2C 3C 1C 02" make = "Sigma" model = "28-90mm F3.5-5.6 Macro" focal_range = [[28, 1], [90, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 48 3C 6A 24 30 1C 02" make = "Sigma" model = "28-105mm F2.8-4 Aspherical" focal_range = [[28, 1], [105, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "26 3E 3C 6A 2E 3C 1C 02" make = "Sigma" model = "28-105mm F3.8-5.6 UC-III Aspherical IF" focal_range = [[28, 1], [105, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 3C 80 2C 3C 1C 02" make = "Sigma" model = "28-200mm F3.5-5.6 Compact Aspherical Hyperzoom Macro" focal_range = [[28, 1], [200, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 3C 80 2B 3C 1C 02" make = "Sigma" model = "28-200mm F3.5-5.6 Compact Aspherical Hyperzoom Macro" focal_range = [[28, 1], [200, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 3D 3C 80 2F 3D 1C 02" make = "Sigma" model = "28-300mm F3.8-5.6 Aspherical" focal_range = [[28, 1], [300, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 41 3C 8E 2C 40 1C 02" make = "Sigma" model = "28-300mm F3.5-6.3 DG Macro" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "E6 41 3C 8E 2C 40 1C 02" make = "Sigma" model = "28-300mm F3.5-6.3 DG Macro" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 3C 8E 2C 40 1C 02" make = "Sigma" model = "28-300mm F3.5-6.3 Macro" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 3B 44 61 30 3D 02 00" make = "Sigma" model = "35-80mm F4-5.6" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 40 44 73 2B 36 02 00" make = "Sigma" model = "35-135mm F3.5-4.5 a" focal_range = [[35, 1], [135, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "CC 4C 50 68 14 14 4B 06" make = "Sigma" model = "50-100mm F1.8 DC HSM | A" focal_range = [[50, 1], [100, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "7A 47 50 76 24 24 4B 06" make = "Sigma" model = "50-150mm F2.8 EX APO DC HSM" focal_range = [[50, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "FD 47 50 76 24 24 4B 06" make = "Sigma" model = "50-150mm F2.8 EX APO DC HSM II" focal_range = [[50, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "98 48 50 76 24 24 4B 0E" make = "Sigma" model = "50-150mm F2.8 EX APO DC OS HSM" focal_range = [[50, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 3C 50 A0 30 40 4B 02" make = "Sigma" model = "50-500mm F4-6.3 EX APO RF HSM" focal_range = [[50, 1], [500, 1]] aperture_range = [[4, 1], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "9F 37 50 A0 34 40 4B 0E" make = "Sigma" model = "50-500mm F4.5-6.3 DG OS HSM" focal_range = [[50, 1], [500, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 3C 54 80 30 3C 1C 06" make = "Sigma" model = "55-200mm F4-5.6 DC" focal_range = [[55, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "7A 3B 53 80 30 3C 4B 06" make = "Sigma" model = "55-200mm F4-5.6 DC HSM" focal_range = [[55, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 54 5C 80 24 24 4B 02" make = "Sigma" model = "70-200mm F2.8 EX APO IF HSM" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "7A 48 5C 80 24 24 4B 06" make = "Sigma" model = "70-200mm F2.8 EX APO DG Macro HSM II" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "EE 48 5C 80 24 24 4B 06" make = "Sigma" model = "70-200mm F2.8 EX APO DG Macro HSM II" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "9C 48 5C 80 24 24 4B 0E" make = "Sigma" model = "70-200mm F2.8 EX DG OS HSM" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "BB 48 5C 80 24 24 4B 4E" make = "Sigma" model = "70-200mm F2.8 DG OS HSM | S" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 46 5C 82 25 25 02 00" make = "Sigma" model = "70-210mm F2.8 APO" focal_range = [[70, 1], [210, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 40 5C 82 2C 35 02 00" make = "Sigma" model = "APO 70-210mm F3.5-4.5" focal_range = [[70, 1], [210, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 3C 5C 82 30 3C 1C 02" make = "Sigma" model = "70-210mm F4-5.6 UC-II" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 3B 5C 82 30 3C 02 00" make = "Sigma" model = "Zoom-K 70-210mm F4-5.6" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 3C 5C 8E 30 3C 1C 02" make = "Sigma" model = "70-300mm F4-5.6 DG Macro" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "56 3C 5C 8E 30 3C 1C 02" make = "Sigma" model = "70-300mm F4-5.6 APO Macro Super II" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "E0 3C 5C 8E 30 3C 4B 06" make = "Sigma" model = "70-300mm F4-5.6 APO DG Macro HSM" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "A3 3C 5C 8E 30 3C 4B 0E" make = "Sigma" model = "70-300mm F4-5.6 DG OS" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 37 5E 8E 35 3D 02 00" make = "Sigma" model = "75-300mm F4.5-5.6 APO" focal_range = [[75, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "02 3A 5E 8E 32 3D 02 00" make = "Sigma" model = "75-300mm F4.0-5.6" focal_range = [[75, 1], [300, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "77 44 61 98 34 3C 7B 0E" make = "Sigma" model = "80-400mm F4.5-5.6 EX OS" focal_range = [[80, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "77 44 60 98 34 3C 7B 0E" make = "Sigma" model = "80-400mm F4.5-5.6 APO DG D OS" focal_range = [[80, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 48 68 8E 30 30 4B 02" make = "Sigma" model = "APO 100-300mm F4 EX IF HSM" focal_range = [[100, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "F3 48 68 8E 30 30 4B 02" make = "Sigma" model = "APO 100-300mm F4 EX IF HSM" focal_range = [[100, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "26 45 68 8E 34 42 1C 02" make = "Sigma" model = "100-300mm F4.5-6.7 DL" focal_range = [[100, 1], [300, 1]] aperture_range = [[45, 10], [67, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 54 6F 8E 24 24 4B 02" make = "Sigma" model = "APO 120-300mm F2.8 EX DG HSM" focal_range = [[120, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "7A 54 6E 8E 24 24 4B 02" make = "Sigma" model = "APO 120-300mm F2.8 EX DG HSM" focal_range = [[120, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "FA 54 6E 8E 24 24 4B 02" make = "Sigma" model = "APO 120-300mm F2.8 EX DG HSM" focal_range = [[120, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "CF 38 6E 98 34 3C 4B 0E" make = "Sigma" model = "APO 120-400mm F4.5-5.6 DG OS HSM" focal_range = [[120, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "C3 34 68 98 38 40 4B 4E" make = "Sigma" model = "100-400mm F5-6.3 DG OS HSM | C" focal_range = [[100, 1], [400, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "8D 48 6E 8E 24 24 4B 0E" make = "Sigma" model = "120-300mm F2.8 DG OS HSM Sports" focal_range = [[120, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 44 73 98 34 3C 1C 02" make = "Sigma" model = "135-400mm F4.5-5.6 APO Aspherical" focal_range = [[135, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "CE 34 76 A0 38 40 4B 0E" make = "Sigma" model = "150-500mm F5-6.3 DG OS APO HSM" focal_range = [[150, 1], [500, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "81 34 76 A6 38 40 4B 0E" make = "Sigma" model = "150-600mm F5-6.3 DG OS HSM | S" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "82 34 76 A6 38 40 4B 0E" make = "Sigma" model = "150-600mm F5-6.3 DG OS HSM | C" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "C4 4C 73 73 14 14 4B 46" make = "Sigma" model = "135mm F1.8 DG HSM | A" focal_range = [[135, 1], [135, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "26 40 7B A0 34 40 1C 02" make = "Sigma" model = "APO 170-500mm F5-6.3 Aspherical RF" focal_range = [[170, 1], [500, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "A7 49 80 A0 24 24 4B 06" make = "Sigma" model = "APO 200-500mm F2.8 EX DG" focal_range = [[200, 1], [500, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "48 3C 8E B0 3C 3C 4B 02" make = "Sigma" model = "APO 300-800mm F5.6 EX DG HSM" focal_range = [[300, 1], [800, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "D2 3C 8E B0 3C 3C 4B 02" make = "Sigma" model = "APO 300-800mm F5.6 EX DG HSM" focal_range = [[300, 1], [800, 1]] aperture_range = [[56, 10], [56, 10]] rawler-0.7.1/data/lenses/f_mount/sony.toml000064400000000000000000000005541046102023000166670ustar 00000000000000[[lenses]] mount = "F-mount" nikon_id = "A0 56 44 44 14 14 A2 06" make = "Sony" model = "FE 35mm F1.8" focal_range = [[35, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "A0 37 5C 8E 34 3C A2 06" make = "Sony" model = "FE 70-300mm F4.5-5.6 G OSS" focal_range = [[70, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] rawler-0.7.1/data/lenses/f_mount/tamron.toml000064400000000000000000000405631046102023000172030ustar 00000000000000[[lenses]] mount = "F-mount" nikon_id = "00 47 25 25 24 24 00 02" make = "Tamron" model = "SP AF 14mm f/2.8 Aspherical (IF) (69E)" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "C8 54 44 44 0D 0D DF 46" make = "Tamron" model = "SP 35mm f/1.4 Di USD (F045)" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "E8 4C 44 44 14 14 DF 0E" make = "Tamron" model = "SP 35mm f/1.8 Di VC USD (F012)" focal_range = [[35, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "E7 4C 4C 4C 14 14 DF 0E" make = "Tamron" model = "SP 45mm f/1.8 Di VC USD (F013)" focal_range = [[45, 1], [45, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "F4 54 56 56 18 18 84 06" make = "Tamron" model = "SP AF 60mm f/2.0 Di II Macro 1:1 (G005)" focal_range = [[60, 1], [60, 1]] aperture_range = [[20, 10], [20, 10]] [[lenses]] mount = "F-mount" nikon_id = "E5 4C 62 62 14 14 C9 4E" make = "Tamron" model = "SP 85mm f/1.8 Di VC USD (F016)" focal_range = [[85, 1], [85, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "F-mount" nikon_id = "1E 5D 64 64 20 20 13 00" make = "Tamron" model = "SP AF 90mm f/2.5 (52E)" focal_range = [[90, 1], [90, 1]] aperture_range = [[25, 10], [25, 10]] [[lenses]] mount = "F-mount" nikon_id = "20 5A 64 64 20 20 14 00" make = "Tamron" model = "SP AF 90mm f/2.5 Macro (152E)" focal_range = [[90, 1], [90, 1]] aperture_range = [[25, 10], [25, 10]] [[lenses]] mount = "F-mount" nikon_id = "22 53 64 64 24 24 E0 02" make = "Tamron" model = "SP AF 90mm f/2.8 Macro 1:1 (72E)" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "32 53 64 64 24 24 35 02" make = "Tamron" model = "SP AF 90mm f/2.8 [Di] Macro 1:1 (172E/272E)" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "F8 55 64 64 24 24 84 06" make = "Tamron" model = "SP AF 90mm f/2.8 Di Macro 1:1 (272NII)" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "F8 54 64 64 24 24 DF 06" make = "Tamron" model = "SP AF 90mm f/2.8 Di Macro 1:1 (272NII)" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "FE 54 64 64 24 24 DF 0E" make = "Tamron" model = "SP 90mm f/2.8 Di VC USD Macro 1:1 (F004)" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "E4 54 64 64 24 24 DF 0E" make = "Tamron" model = "SP 90mm f/2.8 Di VC USD Macro 1:1 (F017)" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 4C 7C 7C 2C 2C 00 02" make = "Tamron" model = "SP AF 180mm f/3.5 Di Model (B01)" focal_range = [[180, 1], [180, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "21 56 8E 8E 24 24 14 00" make = "Tamron" model = "SP AF 300mm f/2.8 LD-IF (60E)" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "27 54 8E 8E 24 24 1D 02" make = "Tamron" model = "SP AF 300mm f/2.8 LD-IF (360E)" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "E1 40 19 36 2C 35 DF 4E" make = "Tamron" model = "10-24mm f/3.5-4.5 Di II VC HLD (B023)" focal_range = [[10, 1], [24, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "F6 3F 18 37 2C 34 84 06" make = "Tamron" model = "SP AF 10-24mm f/3.5-4.5 Di II LD Aspherical (IF) (B001)" focal_range = [[10, 1], [24, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "F6 3F 18 37 2C 34 DF 06" make = "Tamron" model = "SP AF 10-24mm f/3.5-4.5 Di II LD Aspherical (IF) (B001)" focal_range = [[10, 1], [24, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 36 1C 2D 34 3C 00 06" make = "Tamron" model = "SP AF 11-18mm f/4.5-5.6 Di II LD Aspherical (IF) (A13)" focal_range = [[11, 1], [18, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "E9 48 27 3E 24 24 DF 0E" make = "Tamron" model = "SP 15-30mm f/2.8 Di VC USD (A012)" focal_range = [[15, 1], [30, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "CA 48 27 3E 24 24 DF 4E" make = "Tamron" model = "SP 15-30mm f/2.8 Di VC USD G2 (A041)" focal_range = [[15, 1], [30, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "EA 40 29 8E 2C 40 DF 0E" make = "Tamron" model = "16-300mm f/3.5-6.3 Di II VC PZD (B016)" focal_range = [[16, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "07 46 2B 44 24 30 03 02" make = "Tamron" model = "SP AF 17-35mm f/2.8-4 Di LD Aspherical (IF) (A05)" focal_range = [[17, 1], [35, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "CB 3C 2B 44 24 31 DF 46" make = "Tamron" model = "17-35mm f/2.8-4 Di OSD (A037)" focal_range = [[17, 1], [35, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 53 2B 50 24 24 00 06" make = "Tamron" model = "SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16)" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "7C 54 2B 50 24 24 00 06" make = "Tamron" model = "SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16)" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 54 2B 50 24 24 00 06" make = "Tamron" model = "SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16NII)" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "FB 54 2B 50 24 24 84 06" make = "Tamron" model = "SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16NII)" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "F3 54 2B 50 24 24 84 0E" make = "Tamron" model = "SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical (IF) (B005)" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 3F 2D 80 2B 40 00 06" make = "Tamron" model = "AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) (A14)" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 3F 2D 80 2C 40 00 06" make = "Tamron" model = "AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14)" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "EC 3E 3C 8E 2C 40 DF 0E" make = "Tamron" model = "28-300mm f/3.5-6.3 Di VC PZD A010" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 40 2D 80 2C 40 00 06" make = "Tamron" model = "AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14NII)" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "FC 40 2D 80 2C 40 DF 06" make = "Tamron" model = "AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14NII)" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "E6 40 2D 80 2C 40 DF 0E" make = "Tamron" model = "18-200mm f/3.5-6.3 Di II VC (B018)" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 40 2D 88 2C 40 62 06" make = "Tamron" model = "AF 18-250mm f/3.5-6.3 Di II LD Aspherical (IF) Macro (A18)" focal_range = [[18, 1], [250, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 40 2D 88 2C 40 00 06" make = "Tamron" model = "AF 18-250mm f/3.5-6.3 Di II LD Aspherical (IF) Macro (A18NII)" focal_range = [[18, 1], [250, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "F5 40 2C 8A 2C 40 40 0E" make = "Tamron" model = "AF 18-270mm f/3.5-6.3 Di II VC LD Aspherical (IF) Macro (B003)" focal_range = [[18, 1], [270, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "F0 3F 2D 8A 2C 40 DF 0E" make = "Tamron" model = "AF 18-270mm f/3.5-6.3 Di II VC PZD (B008)" focal_range = [[18, 1], [270, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "E0 40 2D 98 2C 41 DF 4E" make = "Tamron" model = "18-400mm f/3.5-6.3 Di II VC HLD (B028)" focal_range = [[18, 1], [400, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "07 40 2F 44 2C 34 03 02" make = "Tamron" model = "AF 19-35mm f/3.5-4.5 (A10)" focal_range = [[19, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "07 40 30 45 2D 35 03 02.1" make = "Tamron" model = "AF 19-35mm f/3.5-4.5 (A10)" focal_range = [[19, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 49 30 48 22 2B 00 02" make = "Tamron" model = "SP AF 20-40mm f/2.7-3.5 (166D)" focal_range = [[20, 1], [40, 1]] aperture_range = [[27, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "0E 4A 31 48 23 2D 0E 02" make = "Tamron" model = "SP AF 20-40mm f/2.7-3.5 (166D)" focal_range = [[20, 1], [40, 1]] aperture_range = [[27, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "FE 48 37 5C 24 24 DF 0E" make = "Tamron" model = "SP 24-70mm f/2.8 Di VC USD (A007)" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "CE 47 37 5C 25 25 DF 4E" make = "Tamron" model = "SP 24-70mm f/2.8 Di VC USD G2 (A032)" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "45 41 37 72 2C 3C 48 02" make = "Tamron" model = "SP AF 24-135mm f/3.5-5.6 AD Aspherical (IF) Macro (190D)" focal_range = [[24, 1], [135, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "33 54 3C 5E 24 24 62 02" make = "Tamron" model = "SP AF 28-75mm f/2.8 XR Di LD Aspherical (IF) Macro (A09)" focal_range = [[28, 1], [75, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "FA 54 3C 5E 24 24 84 06" make = "Tamron" model = "SP AF 28-75mm f/2.8 XR Di LD Aspherical (IF) Macro (A09NII)" focal_range = [[28, 1], [75, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "FA 54 3C 5E 24 24 DF 06" make = "Tamron" model = "SP AF 28-75mm f/2.8 XR Di LD Aspherical (IF) Macro (A09NII)" focal_range = [[28, 1], [75, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "10 3D 3C 60 2C 3C D2 02" make = "Tamron" model = "AF 28-80mm f/3.5-5.6 Aspherical (177D)" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "45 3D 3C 60 2C 3C 48 02" make = "Tamron" model = "AF 28-80mm f/3.5-5.6 Aspherical (177D)" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 48 3C 6A 24 24 00 02" make = "Tamron" model = "SP AF 28-105mm f/2.8 LD Aspherical IF (176D)" focal_range = [[28, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "4D 3E 3C 80 2E 3C 62 02" make = "Tamron" model = "AF 28-200mm f/3.8-5.6 XR Aspherical (IF) Macro (A03N)" focal_range = [[28, 1], [200, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "0B 3E 3D 7F 2F 3D 0E 00" make = "Tamron" model = "AF 28-200mm f/3.8-5.6 (71D)" focal_range = [[28, 1], [200, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "0B 3E 3D 7F 2F 3D 0E 02" make = "Tamron" model = "AF 28-200mm f/3.8-5.6D (171D)" focal_range = [[28, 1], [200, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "12 3D 3C 80 2E 3C DF 02" make = "Tamron" model = "AF 28-200mm f/3.8-5.6 AF Aspherical LD (IF) (271D)" focal_range = [[28, 1], [200, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "4D 41 3C 8E 2B 40 62 02" make = "Tamron" model = "AF 28-300mm f/3.5-6.3 XR Di LD Aspherical (IF) (A061)" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "4D 41 3C 8E 2C 40 62 02" make = "Tamron" model = "AF 28-300mm f/3.5-6.3 XR LD Aspherical (IF) (185D)" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "F9 40 3C 8E 2C 40 40 0E" make = "Tamron" model = "AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical (IF) Macro (A20)" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "C9 3C 44 76 25 31 DF 4E" make = "Tamron" model = "35-150mm f/2.8-4 Di VC OSD (A043)" focal_range = [[35, 1], [150, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 47 53 80 30 3C 00 06" make = "Tamron" model = "AF 55-200mm f/4-5.6 Di II LD (A15)" focal_range = [[55, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "F7 53 5C 80 24 24 84 06" make = "Tamron" model = "SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001)" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "FE 53 5C 80 24 24 84 06" make = "Tamron" model = "SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001)" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "F7 53 5C 80 24 24 40 06" make = "Tamron" model = "SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001)" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "FE 54 5C 80 24 24 DF 0E" make = "Tamron" model = "SP AF 70-200mm f/2.8 Di VC USD (A009)" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "FE 54 5C 80 24 24 DF 0E" make = "Tamron" model = "SP 70-200mm f/2.8 Di VC USD (A009)" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "E2 47 5C 80 24 24 DF 4E" make = "Tamron" model = "SP 70-200mm f/2.8 Di VC USD G2 (A025)" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "69 48 5C 8E 30 3C 6F 02" make = "Tamron" model = "AF 70-300mm f/4-5.6 LD Macro 1:2 (572D/772D)" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "69 47 5C 8E 30 3C 00 02" make = "Tamron" model = "AF 70-300mm f/4-5.6 Di LD Macro 1:2 (A17N)" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 48 5C 8E 30 3C 00 06" make = "Tamron" model = "AF 70-300mm f/4-5.6 Di LD Macro 1:2 (A17NII)" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "F1 47 5C 8E 30 3C DF 0E" make = "Tamron" model = "SP 70-300mm f/4-5.6 Di VC USD (A005)" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "CF 47 5C 8E 31 3D DF 0E" make = "Tamron" model = "SP 70-300mm f/4-5.6 Di VC USD (A030)" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "CC 44 68 98 34 41 DF 0E" make = "Tamron" model = "100-400mm f/4.5-6.3 Di VC USD" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "EB 40 76 A6 38 40 DF 0E" make = "Tamron" model = "SP AF 150-600mm f/5-6.3 VC USD (A011)" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "E3 40 76 A6 38 40 DF 4E" make = "Tamron" model = "SP 150-600mm f/5-6.3 Di VC USD G2" focal_range = [[150, 1], [600, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "20 3C 80 98 3D 3D 1E 02" make = "Tamron" model = "AF 200-400mm f/5.6 LD IF (75D)" focal_range = [[200, 1], [400, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 3E 80 A0 38 3F 00 02" make = "Tamron" model = "SP AF 200-500mm f/5-6.3 Di LD (IF) (A08)" focal_range = [[200, 1], [500, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 3F 80 A0 38 3F 00 02" make = "Tamron" model = "SP AF 200-500mm f/5-6.3 Di (A08)" focal_range = [[200, 1], [500, 1]] aperture_range = [[5, 1], [63, 10]] rawler-0.7.1/data/lenses/f_mount/tokina.toml000064400000000000000000000177751046102023000172010ustar 00000000000000[[lenses]] mount = "F-mount" nikon_id = "00 40 2B 2B 2C 2C 00 02" make = "Tokina" model = "AT-X 17 AF PRO (AF 17mm f/3.5)" focal_range = [[17, 1], [17, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 47 44 44 24 24 00 06" make = "Tokina" model = "AT-X M35 PRO DX (AF 35mm f/2.8 Macro)" focal_range = [[35, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 54 68 68 24 24 00 02" make = "Tokina" model = "AT-X M100 AF PRO D (AF 100mm f/2.8 Macro)" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "27 48 8E 8E 30 30 1D 02" make = "Tokina" model = "AT-X 304 AF (AF 300mm f/4.0)" focal_range = [[300, 1], [300, 1]] aperture_range = [[40, 10], [40, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 54 8E 8E 24 24 00 02" make = "Tokina" model = "AT-X 300 AF PRO (AF 300mm f/2.8)" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "12 3B 98 98 3D 3D 09 00" make = "Tokina" model = "AT-X 400 AF SD (AF 400mm f/5.6)" focal_range = [[400, 1], [400, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 40 18 2B 2C 34 00 06" make = "Tokina" model = "AT-X 107 AF DX Fisheye (AF 10-17mm f/3.5-4.5)" focal_range = [[10, 1], [17, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 48 1C 29 24 24 00 06" make = "Tokina" model = "AT-X 116 PRO DX (AF 11-16mm f/2.8)" focal_range = [[11, 1], [16, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "7A 48 1C 29 24 24 7E 06" make = "Tokina" model = "AT-X 116 PRO DX II (AF 11-16mm f/2.8)" focal_range = [[11, 1], [16, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "80 48 1C 29 24 24 7A 06" make = "Tokina" model = "atx-i 11-16mm F2.8 CF" focal_range = [[11, 1], [16, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "7A 48 1C 30 24 24 7E 06" make = "Tokina" model = "AT-X 11-20 F2.8 PRO DX (AF 11-20mm f/2.8)" focal_range = [[11, 1], [20, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "8B 48 1C 30 24 24 85 06" make = "Tokina" model = "AT-X 11-20 F2.8 PRO DX (AF 11-20mm f/2.8)" focal_range = [[11, 1], [20, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 3C 1F 37 30 30 00 06" make = "Tokina" model = "AT-X 124 AF PRO DX (AF 12-24mm f/4)" focal_range = [[12, 1], [24, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "7A 3C 1F 37 30 30 7E 06.2" make = "Tokina" model = "AT-X 124 AF PRO DX II (AF 12-24mm f/4)" focal_range = [[12, 1], [24, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "7A 3C 1F 3C 30 30 7E 06" make = "Tokina" model = "AT-X 12-28 PRO DX (AF 12-28mm f/4)" focal_range = [[12, 1], [28, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 48 29 3C 24 24 00 06" make = "Tokina" model = "AT-X 16-28 AF PRO FX (AF 16-28mm f/2.8)" focal_range = [[16, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 48 29 50 24 24 00 06" make = "Tokina" model = "AT-X 165 PRO DX (AF 16-50mm f/2.8)" focal_range = [[16, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 40 2A 72 2C 3C 00 06" make = "Tokina" model = "AT-X 16.5-135 DX (AF 16.5-135mm F3.5-5.6)" focal_range = [[165, 10], [135, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 3C 2B 44 30 30 00 06" make = "Tokina" model = "AT-X 17-35 F4 PRO FX (AF 17-35mm f/4)" focal_range = [[17, 1], [35, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "2F 40 30 44 2C 34 29 02.2" make = "Tokina" model = "AF 193 (AF 19-35mm f/3.5-4.5)" focal_range = [[19, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "2F 48 30 44 24 24 29 02.2" make = "Tokina" model = "AT-X 235 AF PRO (AF 20-35mm f/2.8)" focal_range = [[20, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "2F 40 30 44 2C 34 29 02.1" make = "Tokina" model = "AF 235 II (AF 20-35mm f/3.5-4.5)" focal_range = [[20, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 48 37 5C 24 24 00 06" make = "Tokina" model = "AT-X 24-70 F2.8 PRO FX (AF 24-70mm f/2.8)" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 40 37 80 2C 3C 00 02" make = "Tokina" model = "AT-X 242 AF (AF 24-200mm f/3.5-5.6)" focal_range = [[24, 1], [200, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "25 48 3C 5C 24 24 1B 02.1" make = "Tokina" model = "AT-X 270 AF PRO II (AF 28-70mm f/2.6-2.8)" focal_range = [[28, 1], [70, 1]] aperture_range = [[26, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "25 48 3C 5C 24 24 1B 02.2" make = "Tokina" model = "AT-X 287 AF PRO SV (AF 28-70mm f/2.8)" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "07 48 3C 5C 24 24 03 00" make = "Tokina" model = "AT-X 287 AF (AF 28-70mm f/2.8)" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "07 47 3C 5C 25 35 03 00" make = "Tokina" model = "AF 287 SD (AF 28-70mm f/2.8-4.5)" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "07 40 3C 5C 2C 35 03 00" make = "Tokina" model = "AF 270 II (AF 28-70mm f/3.5-4.5)" focal_range = [[28, 1], [70, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 48 3C 60 24 24 00 02" make = "Tokina" model = "AT-X 280 AF PRO (AF 28-80mm f/2.8)" focal_range = [[28, 1], [80, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "25 44 44 8E 34 42 1B 02" make = "Tokina" model = "AF 353 (AF 35-300mm f/4.5-6.7)" focal_range = [[35, 1], [300, 1]] aperture_range = [[45, 10], [67, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 48 50 72 24 24 00 06" make = "Tokina" model = "AT-X 535 PRO DX (AF 50-135mm f/2.8)" focal_range = [[50, 1], [135, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 3C 5C 80 30 30 00 0E" make = "Tokina" model = "AT-X 70-200 F4 FX VCM-S (AF 70-200mm f/4)" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 48 5C 80 30 30 00 0E" make = "Tokina" model = "AT-X 70-200 F4 FX VCM-S (AF 70-200mm f/4)" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "12 44 5E 8E 34 3C 09 00" make = "Tokina" model = "AF 730 (AF 75-300mm F4.5-5.6)" focal_range = [[75, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "14 54 60 80 24 24 0B 00" make = "Tokina" model = "AT-X 828 AF (AF 80-200mm f/2.8)" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "24 54 60 80 24 24 1A 02" make = "Tokina" model = "AT-X 828 AF PRO (AF 80-200mm f/2.8)" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "24 44 60 98 34 3C 1A 02" make = "Tokina" model = "AT-X 840 AF-II (AF 80-400mm f/4.5-5.6)" focal_range = [[80, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 44 60 98 34 3C 00 02" make = "Tokina" model = "AT-X 840 D (AF 80-400mm f/4.5-5.6)" focal_range = [[80, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "F-mount" nikon_id = "14 48 68 8E 30 30 0B 00" make = "Tokina" model = "AT-X 340 AF (AF 100-300mm f/4)" focal_range = [[100, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "F-mount" nikon_id = "8C 48 29 3C 24 24 86 06" make = "Tokina" model = "opera 16-28mm F2.8 FF" focal_range = [[16, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] rawler-0.7.1/data/lenses/f_mount/voigtlander.toml000064400000000000000000000022611046102023000202120ustar 00000000000000[[lenses]] mount = "F-mount" nikon_id = "00 40 31 31 2C 2C 00 00" make = "Voigtlander" model = "Color Skopar 20mm F3.5 SLII Aspherical" focal_range = [[20, 1], [20, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 48 3C 3C 24 24 00 00" make = "Voigtlander" model = "Color Skopar 28mm F2.8 SL II" focal_range = [[28, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 54 48 48 18 18 00 00" make = "Voigtlander" model = "Ultron 40mm F2 SLII Aspherical" focal_range = [[40, 1], [40, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 54 55 55 0C 0C 00 00" make = "Voigtlander" model = "Nokton 58mm F1.4 SLII" focal_range = [[58, 1], [58, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 40 64 64 2C 2C 00 00" make = "Voigtlander" model = "APO-Lanthar 90mm F3.5 SLII Close Focus" focal_range = [[90, 1], [90, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "07 40 30 45 2D 35 03 02.2" make = "Voigtlander" model = "Ultragon 19-35mm F3.5-4.5 VMV" focal_range = [[19, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] rawler-0.7.1/data/lenses/f_mount/zeiss.toml000064400000000000000000000071751046102023000170420ustar 00000000000000[[lenses]] mount = "F-mount" nikon_id = "00 40 2D 2D 2C 2C 00 00" make = "Carl Zeiss" model = "Distagon T* 3.5/18 ZF.2" focal_range = [[18, 1], [18, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 48 27 27 24 24 00 00" make = "Carl Zeiss" model = "Distagon T* 2.8/15 ZF.2" focal_range = [[15, 1], [15, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 48 32 32 24 24 00 00" make = "Carl Zeiss" model = "Distagon T* 2.8/21 ZF.2" focal_range = [[21, 1], [21, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 54 38 38 18 18 00 00" make = "Carl Zeiss" model = "Distagon T* 2/25 ZF.2" focal_range = [[25, 1], [25, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 54 3C 3C 18 18 00 00" make = "Carl Zeiss" model = "Distagon T* 2/28 ZF.2" focal_range = [[28, 1], [28, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 54 44 44 0C 0C 00 00" make = "Carl Zeiss" model = "Distagon T* 1.4/35 ZF.2" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 54 44 44 18 18 00 00" make = "Carl Zeiss" model = "Distagon T* 2/35 ZF.2" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 54 50 50 0C 0C 00 00" make = "Carl Zeiss" model = "Planar T* 1.4/50 ZF.2" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 54 50 50 18 18 00 00" make = "Carl Zeiss" model = "Makro-Planar T* 2/50 ZF.2" focal_range = [[50, 1], [50, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 54 62 62 0C 0C 00 00" make = "Carl Zeiss" model = "Planar T* 1.4/85 ZF.2" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "00 54 68 68 18 18 00 00" make = "Carl Zeiss" model = "Makro-Planar T* 2/100 ZF.2" focal_range = [[100, 1], [100, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 54 72 72 18 18 00 00" make = "Carl Zeiss" model = "Apo Sonnar T* 2/135 ZF.2" focal_range = [[135, 1], [135, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "00 54 53 53 0C 0C 00 00" make = "Zeiss" model = "Otus 1.4/55" focal_range = [[55, 1], [55, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "01 54 62 62 0C 0C 00 00" make = "Zeiss" model = "Otus 1.4/85" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "03 54 68 68 0C 0C 00 00" make = "Zeiss" model = "Otus 1.4/100" focal_range = [[100, 1], [100, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "52 54 44 44 18 18 00 00" make = "Zeiss" model = "Milvus 35mm f/2" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "53 54 50 50 0C 0C 00 00" make = "Zeiss" model = "Milvus 50mm f/1.4" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "54 54 50 50 18 18 00 00" make = "Zeiss" model = "Milvus 50mm f/2 Macro" focal_range = [[50, 1], [50, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "F-mount" nikon_id = "55 54 62 62 0C 0C 00 00" make = "Zeiss" model = "Milvus 85mm f/1.4" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "F-mount" nikon_id = "56 54 68 68 18 18 00 00" make = "Zeiss" model = "Milvus 100mm f/2 Macro" focal_range = [[100, 1], [100, 1]] aperture_range = [[2, 1], [2, 1]] rawler-0.7.1/data/lenses/fixed/canon_fixed_lenses.toml000064400000000000000000000005471046102023000211570ustar 00000000000000[[lenses]] mount = "fixed" make = "Canon" model = "PowerShot SX70 HS" focal_range = [[38, 10], [247, 1]] aperture_range = [[34, 10], [65, 10]] key = "canon_powershot_sx70hs_lens" [[lenses]] mount = "fixed" make = "Canon" model = "PowerShot SX60 HS" focal_range = [[38, 10], [247, 1]] aperture_range = [[34, 10], [65, 10]] key = "canon_powershot_sx60hs_lens" rawler-0.7.1/data/lenses/k_mount/pentax.toml000064400000000000000000001473501046102023000172110ustar 00000000000000[[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 17 model = "smc PENTAX-FA SOFT 85mm F2.8" make = "Pentax" focal_range = [[85, 1], [85, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 19 model = "smc PENTAX-F 24-50mm F4" make = "Pentax" focal_range = [[24, 1], [50, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 20 model = "smc PENTAX-F 35-80mm F4-5.6" make = "Pentax" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 21 model = "smc PENTAX-F 80-200mm F4.7-5.6" make = "Pentax" focal_range = [[80, 1], [200, 1]] aperture_range = [[47, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 22 model = "smc PENTAX-F FISH-EYE 17-28mm F3.5-4.5" make = "Pentax" focal_range = [[17, 1], [28, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 23 model = "Sigma AF 28-300mm F3.5-5.6 DL IF" make = "Sigma" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 23 model = "Sigma AF 28-300mm F3.5-6.3 DG IF Macro" make = "Sigma" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 23 model = "Tokina 80-200mm F2.8 ATX-Pro" make = "Tokina" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 24 model = "smc PENTAX-F 35-135mm F3.5-4.5" make = "Pentax" focal_range = [[35, 1], [135, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 25 model = "Sigma 55-200mm F4-5.6 DC" make = "Sigma" focal_range = [[55, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 25 model = "Sigma AF 28-300mm F3.5-5.6 DL IF" make = "Sigma" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 25 model = "Sigma AF 28-300mm F3.5-6.3 DL IF" make = "Sigma" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 25 model = "Sigma AF 28-300mm F3.5-6.3 DG IF Macro" make = "Sigma" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 25 model = "Tokina 80-200mm F2.8 ATX-Pro" make = "Tokina" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 26 model = "smc PENTAX-F* 250-600mm F5.6 ED[IF]" make = "Pentax" focal_range = [[250, 1], [600, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 27 model = "Tokina AT-X Pro AF 28-70mm F2.6-2.8" make = "Tokina" focal_range = [[28, 1], [70, 1]] aperture_range = [[26, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 28 model = "Tokina 19-35mm F3.5-4.5 AF" make = "Tokina" focal_range = [[19, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 28 model = "Tokina AT-X AF 400mm F5.6" make = "Tokina" focal_range = [[400, 1], [400, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 29 model = "Sigma AF 18-125mm F3.5-5.6 DC" make = "Sigma" focal_range = [[18, 1], [125, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 29 model = "Tokina AT-X PRO 28-70mm F2.6-2.8" make = "Tokina" focal_range = [[28, 1], [70, 1]] aperture_range = [[26, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 30 model = "PENTAX-F 70-200mm F4-5.6" make = "Pentax" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 31 model = "Tokina AF 730 75-300mm F4.5-5.6" make = "Tokina" focal_range = [[75, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 31 model = "Takumar-F 70-210mm F4-5.6" make = "Pentax" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 32 model = "smc PENTAX-F 50mm F1.4" make = "Pentax" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 33 model = "smc PENTAX-F 50mm F1.7" make = "Pentax" focal_range = [[50, 1], [50, 1]] aperture_range = [[17, 10], [17, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 34 model = "smc PENTAX-F 135mm F2.8 [IF]" make = "Pentax" focal_range = [[135, 1], [135, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 35 model = "smc PENTAX-F 28mm F2.8" make = "Pentax" focal_range = [[28, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 36 model = "Sigma 20mm F1.8 EX DG Aspherical RF" make = "Sigma" focal_range = [[20, 1], [20, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 38 model = "smc PENTAX-F* 300mm F4.5 ED[IF]" make = "Pentax" focal_range = [[300, 1], [300, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 39 model = "smc PENTAX-F* 600mm F4 ED[IF]" make = "Pentax" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 40 model = "smc PENTAX-F Macro 100mm F2.8" make = "Pentax" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 41 model = "Sigma 50mm F2.8 Macro" make = "Sigma" focal_range = [[50, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 42 model = "Sigma 300mm F2.8 EX DG APO IF" make = "Sigma" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 44 model = "Sigma AF 10-20mm F4-5.6 EX DC" make = "Sigma" focal_range = [[10, 1], [20, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 44 model = "Sigma 12-24mm F4.5-5.6 EX DG" make = "Sigma" focal_range = [[12, 1], [24, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 44 model = "Sigma 17-70mm F2.8-4.5 DC Macro" make = "Sigma" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 44 model = "Sigma 18-50mm F3.5-5.6 DC" make = "Sigma" focal_range = [[18, 1], [50, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 44 model = "Sigma 17-35mm F2.8-4 EX DG" make = "Sigma" focal_range = [[17, 1], [35, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 44 model = "Tamron 35-90mm F4-5.6 AF" make = "Tamron" focal_range = [[35, 1], [90, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 44 model = "Sigma AF 18-35mm F3.5-4.5 Aspherical" make = "Sigma" focal_range = [[18, 1], [35, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 46 model = "Sigma APO 70-200mm F2.8 EX" make = "Sigma" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 46 model = "Sigma EX APO 100-300mm F4 IF" make = "Sigma" focal_range = [[100, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 46 model = "Samsung/Schneider D-XENON 50-200mm F4-5.6 ED" make = "Samsung/Schneider" focal_range = [[50, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 50 model = "smc PENTAX-FA 28-70mm F4 AL" make = "Pentax" focal_range = [[28, 1], [70, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 51 model = "Sigma 28mm F1.8 EX DG Aspherical Macro" make = "Sigma" focal_range = [[28, 1], [28, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 52 model = "Tamron AF LD 28-200mm F3.8-5.6 [IF] Aspherical (171D)" make = "Tamron" focal_range = [[28, 1], [200, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 53 model = "smc PENTAX-FA 28-80mm F3.5-5.6 AL" make = "Pentax" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 247 model = "smc PENTAX-DA FISH-EYE 10-17mm F3.5-4.5 ED[IF]" make = "Pentax" focal_range = [[10, 1], [17, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 248 model = "smc PENTAX-DA 12-24mm F4 ED AL[IF]" make = "Pentax" focal_range = [[12, 1], [24, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 250 model = "smc PENTAX-DA 50-200mm F4-5.6 ED" make = "Pentax" focal_range = [[50, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 251 model = "smc PENTAX-DA 40mm F2.8 Limited" make = "Pentax" focal_range = [[40, 1], [40, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 252 model = "smc PENTAX-DA 18-55mm F3.5-5.6 AL" make = "Pentax" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 253 model = "smc PENTAX-DA 14mm F2.8 ED[IF]" make = "Pentax" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 254 model = "smc PENTAX-DA 16-45mm F4 ED AL" make = "Pentax" focal_range = [[16, 1], [45, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 255 model = "Sigma 18-200mm F3.5-6.3 DC" make = "Sigma" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 255 model = "Sigma DL-II 35-80mm F4-5.6" make = "Sigma" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 255 model = "Sigma DL Zoom 75-300mm F4-5.6" make = "Sigma" focal_range = [[75, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 255 model = "Sigma DF EX Aspherical 28-70mm F2.8" make = "Sigma" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 255 model = "Sigma AF Tele 400mm F5.6 Multi-coated" make = "Sigma" focal_range = [[400, 1], [400, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 255 model = "Sigma 24-60mm F2.8 EX DG" make = "Sigma" focal_range = [[24, 1], [60, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 255 model = "Sigma 70-300mm F4-5.6 Macro" make = "Sigma" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 255 model = "Sigma 55-200mm F4-5.6 DC" make = "Sigma" focal_range = [[55, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 3 lens_subid = 255 model = "Sigma 18-50mm F2.8 EX DC" make = "Sigma" focal_range = [[18, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 1 model = "smc PENTAX-FA SOFT 28mm F2.8" make = "Pentax" focal_range = [[28, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 2 model = "smc PENTAX-FA 80-320mm F4.5-5.6" make = "Pentax" focal_range = [[80, 1], [320, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 3 model = "smc PENTAX-FA 43mm F1.9 Limited" make = "Pentax" focal_range = [[43, 1], [43, 1]] aperture_range = [[19, 10], [19, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 6 model = "smc PENTAX-FA 35-80mm F4-5.6" make = "Pentax" focal_range = [[35, 1], [80, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 8 model = "Irix 150mm F2.8 Macro" make = "Irix" focal_range = [[150, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 9 model = "Irix 11mm F4 Firefly" make = "Irix" focal_range = [[11, 1], [11, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 10 model = "Irix 15mm F2.4" make = "Irix" focal_range = [[15, 1], [15, 1]] aperture_range = [[24, 10], [24, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 12 model = "smc PENTAX-FA 50mm F1.4" make = "Pentax" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 15 model = "smc PENTAX-FA 28-105mm F4-5.6 [IF]" make = "Pentax" focal_range = [[28, 1], [105, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 16 model = "Tamron AF 80-210mm F4-5.6 (178D)" make = "Tamron" focal_range = [[80, 1], [210, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 19 model = "Tamron SP AF 90mm F2.8 (172E)" make = "Tamron" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 20 model = "smc PENTAX-FA 28-80mm F3.5-5.6" make = "Pentax" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 21 model = "Cosina AF 100-300mm F5.6-6.7" make = "Cosina" focal_range = [[100, 1], [300, 1]] aperture_range = [[56, 10], [67, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 22 model = "Tokina 28-80mm F3.5-5.6" make = "Tokina" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 23 model = "smc PENTAX-FA 20-35mm F4 AL" make = "Pentax" focal_range = [[20, 1], [35, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 24 model = "smc PENTAX-FA 77mm F1.8 Limited" make = "Pentax" focal_range = [[77, 1], [77, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 25 model = "Tamron SP AF 14mm F2.8" make = "Tamron" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 26 model = "Cosina 100mm F3.5 Macro" make = "Cosina" focal_range = [[100, 1], [100, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 27 model = "Tamron AF 28-300mm F3.5-6.3 LD Aspherical[IF] Macro (185D/285D)" make = "Tamron" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 28 model = "smc PENTAX-FA 35mm F2 AL" make = "Pentax" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 29 model = "Tamron AF 28-200mm F3.8-5.6 LD Super II Macro (371D)" make = "Tamron" focal_range = [[28, 1], [200, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 34 model = "smc PENTAX-FA 24-90mm F3.5-4.5 AL[IF]" make = "Pentax" focal_range = [[24, 1], [90, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 35 model = "smc PENTAX-FA 100-300mm F4.7-5.8" make = "Pentax" focal_range = [[100, 1], [300, 1]] aperture_range = [[47, 10], [58, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 36 model = "Tamron AF70-300mm F4-5.6 LD Macro" make = "Tamron" focal_range = [[70, 1], [300, 1]] aperture_range = [[70, 1], [30, 1]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 36 model = "Tamron AF 70-300mm F4-5.6 LD Macro 1:2" make = "Tamron" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 37 model = "Tamron SP AF 24-135mm F3.5-5.6 AD AL (190D)" make = "Tamron" focal_range = [[24, 1], [135, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 38 model = "smc PENTAX-FA 28-105mm F3.2-4.5 AL[IF]" make = "Pentax" focal_range = [[28, 1], [105, 1]] aperture_range = [[32, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 39 model = "smc PENTAX-FA 31mm F1.8 AL Limited" make = "Pentax" focal_range = [[31, 1], [31, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 41 model = "Tamron AF 28-200mm Super Zoom F3.8-5.6 Aspherical XR [IF] Macro (A03)" make = "Tamron" focal_range = [[28, 1], [200, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 43 model = "smc PENTAX-FA 28-90mm F3.5-5.6" make = "Pentax" focal_range = [[28, 1], [90, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 44 model = "smc PENTAX-FA J 75-300mm F4.5-5.8 AL" make = "Pentax" focal_range = [[75, 1], [300, 1]] aperture_range = [[45, 10], [58, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 45 model = "Tamron 28-300mm F3.5-6.3 Ultra zoom XR" make = "Tamron" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 45 model = "Tamron AF 28-300mm F3.5-6.3 XR Di LD Aspherical [IF] Macro" make = "Tamron" focal_range = [[28, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 46 model = "smc PENTAX-FA J 28-80mm F3.5-5.6 AL" make = "Pentax" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 47 model = "smc PENTAX-FA J 18-35mm F4-5.6 AL" make = "Pentax" focal_range = [[18, 1], [35, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 49 model = "Tamron SP AF 28-75mm F2.8 XR Di (A09)" make = "Tamron" focal_range = [[28, 1], [75, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 49 model = "Tamron SP AF 28-75mm F2.8 XR Di LD Aspherical [IF] Macro" make = "Tamron" focal_range = [[28, 1], [75, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 51 model = "smc PENTAX-D FA 50mm F2.8 Macro" make = "Pentax" focal_range = [[50, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 52 model = "smc PENTAX-D FA 100mm F2.8 Macro" make = "Pentax" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 55 model = "Samsung/Schneider D-XENOGON 35mm F2" make = "Samsung/Schneider" focal_range = [[35, 1], [35, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 56 model = "Samsung/Schneider D-XENON 100mm F2.8 Macro" make = "Samsung/Schneider" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 75 model = "Tamron SP AF 70-200mm F2.8 Di LD [IF] Macro (A001)" make = "Tamron" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 214 model = "smc PENTAX-DA 35mm F2.4 AL" make = "Pentax" focal_range = [[35, 1], [35, 1]] aperture_range = [[24, 10], [24, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 229 model = "smc PENTAX-DA 18-55mm F3.5-5.6 AL II" make = "Pentax" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 230 model = "Tamron SP AF 17-50mm F2.8 XR Di II" make = "Tamron" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 231 model = "smc PENTAX-DA 18-250mm F3.5-6.3 ED AL [IF]" make = "Pentax" focal_range = [[18, 1], [250, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 237 model = "Samsung/Schneider D-XENOGON 10-17mm F3.5-4.5" make = "Samsung/Schneider" focal_range = [[10, 1], [17, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 239 model = "Samsung/Schneider D-XENON 12-24mm F4 ED AL [IF]" make = "Samsung/Schneider" focal_range = [[12, 1], [24, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 242 model = "smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDM (SDM unused)" make = "Pentax" focal_range = [[16, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 243 model = "smc PENTAX-DA 70mm F2.4 Limited" make = "Pentax" focal_range = [[70, 1], [70, 1]] aperture_range = [[24, 10], [24, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 244 model = "smc PENTAX-DA 21mm F3.2 AL Limited" make = "Pentax" focal_range = [[21, 1], [21, 1]] aperture_range = [[32, 10], [32, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 245 model = "Samsung/Schneider D-XENON 50-200mm F4-5.6" make = "Samsung/Schneider" focal_range = [[50, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 246 model = "Samsung/Schneider D-XENON 18-55mm F3.5-5.6" make = "Samsung/Schneider" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 247 model = "smc PENTAX-DA FISH-EYE 10-17mm F3.5-4.5 ED[IF]" make = "Pentax" focal_range = [[10, 1], [17, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 248 model = "smc PENTAX-DA 12-24mm F4 ED AL [IF]" make = "Pentax" focal_range = [[12, 1], [24, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 249 model = "Tamron XR DiII 18-200mm F3.5-6.3 (A14)" make = "Tamron" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 250 model = "smc PENTAX-DA 50-200mm F4-5.6 ED" make = "Pentax" focal_range = [[50, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 251 model = "smc PENTAX-DA 40mm F2.8 Limited" make = "Pentax" focal_range = [[40, 1], [40, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 252 model = "smc PENTAX-DA 18-55mm F3.5-5.6 AL" make = "Pentax" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 253 model = "smc PENTAX-DA 14mm F2.8 ED[IF]" make = "Pentax" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 4 lens_subid = 254 model = "smc PENTAX-DA 16-45mm F4 ED AL" make = "Pentax" focal_range = [[16, 1], [45, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 1 model = "smc PENTAX-FA* 24mm F2 AL[IF]" make = "Pentax" focal_range = [[24, 1], [24, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 2 model = "smc PENTAX-FA 28mm F2.8 AL" make = "Pentax" focal_range = [[28, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 3 model = "smc PENTAX-FA 50mm F1.7" make = "Pentax" focal_range = [[50, 1], [50, 1]] aperture_range = [[17, 10], [17, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 4 model = "smc PENTAX-FA 50mm F1.4" make = "Pentax" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 5 model = "smc PENTAX-FA* 600mm F4 ED[IF]" make = "Pentax" focal_range = [[600, 1], [600, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 6 model = "smc PENTAX-FA* 300mm F4.5 ED[IF]" make = "Pentax" focal_range = [[300, 1], [300, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 7 model = "smc PENTAX-FA 135mm F2.8 [IF]" make = "Pentax" focal_range = [[135, 1], [135, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 8 model = "smc PENTAX-FA Macro 50mm F2.8" make = "Pentax" focal_range = [[50, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 9 model = "smc PENTAX-FA Macro 100mm F2.8" make = "Pentax" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 10 model = "smc PENTAX-FA* 85mm F1.4 [IF]" make = "Pentax" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 11 model = "smc PENTAX-FA* 200mm F2.8 ED[IF]" make = "Pentax" focal_range = [[200, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 12 model = "smc PENTAX-FA 28-80mm F3.5-4.7" make = "Pentax" focal_range = [[28, 1], [80, 1]] aperture_range = [[35, 10], [47, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 13 model = "smc PENTAX-FA 70-200mm F4-5.6" make = "Pentax" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 14 model = "smc PENTAX-FA* 250-600mm F5.6 ED[IF]" make = "Pentax" focal_range = [[250, 1], [600, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 15 model = "smc PENTAX-FA 28-105mm F4-5.6" make = "Pentax" focal_range = [[28, 1], [105, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 16 model = "smc PENTAX-FA 100-300mm F4.5-5.6" make = "Pentax" focal_range = [[100, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 5 lens_subid = 98 model = "smc PENTAX-FA 100-300mm F4.5-5.6" make = "Pentax" focal_range = [[100, 1], [300, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 6 lens_subid = 1 model = "smc PENTAX-FA* 85mm F1.4 [IF]" make = "Pentax" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 6 lens_subid = 2 model = "smc PENTAX-FA* 200mm F2.8 ED[IF]" make = "Pentax" focal_range = [[200, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 6 lens_subid = 3 model = "smc PENTAX-FA* 300mm F2.8 ED[IF]" make = "Pentax" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 6 lens_subid = 4 model = "smc PENTAX-FA* 28-70mm F2.8 AL" make = "Pentax" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 6 lens_subid = 5 model = "smc PENTAX-FA* 80-200mm F2.8 ED[IF]" make = "Pentax" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 6 lens_subid = 6 model = "smc PENTAX-FA* 28-70mm F2.8 AL" make = "Pentax" focal_range = [[28, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 6 lens_subid = 7 model = "smc PENTAX-FA* 80-200mm F2.8 ED[IF]" make = "Pentax" focal_range = [[80, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 6 lens_subid = 8 model = "smc PENTAX-FA 28-70mm F4AL" make = "Pentax" focal_range = [[28, 1], [70, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 6 lens_subid = 9 model = "smc PENTAX-FA 20mm F2.8" make = "Pentax" focal_range = [[20, 1], [20, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 6 lens_subid = 10 model = "smc PENTAX-FA* 400mm F5.6 ED[IF]" make = "Pentax" focal_range = [[400, 1], [400, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 6 lens_subid = 13 model = "smc PENTAX-FA* 400mm F5.6 ED[IF]" make = "Pentax" focal_range = [[400, 1], [400, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 6 lens_subid = 14 model = "smc PENTAX-FA* Macro 200mm F4 ED[IF]" make = "Pentax" focal_range = [[200, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 0 model = "smc PENTAX-DA 21mm F3.2 AL Limited" make = "Pentax" focal_range = [[21, 1], [21, 1]] aperture_range = [[32, 10], [32, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 58 model = "smc PENTAX-D FA Macro 100mm F2.8 WR" make = "Pentax" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 75 model = "Tamron SP AF 70-200mm F2.8 Di LD [IF] Macro (A001)" make = "Tamron" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 201 model = "smc Pentax-DA L 50-200mm F4-5.6 ED WR" make = "Pentax" focal_range = [[50, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 202 model = "smc PENTAX-DA L 18-55mm F3.5-5.6 AL WR" make = "Pentax" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 203 model = "HD PENTAX-DA 55-300mm F4-5.8 ED WR" make = "Pentax" focal_range = [[55, 1], [300, 1]] aperture_range = [[4, 1], [58, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 204 model = "HD PENTAX-DA 15mm F4 ED AL Limited" make = "Pentax" focal_range = [[15, 1], [15, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 205 model = "HD PENTAX-DA 35mm F2.8 Macro Limited" make = "Pentax" focal_range = [[35, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 206 model = "HD PENTAX-DA 70mm F2.4 Limited" make = "Pentax" focal_range = [[70, 1], [70, 1]] aperture_range = [[24, 10], [24, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 207 model = "HD PENTAX-DA 21mm F3.2 ED AL Limited" make = "Pentax" focal_range = [[21, 1], [21, 1]] aperture_range = [[32, 10], [32, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 208 model = "HD PENTAX-DA 40mm F2.8 Limited" make = "Pentax" focal_range = [[40, 1], [40, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 212 model = "smc PENTAX-DA 50mm F1.8" make = "Pentax" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 213 model = "smc PENTAX-DA 40mm F2.8 XS" make = "Pentax" focal_range = [[40, 1], [40, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 214 model = "smc PENTAX-DA 35mm F2.4 AL" make = "Pentax" focal_range = [[35, 1], [35, 1]] aperture_range = [[24, 10], [24, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 216 model = "smc PENTAX-DA L 55-300mm F4-5.8 ED" make = "Pentax" focal_range = [[55, 1], [300, 1]] aperture_range = [[4, 1], [58, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 217 model = "smc PENTAX-DA 50-200mm F4-5.6 ED WR" make = "Pentax" focal_range = [[50, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 218 model = "smc PENTAX-DA 18-55mm F3.5-5.6 AL WR" make = "Pentax" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 220 model = "Tamron SP AF 10-24mm F3.5-4.5 Di II LD Aspherical [IF]" make = "Tamron" focal_range = [[10, 1], [24, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 221 model = "smc PENTAX-DA L 50-200mm F4-5.6 ED" make = "Pentax" focal_range = [[50, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 222 model = "smc PENTAX-DA L 18-55mm F3.5-5.6" make = "Pentax" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 223 model = "Samsung/Schneider D-XENON 18-55mm F3.5-5.6 II" make = "Samsung/Schneider" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 224 model = "smc PENTAX-DA 15mm F4 ED AL Limited" make = "Pentax" focal_range = [[15, 1], [15, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 225 model = "Samsung/Schneider D-XENON 18-250mm F3.5-6.3" make = "Samsung/Schneider" focal_range = [[18, 1], [250, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 226 model = "smc PENTAX-DA* 55mm F1.4 SDM (SDM unused)" make = "Pentax" focal_range = [[55, 1], [55, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 227 model = "smc PENTAX-DA* 60-250mm F4 [IF] SDM (SDM unused)" make = "Pentax" focal_range = [[60, 1], [250, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 228 model = "Samsung 16-45mm F4 ED" make = "Samsung" focal_range = [[16, 1], [45, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 229 model = "smc PENTAX-DA 18-55mm F3.5-5.6 AL II" make = "Pentax" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 230 model = "Tamron AF 17-50mm F2.8 XR Di-II LD (Model A16)" make = "Tamron" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 231 model = "smc PENTAX-DA 18-250mm F3.5-6.3 ED AL [IF]" make = "Pentax" focal_range = [[18, 1], [250, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 233 model = "smc PENTAX-DA 35mm F2.8 Macro Limited" make = "Pentax" focal_range = [[35, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 234 model = "smc PENTAX-DA* 300mm F4 ED [IF] SDM (SDM unused)" make = "Pentax" focal_range = [[300, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 235 model = "smc PENTAX-DA* 200mm F2.8 ED [IF] SDM (SDM unused)" make = "Pentax" focal_range = [[200, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 236 model = "smc PENTAX-DA 55-300mm F4-5.8 ED" make = "Pentax" focal_range = [[55, 1], [300, 1]] aperture_range = [[4, 1], [58, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 238 model = "Tamron AF 18-250mm F3.5-6.3 Di II LD Aspherical [IF] Macro" make = "Tamron" focal_range = [[18, 1], [250, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 241 model = "smc PENTAX-DA* 50-135mm F2.8 ED [IF] SDM (SDM unused)" make = "Pentax" focal_range = [[50, 1], [135, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 242 model = "smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDM (SDM unused)" make = "Pentax" focal_range = [[16, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 243 model = "smc PENTAX-DA 70mm F2.4 Limited" make = "Pentax" focal_range = [[70, 1], [70, 1]] aperture_range = [[24, 10], [24, 10]] [[lenses]] mount = "k-mount" lens_id = 7 lens_subid = 244 model = "smc PENTAX-DA 21mm F3.2 AL Limited" make = "Pentax" focal_range = [[21, 1], [21, 1]] aperture_range = [[32, 10], [32, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 0 model = "Sigma 50-150mm F2.8 II APO EX DC HSM" make = "Sigma" focal_range = [[50, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 3 model = "Sigma 18-125mm F3.8-5.6 DC HSM" make = "Sigma" focal_range = [[18, 1], [125, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 4 model = "Sigma 50mm F1.4 EX DG HSM" make = "Sigma" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 6 model = "Sigma 4.5mm F2.8 EX DC Fisheye" make = "Sigma" focal_range = [[45, 10], [45, 10]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 7 model = "Sigma 24-70mm F2.8 IF EX DG HSM" make = "Sigma" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 8 model = "Sigma 18-250mm F3.5-6.3 DC OS HSM" make = "Sigma" focal_range = [[18, 1], [250, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 11 model = "Sigma 10-20mm F3.5 EX DC HSM" make = "Sigma" focal_range = [[10, 1], [20, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 12 model = "Sigma 70-300mm F4-5.6 DG OS" make = "Sigma" focal_range = [[70, 1], [300, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 13 model = "Sigma 120-400mm F4.5-5.6 APO DG OS HSM" make = "Sigma" focal_range = [[120, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 14 model = "Sigma 17-70mm F2.8-4.0 DC Macro OS HSM" make = "Sigma" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [40, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 15 model = "Sigma 150-500mm F5-6.3 APO DG OS HSM" make = "Sigma" focal_range = [[150, 1], [500, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 16 model = "Sigma 70-200mm F2.8 EX DG Macro HSM II" make = "Sigma" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 17 model = "Sigma 50-500mm F4.5-6.3 DG OS HSM" make = "Sigma" focal_range = [[50, 1], [500, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 18 model = "Sigma 8-16mm F4.5-5.6 DC HSM" make = "Sigma" focal_range = [[8, 1], [16, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 20 model = "Sigma 18-50mm F2.8-4.5 DC HSM" make = "Sigma" focal_range = [[18, 1], [50, 1]] aperture_range = [[28, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 21 model = "Sigma 17-50mm F2.8 EX DC OS HSM" make = "Sigma" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 22 model = "Sigma 85mm F1.4 EX DG HSM" make = "Sigma" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 23 model = "Sigma 70-200mm F2.8 APO EX DG OS HSM" make = "Sigma" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 24 model = "Sigma 17-70mm F2.8-4 DC Macro OS HSM" make = "Sigma" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 25 model = "Sigma 17-50mm F2.8 EX DC HSM" make = "Sigma" focal_range = [[17, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 27 model = "Sigma 18-200mm F3.5-6.3 II DC HSM" make = "Sigma" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 28 model = "Sigma 18-250mm F3.5-6.3 DC Macro HSM" make = "Sigma" focal_range = [[18, 1], [250, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 29 model = "Sigma 35mm F1.4 DG HSM" make = "Sigma" focal_range = [[35, 1], [35, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 30 model = "Sigma 17-70mm F2.8-4 DC Macro HSM | C" make = "Sigma" focal_range = [[17, 1], [70, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 31 model = "Sigma 18-35mm F1.8 DC HSM" make = "Sigma" focal_range = [[18, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 32 model = "Sigma 30mm F1.4 DC HSM | A" make = "Sigma" focal_range = [[30, 1], [30, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 33 model = "Sigma 18-200mm F3.5-6.3 DC Macro HSM" make = "Sigma" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 34 model = "Sigma 18-300mm F3.5-6.3 DC Macro HSM" make = "Sigma" focal_range = [[18, 1], [300, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 59 model = "HD PENTAX-D FA 150-450mm F4.5-5.6 ED DC AW" make = "Pentax" focal_range = [[150, 1], [450, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 60 model = "HD PENTAX-D FA* 70-200mm F2.8 ED DC AW" make = "Pentax" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 61 model = "HD PENTAX-D FA 28-105mm F3.5-5.6 ED DC WR" make = "Pentax" focal_range = [[28, 1], [105, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 62 model = "HD PENTAX-D FA 24-70mm F2.8 ED SDM WR" make = "Pentax" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 63 model = "HD PENTAX-D FA 15-30mm F2.8 ED SDM WR" make = "Pentax" focal_range = [[15, 1], [30, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 64 model = "HD PENTAX-D FA* 50mm F1.4 SDM AW" make = "Pentax" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 65 model = "HD PENTAX-D FA 70-210mm F4 ED SDM WR" make = "Pentax" focal_range = [[70, 1], [210, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 66 model = "HD PENTAX-D FA 85mm F1.4 ED SDM AW" make = "Pentax" focal_range = [[85, 1], [85, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 67 model = "HD PENTAX-D FA 21mm F2.4 ED Limited DC WR" make = "Pentax" focal_range = [[21, 1], [21, 1]] aperture_range = [[24, 10], [24, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 195 model = "HD PENTAX DA* 16-50mm F2.8 ED PLM AW" make = "Pentax" focal_range = [[16, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 196 model = "HD PENTAX-DA* 11-18mm F2.8 ED DC AW" make = "Pentax" focal_range = [[11, 1], [18, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 197 model = "HD PENTAX-DA 55-300mm F4.5-6.3 ED PLM WR RE" make = "Pentax" focal_range = [[55, 1], [300, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 198 model = "smc PENTAX-DA L 18-50mm F4-5.6 DC WR RE" make = "Pentax" focal_range = [[18, 1], [50, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 199 model = "HD PENTAX-DA 18-50mm F4-5.6 DC WR RE" make = "Pentax" focal_range = [[18, 1], [50, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 200 model = "HD PENTAX-DA 16-85mm F3.5-5.6 ED DC WR" make = "Pentax" focal_range = [[16, 1], [85, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 209 model = "HD PENTAX-DA 20-40mm F2.8-4 ED Limited DC WR" make = "Pentax" focal_range = [[20, 1], [40, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 210 model = "smc PENTAX-DA 18-270mm F3.5-6.3 ED SDM" make = "Pentax" focal_range = [[18, 1], [270, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 211 model = "HD PENTAX-DA 560mm F5.6 ED AW" make = "Pentax" focal_range = [[560, 1], [560, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 215 model = "smc PENTAX-DA 18-135mm F3.5-5.6 ED AL [IF] DC WR" make = "Pentax" focal_range = [[18, 1], [135, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 226 model = "smc PENTAX-DA* 55mm F1.4 SDM" make = "Pentax" focal_range = [[55, 1], [55, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 227 model = "smc PENTAX-DA* 60-250mm F4 [IF] SDM" make = "Pentax" focal_range = [[60, 1], [250, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 232 model = "smc PENTAX-DA 17-70mm F4 AL [IF] SDM" make = "Pentax" focal_range = [[17, 1], [70, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 234 model = "smc PENTAX-DA* 300mm F4 ED [IF] SDM" make = "Pentax" focal_range = [[300, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 235 model = "smc PENTAX-DA* 200mm F2.8 ED [IF] SDM" make = "Pentax" focal_range = [[200, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 241 model = "smc PENTAX-DA* 50-135mm F2.8 ED [IF] SDM" make = "Pentax" focal_range = [[50, 1], [135, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 242 model = "smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDM" make = "Pentax" focal_range = [[16, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 255 model = "Sigma 70-200mm F2.8 EX DG Macro HSM II" make = "Sigma" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 255 model = "Sigma 150-500mm F5-6.3 DG APO [OS] HSM" make = "Sigma" focal_range = [[150, 1], [500, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 255 model = "Sigma 50-150mm F2.8 II APO EX DC HSM" make = "Sigma" focal_range = [[50, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 255 model = "Sigma 4.5mm F2.8 EX DC HSM Circular Fisheye" make = "Sigma" focal_range = [[45, 10], [45, 10]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 255 model = "Sigma 50-200mm F4-5.6 DC OS" make = "Sigma" focal_range = [[50, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 8 lens_subid = 255 model = "Sigma 24-70mm F2.8 EX DG HSM" make = "Sigma" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 1 model = "smc PENTAX-FA 645 75mm F2.8" make = "Pentax" focal_range = [[75, 1], [75, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 2 model = "smc PENTAX-FA 645 45mm F2.8" make = "Pentax" focal_range = [[45, 1], [45, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 3 model = "smc PENTAX-FA* 645 300mm F4 ED [IF]" make = "Pentax" focal_range = [[300, 1], [300, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 4 model = "smc PENTAX-FA 645 45-85mm F4.5" make = "Pentax" focal_range = [[45, 1], [85, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 5 model = "smc PENTAX-FA 645 400mm F5.6 ED [IF]" make = "Pentax" focal_range = [[400, 1], [400, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 7 model = "smc PENTAX-FA 645 Macro 120mm F4" make = "Pentax" focal_range = [[120, 1], [120, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 8 model = "smc PENTAX-FA 645 80-160mm F4.5" make = "Pentax" focal_range = [[80, 1], [160, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 9 model = "smc PENTAX-FA 645 200mm F4 [IF]" make = "Pentax" focal_range = [[200, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 10 model = "smc PENTAX-FA 645 150mm F2.8 [IF]" make = "Pentax" focal_range = [[150, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 11 model = "smc PENTAX-FA 645 35mm F3.5 AL [IF]" make = "Pentax" focal_range = [[35, 1], [35, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 12 model = "smc PENTAX-FA 645 300mm F5.6 ED [IF]" make = "Pentax" focal_range = [[300, 1], [300, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 14 model = "smc PENTAX-FA 645 55-110mm F5.6" make = "Pentax" focal_range = [[55, 1], [110, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 16 model = "smc PENTAX-FA 645 33-55mm F4.5 AL" make = "Pentax" focal_range = [[33, 1], [55, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 17 model = "smc PENTAX-FA 645 150-300mm F5.6 ED [IF]" make = "Pentax" focal_range = [[150, 1], [300, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 11 lens_subid = 21 model = "HD PENTAX-D FA 645 35mm F3.5 AL [IF]" make = "Pentax" focal_range = [[35, 1], [35, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "k-mount" lens_id = 13 lens_subid = 18 model = "smc PENTAX-D FA 645 55mm F2.8 AL [IF] SDM AW" make = "Pentax" focal_range = [[55, 1], [55, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 13 lens_subid = 19 model = "smc PENTAX-D FA 645 25mm F4 AL [IF] SDM AW" make = "Pentax" focal_range = [[25, 1], [25, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 13 lens_subid = 20 model = "HD PENTAX-D FA 645 90mm F2.8 ED AW SR" make = "Pentax" focal_range = [[90, 1], [90, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 13 lens_subid = 253 model = "HD PENTAX-DA 645 28-45mm F4.5 ED AW SR" make = "Pentax" focal_range = [[28, 1], [45, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 13 lens_subid = 254 model = "smc PENTAX-DA 645 25mm F4 AL [IF] SDM AW" make = "Pentax" focal_range = [[25, 1], [25, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "k-mount" lens_id = 21 lens_subid = 1 model = "01 Standard Prime 8.5mm F1.9" make = "Pentax" focal_range = [[85, 10], [85, 10]] aperture_range = [[19, 10], [19, 10]] [[lenses]] mount = "k-mount" lens_id = 21 lens_subid = 2 model = "02 Standard Zoom 5-15mm F2.8-4.5" make = "Pentax" focal_range = [[5, 1], [15, 1]] aperture_range = [[28, 10], [45, 10]] [[lenses]] mount = "k-mount" lens_id = 22 lens_subid = 3 model = "03 Fish-eye 3.2mm F5.6" make = "Pentax" focal_range = [[32, 10], [32, 10]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "k-mount" lens_id = 22 lens_subid = 4 model = "04 Toy Lens Wide 6.3mm F7.1" make = "Pentax" focal_range = [[63, 10], [63, 10]] aperture_range = [[71, 10], [71, 10]] [[lenses]] mount = "k-mount" lens_id = 22 lens_subid = 5 model = "05 Toy Lens Telephoto 18mm F8" make = "Pentax" focal_range = [[18, 1], [18, 1]] aperture_range = [[8, 1], [8, 1]] [[lenses]] mount = "k-mount" lens_id = 21 lens_subid = 6 model = "06 Telephoto Zoom 15-45mm F2.8" make = "Pentax" focal_range = [[15, 1], [45, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "k-mount" lens_id = 21 lens_subid = 7 model = "07 Mount Shield 11.5mm F9" make = "Pentax" focal_range = [[115, 10], [115, 10]] aperture_range = [[9, 1], [9, 1]] [[lenses]] mount = "k-mount" lens_id = 21 lens_subid = 8 model = "08 Wide Zoom 3.8-5.9mm F3.7-4" make = "Pentax" focal_range = [[38, 10], [59, 10]] aperture_range = [[37, 10], [4, 1]] rawler-0.7.1/data/lenses/mft_mount/leica.toml000064400000000000000000000070121046102023000173110ustar 00000000000000[[lenses]] mount = "MFT-mount" olympus_id = "02 01 00" make = "Leica" model = "D Vario Elmarit 14-50mm F2.8-3.5 Asph." focal_range = [[14, 1], [50, 1]] aperture_range = [[28, 10], [35, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 02 00" make = "Leica" model = "D Summilux 25mm F1.4 Asph." focal_range = [[25, 1], [25, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 03 00" make = "Leica" model = "D Vario Elmar 14-50mm F3.8-5.6 Asph. Mega OIS" focal_range = [[14, 1], [50, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 03 01" make = "Leica" model = "D Vario Elmar 14-50mm F3.8-5.6 Asph." focal_range = [[14, 1], [50, 1]] aperture_range = [[38, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 04 00" make = "Leica" model = "D Vario Elmar 14-150mm F3.5-5.6" focal_range = [[14, 1], [150, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 06 10" make = "Leica" model = "DG Macro-Elmarit 45mm F2.8 Asph. Mega OIS" focal_range = [[45, 1], [45, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 12 10" make = "Leica" model = "DG Summilux 25mm F1.4 Asph." focal_range = [[25, 1], [25, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 21 10" make = "Leica" model = "DG Nocticron 42.5mm F1.2 Asph. Power OIS" focal_range = [[425, 10], [425, 10]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 22 10" make = "Leica" model = "DG Summilux 15mm F1.7 Asph." focal_range = [[15, 1], [15, 1]] aperture_range = [[17, 10], [17, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 27 10" make = "Leica" model = "DG Vario-Elmar 100-400mm F4.0-6.3 Asph. Power OIS" focal_range = [[100, 1], [400, 1]] aperture_range = [[40, 10], [63, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 29 10" make = "Leica" model = "DG Summilux 12mm F1.4 Asph." focal_range = [[12, 1], [12, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 30 10" make = "Leica" model = "DG Vario-Elmarit 12-60mm F2.8-4 Asph. Power OIS" focal_range = [[12, 1], [60, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "MFT-mount" olympus_id = "02 35 10" make = "Leica" model = "DG Vario-Elmarit 8-18mm F2.8-4 Asph." focal_range = [[8, 1], [18, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "MFT-mount" olympus_id = "02 36 10" make = "Leica" model = "DG Elmarit 200mm F2.8 Power OIS" focal_range = [[200, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 37 10" make = "Leica" model = "DG Vario-Elmarit 50-200mm F2.8-4 Asph. Power OIS" focal_range = [[50, 1], [200, 1]] aperture_range = [[28, 10], [4, 1]] [[lenses]] mount = "MFT-mount" olympus_id = "02 38 10" make = "Leica" model = "DG Vario-Summilux 10-25mm F1.7 Asph." focal_range = [[10, 1], [25, 1]] aperture_range = [[17, 10], [17, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 40 10" make = "Leica" model = "DG Vario-Summilux 25-50mm F1.7 Asph." focal_range = [[25, 1], [50, 1]] aperture_range = [[17, 10], [17, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "03 01 00" make = "Leica" model = "D Vario Elmarit 14-50mm F2.8-3.5 Asph." focal_range = [[14, 1], [50, 1]] aperture_range = [[28, 10], [35, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "03 02 00" make = "Leica" model = "D Summilux 25mm F1.4 Asph." focal_range = [[25, 1], [25, 1]] aperture_range = [[14, 10], [14, 10]] rawler-0.7.1/data/lenses/mft_mount/lumix.toml000064400000000000000000000116501046102023000173750ustar 00000000000000[[lenses]] mount = "MFT-mount" olympus_id = "02 07 10" make = "Lumix" model = "G Vario 14-42mm F3.5-5.6 Asph. Mega OIS" focal_range = [[14, 1], [42, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 01 10" make = "Lumix" model = "G Vario 14-45mm F3.5-5.6 Asph. Mega OIS" focal_range = [[14, 1], [45, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 02 10" make = "Lumix" model = "G Vario 45-200mm F4.0-5.6 Mega OIS" focal_range = [[45, 1], [200, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 03 10" make = "Lumix" model = "G Vario HD 14-140mm F4.0-5.8 Asph. Mega OIS" focal_range = [[14, 1], [140, 1]] aperture_range = [[40, 10], [58, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 04 10" make = "Lumix" model = "G Vario 7-14mm F4.0 Asph." focal_range = [[7, 1], [14, 1]] aperture_range = [[40, 10], [40, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 05 10" make = "Lumix" model = "G 20mm F1.7 Asph." focal_range = [[20, 1], [20, 1]] aperture_range = [[17, 10], [17, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 08 10" make = "Lumix" model = "G Fisheye 8mm F3.5" focal_range = [[8, 1], [8, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 09 10" make = "Lumix" model = "G Vario 100-300mm F4.0-5.6 Mega OIS" focal_range = [[100, 1], [300, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 10 10" make = "Lumix" model = "G 14mm F2.5 Asph." focal_range = [[14, 1], [14, 1]] aperture_range = [[25, 10], [25, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 11 10" make = "Lumix" model = "G 12.5mm F12 3D" focal_range = [[125, 10], [125, 10]] aperture_range = [[12, 1], [12, 1]] [[lenses]] mount = "MFT-mount" olympus_id = "02 13 10" make = "Lumix" model = "G X Vario PZ 45-175mm F4.0-5.6 Asph. Power OIS" focal_range = [[45, 1], [175, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 14 10" make = "Lumix" model = "G X Vario PZ 14-42mm F3.5-5.6 Asph. Power OIS" focal_range = [[14, 1], [42, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 15 10" make = "Lumix" model = "G X Vario 12-35mm F2.8 Asph. Power OIS" focal_range = [[12, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 16 10" make = "Lumix" model = "G Vario 45-150mm F4.0-5.6 Asph. Mega OIS" focal_range = [[45, 1], [150, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 17 10" make = "Lumix" model = "G X Vario 35-100mm F2.8 Power OIS" focal_range = [[35, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 18 10" make = "Lumix" model = "G Vario 14-42mm F3.5-5.6 II Asph. Mega OIS" focal_range = [[14, 1], [42, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 19 10" make = "Lumix" model = "G Vario 14-140mm F3.5-5.6 Asph. Power OIS" focal_range = [[14, 1], [140, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 20 10" make = "Lumix" model = "G Vario 12-32mm F3.5-5.6 Asph. Mega OIS" focal_range = [[12, 1], [32, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 23 10" make = "Lumix" model = "G Vario 35-100mm F4.0-5.6 Asph. Mega OIS" focal_range = [[35, 1], [100, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 24 10" make = "Lumix" model = "G Macro 30mm F2.8 Asph. Mega OIS" focal_range = [[30, 1], [30, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 25 10" make = "Lumix" model = "G 42.5mm F1.7 Asph. Power OIS" focal_range = [[425, 10], [425, 10]] aperture_range = [[17, 10], [17, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 26 10" make = "Lumix" model = "G 25mm F1.7 Asph." focal_range = [[25, 1], [25, 1]] aperture_range = [[17, 10], [17, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 28 10" make = "Lumix" model = "G Vario 12-60mm F3.5-5.6 Asph. Power OIS" focal_range = [[12, 1], [60, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 31 10" make = "Lumix" model = "G Vario 45-200mm F4.0-5.6 II" focal_range = [[45, 1], [200, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 32 10" make = "Lumix" model = "G Vario 100-300mm F4.0-5.6 II" focal_range = [[100, 1], [300, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 33 10" make = "Lumix" model = "G X Vario 12-35mm F2.8 II Asph. Power OIS" focal_range = [[12, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "02 34 10" make = "Lumix" model = "G Vario 35-100mm F2.8 II" focal_range = [[35, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] rawler-0.7.1/data/lenses/mft_mount/misc.toml000064400000000000000000000005521046102023000171710ustar 00000000000000[[lenses]] mount = "MFT-mount" olympus_id = "05 01 10" make = "Tamron" model = "14-150mm F3.5-5.8 Di III" focal_range = [[14, 1], [150, 1]] aperture_range = [[35, 10], [58, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "24 01 10" make = "Venus Optics" model = "Laowa 50mm F2.8 2x Macro" focal_range = [[50, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] rawler-0.7.1/data/lenses/mft_mount/olympus.toml000064400000000000000000000260561046102023000177550ustar 00000000000000[[lenses]] mount = "MFT-mount" olympus_id = "00 01 00" make = "Olympus" model = "Zuiko Digital ED 50mm F2.0 Macro" focal_range = [[50, 1], [50, 1]] aperture_range = [[20, 10], [20, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 01 01" make = "Olympus" model = "Zuiko Digital 40-150mm F3.5-4.5" focal_range = [[40, 1], [150, 1]] aperture_range = [[35, 10], [45, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 01 10" make = "Olympus" model = "M.Zuiko Digital ED 14-42mm F3.5-5.6" focal_range = [[14, 1], [42, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 02 00" make = "Olympus" model = "Zuiko Digital ED 150mm F2.0" focal_range = [[150, 1], [150, 1]] aperture_range = [[20, 10], [20, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 02 10" make = "Olympus" model = "M.Zuiko Digital 17mm F2.8 Pancake" focal_range = [[17, 1], [17, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 03 00" make = "Olympus" model = "Zuiko Digital ED 300mm F2.8" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 03 10" make = "Olympus" model = "M.Zuiko Digital ED 14-150mm F4.0-5.6 [II]" focal_range = [[14, 1], [150, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 04 10" make = "Olympus" model = "M.Zuiko Digital ED 9-18mm F4.0-5.6" focal_range = [[9, 1], [18, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 05 00" make = "Olympus" model = "Zuiko Digital 14-54mm F2.8-3.5" focal_range = [[14, 1], [54, 1]] aperture_range = [[28, 10], [35, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 05 01" make = "Olympus" model = "Zuiko Digital Pro ED 90-250mm F2.8" focal_range = [[90, 1], [250, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 05 10" make = "Olympus" model = "M.Zuiko Digital ED 14-42mm F3.5-5.6 L" focal_range = [[14, 1], [42, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 06 00" make = "Olympus" model = "Zuiko Digital ED 50-200mm F2.8-3.5" focal_range = [[50, 1], [200, 1]] aperture_range = [[28, 10], [35, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 06 01" make = "Olympus" model = "Zuiko Digital ED 8mm F3.5 Fisheye" focal_range = [[8, 1], [8, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 06 10" make = "Olympus" model = "M.Zuiko Digital ED 40-150mm F4.0-5.6" focal_range = [[40, 1], [150, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 07 00" make = "Olympus" model = "Zuiko Digital 11-22mm F2.8-3.5" focal_range = [[11, 1], [22, 1]] aperture_range = [[28, 10], [35, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 07 01" make = "Olympus" model = "Zuiko Digital 18-180mm F3.5-6.3" focal_range = [[18, 1], [180, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 07 10" make = "Olympus" model = "M.Zuiko Digital ED 12mm F2.0" focal_range = [[12, 1], [12, 1]] aperture_range = [[20, 10], [20, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 08 01" make = "Olympus" model = "Zuiko Digital 70-300mm F4.0-5.6" focal_range = [[70, 1], [300, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 08 10" make = "Olympus" model = "M.Zuiko Digital ED 75-300mm F4.8-6.7" focal_range = [[75, 1], [300, 1]] aperture_range = [[48, 10], [67, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 09 10" make = "Olympus" model = "M.Zuiko Digital 14-42mm F3.5-5.6 II" focal_range = [[14, 1], [42, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 10 01" make = "Kenko" model = "Tokina Reflex 300mm F6.3 MF Macro" focal_range = [[300, 1], [300, 1]] aperture_range = [[63, 10], [63, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 10 10" make = "Olympus" model = "M.Zuiko Digital ED 12-50mm F3.5-6.3 EZ" focal_range = [[12, 1], [50, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 11 10" make = "Olympus" model = "M.Zuiko Digital 45mm F1.8" focal_range = [[45, 1], [45, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 12 10" make = "Olympus" model = "M.Zuiko Digital ED 60mm F2.8 Macro" focal_range = [[60, 1], [60, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 13 10" make = "Olympus" model = "M.Zuiko Digital 14-42mm F3.5-5.6 II R" focal_range = [[14, 1], [42, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 14 10" make = "Olympus" model = "M.Zuiko Digital ED 40-150mm F4.0-5.6 R" focal_range = [[40, 1], [150, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 14 10.1" make = "Olympus" model = "M.Zuiko Digital ED 14-150mm F4.0-5.6 II" focal_range = [[14, 1], [150, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 15 00" make = "Olympus" model = "Zuiko Digital ED 7-14mm F4.0" focal_range = [[7, 1], [14, 1]] aperture_range = [[40, 10], [40, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 15 10" make = "Olympus" model = "M.Zuiko Digital ED 75mm F1.8" focal_range = [[75, 1], [75, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 16 10" make = "Olympus" model = "M.Zuiko Digital 17mm F1.8" focal_range = [[17, 1], [17, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 17 00" make = "Olympus" model = "Zuiko Digital Pro ED 35-100mm F2.0" focal_range = [[35, 1], [100, 1]] aperture_range = [[20, 10], [20, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 18 00" make = "Olympus" model = "Zuiko Digital 14-45mm F3.5-5.6" focal_range = [[14, 1], [45, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 18 10" make = "Olympus" model = "M.Zuiko Digital ED 75-300mm F4.8-6.7 II" focal_range = [[75, 1], [300, 1]] aperture_range = [[48, 10], [67, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 19 10" make = "Olympus" model = "M.Zuiko Digital ED 12-40mm F2.8 Pro" focal_range = [[12, 1], [40, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 20 00" make = "Olympus" model = "Zuiko Digital 35mm F3.5 Macro" focal_range = [[35, 1], [35, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 20 10" make = "Olympus" model = "M.Zuiko Digital ED 40-150mm F2.8 Pro" focal_range = [[40, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 21 10" make = "Olympus" model = "M.Zuiko Digital ED 14-42mm F3.5-5.6 EZ" focal_range = [[14, 1], [42, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 22 00" make = "Olympus" model = "Zuiko Digital 17.5-45mm F3.5-5.6" focal_range = [[175, 10], [45, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 22 10" make = "Olympus" model = "M.Zuiko Digital 25mm F1.8" focal_range = [[25, 1], [25, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 23 00" make = "Olympus" model = "Zuiko Digital ED 14-42mm F3.5-5.6" focal_range = [[14, 1], [42, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 23 10" make = "Olympus" model = "M.Zuiko Digital ED 7-14mm F2.8 Pro" focal_range = [[7, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 24 00" make = "Olympus" model = "Zuiko Digital ED 40-150mm F4.0-5.6" focal_range = [[40, 1], [150, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 24 10" make = "Olympus" model = "M.Zuiko Digital ED 300mm F4.0 IS Pro" focal_range = [[300, 1], [300, 1]] aperture_range = [[40, 10], [40, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 25 10" make = "Olympus" model = "M.Zuiko Digital ED 8mm F1.8 Fisheye Pro" focal_range = [[8, 1], [8, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 26 10" make = "Olympus" model = "M.Zuiko Digital ED 12-100mm F4.0 IS Pro" focal_range = [[12, 1], [100, 1]] aperture_range = [[40, 10], [40, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 27 10" make = "Olympus" model = "M.Zuiko Digital ED 30mm F3.5 Macro" focal_range = [[30, 1], [30, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 28 10" make = "Olympus" model = "M.Zuiko Digital ED 25mm F1.2 Pro" focal_range = [[25, 1], [25, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 29 10" make = "Olympus" model = "M.Zuiko Digital ED 17mm F1.2 Pro" focal_range = [[17, 1], [17, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 30 00" make = "Olympus" model = "Zuiko Digital ED 50-200mm F2.8-3.5 SWD" focal_range = [[50, 1], [200, 1]] aperture_range = [[28, 10], [35, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 30 10" make = "Olympus" model = "M.Zuiko Digital ED 45mm F1.2 Pro" focal_range = [[45, 1], [45, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 31 00" make = "Olympus" model = "Zuiko Digital ED 12-60mm F2.8-4.0 SWD" focal_range = [[12, 1], [60, 1]] aperture_range = [[28, 10], [40, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 32 00" make = "Olympus" model = "Zuiko Digital ED 14-35mm F2.0 SWD" focal_range = [[14, 1], [35, 1]] aperture_range = [[20, 10], [20, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 32 10" make = "Olympus" model = "M.Zuiko Digital ED 12-200mm F3.5-6.3" focal_range = [[12, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 33 00" make = "Olympus" model = "Zuiko Digital 25mm F2.8" focal_range = [[25, 1], [25, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 33 10" make = "Olympus" model = "M.Zuiko Digital 150-400mm F4.5 TC1.25x IS Pro" focal_range = [[150, 1], [400, 1]] aperture_range = [[45, 10], [45, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 34 00" make = "Olympus" model = "Zuiko Digital ED 9-18mm F4.0-5.6" focal_range = [[9, 1], [18, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 34 10" make = "Olympus" model = "M.Zuiko Digital ED 12-45mm F4.0 Pro" focal_range = [[12, 1], [45, 1]] aperture_range = [[40, 10], [40, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 35 00" make = "Olympus" model = "Zuiko Digital 14-54mm F2.8-3.5 II" focal_range = [[14, 1], [54, 1]] aperture_range = [[28, 10], [35, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 35 10" make = "Olympus" model = "M.Zuiko 100-400mm F5.0-6.3" focal_range = [[100, 1], [400, 1]] aperture_range = [[50, 10], [63, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "00 36 10" make = "Olympus" model = "M.Zuiko Digital ED 8-25mm F4 Pro" focal_range = [[8, 1], [25, 1]] aperture_range = [[4, 1], [4, 1]] rawler-0.7.1/data/lenses/mft_mount/sigma.toml000064400000000000000000000102041046102023000173310ustar 00000000000000[[lenses]] mount = "MFT-mount" olympus_id = "01 01 00" make = "Sigma" model = "18-50mm F3.5-5.6 DC" focal_range = [[18, 1], [50, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 01 10" make = "Sigma" model = "30mm F2.8 EX DN" focal_range = [[30, 1], [30, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 02 00" make = "Sigma" model = "55-200mm F4.0-5.6 DC" focal_range = [[55, 1], [200, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 02 10" make = "Sigma" model = "19mm F2.8 EX DN" focal_range = [[19, 1], [19, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 03 00" make = "Sigma" model = "18-125mm F3.5-5.6 DC" focal_range = [[18, 1], [125, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 03 10" make = "Sigma" model = "30mm F2.8 DN | A" focal_range = [[30, 1], [30, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 04 00" make = "Sigma" model = "18-125mm F3.5-5.6 DC" focal_range = [[18, 1], [125, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 04 10" make = "Sigma" model = "19mm F2.8 DN | A" focal_range = [[19, 1], [19, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 05 00" make = "Sigma" model = "30mm F1.4 EX DC HSM" focal_range = [[30, 1], [30, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 05 10" make = "Sigma" model = "60mm F2.8 DN | A" focal_range = [[60, 1], [60, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 06 00" make = "Sigma" model = "APO 50-500mm F4.0-6.3 EX DG HSM" focal_range = [[50, 1], [500, 1]] aperture_range = [[40, 10], [63, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 06 10" make = "Sigma" model = "30mm F1.4 DC DN | C" focal_range = [[30, 1], [30, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 07 00" make = "Sigma" model = "Macro 105mm F2.8 EX DG" focal_range = [[105, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 07 10" make = "Sigma" model = "16mm F1.4 DC DN | C (017)" focal_range = [[16, 1], [16, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 08 00" make = "Sigma" model = "APO Macro 150mm F2.8 EX DG HSM" focal_range = [[150, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 09 00" make = "Sigma" model = "18-50mm F2.8 EX DC Macro" focal_range = [[18, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 10 00" make = "Sigma" model = "24mm F1.8 EX DG Aspherical Macro" focal_range = [[24, 1], [24, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 11 00" make = "Sigma" model = "APO 135-400mm F4.5-5.6 DG" focal_range = [[135, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 12 00" make = "Sigma" model = "APO 300-800mm F5.6 EX DG HSM" focal_range = [[300, 1], [800, 1]] aperture_range = [[56, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 13 00" make = "Sigma" model = "30mm F1.4 EX DC HSM" focal_range = [[30, 1], [30, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 14 00" make = "Sigma" model = "APO 50-500mm F4.0-6.3 EX DG HSM" focal_range = [[50, 1], [500, 1]] aperture_range = [[40, 10], [63, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 15 00" make = "Sigma" model = "10-20mm F4.0-5.6 EX DC HSM" focal_range = [[10, 1], [20, 1]] aperture_range = [[40, 10], [56, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 16 00" make = "Sigma" model = "APO 70-200mm F2.8 II EX DG Macro HSM" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "MFT-mount" olympus_id = "01 17 00" make = "Sigma" model = "50mm F1.4 EX DG HSM" focal_range = [[50, 1], [50, 1]] aperture_range = [[14, 10], [14, 10]] rawler-0.7.1/data/lenses/nx_mount/samsung.toml000064400000000000000000000053671046102023000175630ustar 00000000000000[[lenses]] mount = "NX-mount" lens_id = 1 make = "Samsung" model = "NX 30mm F2 Pancake" focal_range = [[30, 1], [30, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "NX-mount" lens_id = 2 make = "Samsung" model = "NX 18-55mm F3.5-5.6 OIS" focal_range = [[18, 1], [55, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "NX-mount" lens_id = 3 make = "Samsung" model = "NX 50-200mm F4-5.6 ED OIS" focal_range = [[50, 1], [200, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "NX-mount" lens_id = 4 make = "Samsung" model = "NX 20-50mm F3.5-5.6 ED" focal_range = [[20, 1], [50, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "NX-mount" lens_id = 5 make = "Samsung" model = "NX 20mm F2.8 Pancake" focal_range = [[20, 1], [20, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "NX-mount" lens_id = 6 make = "Samsung" model = "NX 18-200mm F3.5-6.3 ED OIS" focal_range = [[18, 1], [200, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "NX-mount" lens_id = 7 make = "Samsung" model = "NX 60mm F2.8 Macro ED OIS SSA" focal_range = [[60, 1], [60, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "NX-mount" lens_id = 8 make = "Samsung" model = "NX 60mm F2.8 Macro ED OIS SSA" focal_range = [[60, 1], [60, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "NX-mount" lens_id = 9 make = "Samsung" model = "NX 85mm F1.4 ED SSA" focal_range = [[85, 1], [785, 1]] aperture_range = [[14, 10], [14, 10]] [[lenses]] mount = "NX-mount" lens_id = 10 make = "Samsung" model = "NX 45mm F1.8" focal_range = [[45, 1], [45, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "NX-mount" lens_id = 11 make = "Samsung" model = "NX 45mm F1.8 2D/3D" focal_range = [[45, 1], [45, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "NX-mount" lens_id = 12 make = "Samsung" model = "NX 12-24mm F4-5.6 ED" focal_range = [[12, 1], [24, 1]] aperture_range = [[4, 1], [56, 10]] [[lenses]] mount = "NX-mount" lens_id = 13 make = "Samsung" model = "NX 16-50mm F2-2.8 S ED OIS" focal_range = [[16, 1], [50, 1]] aperture_range = [[2, 1], [28, 10]] [[lenses]] mount = "NX-mount" lens_id = 14 make = "Samsung" model = "NX 10mm F3.5 Fisheye" focal_range = [[10, 1], [10, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "NX-mount" lens_id = 15 make = "Samsung" model = "NX 16-50mm F3.5-5.6 Power Zoom ED OIS" focal_range = [[16, 1], [50, 1]] aperture_range = [[35, 10], [56, 10]] [[lenses]] mount = "NX-mount" lens_id = 20 make = "Samsung" model = "NX 50-150mm F2.8 S ED OIS" focal_range = [[50, 1], [150, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "NX-mount" lens_id = 21 make = "Samsung" model = "NX 300mm F2.8 ED OIS" focal_range = [[300, 1], [300, 1]] aperture_range = [[28, 10], [28, 10]] rawler-0.7.1/data/lenses/phaseone/phaseone.toml000064400000000000000000000005351046102023000176330ustar 00000000000000[[lenses]] mount = "phaseone" key = "Schneider LS 150mm f/3.5" model = "150mm LS f/3.5" make = "Schneider" focal_range = [[150, 1], [150, 1]] aperture_range = [[35, 10], [35, 10]] [[lenses]] mount = "phaseone" key = "Rodenstock RS 50mm-Ar" model = "RS 50mm-Ar" make = "Rodenstock" focal_range = [[50, 1], [50, 1]] aperture_range = [[4, 1], [4, 1]] rawler-0.7.1/data/lenses/rf_mount/canon.toml000064400000000000000000000162311046102023000171560ustar 00000000000000[[lenses]] mount = "rf-mount" key = "RF50mm F1.2 L USM" lens_id = 61182 lens_subid = 257 make = "Canon" model = "RF 50mm F1.2L USM" focal_range = [[50, 1], [50, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "rf-mount" key = "RF24-105mm F4 L IS USM" lens_id = 61182 lens_subid = 258 make = "Canon" model = "RF 24-105mm F4L IS USM" focal_range = [[24, 1], [105, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "rf-mount" key = "RF28-70mm F2 L USM" lens_id = 61182 lens_subid = 259 make = "Canon" model = "RF 28-70mm F2L USM" focal_range = [[28, 1], [70, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "rf-mount" key = "RF35mm F1.8 MACRO IS STM" lens_id = 61182 lens_subid = 260 make = "Canon" model = "RF 35mm F1.8 MACRO IS STM" focal_range = [[35, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "rf-mount" key = "RF85mm F1.2 L USM" lens_id = 61182 lens_subid = 261 make = "Canon" model = "RF 85mm F1.2L USM" focal_range = [[85, 1], [85, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "rf-mount" key = "RF85mm F1.2 L USM DS" lens_id = 61182 lens_subid = 262 make = "Canon" model = "RF 85mm F1.2L USM DS" focal_range = [[85, 1], [85, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "rf-mount" key = "RF24-70mm F2.8 L IS USM" lens_id = 61182 lens_subid = 263 make = "Canon" model = "RF 24-70mm F2.8L IS USM" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "rf-mount" key = "RF28-70mm F2.8 IS STM" lens_id = 61182 lens_subid = 318 make = "Canon" model = "RF 24-70mm F2.8L IS STM" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "rf-mount" key = "RF15-35mm F2.8 L IS USM" lens_id = 61182 lens_subid = 264 make = "Canon" model = "RF 15-35mm F2.8L IS USM" focal_range = [[15, 1], [35, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "rf-mount" key = "RF24-240mm F4-6.3 IS USM" lens_id = 61182 lens_subid = 265 make = "Canon" model = "RF 24-240mm F4-6.3 IS USM" focal_range = [[24, 1], [240, 1]] aperture_range = [[4, 1], [63, 10]] [[lenses]] mount = "rf-mount" key = "RF70-200mm F2.8 L IS USM" lens_id = 61182 lens_subid = 266 make = "Canon" model = "RF 70-200mm F2.8L IS USM" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "rf-mount" lens_id = 61182 lens_subid = 267 make = "Canon" model = "RF 85mm F2 MACRO IS STM" focal_range = [[85, 1], [85, 1]] aperture_range = [[2, 1], [2, 1]] [[lenses]] mount = "rf-mount" key = "RF600mm F11 IS STM" lens_id = 61182 lens_subid = 268 make = "Canon" model = "RF 600mm F11 IS STM" focal_range = [[600, 1], [600, 1]] aperture_range = [[11, 1], [11, 1]] [[lenses]] mount = "rf-mount" lens_id = 61182 lens_subid = 269 make = "Canon" model = "RF 600mm F11 IS STM + RF1.4x" focal_range = [[600, 1], [600, 1]] aperture_range = [[11, 1], [11, 1]] [[lenses]] mount = "rf-mount" lens_id = 61182 lens_subid = 270 make = "Canon" model = "RF 600mm F11 IS STM + RF2x" focal_range = [[600, 1], [600, 1]] aperture_range = [[11, 1], [11, 1]] [[lenses]] mount = "rf-mount" key = "RF800mm F11 IS STM" lens_id = 61182 lens_subid = 271 make = "Canon" model = "RF 800mm F11 IS STM" focal_range = [[800, 1], [800, 1]] aperture_range = [[11, 1], [11, 1]] [[lenses]] mount = "rf-mount" lens_id = 61182 lens_subid = 272 make = "Canon" model = "RF 800mm F11 IS STM + RF1.4x" focal_range = [[800, 1], [800, 1]] aperture_range = [[11, 1], [11, 1]] [[lenses]] mount = "rf-mount" lens_id = 61182 lens_subid = 273 make = "Canon" model = "RF 800mm F11 IS STM + RF2x" focal_range = [[800, 1], [800, 1]] aperture_range = [[11, 1], [11, 1]] [[lenses]] mount = "rf-mount" key = "RF24-105mm F4-7.1 IS STM" lens_id = 61182 lens_subid = 274 make = "Canon" model = "RF 24-105mm F4-7.1 IS STM" focal_range = [[24, 1], [105, 1]] aperture_range = [[4, 1], [71, 10]] [[lenses]] mount = "rf-mount" key = "RF100-500mm F4.5-7.1 L IS USM" lens_id = 61182 lens_subid = 275 make = "Canon" model = "RF 100-500mm F4.5-7.1L IS USM" focal_range = [[100, 1], [500, 1]] aperture_range = [[45, 10], [71, 10]] [[lenses]] mount = "rf-mount" key = "RF100-500mm F4.5-7.1 L IS USM + EXTENDER RF1.4x" lens_id = 61182 lens_subid = 276 make = "Canon" model = "RF 100-500mm F4.5-7.1L IS USM + RF1.4x" focal_range = [[100, 1], [500, 1]] aperture_range = [[45, 10], [71, 10]] [[lenses]] mount = "rf-mount" key = "RF100-500mm F4.5-7.1 L IS USM + EXTENDER RF2x" lens_id = 61182 lens_subid = 277 make = "Canon" model = "RF 100-500mm F4.5-7.1L IS USM + RF2x" focal_range = [[100, 1], [500, 1]] aperture_range = [[45, 10], [71, 10]] [[lenses]] mount = "rf-mount" key = "RF70-200mm F4 L IS USM" lens_id = 61182 lens_subid = 278 make = "Canon" model = "RF 70-200mm F4L IS USM" focal_range = [[70, 1], [200, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "rf-mount" key = "RF50mm F1.8 STM" lens_id = 61182 lens_subid = 280 make = "Canon" model = "RF 50mm F1.8 STM" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "rf-mount" key = "RF14-35mm F4 L IS USM" lens_id = 61182 lens_subid = 281 make = "Canon" model = "RF 14-35mm F4L IS USM" focal_range = [[14, 1], [35, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "rf-mount" lens_id = 61182 lens_subid = 283 make = "Canon" model = "RF 100-400mm F5.6-8 IS USM" focal_range = [[100, 1], [400, 1]] aperture_range = [[56, 10], [8, 1]] [[lenses]] mount = "rf-mount" lens_id = 61182 lens_subid = 284 make = "Canon" model = "RF 100-400mm F5.6-8 IS USM + RF1.4x" focal_range = [[100, 1], [400, 1]] aperture_range = [[56, 10], [8, 1]] [[lenses]] mount = "rf-mount" lens_id = 61182 lens_subid = 285 make = "Canon" model = "RF 100-400mm F5.6-8 IS USM + RF2x" focal_range = [[100, 1], [400, 1]] aperture_range = [[56, 10], [8, 1]] [[lenses]] mount = "rf-mount" lens_id = 61182 lens_subid = 288 make = "Canon" model = "RF 16mm F2.8 STM" focal_range = [[16, 1], [16, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "rf-mount" key = "RF100mm F2.8 L MACRO IS USM" lens_id = 61182 lens_subid = 289 make = "Canon" model = "RF 100mm F2.8L Macro IS USM" focal_range = [[100, 1], [100, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "rf-mount" key = "RF-S18-150mm F3.5-6.3 IS STM" lens_id = 61182 lens_subid = 286 make = "Canon" model = "RF-S 18-150mm F3.5-6.3 IS STM" focal_range = [[18, 1], [150, 1]] aperture_range = [[5, 1], [63, 10]] [[lenses]] mount = "rf-mount" key = "RF135mm F1.8 L IS USM" lens_id = 61182 lens_subid = 303 make = "Canon" model = "RF 135mm F1.8L IS USM" focal_range = [[135, 1], [135, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "rf-mount" key = "RF200-800mm F6.3-9 IS USM" lens_id = 61182 lens_subid = 309 make = "Canon" model = "RF 200-800mm F6.3-9 IS USM" focal_range = [[200, 1], [800, 1]] aperture_range = [[63, 10], [9, 1]] [[lenses]] mount = "rf-mount" key = "RF-S10-18mm F4.5-6.3 IS STM" lens_id = 61182 lens_subid = 315 make = "Canon" model = "RF-S 10-18mm F4.5-6.3 IS STM" focal_range = [[10, 1], [18, 1]] aperture_range = [[45, 10], [63,10]] [[lenses]] mount = "rf-mount" key = "RF28mm F2.8 STM" lens_id = 61182 lens_subid = 313 make = "Canon" model = "RF 28mm F2.8 STM" focal_range = [[28, 1], [28, 1]] aperture_range = [[28, 10], [28,10]] rawler-0.7.1/data/lenses/rf_mount/samyang.toml000064400000000000000000000002521046102023000175130ustar 00000000000000[[lenses]] mount = "rf-mount" key = "SAMYANG RF 14mm F2.8" model = "AF 14/2.8 RF" make = "Samyang" focal_range = [[14, 1], [14, 1]] aperture_range = [[28, 10], [28, 10]] rawler-0.7.1/data/lenses/x_mount/hasselblad.toml000064400000000000000000000002301046102023000200120ustar 00000000000000[[lenses]] key = "xcd_80" mount = "x-mount" make = "Hasselblad" model = "XCD 80" focal_range = [[80, 1], [80, 1]] aperture_range = [[19, 10], [19, 10]] rawler-0.7.1/data/lenses/z_mount/nikon.toml000064400000000000000000000063231046102023000170410ustar 00000000000000[[lenses]] mount = "Z-mount" lens_id = 1 make = "Nikon" model = "Nikkor Z 24-70mm f/4 S" focal_range = [[24, 1], [70, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "Z-mount" lens_id = 2 make = "Nikon" model = "Nikkor Z 14-30mm f/4 S" focal_range = [[13, 1], [30, 1]] aperture_range = [[4, 1], [4, 1]] [[lenses]] mount = "Z-mount" lens_id = 4 make = "Nikon" model = "Nikkor Z 35mm f/1.8 S" focal_range = [[35, 1], [35, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "Z-mount" lens_id = 8 make = "Nikon" model = "Nikkor Z 58mm f/0.95 S Noct" focal_range = [[58, 1], [58, 1]] aperture_range = [[95, 100], [95, 100]] [[lenses]] mount = "Z-mount" lens_id = 9 make = "Nikon" model = "Nikkor Z 50mm f/1.8 S" focal_range = [[50, 1], [50, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "Z-mount" lens_id = 11 make = "Nikon" model = "Nikkor Z DX 16-50mm f/3.5-6.3 VR" focal_range = [[16, 1], [50, 1]] aperture_range = [[35, 10], [63, 10]] [[lenses]] mount = "Z-mount" lens_id = 12 make = "Nikon" model = "Nikkor Z DX 50-250mm f/4.5-6.3 VR" focal_range = [[50, 1], [250, 1]] aperture_range = [[45, 10], [63, 10]] [[lenses]] mount = "Z-mount" lens_id = 13 make = "Nikon" model = "Nikkor Z 24-70mm f/2.8 S" focal_range = [[24, 1], [70, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "Z-mount" lens_id = 14 make = "Nikon" model = "Nikkor Z 85mm f/1.8 S" focal_range = [[85, 1], [85, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "Z-mount" lens_id = 15 make = "Nikon" model = "Nikkor Z 24mm f/1.8 S" focal_range = [[24, 1], [24, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "Z-mount" lens_id = 16 make = "Nikon" model = "Nikkor Z 70-200mm f/2.8 VR S" focal_range = [[70, 1], [200, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "Z-mount" lens_id = 17 make = "Nikon" model = "Nikkor Z 20mm f/1.8 S" focal_range = [[20, 1], [20, 1]] aperture_range = [[18, 10], [18, 10]] [[lenses]] mount = "Z-mount" lens_id = 18 make = "Nikon" model = "Nikkor Z 24-200mm f/4-6.3 VR" focal_range = [[24, 1], [200, 1]] aperture_range = [[4, 1], [63, 10]] [[lenses]] mount = "Z-mount" lens_id = 21 make = "Nikon" model = "Nikkor Z 50mm f/1.2 S" focal_range = [[50, 1], [50, 1]] aperture_range = [[12, 10], [12, 10]] [[lenses]] mount = "Z-mount" lens_id = 22 make = "Nikon" model = "Nikkor Z 24-50mm f/4-6.3" focal_range = [[24, 1], [50, 1]] aperture_range = [[4, 1], [63, 10]] [[lenses]] mount = "Z-mount" lens_id = 23 make = "Nikon" model = "Nikkor Z 14-24mm f/2.8 S" focal_range = [[14, 1], [24, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "Z-mount" lens_id = 24 make = "Nikon" model = "Nikkor Z MC 105mm f/2.8 VR S" focal_range = [[105, 1], [105, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "Z-mount" lens_id = 27 make = "Nikon" model = "Nikkor Z MC 50mm f/2.8" focal_range = [[50, 1], [50, 1]] aperture_range = [[28, 10], [28, 10]] [[lenses]] mount = "Z-mount" lens_id = 28 make = "Nikon" model = "Nikkor Z 100-400mm f/4.5-5.6 VR S" focal_range = [[100, 1], [400, 1]] aperture_range = [[45, 10], [56, 10]] [[lenses]] mount = "Z-mount" lens_id = 29 make = "Nikon" model = "Nikkor Z 28mm f/2.8" focal_range = [[28, 1], [28, 1]] aperture_range = [[28, 10], [28, 10]] rawler-0.7.1/src/analyze.rs000064400000000000000000000212151046102023000137260ustar 00000000000000use std::{fs::metadata, io::Write, path::Path}; use byteorder::{BigEndian, WriteBytesExt}; use hex::FromHex; use image::DynamicImage; use itertools::Itertools; use md5::Digest; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use zerocopy::IntoBytes; use crate::{ RawImage, RawImageData, RawlerError, Result, decoders::{RawDecodeParams, RawMetadata, cr2::Cr2Format, cr3::Cr3Format, dng::DngFormat, iiq::IiqFormat, nef::NefFormat, pef::PefFormat, tfr::TfrFormat}, formats::tiff::Rational, formats::tiff::SRational, imgop::{Rect, develop::RawDevelop}, rawimage::{BlackLevel, WhiteLevel}, rawsource::RawSource, }; #[derive(Debug, Clone, PartialEq)] pub struct Md5Digest { digest: md5::Digest, } impl From for Md5Digest { fn from(digest: md5::Digest) -> Self { Self { digest } } } impl Serialize for Md5Digest { fn serialize(&self, serializer: S) -> std::result::Result where S: Serializer, { let s = format!("{:x}", self.digest); serializer.serialize_str(&s) } } impl<'de> Deserialize<'de> for Md5Digest { fn deserialize(deserializer: D) -> std::result::Result where D: Deserializer<'de>, { use serde::de::Error; let s = String::deserialize(deserializer)?; if s.len() != 32 { Err(D::Error::custom(format!("Invalid digest value: {}", s))) } else { Ok(Md5Digest { digest: Digest(<[u8; 16]>::from_hex(s).map_err(D::Error::custom)?), }) } } } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct FileMetadata { file_size: u64, file_name: String, digest: Option, } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AnalyzerMetadata { pub raw_params: RawParams, pub raw_metadata: RawMetadata, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] #[allow(clippy::large_enum_variant)] pub enum AnalyzerData { FileStructure(FormatDump), Metadata(AnalyzerMetadata), RawParams(RawParams), } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AnalyzerResult { pub file: FileMetadata, pub data: Option, } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CaptureInfo { pub make: String, pub model: String, pub exposure_time: Option, pub shutter_speed: Option, pub exposure_bias: Option, pub lens_make: Option, pub lens_model: Option, pub lens_spec: Option<[Rational; 4]>, } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RawParams { pub raw_width: usize, pub raw_height: usize, pub bit_depth: usize, pub crop_area: Option, pub active_area: Option, pub blacklevels: BlackLevel, pub whitelevels: WhiteLevel, pub wb_coeffs: (Option, Option, Option, Option), } impl From<&RawImage> for RawParams { fn from(rawimage: &RawImage) -> Self { Self { raw_width: rawimage.width, raw_height: rawimage.height, bit_depth: rawimage.bps, crop_area: rawimage.crop_area, active_area: rawimage.active_area, blacklevels: rawimage.blacklevel.clone(), whitelevels: rawimage.whitelevel.clone(), wb_coeffs: rawimage .wb_coeffs .iter() .map(|c| if c.is_nan() { None } else { Some(*c) }) .collect_tuple() .unwrap(), } } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] #[allow(clippy::large_enum_variant)] pub enum FormatDump { Cr3(Cr3Format), Cr2(Cr2Format), Pef(PefFormat), Iiq(IiqFormat), Tfr(TfrFormat), Nef(NefFormat), Dng(DngFormat), } fn file_metadata>(path: P, rawfile: &RawSource) -> Result { let fs_meta = metadata(&path).map_err(|e| RawlerError::with_io_error("read metadata", &path, e))?; let digest = rawfile.digest(); Ok(FileMetadata { file_name: path.as_ref().file_name().unwrap().to_string_lossy().to_string(), file_size: fs_meta.len(), digest: Some(digest.into()), }) } pub fn analyze_metadata>(path: P) -> Result { //let input = BufReader::new(File::open(&path).map_err(|e| RawlerError::with_io_error("load into buffer", &path, e))?); let rawfile = RawSource::new(path.as_ref())?; let decoder = crate::get_decoder(&rawfile)?; let rawimage = decoder.raw_image(&rawfile, &RawDecodeParams::default(), true)?; let mut result = AnalyzerResult { file: file_metadata(path, &rawfile)?, ..Default::default() }; let md = decoder.raw_metadata(&rawfile, &RawDecodeParams::default())?; result.data = Some(AnalyzerData::Metadata(AnalyzerMetadata { raw_params: RawParams::from(&rawimage), raw_metadata: md, })); Ok(result) } pub fn analyze_file_structure>(path: P) -> Result { let rawfile = RawSource::new(path.as_ref())?; let decoder = crate::get_decoder(&rawfile)?; let result = AnalyzerResult { file: file_metadata(path, &rawfile)?, data: Some(AnalyzerData::FileStructure(decoder.format_dump())), }; Ok(result) } pub fn extract_raw_pixels>(path: P, params: &RawDecodeParams) -> Result { let rawfile = RawSource::new(path.as_ref())?; let decoder = crate::get_decoder(&rawfile)?; let rawimage = decoder.raw_image(&rawfile, params, false)?; Ok(rawimage) } pub fn raw_pixels_digest>(path: P, params: &RawDecodeParams) -> Result<[u8; 16]> { let rawimage = extract_raw_pixels(path, params)?; let byte_buf = match &rawimage.data { RawImageData::Integer(items) => items.as_slice().as_bytes(), RawImageData::Float(items) => items.as_slice().as_bytes(), }; Ok(md5::compute(byte_buf).into()) } pub fn extract_full_pixels>(path: P, params: &RawDecodeParams) -> Result { let rawfile = RawSource::new(path.as_ref())?; let decoder = crate::get_decoder(&rawfile)?; match decoder.full_image(&rawfile, params)? { Some(preview) => Ok(preview), None => Err("Unable to extract full image from RAW".into()), } } pub fn extract_preview_pixels>(path: P, params: &RawDecodeParams) -> Result { let rawfile = RawSource::new(path.as_ref())?; let decoder = crate::get_decoder(&rawfile)?; match decoder.preview_image(&rawfile, params)? { Some(preview) => Ok(preview), None => match decoder.full_image(&rawfile, params)? { Some(preview) => Ok(preview), None => Err("Unable to extract preview image from RAW".into()), }, } } pub fn extract_thumbnail_pixels>(path: P, params: &RawDecodeParams) -> Result { let rawfile = RawSource::new(path.as_ref())?; let decoder = crate::get_decoder(&rawfile)?; match decoder.thumbnail_image(&rawfile, params)? { Some(thumbnail) => Ok(thumbnail), None => match decoder.preview_image(&rawfile, params)? { Some(thumbnail) => Ok(thumbnail), None => match decoder.full_image(&rawfile, params)? { Some(thumbnail) => Ok(thumbnail), None => Err("Unable to extract thumbnail image from RAW".into()), }, }, } } pub fn raw_to_srgb>(path: P, params: &RawDecodeParams) -> Result { let rawfile = RawSource::new(path.as_ref())?; // Get decoder or return let decoder = crate::get_decoder(&rawfile)?; //decoder.decode_metadata(&mut rawfile)?; let rawimage = decoder.raw_image(&rawfile, params, false)?; let dev = RawDevelop::default(); assert_eq!(rawimage.cpp, 1); Ok(dev.develop_intermediate(&rawimage)?.to_dynamic_image().unwrap()) } /// Dump raw pixel data as PGM pub fn raw_as_pgm(width: usize, height: usize, buf: &[u16], writer: &mut dyn Write) -> std::io::Result<()> { let header = format!("P5 {} {} {}\n", width, height, 65535); writer.write_all(header.as_bytes())?; for px in buf { writer.write_u16::(*px)?; } Ok(()) } /// Dump pixel data as PGM pub fn rgb8_as_ppm8(width: usize, height: usize, buf: &[u8], writer: &mut dyn Write) -> std::io::Result<()> { let header = format!("P6 {} {} {}\n", width, height, u8::MAX); writer.write_all(header.as_bytes())?; writer.write_all(buf)?; Ok(()) } /// Dump raw pixel data as PPM pub fn raw_as_ppm16(width: usize, height: usize, buf: &[u16], writer: &mut dyn Write) -> std::io::Result<()> { let header = format!("P6 {} {} {}\n", width, height, 65535); writer.write_all(header.as_bytes())?; for px in buf { writer.write_u16::(*px)?; } Ok(()) } rawler-0.7.1/src/bin/benchmark.rs000064400000000000000000000023001046102023000147570ustar 00000000000000use std::env; use std::path::PathBuf; use std::time::Instant; use rawler::decoders::RawDecodeParams; use rawler::rawsource::RawSource; fn usage() { println!("benchmark "); std::process::exit(1); } static ITERATIONS: u64 = 50; fn error(err: &str) { println!("ERROR: {}", err); std::process::exit(2); } fn main() { let args: Vec<_> = env::args().collect(); if args.len() != 2 { usage(); } let file = &args[1]; println!("Loading file \"{}\"", file); let rawfile = RawSource::new(&PathBuf::from(file)).expect("failed to load raw file"); let rawloader = rawler::RawLoader::new(); let from_time = Instant::now(); { for _ in 0..ITERATIONS { let decoder = match rawloader.get_decoder(&rawfile) { Ok(val) => val, Err(e) => { error(&e.to_string()); return; } }; match decoder.raw_image(&rawfile, &RawDecodeParams::default(), false) { Ok(_) => {} Err(e) => error(&e.to_string()), } } } let duration = from_time.elapsed(); let avgtime = ((duration.as_nanos() as u64) / ITERATIONS / 1000) as f64 / 1000.0; println!("Average decode time: {} ms ({} iterations)", avgtime, ITERATIONS); } rawler-0.7.1/src/bin/identify.rs000064400000000000000000000004621046102023000146470ustar 00000000000000use std::env; fn main() { let args: Vec<_> = env::args().collect(); if args.len() != 2 { println!("Usage: {} ", args[0]); std::process::exit(2); } let file = &args[1]; match rawler::decode_file(file) { Ok(_) => println!("OK file"), Err(_) => println!("FAILED file"), } } rawler-0.7.1/src/bitarray.rs000064400000000000000000000135561046102023000141110ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher use std::{ cmp::Ordering, fmt::{Debug, Display, Write}, ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Shl, ShlAssign, Shr, ShrAssign, Sub}, }; pub type BitArray8 = BitArray; pub type BitArray16 = BitArray; pub type BitArray32 = BitArray; pub type BitArray64 = BitArray; pub type BitArray128 = BitArray; #[derive(Debug, Clone, Copy, Default)] pub struct BitArray { storage: T, nbits: usize, } impl PartialEq for BitArray { fn eq(&self, other: &Self) -> bool { self.nbits == other.nbits && self.storage == other.storage } } impl Eq for BitArray {} impl PartialOrd for BitArray { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for BitArray { fn cmp(&self, other: &Self) -> std::cmp::Ordering { match self.nbits.cmp(&other.nbits) { Ordering::Equal => self.storage.cmp(&other.storage), res => res, } } } impl Display for BitArray { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut value = *self; let mut str = String::new(); while !value.is_empty() { match value.pop() { true => str.push('1'), false => str.push('0'), } } for c in str.chars().rev() { f.write_char(c)?; } Ok(()) } } impl BitArray { pub fn new() -> Self { Self { storage: T::default(), nbits: 0, } } pub fn len(&self) -> usize { self.nbits } pub fn storage(&self) -> T { self.storage } pub fn is_full(&self) -> bool { self.nbits == T::bit_size() } pub fn is_empty(&self) -> bool { self.nbits == 0 } pub fn push(&mut self, bit: bool) { if self.is_full() { panic!("BitArray is full"); } else { self.nbits += 1; self.storage = self.storage | (T::from(bit) << (T::bit_size() - self.nbits)); } } pub fn pop(&mut self) -> bool { if self.is_empty() { panic!("BitArray is empty"); } else { let mask = T::from(true) << (T::bit_size() - self.nbits); let bit = self.storage & mask; self.storage = self.storage & !mask; self.nbits -= 1; bit != T::from(false) } } pub fn get_msb(&self) -> T { self.storage } pub fn get_lsb(&self) -> T { self.storage >> (T::bit_size() - self.nbits) } pub fn from_msb(nbits: usize, value: T) -> Self { Self { storage: value, nbits } } pub fn from_lsb(nbits: usize, value: T) -> Self { Self { storage: value << (T::bit_size() - nbits), nbits, } } } pub trait BitStorage: Default + Debug + Display + Copy + Clone + ShlAssign + ShrAssign + Shl + Shl + Shr + Shr + Add + Sub + Div + Mul + BitXor + BitOr + BitAnd + Not + PartialEq + From + Ord + PartialOrd + Eq + PartialEq { fn bit_size() -> usize; } impl BitStorage for u8 { fn bit_size() -> usize { Self::BITS as usize } } impl BitStorage for u16 { fn bit_size() -> usize { Self::BITS as usize } } impl BitStorage for u32 { fn bit_size() -> usize { Self::BITS as usize } } impl BitStorage for u64 { fn bit_size() -> usize { Self::BITS as usize } } impl BitStorage for u128 { fn bit_size() -> usize { Self::BITS as usize } } #[cfg(test)] mod tests { use super::*; #[test] fn check_storage() -> std::result::Result<(), Box> { crate::init_test_logger(); assert_eq!(BitArray16::from_lsb(3, 0b110).storage(), 0b1100_0000_0000_0000); assert_eq!(BitArray16::from_msb(3, 0b110 << (u16::BITS - 3)).storage(), 0b1100_0000_0000_0000); Ok(()) } #[test] fn push_check_storage() -> std::result::Result<(), Box> { crate::init_test_logger(); let mut bits = BitArray8::new(); bits.push(true); assert_eq!(bits.len(), 1); assert_eq!(bits.storage(), 0b1000_0000); Ok(()) } #[test] fn ppo_check_storage() -> std::result::Result<(), Box> { crate::init_test_logger(); let mut bits = BitArray8::new(); bits.push(true); bits.push(false); bits.push(true); assert_eq!(bits.len(), 3); assert_eq!(bits.storage(), 0b1010_0000); assert_eq!(bits.pop(), true); assert_eq!(bits.storage(), 0b1000_0000); assert_eq!(bits.pop(), false); assert_eq!(bits.storage(), 0b1000_0000); assert_eq!(bits.pop(), true); assert_eq!(bits.storage(), 0b0000_0000); assert!(bits.is_empty()); Ok(()) } #[test] fn bitvec_compare() -> std::result::Result<(), Box> { crate::init_test_logger(); assert!(BitArray8::from_lsb(1, 0b1) > BitArray8::from_lsb(1, 0b0)); assert!(BitArray8::from_lsb(2, 0b00) > BitArray8::from_lsb(1, 0b0)); assert!(BitArray8::from_lsb(2, 0b11) < BitArray8::from_lsb(3, 0b000)); assert!(BitArray8::from_lsb(3, 0b101) == BitArray8::from_lsb(3, 0b101)); assert!(BitArray8::from_lsb(3, 0b101) != BitArray8::from_lsb(3, 0b111)); assert_eq!(10u8.cmp(&20u8), Ordering::Less); assert_eq!(BitArray8::from_lsb(1, 0b0).cmp(&BitArray8::from_lsb(1, 0b1)), Ordering::Less); assert_eq!(BitArray8::from_lsb(1, 0b1).cmp(&BitArray8::from_lsb(1, 0b0)), Ordering::Greater); assert_eq!(BitArray8::from_lsb(1, 0b1).cmp(&BitArray8::from_lsb(1, 0b1)), Ordering::Equal); assert_eq!(BitArray8::from_lsb(1, 0b0).cmp(&BitArray8::from_lsb(2, 0b1)), Ordering::Less); assert_eq!(BitArray8::from_lsb(1, 0b1).cmp(&BitArray8::from_lsb(2, 0b0)), Ordering::Less); assert_eq!(BitArray8::from_lsb(1, 0b1).cmp(&BitArray8::from_lsb(2, 0b1)), Ordering::Less); Ok(()) } } rawler-0.7.1/src/bits.rs000064400000000000000000000261651046102023000132350ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2025 Daniel Vogelbacher // // Floating-Point trait was ported from rawspeed: // https://github.com/darktable-org/rawspeed/blob/6815b8ca1469234768edc9ddce8b7efb419381bf/src/librawspeed/common/FloatingPoint.h // Copyright (C) 2017 Vasily Khoruzhick // Copyright (C) 2020 Roman Lebedev use std::iter::repeat; use byteorder::{BigEndian, ByteOrder, LittleEndian}; use serde::{Deserialize, Serialize}; #[inline(always)] pub fn clampbits(val: i32, bits: u32) -> u16 { let max = (1 << bits) - 1; if val < 0 { 0 } else if val > max { max as u16 } else { val as u16 } } pub fn clamp(val: i32, min: i32, max: i32) -> i32 { let mut res = val; if res < min { res = min; } if res > max { res = max; } res } /// Calculate the required bits to encode as many states. pub fn log2ceil(mut states: usize) -> usize { let mut bits = 0; if states > 0 { states -= 1; loop { states >>= 1; bits += 1; if states == 0 { break; } } } bits } #[inline] pub fn scale_u16(p: u16, bits: u32) -> u16 { let max = ((1_u32 << bits) - 1) as u16; ((p as f32 / max as f32) * u16::MAX as f32) as u16 } #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] pub enum Endian { Big, Little, } impl Default for Endian { fn default() -> Self { Self::Little } } impl Endian { #[inline] pub fn big(&self) -> bool { matches!(*self, Self::Big) } #[inline] pub fn little(&self) -> bool { matches!(*self, Self::Little) } #[inline] pub fn read_u8(&self, buf: &[u8], offset: usize) -> u8 { buf[offset] } #[inline] pub fn read_i8(&self, buf: &[u8], offset: usize) -> i8 { buf[offset] as i8 } #[inline] pub fn read_u16(&self, buf: &[u8], offset: usize) -> u16 { match *self { Self::Big => BigEndian::read_u16(&buf[offset..]), Self::Little => LittleEndian::read_u16(&buf[offset..]), } } #[inline] pub fn read_i16(&self, buf: &[u8], offset: usize) -> i16 { match *self { Self::Big => BigEndian::read_i16(&buf[offset..]), Self::Little => LittleEndian::read_i16(&buf[offset..]), } } #[inline] pub fn read_u32(&self, buf: &[u8], offset: usize) -> u32 { match *self { Self::Big => BigEndian::read_u32(&buf[offset..]), Self::Little => LittleEndian::read_u32(&buf[offset..]), } } #[inline] pub fn read_i32(&self, buf: &[u8], offset: usize) -> i32 { match *self { Self::Big => BigEndian::read_i32(&buf[offset..]), Self::Little => LittleEndian::read_i32(&buf[offset..]), } } #[inline] pub fn write_u16(&self, buf: &mut [u8], n: u16) { match *self { Self::Big => BigEndian::write_u16(buf, n), Self::Little => LittleEndian::write_u16(buf, n), } } } #[allow(non_snake_case)] #[inline] pub fn BEi32(buf: &[u8], pos: usize) -> i32 { BigEndian::read_i32(&buf[pos..pos + 4]) } #[allow(non_snake_case)] #[inline] pub fn LEi32(buf: &[u8], pos: usize) -> i32 { LittleEndian::read_i32(&buf[pos..pos + 4]) } #[allow(non_snake_case)] #[inline] pub fn BEu32(buf: &[u8], pos: usize) -> u32 { BigEndian::read_u32(&buf[pos..pos + 4]) } #[allow(non_snake_case)] #[inline] pub fn LEu32(buf: &[u8], pos: usize) -> u32 { LittleEndian::read_u32(&buf[pos..pos + 4]) } #[allow(non_snake_case)] #[inline] pub fn LEf32(buf: &[u8], pos: usize) -> f32 { LittleEndian::read_f32(&buf[pos..pos + 4]) } #[allow(non_snake_case)] #[inline] pub fn LEf24(buf: &[u8], pos: usize) -> f32 { let fp24: u32 = u32::from_le_bytes([buf[pos + 0], buf[pos + 1], buf[pos + 2], 0]); f32::from_bits(extend_binary_floating_point::(fp24)) } #[allow(non_snake_case)] #[inline] pub fn BEf24(buf: &[u8], pos: usize) -> f32 { let fp24: u32 = u32::from_be_bytes([0, buf[pos + 0], buf[pos + 1], buf[pos + 2]]); f32::from_bits(extend_binary_floating_point::(fp24)) } #[allow(non_snake_case)] #[inline] pub fn LEf16(buf: &[u8], pos: usize) -> f32 { let fp16: u16 = u16::from_le_bytes([buf[pos + 0], buf[pos + 1]]); f32::from_bits(extend_binary_floating_point::(fp16 as u32)) } #[allow(non_snake_case)] #[inline] pub fn BEf16(buf: &[u8], pos: usize) -> f32 { let fp16: u16 = u16::from_be_bytes([buf[pos + 0], buf[pos + 1]]); f32::from_bits(extend_binary_floating_point::(fp16 as u32)) } #[allow(non_snake_case)] #[inline] pub fn BEf32(buf: &[u8], pos: usize) -> f32 { BigEndian::read_f32(&buf[pos..pos + 4]) } #[allow(non_snake_case)] #[inline] pub fn BEu16(buf: &[u8], pos: usize) -> u16 { BigEndian::read_u16(&buf[pos..pos + 2]) } #[allow(non_snake_case)] #[inline] pub fn LEu16(buf: &[u8], pos: usize) -> u16 { LittleEndian::read_u16(&buf[pos..pos + 2]) } #[derive(Debug, Clone)] pub struct LookupTable { table: Vec<(u16, u16, u16)>, } impl LookupTable { pub fn new(table: &[u16]) -> LookupTable { let mut tbl = vec![(0, 0, 0); table.len()]; for i in 0..table.len() { let center = table[i]; let lower = if i > 0 { table[i - 1] } else { center }; let upper = if i < (table.len() - 1) { table[i + 1] } else { center }; let base = if center == 0 { 0 } else { center - ((upper - lower + 2) / 4) }; let delta = upper - lower; tbl[i] = (center, base, delta); } LookupTable { table: tbl } } pub fn new_with_bits(table: &[u16], bits: u32) -> LookupTable { assert!(!table.is_empty()); if table.len() >= 1 << bits { Self::new(table) } else { let mut expanded = Vec::with_capacity(1 << bits); expanded.extend_from_slice(table); expanded.extend(repeat(table.last().expect("Need one element")).take((1 << bits) - table.len())); Self::new(&expanded) } } // pub fn lookup(&self, value: u16) -> u16 { // let (val, _, _) = self.table[value as usize]; // val // } #[inline(always)] pub fn dither(&self, value: u16, rand: &mut u32) -> u16 { let (_, sbase, sdelta) = self.table[value as usize]; let base = sbase as u32; let delta = sdelta as u32; let pixel = base + ((delta * (*rand & 2047) + 1024) >> 12); *rand = 15700 * (*rand & 65535) + (*rand >> 16); pixel as u16 } } /// A trait defining compile-time parameters for a floating-point representation. /// /// This trait provides associated constants that describe the bit layout of a floating-point type, /// including the total storage width, the number of bits for the fraction (mantissa), and the exponent. /// It also provides derived constants for the sign bit, precision, exponent bias, and bit positions. /// /// # Associated Constants /// - `STORAGE_WIDTH`: Total number of bits used to store the floating-point value. /// - `FRACTION_WIDTH`: Number of bits used for the fraction (mantissa). /// - `EXPONENT_WIDTH`: Number of bits used for the exponent. /// - `STORAGE_BYTES`: Number of bytes required (rounded up) for storage. /// - `SIGN_BITS`: Number of bits used for the sign (always 1). /// - `PRECISION`: Number of significant bits in the mantissa (fraction width + 1 for the implicit bit). /// - `EXPONENT_MAX`: Maximum value of the exponent (before bias). /// - `BIAS`: Bias value applied to the exponent. /// - `FRACTION_POS`: Bit position where the fraction starts (always 0). /// - `EXPONENT_POS`: Bit position where the exponent starts. /// - `SIGN_BIT_POS`: Bit position of the sign bit (highest bit). pub(crate) trait FloatingPointParameters { const STORAGE_WIDTH: usize; const FRACTION_WIDTH: usize; const EXPONENT_WIDTH: usize; const STORAGE_BYTES: usize = Self::STORAGE_WIDTH.div_ceil(u8::BITS as usize); const SIGN_BITS: usize = 1; const PRECISION: usize = Self::FRACTION_WIDTH + 1; const EXPONENT_MAX: usize = (1 << (Self::EXPONENT_WIDTH - 1)) - 1; const BIAS: i32 = Self::EXPONENT_MAX as i32; const FRACTION_POS: usize = 0; // FractionPos is always 0. const EXPONENT_POS: usize = Self::FRACTION_WIDTH; const SIGN_BIT_POS: usize = Self::STORAGE_WIDTH - 1; } /// A generic struct representing a binary number with customizable storage width, fraction width, and exponent width. /// /// # Type Parameters /// - `STORAGE_WITH`: The total number of bits used for storage. /// - `FRACTION_WIDTH`: The number of bits allocated for the fractional part. /// - `EXPONENT_WIDTH`: The number of bits allocated for the exponent part. /// /// This struct can be used to represent custom floating-point or fixed-point binary formats. pub(crate) struct BinaryN {} impl FloatingPointParameters for BinaryN { const STORAGE_WIDTH: usize = STORAGE_WITH; const FRACTION_WIDTH: usize = FRACTION_WIDTH; const EXPONENT_WIDTH: usize = EXPONENT_WIDTH; const SIGN_BITS: usize = 1; } pub(crate) type Binary16 = BinaryN<16, 10, 5>; pub(crate) type Binary24 = BinaryN<24, 16, 7>; pub(crate) type Binary32 = BinaryN<32, 23, 8>; pub(crate) fn extend_binary_floating_point(value: u32) -> u32 { let sign = (value >> NARROW::SIGN_BIT_POS) & 1; let narrow_exponent = (value >> NARROW::EXPONENT_POS) & ((1 << NARROW::EXPONENT_WIDTH) - 1); let narrow_fraction = value & ((1 << NARROW::FRACTION_WIDTH) - 1); // Normalized or zero let mut wide_exponent = ((narrow_exponent as i32) - NARROW::BIAS + WIDE::BIAS) as u32; let mut wide_fraction = narrow_fraction << (WIDE::FRACTION_WIDTH - NARROW::FRACTION_WIDTH); if narrow_exponent == ((1 << NARROW::EXPONENT_WIDTH) - 1) { // Infinity or NaN wide_exponent = (1 << WIDE::EXPONENT_WIDTH) - 1; // Narrow fraction is kept/widened! } else if narrow_exponent == 0 { if narrow_fraction == 0 { // +-Zero wide_exponent = 0; wide_fraction = 0; } else { // Subnormal numbers // We can represent it as a normalized value in wider type, // we have to shift fraction until we get 1.new_fraction // and decrement exponent for each shift. // FIXME; what is the implicit precondition here? wide_exponent = (1 - NARROW::BIAS + WIDE::BIAS) as u32; while 0 == (wide_fraction & (1 << WIDE::FRACTION_WIDTH)) { wide_exponent -= 1; wide_fraction <<= 1; } wide_fraction &= (1 << WIDE::FRACTION_WIDTH) - 1; } } return (sign << WIDE::SIGN_BIT_POS) | (wide_exponent << WIDE::EXPONENT_POS) | wide_fraction; } #[cfg(test)] mod tests { use super::*; #[test] fn test_convert() { assert_eq!(Binary16::PRECISION, 11); assert_eq!(Binary16::EXPONENT_MAX, 15); assert_eq!(Binary16::EXPONENT_POS, 10); assert_eq!(Binary16::SIGN_BIT_POS, 15); assert_eq!(Binary16::STORAGE_BYTES, 2); assert_eq!(Binary24::PRECISION, 17); assert_eq!(Binary24::EXPONENT_MAX, 63); assert_eq!(Binary24::EXPONENT_POS, 16); assert_eq!(Binary24::SIGN_BIT_POS, 23); assert_eq!(Binary24::STORAGE_BYTES, 3); assert_eq!(Binary32::PRECISION, 24); assert_eq!(Binary32::EXPONENT_MAX, 127); assert_eq!(Binary32::EXPONENT_POS, 23); assert_eq!(Binary32::SIGN_BIT_POS, 31); assert_eq!(Binary32::STORAGE_BYTES, 4); } } rawler-0.7.1/src/buffer.rs000064400000000000000000000016161046102023000135370ustar 00000000000000use std::ops::Deref; /// Buffer to hold an image in memory with enough extra space at the end for speed optimizations pub struct PaddedBuf<'a> { buf: PaddedBufImpl<'a>, size: usize, } pub enum PaddedBufImpl<'a> { Owned(Vec), Ref(&'a [u8]), } impl<'a> PaddedBuf<'a> { pub fn new_owned(buf: Vec, size: usize) -> Self { Self { buf: PaddedBufImpl::Owned(buf), size, } } pub fn new_ref(buf: &'a [u8], size: usize) -> Self { Self { buf: PaddedBufImpl::Ref(buf), size, } } pub fn size(&self) -> usize { self.size } pub fn buf(&'a self) -> &'a [u8] { self } pub fn real_size(&self) -> usize { self.buf().len() } } impl<'a> Deref for PaddedBuf<'a> { type Target = [u8]; fn deref(&self) -> &Self::Target { match &self.buf { PaddedBufImpl::Owned(x) => x.as_ref(), PaddedBufImpl::Ref(x) => x, } } } rawler-0.7.1/src/cfa.rs000064400000000000000000000234571046102023000130260ustar 00000000000000use std::fmt; use itertools::Itertools; use crate::formats::tiff::{self, Value}; pub const CFA_COLOR_R: usize = 0; pub const CFA_COLOR_G: usize = 1; pub const CFA_COLOR_B: usize = 2; use num_enum::TryFromPrimitive; #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, TryFromPrimitive)] #[repr(u8)] #[allow(non_camel_case_types)] pub enum CFAColor { // see also DngDecoder RED = 0, GREEN = 1, BLUE = 2, CYAN = 3, MAGENTA = 4, YELLOW = 5, WHITE = 6, FUJI_GREEN = 7, END, // keep it last! UNKNOWN = 255, } impl Default for CFAColor { fn default() -> Self { Self::UNKNOWN } } impl TryFrom for CFAColor { type Error = String; fn try_from(value: char) -> Result { Ok(match value { 'R' => Self::RED, 'G' => Self::GREEN, 'B' => Self::BLUE, 'E' => Self::CYAN, 'M' => Self::MAGENTA, 'Y' => Self::YELLOW, 'C' => Self::CYAN, _ => { return Err(format!("Unknown CFA color \"{}\"", value)); } }) } } /// Representation of the color filter array pattern in raw cameras /// /// # Example /// ``` /// use rawler::CFA; /// let cfa = CFA::new("RGGB"); /// assert_eq!(cfa.color_at(0,0), 0); /// assert_eq!(cfa.color_at(0,1), 1); /// assert_eq!(cfa.color_at(1,0), 1); /// assert_eq!(cfa.color_at(1,1), 2); /// ``` /// /// You will almost always get your CFA struct from a RawImage decode, already fully /// initialized and ready to be used in processing. The color_at() implementation is /// designed to be fast so it can be called inside the inner loop of demosaic or other /// color-aware algorithms that work on pre-demosaic data #[derive(Clone, Eq, PartialEq, PartialOrd, Ord)] pub struct CFA { /// CFA pattern as a String pub name: String, /// Width of the repeating pattern pub width: usize, /// Height of the repeating pattern pub height: usize, // Actual pattern. We use u8 here because usize would blow // the stack usage and we don't need that much bits. pattern: [[u8; 48]; 48], } impl Default for CFA { fn default() -> Self { Self::new("") } } impl CFA { #[doc(hidden)] pub fn new_from_tag(pat: &Value) -> CFA { let mut patname = String::new(); for i in 0..pat.count() { patname.push(match pat.force_u32(i as usize) { 0 => 'R', 1 => 'G', 2 => 'B', 3 => 'C', 4 => 'M', 5 => 'Y', _ => 'U', }); } CFA::new(&patname) } /// Create a new CFA from a string describing it. For simplicity the pattern is specified /// as each pixel being one of R/G/B/E representing the 0/1/2/3 colors in a 4 color image. /// The pattern is specified as the colors in each row concatenated so RGGB means that /// the first row is RG and the second row GB. Row size is determined by pattern size /// (e.g., the xtrans pattern is 6x6 and thus 36 characters long). In theory this could /// lead to confusion between different pattern sizes but in practice there are only /// a few oddball cameras no one cares about that do anything but 2x2 and 6x6 (and those /// work fine with this as well). pub fn new(patname: &str) -> CFA { let (width, height) = match patname.len() { 0 => (0, 0), 4 => (2, 2), 36 => (6, 6), 16 => (2, 8), 144 => (12, 12), _ => panic!("Unknown CFA size \"{}\"", patname), }; let mut pattern: [[u8; 48]; 48] = [[0; 48]; 48]; if width > 0 { // copy the pattern into the top left for (i, c) in patname.chars().enumerate() { pattern[i / width][i % width] = CFAColor::try_from(c).expect("Invalid CFA pattern") as u8; } // extend the pattern into the full matrix for row in 0..48 { for col in 0..48 { pattern[row][col] = pattern[row % height][col % width]; } } } CFA { name: patname.to_string(), pattern, width, height, } } /// Remap the color values /// This is useful if you need to remap RGB to R G1 G2 B. pub fn map_colors(&self, op: F) -> Self where F: Fn(usize, usize, u8) -> u8, // row, col, color -> new-color { let mut copy = self.clone(); for row in 0..48 { for col in 0..48 { copy.pattern[row][col] = op(row % self.height, col % self.width, copy.pattern[row % self.height][col % self.width]); } } copy } /// Get the color index at the given position. Designed to be fast so it can be called /// from inner loops without performance issues. pub fn color_at(&self, row: usize, col: usize) -> usize { self.pattern[(row + 48) % 48][(col + 48) % 48] as usize } /// from inner loops without performance issues. pub fn cfa_color_at(&self, row: usize, col: usize) -> CFAColor { (self.pattern[(row + 48) % 48][(col + 48) % 48]).try_into().unwrap() } /// Get a flat pattern pub fn flat_pattern(&self) -> Vec { self .pattern .iter() .take(self.height) .flat_map(|v| v.iter().take(self.width)) .cloned() .map(|v| v as u8) .collect() } /// Count of unique colors in pattern pub fn unique_colors(&self) -> usize { self.pattern.iter().flatten().unique().count() } /// Check if pattern is a RGGB or variant. /// False for 4-color patterns like RGBE. pub fn is_rgb(&self) -> bool { self.name.chars().filter(|ch| !['R', 'G', 'B'].contains(ch)).count() == 0 && self.name.contains('R') && self.name.contains('G') && self.name.contains('B') } pub fn is_rgbe(&self) -> bool { self.name.chars().filter(|ch| !['R', 'G', 'B', 'E'].contains(ch)).count() == 0 && self.name.contains('R') && self.name.contains('G') && self.name.contains('B') && self.name.contains('E') } pub fn is_cygm(&self) -> bool { self.name.chars().filter(|ch| !['C', 'Y', 'G', 'M'].contains(ch)).count() == 0 && self.name.contains('C') && self.name.contains('Y') && self.name.contains('G') && self.name.contains('M') } /// Shift the pattern left and/or down. This is useful when cropping the image to get /// the equivalent pattern of the crop when it's not a multiple of the pattern size. /// /// # Example /// ``` /// use rawler::CFA; /// let cfa = CFA::new("RGGB"); /// assert_eq!(cfa.color_at(0,0), 0); /// assert_eq!(cfa.color_at(0,1), 1); /// assert_eq!(cfa.color_at(1,0), 1); /// assert_eq!(cfa.color_at(1,1), 2); /// /// let shifted = cfa.shift(1,1); /// assert_eq!(shifted.color_at(0,0), 2); /// assert_eq!(shifted.color_at(0,1), 1); /// assert_eq!(shifted.color_at(1,0), 1); /// assert_eq!(shifted.color_at(1,1), 0); /// ``` pub fn shift(&self, x: usize, y: usize) -> CFA { let mut pattern: [[u8; 48]; 48] = [[0; 48]; 48]; for row in 0..48 { for col in 0..48 { pattern[row][col] = self.color_at(row + y, col + x) as u8; } } let mut name = "".to_string(); for row in 0..self.height { for col in 0..self.width { name.push_str(match pattern[row][col] { 0 => "R", 1 => "G", 2 => "B", 3 => "C", 4 => "M", 5 => "Y", x => panic!("Unknown CFA color \"{}\"", x), }); } } CFA { name, pattern, width: self.width, height: self.height, } } /// Test if this is actually a valid CFA pattern /// /// # Example /// ``` /// use rawler::CFA; /// let cfa = CFA::new("RGGB"); /// assert!(cfa.is_valid()); /// /// let cfa = CFA::new(""); /// assert!(!cfa.is_valid()); /// ``` pub fn is_valid(&self) -> bool { self.width != 0 && self.height != 0 } } impl fmt::Display for CFA { /// Convert the CFA back into a pattern string /// /// # Example /// ``` /// use rawler::CFA; /// let cfa = CFA::new("RGGB"); /// assert_eq!(cfa.to_string(), "RGGB"); /// /// let shifted = cfa.shift(1,1); /// assert_eq!(shifted.to_string(), "BGGR"); /// ``` fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(&self.name) } } impl fmt::Debug for CFA { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "CFA {{ {} }}", self.name) } } #[derive(Clone, Eq, PartialEq)] pub struct PlaneColor { pub colors: Vec, } impl PlaneColor { pub fn new(patname: &str) -> Self { let mut colors = vec![CFAColor::default(); patname.len()]; for (i, c) in patname.chars().enumerate() { colors[i] = CFAColor::try_from(c).expect("Invalid CFA color"); } Self { colors } } pub fn plane_colors(&self) -> [CFAColor; N] { self.colors.clone().try_into().expect("PlaneColor has invalid length") } /// Build a lookup table for all possible colors (up to 255). /// The value is the plane/channel number. pub fn plane_lookup_table(&self) -> [usize; 256] { let mut map = [255; 256]; self.colors.iter().enumerate().for_each(|(plane, color)| { map[*color as usize] = plane; }); map } pub fn plane_count(&self) -> usize { self.colors.len() } /// Returns the first occourence for given color. pub fn cfa_index(cfa: &CFA, color: CFAColor) -> usize { for row in 0..cfa.height { for col in 0..cfa.width { if cfa.cfa_color_at(row, col) == color { return row * cfa.width + col; } } } panic!("CFAColor {:?} is not included in CFA {:?}", color, cfa); } } impl From<&PlaneColor> for tiff::Value { fn from(value: &PlaneColor) -> Self { Self::Byte(value.colors.iter().map(|x| *x as u8).collect()) } } impl From for PlaneColor where T: Into>, { fn from(value: T) -> Self { Self { colors: value.into() } } } impl Default for PlaneColor { fn default() -> Self { Self::from([CFAColor::RED, CFAColor::GREEN, CFAColor::BLUE]) } } impl fmt::Debug for PlaneColor { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "PlaneColors {{ {:?} }}", self.colors) } } rawler-0.7.1/src/decoders/ari.rs000064400000000000000000000063401046102023000146300ustar 00000000000000use crate::RawImage; use crate::RawLoader; use crate::Result; use crate::bits::*; use crate::exif::Exif; use crate::formats::tiff::Rational; use crate::packed::*; use crate::rawsource::RawSource; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use super::ok_cfa_image; pub fn is_ari(file: &RawSource) -> bool { match file.subview(0, 4) { Ok(buf) => buf[0..4] == b"ARRI"[..], Err(_) => false, } } #[derive(Debug, Clone)] pub struct AriDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, camera: Camera, } impl<'a> AriDecoder<'a> { pub fn new(file: &RawSource, rawloader: &'a RawLoader) -> Result> { let buffer = file.subview(668, 30)?; let model = String::from_utf8_lossy(buffer).split_terminator('\0').next().unwrap_or("").to_string(); let camera = rawloader.check_supported_with_everything("ARRI", &model, "")?; Ok(AriDecoder { rawloader, camera }) } } impl<'a> Decoder for AriDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let buffer = file.subview(0, 100)?; let offset = LEu32(buffer, ArriRawTag::DataOffset as usize) as usize; let width = LEu32(buffer, ArriRawTag::Width as usize) as usize; let height = LEu32(buffer, ArriRawTag::Height as usize) as usize; let src = file.subview_until_eof_padded(offset as u64)?; let image = if self.camera.find_hint("little-endian") { decode_12le(&src, width, height, dummy) } else { decode_12be_msb32(&src, width, height, dummy) }; let cpp = 1; ok_cfa_image(self.camera.clone(), cpp, self.get_wb(file)?, image, dummy) } fn format_dump(&self) -> crate::analyze::FormatDump { todo!() } fn raw_metadata(&self, file: &RawSource, _params: &RawDecodeParams) -> Result { let mut exif = Exif::default(); let buffer = file.subview(0, 0x0a98)?; // max header exif.recommended_exposure_index = Some(LEu32(buffer, ArriRawTag::ExposureIndexASA as usize)); exif.sensitivity_type = Some(2); let lens_model = char_slice_to_string(&buffer[ArriRawTag::LensModel as usize..ArriRawTag::LensModel as usize + 32]); exif.lens_model = lens_model.map(|s| s.trim().into()); log::debug!("Lens model: {:?}", exif.lens_model); let exposure_time = LEu32(buffer, ArriRawTag::ExposureTime as usize); exif.exposure_time = Some(Rational::new(exposure_time, 1000000)); let focal_len = LEu32(buffer, ArriRawTag::LensFocalLen as usize); exif.focal_length = Some(Rational::new(focal_len, 1000)); let mdata = RawMetadata::new(&self.camera, exif); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::ARI } } impl<'a> AriDecoder<'a> { fn get_wb(&self, file: &RawSource) -> Result<[f32; 4]> { let buffer = file.subview(0, 100 + 12)?; Ok([LEf32(buffer, 100), LEf32(buffer, 104), LEf32(buffer, 108), f32::NAN]) } } enum ArriRawTag { DataOffset = 0x0008, Width = 0x0014, Height = 0x0018, ExposureIndexASA = 0x0074, ExposureTime = 0x018C, LensFocalLen = 0x037C, LensModel = 0x0398, } fn char_slice_to_string(buf: &[u8]) -> Option { Some(buf.iter().take_while(|&&c| c != 0).map(|&c| char::from(c)).collect()) } rawler-0.7.1/src/decoders/arw.rs000064400000000000000000000675201046102023000146550ustar 00000000000000use std::cmp; use std::io::Cursor; use image::DynamicImage; use log::debug; use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::alloc_image; use crate::bits::*; use crate::decoders::decode_threaded; use crate::decoders::decode_threaded_multiline; use crate::decompressors::ljpeg::LjpegDecompressor; use crate::exif::Exif; use crate::formats::tiff::Entry; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::IFD; use crate::formats::tiff::Value; use crate::formats::tiff::ifd::OffsetMode; use crate::formats::tiff::reader::TiffReader; use crate::imgop::Dim2; use crate::imgop::Point; use crate::imgop::Rect; use crate::imgop::yuv::interpolate_yuv; use crate::imgop::yuv::ycbcr_to_rgb; use crate::lens::LensDescription; use crate::lens::LensResolver; use crate::packed::decode_12le; use crate::packed::decode_14be_unpacked; use crate::packed::decode_16be; use crate::packed::decode_16le; use crate::pixarray::PixU16; use crate::pumps::BitPump; use crate::pumps::BitPumpLSB; use crate::pumps::BitPumpMSB; use crate::rawimage::BlackLevel; use crate::rawimage::CFAConfig; use crate::rawimage::RawPhotometricInterpretation; use crate::rawimage::WhiteLevel; use crate::rawsource::RawSource; use crate::tags::ExifTag; use crate::tags::TiffCommonTag; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use super::ok_cfa_image; const SONY_E_MOUNT: &str = "e-mount"; const SONY_A_MOUNT: &str = "a-mount"; #[derive(Debug, Clone)] pub struct ArwDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, makernote: IFD, camera: Camera, } impl<'a> ArwDecoder<'a> { pub fn new(file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { let camera = rawloader.check_supported(tiff.root_ifd())?; let makernote = if let Some(exif) = tiff.find_first_ifd_with_tag(ExifTag::MakerNotes) { exif.parse_makernote(&mut file.reader(), OffsetMode::Absolute, &[])? } else { log::warn!("ARW makernote not found"); None } .ok_or("File has not makernotes")?; //makernote.dump::(0).iter().for_each(|line| eprintln!("DUMP: {}", line)); Ok(ArwDecoder { tiff, rawloader, makernote, camera, }) } } impl<'a> Decoder for ArwDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let data = self.tiff.find_ifds_with_tag(TiffCommonTag::StripOffsets); if data.is_empty() { if self.camera.model == "DSLR-A100" { return self.image_a100(file, dummy); } else { // try decoding as SRF return self.image_srf(file, dummy); } } let raw = data[0]; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let mut height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let offset = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); let count = fetch_tiff_tag!(raw, TiffCommonTag::StripByteCounts).force_usize(0); let compression = fetch_tiff_tag!(raw, TiffCommonTag::Compression).force_u32(0); let bps = if let Some(forced_bps) = &self.camera.bps { *forced_bps } else { fetch_tiff_tag!(raw, TiffCommonTag::BitsPerSample).force_usize(0) }; let params = self.get_params(file)?; debug!("Params: {:?}", params); //assert!(params.blacklevel.is_some()); //assert!(params.whitelevel.is_some()); // DSC-R1 is SR2 format and has no whitelevel let mut white = params.whitelevel.map(|x| x[0]); let mut black = params.blacklevel; let src = file.subview_until_eof(offset as u64)?; let mut cpp = 1; let image = match compression { 1 => { if self.camera.model == "DSC-R1" { decode_14be_unpacked(src, width, height, dummy) } else { decode_16le(src, width, height, dummy) } } 7 => { cpp = fetch_tiff_tag!(raw, TiffCommonTag::SamplesPerPixel).force_usize(0); // Starting with A-1, image is compressed in tiles with LJPEG92. // Data is RGGB for bayer readout and YCbCr for reduced resolution files. ArwDecoder::decode_ljpeg(&self.camera, file, raw, dummy)? } 32767 => { if (width * height * bps) != count * 8 { height += 8; ArwDecoder::decode_arw1(src, width, height, dummy) } else { match bps { 8 => { let curve = ArwDecoder::get_curve(raw)?; ArwDecoder::decode_arw2(src, width, height, &curve, dummy) } 12 => { /* Some cameras like the A700 have an uncompressed mode where the output is 12bit and does not require any curve. For these all we need to do is set 12bit black and white points instead of the 14bit ones of the normal compressed 8bit -> 10bit -> 14bit mode. We set these 12bit points by shifting down the 14bit points. It might make sense to have a separate camera mode instead but since the values seem good we don't bother. */ white = white.map(|x| x >> 2); black = black.map(|mut x| { x.iter_mut().for_each(|x| *x >>= 2); x }); decode_12le(src, width, height, dummy) } _ => return Err(RawlerError::DecoderFailed(format!("ARW2: Don't know how to decode images with {} bps", bps))), } } } _ => return Err(RawlerError::DecoderFailed(format!("ARW: Don't know how to decode type {}", compression))), }; let blacklevel = black.map(|black| match cpp { 1 => BlackLevel::new(&black, self.camera.cfa.width, self.camera.cfa.height, cpp), // For YUV data, the blacklevel needs to be multiplicated by 2 3 => BlackLevel::new(&[black[0] * 2, black[0] * 2, black[0] * 2], 1, 1, cpp), _ => panic!("Unsupported cpp == {}", cpp), }); let whitelevel = white.map(|white| WhiteLevel(vec![white as u32; cpp])); let photometric = match cpp { 1 => RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&self.camera)), 3 => RawPhotometricInterpretation::LinearRaw, _ => todo!(), }; let mut img = RawImage::new(self.camera.clone(), image, cpp, params.wb, photometric, blacklevel, whitelevel, dummy); if cpp == 3 { // For debayer images, we assume WB coeffs already applied img.wb_coeffs = [1.0, 1.0, 1.0, f32::NAN]; } if let Some(raw_image_size) = self.get_raw_image_size(raw)? { log::debug!("Found SONYRAWIMAGESIZE tag, using as active_area"); img.active_area = Some(raw_image_size); } else { img.active_area = self.camera.active_area.map(|area| Rect::new_with_borders(Dim2::new(width, height), &area)); } img.crop_area = Rect::from_tiff(raw).or_else(|| self.camera.crop_area.map(|area| Rect::new_with_borders(Dim2::new(width, height), &area))); log::debug!("raw dim: {}x{}", width, height); log::debug!("crop_area: {:?}", img.crop_area); log::debug!("active_area: {:?}", img.active_area); Ok(img) } /// Return the embedded JPEG preview /// Exiftool docs says there is a tag 0x2002 including the image, but this tag /// exists in none of the samples?! Instead, we can use the JPEG thumbnail /// tags which exists for most samples. fn full_image(&self, file: &RawSource, params: &RawDecodeParams) -> Result> { if params.image_index != 0 { return Ok(None); } let root = self.tiff.root_ifd(); if let Some(preview_off) = root.get_entry(ExifTag::JPEGInterchangeFormat) { if let Some(preview_len) = root.get_entry(ExifTag::JPEGInterchangeFormatLength) { let buf = file.subview(preview_off.force_u64(0), preview_len.force_u64(0))?; let img = image::load_from_memory_with_format(buf, image::ImageFormat::Jpeg) .map_err(|err| RawlerError::DecoderFailed(format!("Failed to read JPEG image: {:?}", err)))?; return Ok(Some(img)); } } Ok(None) } fn format_dump(&self) -> crate::analyze::FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let mut exif = Exif::new(self.tiff.root_ifd())?; exif.extend_from_ifd(self.get_exif()?)?; // TODO: is this required? let mdata = RawMetadata::new_with_lens(&self.camera, exif, self.get_lens_description()?.cloned()); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::ARW } } impl<'a> ArwDecoder<'a> { fn get_exif(&self) -> Result<&IFD> { self .tiff .find_first_ifd_with_tag(ExifTag::MakerNotes) .ok_or_else(|| "EXIF IFD not found".into()) } /// Get lens description by analyzing TIFF tags and makernotes fn get_lens_description(&self) -> Result> { // Try tag 0x9416 if let Some(Entry { value: Value::Undefined(params), .. }) = self.makernote.get_entry(ArwMakernoteTag::Tag_9416) { let dechiphered_9416 = sony_tag9cxx_decipher(params); let lens_id = LEu16(&dechiphered_9416, 0x004b); debug!("Lens Id tag: {}", lens_id); let resolver = LensResolver::new() .with_camera(&self.camera) .with_lens_id((lens_id as u32, 0)) .with_mounts(&[SONY_E_MOUNT.into(), SONY_A_MOUNT.into()]); return Ok(resolver.resolve()); } // Try tag 0x9050 if let Some(Entry { value: Value::Undefined(params), .. }) = self.makernote.get_entry(ArwMakernoteTag::Tag_9050) { if params.len() >= 263 + 2 { let dechiphered_9050 = sony_tag9cxx_decipher(params); let lens_id = LEu16(&dechiphered_9050, 263); debug!("Lens Id tag: {}", lens_id); let resolver = LensResolver::new() .with_camera(&self.camera) .with_lens_id((lens_id as u32, 0)) .with_mounts(&[SONY_E_MOUNT.into(), SONY_A_MOUNT.into()]); return Ok(resolver.resolve()); } } // Try tag 0x940C if let Some(Entry { value: Value::Undefined(params), .. }) = self.makernote.get_entry(ArwMakernoteTag::Tag_940C) { let dechiphered_940c = sony_tag9cxx_decipher(params); let lens_id = LEu16(&dechiphered_940c, 9); debug!("Lens Id tag: {}", lens_id); let resolver = LensResolver::new() .with_camera(&self.camera) .with_lens_id((lens_id as u32, 0)) .with_mounts(&[SONY_E_MOUNT.into(), SONY_A_MOUNT.into()]); return Ok(resolver.resolve()); } Ok(None) } fn image_a100(&self, file: &RawSource, dummy: bool) -> Result { // We've caught the elusive A100 in the wild, a transitional format // between the simple sanity of the MRW custom format and the wordly // wonderfullness of the Tiff-based ARW format, let's shoot from the hip let data = self.tiff.find_ifds_with_tag(TiffCommonTag::SubIFDs); if data.is_empty() { return Err(RawlerError::DecoderFailed("ARW: Couldn't find the data IFD!".to_string())); } let raw = data[0]; let width = 3880; let height = 2608; let offset = fetch_tiff_tag!(raw, TiffCommonTag::SubIFDs).force_usize(0); let src = file.subview_until_eof(offset as u64)?; let image = ArwDecoder::decode_arw1(src, width, height, dummy); // Get the WB the MRW way // DNGPrivateTag contains 4 bytes forming a LE u32 offset value. let priv_offset = { let entry = fetch_tiff_tag!(self.tiff, TiffCommonTag::DNGPrivateArea); assert_eq!(entry.value_type(), 0x1); LEu32(entry.get_data(), 0) }; let buf = file.subview_until_eof(priv_offset as u64)?; if BEu32(buf, 0) != 0x4D5249 { // MRI return Err(format!("Invalid DNGPRIVATEDATA tag: 0x{:X}, expected 0x4D5249 ", BEu32(buf, 0)).into()); } let mut currpos: usize = 8; let mut wb_coeffs: [f32; 4] = [1.0, 1.0, 1.0, f32::NAN]; // At most we read 20 bytes from currpos so check we don't step outside that while currpos + 20 < buf.len() { let tag: u32 = BEu32(buf, currpos); let len: usize = LEu32(buf, currpos + 4) as usize; if tag == 0x574247 { // WBG wb_coeffs[0] = LEu16(buf, currpos + 12) as f32; wb_coeffs[1] = LEu16(buf, currpos + 14) as f32; wb_coeffs[2] = LEu16(buf, currpos + 14) as f32; wb_coeffs[3] = LEu16(buf, currpos + 18) as f32; break; } currpos += len + 8; } let cpp = 1; ok_cfa_image(self.camera.clone(), cpp, normalize_wb(wb_coeffs), image, dummy) } fn image_srf(&self, file: &RawSource, dummy: bool) -> Result { let data = self.tiff.find_ifds_with_tag(TiffCommonTag::ImageWidth); if data.is_empty() { return Err(RawlerError::DecoderFailed("ARW: Couldn't find the data IFD!".to_string())); } let raw = data[0]; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let image = if dummy { PixU16::new_uninit(width, height) } else { let buffer = file.as_vec()?; let len = width * height * 2; // Constants taken from dcraw let off: usize = 862144; let key_off: usize = 200896; let head_off: usize = 164600; // Replicate the dcraw contortions to get the "decryption" key let offset = (buffer[key_off] as usize) * 4; let first_key = BEu32(&buffer, key_off + offset); let head = ArwDecoder::sony_decrypt(&buffer, head_off, 40, first_key)?; let second_key = LEu32(&head, 22); // "Decrypt" the whole image buffer let image_data = ArwDecoder::sony_decrypt(&buffer, off, len, second_key)?; decode_16be(&image_data, width, height, dummy) }; let cpp = 1; ok_cfa_image(self.camera.clone(), cpp, [f32::NAN, f32::NAN, f32::NAN, f32::NAN], image, dummy) } pub(crate) fn decode_arw1(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { let mut out = alloc_image!(width, height, dummy); let mut pump = BitPumpMSB::new(buf); let mut sum: i32 = 0; for x in 0..width { let col = width - 1 - x; let mut row = 0; while row <= height { if row == height { row = 1; } let mut len: u32 = 4 - pump.get_bits(2); if len == 3 && pump.get_bits(1) != 0 { len = 0; } else if len == 4 { let zeros = pump.peek_bits(13).leading_zeros() - 19; len += zeros; pump.get_bits(cmp::min(13, zeros + 1)); } let diff: i32 = pump.get_ibits(len); sum += diff; if len > 0 && (diff & (1 << (len - 1))) == 0 { sum -= (1 << len) - 1; } out[row * width + col] = sum as u16; row += 2 } } out } pub(crate) fn decode_arw2(buf: &[u8], width: usize, height: usize, curve: &LookupTable, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let mut pump = BitPumpLSB::new(&buf[(row * width)..]); let mut random = pump.peek_bits(16); for out in out.chunks_exact_mut(32) { // Process 32 pixels at a time in interleaved fashion for j in 0..2 { let max = pump.get_bits(11); let min = pump.get_bits(11); let delta = max - min; // Calculate the size of the data shift needed by how large the delta is // A delta with 11 bits requires a shift of 4, 10 bits of 3, etc let delta_shift: u32 = cmp::max(0, (32 - (delta.leading_zeros() as i32)) - 7) as u32; let imax = pump.get_bits(4) as usize; let imin = pump.get_bits(4) as usize; for i in 0..16 { let val = if i == imax { max } else if i == imin { min } else { cmp::min(0x7ff, (pump.get_bits(7) << delta_shift) + min) }; out[j + (i * 2)] = curve.dither((val << 1) as u16, &mut random); } } } }), ) } /// Some newer cameras like Alpha-1 uses LJPEG compression, but in an awkward way. /// The image is split into 512x512 tiles with cpp = 1, but the LJPEG stream is /// compressed as 256x256 with cpp = 4. So the total of bytes matches, but the dimension /// is wrong. Actually, the LJPEG stream is two lines packed into a single line each /// decompressed line has the bayer pattern: RGGBRGGBRGGB... /// So we need to decompress first, then unpack the bayer pattern from one line /// into two lines. /// For resolution-reduced files (cpp=3), pixels are encoded in YCbCr color space. pub(crate) fn decode_ljpeg(camera: &Camera, file: &RawSource, raw: &IFD, dummy: bool) -> Result { let offsets = raw.get_entry(TiffCommonTag::TileOffsets).ok_or("Unable to find TileOffsets")?; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let twidth = fetch_tiff_tag!(raw, TiffCommonTag::TileWidth).force_usize(0); let tlength = fetch_tiff_tag!(raw, TiffCommonTag::TileLength).force_usize(0); let cpp = fetch_tiff_tag!(raw, TiffCommonTag::SamplesPerPixel).force_usize(0); let coltiles = (width - 1) / twidth + 1; let rowtiles = (height - 1) / tlength + 1; log::debug!("Sony ARW LJPEG raw: width: {}, height: {}, cpp: {}", width, height, cpp); log::debug!("LJPEG tile parameters: width: {}, length: {}, cpp: {}", twidth, tlength, cpp); if coltiles * rowtiles != offsets.count() as usize { return Err(RawlerError::unsupported( camera, format!("ARW LJPEG: trying to decode {} tiles from {} offsets", coltiles * rowtiles, offsets.count()), )); } let buffer = file.as_vec()?; if cpp == 3 { let mut image = decode_threaded_multiline( width * cpp, height, tlength, dummy, &(|strip: &mut [u16], row| { let row = row / tlength; for col in 0..coltiles { log::debug!("Decode tile: row({}), col({})", row, col); let offset = offsets.force_usize(row * coltiles + col); let src = &buffer[offset..]; let decompressor = LjpegDecompressor::new(src).map_err(|err| format!("Creating LJPEG decompressor for ARW LJPEG tile ({row},{col}) failed: {err}"))?; let cpp = 3; let w = 512; let h = 512; let mut data = vec![0; h * w * cpp]; decompressor.decode_sony(&mut data, 0, w * cpp, w * cpp, h, dummy)?; interpolate_yuv(decompressor.super_h(), decompressor.super_v(), w * cpp, h, &mut data); let mut strip = &mut *strip; for line in data.chunks_exact(w * cpp) { let base = col * twidth * cpp; strip[base..base + w * cpp].copy_from_slice(line); // Now move output strip by one row. strip = &mut strip[width * cpp..]; } } Ok(()) }), )?; // Convert YC'bC'r data to RGB. ycbcr_to_rgb(&mut image.data); Ok(image) } else if cpp == 1 { decode_threaded_multiline( width, height, tlength, dummy, &(|strip: &mut [u16], row| { let row = row / tlength; for col in 0..coltiles { let offset = offsets.force_usize(row * coltiles + col); let src = &buffer[offset..]; let decompressor = LjpegDecompressor::new(src)?; let cpp = 4; let w = 256; let h = 256; let mut data = vec![0; h * w * cpp]; decompressor.decode(&mut data, 0, w * cpp, w * cpp, h, dummy)?; let mut strip = &mut *strip; for line in data.chunks_exact(1024) { for (i, chunk) in line.chunks_exact(4).enumerate() { // Unpack chunks of RGGB pixel data into two output lines // so the first line is RGRGRG and the second one is GBGBGB. strip[col * twidth + i * 2 + 0] = chunk[0]; strip[col * twidth + i * 2 + 1] = chunk[1]; strip[width + col * twidth + i * 2 + 0] = chunk[2]; strip[width + col * twidth + i * 2 + 1] = chunk[3]; } // Now move output strip by two rows. strip = &mut strip[width * 2..]; } } Ok(()) }), ) .map_err(RawlerError::DecoderFailed) } else { Err(RawlerError::unsupported( camera, format!("NRW files with LJPEG compression and unsupported cpp: {}", cpp), )) } } fn get_params(&self, file: &RawSource) -> Result { let priv_offset = { let tag = fetch_tiff_tag!(self.tiff, TiffCommonTag::DNGPrivateArea).get_data(); LEu32(tag, 0) }; let priv_tiff = IFD::new(&mut file.reader(), priv_offset, 0, 0, Endian::Little, &[])?; //priv_tiff.dump::(0).iter().for_each(|line| println!("DUMPXX: {}", line)); let sony_offset = fetch_tiff_tag!(priv_tiff, TiffCommonTag::SonyOffset).force_u32(0); let sony_length = fetch_tiff_tag!(priv_tiff, TiffCommonTag::SonyLength).force_usize(0); // This tag is of type UNDEFINED and contains a 32 bit value let sony_key = { let tag = fetch_tiff_tag!(priv_tiff, TiffCommonTag::SonyKey).get_data(); LEu32(tag, 0) }; let buffer = file.as_vec()?; let decrypted_buf = ArwDecoder::sony_decrypt(&buffer, sony_offset as usize, sony_length, sony_key)?; let decrypted_tiff = IFD::new(&mut Cursor::new(decrypted_buf), 0, 0, -(sony_offset as i32), Endian::Little, &[])?; let wb = self.get_wb(&decrypted_tiff)?; let blacklevel = self.get_blacklevel(&decrypted_tiff); let whitelevel = self.get_whitelevel(&decrypted_tiff); Ok(ArwImageParams { wb, blacklevel, whitelevel }) } fn get_blacklevel(&self, sr2: &IFD) -> Option<[u16; 4]> { if let Some(entry) = sr2.get_entry(SR2SubIFD::BlackLevel2) { if entry.count() == 4 { return Some([entry.force_u16(0), entry.force_u16(1), entry.force_u16(2), entry.force_u16(3)]); } else { return Some([entry.force_u16(0), entry.force_u16(0), entry.force_u16(0), entry.force_u16(0)]); } } if let Some(entry) = sr2.get_entry(SR2SubIFD::BlackLevel1) { if entry.count() == 4 { return Some([entry.force_u16(0), entry.force_u16(1), entry.force_u16(2), entry.force_u16(3)]); } else { return Some([entry.force_u16(0), entry.force_u16(0), entry.force_u16(0), entry.force_u16(0)]); } } None } fn get_whitelevel(&self, sr2: &IFD) -> Option<[u16; 4]> { if let Some(entry) = sr2.get_entry(SR2SubIFD::WhiteLevel) { if entry.count() == 4 { return Some([entry.force_u16(0), entry.force_u16(1), entry.force_u16(2), entry.force_u16(3)]); } else { return Some([entry.force_u16(0), entry.force_u16(0), entry.force_u16(0), entry.force_u16(0)]); } } None } fn get_wb(&self, sr2: &IFD) -> Result<[f32; 4]> { let grbg_levels = sr2.get_entry(SR2SubIFD::SonyGRBG); let rggb_levels = sr2.get_entry(SR2SubIFD::SonyRGGB); if let Some(levels) = grbg_levels { Ok(normalize_wb([ levels.force_u32(1) as f32, levels.force_u32(0) as f32, levels.force_u32(3) as f32, levels.force_u32(2) as f32, ])) } else if let Some(levels) = rggb_levels { Ok(normalize_wb([ levels.force_u32(0) as f32, levels.force_u32(1) as f32, levels.force_u32(2) as f32, levels.force_u32(3) as f32, ])) } else { Err(RawlerError::DecoderFailed("ARW: Couldn't find GRGB or RGGB levels".to_string())) } } fn get_curve(raw: &IFD) -> Result { let centry = fetch_tiff_tag!(raw, TiffCommonTag::SonyCurve); let mut curve: [usize; 6] = [0, 0, 0, 0, 0, 4095]; for i in 0..4 { curve[i + 1] = ((centry.force_u32(i) >> 2) & 0xfff) as usize; } Ok(Self::calculate_curve(curve)) } pub(crate) fn calculate_curve(curve: [usize; 6]) -> LookupTable { let mut out = vec![0_u16; curve[5] + 1]; for i in 0..5 { for j in (curve[i] + 1)..(curve[i + 1] + 1) { out[j] = out[j - 1] + (1 << i); } } LookupTable::new(&out) } pub(crate) fn sony_decrypt(buf: &[u8], offset: usize, length: usize, key: u32) -> crate::Result> { if buf.len() < offset + 4 * (length / 4) { return Err(RawlerError::DecoderFailed("sony_decrypt() failed: buffer to short".into())); } let mut pad: [u32; 128] = [0_u32; 128]; let mut mkey = key; // Initialize the decryption pad from the key for p in 0..4 { mkey = mkey.wrapping_mul(48828125).wrapping_add(1); pad[p] = mkey; } pad[3] = (pad[3] << 1) | ((pad[0] ^ pad[2]) >> 31); for p in 4..127 { pad[p] = ((pad[p - 4] ^ pad[p - 2]) << 1) | ((pad[p - 3] ^ pad[p - 1]) >> 31); } for p in 0..127 { pad[p] = u32::from_be(pad[p]); } let mut out = Vec::with_capacity(length + 4); //for i in 0..(length / 4 + 1) { for i in 0..(length / 4) { let p = i + 127; pad[p & 127] = pad[(p + 1) & 127] ^ pad[(p + 1 + 64) & 127]; let output = LEu32(buf, offset + i * 4) ^ pad[p & 127]; out.push(((output >> 0) & 0xff) as u8); out.push(((output >> 8) & 0xff) as u8); out.push(((output >> 16) & 0xff) as u8); out.push(((output >> 24) & 0xff) as u8); } Ok(out) } fn get_raw_image_size(&self, raw_ifd: &IFD) -> Result> { if let Some(entry) = raw_ifd.get_entry(ExifTag::SonyRawImageSize) { Ok(Some(Rect::new(Point::default(), Dim2::new(entry.force_usize(0), entry.force_usize(1))))) } else { Ok(None) } } } fn normalize_wb(raw_wb: [f32; 4]) -> [f32; 4] { debug!("ARW raw wb: {:?}", raw_wb); // We never have more then RGB colors so far (no RGBE etc.) // So we combine G1 and G2 to get RGB wb. let div = raw_wb[1]; // G1 should be 1024 and we use this as divisor let mut norm = raw_wb; norm.iter_mut().for_each(|v| { if v.is_normal() { *v /= div } }); [norm[0], (norm[1] + norm[2]) / 2.0, norm[3], f32::NAN] } crate::tags::tiff_tag_enum!(ArwMakernoteTag); /// Specific Makernotes tags. /// These are only related to the Makernote IFD. #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] #[allow(non_camel_case_types)] pub enum ArwMakernoteTag { CameraInfo = 0x0010, Tag_940C = 0x940C, Tag_9050 = 0x9050, Tag_9405 = 0x9405, Tag_9416 = 0x9416, // replaces 0x9405 for the Sony ILCE-7SM3, from July 2020 } /// Decipher/encipher Sony tag 0x2010, 0x900b, 0x9050 and 0x940x data /// Extracted from exiftool, comment from PH: /// This is a simple substitution cipher, so use a hardcoded translation table for speed. /// The formula is: $c = ($b*$b*$b) % 249, where $c is the enciphered data byte /// note that bytes with values 249-255 are not translated, and 0-1, 82-84, /// 165-167 and 248 have the same enciphered value) const fn sony_tag9cxx_decipher_table() -> [u8; 256] { let mut tbl = [0; 256]; let mut i = 0; loop { if i >= 249 { tbl[i] = i as u8; } else { tbl[i * i * i % 249] = i as u8; } i += 1; if i >= tbl.len() { break; } } tbl } const SONY_TAG_940X_DECIPHER_TABLE: [u8; 256] = sony_tag9cxx_decipher_table(); fn sony_tag9cxx_decipher(data: &[u8]) -> Vec { let mut buf = Vec::from(data); buf.iter_mut().for_each(|v| *v = SONY_TAG_940X_DECIPHER_TABLE[*v as usize]); buf } #[derive(Debug)] struct ArwImageParams { wb: [f32; 4], blacklevel: Option<[u16; 4]>, whitelevel: Option<[u16; 4]>, } crate::tags::tiff_tag_enum!(SR2SubIFD); /// Specific Canon CR2 Makernotes tags. /// These are only related to the Makernote IFD. #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] #[allow(non_camel_case_types)] pub enum SR2SubIFD { SonyGRBG = 0x7303, SonyRGGB = 0x7313, BlackLevel1 = 0x7300, BlackLevel2 = 0x7310, WhiteLevel = 0x787f, } rawler-0.7.1/src/decoders/camera.rs000064400000000000000000000231571046102023000153120ustar 00000000000000use toml::Value; use crate::CFA; use crate::cfa::PlaneColor; use crate::imgop::xyz::FlatColorMatrix; use crate::imgop::xyz::Illuminant; use std::collections::HashMap; use super::BlackLevel; use super::WhiteLevel; /// Contains sanitized information about the raw image's properties #[derive(Debug, Clone, Default)] pub struct Camera { pub make: String, pub model: String, pub mode: String, pub clean_make: String, pub clean_model: String, pub remark: Option, pub filesize: usize, pub raw_width: usize, pub raw_height: usize, //pub orientation: Orientation, pub whitelevel: Option>, pub blacklevel: Option>, pub blackareah: Option<(usize, usize)>, pub blackareav: Option<(usize, usize)>, pub xyz_to_cam: [[f32; 3]; 4], pub color_matrix: HashMap, pub cfa: CFA, pub plane_color: PlaneColor, // Active area relative to sensor size pub active_area: Option<[usize; 4]>, // Recommended area relative to sensor size pub crop_area: Option<[usize; 4]>, // Hint/Replacement for EXIF BITDEPTH info pub bps: Option, // The BPS of the output after decoding pub real_bps: usize, pub highres_width: usize, pub default_scale: DefaultScale, pub best_quality_scale: BestQualityScale, pub hints: Vec, pub params: HashMap, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct DefaultScale(pub [[u32; 2]; 2]); impl Default for DefaultScale { fn default() -> Self { Self([[1, 1], [1, 1]]) } } #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct BestQualityScale(pub [u32; 2]); impl Default for BestQualityScale { fn default() -> Self { Self([1, 1]) } } impl Camera { pub fn find_hint(&self, hint: &str) -> bool { self.hints.contains(&hint.to_string()) } pub fn param_usize(&self, name: &str) -> Option { self.params.get(name).and_then(|p| p.as_integer()).map(|i| i as usize) } pub fn param_i32(&self, name: &str) -> Option { self.params.get(name).and_then(|p| p.as_integer()).map(|i| i as i32) } pub fn param_str(&self, name: &str) -> Option<&str> { self.params.get(name).and_then(|p| p.as_str()) } pub fn make_blacklevel(&self, cpp: usize) -> Option { self.blacklevel.as_ref().map(|x| { if x.len() == 1 { BlackLevel::new(&vec![x[0]; cpp], 1, 1, cpp) } else if x.len() == self.cfa.width * self.cfa.height * cpp { BlackLevel::new(x, self.cfa.width, self.cfa.height, cpp) } else { panic!("Invalid blacklevel data") } }) } pub fn make_whitelevel(&self, cpp: usize) -> Option { self.whitelevel.as_ref().map(|x| { if x.len() == 1 { WhiteLevel(vec![x[0] as u32; cpp]) } else if x.len() == cpp { WhiteLevel(x.clone()) } else { panic!("Invalid whitelevel data") } }) } pub fn update_from_toml(&mut self, ct: &toml::value::Table) { for (name, val) in ct { match name.as_ref() { n @ "make" => { self.make = val.as_str().unwrap_or_else(|| panic!("{} must be a string", n)).to_string(); } n @ "model" => { self.model = val.as_str().unwrap_or_else(|| panic!("{} must be a string", n)).to_string(); } n @ "mode" => { self.mode = val.as_str().unwrap_or_else(|| panic!("{} must be a string", n)).to_string(); } n @ "clean_make" => { self.clean_make = val.as_str().unwrap_or_else(|| panic!("{} must be a string", n)).to_string(); } n @ "clean_model" => { self.clean_model = val.as_str().unwrap_or_else(|| panic!("{} must be a string", n)).to_string(); } n @ "remark" => { self.remark = Some(val.as_str().unwrap_or_else(|| panic!("{} must be a string", n)).to_string()); } n @ "whitepoint" => { let white = val.as_integer().unwrap_or_else(|| panic!("{} must be an integer", n)) as u32; self.whitelevel = Some(vec![white]); } n @ "blackpoint" => { let black = val.as_integer().unwrap_or_else(|| panic!("{} must be an integer", n)) as u32; self.blacklevel = Some(vec![black]); } n @ "blackareah" => { let vals = val.as_array().unwrap_or_else(|| panic!("{} must be an array", n)); self.blackareah = Some((vals[0].as_integer().unwrap() as usize, vals[1].as_integer().unwrap() as usize)); } n @ "blackareav" => { let vals = val.as_array().unwrap_or_else(|| panic!("{} must be an array", n)); self.blackareav = Some((vals[0].as_integer().unwrap() as usize, vals[1].as_integer().unwrap() as usize)); } "color_matrix" => { if let Some(color_matrix) = val.as_table() { for (illu_str, matrix) in color_matrix.into_iter() { let illu = Illuminant::new_from_str(illu_str).unwrap(); let xyz_to_cam = matrix .as_array() .expect("color matrix must be array") .iter() .map(|a| a.as_float().expect("color matrix values must be float") as f32) .collect(); self.color_matrix.insert(illu, xyz_to_cam); } } else { eprintln!("Invalid matrix spec for {}", self.clean_model); } assert!(!self.color_matrix.is_empty()); } n @ "active_area" => { let crop_vals = val.as_array().unwrap_or_else(|| panic!("{} must be an array", n)); let mut crop = [0, 0, 0, 0]; for (i, val) in crop_vals.iter().enumerate() { crop[i] = val.as_integer().unwrap() as usize; } self.active_area = Some(crop); } n @ "crop_area" => { let crop_vals = val.as_array().unwrap_or_else(|| panic!("{} must be an array", n)); let mut crop = [0, 0, 0, 0]; for (i, val) in crop_vals.iter().enumerate() { crop[i] = val.as_integer().unwrap() as usize; } self.crop_area = Some(crop); } n @ "color_pattern" => { self.cfa = CFA::new(val.as_str().unwrap_or_else(|| panic!("{} must be a string", n))); } n @ "plane_color" => { self.plane_color = PlaneColor::new(val.as_str().unwrap_or_else(|| panic!("{} must be a string", n))); } n @ "bps" => { self.bps = Some(val.as_integer().unwrap_or_else(|| panic!("{} must be an integer", n)) as usize); } n @ "real_bps" => { self.real_bps = val.as_integer().unwrap_or_else(|| panic!("{} must be an integer", n)) as usize; } n @ "filesize" => { self.filesize = val.as_integer().unwrap_or_else(|| panic!("{} must be an integer", n)) as usize; } n @ "raw_width" => { self.raw_width = val.as_integer().unwrap_or_else(|| panic!("{} must be an integer", n)) as usize; } n @ "raw_height" => { self.raw_height = val.as_integer().unwrap_or_else(|| panic!("{} must be an integer", n)) as usize; } n @ "highres_width" => { self.highres_width = val.as_integer().unwrap_or_else(|| panic!("{} must be an integer", n)) as usize; } n @ "default_scale" => { let scale_vals = val.as_array().unwrap_or_else(|| panic!("{} must be an array", n)); let scale_h = scale_vals[0].as_array().expect("must be array"); let scale_v = scale_vals[1].as_array().expect("must be array"); let scale = [ [ scale_h[0].as_integer().expect("must be integer") as u32, scale_h[1].as_integer().expect("must be integer") as u32, ], [ scale_v[0].as_integer().expect("must be integer") as u32, scale_v[1].as_integer().expect("must be integer") as u32, ], ]; self.default_scale = DefaultScale(scale); } n @ "best_quality_scale" => { let scale_vals = val.as_array().unwrap_or_else(|| panic!("{} must be an array", n)); self.best_quality_scale = BestQualityScale([ scale_vals[0].as_integer().expect("must be integer") as u32, scale_vals[1].as_integer().expect("must be integer") as u32, ]); } n @ "hints" => { self.hints = Vec::new(); for hint in val.as_array().unwrap_or_else(|| panic!("{} must be an array", n)) { self.hints.push(hint.as_str().expect("hints must be a string").to_string()); } } n @ "params" => { for (name, val) in val.as_table().unwrap_or_else(|| panic!("{} must be a table", n)) { self.params.insert(name.clone(), val.clone()); } } "model_aliases" => {} "modes" => {} // ignore key => { panic!("Unknown key: {}", key); } } } } pub fn new() -> Camera { Camera { make: "".to_string(), model: "".to_string(), mode: "".to_string(), clean_make: "".to_string(), clean_model: "".to_string(), remark: None, filesize: 0, raw_width: 0, raw_height: 0, whitelevel: None, blacklevel: None, blackareah: None, blackareav: None, xyz_to_cam: [[0.0; 3]; 4], color_matrix: HashMap::new(), cfa: CFA::new(""), plane_color: PlaneColor::default(), active_area: None, crop_area: None, bps: None, real_bps: 16, highres_width: usize::MAX, default_scale: DefaultScale::default(), best_quality_scale: BestQualityScale::default(), hints: Vec::new(), params: HashMap::new(), //orientation: Orientation::Unknown, } } } rawler-0.7.1/src/decoders/cr2/colordata.rs000064400000000000000000000130261046102023000165120ustar 00000000000000use crate::{ RawlerError, Result, formats::tiff::{Entry, Value}, }; #[derive(Debug, Clone)] #[allow(dead_code)] pub(crate) struct ColorData { pub(crate) version: i16, pub(crate) wb: [f32; 4], pub(crate) blacklevel: Option<[u16; 4]>, pub(crate) normal_whitelevel: Option, pub(crate) specular_whitelevel: Option, } impl ColorData { fn new(data: &[u16], version: i16, wb_off: usize, black_off: Option, norm_white_off: Option, specular_white_off: Option) -> Self { log::debug!("Found Canon COLORDATA version: {}, data len: {}", version, data.len()); let wb = [data[wb_off] as f32, data[wb_off + 1] as f32, data[wb_off + 2] as f32, data[wb_off + 3] as f32]; let blacklevel = black_off.map(|off| [data[off], data[off + 1], data[off + 2], data[off + 3]]); let normal_whitelevel = norm_white_off.map(|off| data[off]); let specular_whitelevel = specular_white_off.map(|off| data[off]); Self { version, wb, blacklevel, normal_whitelevel, specular_whitelevel, } } } pub(crate) fn parse_colordata(colordata: &Entry) -> Result { match &colordata.value { Value::Undefined(undef) => { let transmuted: Vec = undef.chunks(2).map(|v| ((v[1] as u16) << 8) | (v[0] as u16)).collect(); let data = &transmuted; let version: i16 = data[0] as i16; Ok(match version { // -4 (M100/M5/M6) -4 => ColorData::new(data, version, 0x47, Some(0x14d), Some(0x0569), Some(0x056a)), // -3 (M10/M3) -3 => ColorData::new(data, version, 0x47, Some(0x108), None, None), _ => return Err(format!("Unknown2 COLORDATA version: {}", data[0]).into()), }) /* Ok(match data.len() { // 20D and 350D 582 => ColorData::new(&data, version, 0x19, None, None, None), // 1DmkII and 1DSmkII 653 => ColorData::new(&data, version, 0x22, None, None, None), // 1DmkIIN, 5D, 30D, 400D 796 => ColorData::new(&data, version, 0x3f, Some(0xc4), None, None), _ => panic!("COLORDATA count of {} is unknown", data.len()) }) */ } Value::Short(data) => { match data.len() { // 20D and 350D 582 => return Ok(ColorData::new(data, 0, 0x19, None, None, None)), // 1DmkII and 1DSmkII 653 => return Ok(ColorData::new(data, 0, 0x22, None, None, None)), // 1DmkIIN, 5D, 30D, 400D 796 => return Ok(ColorData::new(data, 0, 0x3f, Some(0xc4), None, None)), _ => log::debug!("COLORDATA count of {} is unknown, continue with version matching", data.len()), } let version: i16 = data[0] as i16; /* for (i, item) in data.iter().enumerate() { if *item > 127 { eprintln!("0x{:>4x}: {}", i, item); } } */ Ok(match version { // 1 = (1DmkIIN/5D/30D/400D) 1 => ColorData::new(data, version, 63, Some(196), None, None), // 2 (1DmkIII) // 3 (40D) 2 | 3 => ColorData::new(data, version, 0x3f, Some(0xe7), None, None), // 4 (1DSmkIII) // 5 (450D/1000D) 4 | 5 => ColorData::new(data, version, 0x3f, Some(0x2b4), Some(0x2b8), Some(0x2b9)), // 6 (50D/5DmkII) // 7 (500D/550D/7D/1DmkIV) 6 | 7 => ColorData::new(data, version, 0x3f, Some(0x2cb), Some(0x2cf), Some(0x2d0)), // 9 (60D/1100D) 9 => ColorData::new(data, version, 0x3f, Some(0x2cf), Some(0x2d3), Some(0x2d4)), // -4 (M100/M5/M6) -4 => ColorData::new(data, version, 0x47, Some(0x14d), Some(0x0569), Some(0x056a)), // -3 (M10/M3) -3 => ColorData::new(data, version, 0x47, Some(0x108), None, None), // 10 (600D/1200D) // 10 (1DX/5DmkIII/6D/70D/100D/650D/700D/M/M2) 10 => { if data.len() == 1273 || data.len() == 1275 { ColorData::new(data, version, 0x3f, Some(0x1df), Some(0x1e3), Some(0x1e4)) } else { ColorData::new(data, version, 0x3f, Some(0x1f8), Some(0x1fc), Some(0x1fd)) } } // 11 (7DmkII/750D/760D/8000D) 11 => ColorData::new(data, version, 0x3f, Some(0x2d8), Some(0x2dc), Some(0x2dd)), // 12 (1DXmkII/5DS/5DSR) 12 => ColorData::new(data, version, 0x3f, Some(0x30a), Some(0x30e), Some(0x30f)), // 13 (80D/5DmkIV) 13 => ColorData::new(data, version, 0x3f, Some(0x30a), Some(0x30e), Some(0x30f)), // 14 (1300D/2000D/4000D) 14 => ColorData::new(data, version, 0x3f, Some(0x22c), Some(0x230), Some(0x231)), // 15 (6DmkII/77D/200D/800D,9000D) 15 => ColorData::new(data, version, 0x3f, Some(0x30a), Some(0x30e), Some(0x30f)), // 16 (M50) // 17 (EOS R) // 18 (EOS RP/250D) // 19 (90D/850D/M6mkII/M200) 16 | 17 | 18 | 19 => ColorData::new(data, version, 0x47, Some(0x149), Some(0x31c), Some(0x31d)), // 32 (1DXmkIII) // 33 (R5/R6) 32 | 33 => ColorData::new(data, version, 0x55, Some(0x157), Some(0x32a), Some(0x32b)), // 34 (R3) 34 => ColorData::new(data, version, 0x69, Some(0x16b), Some(0x280), Some(0x281)), // 48 (R7/R10) 48 => ColorData::new(data, version, 0x69, Some(0x16b), Some(0x281), Some(0x282)), // 64 (R5MK2) 64 => ColorData::new(data, version, 0x69, Some(0x17f), Some(0x294), Some(0x295)), _ => return Err(format!("Unknown COLORDATA version: {}", data[0]).into()), }) } _ => Err(RawlerError::DecoderFailed(format!( "Invalid COLORDATA tag: type {}", colordata.value_type_name() ))), } } rawler-0.7.1/src/decoders/cr2.rs000064400000000000000000000763331046102023000145540ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher use core::panic; use image::DynamicImage; use image::ImageBuffer; use image::Rgb; use log::debug; use log::info; use rayon::iter::ParallelIterator; use rayon::slice::ParallelSliceMut; use serde::Deserialize; use serde::Serialize; use std::convert::TryFrom; use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::alloc_image_plain; use crate::analyze::FormatDump; use crate::bits::LookupTable; use crate::bits::clampbits; use crate::decompressors::ljpeg::*; use crate::exif::Exif; use crate::formats::tiff::Entry; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::IFD; use crate::formats::tiff::Rational; use crate::formats::tiff::Value; use crate::formats::tiff::reader::TiffReader; use crate::imgop::Dim2; use crate::imgop::Point; use crate::imgop::Rect; use crate::lens::LensDescription; use crate::lens::LensResolver; use crate::rawimage::CFAConfig; use crate::rawimage::RawPhotometricInterpretation; use crate::rawsource::RawSource; use crate::tags::ExifTag; use crate::tags::TiffCommonTag; use super::BlackLevel; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use super::Result; use super::WhiteLevel; mod colordata; pub(crate) use colordata::parse_colordata; const CANON_EF_MOUNT: &str = "ef-mount"; const CANON_CN_MOUNT: &str = "cn-mount"; /// CR2 Decoder pub struct Cr2Decoder<'a> { #[allow(dead_code)] rawloader: &'a RawLoader, tiff: GenericTiffReader, exif: IFD, makernote: Option, #[allow(dead_code)] mode: Cr2Mode, xpacket: Option>, camera: Camera, model_id: Option, } /// CR2 format encapsulation for analyzer #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Cr2Format { tiff: GenericTiffReader, } impl<'a> Decoder for Cr2Decoder<'a> { fn format_dump(&self) -> FormatDump { FormatDump::Cr2(Cr2Format { tiff: self.tiff.clone() }) } fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { /* for (i, ifd) in self.tiff.chains().iter().enumerate() { eprintln!("IFD {}", i); for line in ifd_dump::(ifd, 10) { eprintln!("{}", line); } } */ let camera = &self.camera; let (raw, offset) = { if let Some(raw) = self.tiff.find_first_ifd(TiffCommonTag::Cr2Id) { (raw, fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0)) } else if let Some(raw) = self.tiff.find_first_ifd(TiffCommonTag::CFAPattern) { (raw, fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0)) } else if let Some(off) = self.makernote.as_ref().and_then(|md| md.get_entry(TiffCommonTag::Cr2OldOffset)) { // Old Canon TIF files contains the offset in makernote tags (self.tiff.root_ifd(), off.value.force_usize(0)) } else { return Err(RawlerError::DecoderFailed("CR2: Couldn't find raw info".to_string())); } }; // We don't have an excact length, so read until end. let src = file.subview_until_eof(offset as u64)?; let (cpp, image) = { let decompressor = LjpegDecompressor::new(src)?; let ljpegwidth = decompressor.width(); let mut width = ljpegwidth; let mut height = decompressor.height(); let cpp = if decompressor.super_h() == 2 { 3 } else { 1 }; debug!("CR2 ljpeg components: {}", decompressor.components()); debug!("CR2 final cpp: {}", cpp); debug!("CR2 dimension: {},{}", width / cpp, height); let mut ljpegout = alloc_image_plain!(width, height, dummy); if !dummy { decompressor.decode(ljpegout.pixels_mut(), 0, width, width, height, dummy)?; } //crate::devtools::dump_image_u16(&ljpegout, width, height, "/tmp/cr2_before_striped.pnm"); // Linearize the output (applies only to D2000 as far as I can tell) if !dummy && camera.find_hint("linearization") { let table = { let linearization = fetch_tiff_tag!(raw, TiffCommonTag::GrayResponse); let mut t = [0_u16; 4096]; for i in 0..t.len() { t[i] = linearization.force_u16(i); } LookupTable::new(&t) }; let mut random = ljpegout[0] as u32; for p in ljpegout.pixels_mut().iter_mut() { *p = table.dither(*p, &mut random); } } if cpp == 3 { if raw.has_entry(TiffCommonTag::ImageWidth) { width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0) * cpp; height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); } else if width / cpp < height { let temp = width / cpp; width = height * cpp; height = temp; } } else if camera.find_hint("double_line") { width /= 2; height *= 2; } debug!("CR2 dimension2: {},{}", width / cpp, height); // Take each of the vertical fields and put them into the right location // FIXME: Doing this at the decode would reduce about 5% in runtime but I haven't // been able to do it without hairy code if let Some(canoncol) = raw.get_entry(TiffCommonTag::Cr2StripeWidths) { debug!("Found Cr2StripeWidths tag: {:?}", canoncol.value); if canoncol.value.force_usize(0) == 0 { if cpp == 3 { self.convert_to_rgb(file, camera, &decompressor, width, height, ljpegout.pixels_mut(), dummy)?; //width /= 3; } ljpegout.update_dimension(Dim2::new(width, height)); (cpp, ljpegout) /* if camera.find_hint("double_line") { (width, height, cpp, PixU16::new_with(ljpegout.into_inner(), width, height)) } else { (width, height, cpp, ljpegout) } */ } else { let mut out = alloc_image_plain!(width, height, dummy); if !dummy { let mut fieldwidths = Vec::new(); debug_assert!(canoncol.value.force_usize(0) > 0); debug_assert!(canoncol.value.force_usize(1) > 0); debug_assert!(canoncol.value.force_usize(2) > 0); for _ in 0..canoncol.value.force_usize(0) { fieldwidths.push(canoncol.value.force_usize(1)); } fieldwidths.push(canoncol.value.force_usize(2)); if decompressor.super_v() == 2 { debug!("CR2 v=2 decoder used, h={}", decompressor.super_h()); // We've decoded 2 lines at a time so we also need to copy two strips at a time let nfields = fieldwidths.len(); let fieldwidth = fieldwidths[0]; let mut fieldstart = 0; let mut inpos = 0; for _ in 0..nfields { for row in (0..height).step_by(2) { for col in (0..fieldwidth).step_by(3) { let outpos = row * width + fieldstart + col; out[outpos..outpos + 3].copy_from_slice(&ljpegout[inpos..inpos + 3]); let outpos = (row + 1) * width + fieldstart + col; let inpos2 = inpos + ljpegwidth; out[outpos..outpos + 3].copy_from_slice(&ljpegout[inpos2..inpos2 + 3]); inpos += 3; if inpos % ljpegwidth == 0 { // we've used a full input line and we're reading 2 by 2 so skip one inpos += ljpegwidth; } } } fieldstart += fieldwidth; } } else { let sh = decompressor.super_h(); debug!("CR2 v=1 decoder used, super_h: {}", sh); let mut fieldstart = 0; let mut fieldpos = 0; for fieldwidth in fieldwidths { // fix the inconsistent slice width in sRaw mode, ask Canon. let fieldwidth = fieldwidth / sh * cpp; // The output for full height of a vertical stripe is // composed by the lines of all input stripes N: // outb(line0) = slice[0](line[0]) // outb(line1) = slice[1](line[0]) // outb(line2) = slice[N-1](line[0]) for row in 0..height { let outpos = row * width + fieldstart; let inpos = fieldpos + row * fieldwidth; let outb = &mut out[outpos..outpos + fieldwidth]; let inb = &ljpegout[inpos..inpos + fieldwidth]; outb.copy_from_slice(inb); } fieldstart += fieldwidth; fieldpos += fieldwidth * height; } } } if cpp == 3 { self.convert_to_rgb(file, camera, &decompressor, width, height, out.pixels_mut(), dummy)?; //width /= 3; } (cpp, out) //(width, height, cpp, out) } } else { ljpegout.update_dimension(Dim2::new(width, height)); (cpp, ljpegout) // (width, height, cpp, PixU16::new_with(ljpegout.into_inner(), width, height)) } }; let wb = self.get_wb(file, camera)?; debug!("CR2 WB: {:?}", wb); //assert_eq!(image.width, width * cpp); let blacklevel = self.get_blacklevel(camera, cpp)?; let whitelevel = self.get_whitelevel(cpp)?; let photometric = match cpp { 1 => RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&self.camera)), 3 => RawPhotometricInterpretation::LinearRaw, _ => todo!(), }; let mut img = RawImage::new(camera.clone(), image, cpp, wb, photometric, blacklevel, whitelevel, dummy); if let Some(file_crop) = self.get_sensor_area()? { assert!( img.crop_area.is_none(), "Camera {} has embedded crop params, remove crop from config file!", self.camera.clean_make ); img.crop_area = Some(file_crop); } else { //panic!("Camera {} has no embedded crops, but all CR2 should contain them?!", self.camera.clean_make); // 1D and D2000C has no crops! } if cpp == 3 { // We have a sRAW or mRAW: the active_area from camera config is invalid now! // We just apply the crop_area that comes from metadata, which is correct. img.active_area = img.crop_area; } debug!("Blacklevel: {:?}", img.blacklevel); debug!("Whitelevel: {:?}", img.whitelevel); debug!("Black areas: {:?}", img.blackareas); debug!("Active area: {:?}", img.active_area); debug!("Crop area: {:?}", img.crop_area); Ok(img) } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; let mdata = RawMetadata::new_with_lens(&self.camera, exif, self.get_lens_description()?.cloned()); Ok(mdata) } fn xpacket(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result>> { Ok(self.xpacket.clone()) } fn full_image(&self, file: &RawSource, params: &RawDecodeParams) -> Result> { if params.image_index != 0 { return Ok(None); } // For CR2, there is a full resolution image in IFD0. // This is compressed with old-JPEG compression (Compression = 6) let root_ifd = &self.tiff.root_ifd(); let buf = root_ifd .singlestrip_data_rawsource(file) .map_err(|e| RawlerError::DecoderFailed(format!("Failed to get strip data: {}", e)))?; let compression = root_ifd.get_entry(TiffCommonTag::Compression).ok_or("Missing tag")?.force_usize(0); let width = fetch_tiff_tag!(root_ifd, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(root_ifd, TiffCommonTag::ImageLength).force_usize(0); if compression == 1 { Ok(Some(DynamicImage::ImageRgb8( ImageBuffer::, Vec>::from_raw(width as u32, height as u32, buf.to_vec()) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to read uncompressed image")))?, ))) } else { let img = image::load_from_memory_with_format(buf, image::ImageFormat::Jpeg) .map_err(|err| RawlerError::DecoderFailed(format!("Failed to read JPEG image: {:?}", err)))?; Ok(Some(img)) } } fn format_hint(&self) -> FormatHint { FormatHint::CR2 } } #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] enum Cr2Mode { Raw, Sraw1, Sraw2, } impl<'a> Cr2Decoder<'a> { fn get_mode(makernote: &Option) -> Result { if let Some(settings) = makernote.as_ref().and_then(|mn| mn.get_entry(Cr2MakernoteTag::CameraSettings)) { match settings.get_u16(46) { Ok(Some(0)) => Ok(Cr2Mode::Raw), Ok(Some(1)) => Ok(Cr2Mode::Sraw1), Ok(Some(2)) => Ok(Cr2Mode::Sraw2), Ok(None) => Ok(Cr2Mode::Raw), Ok(Some(v)) => Err(RawlerError::DecoderFailed(format!("Unknown sraw quality value found: {}", v))), Err(_) => Err(RawlerError::DecoderFailed("Unknown sraw quality value".to_string())), } } else { Ok(Cr2Mode::Raw) } } /// Construct new CR2 decoder /// This parses the RawFile again to include specific sub IFDs. pub fn new(file: &RawSource, _tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { debug!("CR2 decoder choosen"); // Parse the TIFF again, with custom settings let tiff = GenericTiffReader::new(&mut file.reader(), 0, 0, None, &[33424])?; let exif = Self::new_exif_ifd(file, &tiff, rawloader)?; let makernote = Self::new_makernote(file, &tiff, &exif, rawloader)?; let mode = Self::get_mode(&makernote)?; debug!("sRaw quality: {:?}", mode); let mode_str = match mode { Cr2Mode::Raw => "", Cr2Mode::Sraw1 => "sRaw1", Cr2Mode::Sraw2 => "sRaw2", }; let camera = rawloader.check_supported_with_mode(tiff.root_ifd(), mode_str)?; let xpacket = Self::read_xpacket(file, &tiff, rawloader)?; let model_id = makernote .as_ref() .and_then(|mn| mn.get_entry(Cr2MakernoteTag::ModelId).and_then(|v| v.get_u32(0).transpose())) .transpose() .map_err(|_| RawlerError::DecoderFailed("CR2: invalid model id".to_string()))?; Ok(Cr2Decoder { tiff, rawloader, exif, makernote, mode, xpacket, camera, model_id, }) } /// Search for EXIF IFD, if not found, fallback to root IFD. /// This is useful for EOS D2000 where EXIF tags are located in the root. fn new_exif_ifd(_file: &RawSource, tiff: &GenericTiffReader, _rawloader: &RawLoader) -> Result { if let Some(exif_ifd) = tiff .root_ifd() .sub_ifds() .get(&TiffCommonTag::ExifIFDPointer.into()) .and_then(|subs| subs.get(0)) { Ok(exif_ifd.clone()) } else { debug!("No EXIF IFD found, fallback to root IFD"); Ok(tiff.root_ifd().clone()) } /* if let Some(exif_ifd) = tiff.root_ifd().get_ifd(LegacyTiffRootTag::ExifIFDPointer, &mut file.reader())? { return Ok(exif_ifd); } else { return Ok(tiff.root_ifd().clone()); } */ } fn get_focal_len(&self) -> Result> { if let Some(Entry { value: Value::Short(focal), .. }) = self.makernote.as_ref().and_then(|mn| mn.get_entry(Cr2MakernoteTag::FocalLen)) { return Ok(focal.get(1).map(|v| Rational::new(*v as u32, 1))); } Ok(None) } /// Get lens description by analyzing TIFF tags and makernotes fn get_lens_description(&self) -> Result> { let exif_lens_name = if let Some(Entry { value: Value::Ascii(lens_id), .. }) = self.exif.get_entry(ExifTag::LensModel) { lens_id.strings().get(0) } else { None }; match self.makernote.as_ref().and_then(|mn| mn.get_entry(Cr2MakernoteTag::CameraSettings)) { Some(Entry { value: Value::Short(settings), .. }) => { let lens_info = settings[22]; debug!("Lens Info tag: {}", lens_info); let resolver = LensResolver::new() .with_lens_keyname(exif_lens_name) .with_camera(&self.camera) // must follow with_lens_keyname() as it my override key .with_lens_id((lens_info as u32, 0)) .with_focal_len(self.get_focal_len()?) .with_mounts(&[CANON_CN_MOUNT.into(), CANON_EF_MOUNT.into()]); return Ok(resolver.resolve()); } _ => { log::warn!("Camera settings in makernote not found, no lens data available"); } } Ok(None) } /// Parse the Canon makernote IFD fn new_makernote(file: &RawSource, tiff: &GenericTiffReader, exif_ifd: &IFD, _rawloader: &RawLoader) -> Result> { if let Some(entry) = exif_ifd.get_entry(TiffCommonTag::Makernote) { let offset = entry.offset().expect("Makernote internal offset is not present but should be"); let makernote = tiff.parse_ifd(&mut file.reader(), offset as u32, 0, 0, exif_ifd.endian, &[])?; return Ok(Some(makernote)); } info!("No makernote tag found"); Ok(None) } /// Read XMP data from TIFF entry /// This is useful as it stores the image rating (if present). fn read_xpacket(_file: &RawSource, tiff: &GenericTiffReader, _rawloader: &RawLoader) -> Result>> { if let Some(entry) = tiff.root_ifd().get_entry(TiffCommonTag::Xmp) { if let Entry { value: Value::Byte(xmp), .. } = entry { Ok(Some(xmp.clone())) } else { Err("Image has XMP data but invalid tag type!".into()) } } else { Ok(None) } } /* pub fn new_makernote(buf: &'a[u8], offset: usize, base_offset: usize, chain_level: isize, e: Endian) -> Result> { let mut off = 0; let data = &buf[offset..]; let mut endian = e; // Some have MM or II to indicate endianness - read that if data[off..off+2] == b"II"[..] { off +=2; endian = Endian::Little; } if data[off..off+2] == b"MM"[..] { off +=2; endian = Endian::Big; } Ok(LegacyTiffIFD::new(buf, offset+off, base_offset, 0, chain_level+1, endian, &vec![])?) } */ /// Build firmware value from string fn get_firmware(&self) -> Result> { Ok( match self .makernote .as_ref() .and_then(|mn| mn.get_entry(Cr2MakernoteTag::FirmareVer).and_then(|v| v.as_string())) { Some(fw) => { let str: String = fw.chars().filter(|c| c.is_ascii_digit() || c == &'.').collect(); let v: Vec = str.split('.').map(|v| v.parse().expect("Only digits here")).collect(); Some(v.iter().rev().enumerate().map(|(i, v)| 10_u32.pow(i as u32 * 3) * *v as u32).sum()) } None => None, }, ) } /// Get the SRAW white balance coefficents from COLORDATA tag /// The offsets are always at offset 78. /// These coefficents are used for SRAW YUV2RGB conversion. fn get_sraw_wb(&self, rawfile: &RawSource, _cam: &Camera) -> Result<[f32; 4]> { if let Some(levels) = self .makernote .as_ref() .and_then(|mn| mn.get_entry_raw(Cr2MakernoteTag::ColorData, &mut rawfile.reader()).transpose()) .transpose()? { let offset = 78; return Ok([ levels.get_force_u16(offset) as f32, (levels.get_force_u16(offset + 1) as f32 + levels.get_force_u16(offset + 2) as f32) / 2.0, levels.get_force_u16(offset + 3) as f32, f32::NAN, ]); } Ok([f32::NAN, f32::NAN, f32::NAN, f32::NAN]) } /// Get the white balance coefficents from COLORDATA tag /// The offsets are different, so we take the offset from camera params. fn get_wb(&self, rawfile: &RawSource, _cam: &Camera) -> Result<[f32; 4]> { if let Some(colordata) = self.makernote.as_ref().and_then(|mn| mn.get_entry(Cr2MakernoteTag::ColorData)) { let raw_wb = colordata::parse_colordata(colordata)?.wb; return Ok(normalize_wb(raw_wb)); } // TODO: check if these tags belongs to RootIFD or makernote if let Some(levels) = self.tiff.get_entry_raw(TiffCommonTag::Cr2PowerShotWB, &mut rawfile.reader())? { Ok([ levels.get_force_u32(3) as f32, levels.get_force_u32(2) as f32, levels.get_force_u32(4) as f32, f32::NAN, ]) } else if let Some(levels) = self.tiff.get_entry(TiffCommonTag::Cr2OldWB) { Ok([levels.force_f32(0), levels.force_f32(1), levels.force_f32(2), f32::NAN]) } else { // At least the D2000 has no WB Ok([f32::NAN, f32::NAN, f32::NAN, f32::NAN]) } } /// Get the black level from COLORDATA tag /// The offsets are different, so we take the offset from camera params. fn get_blacklevel(&self, cam: &Camera, cpp: usize) -> Result> { if let Some(colordata) = self.makernote.as_ref().and_then(|mn| mn.get_entry(Cr2MakernoteTag::ColorData)) { if let Some(blacklevel) = colordata::parse_colordata(colordata)?.blacklevel { match cpp { 1 => return Ok(Some(BlackLevel::new(&blacklevel, cam.cfa.width, cam.cfa.height, cpp))), 3 => { let avg = blacklevel.into_iter().sum::() / 4; let levels: [u16; 3] = [avg, avg, avg]; return Ok(Some(BlackLevel::new(&levels, 1, 1, cpp))); } _ => unreachable!(), } } } Ok(None) } /// Get the white level from COLORDATA tag /// The offsets are different, so we take the offset from camera params. fn get_whitelevel(&self, cpp: usize) -> Result> { if let Some(colordata) = self.makernote.as_ref().and_then(|mn| mn.get_entry(Cr2MakernoteTag::ColorData)) { if let Some(whitelevel) = colordata::parse_colordata(colordata)?.specular_whitelevel { return Ok(Some(WhiteLevel(vec![whitelevel as u32; cpp]))); } } Ok(None) } /// Get the SENSOR information, if available /// If not, fall back to sensor dimension reported by width/hight values. fn get_sensor_area(&self) -> Result> { if let Some(sensorinfo) = self.makernote.as_ref().and_then(|mn| mn.get_entry(Cr2MakernoteTag::SensorInfo)) { match &sensorinfo.value { Value::Short(v) => { debug!("Sensor info: {:?}", v); let _w = v[1] as usize; let _h = v[2] as usize; let left = v[5] as usize; let top = v[6] as usize; let right = v[7] as usize; let bottom = v[8] as usize; Ok(Some(Rect::new_with_points(Point::new(left, top), Point::new(right + 1, bottom + 1)))) } _ => Err(RawlerError::DecoderFailed("Makernote contains invalid type for SensorInfo tag".to_string())), } } else { Ok(None) } } /// Interpolate YCbCr (YUV) data fn interpolate_yuv(&self, ljpeg: &LjpegDecompressor, width: usize, _height: usize, image: &mut [u16]) { if ljpeg.super_h() == 1 && ljpeg.super_v() == 1 { return; // No interpolation needed } // Iterate over a block of 3 rows, smaller chunks are okay // but must always a multiple of row width. image.par_chunks_mut(width * 3).for_each(|slice| { // Do horizontal interpolation. // [y1 Cb Cr ] [ y2 . . ] [y1 Cb Cr ] [ y2 . . ] ... if ljpeg.super_h() == 2 { debug_assert_eq!(slice.len() % width, 0); for row in 0..(slice.len() / width) { for col in (6..width).step_by(6) { let pix1 = row * width + col - 6; let pix2 = pix1 + 3; let pix3 = row * width + col; slice[pix2 + 1] = ((slice[pix1 + 1] as i32 + slice[pix3 + 1] as i32 + 1) / 2) as u16; slice[pix2 + 2] = ((slice[pix1 + 2] as i32 + slice[pix3 + 2] as i32 + 1) / 2) as u16; } } } // Do vertical interpolation // pixel n pixel n+1 pixel n+2 pixel n+3 ... // row i : [y1 Cb Cr ] [ y2 Cb* Cr* ] [y1 Cb Cr ] [ y2 Cb* Cr* ] ... // row i+1: [y3 Cb* Cr*] [ y4 Cb** Cr**] [y3 Cb* Cr*] [ y4 Cb** Cr**] ... // row i+2: [y1 Cb Cr ] [ y2 Cb* Cr* ] [y1 Cb Cr ] [ y2 Cb* Cr* ] ... // row i+3: [y3 Cb* Cr*] [ y4 Cb** Cr**] [y3 Cb* Cr*] [ y4 Cb** Cr**] ... if ljpeg.super_v() == 2 && slice.len() == width * 3 { for col in (0..width).step_by(3) { let pix1 = col; let pix2 = width + col; let pix3 = 2 * width + col; slice[pix2 + 1] = ((slice[pix1 + 1] as i32 + slice[pix3 + 1] as i32 + 1) / 2) as u16; slice[pix2 + 2] = ((slice[pix1 + 2] as i32 + slice[pix3 + 2] as i32 + 1) / 2) as u16; } } }); /* Old non-parallel code if ljpeg.super_h() == 2 { for row in 0..height { for col in (6..width).step_by(6) { let pix1 = row * width + col - 6; let pix2 = pix1 + 3; let pix3 = row * width + col; image[pix2 + 1] = ((image[pix1 + 1] as i32 + image[pix3 + 1] as i32 + 1) / 2) as u16; image[pix2 + 2] = ((image[pix1 + 2] as i32 + image[pix3 + 2] as i32 + 1) / 2) as u16; } } } if ljpeg.super_v() == 2 { for row in (1..height - 1).step_by(2) { for col in (0..width).step_by(3) { let pix1 = (row - 1) * width + col; let pix2 = row * width + col; let pix3 = (row + 1) * width + col; image[pix2 + 1] = ((image[pix1 + 1] as i32 + image[pix3 + 1] as i32 + 1) / 2) as u16; image[pix2 + 2] = ((image[pix1 + 2] as i32 + image[pix3 + 2] as i32 + 1) / 2) as u16; } } } */ } /// Convert YCbCr (YUV) data to linear RGB fn convert_to_rgb( &self, rawfile: &RawSource, cam: &Camera, ljpeg: &LjpegDecompressor, width: usize, height: usize, image: &mut [u16], dummy: bool, ) -> Result<()> { debug!("YUV2RGB: Regular WB: {:?}", self.get_wb(rawfile, cam)); debug!("YUV2RGB: SRAW WB: {:?}", self.get_sraw_wb(rawfile, cam)); debug!("Model ID: 0x{:X}", self.model_id.unwrap_or(0)); if dummy { return Ok(()); } let do_interpolate = std::env::var("RAWLER_CR2_YUV_INTERPOLATE") .ok() .map(|id| id.parse::().expect("RAWLER_CR2_YUV_INTERPOLATE must by of type bool")) .unwrap_or(true); if do_interpolate { self.interpolate_yuv(ljpeg, width, height, image); } let coeffs = self.get_sraw_wb(rawfile, cam)?; let (c1, c2, c3) = if cam.find_hint("invert_sraw_wb") { let c1 = (1024.0 * 1024.0 / coeffs[0]) as i32; let c2 = coeffs[1] as i32; let c3 = (1024.0 * 1024.0 / coeffs[2]) as i32; (c1, c2, c3) } else { (coeffs[0] as i32, coeffs[1] as i32, coeffs[2] as i32) }; // Starting with 40D, sRaw format was introduced. This uses // version 0. With 5D Mark II, version 1 gets used. // And with 5D Mark III, back to version 0 method // but without an offset of 512 for y. let version = if cam.find_hint("sraw_40d") { 0 } else if cam.find_hint("sraw_new") { 2 } else { 1 }; let fw = self.get_firmware()?; debug!("Firmware: {:?}", fw); // This magic comes from dcraw. // Seems to because of rounding during interpolation, we need to // adjust the hue a little bit (only guessing) let hue = match self.model_id { None => 0, Some(model_id) => { if model_id >= 0x80000281 || (model_id == 0x80000218 && fw.unwrap_or(0) > 1000006) { (((ljpeg.super_h() * ljpeg.super_v()) - 1) >> 1) as i32 } else { (ljpeg.super_h() * ljpeg.super_v()) as i32 } } }; debug!("SRAW hue correction: {:?}", hue); // Now calculate RGB for each YUV tuple. image.par_chunks_exact_mut(3).for_each(|pix| { let y = pix[0] as i32; let cb = pix[1] as i32 - 16383; let cr = pix[2] as i32 - 16383; match version { 0 => { let y = y - 512; // correction for 40D and others let r = c1 * (y + cr); let g = c2 * (y + ((-778 * cb - (cr << 11)) >> 12)); let b = c3 * (y + cb); pix[0] = clampbits(r >> 8, 16); pix[1] = clampbits(g >> 8, 16); pix[2] = clampbits(b >> 8, 16); } 1 => { // found in EOS 5D Mark II let cb = (cb << 2) + hue; let cr = (cr << 2) + hue; let r = c1 * (y + ((50 * cb + 22929 * cr) >> 14)); let g = c2 * (y + ((-5640 * cb - 11751 * cr) >> 14)); let b = c3 * (y + ((29040 * cb - 101 * cr) >> 14)); pix[0] = clampbits(r >> 8, 16); pix[1] = clampbits(g >> 8, 16); pix[2] = clampbits(b >> 8, 16); } 2 => { // found in EOS 5D Mark III and others let r = c1 * (y + cr); let g = c2 * (y + ((-778 * cb - (cr << 11)) >> 12)); let b = c3 * (y + cb); pix[0] = clampbits(r >> 8, 16); pix[1] = clampbits(g >> 8, 16); pix[2] = clampbits(b >> 8, 16); } _ => { unreachable!() } } }); Ok(()) } } fn normalize_wb(raw_wb: [f32; 4]) -> [f32; 4] { debug!("CR2 raw wb: {:?}", raw_wb); // We never have more then RGB colors so far (no RGBE etc.) // So we combine G1 and G2 to get RGB wb. let div = raw_wb[1]; // G1 should be 1024 and we use this as divisor let mut norm = raw_wb; norm.iter_mut().for_each(|v| { if v.is_normal() { *v /= div } }); [norm[0], (norm[1] + norm[2]) / 2.0, norm[3], f32::NAN] } crate::tags::tiff_tag_enum!(Cr2MakernoteTag); /// Specific Canon CR2 Makernotes tags. /// These are only related to the Makernote IFD. #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum Cr2MakernoteTag { CameraSettings = 0x0001, FocalLen = 0x0002, FlashInfo = 0x0003, ShotInfo = 0x0004, Panorama = 0x0005, ImageType = 0x0006, FirmareVer = 0x0007, FileNumber = 0x0008, OwnerName = 0x0009, UnknownD30 = 0x000a, SerialNum = 0x000c, CameraInfo = 0x000d, FileLen = 0x000e, CustomFunc = 0x000f, ModelId = 0x0010, MovieInfo = 0x0011, AFInfo = 0x0012, ThumbArea = 0x0013, SerialFormat = 0x0014, SuperMacro = 0x001a, DateStampMode = 0x001c, MyColors = 0x001d, FirmwareRev = 0x001e, Categories = 0x0023, FaceDetect1 = 0x0024, FaceDetect2 = 0x0025, AFInfo2 = 0x0026, ContrastInfo = 0x0027, ImgUniqueID = 0x0028, WBInfo = 0x0029, FaceDetect3 = 0x002f, TimeInfo = 0x0035, BatteryType = 0x0038, AFInfo3 = 0x003c, RawDataOffset = 0x0081, OrigDecisionDataOffset = 0x0083, CustomFunc1D = 0x0090, PersFunc = 0x0091, PersFuncValues = 0x0092, FileInfo = 0x0093, AFPointsInFocus1D = 0x0094, LensModel = 0x0095, InternalSerial = 0x0096, DustRemovalData = 0x0097, CropInfo = 0x0098, CustomFunc2 = 0x0099, AspectInfo = 0x009a, ProcessingInfo = 0x00a0, ToneCurveTable = 0x00a1, SharpnessTable = 0x00a2, SharpnessFreqTable = 0x00a3, WhiteBalanceTable = 0x00a4, ColorBalance = 0x00a9, MeasuredColor = 0x00aa, ColorTemp = 0x00ae, CanonFlags = 0x00b0, ModifiedInfo = 0x00b1, TnoeCurveMatching = 0x00b2, WhiteBalanceMatching = 0x00b3, ColorSpace = 0x00b4, PreviewImageInfo = 0x00b6, VRDOffset = 0x00d0, SensorInfo = 0x00e0, ColorData = 0x4001, CRWParam = 0x4002, ColorInfo = 0x4003, Flavor = 0x4005, PictureStyleUserDef = 0x4008, PictureStylePC = 0x4009, CustomPictureStyleFileName = 0x4010, AFMicroAdj = 0x4013, VignettingCorr = 0x4015, VignettingCorr2 = 0x4016, LightningOpt = 0x4018, LensInfo = 0x4019, AmbienceInfo = 0x4020, MultiExp = 0x4021, FilterInfo = 0x4024, HDRInfo = 0x4025, AFConfig = 0x4028, RawBurstModeRoll = 0x403f, } //const CR2_MODEL_40D: u32 = 0x80000190; rawler-0.7.1/src/decoders/cr3.rs000064400000000000000000000660021046102023000145450ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher use image::DynamicImage; use log::{debug, warn}; use std::convert::{TryFrom, TryInto}; use std::fmt::Debug; use crate::bits::Endian; use crate::decoders::*; use crate::decompressors::crx::decompress_crx_image; use crate::envparams::{rawler_crx_raw_trak, rawler_ignore_previews}; use crate::exif::ExifGPS; use crate::formats::bmff::FileBox; use crate::formats::bmff::ext_cr3::cmp1::Cmp1Box; use crate::formats::bmff::ext_cr3::cr3desc::Cr3DescBox; use crate::formats::bmff::ext_cr3::iad1::{Iad1Box, Iad1Type}; use crate::formats::bmff::trak::TrakBox; use crate::formats::tiff::reader::TiffReader; use crate::formats::tiff::{Entry, GenericTiffReader, Rational, Value}; use crate::imgop::{Point, Rect}; use crate::lens::{LensDescription, LensId, LensResolver}; use crate::{RawImage, pumps::ByteStream}; const CANON_CN_MOUNT: &str = "cn-mount"; const CANON_EF_MOUNT: &str = "ef-mount"; const CANON_RF_MOUNT: &str = "rf-mount"; /// Decoder for CR3 and CRM files #[allow(dead_code)] #[derive(Debug, Clone)] pub struct Cr3Decoder<'a> { camera: Camera, rawloader: &'a RawLoader, bmff: Bmff, // Basic EXIF information cmt1: GenericTiffReader, // EXIF cmt2: GenericTiffReader, // Makernotes cmt3: GenericTiffReader, // GPS cmt4: GenericTiffReader, // Metadata cache md_cache: DecoderCache, } #[allow(dead_code)] #[derive(Debug, Clone, Default)] struct Cr3Metadata { ctmd_exposure: Option, ctmd_focallen: Option, ctmd_rec7_exif: Option, ctmd_rec7_makernotes: Option, // CTMD Makernotes: COLORDATA ctmd_rec8: Option, ctmd_rec9: Option, xpacket: Option>, image_unique_id: Option<[u8; 16]>, lens_description: Option<&'static LensDescription>, exif: Option, makernotes: Option, wb: Option<[f32; 4]>, blacklevels: Option<[u16; 4]>, whitelevel: Option, } #[allow(dead_code)] const CR3_CTMD_BLOCK_EXIFIFD: u16 = 0x8769; const CR3_CTMD_BLOCK_MAKERNOTES: u16 = 0x927c; /// Type values fro CCTP records #[derive(Clone, Copy, Debug)] #[allow(dead_code)] enum Cr3ImageType { CrxBix = 0, CrxSmall = 1, PreviewBig = 2, Ctmd = 3, CrxDual = 4, } impl<'a> Cr3Decoder<'a> { /// Construct new CR3 or CRM deocder pub fn new(_rawfile: &RawSource, bmff: Bmff, rawloader: &'a RawLoader) -> Result> { if let Some(Cr3DescBox { cmt1, cmt2, cmt3, cmt4, .. }) = bmff.filebox.moov.cr3desc.as_ref() { let mode = Self::get_mode(cmt3.tiff.root_ifd())?; let camera = rawloader.check_supported_with_mode(cmt1.tiff.root_ifd(), mode)?; let decoder = Cr3Decoder { camera, rawloader, cmt1: cmt1.tiff.clone(), cmt2: cmt2.tiff.clone(), cmt3: cmt3.tiff.clone(), cmt4: cmt4.tiff.clone(), bmff, md_cache: DecoderCache::new(), }; Ok(decoder) } else { Err("It's not a CR3 file: CMT boxes not found.".into()) } } // Search for quality tag inside makernotes and derive // our mode string for configuration. fn get_mode(makernotes: &IFD) -> Result<&str> { Ok(if let Some(entry) = makernotes.get_entry(0x0001) { match entry.force_u16(3) { 4 => "raw", 7 => "craw", 130 => "crm", 131 => "crm", _ => "undefined", } } else { "undefined" }) } /// Get trak from moov box fn moov_trak(&self, trak_id: usize) -> Option<&TrakBox> { self.bmff.filebox.moov.traks.get(trak_id) } /// Get IAD1 box for specific trak fn iad1_box(&self, trak_idx: usize) -> Option<&Iad1Box> { let trak = &self.bmff.filebox.moov.traks[trak_idx]; let craw = trak.mdia.minf.stbl.stsd.craw.as_ref(); craw.and_then(|craw| craw.cdi1.as_ref()).map(|cdi1| &cdi1.iad1) } /// Get CMP1 box for specific trak fn cmp1_box(&self, trak_idx: usize) -> Option<&Cmp1Box> { let trak = &self.bmff.filebox.moov.traks[trak_idx]; let craw = trak.mdia.minf.stbl.stsd.craw.as_ref(); craw.and_then(|craw| craw.cmp1.as_ref()) } /// Read CTMD records for given sample /// Each sample (for movie files) have their own CTMD records fn read_ctmd(&self, rawfile: &RawSource, sample_idx: u32) -> Result> { // Search for a trak which has a CTMD box (there should be only one) if let Some(ctmd_trak_index) = self .bmff .filebox .moov .traks .iter() .enumerate() .find(|(_, trak)| trak.mdia.minf.stbl.stsd.ctmd.is_some()) .map(|(id, _)| id) { log::debug!("CTMD trak_index: {}", ctmd_trak_index); let ctmd_trak = &self.bmff.filebox.moov.traks[ctmd_trak_index]; let (offset, size) = ctmd_trak .mdia .minf .stbl .get_sample_offset(sample_idx as u32 + 1) .ok_or_else(|| RawlerError::DecoderFailed(format!("CTMD sample index {} out of bound", sample_idx)))?; debug!("CR3 CTMD mdat offset for sample_idx {}: {}, len: {}", sample_idx, offset, size); let buf = rawfile .subview(offset as u64, size as u64) .map_err(|e| RawlerError::with_io_error("CR3: failed to read CTMD", rawfile.path(), e))?; //dump_buf("/tmp/ctmd.buf", &buf); let mut substream = ByteStream::new(buf, Endian::Little); let ctmd = Ctmd::new(&mut substream); Ok(Some(ctmd)) } else { log::warn!("No CTMD trak found"); Ok(None) } } } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Cr3Format { pub filebox: FileBox, } impl<'a> Decoder for Cr3Decoder<'a> { fn format_dump(&self) -> FormatDump { FormatDump::Cr3(Cr3Format { filebox: self.bmff.filebox.clone(), }) } fn raw_metadata(&self, file: &RawSource, params: &RawDecodeParams) -> Result { let cr3md = self.read_cr3_metadata(file, params)?; let mut exif = Exif::default(); exif.extend_from_ifd(self.cmt1.root_ifd())?; exif.extend_from_ifd(self.cmt2.root_ifd())?; exif.extend_from_gps_ifd(self.cmt4.root_ifd())?; if exif.gps.is_none() { exif.gps = Some(ExifGPS::default()); } if let Some(gps) = &mut exif.gps { for (tag, entry) in self.cmt4.root_ifd().entries() { match tag { // Special handling for Exif.GPSInfo.GPSLatitude and Exif.GPSInfo.GPSLongitude. // Exif.GPSInfo.GPSTimeStamp is wrong, too and can be fixed with the same logic. // Canon CR3 contains only two rationals, but these tags are specified as a vector // of three reationals (degrees, minutes, seconds). // We fix this by extending with 0/1 as seconds value. 0x0002 | 0x0004 | 0x0007 => match &entry.value { Value::Rational(v) => { let fixed_value = if v.len() == 2 { vec![v[0], v[1], Rational::new(0, 1)] } else { v.clone() }; match tag { 0x0002 => gps.gps_latitude = fixed_value.try_into().ok(), 0x0004 => gps.gps_longitude = fixed_value.try_into().ok(), 0x0007 => gps.gps_timestamp = fixed_value.try_into().ok(), _ => unreachable!(), } } _ => { warn!("CR3: Exif.GPSInfo.GPSLatitude and Exif.GPSInfo.GPSLongitude expected to be of type RATIONAL, GPS data is ignored"); } }, _ => {} } } } let mut mdata = RawMetadata::new_with_lens(&self.camera, exif, cr3md.lens_description.cloned()); if let Some(unique_id) = &cr3md.image_unique_id { // For CR3, we use the already included Makernote tag with unique image ID mdata.unique_image_id = Some(u128::from_le_bytes(*unique_id)); } Ok(mdata) } fn xpacket(&self, file: &RawSource, params: &RawDecodeParams) -> Result>> { let cr3md = self.read_cr3_metadata(file, params)?; Ok(cr3md.xpacket) } /// CR3 can store multiple samples in trak fn raw_image_count(&self) -> Result { let raw_trak_id = rawler_crx_raw_trak() .or_else(|| self.get_trak_index(Cr3ImageType::CrxBix)) .ok_or("Unable to find trak index")?; let moov_trak = self.moov_trak(raw_trak_id).ok_or(format!("Unable to get MOOV trak {}", raw_trak_id))?; Ok(moov_trak.mdia.minf.stbl.stsz.sample_count as usize) } /// Decode raw image fn raw_image(&self, file: &RawSource, params: &RawDecodeParams, dummy: bool) -> Result { let sample_idx = params.image_index; if sample_idx >= self.raw_image_count()? { return Err(RawlerError::DecoderFailed(format!( "Raw image index {} out of range ({})", sample_idx, self.raw_image_count()? ))); } let cr3md = self.read_cr3_metadata(file, params)?; if let Some(cr3desc) = &self.bmff.filebox.moov.cr3desc { for item in cr3desc.cctp.ccdts.iter() { log::debug!("CCDT: trak {} type {} dual {}", item.trak_index, item.image_type, item.dual_pixel); } } let raw_trak_id = rawler_crx_raw_trak() .or_else(|| self.get_trak_index(Cr3ImageType::CrxBix)) .ok_or("Unable to find trak index")?; // Load trak with raw MDAT section let moov_trak = self.moov_trak(raw_trak_id).ok_or(format!("Unable to get MOOV trak {}", raw_trak_id))?; let (offset, size) = moov_trak .mdia .minf .stbl .get_sample_offset(sample_idx as u32 + 1) .ok_or_else(|| RawlerError::DecoderFailed(format!("stbl sample not found")))?; debug!("RAW mdat offset: {}, len: {}", offset, size); // Raw data buffer let buf = file .subview(offset as u64, size as u64) .map_err(|e| RawlerError::with_io_error("CR3: failed to read raw data", file.path(), e))?; let cmp1 = self.cmp1_box(raw_trak_id).ok_or(format!("CMP1 box not found for trak {}", raw_trak_id))?; debug!("cmp1 mdat hdr size: {}", cmp1.mdat_hdr_size); let mut wb = cr3md.wb.unwrap_or_else(|| { // This is known for R5 C CRM Standard-Raw files log::warn!("No WB info in CR3 metadata found, fallback to 1.0 coefficients"); [1.0, 1.0, 1.0, f32::NAN] }); let whitelevel = cr3md.whitelevel.unwrap_or(((1_u32 << self.camera.bps.unwrap_or(16)) - 1) as u16); // Special handling for CRM movie files if let Some(entry) = self.cmt3.get_entry(0x0001) { if 130 == entry.force_u16(3) { // Light Raw // WB is already applied, use 1.0 wb = [1.0, 1.0, 1.0, f32::NAN]; } if 131 == entry.force_u16(3) { // Standard Raw // Nothing special for Standard raw } } let image = if !dummy { PixU16::new_with( decompress_crx_image(buf, cmp1).map_err(|e| format!("Failed to decode raw: {}", e))?, cmp1.f_width as usize, cmp1.f_height as usize, ) } else { PixU16::new_uninit(cmp1.f_width as usize, cmp1.f_height as usize) }; let cpp = 1; let blacklevel = cr3md .blacklevels .map(|x| BlackLevel::new(&x, self.camera.cfa.width, self.camera.cfa.height, cpp)); let whitelevel = WhiteLevel(vec![whitelevel as u32]); let photometric = RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&self.camera)); let mut img = RawImage::new(self.camera.clone(), image, cpp, wb, photometric, blacklevel, Some(whitelevel), dummy); // IAD1 box contains sensor information // We use the sensor crop from IAD1 as recommended image crop. // The same crop is used as ActiveArea, because black areas in IAD1 are not // correct (they differs like 4-6 pixels from real values). match self.iad1_box(raw_trak_id) { Some(iad1) => { match &iad1.iad1_type { // IAD1 (small, used for CRM movie files) Iad1Type::Small(small) => { img.crop_area = Some(Rect::new_with_points( Point::new(small.crop_left_offset as usize, small.crop_top_offset as usize), Point::new((small.crop_right_offset + 1) as usize, (small.crop_bottom_offset + 1) as usize), )); img.active_area = img.crop_area; } // IAD1 (big, used for full size raws) Iad1Type::Big(big) => { img.crop_area = Some(Rect::new_with_points( Point::new(big.crop_left_offset as usize, big.crop_top_offset as usize), Point::new((big.crop_right_offset + 1) as usize, (big.crop_bottom_offset + 1) as usize), )); // For uncropped files this is fine, but for 1.6 crop files, the dimension is wrong. // For example, R5 crop is total height of 3510, but active_area_bottom_offset is 3512. let rect = { // Limit the offsets to image bounds. // Probably broken firmware, glitches in sensor size calculation or I'm just making // wrong asumptions... let right = usize::min(cmp1.f_width as usize, (big.active_area_right_offset - 1) as usize); let bottom = usize::min(cmp1.f_height as usize, (big.active_area_bottom_offset - 1) as usize); Rect::new_with_points( Point::new(big.active_area_left_offset as usize, big.active_area_top_offset as usize), Point::new(right, bottom), ) }; log::debug!("IAD1 active area: {:?}", rect); img.active_area = Some(rect); //img.active_area = img.crop_area; let blackarea_h = Rect::new_with_points( Point::new(big.lob_left_offset as usize, big.lob_top_offset as usize), Point::new((big.lob_right_offset - 1) as usize, (big.lob_bottom_offset - 1) as usize), ); if !blackarea_h.is_empty() { //img.blackareas.push(blackarea_h); } let blackarea_v = Rect::new_with_points( Point::new(big.tob_left_offset as usize, big.tob_top_offset as usize), Point::new((big.tob_right_offset - 1) as usize, (big.tob_bottom_offset - 1) as usize), ); if !blackarea_v.is_empty() { //img.blackareas.push(blackarea_v); } } } } None => { warn!("No IAD1 box found for sensor data"); } } debug!("Canon active area: {:?}", img.active_area); debug!("Canon crop area: {:?}", img.crop_area); debug!("Black areas: {:?}", img.blackareas); Ok(img) } /// Extract preview image embedded in CR3 fn full_image(&self, file: &RawSource, params: &RawDecodeParams) -> Result> { if params.image_index != 0 { return Ok(None); } if rawler_ignore_previews() { return Err(RawlerError::DecoderFailed("Unable to extract preview image".into())); } let offset = self.bmff.filebox.moov.traks[0].mdia.minf.stbl.co64.as_ref().expect("co64 box").entries[0] as usize; let size = self.bmff.filebox.moov.traks[0].mdia.minf.stbl.stsz.sample_sizes[0] as usize; debug!("JPEG preview mdat offset: {}, len: {}", offset, size); let buf = file .subview(offset as u64, size as u64) .map_err(|e| RawlerError::with_io_error("CR3: failed to read full image data", file.path(), e))?; match image::load_from_memory_with_format(buf, image::ImageFormat::Jpeg) { Ok(img) => Ok(Some(img)), Err(e) => { debug!("TRAK 0 contains no JPEG preview, is it PQ/HEIF? Error: {}", e); Err(RawlerError::DecoderFailed( "Unable to extract preview image from CR3 HDR-PQ file. Please see 'https://github.com/dnglab/dnglab/issues/7'".into(), )) } } } fn format_hint(&self) -> FormatHint { FormatHint::CR3 } } impl<'a> Cr3Decoder<'a> { fn read_lens_id(&self) -> Result { let mut id = (0, 0); if let Some(Entry { value: Value::Short(v), .. }) = self.cmt3.get_entry(Cr3MakernoteTag::CameraSettings) { id.0 = v[22] as u32; } if let Some(Entry { value: Value::Short(v), .. }) = self.cmt3.get_entry(Cr3MakernoteTag::FileInfo) { id.1 = v[61] as u32; } Ok(id) } fn read_lens_name(&self) -> Result> { if let Some(Entry { value: crate::formats::tiff::Value::Ascii(lens_id), .. }) = self.cmt2.get_entry(ExifTag::LensModel) { return Ok(lens_id.strings().get(0)); } Ok(None) } fn read_cr3_metadata(&self, rawfile: &RawSource, params: &RawDecodeParams) -> Result { if let Some(md) = self.md_cache.get(params) { return Ok(md); } let mut md = Cr3Metadata::default(); let resolver = LensResolver::new() .with_lens_keyname(self.read_lens_name()?) .with_camera(&self.camera) // must follow with_lens_keyname() as it my override key .with_lens_id(self.read_lens_id()?) .with_mounts(&[CANON_CN_MOUNT.into(), CANON_EF_MOUNT.into(), CANON_RF_MOUNT.into()]); md.lens_description = resolver.resolve(); if let Some(Entry { value: crate::formats::tiff::Value::Byte(v), .. }) = self.cmt3.get_entry(Cr3MakernoteTag::ImgUniqueID) { if v.len() == 16 { debug!("CR3 makernote ImgUniqueID: {:x?}", v); md.image_unique_id = Some(v.as_slice().try_into().expect("Invalid slice size")); } } if let Some(entry) = self.cmt3.get_entry(0x0001) { let quality = match entry.force_u16(3) { 4 => "RAW", 5 => "Superfine", 7 => "CRAW", 130 => "LightRaw", 131 => "StandardRaw", _ => "unknown", }; debug!("Canon quality mode: {}", quality); } if let Some(entry) = self.cmt3.get_entry(0x4026) { let clog = match entry.force_u32(11) { 0 => "OFF", 1 => "CLog1", 2 => "CLog2", 3 => "CLog3", _ => "unknown", }; debug!("Canon CLog mode: {}", clog); } if let Some(xpacket_box) = self.bmff.filebox.cr3xpacket.as_ref() { let offset = xpacket_box.header.offset + xpacket_box.header.header_len; let size = xpacket_box.header.size - xpacket_box.header.header_len; let buf = rawfile .subview(offset, size) .map_err(|e| RawlerError::with_io_error("CR3: failed to read XPACKET", rawfile.path(), e))?; md.xpacket = Some(buf.to_vec()); } if let Some(ctmd) = self.read_ctmd(rawfile, params.image_index as u32)? { if let Some(rec5) = ctmd.exposure_info()? { debug!("CTMD Rec(5): {:?}", rec5); md.ctmd_exposure = Some(rec5); } md.ctmd_focallen = ctmd.focal_len()?; if let Some(rec7) = ctmd.get_as_tiff(7, CR3_CTMD_BLOCK_EXIFIFD)? { md.ctmd_rec7_exif = Some(rec7); } if let Some(rec7) = ctmd.get_as_tiff(7, CR3_CTMD_BLOCK_MAKERNOTES)? { md.ctmd_rec7_makernotes = Some(rec7); } if let Some(rec8) = ctmd.get_as_tiff(8, CR3_CTMD_BLOCK_MAKERNOTES)? { if let Some(colordata) = rec8.get_entry(Cr3MakernoteTag::ColorData) { let colordata = cr2::parse_colordata(colordata)?; //rec8.root_ifd().dump::(10).iter().for_each(|line| eprintln!("MKD: {}", line)); md.wb = Some(normalize_wb(colordata.wb)); md.blacklevels = colordata.blacklevel; md.whitelevel = colordata.specular_whitelevel; /* if let crate::formats::tiff::Value::Short(v) = &levels.value { if let Some(offset) = self.camera.param_usize("colordata_wbcoeffs") { let raw_wb = [v[offset] as f32, v[offset + 1] as f32, v[offset + 2] as f32, v[offset + 3] as f32]; md.wb = Some(normalize_wb(raw_wb)); } if let Some(offset) = self.camera.param_usize("colordata_blacklevel") { debug!("Blacklevel offset: {:x}", offset); md.blacklevels = Some([v[offset], v[offset + 1], v[offset + 2], v[offset + 3]]); } if let Some(offset) = self.camera.param_usize("colordata_whitelevel") { md.whitelevel = Some(v[offset]); } } */ } md.ctmd_rec8 = Some(rec8); } if let Some(rec9) = ctmd.get_as_tiff(9, CR3_CTMD_BLOCK_MAKERNOTES)? { md.ctmd_rec9 = Some(rec9); } } debug!("CR3 blacklevels: {:?}", md.blacklevels); debug!("CR3 whitelevel: {:?}", md.whitelevel); self.md_cache.set(params, md.clone()); Ok(md) } fn get_trak_index(&self, image_type: Cr3ImageType) -> Option { if let Some(cr3desc) = &self.bmff.filebox.moov.cr3desc { cr3desc.cctp.ccdts.iter().find(|ccdt| ccdt.image_type == image_type as u64).map(|rec| { debug_assert!(rec.trak_index > 0); (rec.trak_index - 1) as usize }) } else { None } } } /// CTMD section with multiple records #[derive(Clone, Debug)] struct Ctmd { pub records: HashMap, } /// Record inside CTMD section #[allow(dead_code)] #[derive(Clone, Debug)] struct CtmdRecord { pub rec_size: u32, pub rec_type: u16, pub reserved1: u8, pub reserved2: u8, pub reserved3: u8, pub reserved4: u8, pub reserved5: i8, pub reserved6: i8, pub payload: Vec, pub blocks: HashMap>, } impl Ctmd { pub fn new(data: &mut ByteStream) -> Self { let mut records = HashMap::new(); while data.remaining_bytes() >= 12 { let size = data.get_u32(); let mut rec = CtmdRecord { rec_size: size, rec_type: data.get_u16(), reserved1: data.get_u8(), reserved2: data.get_u8(), reserved3: data.get_u8(), reserved4: data.get_u8(), reserved5: data.get_i8(), reserved6: data.get_i8(), payload: data.get_bytes(size as usize - 12), blocks: HashMap::new(), }; debug!( "CTMD Rec {:02}: {}, {}, {}, {}, {}, {}", rec.rec_type, rec.reserved1, rec.reserved2, rec.reserved3, rec.reserved4, rec.reserved5, rec.reserved6 ); //dump_buf(&format!("/tmp/ctmd_rec{}.bin", rec.rec_type), rec.payload.as_slice()); if [7, 8, 9, 10, 11, 12].contains(&rec.rec_type) { let mut bs = ByteStream::new(rec.payload.as_slice(), Endian::Little); let mut _block_id = 0; while bs.remaining_bytes() >= (4 + 2 + 2) { let sz = bs.get_u32() as usize; let tag = bs.get_u16(); let _uk = bs.get_u16(); if sz >= 8 && bs.remaining_bytes() >= (sz - 8) { log::debug!("CTMD BLOCK: size {}, tag {}, remaining: {}", sz, tag, bs.remaining_bytes()); let data = bs.get_bytes(sz as usize - 8); //dump_buf(&format!("/tmp/ctmd_rec{}_block{}_tag0x{:X}_uk{:X}.bin", rec.rec_type, block_id, tag, uk), data.as_slice()); if [CR3_CTMD_BLOCK_EXIFIFD, CR3_CTMD_BLOCK_MAKERNOTES].contains(&tag) { assert_eq!(rec.blocks.contains_key(&tag), false, "Double tag found?!"); rec.blocks.insert(tag, data); } _block_id += 1; } else { log::debug!( "CTMD BLOCK: size {}, tag {}, remaining: {} - is invalid, maybe not a block", sz, tag, bs.remaining_bytes() ); break; } } } else { log::debug!("CTMD record type {} unknown, ignoring.", rec.rec_type); //dump_buf(&format!("/tmp/ctmd_rec{}.bin", rec.rec_type), rec.payload.as_slice()); } records.insert(rec.rec_type, rec); } Self { records } } pub fn get_as_tiff(&self, record: u16, tag: u16) -> Result> { if let Some(block) = self.records.get(&record).and_then(|rec| rec.blocks.get(&tag)) { Ok(Some(GenericTiffReader::new_with_buffer(block, 0, 0, Some(0))?)) } else { warn!("Unable to find CTMD record {}, tag 0x{:X}", record, tag); Ok(None) } } pub fn exposure_info(&self) -> Result> { if let Some(rec) = self.records.get(&5) { let mut buf = ByteStream::new(rec.payload.as_slice(), Endian::Little); let fnumber = Rational::new(buf.get_u16().into(), buf.get_u16().into()); let exposure = Rational::new(buf.get_u16().into(), buf.get_u16().into()); let iso_speed = buf.get_u32(); let unknown = buf.get_bytes(buf.remaining_bytes()); Ok(Some(CtmdExposureInfo { fnumber, exposure, iso_speed, unknown, })) } else { Ok(None) } } pub fn focal_len(&self) -> Result> { if let Some(rec) = self.records.get(&4) { let mut buf = ByteStream::new(rec.payload.as_slice(), Endian::Little); let focal_len = Rational::new(buf.get_u16().into(), buf.get_u16().into()); Ok(Some(focal_len)) } else { Ok(None) } } } fn normalize_wb(raw_wb: [f32; 4]) -> [f32; 4] { debug!("CR3 raw wb: {:?}", raw_wb); // We never have more then RGB colors so far (no RGBE etc.) // So we combine G1 and G2 to get RGB wb. let div = raw_wb[1]; // G1 should be 1024 and we use this as divisor let mut norm = raw_wb; norm.iter_mut().for_each(|v| { if v.is_normal() { *v /= div } }); [norm[0], (norm[1] + norm[2]) / 2.0, norm[3], f32::NAN] } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct CtmdExposureInfo { pub fnumber: Rational, pub exposure: Rational, pub iso_speed: u32, pub unknown: Vec, } crate::tags::tiff_tag_enum!(Cr3MakernoteTag); #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum Cr3MakernoteTag { CameraSettings = 0x0001, FocusInfo = 0x0002, FlashInfo = 0x0003, ShotInfo = 0x0004, Panorama = 0x0005, ImageType = 0x0006, FirmareVer = 0x0007, FileNumber = 0x0008, OwnerName = 0x0009, UnknownD30 = 0x000a, SerialNum = 0x000c, CameraInfo = 0x000d, FileLen = 0x000e, CustomFunc = 0x000f, ModelId = 0x0010, MovieInfo = 0x0011, AFInfo = 0x0012, ThumbArea = 0x0013, SerialFormat = 0x0014, SuperMacro = 0x001a, DateStampMode = 0x001c, MyColors = 0x001d, FirmwareRev = 0x001e, Categories = 0x0023, FaceDetect1 = 0x0024, FaceDetect2 = 0x0025, AFInfo2 = 0x0026, ContrastInfo = 0x0027, ImgUniqueID = 0x0028, WBInfo = 0x0029, FaceDetect3 = 0x002f, TimeInfo = 0x0035, BatteryType = 0x0038, AFInfo3 = 0x003c, RawDataOffset = 0x0081, OrigDecisionDataOffset = 0x0083, CustomFunc1D = 0x0090, PersFunc = 0x0091, PersFuncValues = 0x0092, FileInfo = 0x0093, AFPointsInFocus1D = 0x0094, LensModel = 0x0095, InternalSerial = 0x0096, DustRemovalData = 0x0097, CropInfo = 0x0098, CustomFunc2 = 0x0099, AspectInfo = 0x009a, ProcessingInfo = 0x00a0, ToneCurveTable = 0x00a1, SharpnessTable = 0x00a2, SharpnessFreqTable = 0x00a3, WhiteBalanceTable = 0x00a4, ColorBalance = 0x00a9, MeasuredColor = 0x00aa, ColorTemp = 0x00ae, CanonFlags = 0x00b0, ModifiedInfo = 0x00b1, TnoeCurveMatching = 0x00b2, WhiteBalanceMatching = 0x00b3, ColorSpace = 0x00b4, PreviewImageInfo = 0x00b6, VRDOffset = 0x00d0, SensorInfo = 0x00e0, ColorData = 0x4001, CRWParam = 0x4002, ColorInfo = 0x4003, Flavor = 0x4005, PictureStyleUserDef = 0x4008, PictureStylePC = 0x4009, CustomPictureStyleFileName = 0x4010, AFMicroAdj = 0x4013, VignettingCorr = 0x4015, VignettingCorr2 = 0x4016, LightningOpt = 0x4018, LensInfo = 0x4019, AmbienceInfo = 0x4020, MultiExp = 0x4021, FilterInfo = 0x4024, HDRInfo = 0x4025, AFConfig = 0x4028, RawBurstModeRoll = 0x403f, } rawler-0.7.1/src/decoders/crw.rs000064400000000000000000000261001046102023000146440ustar 00000000000000use crate::RawImage; use crate::decoders::*; use crate::decompressors::ljpeg::huffman::*; use crate::formats::ciff::*; use crate::packed::*; use crate::pumps::BitPump; use crate::pumps::BitPumpJPEG; const CRW_FIRST_TREE: [[u8; 29]; 3] = [ [ 0, 1, 4, 2, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x04, 0x03, 0x05, 0x06, 0x02, 0x07, 0x01, 0x08, 0x09, 0x00, 0x0a, 0x0b, 0xff, ], [ 0, 2, 2, 3, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0x03, 0x02, 0x04, 0x01, 0x05, 0x00, 0x06, 0x07, 0x09, 0x08, 0x0a, 0x0b, 0xff, ], [ 0, 0, 6, 3, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x06, 0x05, 0x07, 0x04, 0x08, 0x03, 0x09, 0x02, 0x00, 0x0a, 0x01, 0x0b, 0xff, ], ]; const CRW_SECOND_TREE: [[u8; 180]; 3] = [ [ 0, 2, 2, 2, 1, 4, 2, 1, 2, 5, 1, 1, 0, 0, 0, 139, 0x03, 0x04, 0x02, 0x05, 0x01, 0x06, 0x07, 0x08, 0x12, 0x13, 0x11, 0x14, 0x09, 0x15, 0x22, 0x00, 0x21, 0x16, 0x0a, 0xf0, 0x23, 0x17, 0x24, 0x31, 0x32, 0x18, 0x19, 0x33, 0x25, 0x41, 0x34, 0x42, 0x35, 0x51, 0x36, 0x37, 0x38, 0x29, 0x79, 0x26, 0x1a, 0x39, 0x56, 0x57, 0x28, 0x27, 0x52, 0x55, 0x58, 0x43, 0x76, 0x59, 0x77, 0x54, 0x61, 0xf9, 0x71, 0x78, 0x75, 0x96, 0x97, 0x49, 0xb7, 0x53, 0xd7, 0x74, 0xb6, 0x98, 0x47, 0x48, 0x95, 0x69, 0x99, 0x91, 0xfa, 0xb8, 0x68, 0xb5, 0xb9, 0xd6, 0xf7, 0xd8, 0x67, 0x46, 0x45, 0x94, 0x89, 0xf8, 0x81, 0xd5, 0xf6, 0xb4, 0x88, 0xb1, 0x2a, 0x44, 0x72, 0xd9, 0x87, 0x66, 0xd4, 0xf5, 0x3a, 0xa7, 0x73, 0xa9, 0xa8, 0x86, 0x62, 0xc7, 0x65, 0xc8, 0xc9, 0xa1, 0xf4, 0xd1, 0xe9, 0x5a, 0x92, 0x85, 0xa6, 0xe7, 0x93, 0xe8, 0xc1, 0xc6, 0x7a, 0x64, 0xe1, 0x4a, 0x6a, 0xe6, 0xb3, 0xf1, 0xd3, 0xa5, 0x8a, 0xb2, 0x9a, 0xba, 0x84, 0xa4, 0x63, 0xe5, 0xc5, 0xf3, 0xd2, 0xc4, 0x82, 0xaa, 0xda, 0xe4, 0xf2, 0xca, 0x83, 0xa3, 0xa2, 0xc3, 0xea, 0xc2, 0xe2, 0xe3, 0xff, 0xff, ], [ 0, 2, 2, 1, 4, 1, 4, 1, 3, 3, 1, 0, 0, 0, 0, 140, 0x02, 0x03, 0x01, 0x04, 0x05, 0x12, 0x11, 0x06, 0x13, 0x07, 0x08, 0x14, 0x22, 0x09, 0x21, 0x00, 0x23, 0x15, 0x31, 0x32, 0x0a, 0x16, 0xf0, 0x24, 0x33, 0x41, 0x42, 0x19, 0x17, 0x25, 0x18, 0x51, 0x34, 0x43, 0x52, 0x29, 0x35, 0x61, 0x39, 0x71, 0x62, 0x36, 0x53, 0x26, 0x38, 0x1a, 0x37, 0x81, 0x27, 0x91, 0x79, 0x55, 0x45, 0x28, 0x72, 0x59, 0xa1, 0xb1, 0x44, 0x69, 0x54, 0x58, 0xd1, 0xfa, 0x57, 0xe1, 0xf1, 0xb9, 0x49, 0x47, 0x63, 0x6a, 0xf9, 0x56, 0x46, 0xa8, 0x2a, 0x4a, 0x78, 0x99, 0x3a, 0x75, 0x74, 0x86, 0x65, 0xc1, 0x76, 0xb6, 0x96, 0xd6, 0x89, 0x85, 0xc9, 0xf5, 0x95, 0xb4, 0xc7, 0xf7, 0x8a, 0x97, 0xb8, 0x73, 0xb7, 0xd8, 0xd9, 0x87, 0xa7, 0x7a, 0x48, 0x82, 0x84, 0xea, 0xf4, 0xa6, 0xc5, 0x5a, 0x94, 0xa4, 0xc6, 0x92, 0xc3, 0x68, 0xb5, 0xc8, 0xe4, 0xe5, 0xe6, 0xe9, 0xa2, 0xa3, 0xe3, 0xc2, 0x66, 0x67, 0x93, 0xaa, 0xd4, 0xd5, 0xe7, 0xf8, 0x88, 0x9a, 0xd7, 0x77, 0xc4, 0x64, 0xe2, 0x98, 0xa5, 0xca, 0xda, 0xe8, 0xf3, 0xf6, 0xa9, 0xb2, 0xb3, 0xf2, 0xd2, 0x83, 0xba, 0xd3, 0xff, 0xff, ], [ 0, 0, 6, 2, 1, 3, 3, 2, 5, 1, 2, 2, 8, 10, 0, 117, 0x04, 0x05, 0x03, 0x06, 0x02, 0x07, 0x01, 0x08, 0x09, 0x12, 0x13, 0x14, 0x11, 0x15, 0x0a, 0x16, 0x17, 0xf0, 0x00, 0x22, 0x21, 0x18, 0x23, 0x19, 0x24, 0x32, 0x31, 0x25, 0x33, 0x38, 0x37, 0x34, 0x35, 0x36, 0x39, 0x79, 0x57, 0x58, 0x59, 0x28, 0x56, 0x78, 0x27, 0x41, 0x29, 0x77, 0x26, 0x42, 0x76, 0x99, 0x1a, 0x55, 0x98, 0x97, 0xf9, 0x48, 0x54, 0x96, 0x89, 0x47, 0xb7, 0x49, 0xfa, 0x75, 0x68, 0xb6, 0x67, 0x69, 0xb9, 0xb8, 0xd8, 0x52, 0xd7, 0x88, 0xb5, 0x74, 0x51, 0x46, 0xd9, 0xf8, 0x3a, 0xd6, 0x87, 0x45, 0x7a, 0x95, 0xd5, 0xf6, 0x86, 0xb4, 0xa9, 0x94, 0x53, 0x2a, 0xa8, 0x43, 0xf5, 0xf7, 0xd4, 0x66, 0xa7, 0x5a, 0x44, 0x8a, 0xc9, 0xe8, 0xc8, 0xe7, 0x9a, 0x6a, 0x73, 0x4a, 0x61, 0xc7, 0xf4, 0xc6, 0x65, 0xe9, 0x72, 0xe6, 0x71, 0x91, 0x93, 0xa6, 0xda, 0x92, 0x85, 0x62, 0xf3, 0xc5, 0xb2, 0xa4, 0x84, 0xba, 0x64, 0xa5, 0xb3, 0xd2, 0x81, 0xe5, 0xd3, 0xaa, 0xc4, 0xca, 0xf2, 0xb1, 0xe4, 0xd1, 0x83, 0x63, 0xea, 0xc3, 0xe2, 0x82, 0xf1, 0xa3, 0xc2, 0xa1, 0xc1, 0xe3, 0xa2, 0xe1, 0xff, 0xff, ], ]; #[derive(Debug, Clone)] pub struct CrwDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, ciff: CiffIFD, camera: Camera, } impl<'a> CrwDecoder<'a> { pub fn new(file: &RawSource, rawloader: &'a RawLoader) -> Result> { let ciff = CiffIFD::new_file(file)?; let makemodel = fetch_ciff_tag!(ciff, CiffTag::MakeModel).get_strings(); if makemodel.len() < 2 { return Err(RawlerError::DecoderFailed("CRW: MakeModel tag needs to have 2 strings".to_string())); } let camera = rawloader.check_supported_with_everything(&makemodel[0], &makemodel[1], "")?; Ok(CrwDecoder { ciff, rawloader, camera }) } } impl<'a> Decoder for CrwDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let image = if self.camera.model == "Canon PowerShot Pro70" { let src = file.subview_until_eof(26)?; decode_10le_lsb16(src, 1552, 1024, dummy) } else { let sensorinfo = fetch_ciff_tag!(self.ciff, CiffTag::SensorInfo); let width = sensorinfo.get_usize(1); let height = sensorinfo.get_usize(2); self.decode_compressed(file, width, height, dummy)? }; let wb = { let wb_raw = self.get_wb()?; match self.camera.cfa.unique_colors() { 3 => normalize_wb(wb_raw), 4 => { let maxval = wb_raw.into_iter().map(|v| v as i32).min().unwrap_or(0) as f32; [wb_raw[0] / maxval, wb_raw[1] / maxval, wb_raw[2] / maxval, wb_raw[3] / maxval] } _ => unreachable!(), } }; let cpp = 1; ok_cfa_image(self.camera.clone(), cpp, wb, image, dummy) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, __params: &RawDecodeParams) -> Result { // TODO: Add EXIF info let exif = Exif::default(); Ok(RawMetadata::new(&self.camera, exif)) } fn format_hint(&self) -> FormatHint { FormatHint::CRW } } impl<'a> CrwDecoder<'a> { fn get_wb(&self) -> Result<[f32; 4]> { if let Some(levels) = self.ciff.find_entry(CiffTag::WhiteBalance) { let offset = self.camera.param_usize("wb_offset").unwrap_or(0); return Ok([ levels.get_f32(offset + 0), levels.get_f32(offset + 1), levels.get_f32(offset + 2), levels.get_f32(offset + 3), ]); } if !self.camera.find_hint("nocinfo2") { if let Some(cinfo) = self.ciff.find_entry(CiffTag::ColorInfo2) { return Ok(if cinfo.get_u32(0) > 512 { [cinfo.get_f32(62), cinfo.get_f32(63), cinfo.get_f32(60), cinfo.get_f32(61)] // RGBE??? } else { [cinfo.get_f32(51), cinfo.get_f32(50), cinfo.get_f32(53), cinfo.get_f32(52)] }); } } if let Some(cinfo) = self.ciff.find_entry(CiffTag::ColorInfo1) { if cinfo.count == 768 { // D30 return Ok([ 1024.0 / (cinfo.get_force_u16(36) as f32), 1024.0 / (cinfo.get_force_u16(37) as f32), 1024.0 / (cinfo.get_force_u16(38) as f32), 1024.0 / (cinfo.get_force_u16(39) as f32), ]); } let off = self.camera.param_usize("wb_offset").unwrap_or(0); let key: [u16; 2] = if self.camera.find_hint("wb_mangle") { [0x410, 0x45f3] } else { [0, 0] }; return Ok([ (cinfo.get_force_u16(off + 1) ^ key[1]) as f32, (cinfo.get_force_u16(off + 0) ^ key[0]) as f32, (cinfo.get_force_u16(off + 0) ^ key[0]) as f32, (cinfo.get_force_u16(off + 2) ^ key[0]) as f32, ]); } Ok([f32::NAN, f32::NAN, f32::NAN, f32::NAN]) } fn create_hufftables(num: usize) -> [HuffTable; 2] { [Self::create_hufftable(&CRW_FIRST_TREE[num]), Self::create_hufftable(&CRW_SECOND_TREE[num])] } fn create_hufftable(table: &[u8]) -> HuffTable { let mut htable = HuffTable::empty(); for i in 0..16 { htable.bits[i + 1] = table[i] as u32; } for i in 16..table.len() { htable.huffval[i - 16] = table[i] as u32; } htable.disable_cache = true; htable.initialize().unwrap(); htable } fn decode_compressed(&self, file: &RawSource, width: usize, height: usize, dummy: bool) -> Result { let lowbits = !self.camera.find_hint("nolowbits"); let dectable = fetch_ciff_tag!(self.ciff, CiffTag::DecoderTable).get_usize(0); if dectable > 2 { return Err(RawlerError::DecoderFailed(format!("CRW: Unknown decoder table {}", dectable))); } Self::do_decode(file, lowbits, dectable, width, height, dummy) } pub(crate) fn do_decode(file: &RawSource, lowbits: bool, dectable: usize, width: usize, height: usize, dummy: bool) -> Result { let mut out = alloc_image_ok!(width, height, dummy); let htables = Self::create_hufftables(dectable); let offset = 540 + (lowbits as usize) * height * width / 4; let src = file.subview_until_eof(offset as u64)?; let mut pump = BitPumpJPEG::new(src); let mut carry: i32 = 0; let mut base = [0_i32; 2]; let mut pnum = 0; for pixout in out.pixels_mut().chunks_exact_mut(64) { // Decode a block of 64 differences let mut diffbuf = [0_i32; 64]; let mut i: usize = 0; while i < 64 { let tbl = &htables[(i > 0) as usize]; let leaf = tbl.huff_get_bits(&mut pump); if leaf == 0 && i != 0 { break; } if leaf == 0xff { i += 1; continue; } i += (leaf >> 4) as usize; let len = leaf & 0x0f; if len == 0 { i += 1; continue; } let mut diff: i32 = pump.get_bits(len) as i32; if (diff & (1 << (len - 1))) == 0 { diff -= (1 << len) - 1; } if i < 64 { diffbuf[i] = diff; } i += 1; } diffbuf[0] += carry; carry = diffbuf[0]; // Save those differences to 64 pixels adjusting the predictor as we go for i in 0..64 { // At the start of lines reset the predictor to 512 if pnum % width == 0 { base[0] = 512; base[1] = 512; } pnum += 1; base[i & 1] += diffbuf[i]; pixout[i] = base[i & 1] as u16; } } if lowbits { let buffer = file.as_vec()?; // Add the uncompressed 2 low bits to the decoded 8 high bits for (i, o) in out.pixels_mut().chunks_exact_mut(4).enumerate() { let c = buffer[26 + i] as u16; o[0] = (o[0] << 2) | (c) & 0x03; o[1] = (o[1] << 2) | (c >> 2) & 0x03; o[2] = (o[2] << 2) | (c >> 4) & 0x03; o[3] = (o[3] << 2) | (c >> 6) & 0x03; if width == 2672 { // No idea why this is needed, probably some broken camera if o[0] < 512 { o[0] += 2 } if o[1] < 512 { o[1] += 2 } if o[2] < 512 { o[2] += 2 } if o[3] < 512 { o[3] += 2 } } } } Ok(out) } } fn normalize_wb(raw_wb: [f32; 4]) -> [f32; 4] { debug!("CRW raw wb: {:?}", raw_wb); // We never have more then RGB colors so far (no RGBE etc.) // So we combine G1 and G2 to get RGB wb. let div = raw_wb[1]; let mut norm = raw_wb; norm.iter_mut().for_each(|v| { if v.is_normal() { *v /= div } }); [norm[0], (norm[1] + norm[2]) / 2.0, norm[3], f32::NAN] } rawler-0.7.1/src/decoders/dcr.rs000064400000000000000000000114171046102023000146260ustar 00000000000000use std::cmp; use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::alloc_image; use crate::analyze::FormatDump; use crate::bits::BEu16; use crate::bits::Endian; use crate::bits::LookupTable; use crate::exif::Exif; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::IFD; use crate::formats::tiff::reader::TiffReader; use crate::pixarray::PixU16; use crate::pumps::ByteStream; use crate::rawsource::RawSource; use crate::tags::TiffCommonTag; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use super::ok_cfa_image; #[derive(Debug, Clone)] pub struct DcrDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, makernote: IFD, camera: Camera, } impl<'a> DcrDecoder<'a> { pub fn new(file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { let camera = rawloader.check_supported(tiff.root_ifd())?; let kodak_ifd = fetch_tiff_tag!(tiff, TiffCommonTag::KodakIFD); let makernote = IFD::new(&mut file.reader(), kodak_ifd.force_u32(0), 0, 0, tiff.get_endian(), &[])?; Ok(DcrDecoder { tiff, rawloader, camera, makernote, }) } } impl<'a> Decoder for DcrDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let raw = self .tiff .find_first_ifd_with_tag(TiffCommonTag::CFAPattern) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with CFAPattern tag")))?; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let offset = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); let src = file.subview_until_eof_padded(offset as u64)?; // TODO add size and check all samples let linearization = fetch_tiff_tag!(self.makernote, TiffCommonTag::DcrLinearization); let curve = { let mut points = Vec::new(); for i in 0..linearization.count() { points.push(linearization.force_u32(i) as u16); } LookupTable::new(&points) }; let image = DcrDecoder::decode_kodak65000(&src, &curve, width, height, dummy); let cpp = 1; ok_cfa_image(self.camera.clone(), cpp, self.get_wb()?, image, dummy) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, __params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; let mdata = RawMetadata::new(&self.camera, exif); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::DCR } } impl<'a> DcrDecoder<'a> { fn get_wb(&self) -> Result<[f32; 4]> { let dcrwb = fetch_tiff_tag!(self.makernote, TiffCommonTag::DcrWB); if dcrwb.count() >= 46 { let levels = dcrwb.get_data(); Ok([ 2048.0 / BEu16(levels, 40) as f32, 2048.0 / BEu16(levels, 42) as f32, 2048.0 / BEu16(levels, 44) as f32, f32::NAN, ]) } else { Ok([f32::NAN, f32::NAN, f32::NAN, f32::NAN]) } } pub(crate) fn decode_kodak65000(buf: &[u8], curve: &LookupTable, width: usize, height: usize, dummy: bool) -> PixU16 { let mut out = alloc_image!(width, height, dummy); let mut input = ByteStream::new(buf, Endian::Little); let mut random: u32 = 0; for row in 0..height { for col in (0..width).step_by(256) { let mut pred: [i32; 2] = [0; 2]; let buf = DcrDecoder::decode_segment(&mut input, cmp::min(256, width - col)); for (i, val) in buf.iter().enumerate() { pred[i & 1] += *val; if pred[i & 1] < 0 { panic!("Found a negative pixel!"); } out[row * width + col + i] = curve.dither(pred[i & 1] as u16, &mut random); } } } out } fn decode_segment(input: &mut ByteStream, size: usize) -> Vec { let mut out: Vec = vec![0; size]; let mut lens: [usize; 256] = [0; 256]; for i in (0..size).step_by(2) { lens[i] = (input.peek_u8() & 15) as usize; lens[i + 1] = (input.get_u8() >> 4) as usize; } let mut bitbuf: u64 = 0; let mut bits: usize = 0; if (size & 7) == 4 { bitbuf = ((input.get_u8() as u64) << 8) | (input.get_u8() as u64); bits = 16; } for i in 0..size { let len = lens[i]; if bits < len { for j in (0..32).step_by(8) { bitbuf += (input.get_u8() as u64) << (bits + (j ^ 8)); } bits += 32; } out[i] = (bitbuf & (0xffff >> (16 - len))) as i32; bitbuf >>= len; bits -= len; if len != 0 && (out[i] & (1 << (len - 1))) == 0 { out[i] -= (1 << len) - 1; } } out } } rawler-0.7.1/src/decoders/dcs.rs000064400000000000000000000044661046102023000146350ustar 00000000000000use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::analyze::FormatDump; use crate::bits::LookupTable; use crate::exif::Exif; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::reader::TiffReader; use crate::packed::decode_8bit_wtable; use crate::rawsource::RawSource; use crate::tags::TiffCommonTag; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use super::ok_cfa_image; #[derive(Debug, Clone)] pub struct DcsDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, camera: Camera, } impl<'a> DcsDecoder<'a> { pub fn new(_file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { let camera = rawloader.check_supported(tiff.root_ifd())?; Ok(DcsDecoder { camera, tiff, rawloader }) } } impl<'a> Decoder for DcsDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let raw = self .tiff .find_ifd_with_new_subfile_type(0) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find IFD with subfile type 0")))?; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let offset = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); let src = file.subview_until_eof_padded(offset as u64)?; // TODO add size and check all samples let linearization = fetch_tiff_tag!(self.tiff, TiffCommonTag::GrayResponse); let table = { let mut t: [u16; 256] = [0; 256]; for i in 0..256 { t[i] = linearization.force_u32(i) as u16; } LookupTable::new(&t) }; let image = decode_8bit_wtable(&src, &table, width, height, dummy); let cpp = 1; ok_cfa_image(self.camera.clone(), cpp, [f32::NAN, f32::NAN, f32::NAN, f32::NAN], image, dummy) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; let mdata = RawMetadata::new(&self.camera, exif); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::DCS } } rawler-0.7.1/src/decoders/dng.rs000064400000000000000000000406511046102023000146300ustar 00000000000000use crate::RawImage; use crate::cfa::*; use crate::decoders::*; use crate::formats::tiff::Entry; use crate::formats::tiff::Rational; use crate::formats::tiff::Value; use crate::imgop::Dim2; use crate::imgop::Point; use crate::imgop::Rect; use crate::imgop::xyz::FlatColorMatrix; use crate::imgop::xyz::Illuminant; use crate::tags::DngTag; use crate::tags::TiffCommonTag; #[derive(Debug, Clone)] pub struct DngDecoder<'a> { rawloader: &'a RawLoader, tiff: GenericTiffReader, } impl<'a> DngDecoder<'a> { pub fn new(_file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { Ok(DngDecoder { tiff, rawloader }) } } /// DNG format encapsulation for analyzer #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DngFormat { tiff: GenericTiffReader, } impl<'a> Decoder for DngDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let raw = self.get_raw_ifd()?; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let cpp = fetch_tiff_tag!(raw, TiffCommonTag::SamplesPerPixel).force_usize(0); let bits = fetch_tiff_tag!(raw, TiffCommonTag::BitsPerSample).force_u32(0); let orientation = Orientation::from_tiff(self.tiff.root_ifd()); let mut cam = self.make_camera(raw, width, height)?; // If we know the camera, re-use the clean names if let Ok(known_cam) = self.rawloader.check_supported(self.tiff.root_ifd()) { cam.clean_make = known_cam.clean_make; cam.clean_model = known_cam.clean_model; } let blacklevel = self.get_blacklevels(raw)?; let whitelevel = self.get_whitelevels(raw)?.or(Some(WhiteLevel::new_bits(bits, cpp))); let photometric = match fetch_tiff_tag!(raw, TiffCommonTag::PhotometricInt).force_u32(0) { 1 => RawPhotometricInterpretation::BlackIsZero, 32803 => RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&cam)), 34892 => RawPhotometricInterpretation::LinearRaw, _ => todo!(), }; let raw_data = plain_image_from_ifd(raw, file)?; let mut image = RawImage::new_with_data( cam, raw_data, width * cpp, height, cpp, self.get_wb()?, photometric, blacklevel, whitelevel, dummy, ); image.orientation = orientation; Ok(image) } fn format_dump(&self) -> FormatDump { FormatDump::Dng(DngFormat { tiff: self.tiff.clone() }) } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let raw = self.get_raw_ifd()?; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let mut cam = self.make_camera(raw, width, height)?; // If we know the camera, re-use the clean names if let Ok(known_cam) = self.rawloader.check_supported(self.tiff.root_ifd()) { cam.clean_make = known_cam.clean_make; cam.clean_model = known_cam.clean_model; } let exif = Exif::new(self.tiff.root_ifd())?; let mdata = RawMetadata::new(&cam, exif); Ok(mdata) } fn thumbnail_image(&self, file: &RawSource, _params: &RawDecodeParams) -> Result> { if let Some(thumb_ifd) = Some(self.tiff.root_ifd()).filter(|ifd| ifd.get_entry(TiffCommonTag::NewSubFileType).map(|entry| entry.force_u16(0)) == Some(1)) { Ok(Some(dynamic_image_from_ifd(thumb_ifd, file)?)) } else { Ok(None) } } fn full_image(&self, file: &RawSource, params: &RawDecodeParams) -> Result> { if params.image_index != 0 { return Ok(None); } if let Some(sub_ifds) = self.tiff.root_ifd().get_sub_ifd_all(TiffCommonTag::SubIFDs) { let first_ifd = sub_ifds .iter() .find(|ifd| ifd.get_entry(TiffCommonTag::NewSubFileType).map(|entry| entry.force_u32(0)) == Some(1)); if let Some(preview_ifd) = first_ifd { return Ok(Some(dynamic_image_from_ifd(preview_ifd, file)?)); } } Ok(None) } fn ifd(&self, wk_ifd: WellKnownIFD) -> Result>> { Ok(match wk_ifd { WellKnownIFD::Root => Some(Rc::new(self.tiff.root_ifd().clone())), WellKnownIFD::Raw => Some(Rc::new(self.get_raw_ifd()?.clone())), WellKnownIFD::Exif => self .tiff .root_ifd() .get_sub_ifd_all(ExifTag::ExifOffset) .and_then(|list| list.get(0)) .cloned() .map(Rc::new), WellKnownIFD::ExifGps => self .tiff .root_ifd() .get_sub_ifd_all(ExifTag::GPSInfo) .and_then(|list| list.get(0)) .cloned() .map(Rc::new), WellKnownIFD::VirtualDngRawTags => { let mut ifd = IFD::default(); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::OpcodeList1); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::OpcodeList2); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::OpcodeList3); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::NoiseProfile); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::BayerGreenSplit); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::ChromaBlurRadius); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::AntiAliasStrength); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::NoiseReductionApplied); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::ProfileGainTableMap); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::CameraCalibration1); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::CameraCalibration2); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::CameraCalibration3); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::ForwardMatrix1); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::ForwardMatrix2); IFD::copy_tag(&mut ifd, self.get_raw_ifd()?, DngTag::ForwardMatrix3); Some(Rc::new(ifd)) } WellKnownIFD::VirtualDngRootTags => { let mut ifd = IFD::default(); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileEmbedPolicy); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileHueSatMapData1); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileHueSatMapData2); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileHueSatMapData3); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileHueSatMapDims); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileHueSatMapData1); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileHueSatMapData2); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileHueSatMapData3); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileHueSatMapEncoding); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileLookTableData); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileLookTableDims); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileLookTableEncoding); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileName); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileCopyright); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::ProfileToneCurve); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::DNGPrivateData); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::MakerNoteSafety); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::AnalogBalance); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::BaselineExposure); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::BaselineNoise); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::BaselineSharpness); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::LinearResponseLimit); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::CameraSerialNumber); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::AsShotICCProfile); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::AsShotPreProfileMatrix); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::CurrentICCProfile); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::CurrentPreProfileMatrix); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::AsShotProfileName); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::DefaultBlackRender); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::BaselineExposureOffset); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::DepthFormat); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::DepthNear); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::DepthFar); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::DepthUnits); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::DepthMeasureType); IFD::copy_tag(&mut ifd, self.tiff.root_ifd(), DngTag::RGBTables); Some(Rc::new(ifd)) } _ => return Ok(None), }) } fn format_hint(&self) -> FormatHint { FormatHint::DNG } } impl<'a> DngDecoder<'a> { fn get_raw_ifd(&self) -> Result<&IFD> { let ifds = self .tiff .find_ifds_with_tag(TiffCommonTag::Compression) .into_iter() .filter(|ifd| { let compression = (**ifd) .get_entry(TiffCommonTag::Compression) .expect("This IFD must contains this tag") .force_u32(0); let subsampled = match (**ifd).get_entry(TiffCommonTag::NewSubFileType) { Some(e) => e.force_u32(0) & 1 != 0, None => false, }; !subsampled && (compression == 7 || compression == 8 || compression == 1 || compression == 0x884c || compression == 52546) }) .collect::>(); if let Some(first) = ifds.first() { Ok(first) } else { Err(RawlerError::DecoderFailed(format!("TODO: Unsupported DNG compression"))) } } fn make_camera(&self, raw: &IFD, width: usize, height: usize) -> Result { let mode = String::from("dng"); let make = self .tiff .root_ifd() .get_entry(TiffCommonTag::Make) .and_then(|x| x.as_string()) .cloned() .unwrap_or_default(); let model = self .tiff .root_ifd() .get_entry(TiffCommonTag::Model) .and_then(|x| x.as_string()) .cloned() .unwrap_or_default(); let active_area = self.get_active_area(raw, width, height); let crop_area = if let Some(crops) = self.get_crop(raw) { if let Some(active_area) = &active_area { let mut full = crops; full.p.x += active_area[0]; // left full.p.y += active_area[1]; // Top Some(full.as_ltrb_offsets(width, height)) } else { Some(crops.as_ltrb_offsets(width, height)) } } else { None }; let linear = fetch_tiff_tag!(raw, TiffCommonTag::PhotometricInt).force_usize(0) == 34892; let cfa = if linear { CFA::default() } else { self.get_cfa(raw)? }; let color_matrix = self.get_color_matrix()?; let real_bps = if raw.has_entry(TiffCommonTag::Linearization) { // If DNG contains linearization table, output is always 16 bits 16 } else { raw.get_entry(TiffCommonTag::BitsPerSample).map(|v| v.force_usize(0)).unwrap_or(16) }; Ok(Camera { clean_make: make.clone(), clean_model: model.clone(), make, model, mode, whitelevel: None, blacklevel: None, blackareah: None, blackareav: None, xyz_to_cam: Default::default(), color_matrix, cfa, active_area, crop_area, real_bps, ..Default::default() }) } fn get_wb(&self) -> Result<[f32; 4]> { if let Some(levels) = self.tiff.get_entry(TiffCommonTag::AsShotNeutral) { Ok([1.0 / levels.force_f32(0), 1.0 / levels.force_f32(1), 1.0 / levels.force_f32(2), f32::NAN]) } else { Ok([f32::NAN, f32::NAN, f32::NAN, f32::NAN]) } } fn get_blacklevels(&self, raw: &IFD) -> Result> { let cpp = raw.get_entry(TiffCommonTag::SamplesPerPixel).map(|entry| entry.force_usize(0)).unwrap_or(1); if let Some(entry) = raw.get_entry(TiffCommonTag::BlackLevels) { let levels = match &entry.value { Value::Short(black) => black.iter().copied().map(Rational::from).collect(), Value::Long(black) => black.iter().copied().map(Rational::from).collect(), Value::Rational(black) => black.clone(), _ => return Err(format!("Unsupported BlackLevel type: {}", entry.value_type_name()).into()), }; let mut repeat = (1, 1); if let Some(Entry { value: Value::Short(value), .. }) = raw.get_entry(DngTag::BlackLevelRepeatDim) { if value.len() == 2 { repeat = (value[0] as usize, value[1] as usize); } else { // Pentax K-3 Mark III Monochrome is known to has invalid tag log::warn!("File has BlackLevelRepeatDim tag but with invalid length: {}", value.len()); } } Ok(Some(BlackLevel::new(&levels, repeat.1, repeat.0, cpp))) } else { Ok(None) } } fn get_whitelevels(&self, raw: &IFD) -> Result> { let cpp = fetch_tiff_tag!(raw, TiffCommonTag::SamplesPerPixel).force_usize(0); if let Some(levels) = raw.get_entry(TiffCommonTag::WhiteLevel) { let mut whitelevels = WhiteLevel((0..levels.count()).map(|i| levels.force_u32(i as usize)).collect()); // Fixes a bug where only a single whitelevel value is given. if whitelevels.0.len() == 1 && cpp > 1 { whitelevels.0 = vec![whitelevels.0[0]; cpp]; } return Ok(Some(whitelevels)); } Ok(None) } fn get_cfa(&self, raw: &IFD) -> Result { let pattern = fetch_tiff_tag!(raw, TiffCommonTag::CFAPattern); let cfa = CFA::new_from_tag(pattern); // If DNG has active area, we need to calulate back the CFA pattern, // because for DNG the CFAPattern is relative to ActiveArea and we // use (0, 0) as starting point. if let Some(active_area) = self.get_active_area_borders(raw) { let top = active_area[0]; let left = active_area[1]; Ok(cfa.shift(left % cfa.width, top % cfa.height)) } else { Ok(cfa) } } fn get_active_area_borders(&self, raw: &IFD) -> Option<[usize; 4]> { if let Some(crops) = raw.get_entry(DngTag::ActiveArea) { let rect = [crops.force_usize(0), crops.force_usize(1), crops.force_usize(2), crops.force_usize(3)]; Some(rect) } else { // Ignore missing crops, at least some pentax DNGs don't have it None } } fn get_active_area(&self, raw: &IFD, width: usize, height: usize) -> Option<[usize; 4]> { if let Some(rect) = self.get_active_area_borders(raw) { Some(Rect::new_with_dng(&rect).as_ltrb_offsets(width, height)) } else { None } } fn get_crop(&self, raw: &IFD) -> Option { if let Some(crops) = raw.get_entry(DngTag::DefaultCropOrigin) { let p = Point::new(crops.force_usize(0), crops.force_usize(1)); if let Some(size) = raw.get_entry(DngTag::DefaultCropSize) { let d = Dim2::new(size.force_usize(0), size.force_usize(1)); return Some(Rect::new(p, d)); } } None } fn _get_masked_areas(&self, raw: &IFD) -> Vec { let mut areas = Vec::new(); if let Some(masked_area) = raw.get_entry(TiffCommonTag::MaskedAreas) { for x in (0..masked_area.count() as usize).step_by(4) { areas.push(Rect::new_with_points( Point::new(masked_area.force_usize(x), masked_area.force_usize(x + 1)), Point::new(masked_area.force_usize(x + 2), masked_area.force_usize(x + 3)), )); } } areas } fn get_color_matrix(&self) -> Result> { let mut result = HashMap::new(); let mut read_matrix = |cal: DngTag, mat: DngTag| -> Result<()> { if let Some(c) = self.tiff.get_entry(mat) { let illuminant: Illuminant = fetch_tiff_tag!(self.tiff, cal).force_u16(0).try_into()?; let mut matrix = FlatColorMatrix::new(); for i in 0..c.count() as usize { matrix.push(c.force_f32(i)); } assert!(matrix.len() <= 12 && !matrix.is_empty()); result.insert(illuminant, matrix); } Ok(()) }; read_matrix(DngTag::CalibrationIlluminant1, DngTag::ColorMatrix1)?; read_matrix(DngTag::CalibrationIlluminant2, DngTag::ColorMatrix2)?; // TODO: add 3 Ok(result) } } rawler-0.7.1/src/decoders/erf.rs000064400000000000000000000067511046102023000146370ustar 00000000000000use log::warn; use crate::RawlerError; use crate::analyze::FormatDump; use crate::rawsource::RawSource; use crate::RawImage; use crate::RawLoader; use crate::Result; use crate::bits::BEu16; use crate::exif::Exif; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::IFD; use crate::formats::tiff::ifd::OffsetMode; use crate::formats::tiff::reader::TiffReader; use crate::packed::decode_12be_wcontrol; use crate::tags::ExifTag; use crate::tags::TiffCommonTag; use super::BlackLevel; use super::CFAConfig; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use super::RawPhotometricInterpretation; #[derive(Debug, Clone)] pub struct ErfDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, makernote: IFD, camera: Camera, } impl<'a> ErfDecoder<'a> { pub fn new(file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { let camera = rawloader.check_supported(tiff.root_ifd())?; let makernote = if let Some(exif) = tiff.find_first_ifd_with_tag(ExifTag::MakerNotes) { exif.parse_makernote(&mut file.reader(), OffsetMode::Absolute, &[])? } else { warn!("ERF makernote not found"); None } .ok_or("File has not makernotes")?; Ok(ErfDecoder { tiff, rawloader, camera, makernote, }) } } impl<'a> Decoder for ErfDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let raw = self .tiff .find_first_ifd_with_tag(TiffCommonTag::CFAPattern) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with CFAPattern tag")))?; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let offset = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); let src = file.subview_until_eof(offset as u64)?; let image = decode_12be_wcontrol(src, width, height, dummy); let cpp = 1; let blacklevel = self.get_blacklevel(cpp); let photometric = RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&self.camera)); let img = RawImage::new(self.camera.clone(), image, cpp, self.get_wb()?, photometric, blacklevel, None, dummy); Ok(img) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; let mdata = RawMetadata::new(&self.camera, exif); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::ERF } } impl<'a> ErfDecoder<'a> { fn get_wb(&self) -> Result<[f32; 4]> { let levels = fetch_tiff_tag!(self.makernote, TiffCommonTag::EpsonWB); if levels.count() != 256 { Err(RawlerError::DecoderFailed("ERF: Levels count is off".to_string())) } else { let r = BEu16(levels.get_data(), 48) as f32; let b = BEu16(levels.get_data(), 50) as f32; Ok([r * 508.0 * 1.078 / 65536.0, 1.0, b * 382.0 * 1.173 / 65536.0, f32::NAN]) } } fn get_blacklevel(&self, cpp: usize) -> Option { if let Some(levels) = self.makernote.get_entry(0x0401) { let levels = [levels.force_u16(0), levels.force_u16(1), levels.force_u16(2), levels.force_u16(3)]; return Some(BlackLevel::new(&levels, self.camera.cfa.width, self.camera.cfa.height, cpp)); } None } } rawler-0.7.1/src/decoders/iiq.rs000064400000000000000000001216711046102023000146440ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2022 Daniel Vogelbacher // // This code & comments are partially a rewrite of librawspeed and dcraw. // Copyright 1997-2016 by Dave Coffin, dcoffin a cybercom o net // Copyright (C) 2009-2014 Klaus Post // Copyright (C) 2014-2015 Pedro Côrte-Real // Copyright (C) 2017-2019 Roman Lebedev // Copyright (C) 2019 Robert Bridge use byteorder::LittleEndian; use byteorder::ReadBytesExt; use log::debug; use log::warn; use serde::Deserialize; use serde::Serialize; use std::collections::HashMap; use std::io::Read; use std::io::Seek; use std::io::SeekFrom; use std::mem::size_of; use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::analyze::FormatDump; use crate::bits::*; use crate::cfa; use crate::decoders::decode_threaded; use crate::decoders::ok_cfa_image_with_blacklevels; use crate::exif::Exif; use crate::formats::tiff; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::reader::TiffReader; use crate::imgop::Point; use crate::imgop::spline::Spline; use crate::lens::LensDescription; use crate::lens::LensResolver; use crate::pixarray::PixU16; use crate::pumps::BitPump; use crate::pumps::BitPumpMSB32; use crate::rawsource::RawSource; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; const MAX_BITDEPTH: u32 = 16; const SV2_USED_CORR: [u32; 8] = [ 3, 3, 3, 3, // 1, 1, 1, 1, ]; const SV2_EXTRA_BITS: [u32; 8] = [ 1, 2, 3, 4, // 0, 0, 0, 0, ]; const SV2_BIT_INDICATOR: [u32; 32] = [ 9, 8, 0, 7, 6, 6, 5, 5, // 1, 1, 1, 1, 4, 4, 4, 4, // 3, 3, 3, 3, 3, 3, 3, 3, // 2, 2, 2, 2, 2, 2, 2, 2, ]; const SV2_SKIP_BITS: [u8; 32] = [ 5, 5, 5, 5, 4, 4, 4, 4, // 3, 3, 3, 3, 3, 3, 3, 3, // 2, 2, 2, 2, 2, 2, 2, 2, // 2, 2, 2, 2, 2, 2, 2, 2, ]; /// Sensor defect information #[allow(unused)] #[derive(Clone, Debug)] struct Defect { row: usize, col: usize, typ: u16, reserved: u16, } /// Flat field correction data. #[derive(Debug, Clone)] struct FlatField { typ: u32, head: [u16; 8], data: Vec, } /// Stuct to hold all known calibration data. struct SensorCalibration { poly_curve_half: Option<[f32; 8]>, poly_curve_full: Option<[f32; 4]>, quadrant_linearization: Option>, quadrant_multipliers: Option<[f32; 19]>, quadrant_combined: Option<([usize; 7], [usize; 7 * 4])>, defects: Option>, flats: Vec, blacklevel: u16, q_blacklevel: Option<(Vec, Vec)>, sensor_margins: (usize, usize), // left, top } /// Known IIQ compression formats #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[allow(non_camel_case_types)] enum IiqCompression { Uncompressed = 0, Raw1 = 1, Raw2 = 2, // L14 IIQ_L = 3, // Like L14 but with nonlinear data which requires curve multiplication IIQ_S = 5, // "IIQ 14 Smart" and "IIQ 14 Sensor+" IIQ_Sv2 = 6, // "IIQ 16 Extended" and "IIQ 16 Large" IIQ_L16 = 8, } impl From for IiqCompression { fn from(v: usize) -> Self { match v { 0 => Self::Uncompressed, 1 => Self::Raw1, 2 => Self::Raw2, 3 => Self::IIQ_L, 5 => Self::IIQ_S, 6 => Self::IIQ_Sv2, 8 => Self::IIQ_L16, _ => panic!("Unsupported IIQ format: {}", v), } } } /// IIQ format encapsulation for analyzer #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct IiqFormat { //tiff: GenericTiffReader, makernotes: IiqMakernotes, } pub type IiqMakernotes = HashMap; #[derive(Debug, Clone)] pub struct IiqDecoder<'a> { camera: Camera, #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, makernotes: IiqMakernotes, } impl<'a> IiqDecoder<'a> { pub fn new(file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { debug!("IIQ decoder choosen"); let camera = rawloader.check_supported(tiff.root_ifd())?; let makernotes = new_makernote(file, 8).map_err(|ioerr| RawlerError::with_io_error("load IIQ makernotes", file.path(), ioerr))?; Ok(IiqDecoder { camera, tiff, rawloader, makernotes, }) } } fn new_makernote(file: &RawSource, moffset: u64) -> std::io::Result> { // All makernote offsets are not absolute to file, but to start of makernote data. // The makernote data starts straight after the TIFF header (8 bytes). // If this may change in future, offsets must be revalidated. assert_eq!(moffset, 8); let stream = &mut file.reader(); stream.seek(SeekFrom::Start(moffset + 8))?; // Skip first 8 bytes of makernote let ifd = stream.read_u32::()? as u64; stream.seek(SeekFrom::Start(moffset + ifd))?; let entry_count = stream.read_u32::()? as usize; // Skip 8 bytes in IFD let _ = stream.read_u32::()?; // Skip it let mut buf = vec![0; entry_count * 16]; stream.read_exact(&mut buf)?; let mut entries: HashMap = HashMap::with_capacity(entry_count); let mut buf = &buf[..]; for _ in 0..entry_count { let tag = LEu32(buf, 0); let typ = LEu32(buf, 4); let byte_count = LEu32(buf, 8) as usize; let data = LEu32(buf, 12) as usize; //println!("Tag 0x{:x}, typ: {}, count: {}, data: {}", tag, typ, byte_count, data); match typ { // Sensor calibration file, it's like a TIFF file and stored with ASCII type 1 if tag == IiqTag::SensorCorrection.into() => { entries.insert(tag, (byte_count, tiff::Value::Long(vec![data as u32 + moffset as u32]))); } // Others should be just ASCII strings 1 => { let mut v = vec![0; byte_count]; stream.seek(SeekFrom::Start(moffset + data as u64))?; // skip header stream.read_exact(&mut v)?; let value = tiff::Value::Ascii(tiff::TiffAscii::new_from_raw(&v)); entries.insert(tag, (byte_count, value)); } // Short values 2 => { entries.insert(tag, (byte_count, tiff::Value::Long(vec![data as u32]))); } // Integer values 4 => { // long entries.insert(tag, (byte_count, tiff::Value::Long(vec![data as u32]))); } _ => { warn!("Unknow tag 0x{:x}, typ: {}, count: {}, data: {}", tag, typ, byte_count, data); } } buf = &buf[16..]; } Ok(entries) } impl<'a> Decoder for IiqDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let fmt = self.compression_mode()?; let wb_offset = self.wb_offset()?; let (width, height) = self.dimension()?; let (data_offset, data_len) = self.data_offset()?; let (strips_offset, strips_len) = if fmt != IiqCompression::Uncompressed { self.strip_offset()? } else { (0, 0) }; debug!("Strips offset: {}", strips_offset); debug!("data offset: {}", data_offset); debug!("RAW IIQ Format: {:?}", fmt); if width == 0 || height == 0 { return Err(RawlerError::DecoderFailed("IIQ: couldn't find width and height".to_string())); } let data = file .subview(data_offset, data_len as u64) .map_err(|ioerr| RawlerError::with_io_error("load IIQ data", file.path(), ioerr))?; let strips = file .subview(strips_offset, strips_len as u64) .map_err(|ioerr| RawlerError::with_io_error("load IIQ strips", file.path(), ioerr))?; let mut image = match fmt { IiqCompression::Raw1 => todo!(), IiqCompression::Raw2 => todo!(), IiqCompression::Uncompressed => Self::decode_uncompressed(data, width, height, 14, dummy), IiqCompression::IIQ_L => Self::decode_compressed(data, strips, width, height, 14, dummy), IiqCompression::IIQ_L16 => Self::decode_compressed(data, strips, width, height, 16, dummy), IiqCompression::IIQ_S => Self::decode_nonlinear(data, strips, width, height, 14, dummy), IiqCompression::IIQ_Sv2 => Self::decode_compressed_sv2(data, strips, width, height, 14, dummy), }; let black = self.blacklevel().unwrap_or(0); log::debug!("Blacklevel: {}", black); if !dummy { let senscorr = self .new_sensor_correction(file, black) .map_err(|ioerr| RawlerError::with_io_error("read IIQ sensor calibration data", file.path(), ioerr))?; self.correct_raw(&mut image, &senscorr)?; } // Reset blacklevel, as the pixels are already scaled by decoder and sensor correction! let blacklevel = [0, 0, 0, 0]; let cpp = 1; let wb = self .get_wb(file, wb_offset) .map_err(|ioerr| RawlerError::with_io_error("read IIQ white balance", file.path(), ioerr))?; ok_cfa_image_with_blacklevels(self.camera.clone(), cpp, wb, blacklevel, image, dummy) } fn format_dump(&self) -> FormatDump { FormatDump::Iiq(IiqFormat { //tiff: self.tiff.clone(), makernotes: self.makernotes.clone(), }) } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; let mdata = RawMetadata::new_with_lens(&self.camera, exif, self.get_lens_description()?.cloned()); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::IIQ } } impl<'a> IiqDecoder<'a> { /// Apply correction information for sensor defects /// Only bad columns are corrected for now. fn correct_raw_defects(&self, img: &mut PixU16, senscorr: &SensorCalibration) -> Result<()> { if let Some(defects) = &senscorr.defects { debug!("Apply defect correction"); for def in defects.iter() { if def.col >= img.width { continue; }; match def.typ { 131 | 137 => { debug!("Correct bad colum: {}", def.col); self.fix_bad_column(img, def); } 129 => { // single bad pixels are ignored, these can be fixed by // hot pixel modules in development process. } _ => { // many unknows... } } } } Ok(()) } /// Apply polynom curve correction for the right side of the sensor. fn correct_raw_poly_half(&self, img: &mut PixU16, senscorr: &SensorCalibration) -> Result<()> { if let Some(poly) = &senscorr.poly_curve_half { debug!("Apply polynom curve half correction"); let split_col = self.split_column()?.expect("Must have split column"); let mut poly = *poly; let sensor_temp = self.sensor_temp()?.expect("Half polynom curve correction requires the sensor temp."); poly[3] += (sensor_temp - poly[7]) * poly[6] + 1.0; let mut curve = vec![0_u16; 0x10000]; for (i, x) in curve.iter_mut().enumerate() { let num = (poly[5] * i as f32 + poly[3]) * i as f32 + poly[1]; *x = clamp(num as i32, 0, 0xffff) as u16; } // Only apply for right side of image for row in img.pixel_rows_mut() { for pix in row.iter_mut().skip(split_col) { *pix = curve[*pix as usize]; } } } Ok(()) } /// Apply polynom curve correction to the full sensor. fn correct_raw_poly_full(&self, img: &mut PixU16, senscorr: &SensorCalibration) -> Result<()> { if let Some(poly) = &senscorr.poly_curve_full { debug!("Apply polynom curve full correction"); let mut curve = vec![0_u16; 0x10000]; for (i, x) in curve.iter_mut().enumerate() { let mut num = 0.0; for p in poly.iter().rev() { num = num * i as f32 + *p; } *x = clamp((num + i as f32) as i32, 0, 0xffff) as u16; } img.for_each(|pix| curve[pix as usize]); } Ok(()) } /// Apply quadrant linerarization correction fn correct_raw_q_linearization(&self, img: &mut PixU16, senscorr: &SensorCalibration) -> Result<()> { if let Some(table) = &senscorr.quadrant_linearization { debug!("Apply quadrant linearization"); let (split_col, split_row) = self.split_offsets()?.expect("Must have split values"); debug!("Split col: {}, row: {}", split_col, split_row); let mut control_points = [[[Point::default(); 19]; 2]; 2]; for qr in 0..2 { for qc in 0..2 { for i in 0..16 { control_points[qr][qc][1 + i].x = table[qr * (2 * 16) + (qc * 16) + i] as usize; } } } for i in 0..16 { let mut v = 0; for qr in 0..2 { for qc in 0..2 { v += control_points[qr][qc][1 + i].x; } } control_points.iter_mut().flatten().for_each(|point| point[1 + i].y = (v + 2) >> 2); } for qr in 0..2 { for qc in 0..2 { let cp = &mut control_points[qr][qc]; // Some images may overflow 65535 here, but it's also in dcraw... // We clamp here to be <= then the final control point. cp[17].x = clamp(((cp[16].y * 65535) / cp[16].x) as i32, 0, 65535) as usize; cp[17].y = cp[17].x; cp[18] = Point::new(65535, 65535); let curve = Spline::new(cp).calculate_curve(); let (start_row, end_row) = if qr > 0 { (split_row, img.height) } else { (0, split_row) }; let (start_col, end_col) = if qc > 0 { (split_col, img.width) } else { (0, split_col) }; for row in start_row..end_row { for col in start_col..end_col { let pix = img.at_mut(row, col); *pix = clamp(curve[*pix as usize] as i32, 0, 0xffff) as u16; } } } } } Ok(()) } /// Apply quadrant multipliers correction fn correct_raw_q_mul(&self, img: &mut PixU16, senscorr: &SensorCalibration) -> Result<()> { if let Some(multipliers) = &senscorr.quadrant_multipliers { debug!("Apply quadrant multiplier correction"); let (split_col, split_row) = self.split_offsets()?.expect("Must have split values"); debug!("Split col: {}, row: {}", split_col, split_row); let mut qmul = [[f32::NAN; 2]; 2]; qmul[0][0] = 1.0 + multipliers[4]; qmul[0][1] = 1.0 + multipliers[10]; qmul[1][0] = 1.0 + multipliers[14]; qmul[1][1] = 1.0 + multipliers[18]; img.for_each_index(|pix, row, col| { let qr = if row >= split_row { 1 } else { 0 }; let qc = if col >= split_col { 1 } else { 0 }; let x = qmul[qr][qc] * (pix as f32); clamp(x as i32, 0, 0xffff) as u16 }); } Ok(()) } /// Apply quadrant combined spline curve correction fn correct_raw_q_combined(&self, img: &mut PixU16, senscorr: &SensorCalibration) -> Result<()> { if let Some((coord_x, coord_y)) = &senscorr.quadrant_combined { debug!("Apply quadrant combined correction"); let (split_col, split_row) = self.split_offsets()?.expect("Must have split values"); debug!("Split col: {}, row: {}", split_col, split_row); let mut control_points = [[[Point::default(); 1 + 7 + 1]; 2]; 2]; // 7 points + start & end for qr in 0..2 { for qc in 0..2 { // we already have a 0 point at [0] by default initialization for i in 0..7 { control_points[qr][qc][1 + i].x = coord_x[i]; control_points[qr][qc][1 + i].y = (coord_x[i] * coord_y[qr * (2 * 7) + (qc * 7) + i] as usize) / 10_000; } control_points[qr][qc][8] = Point::new(65535, 65535); } } for qr in 0..2 { for qc in 0..2 { let cp = &mut control_points[qr][qc]; //for i in 0..9 { // println!("X: {}", cp[i].x); // //println!("Y: {}", cp[i].y); //} let curve = Spline::new(cp).calculate_curve(); let (start_row, end_row) = if qr > 0 { (split_row, img.height) } else { (0, split_row) }; let (start_col, end_col) = if qc > 0 { (split_col, img.width) } else { (0, split_col) }; for row in start_row..end_row { for col in start_col..end_col { let pix = img.at_mut(row, col); *pix = curve[*pix as usize]; } } } } } Ok(()) } /// Apply flat field correction fn correct_raw_flatfield(&self, img: &mut PixU16, senscorr: &SensorCalibration) -> Result<()> { // Map the second green (on odd rows) to color 3 let cfa = self .camera .cfa .map_colors(|row, _col, color| if (color as usize) == cfa::CFA_COLOR_G && (row & 1 == 1) { 3 } else { color }); for flat in senscorr.flats.iter() { let nc = match flat.typ { 0x401 => { debug!("Apply all-color flat field correction 0x{:x} HEAD: {:?}", flat.typ, flat.head); 2 } 0x410 | 0x416 => { debug!("Apply all-color flat field correction 0x{:x} HEAD: {:?}", flat.typ, flat.head); 2 } 0x40b => { debug!("Apply red-blue flat field correction 0x{:x} HEAD: {:?}", flat.typ, flat.head); 4 } _ => { panic!("Unsupported flat field typ"); } }; let mut head: [usize; 8] = Default::default(); for (i, entry) in flat.head.iter().enumerate() { head[i] = *entry as usize; } if head[2] * head[3] * head[4] * head[5] == 0 { continue; }; let wide: usize = head[2] / head[4] + ((head[2] % head[4] != 0) as usize); let high: usize = head[3] / head[5] + ((head[3] % head[5] != 0) as usize); let mut mrow = vec![0.0; nc * wide]; let mut pump = flat.data.iter(); let mut mult = [0.0; 4]; // One multiplier per color (R=0, G1=1, ...) for y in 0..high { for x in 0..wide { for c in (0..nc).step_by(2) { let num = *pump.next().expect("flat field correction data consumed but tried to get more"); if y == 0 { mrow[c * wide + x] = num; } else { mrow[(c + 1) * wide + x] = (num - mrow[c * wide + x]) / head[5] as f32; } } } if y == 0 { continue; }; let rend = head[1] + y * head[5]; let mut row = rend - head[5]; while row < img.height && row < rend && row < head[1] + head[3] - head[5] { for x in 1..wide { for c in (0..nc).step_by(2) { mult[c] = mrow[c * wide + x - 1]; mult[c + 1] = (mrow[c * wide + x] - mult[c]) / head[4] as f32; } let cend = head[0] + x * head[4]; let mut col = cend - head[4]; while col < img.width && col < cend && col < head[0] + head[2] - head[4] { let color = if nc > 2 { debug_assert!(row >= senscorr.sensor_margins.1); debug_assert!(col >= senscorr.sensor_margins.0); cfa.color_at(row - senscorr.sensor_margins.1, col - senscorr.sensor_margins.0) } else { 0 // match all colors }; // This matches for R (0) and B (2), not for G1 (1) and G2 (3) if (color & 1) == 0 { let pix = *img.at(row, col) as f32 * mult[color]; *img.at_mut(row, col) = clamp(pix as i32, 0, 65535) as u16; } for c in (0..nc).step_by(2) { mult[c] += mult[c + 1]; } col += 1; } // end while } for x in 0..wide { for c in (0..nc).step_by(2) { mrow[c * wide + x] += mrow[(c + 1) * wide + x]; } } row += 1; } } } Ok(()) } /// Apply raw sensor corrections fn correct_raw_blacklevel(&self, img: &mut PixU16, calib: &SensorCalibration) -> Result<()> { // Remove black level and ajdust individual row/col blacklevel if let Some(q_blacklevel) = &calib.q_blacklevel { let black = calib.blacklevel as i32; let (split_col, split_row) = self.split_offsets()?.expect("Must have split values"); let (cblack, rblack) = q_blacklevel; debug_assert_eq!(cblack.len(), img.height * 2); debug_assert_eq!(rblack.len(), img.width * 2); img.for_each_index(|pix, row, col| { let qr = if row >= split_row { 1 } else { 0 }; let qc = if col >= split_col { 1 } else { 0 }; let x = pix as i32 - black + (cblack[row * 2 + qc] as i32) + (rblack[col * 2 + qr] as i32); clamp(x, 0, 0xffff) as u16 }); } else { log::debug!("No q_blacklevel correction available, just apply basic blacklevel correction"); img.for_each(|pix| clamp(pix as i32 - calib.blacklevel as i32, 0, 0xffff) as u16); } Ok(()) } /// Apply raw sensor corrections fn correct_raw(&self, img: &mut PixU16, calib: &SensorCalibration) -> Result<()> { self.correct_raw_blacklevel(img, calib)?; self.correct_raw_poly_half(img, calib)?; self.correct_raw_poly_full(img, calib)?; self.correct_raw_q_mul(img, calib)?; self.correct_raw_q_combined(img, calib)?; self.correct_raw_q_linearization(img, calib)?; self.correct_raw_defects(img, calib)?; self.correct_raw_flatfield(img, calib)?; Ok(()) } fn dimension(&self) -> Result<(usize, usize)> { let width = self.makernotes.get(&IiqTag::Width.into()); let height = self.makernotes.get(&IiqTag::Height.into()); match (width, height) { (Some(width), Some(height)) => Ok(( width.1.force_usize(0), // height.1.force_usize(0), )), _ => Err(RawlerError::DecoderFailed("Unable to find width/height in IIQ makernotes".to_string())), } } fn sensor_margins(&self) -> Option<(usize, usize)> { let left = self.makernotes.get(&IiqTag::MarginLeft.into()); let top = self.makernotes.get(&IiqTag::MarginTop.into()); match (left, top) { (Some(left), Some(top)) => Some(( left.1.force_usize(0), // top.1.force_usize(0), // )), _ => { warn!("Unable to find sensor margins in IIQ makernotes"); None } } } fn sensor_temp(&self) -> Result> { let sensor_temp = self.makernotes.get(&IiqTag::SensorTemperature1.into()); if let Some((_, data)) = sensor_temp { let x = data.force_u32(0); let flt = f32::from_bits(x); debug!("Sensor temp: {}", flt); return Ok(Some(flt)); } Ok(None) } fn split_column(&self) -> Result> { let split_col = self.makernotes.get(&IiqTag::SplitCol.into()); match split_col { Some(col) => Ok(Some(col.1.force_usize(0))), _ => Ok(None), } } fn split_offsets(&self) -> Result> { let split_col = self.makernotes.get(&IiqTag::SplitCol.into()); let split_row = self.makernotes.get(&IiqTag::SplitRow.into()); match (split_col, split_row) { (Some(col), Some(row)) => Ok(Some((col.1.force_usize(0), row.1.force_usize(0)))), _ => Ok(None), } } fn split_blacks(&self, file: &RawSource) -> std::io::Result, Vec)>> { let black_col = self.makernotes.get(&IiqTag::BlackCol.into()); let black_row = self.makernotes.get(&IiqTag::BlackRow.into()); match (black_col, black_row) { (Some(black_col), Some(black_row)) => { let stream = &mut file.reader(); let (len, offset) = (black_col.0, black_col.1.force_u64(0)); stream.seek(SeekFrom::Start(offset + 8))?; let mut cols = vec![0; len / 2]; // u16 size for entry in cols.iter_mut() { *entry = stream.read_i16::()?; } let (len, offset) = (black_row.0, black_row.1.force_u64(0)); stream.seek(SeekFrom::Start(offset + 8))?; let mut rows = vec![0; len / 2]; // u16 size for entry in rows.iter_mut() { *entry = stream.read_i16::()?; } Ok(Some((cols, rows))) } _ => Ok(None), } } fn compression_mode(&self) -> Result { match self.makernotes.get(&IiqTag::Format.into()) { Some(mode) => { let code = mode.1.force_u32(0); Ok(IiqCompression::from(code as usize)) } _ => Err(RawlerError::DecoderFailed("Unable to find compression mode in IIQ makernotes".to_string())), } } fn data_offset(&self) -> Result<(u64, usize)> { match self.makernotes.get(&IiqTag::DataOffset.into()) { Some(mode) => Ok(( (mode.1.force_u64(0) + 8), // mode.0, )), _ => Err(RawlerError::DecoderFailed("Unable to find data offset in IIQ makernotes".to_string())), } } fn strip_offset(&self) -> Result<(u64, usize)> { match self.makernotes.get(&IiqTag::StripOffset.into()) { Some(mode) => Ok(( (mode.1.force_u64(0) + 8), // mode.0, )), _ => Err(RawlerError::DecoderFailed("Unable to find strip offset in IIQ makernotes".to_string())), } } fn wb_offset(&self) -> Result { match self.makernotes.get(&IiqTag::WhiteBalance.into()) { Some(mode) => Ok((mode.1.force_u64(0) + 8) as u64), _ => Err(RawlerError::DecoderFailed("Unable to find whitebalance offset in IIQ makernotes".to_string())), } } fn blacklevel(&self) -> Result { match self.makernotes.get(&IiqTag::BlackLevel.into()) { Some(mode) => Ok(mode.1.force_u16(0)), _ => Err(RawlerError::DecoderFailed("Unable to find lacklevel in IIQ makernotes".to_string())), } } #[allow(unused)] fn camera_model(&self) -> Result> { match self.makernotes.get(&IiqTag::CameraModel.into()) { Some(model) => Ok(model.1.as_string()), _ => Ok(None), } } fn lens_model(&self) -> Result> { match self.makernotes.get(&IiqTag::LensModel.into()) { Some(model) => Ok(model.1.as_string()), _ => Ok(None), } } fn new_sensor_correction(&self, file: &RawSource, blacklevel: u16) -> std::io::Result { let q_blacklevel = self.split_blacks(file)?; let sensor_margins = self.sensor_margins().unwrap_or((0, 0)); match self.makernotes.get(&IiqTag::SensorCorrection.into()) { Some((_len, offset)) => { let offset = offset.force_u64(0); debug!("Sensor correction data offset: {}", offset); let mut stream = file.reader(); stream.seek(SeekFrom::Start(offset + 8))?; let bytes_to_entries = stream.read_u32::()? as u64; stream.seek(SeekFrom::Start(offset + bytes_to_entries))?; let entries_count = stream.read_u32::()? as usize; stream.seek(SeekFrom::Current(4))?; // skip 4 bytes let mut poly_curve_half = None; let mut poly_curve_full = None; let mut quadrant_linearization = None; let mut quadrant_multipliers = None; let mut quadrant_combined = None; let mut defects = None; let mut flats = Vec::new(); //println!("Entry count:{}", entries_count); for _ in 0..entries_count { let tag = stream.read_u32::()?; let len = stream.read_u32::()?; let tag_offset = stream.read_u32::()? as u64; //println!("Tag 0x{:x}, count: {}, data: {}", tag, len, tag_offset); let stream_pos = stream.stream_position()?; match tag { 0x0400 => { stream.seek(SeekFrom::Start(offset + tag_offset))?; assert_eq!(len % 4, 0); let mut defect_list = Vec::new(); for _ in 0..(len / 4) { let col = stream.read_u16::()? as usize; let row = stream.read_u16::()? as usize; let typ = stream.read_u16::()?; let reserved = stream.read_u16::()?; //println!("Defect: col: {}, row: {}, typ: {}, res: {}", col, row, typ, reserved); defect_list.push(Defect { col, row, typ, reserved }); } defects = Some(defect_list); } 0x401 | 0x410 | 0x416 | 0x40b => { debug!("Found flat field correction: 0x{:x}", tag); stream.seek(SeekFrom::Start(offset + tag_offset))?; let mut head = [0; 8]; let mut data = Vec::new(); for entry in head.iter_mut() { *entry = stream.read_u16::()?; } if tag == 0x401 { for _ in (8..(len)).step_by(size_of::()) { data.push(stream.read_f32::()?); } } else { for _ in (8..(len)).step_by(size_of::()) { data.push(stream.read_u16::()? as f32 / 32768.0); } } flats.push(FlatField { typ: tag, head, data }); } 0x0419 => { stream.seek(SeekFrom::Start(offset + tag_offset))?; assert!(len as usize >= 8 * size_of::()); let mut data = [f32::NAN; 8]; for entry in data.iter_mut() { *entry = stream.read_f32::()?; } poly_curve_half = Some(data); } 0x041a => { stream.seek(SeekFrom::Start(offset + tag_offset))?; assert_eq!(len as usize, 4 * size_of::()); let mut data = [f32::NAN; 4]; for entry in data.iter_mut() { *entry = stream.read_f32::()?; } poly_curve_full = Some(data); } 0x041f => { stream.seek(SeekFrom::Start(offset + tag_offset))?; assert_eq!(len as usize, 2 * 2 * 16 * size_of::() + 4); // there is an extra value... let mut data = vec![0_u16; 2 * 2 * 16]; for entry in data.iter_mut() { *entry = stream.read_u32::()? as u16; } quadrant_linearization = Some(data); } 0x041e => { stream.seek(SeekFrom::Start(offset + tag_offset))?; let mut data = [f32::NAN; 19]; for entry in data.iter_mut() { *entry = stream.read_f32::()?; } quadrant_multipliers = Some(data); } 0x0431 => { stream.seek(SeekFrom::Start(offset + tag_offset))?; let mut x_coords = [0; 7]; for coord in x_coords.iter_mut() { *coord = stream.read_u32::()? as usize; } let mut y_coords = [0; 7 * 4]; for coord in y_coords.iter_mut() { *coord = stream.read_u32::()? as usize; } quadrant_combined = Some((x_coords, y_coords)); } _ => {} } stream.seek(SeekFrom::Start(stream_pos))?; // restore } Ok(SensorCalibration { poly_curve_half, poly_curve_full, quadrant_linearization, quadrant_multipliers, quadrant_combined, defects, flats, blacklevel, q_blacklevel, sensor_margins, }) } _ => panic!("No sensor calibration data found."), } } fn fix_bad_column(&self, img: &mut PixU16, defect: &Defect) { let col = defect.col; for row in 2..img.height - 2 { match self.camera.cfa.color_at(row, col) { cfa::CFA_COLOR_G => { // Do green pixels. Let's pretend we are in "G" pixel, in the middle: // G=G // BGB // G0G // We accumulate the values 4 "G" pixels form diagonals, then check which // of 4 values is most distant from the mean of those 4 values, subtract // it from the sum, average (divide by 3) and round to nearest int. let mut max = 0; let mut val = [0_u16; 4]; let mut dev = [0_i32; 4]; val[0] = *img.at(row - 1, col - 1); val[1] = *img.at(row + 1, col - 1); val[2] = *img.at(row - 1, col + 1); val[3] = *img.at(row + 1, col + 1); let sum: i32 = val.iter().map(|x| *x as i32).sum(); for (i, v) in val.iter().enumerate() { dev[i] = (((*v as i32) * 4_i32) - sum).abs(); if dev[max] < dev[i] { max = i; } } let three_pixels = sum - val[max] as i32; debug_assert!(three_pixels >= 0); *img.at_mut(row, col) = ((three_pixels + 1) / 3) as u16; //image[row * width + col] = ((three_pixels + 1) / 3) as u16; } cfa::CFA_COLOR_R | cfa::CFA_COLOR_B => { // Do non-green pixels. Let's pretend we are in "R" pixel, in the middle: // RG=GR // GB=BG // RGRGR // GB0BG // RG0GR // We have 6 other "R" pixels - 2 by horizontal, 4 by diagonals. // We need to combine them, to get the value of the pixel we are in. let diags = *img.at(row + 2, col - 2) as u32 + // 1 *img.at(row - 2, col - 2) as u32 + // 2 *img.at(row + 2, col + 2) as u32 + // 3 *img.at(row - 2, col + 2) as u32; // 4 let horiz: u32 = *img.at(row, col - 2) as u32 + *img.at(row, col + 2) as u32; // But this is not just averaging, we bias towards the horizontal pixels. *img.at_mut(row, col) = (diags as f32 * 0.0732233 + horiz as f32 * 0.3535534).round() as u16; } _ => { panic!("Other colors should not appear here"); } } } } /// Extract white balance parameters fn get_wb(&self, file: &RawSource, wb_offset: u64) -> std::io::Result<[f32; 4]> { let buffer = file.subview(wb_offset, 3 * 4)?; Ok([LEf32(buffer, 0), LEf32(buffer, 4), LEf32(buffer, 8), f32::NAN]) } /// Get lens description by analyzing TIFF tags and makernotes fn get_lens_description(&self) -> Result> { match self.lens_model()? { Some(model) => { let resolver = LensResolver::new() .with_mounts(&[String::from("phaseone")]) .with_lens_keyname(Some(model)) .with_camera(&self.camera); Ok(resolver.resolve()) } None => Ok(None), } } /// Decode IIQ S format /// Same as IIQ L, but requires a linearization curve fn decode_nonlinear(buffer: &[u8], strips: &[u8], width: usize, height: usize, bits: u8, dummy: bool) -> PixU16 { // We fake the bit count as 16, then no shift happens in decoding. // Then we can linearize back the data. let mut img = Self::decode_compressed(buffer, strips, width, height, 16, dummy); let value_shift: u32 = MAX_BITDEPTH - (bits as u32); if !dummy { let mut curve: [u16; 256] = [0; 256]; for (i, out) in curve.iter_mut().enumerate() { *out = (i as f32 * i as f32 / 3.969 + 0.5) as u16; } // For IIQ_S format, data is 8 bit and non-linear. // Use the linearization curve to get back original data. img.for_each(|pix| if pix < 256 { curve[pix as usize] << value_shift } else { pix }); } img } /// Decoder for IIQ uncompressed fn decode_uncompressed(buffer: &[u8], width: usize, height: usize, bits: u8, dummy: bool) -> PixU16 { let value_shift: u32 = MAX_BITDEPTH - (bits as u32); decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { for (i, word) in out.iter_mut().enumerate() { *word = LEu16(buffer, row * (width * 2) + i * 2) << value_shift; } }), ) } /// Decoder for IIQ L / S data pub(crate) fn decode_compressed(buffer: &[u8], strips: &[u8], width: usize, height: usize, bits: u8, dummy: bool) -> PixU16 { let value_shift: u32 = MAX_BITDEPTH - (bits as u32); let lens: [u32; 10] = [8, 7, 6, 9, 11, 10, 5, 12, 14, 13]; decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let offset = LEu32(strips, row * 4) as usize; let mut pump = BitPumpMSB32::new(&buffer[offset..]); let mut pred = [0_u32; 2]; let mut len = [0_u32; 2]; for (col, pixout) in out.chunks_exact_mut(1).enumerate() { if col >= (width & 0xfffffff8) { len[0] = 14; len[1] = 14; } else if col & 7 == 0 { for i in 0..2 { let mut j: usize = 0; while j < 5 && pump.get_bits(1) == 0 { j += 1 } if j > 0 { len[i] = lens[(j - 1) * 2 + pump.get_bits(1) as usize]; } } } let i = len[col & 1]; pred[col & 1] = if i == 14 { pump.get_bits(16) } else { pred[col & 1] + pump.get_bits(i) + 1 - (1 << (i - 1)) }; pixout[0] = (pred[col & 1] as u16) << value_shift; } }), ) } /// Decoder for IIQ S v2 /// This compression stores row pixels in clusters of 8 pixels. fn decode_compressed_sv2(buffer: &[u8], strips: &[u8], width: usize, height: usize, bits: u8, dummy: bool) -> PixU16 { // Correction shift for pixel values let value_shift: u32 = MAX_BITDEPTH - (bits as u32); // We can decode each row independently decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let offset = LEu32(strips, row * 4) as usize; let mut pump = BitPumpMSB32::new(&buffer[offset..]); let base_bits = pump.get_bits(16) & 7; // first 3 bits let mut bit_check: [u32; 2] = [0, 0]; // for even and odd pixels let mut prev_pix_value = [0, 0]; // for even and odd pixels let pix_sub_init = 17 - base_bits; for cluster in out.chunks_mut(8) { // When we have a full cluster with 8 possible pixels if cluster.len() == 8 { // Initialize the bit_check values for even and odd. for i in 0..bit_check.len() { let idx = pump.peek_bits(7) as usize; pump.consume_bits(2); if idx >= 32 { // If idx is larger then lookup array, the value // is calculated by re-using the previous value. bit_check[i] = (idx as u32 >> 5) + bit_check[i] - 2; } else { // Otherwise, just do a lookup. debug_assert!(idx < 32); bit_check[i] = SV2_BIT_INDICATOR[idx]; pump.consume_bits(SV2_SKIP_BITS[idx] as u32); } } let pump_savepoint = pump; // savepoint for error recovery let x = pump.peek_bits(3) as usize; // 3 bits are max 7, so it's safe as array index pump.consume_bits(SV2_USED_CORR[x]); let nbits = base_bits + SV2_EXTRA_BITS[x]; let corr = [ bit_check[0].saturating_sub(SV2_EXTRA_BITS[x]), // even bit_check[1].saturating_sub(SV2_EXTRA_BITS[x]), // odd ]; let diff = [ 0xFFFF_u32 >> (pix_sub_init - bit_check[0]), // even 0xFFFF_u32 >> (pix_sub_init - bit_check[1]), // odd ]; // Detector for invalid decompression result let mut check_val = 0; // decompress cluster for i in 0..8 { let value = if bit_check[i & 1] == 9 { // Just get the value straight out the bit pump pump.get_bits(14) } else { // Otherwise reconstruct the value let tmp = prev_pix_value[i & 1] + (pump.get_bits(nbits) << corr[i & 1]) - diff[i & 1]; check_val |= tmp; // Apply to checker tmp }; cluster[i] = (value as u16) << value_shift; prev_pix_value[i & 1] = value; } // Check for decompressor errors if (check_val & ((1 << 14) - 1)) != check_val { warn!("Error in IIQ Sv2 decompressor, run error recovery"); // restore pump pump = pump_savepoint; for i in 0..8 { let value = if bit_check[i & 1] == 9 { // Just get the value straight out the bit pump pump.get_bits(14) } else { // Otherwise reconstruct the value let tmp = prev_pix_value[i & 1] as i32 + (pump.get_bits(nbits) << corr[i & 1]) as i32 - diff[i & 1] as i32; clamp(tmp as i32, 0, 0x3FFF) as u32 }; cluster[i] = (value as u16) << value_shift; prev_pix_value[i & 1] = value; } } } else { // Not a full cluster, just take the full values from the bit pump for pix in cluster.iter_mut() { *pix = (pump.get_bits(14) as u16) << value_shift; } } } }), ) } } #[allow(unused)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)] enum IiqTag { WhiteBalance = 0x107, Width = 0x108, Height = 0x109, MarginLeft = 0x10a, MarginTop = 0x10b, ImageWidth = 0x10c, ImageHeight = 0x10d, Format = 0x10e, DataOffset = 0x10f, SensorCorrection = 0x110, SensorTemperature1 = 0x210, SensorTemperature2 = 0x211, StripOffset = 0x21c, BlackLevel = 0x21d, SplitCol = 0x222, BlackCol = 0x223, SplitRow = 0x224, BlackRow = 0x225, CameraModel = 0x410, LensModel = 0x412, } impl From for u32 { fn from(v: IiqTag) -> Self { v as u32 } } rawler-0.7.1/src/decoders/kdc.rs000064400000000000000000000173231046102023000146210ustar 00000000000000use log::warn; use crate::RawImage; use crate::RawLoader; use crate::RawSource; use crate::RawlerError; use crate::Result; use crate::alloc_image; use crate::alloc_image_ok; use crate::analyze::FormatDump; use crate::bits::BEu16; use crate::exif::Exif; use crate::formats::tiff::Entry; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::IFD; use crate::formats::tiff::Value; use crate::formats::tiff::ifd::OffsetMode; use crate::formats::tiff::reader::TiffReader; use crate::packed::decode_12be; use crate::pixarray::PixU16; use crate::tags::ExifTag; use crate::tags::TiffCommonTag; use super::CFAConfig; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use super::RawPhotometricInterpretation; use super::WhiteLevel; use super::ok_cfa_image; #[derive(Debug, Clone)] pub struct KdcDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, makernote: Option, camera: Camera, } impl<'a> KdcDecoder<'a> { pub fn new(file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { let camera = rawloader.check_supported(tiff.root_ifd())?; let makernote = if let Some(exif) = tiff.find_first_ifd_with_tag(ExifTag::MakerNotes) { exif.parse_makernote(&mut file.reader(), OffsetMode::Absolute, &[])? } else { warn!("KDC makernote not found"); None }; Ok(KdcDecoder { tiff, rawloader, camera, makernote, }) } } impl<'a> Decoder for KdcDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { if self.camera.clean_model == "DC120" { let width = 848; let height = 976; let raw = self.tiff.find_ifds_with_tag(TiffCommonTag::CFAPattern)[0]; let off = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); let mut white = self.camera.whitelevel.clone().expect("KDC needs a whitelevel in camera config")[0]; let src = file.subview_until_eof(off as u64)?; let image = match fetch_tiff_tag!(raw, TiffCommonTag::Compression).force_usize(0) { 1 => Self::decode_dc120(src, width, height, dummy), 7 => { white = 0xFF << 1; Self::decode_dc120_jpeg(src, width, height, dummy)? } c => { return Err(RawlerError::unsupported( &self.camera, format!("KDC: DC120: Don't know how to handle compression type {}", c), )); } }; let cpp = 1; let whitelevel = Some(WhiteLevel::new(vec![white; cpp])); let photometric = RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&self.camera)); let img = RawImage::new(self.camera.clone(), image, cpp, [1.0, 1.0, 1.0, f32::NAN], photometric, None, whitelevel, dummy); return Ok(img); } if self.camera.clean_model == "DC50" { let raw = self.tiff.find_ifds_with_tag(TiffCommonTag::CFAPattern)[0]; let width = self.camera.raw_width; let height = self.camera.raw_height; let off = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); let white = self.camera.whitelevel.clone().expect("KDC needs a whitelevel in camera config")[0]; let cbpp = match raw.get_entry(ExifTag::CompressedBitsPerPixel) { Some(Entry { value: Value::Rational(data), .. }) if data[0].n == 243 => 2, _ => 3, }; let src = file.subview_until_eof_padded(off as u64)?; let image = crate::decompressors::radc::decompress(&src, width, height, cbpp, dummy)?; let cpp = 1; let whitelevel = Some(WhiteLevel::new(vec![white; cpp])); let photometric = RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&self.camera)); let img = RawImage::new(self.camera.clone(), image, cpp, [1.0, 1.0, 1.0, f32::NAN], photometric, None, whitelevel, dummy); return Ok(img); } let raw = self .tiff .find_first_ifd_with_tag(TiffCommonTag::KdcWidth) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with KdcWidth tag")))?; let width = fetch_tiff_tag!(raw, TiffCommonTag::KdcWidth).force_usize(0) + 80; let height = fetch_tiff_tag!(raw, TiffCommonTag::KdcLength).force_usize(0) + 70; let offset = fetch_tiff_tag!(raw, TiffCommonTag::KdcOffset); if offset.count() < 13 { panic!("KDC Decoder: Couldn't find the KDC offset"); } let mut off = offset.force_usize(4) + offset.force_usize(12); // Offset hardcoding gotten from dcraw if self.camera.find_hint("easyshare_offset_hack") { off = if off < 0x15000 { 0x15000 } else { 0x17000 }; } let src = file.subview_until_eof(off as u64)?; let image = decode_12be(src, width, height, dummy); let cpp = 1; ok_cfa_image(self.camera.clone(), cpp, self.get_wb()?, image, dummy) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; let mdata = RawMetadata::new(&self.camera, exif); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::KDC } } impl<'a> KdcDecoder<'a> { fn get_wb(&self) -> Result<[f32; 4]> { if let Some(makernote) = self.makernote.as_ref() { match makernote.get_entry(TiffCommonTag::KdcWB) { Some(levels) => { if levels.count() != 3 { Err(format!("KDC: Levels count is off: {}", levels.count()).into()) } else { Ok([levels.force_f32(0), levels.force_f32(1), levels.force_f32(2), f32::NAN]) } } None => { let levels = fetch_tiff_tag!(makernote, TiffCommonTag::KodakWB); if ![734, 1502, 1512, 2288].contains(&levels.count()) { Err(format!("KDC: Levels count is off: {}", levels.count()).into()) } else { let r = BEu16(levels.get_data(), 148) as f32; let b = BEu16(levels.get_data(), 150) as f32; Ok([r / 256.0, 1.0, b / 256.0, f32::NAN]) } } } } else { Ok([f32::NAN, f32::NAN, f32::NAN, f32::NAN]) } } pub(crate) fn decode_dc120(src: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { let mut out = alloc_image!(width, height, dummy); let mul: [usize; 4] = [162, 192, 187, 92]; let add: [usize; 4] = [0, 636, 424, 212]; for row in 0..height { let shift = row * mul[row & 3] + add[row & 3]; for col in 0..width { out[row * width + col] = src[row * width + ((col + shift) % 848)] as u16; } } out } pub(crate) fn decode_dc120_jpeg(src: &[u8], width: usize, height: usize, dummy: bool) -> Result { let mut out = alloc_image_ok!(width, height, dummy); let swapped_src: Vec = src.chunks_exact(2).flat_map(|x| [x[1], x[0]]).collect(); let img = image::load_from_memory_with_format(&swapped_src, image::ImageFormat::Jpeg) .map_err(|err| RawlerError::DecoderFailed(format!("Failed to read JPEG image: {:?}", err)))?; assert_eq!(width, img.width() as usize); assert_eq!(height, img.height() as usize * 2); let buf = img.as_flat_samples_u8().unwrap(); let jpeg = buf.as_slice(); for irow in 0..img.height() as usize { let row = irow * 2; let iline = &jpeg[irow * width * 3..]; for col in (0..width).step_by(2) { *out.at_mut(row + 0, col + 0) = (iline[col * 3 + 1] as u16) << 1; *out.at_mut(row + 1, col + 1) = (iline[(col + 1) * 3 + 1] as u16) << 1; *out.at_mut(row + 0, col + 1) = (iline[col * 3 + 0]) as u16 + (iline[(col + 1) * 3 + 0]) as u16; *out.at_mut(row + 1, col + 0) = (iline[col * 3 + 2]) as u16 + (iline[(col + 1) * 3 + 2]) as u16; } } Ok(out) } } rawler-0.7.1/src/decoders/mef.rs000064400000000000000000000037471046102023000146340ustar 00000000000000use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::analyze::FormatDump; use crate::exif::Exif; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::reader::TiffReader; use crate::packed::decode_12be; use crate::rawsource::RawSource; use crate::tags::TiffCommonTag; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use super::ok_cfa_image; #[derive(Debug, Clone)] pub struct MefDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, camera: Camera, } impl<'a> MefDecoder<'a> { pub fn new(_file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { let camera = rawloader.check_supported(tiff.root_ifd())?; Ok(MefDecoder { tiff, rawloader, camera }) } } impl<'a> Decoder for MefDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let raw = &self .tiff .find_first_ifd_with_tag(TiffCommonTag::CFAPattern) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with CFAPattern tag")))?; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let offset = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); let src = file.subview_until_eof(offset as u64)?; let image = decode_12be(src, width, height, dummy); let cpp = 1; ok_cfa_image(self.camera.clone(), cpp, [f32::NAN, f32::NAN, f32::NAN, f32::NAN], image, dummy) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, __params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; let mdata = RawMetadata::new(&self.camera, exif); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::MEF } } rawler-0.7.1/src/decoders/mod.rs000064400000000000000000001146361046102023000146440ustar 00000000000000use chrono::FixedOffset; use chrono::NaiveDateTime; use chrono::TimeZone; use image::DynamicImage; use image::ImageBuffer; use image::Luma; use image::Rgb; use log::debug; use log::warn; use multiversion::multiversion; use rayon::iter::IndexedParallelIterator; use rayon::iter::ParallelIterator; use rayon::prelude::*; use rayon::slice::ParallelSliceMut; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::hash::Hash; use std::panic; use std::panic::AssertUnwindSafe; use std::path::Path; use std::rc::Rc; use std::str::FromStr; use std::sync::Arc; use std::time::SystemTime; use zerocopy::IntoBytes; use crate::Result; use crate::alloc_image_f32_plain; use crate::alloc_image_ok; use crate::alloc_image_plain; use crate::analyze::FormatDump; use crate::bits::LEu32; use crate::bits::LookupTable; use crate::bits::scale_u16; use crate::decompressors::Decompressor; use crate::decompressors::LineIteratorMut; use crate::decompressors::deflate::DeflateDecompressor; use crate::decompressors::jpeg::JpegDecompressor; use crate::decompressors::jpeg::LJpegDecompressor; use crate::decompressors::jpegxl::JpegXLDecompressor; use crate::decompressors::packed::PackedDecompressor; use crate::exif::Exif; use crate::formats::ciff; use crate::formats::jfif; use crate::formats::tiff::CompressionMethod; use crate::formats::tiff::ExtractFromIFD; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::IFD; use crate::formats::tiff::PhotometricInterpretation; use crate::formats::tiff::SampleFormat; use crate::formats::tiff::Value; use crate::formats::tiff::ifd::DataMode; use crate::formats::tiff::reader::TiffReader; use crate::imgop::Dim2; use crate::imgop::Point; use crate::imgop::Rect; use crate::lens::LensDescription; use crate::pixarray::Pix2D; use crate::pixarray::PixF32; use crate::pixarray::PixU16; use crate::pixarray::SubPixel; use crate::pixarray::deinterleave2x2; use crate::rawsource::RawSource; use crate::tags::DngTag; macro_rules! fetch_ciff_tag { ($tiff:expr, $tag:expr) => { $tiff.find_entry($tag).ok_or(format!("Couldn't find tag {}", stringify!($tag)).to_string())? }; } macro_rules! fetch_tiff_tag { ($ifd:expr, $tag:expr) => { $ifd .get_entry($tag) .map(|entry| &entry.value) .ok_or(format!("Couldn't find tag {}", stringify!($tag)))? }; } #[allow(unused_macros)] macro_rules! fetch_tiff_tag_variant { ($ifd:expr, $tag:expr, $variant:path) => { if let $variant(tmp) = $ifd .get_entry($tag) .map(|entry| &entry.value) .ok_or(format!("Couldn't find tag {}", stringify!($tag)))? { tmp } else { return Err(format!("fetch_tiff_tag_variant!(): tag {} has unepxected datatype", stringify!($tag)).into()); } }; } /* macro_rules! fetch_ifd { ($tiff:expr, $tag:expr) => { $tiff .find_first_ifd($tag) .ok_or(format!("Couldn't find ifd with tag {}", stringify!($tag)).to_string())? }; } */ pub mod ari; pub mod arw; mod camera; pub mod cr2; pub mod cr3; pub mod crw; pub mod dcr; pub mod dcs; pub mod dng; pub mod erf; pub mod iiq; pub mod kdc; pub mod mef; pub mod mos; pub mod mrw; pub mod nef; pub mod nkd; pub mod nrw; pub mod orf; pub mod pef; pub mod qtk; pub mod raf; pub mod rw2; pub mod srw; pub mod tfr; mod unwrapped; pub mod x3f; pub use camera::Camera; use crate::RawlerError; use crate::alloc_image; use crate::formats::bmff::Bmff; use crate::tags::ExifTag; use crate::tags::TiffCommonTag; pub use super::rawimage::*; pub static CAMERAS_TOML: &str = include_str!(concat!(env!("OUT_DIR"), "/cameras.toml")); pub static SAMPLE: &str = "\nPlease submit samples at https://raw.pixls.us/"; pub static BUG: &str = "\nPlease file a bug with a sample file at https://github.com/dnglab/dnglab/issues"; const SUPPORTED_FILES_EXT: [&str; 29] = [ "ARI", "ARW", "CR2", "CR3", "CRM", "CRW", "DCR", "DCS", "DNG", "ERF", "IIQ", "KDC", "MEF", "MOS", "MRW", "NEF", "NRW", "ORF", "ORI", "PEF", "RAF", "RAW", "RW2", "RWL", "SRW", "3FR", "FFF", "X3F", "QTK", ]; /// Get list of supported file extensions. All names /// are upper-case. pub fn supported_extensions() -> &'static [&'static str] { &SUPPORTED_FILES_EXT[..] } pub trait Readable: std::io::Read + std::io::Seek {} pub type ReadableBoxed = Box; #[derive(Default, Clone, Debug, Hash, Eq, PartialEq)] pub struct RawDecodeParams { pub image_index: usize, } #[derive(Default, Debug, Clone)] struct DecoderCache where T: Default + Clone, { cache: Arc>>, } impl DecoderCache where T: Default + Clone, { fn new() -> Self { Self::default() } fn get(&self, params: &RawDecodeParams) -> Option { self.cache.read().expect("DecoderCache is poisoned").get(params).cloned() } fn set(&self, params: &RawDecodeParams, value: T) { self.cache.write().expect("DecoderCache is poisoned").insert(params.clone(), value); } } #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub enum WellKnownIFD { Root, Raw, Preview, Exif, ExifGps, VirtualDngRootTags, VirtualDngRawTags, } #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub enum FormatHint { Unknown, CR2, CR3, CRW, NEF, ARW, RAF, RW2, ARI, DNG, DCR, DCS, ERF, IIQ, KDC, MEF, MOS, MRW, NRW, ORF, PEF, QTK, SRW, TFR, X3F, } impl Default for FormatHint { fn default() -> Self { Self::Unknown } } #[derive(Default, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct RawMetadata { pub exif: Exif, pub model: String, pub make: String, pub lens: Option, pub unique_image_id: Option, pub rating: Option, } impl RawMetadata { pub(crate) fn new(camera: &Camera, exif: Exif) -> Self { Self { exif, model: camera.clean_model.clone(), make: camera.clean_make.clone(), unique_image_id: None, lens: None, rating: None, } } pub(crate) fn new_with_lens(camera: &Camera, mut exif: Exif, lens: Option) -> Self { if let Some(lens) = &lens { exif.extend_from_lens(lens); } Self { exif, model: camera.clean_model.clone(), make: camera.clean_make.clone(), unique_image_id: None, lens, rating: None, } } pub fn last_modified(&self) -> Result> { let mtime = self .exif .modify_date .as_ref() .map(|mtime| NaiveDateTime::parse_from_str(mtime, "%Y:%m:%d %H:%M:%S")) .transpose() .map_err(|err| RawlerError::DecoderFailed(err.to_string()))?; if let Some(mtime) = mtime { // Probe for available timezone information let tz = if let Some(offset) = self.exif.timezone_offset.as_ref().and_then(|x| x.get(1)) { if let Some(tz) = FixedOffset::east_opt(*offset as i32 * 3600) { Some(tz) } else { log::warn!("TZ Offset overflow"); None } } else if let Some(offset) = &self.exif.offset_time { match FixedOffset::from_str(offset) { Ok(tz) => Some(tz), Err(err) => { log::warn!("Invalid fixed offset: {}", err); None } } } else { None }; // Any timezone? Then correct... if let Some(tz) = tz { let x = tz .from_local_datetime(&mtime) .earliest() .ok_or(RawlerError::DecoderFailed(format!("Failed to convert datetime to local: {:?}", mtime)))?; return Ok(Some(x.into())); } else { match chrono::Local.from_local_datetime(&mtime).earliest() { Some(ts) => return Ok(Some(ts.into())), None => { log::warn!("Failed to convert ts to local time"); } } } } Ok(None) } } pub trait Decoder: Send { fn raw_image(&self, file: &RawSource, params: &RawDecodeParams, dummy: bool) -> Result; fn raw_image_count(&self) -> Result { Ok(1) } /// Gives the metadata for a Raw. This is not the original data but /// a generalized set of metadata attributes. fn raw_metadata(&self, file: &RawSource, params: &RawDecodeParams) -> Result; fn xpacket(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result>> { Ok(None) } // TODO: extend with decode params for image index fn thumbnail_image(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result> { warn!("Decoder has no thumbnail image support, fallback to preview image"); Ok(None) } // TODO: clarify preview and full image fn preview_image(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result> { warn!("Decoder has no preview image support"); Ok(None) } fn full_image(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result> { warn!("Decoder has no full image support"); Ok(None) } fn format_dump(&self) -> FormatDump; fn ifd(&self, _wk_ifd: WellKnownIFD) -> Result>> { Ok(None) } fn format_hint(&self) -> FormatHint; } /// Possible orientations of an image /// /// Values are taken from the IFD tag Orientation (0x0112) in most cases but they can be /// obtained from other metadata in the file. #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] #[allow(missing_docs)] pub enum Orientation { Normal, HorizontalFlip, Rotate180, VerticalFlip, Transpose, Rotate90, Transverse, Rotate270, Unknown, } impl Orientation { /// Convert a u16 from the IFD tag Orientation (0x0112) into its corresponding /// enum value pub fn from_u16(orientation: u16) -> Orientation { match orientation { 1 => Orientation::Normal, 2 => Orientation::HorizontalFlip, 3 => Orientation::Rotate180, 4 => Orientation::VerticalFlip, 5 => Orientation::Transpose, 6 => Orientation::Rotate90, 7 => Orientation::Transverse, 8 => Orientation::Rotate270, _ => Orientation::Unknown, } } /// Extract orienation from a TiffIFD. If the given TiffIFD has an invalid /// value or contains no orientation data `Orientation::Unknown` is returned fn from_tiff(tiff: &IFD) -> Orientation { match tiff.get_entry(TiffCommonTag::Orientation) { Some(entry) => Orientation::from_u16(entry.force_usize(0) as u16), None => Orientation::Unknown, } } /// Convert orientation to an image flip operation tuple. The first field is /// if x and y coordinates should be swapped (transposed). The second and /// third field is horizontal and vertical flipping respectively. For a /// correct result, flipping must be done before transposing. pub fn to_flips(&self) -> (bool, bool, bool) { match *self { Orientation::Normal | Orientation::Unknown => (false, false, false), Orientation::VerticalFlip => (false, false, true), Orientation::HorizontalFlip => (false, true, false), Orientation::Rotate180 => (false, true, true), Orientation::Transpose => (true, false, false), Orientation::Rotate90 => (true, false, true), Orientation::Rotate270 => (true, true, false), Orientation::Transverse => (true, true, true), } } /// Does the opposite of to_flips() pub fn from_flips(flips: (bool, bool, bool)) -> Self { match flips { (false, false, false) => Orientation::Normal, (false, false, true) => Orientation::VerticalFlip, (false, true, false) => Orientation::HorizontalFlip, (false, true, true) => Orientation::Rotate180, (true, false, false) => Orientation::Transpose, (true, false, true) => Orientation::Rotate90, (true, true, false) => Orientation::Rotate270, (true, true, true) => Orientation::Transverse, } } /// Convert orientation to the Tiff Orientation value pub fn to_u16(&self) -> u16 { match *self { Orientation::Unknown => 0, Orientation::Normal => 1, Orientation::HorizontalFlip => 2, Orientation::Rotate180 => 3, Orientation::VerticalFlip => 4, Orientation::Transpose => 5, Orientation::Rotate90 => 6, Orientation::Transverse => 7, Orientation::Rotate270 => 8, } } } pub(crate) fn ok_cfa_image(camera: Camera, cpp: usize, wb_coeffs: [f32; 4], image: PixU16, dummy: bool) -> Result { assert_eq!(cpp, 1); Ok(RawImage::new( camera.clone(), image, cpp, wb_coeffs, RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&camera)), None, None, dummy, )) } pub(crate) fn ok_cfa_image_with_blacklevels(camera: Camera, cpp: usize, wb_coeffs: [f32; 4], blacks: [u32; 4], image: PixU16, dummy: bool) -> Result { assert_eq!(cpp, 1); let blacklevel = BlackLevel::new(&blacks, camera.cfa.width, camera.cfa.height, cpp); let img = RawImage::new( camera.clone(), image, cpp, wb_coeffs, RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&camera)), Some(blacklevel), None, dummy, ); Ok(img) } /* pub(crate) fn ok_cfa_image_with_black_white(camera: Camera, cpp: usize, wb_coeffs: [f32; 4], black: u32, white: u32, image: PixU16, dummy: bool) -> Result { assert_eq!(cpp, 1); let blacklevel = BlackLevel::new(&vec![black; cpp], 1, 1, cpp); let whitelevel = WhiteLevel::new(vec![white; cpp]); let img = RawImage::new( camera.clone(), image, cpp, wb_coeffs, RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&camera)), Some(blacklevel), Some(whitelevel), dummy, ); Ok(img) } */ pub(crate) fn dynamic_image_from_ifd(ifd: &IFD, rawsource: &RawSource) -> Result { let tiff_width = fetch_tiff_tag!(ifd, TiffCommonTag::ImageWidth).force_usize(0); let tiff_height = fetch_tiff_tag!(ifd, TiffCommonTag::ImageLength).force_usize(0); let cpp = fetch_tiff_tag!(ifd, TiffCommonTag::SamplesPerPixel).force_usize(0); let bits = fetch_tiff_tag!(ifd, TiffCommonTag::BitsPerSample).force_u32(0); let image = plain_image_from_ifd(ifd, rawsource)?; match image { RawImageData::Integer(samples) => match bits { 8 => { let buf: Vec = samples.into_iter().map(|p| p as u8).collect(); match cpp { 1 => Ok(DynamicImage::ImageLuma8( ImageBuffer::, Vec>::from_raw(tiff_width as u32, tiff_height as u32, buf.to_vec()) .ok_or(RawlerError::DecoderFailed(format!("Create RGB thumbnail from strip failed")))?, )), 3 => Ok(DynamicImage::ImageRgb8( ImageBuffer::, Vec>::from_raw(tiff_width as u32, tiff_height as u32, buf.to_vec()) .ok_or(RawlerError::DecoderFailed(format!("Create RGB thumbnail from strip failed")))?, )), _ => unimplemented!(), } } 9..=16 => { let samples = if bits == 16 { samples } else { samples.into_par_iter().map(|p| scale_u16(p, bits)).collect() }; match cpp { 1 => Ok(DynamicImage::ImageLuma16( ImageBuffer::, Vec>::from_raw((tiff_width) as u32, tiff_height as u32, samples) .ok_or(RawlerError::DecoderFailed(format!("Create Y image failed")))?, )), 3 => Ok(DynamicImage::ImageRgb16( ImageBuffer::, Vec>::from_raw((tiff_width) as u32, tiff_height as u32, samples) .ok_or(RawlerError::DecoderFailed(format!("Create RGB image failed")))?, )), _ => unimplemented!(), } } _ => unimplemented!(), }, RawImageData::Float(samples) => match cpp { 3 => Ok(DynamicImage::ImageRgb32F( // This may not work, rescaling required. ImageBuffer::, Vec>::from_raw(tiff_width as u32, tiff_height as u32, samples) .ok_or(RawlerError::DecoderFailed(format!("Create RGB image failed")))?, )), _ => unimplemented!(), }, } } pub(crate) fn plain_image_from_ifd(ifd: &IFD, rawsource: &RawSource) -> Result { let endian = ifd.endian; let tiff_width = fetch_tiff_tag!(ifd, TiffCommonTag::ImageWidth).force_usize(0); let tiff_height = fetch_tiff_tag!(ifd, TiffCommonTag::ImageLength).force_usize(0); let cpp = fetch_tiff_tag!(ifd, TiffCommonTag::SamplesPerPixel).force_usize(0); let bits = fetch_tiff_tag!(ifd, TiffCommonTag::BitsPerSample).force_u32(0); let sample_format = SampleFormat::extract(ifd)?.unwrap_or(SampleFormat::Uint); let compression = CompressionMethod::extract(ifd)?.unwrap_or(CompressionMethod::None); let pi = PhotometricInterpretation::extract(ifd)?.unwrap_or(PhotometricInterpretation::BlackIsZero); log::debug!( "TIFF image: {}x{}, cpp={}, bits={}, compression={:?}, sample_format={:?}, data_mode={:?}, endian={:?}", tiff_width, tiff_height, cpp, bits, compression, sample_format, ifd.data_mode()?, endian, ); let (decode_width, decode_height) = match ifd.data_mode()? { DataMode::Strips => (tiff_width, tiff_height), DataMode::Tiles => { let twidth = fetch_tiff_tag!(ifd, TiffCommonTag::TileWidth).force_usize(0); let tlength = fetch_tiff_tag!(ifd, TiffCommonTag::TileLength).force_usize(0); (((tiff_width - 1) / twidth + 1) * twidth, ((tiff_height - 1) / tlength + 1) * tlength) } }; match sample_format { SampleFormat::Uint => { let mut pixbuf: PixU16 = alloc_image_plain!(decode_width * cpp, decode_height, false); match (compression, ifd.data_mode()?) { (CompressionMethod::None, DataMode::Strips) => { decode_strips::(&mut pixbuf, rawsource, ifd, PackedDecompressor::new(bits, endian))?; } (CompressionMethod::None, DataMode::Tiles) => { decode_tiles::(&mut pixbuf, rawsource, ifd, PackedDecompressor::new(bits, endian))?; } (CompressionMethod::ModernJPEG, DataMode::Strips) => { if (pi == PhotometricInterpretation::YCbCr && bits == 8) || (pi == PhotometricInterpretation::BlackIsZero && bits == 8) { decode_strips::(&mut pixbuf, rawsource, ifd, JpegDecompressor::new())?; } else { decode_strips::(&mut pixbuf, rawsource, ifd, LJpegDecompressor::new())?; } } (CompressionMethod::ModernJPEG, DataMode::Tiles) => { if (pi == PhotometricInterpretation::YCbCr && bits == 8) || (pi == PhotometricInterpretation::BlackIsZero && bits == 8) { decode_tiles::(&mut pixbuf, rawsource, ifd, JpegDecompressor::new())?; } else { decode_tiles::(&mut pixbuf, rawsource, ifd, LJpegDecompressor::new())?; } } (CompressionMethod::LossyJPEG, DataMode::Strips) => { decode_strips::(&mut pixbuf, rawsource, ifd, JpegDecompressor::new())?; } (CompressionMethod::LossyJPEG, DataMode::Tiles) => { decode_tiles::(&mut pixbuf, rawsource, ifd, JpegDecompressor::new())?; } (CompressionMethod::JPEGXL, DataMode::Strips) => decode_strips::(&mut pixbuf, rawsource, ifd, JpegXLDecompressor::new(bits))?, (CompressionMethod::JPEGXL, DataMode::Tiles) => decode_tiles::(&mut pixbuf, rawsource, ifd, JpegXLDecompressor::new(bits))?, _ => { return Err(RawlerError::DecoderFailed(format!( "Unsupported compression method: {:?}, storage: {:?}", compression, ifd.data_mode()? ))); } } // We need to crop first, before we do stuff like deinterleaving. // Padded pixels on output by LJPEG compression will corrupt deinterleave. pixbuf = pixbuf.into_crop(Rect::new(Point::zero(), Dim2::new(tiff_width * cpp, tiff_height))); if let Some(lintable) = ifd.get_entry(TiffCommonTag::Linearization) { apply_linearization(&mut pixbuf, &lintable.value, bits); } // DNG 1.7.1 may store JPEG-XL data in interleaved format let col_ilf = ifd.get_entry(DngTag::ColumnInterleaveFactor).map(|tag| tag.force_u16(0)).unwrap_or(1); let row_ilf = ifd.get_entry(DngTag::RowInterleaveFactor).map(|tag| tag.force_u16(0)).unwrap_or(1); match (row_ilf, col_ilf) { (1, 1) => {} (2, 2) => { // Make sure pixbuf is properly cropped (e.g. LJPEG padding) pixbuf = deinterleave2x2(&pixbuf)?; } _ => todo!(), } return Ok(RawImageData::Integer(pixbuf.into_inner())); } // Floating Point (IEEE) storage SampleFormat::IEEEFP => { let mut pixbuf: PixF32 = alloc_image_f32_plain!(decode_width * cpp, decode_height, false); match (compression, ifd.data_mode()?) { (CompressionMethod::None, DataMode::Strips) => { decode_strips::(&mut pixbuf, rawsource, ifd, PackedDecompressor::new(bits, endian))?; } (CompressionMethod::None, DataMode::Tiles) => { decode_tiles::(&mut pixbuf, rawsource, ifd, PackedDecompressor::new(bits, endian))?; } (CompressionMethod::Deflate, DataMode::Tiles) => { let predictor = fetch_tiff_tag!(ifd, TiffCommonTag::Predictor).force_u16(0); decode_tiles::(&mut pixbuf, rawsource, ifd, DeflateDecompressor::new(cpp, predictor, bits, endian))?; } _ => { return Err(RawlerError::DecoderFailed(format!( "Unsupported compression method: {:?}, storage: {:?}", compression, ifd.data_mode()? ))); } } // We need to crop first, before we do stuff like deinterleaving. // Padded pixels on output by LJPEG compression will corrupt deinterleave. pixbuf = pixbuf.into_crop(Rect::new(Point::zero(), Dim2::new(tiff_width * cpp, tiff_height))); // TODO: other corrections (see u16 code above)? return Ok(RawImageData::Float(pixbuf.into_inner())); } _ => unimplemented!("other sample-formats"), } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] pub(super) fn decode_strips<'a, T>(pixbuf: &'a mut Pix2D, file: &RawSource, raw: &IFD, dc: impl Decompressor<'a, T>) -> Result<()> where T: SubPixel + 'a, { let (strips, cont) = raw.strip_data(file)?; let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let rows_per_strip = raw.get_entry(TiffCommonTag::RowsPerStrip).map(|tag| tag.force_usize(0)).unwrap_or(height); let line_width = pixbuf.width; // If we have a continous buffer, we can optimize decompression of multiple strips. if let Some(src) = cont { // Some decompressors performing badly when skip_rows is > 0, because they need to // decompress the skipped rows anyway. if dc.strips_optimized() { decode_threaded_prealloc(pixbuf, &|line, row| dc.decompress(src, row, std::iter::once(line), line_width))?; } else { dc.decompress(src, 0, pixbuf.pixel_rows_mut(), line_width)?; } } else { decode_threaded_multiline_prealloc(pixbuf, rows_per_strip, &|lines, strip, _row| { let src = strips[strip]; dc.decompress(src, 0, lines, line_width) })?; } Ok(()) } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] pub(super) fn decode_tiles<'a, T>(pixbuf: &'a mut Pix2D, file: &RawSource, raw: &IFD, dc: impl Decompressor<'a, T>) -> Result<()> where T: SubPixel + 'a, { use crate::tiles::TilesMut; let tiles_src = raw.tile_data(file)?; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let cpp = fetch_tiff_tag!(raw, TiffCommonTag::SamplesPerPixel).force_usize(0); let twidth = fetch_tiff_tag!(raw, TiffCommonTag::TileWidth).force_usize(0); // * cpp; let tlength = fetch_tiff_tag!(raw, TiffCommonTag::TileLength).force_usize(0); let coltiles = (width - 1) / twidth + 1; let rowtiles = (height - 1) / tlength + 1; if coltiles * rowtiles != tiles_src.len() as usize { return Err(format_args!("DNG: trying to decode {} tiles from {} offsets", coltiles * rowtiles, tiles_src.len()).into()); } let tiles = pixbuf .data .into_tiles_iter_mut(pixbuf.width / cpp, cpp, twidth, tlength) .map_err(|_| RawlerError::DecoderFailed(format!("Unable to divide source image into tiles")))?; let line_width = twidth * cpp; tiles .enumerate() .par_bridge() .map(|(tile_id, tile)| { //eprintln!("Decode tile id {}", tile_id); dc.decompress(tiles_src[tile_id], 0, tile.into_iter_mut(), line_width) }) .collect::, _>>()?; Ok(()) } pub(crate) fn apply_linearization(image: &mut PixU16, tbl: &Value, bits: u32) { match tbl { Value::Short(points) => { if points.is_empty() { return; } let table = LookupTable::new_with_bits(points, bits); image.par_pixel_rows_mut().for_each(|row| { let mut random = LEu32(row.as_bytes(), 0); row.iter_mut().for_each(|p| { *p = table.dither(*p, &mut random); }) }); } _ => { panic!("Unsupported linear table"); } } } /// The struct that holds all the info about the cameras and is able to decode a file #[derive(Debug, Clone, Default)] pub struct RawLoader { cameras: HashMap<(String, String, String), Camera>, #[allow(dead_code)] // TODO: remove once naked cams supported again naked: HashMap, } impl RawLoader { /// Creates a new raw loader using the camera information included in the library pub fn new() -> RawLoader { let toml = match CAMERAS_TOML.parse::() { Ok(val) => val, Err(e) => panic!("{}", format!("Error parsing cameras.toml: {:?}", e)), }; let mut cams = Vec::new(); for camera in toml.get("cameras").unwrap().as_array().unwrap() { // Create a list of all the camera modes including the base one let mut cammodes = Vec::new(); let ct = camera.as_table().unwrap(); cammodes.push(ct); if let Some(val) = ct.get("modes") { for mode in val.as_array().unwrap() { cammodes.push(mode.as_table().unwrap()); } } // Start with the basic camera let mut cam = Camera::new(); cam.update_from_toml(cammodes[0]); // Create a list of alias names including the base one let mut camnames = vec![(cam.model.clone(), cam.clean_model.clone())]; if let Some(val) = ct.get("model_aliases") { for alias in val.as_array().unwrap() { camnames.push((alias[0].as_str().unwrap().to_string().clone(), alias[1].as_str().unwrap().to_string().clone())); } } // For each combination of alias and mode (including the base ones) create Camera for (model, clean_model) in camnames { for ct in cammodes.clone() { let mut mcam = cam.clone(); mcam.update_from_toml(ct); mcam.model = model.clone(); mcam.clean_model = clean_model.clone(); cams.push(mcam); } } } let mut map = HashMap::new(); let mut naked = HashMap::new(); for cam in cams { map.insert((cam.make.clone(), cam.model.clone(), cam.mode.clone()), cam.clone()); if cam.filesize > 0 { naked.insert(cam.filesize, cam); } } RawLoader { cameras: map, naked } } /// Get list of cameras pub fn get_cameras(&self) -> &HashMap<(String, String, String), Camera> { &self.cameras } /// Returns a decoder for a given buffer pub fn get_decoder<'b>(&'b self, rawfile: &RawSource) -> Result> { if mrw::is_mrw(rawfile) { let dec = Box::new(mrw::MrwDecoder::new(rawfile, self)?); return Ok(dec as Box); } if raf::is_raf(rawfile) { let dec = Box::new(raf::RafDecoder::new(rawfile, self)?); return Ok(dec as Box); } if ari::is_ari(rawfile) { let dec = Box::new(ari::AriDecoder::new(rawfile, self)?); return Ok(dec as Box); } if qtk::is_qtk(rawfile) { let dec = Box::new(qtk::QtkDecoder::new(rawfile, self)?); return Ok(dec as Box); } if ciff::is_ciff(rawfile) { let dec = Box::new(crw::CrwDecoder::new(rawfile, self)?); return Ok(dec as Box); } if jfif::is_exif(rawfile) { let exif = jfif::Jfif::new(rawfile)?; if let Some(make) = exif .exif_ifd() .and_then(|ifd| ifd.get_entry(TiffCommonTag::Make)) .and_then(|entry| entry.value.as_string().map(|s| s.as_str().trim_end())) { match make { "Konica Minolta Photo Imaging, Inc." => { let dec = Box::new(mrw::MrwDecoder::new_jfif(rawfile, exif, self)?); return Ok(dec as Box); } _ => { log::warn!("Unknown make for EXIF file: {}", make); } } } } if x3f::is_x3f(rawfile) { let dec = Box::new(x3f::X3fDecoder::new(rawfile, self)?); return Ok(dec as Box); } match Bmff::new(&mut rawfile.reader()) { Ok(bmff) => { if bmff.compatible_brand("crx ") { return Ok(Box::new(cr3::Cr3Decoder::new(rawfile, bmff, self)?)); } } Err(e) => { debug!("It's not a BMFF file: {:?}", e); } } match GenericTiffReader::new(&mut rawfile.reader(), 0, 0, None, &[]) { Ok(tiff) => { debug!("File is a TIFF file!"); macro_rules! use_decoder { ($dec:ty, $buf:ident, $tiff:ident, $rawdec:ident) => { Ok(Box::new(<$dec>::new(rawfile, $tiff, $rawdec)?) as Box) }; } if tiff.has_entry(DngTag::DNGVersion) { return Ok(Box::new(dng::DngDecoder::new(rawfile, tiff, self)?)); } // The DCS560C is really a CR2 camera so we just special case it here if let Some(model) = tiff.get_entry(TiffCommonTag::Model) { if model.get_string().ok() == Some(&String::from("DCS560C")) { return use_decoder!(cr2::Cr2Decoder, rawfile, tiff, self); } } if let Some(make) = tiff .get_entry(TiffCommonTag::Make) .and_then(|entry| entry.value.as_string().map(|s| s.as_str().trim_end())) { match make { "Canon" => return use_decoder!(cr2::Cr2Decoder, rawfile, tiff, self), "PENTAX" => return use_decoder!(pef::PefDecoder, rawfile, tiff, self), "PENTAX Corporation" => return use_decoder!(pef::PefDecoder, rawfile, tiff, self), "RICOH IMAGING COMPANY, LTD." => return use_decoder!(pef::PefDecoder, rawfile, tiff, self), "Phase One" => return use_decoder!(iiq::IiqDecoder, rawfile, tiff, self), "Phase One A/S" => return use_decoder!(iiq::IiqDecoder, rawfile, tiff, self), "Leaf" => return use_decoder!(iiq::IiqDecoder, rawfile, tiff, self), "Hasselblad" => return use_decoder!(tfr::TfrDecoder, rawfile, tiff, self), "SONY" => return use_decoder!(arw::ArwDecoder, rawfile, tiff, self), "Mamiya-OP Co.,Ltd." => return use_decoder!(mef::MefDecoder, rawfile, tiff, self), "OLYMPUS IMAGING CORP." => return use_decoder!(orf::OrfDecoder, rawfile, tiff, self), "OLYMPUS CORPORATION" => return use_decoder!(orf::OrfDecoder, rawfile, tiff, self), "OLYMPUS OPTICAL CO.,LTD" => return use_decoder!(orf::OrfDecoder, rawfile, tiff, self), "OM Digital Solutions" => return use_decoder!(orf::OrfDecoder, rawfile, tiff, self), "SAMSUNG" => return use_decoder!(srw::SrwDecoder, rawfile, tiff, self), "SEIKO EPSON CORP." => return use_decoder!(erf::ErfDecoder, rawfile, tiff, self), "EASTMAN KODAK COMPANY" => return use_decoder!(kdc::KdcDecoder, rawfile, tiff, self), "Eastman Kodak Company" => return use_decoder!(kdc::KdcDecoder, rawfile, tiff, self), "KODAK" => return use_decoder!(dcs::DcsDecoder, rawfile, tiff, self), "Kodak" => return use_decoder!(dcr::DcrDecoder, rawfile, tiff, self), "Panasonic" => return use_decoder!(rw2::Rw2Decoder, rawfile, tiff, self), "LEICA" => return use_decoder!(rw2::Rw2Decoder, rawfile, tiff, self), "LEICA CAMERA AG" => return use_decoder!(rw2::Rw2Decoder, rawfile, tiff, self), //"FUJIFILM" => return use_decoder!(raf::RafDecoder, rawfile, tiff, self), "NIKON" => return use_decoder!(nrw::NrwDecoder, rawfile, tiff, self), "NIKON CORPORATION" => return use_decoder!(nef::NefDecoder, rawfile, tiff, self), x => { return Err(RawlerError::Unsupported { what: format!("Couldn't find a decoder for make \"{}\"", x), make: make.to_string(), model: tiff .get_entry(TiffCommonTag::Model) .and_then(|entry| entry.as_string().cloned()) .unwrap_or_default(), mode: String::new(), }); } } } if tiff.has_entry(TiffCommonTag::Software) { // Last ditch effort to identify Leaf cameras without Make and Model if fetch_tiff_tag!(tiff, TiffCommonTag::Software).as_string() == Some(&"Camera Library".to_string()) { return use_decoder!(mos::MosDecoder, rawfile, tiff, self); } } } Err(e) => { debug!("File is not a tiff file: {:?}", e); } } // If all else fails see if we match by filesize to one of those CHDK style files let data = rawfile.as_vec()?; if let Some(cam) = self.naked.get(&data.len()) { return Ok(Box::new(nkd::NakedDecoder::new(cam.clone(), self)?)); } Err(RawlerError::Unsupported { what: String::from("No decoder found"), model: "".to_string(), make: "".to_string(), mode: "".to_string(), }) } /// Check support fn check_supported_with_everything<'a>(&'a self, make: &str, model: &str, mode: &str) -> Result { match self.cameras.get(&(make.to_string(), model.to_string(), mode.to_string())) { Some(cam) => Ok(cam.clone()), None => Err(RawlerError::Unsupported { what: String::from("Unknown camera"), model: model.to_string(), make: make.to_string(), mode: mode.to_string(), }), } } fn check_supported_with_mode(&self, ifd0: &IFD, mode: &str) -> Result { let make = fetch_tiff_tag!(ifd0, TiffCommonTag::Make).get_string()?.trim_end(); let model = fetch_tiff_tag!(ifd0, TiffCommonTag::Model).get_string()?.trim_end(); self.check_supported_with_everything(make, model, mode) } #[allow(dead_code)] fn check_supported(&self, ifd0: &IFD) -> Result { self.check_supported_with_mode(ifd0, "") } fn decode_unsafe(&self, rawfile: &RawSource, params: &RawDecodeParams, dummy: bool) -> Result { let decoder = self.get_decoder(rawfile)?; decoder.raw_image(rawfile, params, dummy) } /// Decodes an input into a RawImage pub fn decode(&self, rawfile: &RawSource, params: &RawDecodeParams, dummy: bool) -> Result { //let buffer = Buffer::new(reader)?; match panic::catch_unwind(AssertUnwindSafe(|| self.decode_unsafe(rawfile, params, dummy))) { Ok(val) => val, Err(_) => Err(RawlerError::DecoderFailed(format!("Caught a panic while decoding.{}", BUG))), } } /// Decodes a file into a RawImage pub fn decode_file(&self, path: &Path) -> Result { let rawfile = RawSource::new(path)?; self.decode(&rawfile, &RawDecodeParams::default(), false) } /// Decodes a file into a RawImage pub fn raw_image_count_file(&self, path: &Path) -> Result { let rawfile = RawSource::new(path).map_err(|err| RawlerError::with_io_error("raw_image_count_file()", path, err))?; let decoder = self.get_decoder(&rawfile)?; decoder.raw_image_count() } // Decodes an unwrapped input (just the image data with minimal metadata) into a RawImage // This is only useful for fuzzing really #[doc(hidden)] pub fn decode_unwrapped(&self, rawfile: &RawSource) -> Result { match panic::catch_unwind(AssertUnwindSafe(|| unwrapped::decode_unwrapped(rawfile))) { Ok(val) => val, Err(_) => Err(RawlerError::DecoderFailed(format!("Caught a panic while decoding.{}", BUG))), } } } pub fn decode_unthreaded(width: usize, height: usize, dummy: bool, closure: &F) -> PixU16 where F: Fn(&mut [u16], usize) + Sync, { let mut out: PixU16 = alloc_image!(width, height, dummy); out.pixels_mut().chunks_exact_mut(width).enumerate().for_each(|(row, line)| { closure(line, row); }); out } pub fn decode_threaded(width: usize, height: usize, dummy: bool, closure: &F) -> PixU16 where F: Fn(&mut [u16], usize) + Sync, { let mut out: PixU16 = alloc_image!(width, height, dummy); out.pixels_mut().par_chunks_exact_mut(width).enumerate().for_each(|(row, line)| { closure(line, row); }); out } pub fn decode_threaded_prealloc<'a, T, F>(pixbuf: &'a mut Pix2D, closure: &F) -> std::result::Result<(), String> where F: Fn(&'a mut [T], usize) -> std::result::Result<(), String> + Sync, T: SubPixel + 'a, { let width = pixbuf.width; pixbuf .pixels_mut() .par_chunks_exact_mut(width) .enumerate() .map(|(row, line)| closure(line, row)) .collect::, _>>()?; Ok(()) } pub fn decode_threaded_multiline(width: usize, height: usize, lines: usize, dummy: bool, closure: &F) -> std::result::Result where F: Fn(&mut [u16], usize) -> std::result::Result<(), String> + Sync, { let mut out: PixU16 = alloc_image_ok!(width, height, dummy); out .pixels_mut() .par_chunks_mut(width * lines) .enumerate() .map(|(row, line)| closure(line, row * lines)) .collect::, _>>()?; Ok(out) } /// Split pixbuf by `lines`. /// Caution: The last chunk may not be equal to `lines`. pub fn decode_threaded_multiline_prealloc<'a, T, F>(pixbuf: &'a mut Pix2D, lines: usize, closure: &F) -> std::result::Result<(), String> where F: Fn(&mut (dyn LineIteratorMut<'a, T>), usize, usize) -> std::result::Result<(), String> + Sync, T: SubPixel + 'a, { let width = pixbuf.width; let chunksize = pixbuf.width * lines; pixbuf .pixels_mut() .par_chunks_mut(chunksize) .enumerate() .map(|(strip, chunk)| closure(&mut chunk.chunks_exact_mut(width), strip, strip * lines)) .collect::, _>>()?; Ok(()) } /// This is used for streams where not chunked at line boundaries. pub fn decode_threaded_chunked(width: usize, height: usize, chunksize: usize, dummy: bool, closure: &F) -> PixU16 where F: Fn(&mut [u16], usize) + Sync, { let mut out: PixU16 = alloc_image!(width, height, dummy); out.pixels_mut().par_chunks_mut(chunksize).enumerate().for_each(|(chunk_id, chunk)| { closure(chunk, chunk_id); }); out } rawler-0.7.1/src/decoders/mos.rs000064400000000000000000000116271046102023000146570ustar 00000000000000use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::alloc_image_ok; use crate::analyze::FormatDump; use crate::decompressors::ljpeg::LjpegDecompressor; use crate::exif::Exif; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::reader::TiffReader; use crate::packed::decode_16be; use crate::packed::decode_16le; use crate::pixarray::PixU16; use crate::rawsource::RawSource; use crate::tags::TiffCommonTag; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use super::ok_cfa_image; #[derive(Debug, Clone)] pub struct MosDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, camera: Camera, } impl<'a> MosDecoder<'a> { pub fn new(_file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { let make = Self::xmp_tag(&tiff, "Make")?; let model_full = Self::xmp_tag(&tiff, "Model")?; let model = model_full.split_terminator('(').next().unwrap(); let camera = rawloader.check_supported_with_everything(&make, model, "")?; Ok(MosDecoder { tiff, rawloader, camera }) } } impl<'a> Decoder for MosDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let raw = self .tiff .find_first_ifd_with_tag(TiffCommonTag::TileOffsets) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with TileOffsets tag")))?; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let offset = fetch_tiff_tag!(raw, TiffCommonTag::TileOffsets).force_usize(0); let src = file.subview_until_eof(offset as u64)?; let image = match fetch_tiff_tag!(raw, TiffCommonTag::Compression).force_usize(0) { 1 => { if self.tiff.little_endian() { decode_16le(src, width, height, dummy) } else { decode_16be(src, width, height, dummy) } } 7 | 99 => self.decode_compressed(&self.camera, src, width, height, dummy)?, x => return Err(RawlerError::unsupported(&self.camera, format!("MOS: unsupported compression {}", x))), }; let cpp = 1; ok_cfa_image(self.camera.clone(), cpp, self.get_wb()?, image, dummy) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; let mdata = RawMetadata::new(&self.camera, exif); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::MOS } } impl<'a> MosDecoder<'a> { fn get_wb(&self) -> Result<[f32; 4]> { let meta = fetch_tiff_tag!(self.tiff, TiffCommonTag::LeafMetadata).get_data(); let mut pos = 0; // We need at least 16+45+10 bytes for the NeutObj_neutrals section itself while pos + 70 < meta.len() { if meta[pos..pos + 16] == b"NeutObj_neutrals"[..] { let data = &meta[pos + 44..]; if let Some(endpos) = data.iter().position(|&x| x == 0) { let nums = String::from_utf8_lossy(&data[0..endpos]) .split_terminator('\n') .map(|x| x.parse::().unwrap_or(f32::NAN)) .collect::>(); if nums.len() == 4 { return Ok([nums[0] / nums[1], nums[0] / nums[2], nums[0] / nums[3], f32::NAN]); } } break; } pos += 1; } Ok([f32::NAN, f32::NAN, f32::NAN, f32::NAN]) } fn xmp_tag(tiff: &GenericTiffReader, tag: &str) -> Result { let xmp_bytes = fetch_tiff_tag!(tiff, TiffCommonTag::Xmp).get_data(); let xmp = String::from_utf8_lossy(xmp_bytes); let error = format!("MOS: Couldn't find XMP tag {}", tag); let start = xmp.find(&format!("", tag)).ok_or_else(|| error.clone())?; let end = xmp.find(&format!("", tag)).ok_or(error)?; Ok(xmp[start + tag.len() + 7..end].to_string()) } pub fn decode_compressed(&self, cam: &Camera, src: &[u8], width: usize, height: usize, dummy: bool) -> Result { let interlaced = cam.find_hint("interlaced"); Self::do_decode(src, interlaced, width, height, dummy) } pub(crate) fn do_decode(src: &[u8], interlaced: bool, width: usize, height: usize, dummy: bool) -> Result { if dummy { return Ok(PixU16::new_uninit(width, height)); } let decompressor = LjpegDecompressor::new_full(src, true, true)?; let ljpegout = decompressor.decode_leaf(width, height)?; if interlaced { let mut out = alloc_image_ok!(width, height, dummy); for (row, line) in ljpegout.pixels().chunks_exact(width).enumerate() { let orow = if row & 1 == 1 { height - 1 - row / 2 } else { row / 2 }; out[orow * width..(orow + 1) * width].copy_from_slice(line); } Ok(out) } else { Ok(ljpegout) } } } rawler-0.7.1/src/decoders/mrw.rs000064400000000000000000000171471046102023000146710ustar 00000000000000use byteorder::ReadBytesExt; use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::analyze::FormatDump; use crate::bits::BEu16; use crate::bits::BEu32; use crate::exif::Exif; use crate::formats::jfif::Jfif; use crate::formats::jfif::Segment; use crate::formats::jfif::is_exif; use crate::formats::tiff::IFD; use crate::packed::decode_12be; use crate::packed::decode_12be_unpacked; use crate::packed::decode_16le; use crate::rawsource::RawSource; use crate::tags::TiffCommonTag; use std::io::Cursor; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use super::ok_cfa_image; const MRW_MAGIC: u32 = 0x004D524D; // !memcmp (head,"\0MRM",4))? pub fn is_mrw(file: &RawSource) -> bool { match file.subview(0, 4) { Ok(buf) => { if BEu32(buf, 0) == MRW_MAGIC { true } else { log::debug!("MRW: File MAGIC not found"); false } } Err(err) => { log::error!("is_mrw() error: {:?}", err); false } } } #[derive(Debug, Clone)] pub struct MrwDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, data_offset: usize, raw_width: usize, raw_height: usize, bits: u8, packed: bool, wb_vals: [u16; 4], tiff: IFD, camera: Camera, } impl<'a> MrwDecoder<'a> { pub fn new(file: &RawSource, rawloader: &'a RawLoader) -> Result> { if is_mrw(file) { Self::new_mrw(file, rawloader) } else if is_exif(file) { let exif = Jfif::new(file)?; Self::new_jfif(file, exif, rawloader) } else { Err(crate::RawlerError::DecoderFailed(format!( "MRW decoder can't decode given file: {}", file.path().display() ))) } } /// Makernotes for MRW starts with "MLY" ASCII string fn get_mly_wb(ifd: &IFD, rawfile: &RawSource, data_offset: u64) -> Result<[u16; 4]> { if let Some(makernotes) = ifd.get_entry_recursive(TiffCommonTag::Makernote) { debug_assert_eq!(makernotes.get_data()[0..3], [b'M', b'L', b'Y']); if makernotes.get_data().get(0..3) == Some(b"MLY") { let mut buf = Cursor::new(rawfile.as_vec()?); let mut wb = [0_u16; 4]; let mut cam_mul = [1_u16; 4]; while buf.position() < data_offset { wb[0] = wb[2]; wb[2] = wb[1]; wb[1] = wb[3]; wb[3] = match buf.read_u16::() { Ok(val) => val, Err(_) => break, }; if wb[1] == 256 && wb[3] == 256 && wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640 { cam_mul.copy_from_slice(&wb); cam_mul.swap(2, 3); log::debug!("Found WB match: {:?}", cam_mul); } } return Ok(cam_mul); } } else { log::warn!("Makernotes not found, fall back to defaults!"); } Ok([1, 1, 1, 1]) } pub fn new_jfif(file: &RawSource, jfif: Jfif, rawloader: &'a RawLoader) -> Result> { let tiff = jfif .exif_ifd() .ok_or(RawlerError::DecoderFailed("No EXIF IFD found in JFIF file".to_string()))? .clone(); let camera = rawloader.check_supported(&tiff)?; let (app1_offset, app1_len) = jfif .segments .iter() .map(|seg| { if let Segment::APP1 { offset, app1 } = seg { Some((*offset, app1.len)) } else { None } }) .find(Option::is_some) .flatten() .unwrap_or_default(); let data_offset = (app1_offset + app1_len + camera.param_i32("offset_corr").unwrap_or(0) as u64) as usize; let raw_width = camera.raw_width; let raw_height = camera.raw_height; let packed = false; let wb_vals = Self::get_mly_wb(&tiff, file, data_offset as u64)?; let bits = 16; Ok(MrwDecoder { data_offset, raw_width, raw_height, bits, packed, wb_vals, tiff, rawloader, camera, }) } fn new_mrw(file: &RawSource, rawloader: &'a RawLoader) -> Result> { let full = file.as_vec()?; let buf = &full; let data_offset: usize = (BEu32(buf, 4) + 8) as usize; let mut raw_height: usize = 0; let mut raw_width: usize = 0; let bits = 12; let mut packed = false; let mut wb_vals: [u16; 4] = [0; 4]; let mut tiffpos: usize = 0; let mut currpos: usize = 8; // At most we read 20 bytes from currpos so check we don't step outside that while currpos + 20 < data_offset { let tag: u32 = BEu32(buf, currpos); let len: u32 = BEu32(buf, currpos + 4); match tag { 0x505244 => { // PRD raw_height = BEu16(buf, currpos + 16) as usize; raw_width = BEu16(buf, currpos + 18) as usize; packed = buf[currpos + 24] == 12; } 0x574247 => { // WBG for i in 0..4 { wb_vals[i] = BEu16(buf, currpos + 12 + i * 2); } } 0x545457 => { // TTW // Base value for offsets needs to be at the beginning of the // TIFF block, not the file tiffpos = currpos + 8; } _ => {} } currpos += (len + 8) as usize; } let tiff_data = file.subview_until_eof(tiffpos as u64)?; let tiff = IFD::new(&mut Cursor::new(tiff_data), 8, 0, 0, crate::bits::Endian::Big, &[])?; let camera = rawloader.check_supported(&tiff)?; Ok(MrwDecoder { data_offset, raw_width, raw_height, bits, packed, wb_vals, tiff, rawloader, camera, }) } } impl<'a> Decoder for MrwDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let src = file.subview_until_eof(self.data_offset as u64)?; let buffer = if self.bits == 16 { decode_16le(src, self.raw_width, self.raw_height, dummy) } else if self.packed { decode_12be(src, self.raw_width, self.raw_height, dummy) } else { decode_12be_unpacked(src, self.raw_width, self.raw_height, dummy) }; let wb_coeffs = if self.camera.find_hint("swapped_wb") { [self.wb_vals[2] as f32, self.wb_vals[0] as f32, self.wb_vals[0] as f32, self.wb_vals[1] as f32] } else { [self.wb_vals[0] as f32, self.wb_vals[1] as f32, self.wb_vals[2] as f32, self.wb_vals[3] as f32] }; let cpp = 1; ok_cfa_image(self.camera.clone(), cpp, normalize_wb(wb_coeffs), buffer, dummy) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let exif = Exif::new(&self.tiff)?; let mdata = RawMetadata::new(&self.camera, exif); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::MRW } /* /// File is EXIF structure, but contains no valid JPEG image, so this is useless... fn full_image(&self, file: &RawSource) -> Result> { if is_mrw(file) { Ok(None) } else if is_exif(file) { let buf = file.as_vec()?; dump_buf("/tmp/dmp1", &buf); let img = image::load_from_memory_with_format(&buf, image::ImageFormat::Jpeg) .map_err(|err| RawlerError::DecoderFailed(format!("Failed to get full image from RAW file: {:?}", err)))?; log::debug!("Got full image from RAW"); Ok(Some(img)) } else { Ok(None) } } */ } fn normalize_wb(raw_wb: [f32; 4]) -> [f32; 4] { log::debug!("MRW raw wb: {:?}", raw_wb); let div = raw_wb[1]; // G1 should be 1024 and we use this as divisor let mut norm = raw_wb; norm.iter_mut().for_each(|v| { if v.is_normal() { *v /= div } }); [norm[0], (norm[1] + norm[2]) / 2.0, norm[3], f32::NAN] } rawler-0.7.1/src/decoders/nef/decrypt.rs000064400000000000000000000102501046102023000162720ustar 00000000000000use crate::formats::tiff::IFD; use super::NikonMakernote; use crate::Result; pub(super) fn nef_decrypt(buf: &mut [u8], start: usize, makernote: &IFD) -> Result<()> { let serial = fetch_tiff_tag!(makernote, NikonMakernote::NefSerial); let data = serial.get_data(); let mut serialno = 0_usize; for i in 0..serial.count() as usize { if data[i] == 0 { break; } serialno = serialno * 10 + if data[i] >= 48 && data[i] <= 57 { // "0" to "9" (data[i] - 48) as usize } else { (data[i] % 10) as usize }; } // Get the "decryption" key let keydata = fetch_tiff_tag!(makernote, NikonMakernote::NefKey).force_u32(0).to_le_bytes(); let keyno = (keydata[0] ^ keydata[1] ^ keydata[2] ^ keydata[3]) as usize; let src = &mut buf[start..]; let ci = WB_SERIALMAP[serialno & 0xff] as u32; let mut cj = WB_KEYMAP[keyno & 0xff] as u32; let mut ck = 0x60_u32; for i in 0..src.len() { cj += ci * ck; ck += 1; src[i] ^= cj as u8; } Ok(()) } // We use this for the D50 and D2X whacky WB "encryption" const WB_SERIALMAP: [u8; 256] = [ 0xc1, 0xbf, 0x6d, 0x0d, 0x59, 0xc5, 0x13, 0x9d, 0x83, 0x61, 0x6b, 0x4f, 0xc7, 0x7f, 0x3d, 0x3d, 0x53, 0x59, 0xe3, 0xc7, 0xe9, 0x2f, 0x95, 0xa7, 0x95, 0x1f, 0xdf, 0x7f, 0x2b, 0x29, 0xc7, 0x0d, 0xdf, 0x07, 0xef, 0x71, 0x89, 0x3d, 0x13, 0x3d, 0x3b, 0x13, 0xfb, 0x0d, 0x89, 0xc1, 0x65, 0x1f, 0xb3, 0x0d, 0x6b, 0x29, 0xe3, 0xfb, 0xef, 0xa3, 0x6b, 0x47, 0x7f, 0x95, 0x35, 0xa7, 0x47, 0x4f, 0xc7, 0xf1, 0x59, 0x95, 0x35, 0x11, 0x29, 0x61, 0xf1, 0x3d, 0xb3, 0x2b, 0x0d, 0x43, 0x89, 0xc1, 0x9d, 0x9d, 0x89, 0x65, 0xf1, 0xe9, 0xdf, 0xbf, 0x3d, 0x7f, 0x53, 0x97, 0xe5, 0xe9, 0x95, 0x17, 0x1d, 0x3d, 0x8b, 0xfb, 0xc7, 0xe3, 0x67, 0xa7, 0x07, 0xf1, 0x71, 0xa7, 0x53, 0xb5, 0x29, 0x89, 0xe5, 0x2b, 0xa7, 0x17, 0x29, 0xe9, 0x4f, 0xc5, 0x65, 0x6d, 0x6b, 0xef, 0x0d, 0x89, 0x49, 0x2f, 0xb3, 0x43, 0x53, 0x65, 0x1d, 0x49, 0xa3, 0x13, 0x89, 0x59, 0xef, 0x6b, 0xef, 0x65, 0x1d, 0x0b, 0x59, 0x13, 0xe3, 0x4f, 0x9d, 0xb3, 0x29, 0x43, 0x2b, 0x07, 0x1d, 0x95, 0x59, 0x59, 0x47, 0xfb, 0xe5, 0xe9, 0x61, 0x47, 0x2f, 0x35, 0x7f, 0x17, 0x7f, 0xef, 0x7f, 0x95, 0x95, 0x71, 0xd3, 0xa3, 0x0b, 0x71, 0xa3, 0xad, 0x0b, 0x3b, 0xb5, 0xfb, 0xa3, 0xbf, 0x4f, 0x83, 0x1d, 0xad, 0xe9, 0x2f, 0x71, 0x65, 0xa3, 0xe5, 0x07, 0x35, 0x3d, 0x0d, 0xb5, 0xe9, 0xe5, 0x47, 0x3b, 0x9d, 0xef, 0x35, 0xa3, 0xbf, 0xb3, 0xdf, 0x53, 0xd3, 0x97, 0x53, 0x49, 0x71, 0x07, 0x35, 0x61, 0x71, 0x2f, 0x43, 0x2f, 0x11, 0xdf, 0x17, 0x97, 0xfb, 0x95, 0x3b, 0x7f, 0x6b, 0xd3, 0x25, 0xbf, 0xad, 0xc7, 0xc5, 0xc5, 0xb5, 0x8b, 0xef, 0x2f, 0xd3, 0x07, 0x6b, 0x25, 0x49, 0x95, 0x25, 0x49, 0x6d, 0x71, 0xc7, ]; const WB_KEYMAP: [u8; 256] = [ 0xa7, 0xbc, 0xc9, 0xad, 0x91, 0xdf, 0x85, 0xe5, 0xd4, 0x78, 0xd5, 0x17, 0x46, 0x7c, 0x29, 0x4c, 0x4d, 0x03, 0xe9, 0x25, 0x68, 0x11, 0x86, 0xb3, 0xbd, 0xf7, 0x6f, 0x61, 0x22, 0xa2, 0x26, 0x34, 0x2a, 0xbe, 0x1e, 0x46, 0x14, 0x68, 0x9d, 0x44, 0x18, 0xc2, 0x40, 0xf4, 0x7e, 0x5f, 0x1b, 0xad, 0x0b, 0x94, 0xb6, 0x67, 0xb4, 0x0b, 0xe1, 0xea, 0x95, 0x9c, 0x66, 0xdc, 0xe7, 0x5d, 0x6c, 0x05, 0xda, 0xd5, 0xdf, 0x7a, 0xef, 0xf6, 0xdb, 0x1f, 0x82, 0x4c, 0xc0, 0x68, 0x47, 0xa1, 0xbd, 0xee, 0x39, 0x50, 0x56, 0x4a, 0xdd, 0xdf, 0xa5, 0xf8, 0xc6, 0xda, 0xca, 0x90, 0xca, 0x01, 0x42, 0x9d, 0x8b, 0x0c, 0x73, 0x43, 0x75, 0x05, 0x94, 0xde, 0x24, 0xb3, 0x80, 0x34, 0xe5, 0x2c, 0xdc, 0x9b, 0x3f, 0xca, 0x33, 0x45, 0xd0, 0xdb, 0x5f, 0xf5, 0x52, 0xc3, 0x21, 0xda, 0xe2, 0x22, 0x72, 0x6b, 0x3e, 0xd0, 0x5b, 0xa8, 0x87, 0x8c, 0x06, 0x5d, 0x0f, 0xdd, 0x09, 0x19, 0x93, 0xd0, 0xb9, 0xfc, 0x8b, 0x0f, 0x84, 0x60, 0x33, 0x1c, 0x9b, 0x45, 0xf1, 0xf0, 0xa3, 0x94, 0x3a, 0x12, 0x77, 0x33, 0x4d, 0x44, 0x78, 0x28, 0x3c, 0x9e, 0xfd, 0x65, 0x57, 0x16, 0x94, 0x6b, 0xfb, 0x59, 0xd0, 0xc8, 0x22, 0x36, 0xdb, 0xd2, 0x63, 0x98, 0x43, 0xa1, 0x04, 0x87, 0x86, 0xf7, 0xa6, 0x26, 0xbb, 0xd6, 0x59, 0x4d, 0xbf, 0x6a, 0x2e, 0xaa, 0x2b, 0xef, 0xe6, 0x78, 0xb6, 0x4e, 0xe0, 0x2f, 0xdc, 0x7c, 0xbe, 0x57, 0x19, 0x32, 0x7e, 0x2a, 0xd0, 0xb8, 0xba, 0x29, 0x00, 0x3c, 0x52, 0x7d, 0xa8, 0x49, 0x3b, 0x2d, 0xeb, 0x25, 0x49, 0xfa, 0xa3, 0xaa, 0x39, 0xa7, 0xc5, 0xa7, 0x50, 0x11, 0x36, 0xfb, 0xc6, 0x67, 0x4a, 0xf5, 0xa5, 0x12, 0x65, 0x7e, 0xb0, 0xdf, 0xaf, 0x4e, 0xb3, 0x61, 0x7f, 0x2f, ]; rawler-0.7.1/src/decoders/nef/lensdata.rs000064400000000000000000000242011046102023000164140ustar 00000000000000use crate::Result; use crate::bits::LEu16; use crate::{decoders::nef::NikonMakernote, formats::tiff::IFD}; const ERRMSG: &str = "Lens composite buffer error: EOF"; #[derive(Default, Clone)] #[allow(dead_code)] pub struct NefLensDataF { version: u32, exit_pupil_position: u8, af_aperture: u8, focus_position: u8, focus_distance: u8, lens_id_number: u8, lens_fstops: u8, min_focal_len: u8, max_focal_len: u8, max_aperture_at_min_focal: u8, max_aperture_at_max_focal: u8, mcu_version: u8, effective_max_aperture: u8, lens_model: Option, } #[derive(Default, Clone)] #[allow(dead_code)] pub struct NefLensDataZ { version: u32, pub lens_id: u16, } #[derive(Clone)] #[allow(dead_code)] pub enum NefLensData { FMount(NefLensDataF), ZMount(NefLensDataZ), } impl NefLensDataF { pub fn composite_id(&self, lens_type: u8) -> String { format!( "{:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X}", self.lens_id_number, self.lens_fstops, self.min_focal_len, self.max_focal_len, self.max_aperture_at_min_focal, self.max_aperture_at_max_focal, self.mcu_version, lens_type ) } } pub(super) fn from_makernote(makernote: &IFD) -> Result> { if let Some(levels) = makernote.get_entry(NikonMakernote::LensData) { let mut buf = levels.get_data().clone(); let mut version: u32 = 0; for i in 0..4 { version = (version << 4) + (buf[i] - b'0') as u32; } let lensdata = match version { 0x100 => NefLensData::FMount(parse_lensdata_0x100(version, &buf)?), 0x101 => NefLensData::FMount(parse_lensdata_0x101(version, &buf)?), 0x201 | 0x202 | 0x203 => { super::decrypt::nef_decrypt(&mut buf, 4, makernote)?; NefLensData::FMount(parse_lensdata_0x101(version, &buf)?) } 0x204 => { super::decrypt::nef_decrypt(&mut buf, 4, makernote)?; NefLensData::FMount(parse_lensdata_0x204(version, &buf)?) } 0x400 => { super::decrypt::nef_decrypt(&mut buf, 4, makernote)?; NefLensData::FMount(parse_lensdata_0x4xx(version, &buf, 0x18a)?) } 0x401 => { super::decrypt::nef_decrypt(&mut buf, 4, makernote)?; NefLensData::FMount(parse_lensdata_0x4xx(version, &buf, 0x18a)?) } 0x402 => { super::decrypt::nef_decrypt(&mut buf, 4, makernote)?; NefLensData::FMount(parse_lensdata_0x4xx(version, &buf, 0x18b)?) } 0x403 => { super::decrypt::nef_decrypt(&mut buf, 4, makernote)?; NefLensData::FMount(parse_lensdata_0x4xx(version, &buf, 0x2ac)?) } 0x800 | 0x801 | 0x802 // Z Models => { super::decrypt::nef_decrypt(&mut buf, 4, makernote)?; parse_lensdata_0x800(version, &buf)? } _ => todo!("Lensdata version: 0x{:x} not implemented", version), }; log::debug!("NEF lens data version: 0x{:x}", version); Ok(Some(lensdata)) } else { Ok(None) } } fn parse_lensdata_0x100(version: u32, buf: &[u8]) -> Result { Ok(NefLensDataF { version, exit_pupil_position: 0, af_aperture: 0, focus_position: 0, focus_distance: 0, lens_id_number: *buf.get(NefLensData00::LensIDNumber as usize).ok_or(ERRMSG)?, lens_fstops: *buf.get(NefLensData00::LensFStops as usize).ok_or(ERRMSG)?, min_focal_len: *buf.get(NefLensData00::MinFocalLength as usize).ok_or(ERRMSG)?, max_focal_len: *buf.get(NefLensData00::MaxFocalLength as usize).ok_or(ERRMSG)?, max_aperture_at_min_focal: *buf.get(NefLensData00::MaxApertureAtMinFocal as usize).ok_or(ERRMSG)?, max_aperture_at_max_focal: *buf.get(NefLensData00::MaxApertureAtMaxFocal as usize).ok_or(ERRMSG)?, mcu_version: *buf.get(NefLensData00::MCUVersion as usize).ok_or(ERRMSG)?, effective_max_aperture: 0, lens_model: None, }) } fn parse_lensdata_0x101(version: u32, buf: &[u8]) -> Result { Ok(NefLensDataF { version, exit_pupil_position: *buf.get(NefLensData01::ExitPupilPosition as usize).ok_or(ERRMSG)?, af_aperture: *buf.get(NefLensData01::AFAperture as usize).ok_or(ERRMSG)?, focus_position: *buf.get(NefLensData01::FocusPosition as usize).ok_or(ERRMSG)?, focus_distance: *buf.get(NefLensData01::FocusDistance as usize).ok_or(ERRMSG)?, lens_id_number: *buf.get(NefLensData01::LensIDNumber as usize).ok_or(ERRMSG)?, lens_fstops: *buf.get(NefLensData01::LensFStops as usize).ok_or(ERRMSG)?, min_focal_len: *buf.get(NefLensData01::MinFocalLength as usize).ok_or(ERRMSG)?, max_focal_len: *buf.get(NefLensData01::MaxFocalLength as usize).ok_or(ERRMSG)?, max_aperture_at_min_focal: *buf.get(NefLensData01::MaxApertureAtMinFocal as usize).ok_or(ERRMSG)?, max_aperture_at_max_focal: *buf.get(NefLensData01::MaxApertureAtMaxFocal as usize).ok_or(ERRMSG)?, mcu_version: *buf.get(NefLensData01::MCUVersion as usize).ok_or(ERRMSG)?, effective_max_aperture: *buf.get(NefLensData01::EffectiveMaxAperture as usize).ok_or(ERRMSG)?, lens_model: None, }) } fn parse_lensdata_0x204(version: u32, buf: &[u8]) -> Result { Ok(NefLensDataF { version, exit_pupil_position: *buf.get(NefLensData204::ExitPupilPosition as usize).ok_or(ERRMSG)?, af_aperture: *buf.get(NefLensData204::AFAperture as usize).ok_or(ERRMSG)?, focus_position: *buf.get(NefLensData204::FocusPosition as usize).ok_or(ERRMSG)?, focus_distance: *buf.get(NefLensData204::FocusDistance as usize).ok_or(ERRMSG)?, lens_id_number: *buf.get(NefLensData204::LensIDNumber as usize).ok_or(ERRMSG)?, lens_fstops: *buf.get(NefLensData204::LensFStops as usize).ok_or(ERRMSG)?, min_focal_len: *buf.get(NefLensData204::MinFocalLength as usize).ok_or(ERRMSG)?, max_focal_len: *buf.get(NefLensData204::MaxFocalLength as usize).ok_or(ERRMSG)?, max_aperture_at_min_focal: *buf.get(NefLensData204::MaxApertureAtMinFocal as usize).ok_or(ERRMSG)?, max_aperture_at_max_focal: *buf.get(NefLensData204::MaxApertureAtMaxFocal as usize).ok_or(ERRMSG)?, mcu_version: *buf.get(NefLensData204::MCUVersion as usize).ok_or(ERRMSG)?, effective_max_aperture: *buf.get(NefLensData204::EffectiveMaxAperture as usize).ok_or(ERRMSG)?, lens_model: None, }) } fn parse_lensdata_0x4xx(version: u32, buf: &[u8], model_offset: usize) -> Result { let mut data = NefLensDataF { version, ..Default::default() }; if buf.len() >= model_offset + 64 { let str = String::from_utf8_lossy(&buf[model_offset..model_offset + 64]); data.lens_model = Some(str.trim().into()); } Ok(data) } fn parse_lensdata_0x800(version: u32, buf: &[u8]) -> Result { // This check comes from exiftool. If the buffer contains only zeros, // we consider the block as unused. Hopefully we find another method... let old_data_avail = !buf[0x04..0x04 + 16].iter().all(|&x| x == 0); let new_data_avail = !buf[0x30..0x30 + 16].iter().all(|&x| x == 0); if old_data_avail { log::debug!("NEF lensdata 0x80X: Found old lensdata block"); Ok(NefLensData::FMount(NefLensDataF { version, exit_pupil_position: *buf.get(NefLensData800::ExitPupilPosition as usize).ok_or(ERRMSG)?, af_aperture: *buf.get(NefLensData800::AFAperture as usize).ok_or(ERRMSG)?, focus_position: *buf.get(NefLensData800::FocusPosition as usize).ok_or(ERRMSG)?, focus_distance: *buf.get(NefLensData800::FocusDistance as usize).ok_or(ERRMSG)?, lens_id_number: *buf.get(NefLensData800::LensIDNumber as usize).ok_or(ERRMSG)?, lens_fstops: *buf.get(NefLensData800::LensFStops as usize).ok_or(ERRMSG)?, min_focal_len: *buf.get(NefLensData800::MinFocalLength as usize).ok_or(ERRMSG)?, max_focal_len: *buf.get(NefLensData800::MaxFocalLength as usize).ok_or(ERRMSG)?, max_aperture_at_min_focal: *buf.get(NefLensData800::MaxApertureAtMinFocal as usize).ok_or(ERRMSG)?, max_aperture_at_max_focal: *buf.get(NefLensData800::MaxApertureAtMaxFocal as usize).ok_or(ERRMSG)?, mcu_version: *buf.get(NefLensData800::MCUVersion as usize).ok_or(ERRMSG)?, effective_max_aperture: *buf.get(NefLensData800::EffectiveMaxAperture as usize).ok_or(ERRMSG)?, lens_model: None, })) } else if new_data_avail { log::debug!("NEF lensdata 0x80X: Found new lensdata block"); let mut data = NefLensDataZ { version, ..Default::default() }; data.lens_id = LEu16(buf, 0x30); log::debug!("NEF lensdata 0x80X: lens_id: {}", data.lens_id); Ok(NefLensData::ZMount(data)) } else { Err("NEF lens data 0x80X contains neither old and new data".into()) } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[allow(non_camel_case_types)] #[allow(dead_code)] enum NefLensData00 { Version = 0x00, LensIDNumber = 0x06, LensFStops = 0x07, MinFocalLength = 0x08, MaxFocalLength = 0x09, MaxApertureAtMinFocal = 0x0a, MaxApertureAtMaxFocal = 0x0b, MCUVersion = 0x0c, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[allow(non_camel_case_types)] #[allow(dead_code)] enum NefLensData01 { Version = 0x00, ExitPupilPosition = 0x04, AFAperture = 0x05, FocusPosition = 0x08, FocusDistance = 0x09, FocalLength = 0x0a, LensIDNumber = 0x0b, LensFStops = 0x0c, MinFocalLength = 0x0d, MaxFocalLength = 0x0e, MaxApertureAtMinFocal = 0x0f, MaxApertureAtMaxFocal = 0x10, MCUVersion = 0x11, EffectiveMaxAperture = 0x12, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[allow(non_camel_case_types)] #[allow(dead_code)] enum NefLensData204 { Version = 0x00, ExitPupilPosition = 0x04, AFAperture = 0x05, FocusPosition = 0x08, FocusDistance = 0x0a, FocalLength = 0x0b, LensIDNumber = 0x0c, LensFStops = 0x0d, MinFocalLength = 0x0e, MaxFocalLength = 0x0f, MaxApertureAtMinFocal = 0x10, MaxApertureAtMaxFocal = 0x11, MCUVersion = 0x12, EffectiveMaxAperture = 0x13, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[allow(non_camel_case_types)] #[allow(dead_code)] enum NefLensData800 { Version = 0x00, OldLensDataFlag = 0x03, ExitPupilPosition = 0x04, AFAperture = 0x05, FocusPosition = 0x09, FocusDistance = 0x0b, FocalLength = 0x0c, LensIDNumber = 0x0d, LensFStops = 0x0e, MinFocalLength = 0x0f, MaxFocalLength = 0x10, MaxApertureAtMinFocal = 0x11, MaxApertureAtMaxFocal = 0x12, MCUVersion = 0x13, EffectiveMaxAperture = 0x14, } rawler-0.7.1/src/decoders/nef.rs000064400000000000000000000752271046102023000146370ustar 00000000000000use image::DynamicImage; use image::ImageBuffer; use image::Rgb; use log::debug; use log::warn; use serde::Deserialize; use serde::Serialize; use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::alloc_image_ok; use crate::analyze::FormatDump; use crate::bits::BEu16; use crate::bits::BEu32; use crate::bits::Endian; use crate::bits::LEu32; use crate::bits::LookupTable; use crate::bits::clampbits; use crate::buffer::PaddedBuf; use crate::decoders::decode_threaded; use crate::decoders::nef::lensdata::NefLensData; use crate::decompressors::ljpeg::huffman::HuffTable; use crate::exif::Exif; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::IFD; use crate::formats::tiff::Value; use crate::formats::tiff::ifd::OffsetMode; use crate::formats::tiff::reader::TiffReader; use crate::imgop::Dim2; use crate::imgop::Point; use crate::imgop::Rect; use crate::lens::LensDescription; use crate::lens::LensResolver; use crate::packed::*; use crate::pixarray::PixU16; use crate::pumps::BitPump; use crate::pumps::BitPumpMSB; use crate::pumps::ByteStream; use crate::rawimage::CFAConfig; use crate::rawimage::RawPhotometricInterpretation; use crate::rawimage::WhiteLevel; use crate::rawsource::RawSource; use crate::tags::ExifTag; use crate::tags::TiffCommonTag; use super::BlackLevel; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; mod decrypt; pub mod lensdata; const NIKON_F_MOUNT: &str = "F-mount"; const NIKON_Z_MOUNT: &str = "Z-mount"; // NEF Huffman tables in order. First two are the normal huffman definitions. // Third one are weird shifts that are used in the lossy split encodings only // Values are extracted from dcraw with the shifts unmangled out. const NIKON_TREE: [[[u8; 16]; 3]; 6] = [ [ // 12-bit lossy [0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0], [5, 4, 3, 6, 2, 7, 1, 0, 8, 9, 11, 10, 12, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ], [ // 12-bit lossy after split [0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0], [6, 5, 5, 5, 5, 5, 4, 3, 2, 1, 0, 11, 12, 12, 0, 0], [3, 5, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ], [ // 12-bit lossless [0, 0, 1, 4, 2, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0], [5, 4, 6, 3, 7, 2, 8, 1, 9, 0, 10, 11, 12, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ], [ // 14-bit lossy [0, 0, 1, 4, 3, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0], [5, 6, 4, 7, 8, 3, 9, 2, 1, 0, 10, 11, 12, 13, 14, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ], [ // 14-bit lossy after split [0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0], [8, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 13, 14, 0], [0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ], [ // 14-bit lossless [0, 0, 1, 4, 2, 2, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0], [7, 6, 8, 5, 9, 4, 10, 3, 11, 12, 2, 0, 1, 13, 14, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ], ]; // We use this for the D50 and D2X whacky WB "encryption" const WB_SERIALMAP: [u8; 256] = [ 0xc1, 0xbf, 0x6d, 0x0d, 0x59, 0xc5, 0x13, 0x9d, 0x83, 0x61, 0x6b, 0x4f, 0xc7, 0x7f, 0x3d, 0x3d, 0x53, 0x59, 0xe3, 0xc7, 0xe9, 0x2f, 0x95, 0xa7, 0x95, 0x1f, 0xdf, 0x7f, 0x2b, 0x29, 0xc7, 0x0d, 0xdf, 0x07, 0xef, 0x71, 0x89, 0x3d, 0x13, 0x3d, 0x3b, 0x13, 0xfb, 0x0d, 0x89, 0xc1, 0x65, 0x1f, 0xb3, 0x0d, 0x6b, 0x29, 0xe3, 0xfb, 0xef, 0xa3, 0x6b, 0x47, 0x7f, 0x95, 0x35, 0xa7, 0x47, 0x4f, 0xc7, 0xf1, 0x59, 0x95, 0x35, 0x11, 0x29, 0x61, 0xf1, 0x3d, 0xb3, 0x2b, 0x0d, 0x43, 0x89, 0xc1, 0x9d, 0x9d, 0x89, 0x65, 0xf1, 0xe9, 0xdf, 0xbf, 0x3d, 0x7f, 0x53, 0x97, 0xe5, 0xe9, 0x95, 0x17, 0x1d, 0x3d, 0x8b, 0xfb, 0xc7, 0xe3, 0x67, 0xa7, 0x07, 0xf1, 0x71, 0xa7, 0x53, 0xb5, 0x29, 0x89, 0xe5, 0x2b, 0xa7, 0x17, 0x29, 0xe9, 0x4f, 0xc5, 0x65, 0x6d, 0x6b, 0xef, 0x0d, 0x89, 0x49, 0x2f, 0xb3, 0x43, 0x53, 0x65, 0x1d, 0x49, 0xa3, 0x13, 0x89, 0x59, 0xef, 0x6b, 0xef, 0x65, 0x1d, 0x0b, 0x59, 0x13, 0xe3, 0x4f, 0x9d, 0xb3, 0x29, 0x43, 0x2b, 0x07, 0x1d, 0x95, 0x59, 0x59, 0x47, 0xfb, 0xe5, 0xe9, 0x61, 0x47, 0x2f, 0x35, 0x7f, 0x17, 0x7f, 0xef, 0x7f, 0x95, 0x95, 0x71, 0xd3, 0xa3, 0x0b, 0x71, 0xa3, 0xad, 0x0b, 0x3b, 0xb5, 0xfb, 0xa3, 0xbf, 0x4f, 0x83, 0x1d, 0xad, 0xe9, 0x2f, 0x71, 0x65, 0xa3, 0xe5, 0x07, 0x35, 0x3d, 0x0d, 0xb5, 0xe9, 0xe5, 0x47, 0x3b, 0x9d, 0xef, 0x35, 0xa3, 0xbf, 0xb3, 0xdf, 0x53, 0xd3, 0x97, 0x53, 0x49, 0x71, 0x07, 0x35, 0x61, 0x71, 0x2f, 0x43, 0x2f, 0x11, 0xdf, 0x17, 0x97, 0xfb, 0x95, 0x3b, 0x7f, 0x6b, 0xd3, 0x25, 0xbf, 0xad, 0xc7, 0xc5, 0xc5, 0xb5, 0x8b, 0xef, 0x2f, 0xd3, 0x07, 0x6b, 0x25, 0x49, 0x95, 0x25, 0x49, 0x6d, 0x71, 0xc7, ]; const WB_KEYMAP: [u8; 256] = [ 0xa7, 0xbc, 0xc9, 0xad, 0x91, 0xdf, 0x85, 0xe5, 0xd4, 0x78, 0xd5, 0x17, 0x46, 0x7c, 0x29, 0x4c, 0x4d, 0x03, 0xe9, 0x25, 0x68, 0x11, 0x86, 0xb3, 0xbd, 0xf7, 0x6f, 0x61, 0x22, 0xa2, 0x26, 0x34, 0x2a, 0xbe, 0x1e, 0x46, 0x14, 0x68, 0x9d, 0x44, 0x18, 0xc2, 0x40, 0xf4, 0x7e, 0x5f, 0x1b, 0xad, 0x0b, 0x94, 0xb6, 0x67, 0xb4, 0x0b, 0xe1, 0xea, 0x95, 0x9c, 0x66, 0xdc, 0xe7, 0x5d, 0x6c, 0x05, 0xda, 0xd5, 0xdf, 0x7a, 0xef, 0xf6, 0xdb, 0x1f, 0x82, 0x4c, 0xc0, 0x68, 0x47, 0xa1, 0xbd, 0xee, 0x39, 0x50, 0x56, 0x4a, 0xdd, 0xdf, 0xa5, 0xf8, 0xc6, 0xda, 0xca, 0x90, 0xca, 0x01, 0x42, 0x9d, 0x8b, 0x0c, 0x73, 0x43, 0x75, 0x05, 0x94, 0xde, 0x24, 0xb3, 0x80, 0x34, 0xe5, 0x2c, 0xdc, 0x9b, 0x3f, 0xca, 0x33, 0x45, 0xd0, 0xdb, 0x5f, 0xf5, 0x52, 0xc3, 0x21, 0xda, 0xe2, 0x22, 0x72, 0x6b, 0x3e, 0xd0, 0x5b, 0xa8, 0x87, 0x8c, 0x06, 0x5d, 0x0f, 0xdd, 0x09, 0x19, 0x93, 0xd0, 0xb9, 0xfc, 0x8b, 0x0f, 0x84, 0x60, 0x33, 0x1c, 0x9b, 0x45, 0xf1, 0xf0, 0xa3, 0x94, 0x3a, 0x12, 0x77, 0x33, 0x4d, 0x44, 0x78, 0x28, 0x3c, 0x9e, 0xfd, 0x65, 0x57, 0x16, 0x94, 0x6b, 0xfb, 0x59, 0xd0, 0xc8, 0x22, 0x36, 0xdb, 0xd2, 0x63, 0x98, 0x43, 0xa1, 0x04, 0x87, 0x86, 0xf7, 0xa6, 0x26, 0xbb, 0xd6, 0x59, 0x4d, 0xbf, 0x6a, 0x2e, 0xaa, 0x2b, 0xef, 0xe6, 0x78, 0xb6, 0x4e, 0xe0, 0x2f, 0xdc, 0x7c, 0xbe, 0x57, 0x19, 0x32, 0x7e, 0x2a, 0xd0, 0xb8, 0xba, 0x29, 0x00, 0x3c, 0x52, 0x7d, 0xa8, 0x49, 0x3b, 0x2d, 0xeb, 0x25, 0x49, 0xfa, 0xa3, 0xaa, 0x39, 0xa7, 0xc5, 0xa7, 0x50, 0x11, 0x36, 0xfb, 0xc6, 0x67, 0x4a, 0xf5, 0xa5, 0x12, 0x65, 0x7e, 0xb0, 0xdf, 0xaf, 0x4e, 0xb3, 0x61, 0x7f, 0x2f, ]; /// NEF format encapsulation for analyzer #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct NefFormat { tiff: GenericTiffReader, } #[derive(Debug, Clone)] pub struct NefDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, makernote: IFD, camera: Camera, } impl<'a> NefDecoder<'a> { pub fn new(file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { let raw = tiff .find_first_ifd_with_tag(TiffCommonTag::CFAPattern) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with CFAPattern tag")))?; let bps = fetch_tiff_tag!(raw, TiffCommonTag::BitsPerSample).force_usize(0); // Make sure we always use a 12/14 bit mode to get correct white/blackpoints let mode = format!("{}bit", bps); let camera = rawloader.check_supported_with_mode(tiff.root_ifd(), &mode)?; let makernote = if let Some(exif) = tiff.find_first_ifd_with_tag(ExifTag::MakerNotes) { exif.parse_makernote(&mut file.reader(), OffsetMode::Absolute, &[])? } else { warn!("NEF makernote not found"); None } .ok_or("File has not makernotes")?; //makernote.dump::(0).iter().for_each(|line| eprintln!("DUMP: {}", line)); Ok(NefDecoder { tiff, rawloader, makernote, camera, }) } } impl<'a> Decoder for NefDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let raw = self .tiff .find_first_ifd_with_tag(TiffCommonTag::CFAPattern) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with CFAPattern tag")))?; let mut width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let bps = fetch_tiff_tag!(raw, TiffCommonTag::BitsPerSample).force_usize(0); let compression = fetch_tiff_tag!(raw, TiffCommonTag::Compression).force_usize(0); let nef_compression = if let Some(z_makernote) = self.makernote.get_entry(NikonMakernote::Makernotes0x51) { // For new Z models, a new tag 0x51 for makernotes appears. This contains // The new-old NEFCompression tag. The old tag is unavailable in this models. Some(NefCompression::try_from(crate::bits::LEu16(z_makernote.get_data(), 10)).map_err(RawlerError::from)?) } else { self .makernote .get_entry(NikonMakernote::NefCompression) .map(|entry| entry.force_u16(0)) .map(NefCompression::try_from) .transpose() .map_err(RawlerError::from)? }; debug!("TIFF compression flag: {}, NEF compression mode: {:?}", compression, nef_compression); if matches!(nef_compression, Some(NefCompression::HighEfficency)) || matches!(nef_compression, Some(NefCompression::HighEfficencyStar)) { return Err(RawlerError::DecoderFailed(format!("NEF compression {:?} is not supported", nef_compression))); } let offset = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); let size = fetch_tiff_tag!(raw, TiffCommonTag::StripByteCounts).force_usize(0); let rows_per_strip = fetch_tiff_tag!(raw, TiffCommonTag::RowsPerStrip).get_usize(0).ok().flatten().unwrap_or(height); // That's little bit hacky here. Some files like D500 using multiple strips. // Because the strips has no holes between and are perfectly aligned, we can process the whole // chunk at once, instead of iterating over every strip. // It would be safer to process each strip offset, but it is not need for any known model so far. let src = if rows_per_strip == height { file.subview_padded(offset as u64, size as u64)? } else { let full_size: u32 = match fetch_tiff_tag!(raw, TiffCommonTag::StripByteCounts) { Value::Long(data) => data.iter().copied().sum(), _ => { return Err("StripByteCounts is not of type LONG".into()); } }; file.subview_padded(offset as u64, full_size as u64)? }; let mut cpp = 1; let coeffs = normalize_wb(self.get_wb()?); debug!("WB coeff: {:?}", coeffs); assert_eq!(self.tiff.little_endian(), self.makernote.endian == Endian::Little); let image = if self.camera.model == "NIKON D100" { width = 3040; decode_12be_wcontrol(&src, width, height, dummy) } else if self.camera.find_hint("coolpixsplit") { decode_12be_interlaced_unaligned(&src, width, height, dummy) } else if self.camera.find_hint("msb32") { decode_12be_msb32(&src, width, height, dummy) } else if self.camera.find_hint("unpacked") { // P7800 and others is LE, but data is BE, so we use hints here if (self.tiff.little_endian() || self.camera.find_hint("little_endian")) && !self.camera.find_hint("big_endian") { decode_16le(&src, width, height, dummy) } else { decode_16be(&src, width, height, dummy) } } else if let Some(padding) = self.is_uncompressed(raw)? { debug!("NEF uncompressed row padding: {}, little-endian: {}", padding, self.tiff.little_endian()); match bps { 14 => { if (self.tiff.little_endian() || self.camera.find_hint("little_endian")) && !self.camera.find_hint("big_endian") { // Models like D6 uses packed instead of unpacked 14le encoding. And D6 uses // row padding. if matches!(nef_compression, Some(NefCompression::Packed14Bits)) { decode_14le_padded(&src, width, height, (width * bps / u8::BITS as usize) + padding, dummy) } else { decode_14le_unpacked(&src, width, height, dummy) } } else { decode_14be_unpacked(&src, width, height, dummy) } } 12 => { if (self.tiff.little_endian() || self.camera.find_hint("little_endian")) && !self.camera.find_hint("big_endian") { decode_12le_padded(&src, width, height, (width * bps / u8::BITS as usize) + padding, dummy) } else { decode_12be(&src, width, height, dummy) } } x => return Err(RawlerError::unsupported(&self.camera, format!("Don't know uncompressed bps {}", x))), } } else if size == width * height * 3 { cpp = 3; Self::decode_snef_compressed(&src, coeffs, width, height, dummy) } else if compression == 34713 { self.decode_compressed(&src, width, height, bps, dummy)? } else { return Err(RawlerError::unsupported(&self.camera, format!("NEF: Don't know compression {}", compression))); }; assert_eq!(image.width, width * cpp); let blacklevel = self.get_blacklevel(bps)?; let whitelevel = None; let photometric = match cpp { 1 => RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&self.camera)), 3 => RawPhotometricInterpretation::LinearRaw, _ => todo!(), }; let mut img = RawImage::new(self.camera.clone(), image, cpp, coeffs, photometric, blacklevel, whitelevel, dummy); if let Some(crop) = self.get_crop()? { debug!("RAW Crops: {:?}", crop); img.crop_area = Some(crop); } if cpp == 3 { // Reset levels to defaults (0) img.blacklevel = BlackLevel::default(); img.whitelevel = WhiteLevel::new(vec![65535; cpp]); } Ok(img) } fn format_dump(&self) -> FormatDump { FormatDump::Nef(NefFormat { tiff: self.tiff.clone() }) } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; //let mdata = RawMetadata::new(&self.camera, exif); let mdata = RawMetadata::new_with_lens(&self.camera, exif, self.get_lens_description()?.cloned()); Ok(mdata) } fn full_image(&self, file: &RawSource, params: &RawDecodeParams) -> Result> { if params.image_index != 0 { return Ok(None); } let root_ifd = &self.tiff.root_ifd(); if !root_ifd.contains_singlestrip_image() { // TODO: implement multistrip return Ok(None); } let buf = root_ifd .singlestrip_data_rawsource(file) .map_err(|e| RawlerError::DecoderFailed(format!("Failed to get strip data: {}", e)))?; let compression = root_ifd.get_entry(TiffCommonTag::Compression).ok_or("Missing tag")?.force_usize(0); let width = fetch_tiff_tag!(root_ifd, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(root_ifd, TiffCommonTag::ImageLength).force_usize(0); if compression == 1 { Ok(Some(DynamicImage::ImageRgb8( ImageBuffer::, Vec>::from_raw(width as u32, height as u32, buf.to_vec()) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to read image")))?, ))) } else { let img = image::load_from_memory_with_format(buf, image::ImageFormat::Jpeg) .map_err(|err| RawlerError::DecoderFailed(format!("Failed to read JPEG image: {:?}", err)))?; Ok(Some(img)) } } fn format_hint(&self) -> FormatHint { FormatHint::NEF } } impl<'a> NefDecoder<'a> { /// For older formats, we use the camera definitions and this here /// is useless. But if we found here the levels in makernotes, we /// use these instead. For 12 bit images, the blacklevels are still relative to /// 14 bit image data. So we need to reduce them by 2 bits. fn get_blacklevel(&self, bps: usize) -> Result> { if let Some(levels) = self.makernote.get_entry(NikonMakernote::BlackLevel) { let mut black = [levels.force_u16(0), levels.force_u16(1), levels.force_u16(2), levels.force_u16(3)]; if bps == 12 { black.iter_mut().for_each(|v| *v >>= 14 - 12); } Ok(Some(BlackLevel::new(&black, self.camera.cfa.width, self.camera.cfa.height, 1))) } else { Ok(None) } } fn get_crop(&self) -> Result> { if let Some(crop) = self.makernote.get_entry(NikonMakernote::CropArea) { let values = [crop.force_u16(0), crop.force_u16(1), crop.force_u16(2), crop.force_u16(3)]; let rect = Rect::new( Point::new(values[0] as usize, values[1] as usize), Dim2::new(values[2] as usize, values[3] as usize), ); Ok(Some(rect)) } else { Ok(None) } } /// Get lens description by analyzing TIFF tags and makernotes fn get_lens_description(&self) -> Result> { if let Some(lensdata) = lensdata::from_makernote(&self.makernote)? { if let Some(lenstype) = self.makernote.get_entry(NikonMakernote::LensType) { match lensdata { NefLensData::FMount(oldv) => { let composite_id = oldv.composite_id(lenstype.force_u8(0)); log::debug!("NEF lens composite ID: {}", composite_id); let resolver = LensResolver::new() .with_nikon_id(Some(composite_id)) .with_camera(&self.camera) .with_mounts(&[NIKON_F_MOUNT.into()]); return Ok(resolver.resolve()); } NefLensData::ZMount(newv) => { let resolver = LensResolver::new() .with_lens_id((newv.lens_id as u32, 0)) .with_camera(&self.camera) .with_mounts(&[NIKON_Z_MOUNT.into()]); return Ok(resolver.resolve()); } } } } Ok(None) } fn get_wb(&self) -> Result<[f32; 4]> { if self.camera.find_hint("nowb") { Ok([f32::NAN, f32::NAN, f32::NAN, f32::NAN]) } else if let Some(levels) = self.makernote.get_entry(TiffCommonTag::NefWB0) { Ok([levels.force_f32(0), 1.0, 1.0, levels.force_f32(1)]) } else if let Some(levels) = self.makernote.get_entry(TiffCommonTag::NrwWB) { let data = levels.get_data(); if data[0..3] == b"NRW"[..] { let offset = if data[4..8] == b"0100"[..] { 1556 } else { 56 }; Ok([ (LEu32(data, offset) << 2) as f32, (LEu32(data, offset + 4) + LEu32(data, offset + 8)) as f32, (LEu32(data, offset + 4) + LEu32(data, offset + 8)) as f32, (LEu32(data, offset + 12) << 2) as f32, ]) } else { Ok([BEu16(data, 1248) as f32, 256.0, 256.0, BEu16(data, 1250) as f32]) } } else if let Some(levels) = self.makernote.get_entry(TiffCommonTag::NefWB1) { let mut version: u32 = 0; for i in 0..4 { version = (version << 4) + (levels.get_data()[i] - b'0') as u32; } let buf = levels.get_data(); debug!("NEF Color balance version: 0x{:x}", version); match version { 0x100 => Ok([ BEu16(buf, 36 * 2) as f32, BEu16(buf, 38 * 2) as f32, BEu16(buf, 38 * 2) as f32, BEu16(buf, 37 * 2) as f32, ]), // Nikon D2H 0x102 => Ok([ BEu16(buf, 5 * 2) as f32, BEu16(buf, 6 * 2) as f32, BEu16(buf, 6 * 2) as f32, BEu16(buf, 8 * 2) as f32, ]), // Nikon D70 0x103 => Ok([ BEu16(buf, 10 * 2) as f32, BEu16(buf, 11 * 2) as f32, BEu16(buf, 11 * 2) as f32, BEu16(buf, 12 * 2) as f32, ]), 0x204 | 0x205 => { let serial = fetch_tiff_tag!(self.makernote, TiffCommonTag::NefSerial); let data = serial.get_data(); let mut serialno = 0_usize; for i in 0..serial.count() as usize { if data[i] == 0 { break; } serialno = serialno * 10 + if data[i] >= 48 && data[i] <= 57 { // "0" to "9" (data[i] - 48) as usize } else { (data[i] % 10) as usize }; } // Get the "decryption" key let keydata = fetch_tiff_tag!(self.makernote, TiffCommonTag::NefKey).force_u32(0).to_le_bytes(); let keyno = (keydata[0] ^ keydata[1] ^ keydata[2] ^ keydata[3]) as usize; let src = if version == 0x204 { &levels.get_data()[284..] } else { &levels.get_data()[4..] }; let ci = WB_SERIALMAP[serialno & 0xff] as u32; let mut cj = WB_KEYMAP[keyno & 0xff] as u32; let mut ck = 0x60_u32; let mut buf = [0_u8; 280]; for i in 0..280 { cj += ci * ck; ck += 1; buf[i] = src[i] ^ (cj as u8); } let off = if version == 0x204 { 6 } else { 14 }; Ok([ BEu16(&buf, off) as f32, BEu16(&buf, off + 2) as f32, BEu16(&buf, off + 4) as f32, BEu16(&buf, off + 6) as f32, ]) } x => Err(RawlerError::unsupported(&self.camera, format!("NEF: Don't know about WB version 0x{:x}", x))), } } else { Err(RawlerError::DecoderFailed("NEF: Don't know how to fetch WB".to_string())) } } fn create_hufftable(num: usize) -> Result { let mut htable = HuffTable::empty(); for i in 0..15 { htable.bits[i] = NIKON_TREE[num][0][i] as u32; htable.huffval[i] = NIKON_TREE[num][1][i] as u32; htable.shiftval[i] = NIKON_TREE[num][2][i] as u32; } htable.initialize()?; Ok(htable) } /// The compression flags in some raws are not reliable because of firmware bugs. /// We try to figure out the compression by some heuristics. /// The return value is None if the file is not uncompressed or Some(x) /// where x is the extra amount of bytes after each row. fn is_uncompressed(&self, raw: &IFD) -> Result> { let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let bps = fetch_tiff_tag!(raw, TiffCommonTag::BitsPerSample).force_usize(0); let compression = fetch_tiff_tag!(raw, TiffCommonTag::Compression).force_usize(0); let size = fetch_tiff_tag!(raw, TiffCommonTag::StripByteCounts).force_usize(0); fn div_round_up(a: usize, b: usize) -> usize { a.div_ceil(b) // (a + b - 1) / b } let req_pixels = width * height; let req_input_bits = bps * req_pixels; let req_input_bytes = div_round_up(req_input_bits, 8); Ok(if compression == 1 || size == width * height * bps / 8 { Some(0) } else if size >= req_input_bytes { // Some models (D6) using row padding, so the row width is slightly larger. // This should be no more than 16 extra bytes. let total_padding = size - req_input_bytes; let per_row_padding = total_padding / height; if total_padding % height != 0 { None } else if per_row_padding < 16 { Some(per_row_padding) } else { None } } else { None }) } fn decode_compressed(&self, src: &PaddedBuf, width: usize, height: usize, bps: usize, dummy: bool) -> Result { let meta = if let Some(meta) = self.makernote.get_entry(TiffCommonTag::NefMeta2) { debug!("Found NefMeta2"); meta } else { debug!("Fallback NefMeta1"); fetch_tiff_tag!(self.makernote, TiffCommonTag::NefMeta1) }; Self::do_decode(src, meta.get_data(), self.makernote.endian, width, height, bps, dummy) } pub(crate) fn do_decode(src: &[u8], meta: &[u8], endian: Endian, width: usize, height: usize, bps: usize, dummy: bool) -> Result { debug!("NEF decode with: endian: {:?}, width: {}, height: {}, bps: {}", endian, width, height, bps); let mut out = alloc_image_ok!(width, height, dummy); let mut stream = ByteStream::new(meta, endian); let v0 = stream.get_u8(); let v1 = stream.get_u8(); debug!("Nef version v0:{}, v1:{}", v0, v1); let mut huff_select = 0; if v0 == 73 || v1 == 88 { assert!(stream.remaining_bytes() >= 2110); stream.consume_bytes(2110); } if v0 == 70 { huff_select = 2; } if bps == 14 { huff_select += 3; } // Create the huffman table used to decode let mut htable = Self::create_hufftable(huff_select)?; // Setup the predictors let mut pred_up1: [i32; 2] = [stream.get_u16() as i32, stream.get_u16() as i32]; let mut pred_up2: [i32; 2] = [stream.get_u16() as i32, stream.get_u16() as i32]; // Get the linearization curve let mut points = [0_u16; 1 << 16]; for i in 0..points.len() { points[i] = i as u16; } // Some models reports 14 bits, but the data is 12 bits. // So we reduce the bps to calculate the max value which // is needed in the next steps. let real_bps = if v0 == 68 && v1 == 64 { bps as u32 - 2 // Special for D780, Z7 and others } else { bps as u32 }; let mut max = 1 << real_bps; let csize = stream.get_u16() as usize; let mut split = 0_usize; let step = if csize > 1 { max / (csize - 1) } else { 0 }; if v0 == 68 && (v1 == 32 || v1 == 64) && step > 0 { for i in 0..csize { points[i * step] = stream.get_u16(); } for i in 0..max { let b_scale = i % step; let a_pos = i - b_scale; let b_pos = a_pos + step; //assert!(a_pos < max); //assert!(b_pos > 0); //assert!(b_pos < max); //assert!(a_pos < b_pos); let a_scale = step - b_scale; points[i] = ((a_scale * points[a_pos] as usize + b_scale * points[b_pos] as usize) / step) as u16; } split = endian.read_u16(meta, 562) as usize; } else if v0 != 70 && csize <= 0x4001 { for i in 0..csize { points[i] = stream.get_u16(); } max = csize; } let curve = LookupTable::new(&points[0..max]); let mut pump = BitPumpMSB::new(src); let mut random = pump.peek_bits(24); for row in 0..height { if split > 0 && row == split { htable = Self::create_hufftable(huff_select + 1)?; } pred_up1[row & 1] += htable.huff_decode(&mut pump)?; pred_up2[row & 1] += htable.huff_decode(&mut pump)?; let mut pred_left1 = pred_up1[row & 1]; let mut pred_left2 = pred_up2[row & 1]; for col in (0..width).step_by(2) { if col > 0 { pred_left1 += htable.huff_decode(&mut pump)?; pred_left2 += htable.huff_decode(&mut pump)?; } out[row * width + col + 0] = curve.dither(clampbits(pred_left1, real_bps), &mut random); out[row * width + col + 1] = curve.dither(clampbits(pred_left2, real_bps), &mut random); } } Ok(out) } // Decodes 12 bit data in an YUY2-like pattern (2 Luma, 1 Chroma per 2 pixels). // We un-apply the whitebalance, so output matches lossless. pub(crate) fn decode_snef_compressed(src: &PaddedBuf, coeffs: [f32; 4], width: usize, height: usize, dummy: bool) -> PixU16 { let inv_wb_r = (1024.0 / coeffs[0]) as i32; let inv_wb_b = (1024.0 / coeffs[2]) as i32; //println!("Got invwb {} {}", inv_wb_r, inv_wb_b); let snef_curve = { let g: f32 = 2.4; let f: f32 = 0.055; let min: f32 = 0.04045; let mul: f32 = 12.92; let curve = (0..4096) .map(|i| { let v = (i as f32) / 4095.0; let res = if v <= min { v / mul } else { ((v + f) / (1.0 + f)).powf(g) }; clampbits((res * 65535.0 * 4.0) as i32, 16) }) .collect::>(); LookupTable::new(&curve) }; decode_threaded( width * 3, height, dummy, &(|out: &mut [u16], row| { let inb = &src[row * width * 3..]; let mut random = BEu32(inb, 0); for (o, i) in out.chunks_exact_mut(6).zip(inb.chunks_exact(6)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; let g4: u16 = i[3] as u16; let g5: u16 = i[4] as u16; let g6: u16 = i[5] as u16; let y1 = (g1 | ((g2 & 0x0f) << 8)) as f32; let y2 = ((g2 >> 4) | (g3 << 4)) as f32; let cb = (g4 | ((g5 & 0x0f) << 8)) as f32 - 2048.0; let cr = ((g5 >> 4) | (g6 << 4)) as f32 - 2048.0; let r = snef_curve.dither(clampbits((y1 + 1.370705 * cr) as i32, 12), &mut random); let g = snef_curve.dither(clampbits((y1 - 0.337633 * cb - 0.698001 * cr) as i32, 12), &mut random); let b = snef_curve.dither(clampbits((y1 + 1.732446 * cb) as i32, 12), &mut random); // invert the white balance o[0] = clampbits((inv_wb_r * r as i32 + (1 << 9)) >> 10, 15); o[1] = g; o[2] = clampbits((inv_wb_b * b as i32 + (1 << 9)) >> 10, 15); let r = snef_curve.dither(clampbits((y2 + 1.370705 * cr) as i32, 12), &mut random); let g = snef_curve.dither(clampbits((y2 - 0.337633 * cb - 0.698001 * cr) as i32, 12), &mut random); let b = snef_curve.dither(clampbits((y2 + 1.732446 * cb) as i32, 12), &mut random); // invert the white balance o[3] = clampbits((inv_wb_r * r as i32 + (1 << 9)) >> 10, 15); o[4] = g; o[5] = clampbits((inv_wb_b * b as i32 + (1 << 9)) >> 10, 15); } }), ) } } fn normalize_wb(raw_wb: [f32; 4]) -> [f32; 4] { debug!("NEF raw wb: {:?}", raw_wb); // We never have more then RGB colors so far (no RGBE etc.) // So we combine G1 and G2 to get RGB wb. let div = raw_wb[1]; let mut norm = raw_wb; norm.iter_mut().for_each(|v| { if v.is_normal() { *v /= div } }); [norm[0], (norm[1] + norm[2]) / 2.0, norm[3], f32::NAN] } crate::tags::tiff_tag_enum!(NikonMakernote); #[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum NikonMakernote { MakernoteVersion = 0x0001, NefWB0 = 0x000C, PreviewIFD = 0x0011, NrwWB = 0x0014, NefSerial = 0x001d, ImageSizeRaw = 0x003e, CropArea = 0x0045, BlackLevel = 0x003d, Makernotes0x51 = 0x0051, LensType = 0x0083, NefMeta1 = 0x008c, NefMeta2 = 0x0096, ShotInfo = 0x0091, NefCompression = 0x0093, NefWB1 = 0x0097, LensData = 0x0098, NefKey = 0x00a7, } /// Known NEF compression formats #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[allow(non_camel_case_types)] enum NefCompression { LossyType1 = 1, Uncompressed = 2, Lossless = 3, LossyType2 = 4, StripedPacked12Bits = 5, UncompressedReduced12Bits = 6, Unpacked12Bits = 7, Small = 8, Packed12Bits = 9, Packed14Bits = 10, HighEfficency = 13, HighEfficencyStar = 14, } impl TryFrom for NefCompression { type Error = String; fn try_from(v: u16) -> std::result::Result { Ok(match v { 1 => Self::LossyType1, 2 => Self::Uncompressed, 3 => Self::Lossless, 4 => Self::LossyType2, 5 => Self::StripedPacked12Bits, 6 => Self::UncompressedReduced12Bits, 7 => Self::Unpacked12Bits, 8 => Self::Small, 9 => Self::Packed12Bits, 10 => Self::Packed14Bits, 13 => Self::HighEfficency, 14 => Self::HighEfficencyStar, _ => return Err(format!("unknown nef compression: {}", v)), }) } } rawler-0.7.1/src/decoders/nkd.rs000064400000000000000000000034571046102023000146370ustar 00000000000000use super::{Camera, Decoder, FormatHint, RawDecodeParams, RawMetadata, ok_cfa_image}; use crate::Result; use crate::analyze::FormatDump; use crate::exif::Exif; use crate::packed::{decode_10le_lsb16, decode_12be_msb16, decode_12le_16bitaligned}; use crate::rawsource::RawSource; use crate::{RawImage, RawLoader, RawlerError}; #[derive(Debug, Clone)] pub struct NakedDecoder<'a> { #[allow(dead_code)] rawloader: &'a RawLoader, camera: Camera, } impl<'a> NakedDecoder<'a> { pub fn new(camera: Camera, rawloader: &'a RawLoader) -> Result> { Ok(NakedDecoder { rawloader, camera }) } } impl<'a> Decoder for NakedDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let data = file.as_vec()?; let buffer = &data; let width = self.camera.raw_width; let height = self.camera.raw_height; let size = self.camera.filesize; let bits = size * 8 / width / height; let image = if self.camera.find_hint("12le_16bitaligned") { decode_12le_16bitaligned(buffer, width, height, dummy) } else { match bits { 10 => decode_10le_lsb16(buffer, width, height, dummy), 12 => decode_12be_msb16(buffer, width, height, dummy), _ => return Err(RawlerError::unsupported(&self.camera, format!("Naked: Don't know about {} bps images", bits))), } }; let cpp = 1; ok_cfa_image(self.camera.clone(), cpp, [f32::NAN, f32::NAN, f32::NAN, f32::NAN], image, dummy) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let exif = Exif::default(); let mdata = RawMetadata::new(&self.camera, exif); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::Unknown } } rawler-0.7.1/src/decoders/nrw.rs000064400000000000000000000002151046102023000146560ustar 00000000000000/// The Nef decoder can be used for NRW files, too, /// so this is just an type alias. pub type NrwDecoder<'a> = super::nef::NefDecoder<'a>; rawler-0.7.1/src/decoders/orf.rs000064400000000000000000000420531046102023000146440ustar 00000000000000use std::cmp; use std::io::Read; use std::io::Seek; use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::alloc_image; use crate::analyze::FormatDump; use crate::buffer::PaddedBuf; use crate::exif::Exif; use crate::formats::tiff::Entry; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::IFD; use crate::formats::tiff::Rational; use crate::formats::tiff::Value; use crate::formats::tiff::reader::TiffReader; use crate::imgop::Dim2; use crate::imgop::Point; use crate::imgop::Rect; use crate::lens::LensDescription; use crate::lens::LensResolver; use crate::packed::*; use crate::pixarray::PixU16; use crate::pumps::BitPump; use crate::pumps::BitPumpMSB; use crate::rawimage::CFAConfig; use crate::rawimage::RawPhotometricInterpretation; use crate::rawsource::RawSource; use crate::tags::ExifTag; use crate::tags::TiffCommonTag; use super::BlackLevel; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; const MFT_MOUNT: &str = "MFT-mount"; #[derive(Debug, Clone)] pub struct OrfDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, camera: Camera, makernote: IFD, } pub fn parse_makernote(reader: &mut R, exif_ifd: &IFD) -> Result> { if let Some(exif) = exif_ifd.get_entry(ExifTag::MakerNotes) { let offset = exif.offset().unwrap() as u32; log::debug!("Makernote offset: {}", offset); match &exif.value { Value::Undefined(data) => { let mut off = 0; // Olympus starts the makernote with their own name, sometimes truncated if data[0..5] == b"OLYMP"[..] { off += 8; if data[0..7] == b"OLYMPUS"[..] { off += 4; } } // OM Digital Solutions put their name in front of the TIFF structure, too if data[0..9] == b"OM SYSTEM"[..] { off += 16; assert_eq!(data[12..14], b"II"[..]); } let endian = exif_ifd.endian; //assert!(data[off..off + 2] == b"II"[..] || data[off..off + 2] == b"MM"[..], "ORF: must contain endian marker in makernote IFD"); //let endian = if data[off..off + 2] == b"II"[..] { Endian::Little } else { Endian::Big }; //off += 4; let mut mainifd = IFD::new(reader, offset + off as u32, exif_ifd.base, exif_ifd.corr, endian, &[0x3000])?; // Parse the Olympus Equipment section if it exists if let Some(entry) = mainifd.get_entry_raw_with_len(OrfMakernotes::EquipmentIFD, reader, 4)? { // The entry is of type UNDEFINED and count = 1. This tag contains a single 32 bit // offset to the IFD. let ioff = entry.get_force_u32(0); log::debug!("Found EquipmentIFD at offset: {}", ioff); // The IFD start at offset+ioff, but all offsets inside the IFD a relative to the main makernote IFD offset. // So we use the main IFD as base offset, but start parsing IFD at ioff. let ifd = IFD::new(reader, ioff, offset, 0, endian, &[])?; mainifd.sub.insert(OrfMakernotes::EquipmentIFD.into(), vec![ifd]); } // For Olympus or OM-System models if off == 12 || off == 16 { // Parse the Olympus ImgProc section if it exists let ioff = if let Some(entry) = mainifd.get_entry_raw_with_len(OrfMakernotes::ImageProcessingIFD, reader, 4)? { // The entry is of type UNDEFINED and count = 1. This tag contains a single 32 bit // offset to the IFD. entry.get_force_u32(0) } else { 0 }; if ioff != 0 { log::debug!("Found ImageIFD at offset: {}", ioff); // The IFD start at offset+ioff, but all offsets inside the IFD a relative to the main makernote IFD offset. // So we use the main IFD as base offset, but start parsing IFD at ioff. let iprocifd = IFD::new(reader, ioff, offset, 0, endian, &[])?; mainifd.sub.insert(OrfMakernotes::ImageProcessingIFD.into(), vec![iprocifd]); } else { log::debug!("ORF ImageIFD not found"); } } Ok(Some(mainifd)) } _ => Err(RawlerError::DecoderFailed("EXIF makernote has unknown type".to_string())), } } else { Ok(None) } } impl<'a> OrfDecoder<'a> { pub fn new(file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { let camera = rawloader.check_supported(tiff.root_ifd())?; let makernote = if let Some(exif) = tiff.find_first_ifd_with_tag(ExifTag::MakerNotes) { parse_makernote(&mut file.reader(), exif)? } else { log::warn!("ORF makernote not found"); None } .ok_or("File has not makernotes")?; //makernote.dump::(0).iter().for_each(|line| eprintln!("DUMP: {}", line)); Ok(OrfDecoder { tiff, rawloader, camera, makernote, }) } } impl<'a> Decoder for OrfDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let raw = self .tiff .find_first_ifd_with_tag(TiffCommonTag::StripOffsets) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with StripOffsets tag")))?; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let offset = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); let counts = fetch_tiff_tag!(raw, TiffCommonTag::StripByteCounts); let bps = match self.get_bits_per_pixel()? { Some(bps) if [12, 14].contains(&bps) => bps, Some(bps) => { log::warn!("Unsupported bps: {}", bps); bps } None => { log::debug!("No bps found, fallback to 12"); 12 } } as usize; let mut size: usize = 0; for i in 0..counts.count() { size += counts.force_u32(i as usize) as usize; } let camera = if width >= self.camera.highres_width { self.rawloader.check_supported_with_mode(self.tiff.root_ifd(), "highres")? } else { self.camera.clone() }; let src = file.subview_padded(offset as u64, size as u64)?; // TODO add size and check all samples log::debug!( "ORF raw image size: {}, dim: {}x{}, total mp: {}, strip counts: {}", size, width, height, width * height, counts.count() ); // These conditions are sorted in descending order. // All ORF files comes with no hints about the used compression. // But we need to differentiate between 12be-interlaced and // 12be-msb32 because they are in the same size range. let image = if size >= width * height * 2 { if self.tiff.little_endian() { log::debug!("ORF: decode_12le_unpacked_left_aligned"); decode_12le_unpacked_left_aligned(&src, width, height, dummy) } else { log::debug!("ORF: decode_12be_unpacked_left_aligned"); decode_12be_unpacked_left_aligned(&src, width, height, dummy) } } else if size >= width * height / 10 * 16 { log::debug!("ORF: decode_12le_wcontrol"); decode_12le_wcontrol(&src, width, height, dummy) } else if size >= width * height * 12 / 8 { if self.camera.find_hint("interlaced") { log::debug!("ORF: decode_12be_interlaced"); decode_12be_interlaced(&src, width, height, dummy) } else { log::debug!("ORF: decode_12be_msb32"); //decode_12be_interlaced(&src, width, height, dummy) decode_12be_msb32(&src, width, height, dummy) } } else { log::debug!("ORF: fallback to decode_compressed"); OrfDecoder::decode_compressed(&src, width, height, bps, dummy) }; let cpp = 1; let blacklevel = self.get_blacklevel(bps)?; let whitelevel = None; let photometric = RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&self.camera)); let mut img = RawImage::new(camera, image, cpp, normalize_wb(self.get_wb()?), photometric, blacklevel, whitelevel, dummy); if let Some(crop) = self.get_crop()? { img.crop_area = Some(crop); } if bps == 14 { // Blacklevel is already corrected, only required for whitelevel. // Encoded for 12 bps, whitelevel must be multiplied by 4. img.whitelevel.0.iter_mut().for_each(|level| *level = *level << 2); } Ok(img) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, __params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; let mdata = RawMetadata::new_with_lens(&self.camera, exif, self.get_lens_description()?.cloned()); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::ORF } } impl<'a> OrfDecoder<'a> { /* This is probably the slowest decoder of them all. * I cannot see any way to effectively speed up the prediction * phase, which is by far the slowest part of this algorithm. * Also there is no way to multithread this code, since prediction * is based on the output of all previous pixel (bar the first four) */ pub fn decode_compressed(buf: &PaddedBuf, width: usize, height: usize, bps: usize, dummy: bool) -> PixU16 { let mut out = alloc_image!(width, height, dummy); /* Build a table to quickly look up "high" value */ let mut bittable: [u8; 4096] = [0; 4096]; for i in 0..4096 { let mut b = 12; for high in 0..12 { if ((i >> (11 - high)) & 1) != 0 { b = high; break; } } bittable[i] = b; } let mut left: [i32; 2] = [0; 2]; let mut nw: [i32; 2] = [0; 2]; let skip = if bps == 14 { 8 } else { 7 }; let mut pump = BitPumpMSB::new(&buf[skip..]); for row in 0..height { let mut acarry: [[i32; 3]; 2] = [[0; 3]; 2]; for c in 0..width / 2 { let col: usize = c * 2; for s in 0..2 { // Run twice for odd and even pixels let i = if acarry[s][2] < 3 { 2 } else { 0 }; let mut nbits = 2 + i; while ((acarry[s][0] >> (nbits + i)) & 0xffff) > 0 { nbits += 1 } nbits = cmp::min(nbits, 16); let b = pump.peek_ibits(15); let sign: i32 = -(b >> 14); let low: i32 = (b >> 12) & 3; let mut high: i32 = bittable[(b & 4095) as usize] as i32; // Skip bytes used above or read bits if high == 12 { pump.consume_bits(15); high = pump.get_ibits(16 - nbits) >> 1; } else { pump.consume_bits((high + 4) as u32); } acarry[s][0] = ((high << nbits) | pump.get_ibits(nbits)) as i32; let diff = (acarry[s][0] ^ sign) + acarry[s][1]; acarry[s][1] = (diff * 3 + acarry[s][1]) >> 5; acarry[s][2] = if acarry[s][0] > 16 { 0 } else { acarry[s][2] + 1 }; if row < 2 || col < 2 { // We're in a border, special care is needed let pred = if row < 2 && col < 2 { // We're in the top left corner 0 } else if row < 2 { // We're going along the top border left[s] } else { // col < 2, we're at the start of a line nw[s] = out[(row - 2) * width + (col + s)] as i32; nw[s] }; left[s] = pred + ((diff << 2) | low); out[row * width + (col + s)] = left[s] as u16; } else { let up: i32 = out[(row - 2) * width + (col + s)] as i32; let left_minus_nw: i32 = left[s] - nw[s]; let up_minus_nw: i32 = up - nw[s]; // Check if sign is different, and one is not zero let pred = if left_minus_nw * up_minus_nw < 0 { if left_minus_nw.abs() > 32 || up_minus_nw.abs() > 32 { left[s] + up_minus_nw } else { (left[s] + up) >> 1 } } else if left_minus_nw.abs() > up_minus_nw.abs() { left[s] } else { up }; left[s] = pred + ((diff << 2) | low); nw[s] = up; out[row * width + (col + s)] = left[s] as u16; } } } } out } fn get_blacklevel(&self, bps: usize) -> Result> { let ifd = self.makernote.find_ifds_with_tag(OrfImageProcessing::OrfBlackLevels); if ifd.is_empty() { log::info!("ORF: Couldn't find ImgProc IFD, unable to read blacklevel"); return Ok(None); } let blacks = fetch_tiff_tag!(ifd[0], OrfImageProcessing::OrfBlackLevels); let mut levels = [blacks.force_u16(0), blacks.force_u16(1), blacks.force_u16(2), blacks.force_u16(3)]; if bps == 14 { // Blacklevel is encoded for 12 bits levels.iter_mut().for_each(|level| *level = *level << 2); } Ok(Some(BlackLevel::new(&levels, self.camera.cfa.width, self.camera.cfa.height, 1))) } fn get_bits_per_pixel(&self) -> Result> { let ifd = self.makernote.find_ifds_with_tag(OrfImageProcessing::ValidBits); if ifd.is_empty() { return Ok(None); } Ok(Some(fetch_tiff_tag!(ifd[0], OrfImageProcessing::ValidBits).force_u16(0))) } fn get_crop(&self) -> Result> { let ifd = self.makernote.find_ifds_with_tag(OrfImageProcessing::CropLeft); if ifd.is_empty() { return Ok(None); } let crop_left = fetch_tiff_tag!(ifd[0], OrfImageProcessing::CropLeft).force_usize(0); let crop_top = fetch_tiff_tag!(ifd[0], OrfImageProcessing::CropTop).force_usize(0); let crop_width = fetch_tiff_tag!(ifd[0], OrfImageProcessing::CropWidth).force_usize(0); let crop_height = fetch_tiff_tag!(ifd[0], OrfImageProcessing::CropHeight).force_usize(0); Ok(Some(Rect::new(Point::new(crop_left, crop_top), Dim2::new(crop_width, crop_height)))) } /// Get lens description by analyzing TIFF tags and makernotes fn get_lens_description(&self) -> Result> { if let Some(ifd) = self.makernote.get_sub_ifd(OrfMakernotes::EquipmentIFD) { match ifd.get_entry(OrfEquipmentTags::LensType) { Some(Entry { value: Value::Byte(settings), .. }) => { log::debug!("Lens type tag: {:?}", settings); let make_id = settings[0]; let model_id = settings[2]; let submodel_id = settings[3]; let composite_id = format!("{:02X} {:02X} {:02X}", make_id, model_id, submodel_id); log::debug!("ORF lens composite ID: {}", composite_id); let resolver = LensResolver::new() .with_olympus_id(Some(composite_id)) .with_camera(&self.camera) .with_focal_len(self.get_focal_len()?) .with_mounts(&[MFT_MOUNT.into()]); return Ok(resolver.resolve()); } _ => { log::warn!("Camera settings in makernote not found, no lens data available"); } } } log::warn!("No lens data found"); Ok(None) } fn get_focal_len(&self) -> Result> { if let Some(exif) = self.tiff.find_first_ifd_with_tag(ExifTag::MakerNotes) { if let Some(Entry { value: Value::Short(focal), .. }) = exif.get_entry(ExifTag::FocalLength) { return Ok(focal.get(1).map(|v| Rational::new(*v as u32, 1))); } } Ok(None) } fn get_wb(&self) -> Result<[f32; 4]> { let redmul = self.makernote.get_entry(OrfMakernotes::OlympusRedMul); let bluemul = self.makernote.get_entry(OrfMakernotes::OlympusBlueMul); match (redmul, bluemul) { (Some(redmul), Some(bluemul)) => Ok([redmul.force_u32(0) as f32, 256.0, 256.0, bluemul.force_u32(0) as f32]), _ => { let ifd = self.makernote.find_ifds_with_tag(OrfImageProcessing::OrfBlackLevels); if ifd.is_empty() { return Err(RawlerError::DecoderFailed("ORF: Couldn't find ImgProc IFD".to_string())); } let wbs = fetch_tiff_tag!(ifd[0], OrfImageProcessing::WB_RBLevels); Ok([wbs.force_f32(0), 256.0, 256.0, wbs.force_f32(1)]) } } } } fn normalize_wb(raw_wb: [f32; 4]) -> [f32; 4] { log::debug!("ORF raw wb: {:?}", raw_wb); let div = raw_wb[1]; let mut norm = raw_wb; norm.iter_mut().for_each(|v| { if v.is_normal() { *v /= div } }); [norm[0], (norm[1] + norm[2]) / 2.0, norm[3], f32::NAN] } crate::tags::tiff_tag_enum!(OrfMakernotes); crate::tags::tiff_tag_enum!(OrfImageProcessing); crate::tags::tiff_tag_enum!(OrfEquipmentTags); #[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum OrfMakernotes { ImageProcessingIFD = 0x2040, RawInfo = 0x3000, OlympusRedMul = 0x1017, OlympusBlueMul = 0x1018, EquipmentIFD = 0x2010, } #[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum OrfImageProcessing { ImageProcessingVersion = 0x0000, WB_RBLevels = 0x0100, OrfBlackLevels = 0x0600, ValidBits = 0x0611, CropLeft = 0x0612, CropTop = 0x0613, CropWidth = 0x0614, CropHeight = 0x0615, } #[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum OrfEquipmentTags { LensType = 0x0201, } rawler-0.7.1/src/decoders/pef.rs000064400000000000000000000373101046102023000146300ustar 00000000000000use image::DynamicImage; use log::debug; use log::warn; use serde::Deserialize; use serde::Serialize; use super::BlackLevel; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::alloc_image_ok; use crate::analyze::FormatDump; use crate::bits::Endian; use crate::decompressors::ljpeg::huffman::*; use crate::exif::Exif; use crate::formats::tiff::Entry; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::IFD; use crate::formats::tiff::Value; use crate::formats::tiff::ifd::OffsetMode; use crate::formats::tiff::reader::TiffReader; use crate::lens::LensDescription; use crate::lens::LensResolver; use crate::packed::*; use crate::pixarray::PixU16; use crate::pumps::BitPumpMSB; use crate::pumps::ByteStream; use crate::rawimage::CFAConfig; use crate::rawimage::RawPhotometricInterpretation; use crate::rawsource::RawSource; use crate::tags::ExifTag; use crate::tags::TiffCommonTag; #[derive(Debug, Clone)] pub struct PefDecoder<'a> { camera: Camera, #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, makernote: IFD, /// Offset of makernote, needed to correct offsets of preview image makernote_offset: u32, } impl<'a> PefDecoder<'a> { pub fn new(file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { debug!("PEF decoder choosen"); let camera = rawloader.check_supported(tiff.root_ifd())?; let makernote = if let Some(exif) = tiff.find_first_ifd_with_tag(ExifTag::MakerNotes) { exif.parse_makernote(&mut file.reader(), OffsetMode::Absolute, &[])? } else { warn!("PEF makernote not found"); None } .ok_or("File has not makernotes")?; let makernote_offset = tiff .find_first_ifd_with_tag(ExifTag::MakerNotes) .and_then(|exif| exif.get_entry(ExifTag::MakerNotes)) .map(|entry| entry.offset().unwrap() as u32) .unwrap_or(0); //eprintln!("IFD makernote:"); //for line in makernote.dump::(10) { // eprintln!("{}", line); //} Ok(PefDecoder { camera, tiff, rawloader, makernote, makernote_offset, }) } } /// CR2 format encapsulation for analyzer #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PefFormat { tiff: GenericTiffReader, } impl<'a> Decoder for PefDecoder<'a> { fn format_dump(&self) -> FormatDump { FormatDump::Pef(PefFormat { tiff: self.tiff.clone() }) } fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { //for (i, ifd) in self.tiff.chains().iter().enumerate() { // eprintln!("IFD {}", i); // for line in ifd.dump::(10) { // eprintln!("{}", line); // } //} let raw = self .tiff .find_first_ifd_with_tag(TiffCommonTag::StripOffsets) .ok_or_else(|| RawlerError::unsupported(&self.camera, "Unable to find IFD"))?; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let offset = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); let src = file.subview_until_eof(offset as u64)?; let image = match fetch_tiff_tag!(raw, TiffCommonTag::Compression).get_u32(0) { Ok(Some(1)) => decode_16be(src, width, height, dummy), Ok(Some(32773)) => decode_12be(src, width, height, dummy), Ok(Some(65535)) => self.decode_compressed(src, width, height, dummy)?, Ok(Some(c)) => return Err(RawlerError::unsupported(&self.camera, format!("PEF: Don't know how to read compression {}", c))), _ => return Err(RawlerError::unsupported(&self.camera, "PEF: No compression tag found")), }; let cpp = 1; let wb = self.get_wb()?; let blacklevel = self.get_blacklevel()?; let whitelevel = None; debug!("Found WB: {:?}", wb); let photometric = if self.camera.cfa.is_valid() { RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&self.camera)) } else { RawPhotometricInterpretation::LinearRaw }; Ok(RawImage::new(self.camera.clone(), image, cpp, wb, photometric, blacklevel, whitelevel, dummy)) } fn full_image(&self, file: &RawSource, params: &RawDecodeParams) -> Result> { if params.image_index != 0 { return Ok(None); } let size = self.makernote.get_entry(PefMakernote::PreviewImageSize); let length = self.makernote.get_entry(PefMakernote::PreviewImageLength); let start = self.makernote.get_entry(PefMakernote::PreviewImageStart); let image = match (size, length, start) { (Some(size), Some(length), Some(start)) => { let _width = size.force_u16(0); let _height = size.force_u16(1); let len = length.force_u32(0); let offset = start.force_u32(0); if len > 0 && offset > 0 { let buf = file.subview((self.makernote_offset + offset) as u64, len as u64)?; match image::load_from_memory_with_format(buf, image::ImageFormat::Jpeg) { Ok(img) => Some(img), Err(_) => { // Test offset without correction let buf = file.subview(offset as u64, len as u64)?; let img = image::load_from_memory_with_format(buf, image::ImageFormat::Jpeg) .map_err(|err| RawlerError::DecoderFailed(format!("Failed to read JPEG: {:?}", err)))?; Some(img) } } } else { None } } _ => todo!(), }; if let Some(image) = image { // This tag contains the border definitions for the preview image. // We cut away these black borders. if let Some(Entry { value: Value::Byte(borders), .. }) = self.makernote.get_entry(PefMakernote::PreviewImageBorders) { let y = borders[0] as u32; let x = borders[2] as u32; let width = image.width() - x - borders[3] as u32; let height = image.height() - y - borders[1] as u32; return Ok(Some(image.crop_imm(x, y, width, height))); } else { return Ok(Some(image)); } } todo!() } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; let mdata = RawMetadata::new_with_lens(&self.camera, exif, self.get_lens_description()?.cloned()); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::PEF } } impl<'a> PefDecoder<'a> { fn get_wb(&self) -> Result<[f32; 4]> { match self.makernote.get_entry(PefMakernote::WhitePoint) { Some(wb) => { let raw_wb = [wb.force_u16(0) as f32, wb.force_u16(1) as f32, wb.force_u16(2) as f32, wb.force_u16(3) as f32]; Ok(normalize_wb(raw_wb)) } None => Ok([f32::NAN, f32::NAN, f32::NAN, f32::NAN]), } } fn get_blacklevel(&self) -> Result> { match self.makernote.get_entry(PefMakernote::BlackPoint) { Some(data) => { if self.camera.cfa.is_valid() { let levels = [data.force_u16(0), data.force_u16(1), data.force_u16(2), data.force_u16(3)]; Ok(Some(BlackLevel::new(&levels, self.camera.cfa.width, self.camera.cfa.height, 1))) } else { // Monochrome PEF like K-3 let levels = [data.force_u16(0)]; Ok(Some(BlackLevel::new(&levels, 1, 1, 1))) } } None => Ok(None), } } /// Get lens description by analyzing TIFF tags and makernotes fn get_lens_description(&self) -> Result> { if let Some(Entry { value: Value::Byte(settings), .. }) = self.makernote.get_entry(PefMakernote::LensRec) { let lens_id = (settings[0] as u32, settings[1] as u32); debug!("LensRec tag: {:?}", lens_id); if [0, 1, 2].contains(&lens_id.0) { // 0 = M-42 or no lens // 1 = K or M lens // 2 = A Series lens return Ok(None); } else { let resolver = LensResolver::new() .with_camera(&self.camera) .with_lens_id(lens_id) .with_mounts(&["k-mount".into()]); return Ok(resolver.resolve()); } } Ok(None) } fn decode_compressed(&self, src: &[u8], width: usize, height: usize, dummy: bool) -> Result { if let Some(huff) = self.makernote.get_entry(PefMakernote::HuffmanTable) { match &huff.value { Value::Undefined(data) => Self::do_decode(src, Some((data, self.tiff.get_endian())), width, height, dummy), _ => todo!(), // should not happen! } } else { Self::do_decode(src, None, width, height, dummy) } } pub(crate) fn do_decode(src: &[u8], huff: Option<(&[u8], Endian)>, width: usize, height: usize, dummy: bool) -> Result { let mut out = alloc_image_ok!(width, height, dummy); let mut htable = HuffTable::empty(); /* Attempt to read huffman table, if found in makernote */ if let Some((huff, endian)) = huff { debug!("Use in-file Huffman table"); let mut stream = ByteStream::new(huff, endian); let depth: usize = (stream.get_u16() as usize + 12) & 0xf; stream.consume_bytes(12); let mut v0: [u32; 16] = [0; 16]; for i in 0..depth { v0[i] = stream.get_u16() as u32; } let mut v1: [u32; 16] = [0; 16]; for i in 0..depth { v1[i] = stream.get_u8() as u32; } // Calculate codes and store bitcounts let mut v2: [u32; 16] = [0; 16]; for c in 0..depth { v2[c] = v0[c] >> (12 - v1[c]); htable.bits[v1[c] as usize] += 1; } // Find smallest for i in 0..depth { let mut sm_val: u32 = 0xfffffff; let mut sm_num: u32 = 0xff; for j in 0..depth { if v2[j] <= sm_val { sm_num = j as u32; sm_val = v2[j]; } } htable.huffval[i] = sm_num; v2[sm_num as usize] = 0xffffffff; } } else { debug!("Fallback to standard Huffman table"); // Initialize with legacy data let pentax_tree: [u8; 29] = [0, 2, 3, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 3, 4, 2, 5, 1, 6, 0, 7, 8, 9, 10, 11, 12]; let mut acc: usize = 0; for i in 0..16 { htable.bits[i + 1] = pentax_tree[i] as u32; acc += htable.bits[i + 1] as usize; } for i in 0..acc { htable.huffval[i] = pentax_tree[i + 16] as u32; } } htable.initialize()?; let mut pump = BitPumpMSB::new(src); let mut pred_up1: [i32; 2] = [0, 0]; let mut pred_up2: [i32; 2] = [0, 0]; let mut pred_left1: i32; let mut pred_left2: i32; for row in 0..height { pred_up1[row & 1] += htable.huff_decode(&mut pump)?; pred_up2[row & 1] += htable.huff_decode(&mut pump)?; pred_left1 = pred_up1[row & 1]; pred_left2 = pred_up2[row & 1]; out[row * width + 0] = pred_left1 as u16; out[row * width + 1] = pred_left2 as u16; for col in (2..width).step_by(2) { pred_left1 += htable.huff_decode(&mut pump)?; pred_left2 += htable.huff_decode(&mut pump)?; out[row * width + col + 0] = pred_left1 as u16; out[row * width + col + 1] = pred_left2 as u16; } } Ok(out) } } fn normalize_wb(raw_wb: [f32; 4]) -> [f32; 4] { debug!("PEF raw wb: {:?}", raw_wb); // We never have more then RGB colors so far (no RGBE etc.) // So we combine G1 and G2 to get RGB wb. let div = raw_wb[1]; let mut norm = raw_wb; norm.iter_mut().for_each(|v| { if v.is_normal() { *v /= div } }); [norm[0], (norm[1] + norm[2]) / 2.0, norm[3], f32::NAN] } crate::tags::tiff_tag_enum!(PefMakernote); #[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum PefMakernote { PentaxVersion = 0x0000, PentaxModelType = 0x0001, PreviewImageSize = 0x0002, PreviewImageLength = 0x0003, PreviewImageStart = 0x0004, PentaxModelId = 0x0005, Date = 0x0006, Time = 0x0007, Quality = 0x0008, PentaxImageSize = 0x0009, PictureMode = 0x000b, FlashMode = 0x000c, FocusMode = 0x000d, AFPointSelected = 0x000e, AFPointsInFocus = 0x000f, FocusPosition = 0x0010, ExposureTime = 0x0012, FNumber = 0x0013, ISO = 0x0014, LightReading = 0x0015, ExposureCompensation = 0x0016, MeteringMode = 0x0017, AutoBracketing = 0x0018, WhiteBalance = 0x0019, WhiteBalanceMode = 0x001a, BlueBalance = 0x001b, RedBalance = 0x001c, FocalLength = 0x001d, DigitalZoom = 0x001e, Saturation = 0x001f, Contrast = 0x0020, Sharpness = 0x0021, WordTimeLocation = 0x0022, HometownCity = 0x0023, DestinationCity = 0x0024, HometownDST = 0x0025, DestinationDST = 0x0026, DSPFirmwareVersion = 0x0027, CPUFirmwareVersion = 0x0028, FrameNumber = 0x0029, EffectiveLV = 0x002d, ImageEditing = 0x0032, PictureMode2 = 0x0033, DriveMode = 0x0034, SensorSize = 0x0035, ColorSpace = 0x0037, ImageAreaOffset = 0x0038, RawImageSize = 0x0039, AFPointsInFocus2 = 0x003c, DataScaling = 0x003d, PreviewImageBorders = 0x003e, LensRec = 0x003f, SensitivityAdjust = 0x0040, ImageEditCount = 0x0041, CameraTemerature = 0x0047, AELock = 0x0048, NoiseReduction = 0x0049, FlashExposureComp = 0x004d, ImageTone = 0x004f, ColorTemperature = 0x0050, ColorTempDaylight = 0x0053, ColorTempShade = 0x0054, ColorTempCloudy = 0x0055, ColorTempTungsten = 0x0056, ColorTempFluorescentD = 0x0057, ColorTempFluorescentN = 0x0058, ColorTempFluorescentW = 0x0059, ColorTempFlash = 0x005a, ShakeReductionInfo = 0x005c, ShutterCount = 0x005d, FaceInfo = 0x0060, RawDevelopmentProcess = 0x0062, Hue = 0x0067, AWBInfo = 0x0068, DynamicRangeExpansion = 0x0069, TimeInfo = 0x006b, HighLowKeyAdj = 0x006c, ContastHighlight = 0x006d, ContrastShadow = 0x006e, ConstrastHightlightShadowAdj = 0x006f, FineSharpness = 0x0070, HighISONoiseReduction = 0x0071, AFAdjustment = 0x0072, MonochromeFilterEffect = 0x0073, MonochromeToning = 0x0074, FaceDetect = 0x0076, FaceDetectFrameIsze = 0x0077, ShadowCorrection = 0x0079, ISOAutoParameters = 0x007a, CrossProcess = 0x007b, LensCorr = 0x007d, WhiteLevel = 0x007e, BleachBypassToning = 0x007f, AspectRatio = 0x0080, BlurControl = 0x0082, HDR = 0x0085, ShutterType = 0x0087, NeutralDensityFilter = 0x0088, ISO2 = 0x008b, IntervalShooting = 0x0092, SkinToneCorrection = 0x0095, ClarityControl = 0x0096, BlackPoint = 0x0200, WhitePoint = 0x0201, ColorMatrixA = 0x0203, ColorMatrixB = 0x0204, CameraSettings = 0x0205, AEInfo = 0x0206, LensInfo = 0x0207, FlashInfo = 0x0208, AEMeteringSegements = 0x0209, FlashMeteringSegements = 0x020a, SlaveFlashMeteringSegements = 0x020b, WB_RGGBLevelsDaylight = 0x020d, WB_RGGBLevelsShade = 0x020e, WB_RGGBLevelsCloudy = 0x020f, WB_RGGBLevelsTungsten = 0x0210, WB_RGGBLevelsFluorescentD = 0x0211, WB_RGGBLevelsFluorescentN = 0x0212, WB_RGGBLevelsFluorescentW = 0x0213, WB_RGGBLevelsFlash = 0x0214, CameraInfo = 0x0215, BatteryInfo = 0x0216, SaturationInfo = 0x021b, ColorMatrixA2 = 0x021c, ColorMatrixB2 = 0x021d, AFInfo = 0x021f, HuffmanTable = 0x0220, KelvinWB = 0x0221, ColorInfo = 0x0222, EVStepInfo = 0x0224, ShotInfo = 0x0226, FacePos = 0x0227, FaceSize = 0x0228, SerialNumber = 0x0229, FilterInfo = 0x022a, LevelInfo = 0x022b, WBLevels = 0x022d, Artist = 0x022e, Copyright = 0x022f, FirmwareVersion = 0x0230, ConstrastDetectAFArea = 0x0231, CrossProcessParams = 0x0235, LensInfoQ = 0x0239, Model = 0x023f, PixelShiftInfo = 0x0243, AFPointInfo = 0x0245, DataDump = 0x03fe, TempInfo = 0x03ff, ToneCurve = 0x0402, ToneCurves = 0x0403, UnknownBlock = 0x0405, PrintIM = 0x0e00, } rawler-0.7.1/src/decoders/qtk.rs000064400000000000000000000202551046102023000146550ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2024 Daniel Vogelbacher // Originally written in C in dcraw.c by Dave Coffin use rayon::iter::IndexedParallelIterator; use rayon::iter::ParallelIterator; use std::mem::swap; use std::ops::Not; use crate::Orientation; use crate::RawImage; use crate::RawLoader; use crate::Result; use crate::alloc_image_ok; use crate::analyze::FormatDump; use crate::bits::BEu16; use crate::bits::Endian; use crate::bits::LookupTable; use crate::buffer::PaddedBuf; use crate::exif::Exif; use crate::pixarray::PixU16; use crate::pumps::BitPump; use crate::pumps::BitPumpMSB; use crate::pumps::ByteStream; use crate::rawsource::RawSource; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use super::ok_cfa_image; #[derive(Debug, Clone)] pub struct QtkDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, camera: Camera, } pub fn is_qtk(file: &RawSource) -> bool { match file.subview(0, 4) { Ok(buf) => buf[0..4] == b"qktk"[..] || buf[0..4] == b"qktn"[..], Err(_) => false, } } impl<'a> QtkDecoder<'a> { pub fn new(file: &RawSource, rawloader: &'a RawLoader) -> Result> { match file.subview(0, 4)? { b"qktk" => { let make = "Apple"; let model = "QuickTake 100"; let camera = rawloader.check_supported_with_everything(make, model, "")?; Ok(QtkDecoder { rawloader, camera }) } b"qktn" => { if file.subview(0, 6)?[5] != 0 { let make = "Apple"; let model = "QuickTake 200"; let camera = rawloader.check_supported_with_everything(make, model, "")?; Ok(QtkDecoder { rawloader, camera }) } else { let make = "Apple"; let model = "QuickTake 150"; let camera = rawloader.check_supported_with_everything(make, model, "")?; Ok(QtkDecoder { rawloader, camera }) } } sig => Err(crate::RawlerError::DecoderFailed(format!( "Unable to use QTK decoder on file with signature: '{:?}'", sig ))), } } } impl<'a> Decoder for QtkDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { const META_OFFSET: u64 = 544; let meta = file.subview(META_OFFSET, 16)?; let mut stream = ByteStream::new(meta, Endian::Big); let mut height = stream.get_u16() as usize; let mut width = stream.get_u16() as usize; let _zero = stream.get_u32(); let hint = stream.get_u16(); let offset = if hint == 30 { 738 } else { 736 }; let mut orientation = Orientation::Normal; if height > width { swap(&mut width, &mut height); let info = file.subview(offset - 6, 6)?; orientation = if BEu16(info, 0).not() & 3 > 0 { Orientation::Rotate90 } else { Orientation::Rotate270 }; log::debug!("QTK file has flipped width/height, new orientation: {:?}", orientation); } log::debug!("QTK file w: {}, h: {}, hint: {}", width, height, hint); let src = file.subview_until_eof_padded(offset as u64)?; let image = match file.subview(0, 4)? { b"qktk" => Self::decompress_quicktake_100(self, &src, width, height, dummy)?, b"qktn" => Self::decompress_quicktake_150(self, &src, width, height, dummy)?, _ => unreachable!(), }; let cpp = 1; ok_cfa_image(self.camera.clone(), cpp, self.get_wb()?, image, dummy).map(|mut image| { image.orientation = orientation; image }) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let meta = RawMetadata::new(&self.camera, Exif::default()); Ok(meta) } fn format_hint(&self) -> FormatHint { FormatHint::QTK } } impl<'a> QtkDecoder<'a> { fn get_wb(&self) -> Result<[f32; 4]> { Ok([f32::NAN, f32::NAN, f32::NAN, f32::NAN]) } pub fn decompress_quicktake_150(&self, src: &PaddedBuf, width: usize, height: usize, dummy: bool) -> Result { // Model 150 always compress with cbpp=3 let cbpp = 3; crate::decompressors::radc::decompress(src, width, height, cbpp, dummy) } pub fn decompress_quicktake_100(&self, src: &[u8], width: usize, height: usize, dummy: bool) -> Result { assert!(width > height); let mut out = alloc_image_ok!(width, height, dummy); let mut pump = BitPumpMSB::new(src); const GSTEP: [i16; 16] = [-89, -60, -44, -32, -22, -15, -8, -2, 2, 8, 15, 22, 32, 44, 60, 89]; const RSTEP: [[i16; 4]; 6] = [ [-3, -1, 1, 3], [-5, -1, 1, 5], [-8, -2, 2, 8], [-13, -3, 3, 13], [-19, -4, 4, 19], [-28, -6, 6, 28], ]; const CURVE: [u16; 256] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 88, 90, 92, 94, 97, 99, 101, 103, 105, 107, 110, 112, 114, 116, 118, 120, 123, 125, 127, 129, 131, 134, 136, 138, 140, 142, 144, 147, 149, 151, 153, 155, 158, 160, 162, 164, 166, 168, 171, 173, 175, 177, 179, 181, 184, 186, 188, 190, 192, 195, 197, 199, 201, 203, 205, 208, 210, 212, 214, 216, 218, 221, 223, 226, 230, 235, 239, 244, 248, 252, 257, 261, 265, 270, 274, 278, 283, 287, 291, 296, 300, 305, 309, 313, 318, 322, 326, 331, 335, 339, 344, 348, 352, 357, 361, 365, 370, 374, 379, 383, 387, 392, 396, 400, 405, 409, 413, 418, 422, 426, 431, 435, 440, 444, 448, 453, 457, 461, 466, 470, 474, 479, 483, 487, 492, 496, 500, 508, 519, 531, 542, 553, 564, 575, 587, 598, 609, 620, 631, 643, 654, 665, 676, 687, 698, 710, 721, 732, 743, 754, 766, 777, 788, 799, 810, 822, 833, 844, 855, 866, 878, 889, 900, 911, 922, 933, 945, 956, 967, 978, 989, 1001, 1012, 1023, ]; let mut pix = [[0x80_i16; 644]; 484]; for row in 2..(height + 2) { let cstart = 2 + (row & 1); let mut val = 0; for col in (cstart..(width + 2)).step_by(2) { val = (((pix[row - 1][col - 1] + 2 * pix[row - 1][col + 1] + pix[row][col - 2]) >> 2) + GSTEP[pump.get_bits(4) as usize]).clamp(0, 255); pix[row][col] = val; if col < 4 { pix[row][col - 2] = val; pix[row + 1][(!row) & 1] = val; } if row == 2 { pix[row - 1][col + 1] = val; pix[row - 1][col + 3] = val; } } pix[row][width + 2 + (row & 1)] = val; // last column } for rb in 0..2 { for row in ((2 + rb)..(height + 2)).step_by(2) { for col in ((3 - (row & 1))..(width + 2)).step_by(2) { let sharp = if row < 4 || col < 4 { 2 } else { let val = (pix[row - 2][col] - pix[row][col - 2]).abs() as i32 + (pix[row - 2][col] - pix[row - 2][col - 2]).abs() as i32 + (pix[row][col - 2] - pix[row - 2][col - 2]).abs() as i32; match val { 0..4 => 0, 4..8 => 1, 8..16 => 2, 16..32 => 3, 32..48 => 4, _ => 5, } }; let val = (((pix[row - 2][col] + pix[row][col - 2]) >> 1) + RSTEP[sharp][pump.get_bits(2) as usize]).clamp(0, 255); pix[row][col] = val; if row < 4 { pix[row - 2][col + 2] = val; }; if col < 4 { pix[row + 2][col - 2] = val; }; } } } for row in 2..(height + 2) { for col in ((3 - (row & 1))..(width + 2)).step_by(2) { let val = ((pix[row][col - 1] + (pix[row][col] << 2) + pix[row][col + 1]) >> 1) - 0x100; pix[row][col] = val.clamp(0, 255); } } let tbl = LookupTable::new_with_bits(&CURVE, 10); out.par_pixel_rows_mut().enumerate().for_each(|(row, line)| { let mut random = ((pix[row + 2][2] as u32) << 16) | (pix[row + 2][3]) as u32; for (x, p) in line.iter_mut().zip(pix[row + 2][2..width + 2].iter()) { *x = tbl.dither(*p as u16, &mut random); //*x = CURVE[*p as usize]; // no dither } }); Ok(out) } } rawler-0.7.1/src/decoders/raf/dbp.rs000064400000000000000000000017751046102023000154010ustar 00000000000000/// /// Original code by libraw and rawspeed, licensed under LGPL-2 /// /// Copyright (C) 2016 Alexey Danilchenko /// Copyright (C) 2016 Alex Tutubalin use byteorder::{BigEndian, ReadBytesExt}; use std::io::Cursor; use crate::Result; use crate::{alloc_image_ok, pixarray::PixU16}; pub(super) fn decode_dbp(buf: &[u8], width: usize, height: usize, dummy: bool) -> Result { let mut out = alloc_image_ok!(width, height, dummy); let mut cursor = Cursor::new(buf); let n_tiles = 8; let tile_width = width / n_tiles; let _tile_height = 3856; log::debug!("DBP width: {}, height: {}, tile: {}", width, height, tile_width); let mut tile_buffer = vec![0_u16; height * tile_width]; for tile_n in 0..n_tiles { cursor.read_u16_into::(&mut tile_buffer)?; for scan_line in 0..height { let off = scan_line * width + tile_n * tile_width; out[off..off + tile_width].copy_from_slice(&tile_buffer[scan_line * tile_width..scan_line * tile_width + tile_width]); } } Ok(out) } rawler-0.7.1/src/decoders/raf/fuji_decompressor.rs000064400000000000000000001045051046102023000203510ustar 00000000000000/// /// Original code by libraw and rawspeed, licensed under LGPL-2 /// /// Copyright (C) 2016 Alexey Danilchenko /// Copyright (C) 2016 Alex Tutubalin /// Copyright (C) 2017 Uwe Müssel /// Copyright (C) 2017 Roman Lebedev /// Copyright (C) 2022 Daniel Vogelbacher use multiversion::multiversion; use rayon::prelude::*; use std::{fmt::Display, mem::size_of}; use crate::{ CFA, Result, bits::{Endian, log2ceil}, buffer::PaddedBuf, cfa::CFAColor, imgop::Dim2, pixarray::{PixU16, SharedPix2D}, pumps::{BitPump, BitPumpMSB, ByteStream}, }; /// A single gradient with two points type Gradient = (i32, i32); #[derive(Clone, Debug)] struct Strip { offset: usize, size: usize, n: usize, header: Header, cfa: [[CFAColor; 6]; 6], } /// Quantization table #[derive(Debug, Clone, Default)] struct QTable { q_base: i32, q_table: Vec, max_grad: usize, q_gradient_multi: i32, raw_bits: usize, total_values: i32, } #[derive(Debug, Clone)] struct Params { /// Quantization table qtables: Vec, max_bits: usize, min_value: i32, max_value: i32, line_width: usize, } #[derive(Copy, Clone, Debug)] struct ColorPos { even: usize, odd: usize, } #[derive(Clone, Debug)] struct Colors { colors: [ColorPos; 3], } #[derive(Clone, Debug)] struct GradientList { /// Gradients for lossless mode lossless_grads: Vec, // 41 elements /// Gradients for lossy mode lossy_grads: [Vec; 3], // 5 elements } impl Strip { const fn line_height() -> usize { 6 } // how many vertical lines does this block encode? fn height(&self) -> u16 { self.header.total_lines } // how many horizontal pixels does this block encode? fn width(&self) -> usize { // if this is not the last block, we are good. if (self.n + 1) != (self.header.blocks_in_row as usize) { return self.header.block_size as usize; } // ok, this is the last block... debug_assert!(self.header.block_size as usize * self.header.blocks_in_row as usize >= self.header.raw_width as usize); self.header.raw_width as usize - self.offset_x() } // where vertically does this block start? fn offset_y(&self, line: usize) -> usize { debug_assert!(line < (self.height() as usize)); Self::line_height() as usize * line } // where horizontally does this block start? fn offset_x(&self) -> usize { self.header.block_size as usize * self.n } } fn div_round_up(a: T, b: T) -> T where T: std::ops::Add, T: std::ops::Sub, T: std::ops::Div, T: From, T: Copy, { (a + b - T::from(1_u8)) / b } #[derive(Debug, Clone, Eq, PartialEq)] struct Header { signature: u16, lossless: u8, raw_type: u8, raw_bits: u8, raw_height: u16, raw_rounded_width: u16, raw_width: u16, block_size: u16, blocks_in_row: u8, total_lines: u16, } impl Header { fn is_lossless(&self) -> bool { self.lossless == 1 } fn is_valid(&self) -> bool { !(self.signature != 0x4953 //|| self.lossless != 1 || self.raw_height > 0x3000 || (self.raw_height as usize) < Strip::line_height() || (self.raw_height as usize) % Strip::line_height() != 0 || self.raw_width > 0x3000 || self.raw_width < 0x300 || self.raw_width % 24 != 0 || self.raw_rounded_width > 0x3000 || self.block_size != 0x300 || self.raw_rounded_width < self.block_size || self.raw_rounded_width % self.block_size != 0 || self.raw_rounded_width - self.raw_width >= self.block_size || self.blocks_in_row > 0x10 || self.blocks_in_row == 0 || self.blocks_in_row as u16 != self.raw_rounded_width / self.block_size || self.blocks_in_row as u16 != div_round_up(self.raw_width, self.block_size as u16) || self.total_lines > 0x800 || self.total_lines == 0 || (self.total_lines as usize) != (self.raw_height as usize) / Strip::line_height() || (self.raw_bits != 12 && self.raw_bits != 14 && self.raw_bits != 16) || (self.raw_type != 16 && self.raw_type != 0)) } } impl Strip { fn decompress_strip(&self, src: &PaddedBuf, header: &Header, params: &Params, q_bases: Option<&[u8]>, out: &mut PixU16) { let mut info_block = CompressedBlock::new(header, params); log::debug!("Fuji strip offset: {}, len: {}", self.offset, self.size); let mut pump = if self.offset + self.size == src.len() { BitPumpMSB::new(&src[self.offset..]) // use extra bytes from PaddedBuf } else { let extra_bytes = 16; BitPumpMSB::new(&src[self.offset..self.offset + self.size + extra_bytes]) }; let mtable = [ (XT_LINE_R0, XT_LINE_R3), (XT_LINE_R1, XT_LINE_R4), (XT_LINE_G0, XT_LINE_G6), (XT_LINE_G1, XT_LINE_G7), (XT_LINE_B0, XT_LINE_B3), (XT_LINE_B1, XT_LINE_B4), ]; let ztable = [(XT_LINE_R2, 3), (XT_LINE_G2, 6), (XT_LINE_B2, 3)]; let mut params = params.clone(); for cur_line in 0..self.height() as usize { debug_assert_eq!(header.is_lossless(), q_bases.is_none()); // init grads and main qtable if !header.is_lossless() { let q_base = q_bases.as_ref().unwrap()[cur_line] as i32; if cur_line == 0 || q_base != params.qtables[0].q_base { let max_value = (1 << header.raw_bits) - 1; // todo: put into header as function? let main_qtable = Params::new_main_qtable(header, max_value, q_base); params.qtables[0] = main_qtable; // update grads // total_values depends on q_base for QTable let max_diff = 2.max((params.qtables[0].total_values + 0x20) >> 6); for j in 0..3 { debug_assert_eq!(info_block.grad_even[j].lossless_grads.len(), 41); debug_assert_eq!(info_block.grad_odd[j].lossless_grads.len(), 41); for i in 0..41 { info_block.grad_even[j].lossless_grads[i].0 = max_diff; info_block.grad_even[j].lossless_grads[i].1 = 1; info_block.grad_odd[j].lossless_grads[i].0 = max_diff; info_block.grad_odd[j].lossless_grads[i].1 = 1; } } } } if header.raw_type == 16 { info_block.fuji_xtrans_decode_block(&mut pump, ¶ms); } else { info_block.fuji_bayer_decode_block(&mut pump, ¶ms); } // copy data from line buffers and advance for i in mtable.iter() { debug_assert!(i.0 < i.1); let (dest, src) = info_block.linebuf.split_at_mut(i.0 + 1); dest[i.0].copy_from_slice(&src[i.1 - (i.0 + 1)]); //info_block.linebuf[i.0] = info_block.linebuf[i.1].clone(); } if header.raw_type == 16 { info_block.copy_line_to_xtrans(self, cur_line, out); } else { info_block.copy_line_to_bayer(self, cur_line, out); } for i in ztable.iter() { // Rest all lines for line in i.0..i.0 + i.1 { for p in info_block.linebuf[line].iter_mut() { *p = 0; } } // Initialize extra pixels info_block.linebuf[i.0][0] = info_block.linebuf[i.0 - 1][1]; info_block.linebuf[i.0][params.line_width + 1] = info_block.linebuf[i.0 - 1][params.line_width]; } } } } /// We need PaddedBuf here, because the buffer is divided /// into multiple strips and each strip is feed into a BitPump. /// Each pump need as litte bit more overhead at the end. /// For the final strip, we need the extra bytes from PaddedBuf /// to prevent out-of-range errors in BitPump. pub(super) fn decompress_fuji(buf: &PaddedBuf, width: usize, height: usize, _bps: usize, corrected_cfa: &CFA) -> Result { let mut stream = ByteStream::new(buf, Endian::Big); let header = Header { signature: stream.get_u16(), lossless: stream.get_u8(), raw_type: stream.get_u8(), raw_bits: stream.get_u8(), raw_height: stream.get_u16(), raw_rounded_width: stream.get_u16(), raw_width: stream.get_u16(), block_size: stream.get_u16(), blocks_in_row: stream.get_u8(), total_lines: stream.get_u16(), }; log::debug!("Header: {:?}", header); if !header.is_valid() { return Err("Fuji header is not valid".into()); } assert_eq!( Dim2::new(width, height), Dim2::new(header.raw_width.into(), header.raw_height.into()), "RAF header specifies different dimensions!" ); let params = Params::new(&header); log::debug!("Params: {:?}", params); let mut cfa: [[CFAColor; 6]; 6] = Default::default(); for i in 0..6 { for j in 0..6 { let color = corrected_cfa.cfa_color_at(i, j); match color { CFAColor::RED | CFAColor::GREEN | CFAColor::BLUE => cfa[i][j] = color, _ => panic!("Got unexpected color: {:?}", color), } } } let block_sizes: Vec = (0..header.blocks_in_row).map(|_| stream.get_u32() as usize).collect(); let raw_offset = header.blocks_in_row as usize * size_of::(); let raw_offset_padded = (raw_offset + 0xF) & !0xF; stream.consume_bytes(raw_offset_padded - raw_offset); // Global Q bases for all strips let q_bases: Option> = if !header.is_lossless() { let total_q_bases = block_sizes.len() * ((header.total_lines as usize + 0xF) & !0xF); Some(stream.get_bytes(total_q_bases)) } else { None }; //eprintln!("q_bases: {:?}", q_bases); //eprintln!("First block: {}", stream.get_pos()); // calculating raw block offsets let strips: Vec = block_sizes .iter() .enumerate() .map(|(n, &block_size)| { let strip = Strip { offset: stream.get_pos(), size: block_size, n, header: header.clone(), cfa, }; stream.consume_bytes(block_size); strip }) .collect(); assert!(stream.remaining_bytes() <= 16); let out = SharedPix2D::new(PixU16::new(width, height)); // Process each strip strips.par_iter().for_each(|strip| { let line_step = (header.total_lines as usize + 0xF) & !0xF; // Each strip has it's own q_bases let q_bases_strip = q_bases.as_ref().map(|buf| &buf[strip.n * line_step..]); // DANGEROUS: We need multiple mut refs here. This should be // safe as be only write pixels to pre-allocated memory. let outbuf = unsafe { out.inner_mut() }; strip.decompress_strip(buf, &header, ¶ms, q_bases_strip, outbuf); }); Ok(out.into_inner()) } impl ColorPos { fn new() -> Self { Self { even: 0, odd: 1 } } fn reset(&mut self) { self.even = 0; self.odd = 1; } } impl Colors { const R: usize = 0; const G: usize = 1; const B: usize = 2; fn new() -> Self { Self { colors: [ColorPos::new(), ColorPos::new(), ColorPos::new()], } } fn r(&mut self) -> &mut ColorPos { &mut self.colors[0] } fn g(&mut self) -> &mut ColorPos { &mut self.colors[1] } fn b(&mut self) -> &mut ColorPos { &mut self.colors[2] } fn at(&mut self, idx: usize) -> &mut ColorPos { &mut self.colors[idx] } } impl Default for GradientList { fn default() -> Self { Self { lossless_grads: vec![Default::default(); 41], lossy_grads: [vec![Default::default(); 5], vec![Default::default(); 5], vec![Default::default(); 5]], } } } /// A compressed block struct CompressedBlock { // tables of gradients grad_even: [GradientList; 3], grad_odd: [GradientList; 3], linebuf: Vec>, } impl CompressedBlock { /// Create and initialize new compression block. fn new(header: &Header, params: &Params) -> Self { let linebuf = vec![vec![0; params.line_width + 2]; XT_LINE_TOTAL]; let mut grad_even: [GradientList; 3] = Default::default(); let mut grad_odd: [GradientList; 3] = Default::default(); if header.is_lossless() { let max_diff = 2.max((params.qtables[0].total_values + 0x20) >> 6) as i32; for j in 0..3 { debug_assert_eq!(grad_even[j].lossless_grads.len(), 41); debug_assert_eq!(grad_odd[j].lossless_grads.len(), 41); for i in 0..41 { grad_even[j].lossless_grads[i].0 = max_diff; grad_even[j].lossless_grads[i].1 = 1; grad_odd[j].lossless_grads[i].0 = max_diff; grad_odd[j].lossless_grads[i].1 = 1; } } } else { // init static grads for lossy only - main ones are done per line for k in 0..3 { let max_diff = 2.max((params.qtables[k + 1].total_values + 0x20) >> 6) as i32; for j in 0..3 { for i in 0..5 { grad_even[j].lossy_grads[k][i].0 = max_diff; grad_even[j].lossy_grads[k][i].1 = 1; grad_odd[j].lossy_grads[k][i].0 = max_diff; grad_odd[j].lossy_grads[k][i].1 = 1; } } } } Self { grad_even, grad_odd, linebuf } } /// Copy line from decoding buffer to output fn copy_line(&self, strip: &Strip, cur_line: usize, index_f: F, out: &mut PixU16) where F: Fn(usize) -> usize, { let mut line_buf_b = [0; 3]; let mut line_buf_g = [0; 6]; let mut line_buf_r = [0; 3]; for i in 0..3 { line_buf_r[i] = XT_LINE_R2 + i; line_buf_b[i] = XT_LINE_B2 + i; } for i in 0..6 { line_buf_g[i] = XT_LINE_G2 + i; } for row_count in 0..Strip::line_height() { for pixel_count in 0..strip.width() { let line_idx = match strip.cfa[row_count][pixel_count % 6] { CFAColor::RED => line_buf_r[row_count >> 1], CFAColor::GREEN => line_buf_g[row_count], CFAColor::BLUE => line_buf_b[row_count >> 1], _ => unreachable!(), }; let p = self.linebuf[line_idx][1 + index_f(pixel_count)]; *out.at_mut(strip.offset_y(cur_line) + row_count, strip.offset_x() + pixel_count) = p; } } } /// Copy line by Bayer pattern fn copy_line_to_bayer(&self, strip: &Strip, cur_line: usize, out: &mut PixU16) { let index = |pixel_count: usize| -> usize { pixel_count >> 1 }; self.copy_line(strip, cur_line, index, out); } /// Copy line by X-Trans pattern fn copy_line_to_xtrans(&self, strip: &Strip, cur_line: usize, out: &mut PixU16) { let index = |pixel_count: usize| -> usize { (((pixel_count * 2 / 3) & 0x7FFFFFFE) | ((pixel_count % 3) & 1)) + ((pixel_count % 3) >> 1) }; self.copy_line(strip, cur_line, index, out); } /// Decode Bayer pattern (RGGB and the like) from block fn fuji_bayer_decode_block(&mut self, pump: &mut BitPumpMSB, params: &Params) { let line_width = params.line_width; let mut colors = Colors::new(); let pass_red_green = |colors: &mut Colors, pump: &mut BitPumpMSB, block: &mut CompressedBlock, c0: usize, c1: usize, grad: usize| { while colors.g().even < line_width || colors.g().odd < line_width { if colors.g().even < line_width { fuji_decode_sample_even(pump, params, &mut block.linebuf, c0, &mut colors.r().even, &mut block.grad_even[grad]); fuji_decode_sample_even(pump, params, &mut block.linebuf, c1, &mut colors.g().even, &mut block.grad_even[grad]); } if colors.g().even > 8 { fuji_decode_sample_odd(pump, params, &mut block.linebuf, c0, &mut colors.r().odd, &mut block.grad_odd[grad]); fuji_decode_sample_odd(pump, params, &mut block.linebuf, c1, &mut colors.g().odd, &mut block.grad_odd[grad]); } } block.fuji_extend_red(line_width); block.fuji_extend_green(line_width); }; let pass_green_blue = |colors: &mut Colors, pump: &mut BitPumpMSB, block: &mut CompressedBlock, c0: usize, c1: usize, grad: usize| { while colors.g().even < line_width || colors.g().odd < line_width { if colors.g().even < line_width { fuji_decode_sample_even(pump, params, &mut block.linebuf, c0, &mut colors.g().even, &mut block.grad_even[grad]); fuji_decode_sample_even(pump, params, &mut block.linebuf, c1, &mut colors.b().even, &mut block.grad_even[grad]); } if colors.g().even > 8 { fuji_decode_sample_odd(pump, params, &mut block.linebuf, c0, &mut colors.g().odd, &mut block.grad_odd[grad]); fuji_decode_sample_odd(pump, params, &mut block.linebuf, c1, &mut colors.b().odd, &mut block.grad_odd[grad]); } } block.fuji_extend_green(line_width); block.fuji_extend_blue(line_width); }; pass_red_green(&mut colors, pump, self, XT_LINE_R2, XT_LINE_G2, 0); colors.g().reset(); pass_green_blue(&mut colors, pump, self, XT_LINE_G3, XT_LINE_B2, 1); colors.r().reset(); colors.g().reset(); pass_red_green(&mut colors, pump, self, XT_LINE_R3, XT_LINE_G4, 2); colors.g().reset(); colors.b().reset(); pass_green_blue(&mut colors, pump, self, XT_LINE_G5, XT_LINE_B3, 0); colors.r().reset(); colors.g().reset(); pass_red_green(&mut colors, pump, self, XT_LINE_R4, XT_LINE_G6, 1); colors.g().reset(); colors.b().reset(); pass_green_blue(&mut colors, pump, self, XT_LINE_G7, XT_LINE_B4, 2); } /// A single X-Trans decoding pass for the given control colors C0 and C1 fn fuji_xtrans_pass( &mut self, params: &Params, colors: &mut Colors, pump: &mut BitPumpMSB, c0: usize, c1: usize, grad: usize, even_func: F, ) where F: Fn(&mut CompressedBlock, &mut BitPumpMSB, usize, usize, usize, &mut ColorPos, &mut ColorPos), { let line_width = params.line_width; while colors.g().even < line_width || colors.g().odd < line_width { if colors.g().even < line_width { let mut c0_pos = *colors.at(C0); let mut c1_pos = *colors.at(C1); even_func(self, pump, c0, c1, grad, &mut c0_pos, &mut c1_pos); *colors.at(C0) = c0_pos; // Write back *colors.at(C1) = c1_pos; } if colors.g().even > 8 { fuji_decode_sample_odd(pump, params, &mut self.linebuf, c0, &mut colors.at(C0).odd, &mut self.grad_odd[grad]); fuji_decode_sample_odd(pump, params, &mut self.linebuf, c1, &mut colors.at(C1).odd, &mut self.grad_odd[grad]); } } } /// Decode X-Trans pattern from block fn fuji_xtrans_decode_block(&mut self, pump: &mut BitPumpMSB, params: &Params) { let mut colors = Colors::new(); let line_width = params.line_width; // Pass 1 self.fuji_xtrans_pass::<_, { Colors::R }, { Colors::G }>( params, &mut colors, pump, XT_LINE_R2, XT_LINE_G2, 0, |block, pump, c0, c1, grad, c0_pos, c1_pos| { fuji_decode_interpolation_even(block, c0, &mut c0_pos.even); fuji_decode_sample_even(pump, params, &mut block.linebuf, c1, &mut c1_pos.even, &mut block.grad_even[grad]); }, ); self.fuji_extend_red(line_width); self.fuji_extend_green(line_width); colors.g().reset(); // Pass 2 self.fuji_xtrans_pass::<_, { Colors::G }, { Colors::B }>( params, &mut colors, pump, XT_LINE_G3, XT_LINE_B2, 1, |block, pump, c0, c1, grad, c0_pos, c1_pos| { fuji_decode_sample_even(pump, params, &mut block.linebuf, c0, &mut c0_pos.even, &mut block.grad_even[grad]); fuji_decode_interpolation_even(block, c1, &mut c1_pos.even); }, ); self.fuji_extend_green(line_width); self.fuji_extend_blue(line_width); colors.r().reset(); colors.g().reset(); // Pass 3 self.fuji_xtrans_pass::<_, { Colors::R }, { Colors::G }>( params, &mut colors, pump, XT_LINE_R3, XT_LINE_G4, 2, |block, pump, c0, c1, grad, c0_pos, c1_pos| { if c0_pos.even & 3 != 0 { fuji_decode_sample_even(pump, params, &mut block.linebuf, c0, &mut c0_pos.even, &mut block.grad_even[grad]); } else { fuji_decode_interpolation_even(block, c0, &mut c0_pos.even); } fuji_decode_interpolation_even(block, c1, &mut c1_pos.even); }, ); self.fuji_extend_red(line_width); self.fuji_extend_green(line_width); colors.g().reset(); colors.b().reset(); // Pass 4 self.fuji_xtrans_pass::<_, { Colors::G }, { Colors::B }>( params, &mut colors, pump, XT_LINE_G5, XT_LINE_B3, 0, |block, pump, c0, c1, grad, c0_pos, c1_pos| { fuji_decode_sample_even(pump, params, &mut block.linebuf, c0, &mut c0_pos.even, &mut block.grad_even[grad]); if c1_pos.even & 3 == 2 { fuji_decode_interpolation_even(block, c1, &mut c1_pos.even); } else { fuji_decode_sample_even(pump, params, &mut block.linebuf, c1, &mut c1_pos.even, &mut block.grad_even[grad]); } }, ); self.fuji_extend_green(line_width); self.fuji_extend_blue(line_width); colors.r().reset(); colors.g().reset(); // Pass 5 self.fuji_xtrans_pass::<_, { Colors::R }, { Colors::G }>( params, &mut colors, pump, XT_LINE_R4, XT_LINE_G6, 1, |block, pump, c0, c1, grad, c0_pos, c1_pos| { if c0_pos.even & 3 == 2 { fuji_decode_interpolation_even(block, c0, &mut c0_pos.even); } else { fuji_decode_sample_even(pump, params, &mut block.linebuf, c0, &mut c0_pos.even, &mut block.grad_even[grad]); } fuji_decode_sample_even(pump, params, &mut block.linebuf, c1, &mut c1_pos.even, &mut block.grad_even[grad]); }, ); self.fuji_extend_red(line_width); self.fuji_extend_green(line_width); colors.g().reset(); colors.b().reset(); // Pass 6 self.fuji_xtrans_pass::<_, { Colors::G }, { Colors::B }>( params, &mut colors, pump, XT_LINE_G7, XT_LINE_B4, 2, |block, pump, c0, c1, grad, c0_pos, c1_pos| { fuji_decode_interpolation_even(block, c0, &mut c0_pos.even); if c1_pos.even & 3 != 0 { fuji_decode_sample_even(pump, params, &mut block.linebuf, c1, &mut c1_pos.even, &mut block.grad_even[grad]); } else { fuji_decode_interpolation_even(block, c1, &mut c1_pos.even); } }, ); self.fuji_extend_green(line_width); self.fuji_extend_blue(line_width); } fn fuji_extend_generic(&mut self, line_width: usize, start: usize, end: usize) { debug_assert!(start > 0); for i in start..=end { self.linebuf[i][0] = self.linebuf[i - 1][1]; self.linebuf[i][line_width + 1] = self.linebuf[i - 1][line_width]; } } fn fuji_extend_red(&mut self, line_width: usize) { self.fuji_extend_generic(line_width, XT_LINE_R2, XT_LINE_R4) } fn fuji_extend_green(&mut self, line_width: usize) { self.fuji_extend_generic(line_width, XT_LINE_G2, XT_LINE_G7) } fn fuji_extend_blue(&mut self, line_width: usize) { self.fuji_extend_generic(line_width, XT_LINE_B2, XT_LINE_B4) } } impl Display for QTable { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!( "QTable q_base {}, max_grad {}, q_gradient_multi {}, raw_bits {}, total_values {}", self.q_base, self.max_grad, self.q_gradient_multi, self.raw_bits, self.total_values )) } } impl QTable { /// Lookup gradient in q_table. The absolute value of this /// is used as an index into the gradients vector. fn lookup_gradient(&self, params: &Params, v1: i32, v2: i32) -> i32 { self.q_gradient_multi * self.q_table[(params.max_value + (v1)) as usize] + self.q_table[(params.max_value + (v2)) as usize] } /// Build a quantization table based on 5 quantization points. fn build_table(header: &Header, qp: &[i32; 5]) -> Vec { let mut qtable = vec![0; 2 * (1 << (header.raw_bits as usize))]; let mut cur_val = -(qp[4] as i32); for qt in qtable.iter_mut() { if cur_val > qp[4] as i32 { break; } *qt = match cur_val { x if x <= -qp[3] => -4, x if x <= -qp[2] => -3, x if x <= -qp[1] => -2, x if x < -qp[0] => -1, x if x <= qp[0] => 0, x if x < qp[1] => 1, x if x < qp[2] => 2, x if x < qp[3] => 3, _ => 4, }; cur_val += 1; } qtable } } impl Params { /// Construct new main quantization table. fn new_main_qtable(header: &Header, max_value: i32, q_base: i32) -> QTable { let mut qp = [0; 5]; qp[0] = q_base; qp[1] = 3 * q_base + 0x12; qp[2] = 5 * q_base + 0x43; qp[3] = 7 * q_base + 0x114; qp[4] = max_value; let max_val = max_value + 1; if qp[1] >= max_val || qp[1] < q_base + 1 { qp[1] = q_base + 1; } if qp[2] < qp[1] || qp[2] >= max_val { qp[2] = qp[1]; } if qp[3] < qp[2] || qp[3] >= max_val { qp[3] = qp[2]; } let q_table = QTable::build_table(header, &qp); let total_values = (qp[4] + 2 * q_base) / (2 * q_base + 1) + 1; let raw_bits: usize = log2ceil(total_values as usize); QTable { q_base, q_table, q_gradient_multi: 9, max_grad: 0, raw_bits, total_values, } } /// Create new parameter fn new(header: &Header) -> Self { if (header.block_size % 3 != 0 && header.raw_type == 16) || (header.block_size & 1 != 0 && header.raw_type == 0) { panic!("Invalid FUJI header"); } let min_value = 0x40; let max_value = ((1 << header.raw_bits) - 1) as i32; let max_bits: usize = 4 * log2ceil(max_value as usize + 1); let line_width = if header.raw_type == 16 { (header.block_size as usize * 2) / 3 } else { header.block_size as usize >> 1 }; // Build quantization tables. // For lossless, only one table is required. // For lossy, the main table is created on each iteration // while 3 static extra tables are required. let qtables = if header.is_lossless() { // Only a single table is needed for lossless mode let q_base = 0; let main_qtable = Self::new_main_qtable(header, max_value, q_base); vec![main_qtable] } else { let mut qtables = vec![QTable::default(); 4]; // The main table is left uninitialized here as // the table is setup for each iteration. qtables[0].q_base = -1; let mut qp = [0_i32; 5]; qp[4] = max_value; // identical for all tables // table 0 qtables[1].q_base = 0; qtables[1].max_grad = 5; qtables[1].q_gradient_multi = 3; qtables[1].total_values = qp[4] + 1; qtables[1].raw_bits = log2ceil(qtables[1].total_values as usize); qp[0] = qtables[1].q_base; qp[1] = if qp[4] >= 0x12 { 0x12 } else { qp[0] + 1 }; qp[2] = if qp[4] >= 0x43 { 0x43 } else { qp[1] }; qp[3] = if qp[4] >= 0x114 { 0x114 } else { qp[2] }; qtables[1].q_table = QTable::build_table(header, &qp); // table 1 qtables[2].q_base = 1; qtables[2].max_grad = 6; qtables[2].q_gradient_multi = 3; qtables[2].total_values = (qp[4] + 2) / 3 + 1; qtables[2].raw_bits = log2ceil(qtables[2].total_values as usize); qp[0] = qtables[2].q_base; qp[1] = if qp[4] >= 0x15 { 0x15 } else { qp[0] + 1 }; qp[2] = if qp[4] >= 0x48 { 0x48 } else { qp[1] }; qp[3] = if qp[4] >= 0x11B { 0x11B } else { qp[2] }; qtables[2].q_table = QTable::build_table(header, &qp); // table 2 qtables[3].q_base = 2; qtables[3].max_grad = 7; qtables[3].q_gradient_multi = 3; qtables[3].total_values = (qp[4] + 4) / 5 + 1; qtables[3].raw_bits = log2ceil(qtables[3].total_values as usize); qp[0] = qtables[3].q_base; qp[1] = if qp[4] >= 0x18 { 0x18 } else { qp[0] + 1 }; qp[2] = if qp[4] >= 0x4D { 0x4D } else { qp[1] }; qp[3] = if qp[4] >= 0x122 { 0x122 } else { qp[2] }; qtables[3].q_table = QTable::build_table(header, &qp); qtables }; Self { qtables, max_bits, min_value, max_value, line_width, } } } /// Count and consume all zero bits /// Additionally, consume the first 1 bit. #[inline(always)] fn fuji_zerobits(pump: &mut BitPumpMSB) -> u32 { let count = pump.consume_zerobits(); debug_assert_eq!(pump.peek_bits(1), 1); pump.consume_bits(1); // consume the next bit which is 0b1 count } /// Calculate bit difference between two values fn bit_diff(v1: i32, v2: i32) -> u32 { if v2 >= v1 { 0 } else { let mut dec_bits = 0; while dec_bits <= 14 { dec_bits += 1; if (v2 << dec_bits) >= v1 { return dec_bits; } } dec_bits } } /// Read a single code from bitstream and ajust gradient. /// We use bmi1 feature here because it provides LZCNT for /// leading zero count which is used here a lot. #[multiversion(targets("x86_64+avx+avx2+fma+bmi1+bmi2", "x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn read_code(pump: &mut BitPumpMSB, params: &Params, gradient: &mut Gradient, q_table: &QTable) -> i32 { let sample = fuji_zerobits(pump); let mut code: i32 = if (sample as usize) < params.max_bits - q_table.raw_bits - 1 { let dec_bits = bit_diff(gradient.0, gradient.1); let extra_bits = if dec_bits == 0 { 0 } else { pump.get_bits(dec_bits) as i32 }; (sample << dec_bits) as i32 + extra_bits } else { 1 + pump.get_bits(q_table.raw_bits as u32) as i32 }; // Validate code if code < 0 || code >= q_table.total_values as i32 { panic!("Invalid code: {}", code); } // Adjust code if (code & 1) != 0 { code = -1 - code / 2; } else { code /= 2; } // Update gradient gradient.0 += code.abs(); if gradient.1 == params.min_value { gradient.0 >>= 1; gradient.1 >>= 1; } gradient.1 += 1; code } /// Decode samples for even positions fn fuji_decode_sample_even(pump: &mut BitPumpMSB, params: &Params, linebuf: &mut [Vec], line: usize, pos: &mut usize, grads: &mut GradientList) { // Line -2 | | f | | // Line -1 | c | b | d | // Line 0 | a | x | g | let rb = linebuf[line - 1][1 + *pos + 0] as i32; let rc = linebuf[line - 1][1 + *pos - 1] as i32; let rd = linebuf[line - 1][1 + *pos + 1] as i32; let rf = linebuf[line - 2][1 + *pos + 0] as i32; // Calculate horiz/vert. gradients around current sample x let diff_rc_rb = (rc - rb).abs(); let diff_rf_rb = (rf - rb).abs(); let diff_rd_rb = (rd - rb).abs(); // Quantization table and Gradients to use let mut qtable = ¶ms.qtables[0]; let mut gradients = &mut grads.lossless_grads; for i in 1..4 { if params.qtables[0].q_base < i as i32 { break; } if diff_rf_rb + diff_rc_rb <= params.qtables[i].max_grad as i32 { qtable = ¶ms.qtables[i]; gradients = &mut grads.lossy_grads[i - 1]; break; } } // Determine gradient let grad = qtable.lookup_gradient(params, rb - rf, rc - rb); let mut interp_val = if diff_rc_rb > diff_rf_rb && diff_rc_rb > diff_rd_rb { rf + rd + 2 * rb } else if diff_rd_rb > diff_rc_rb && diff_rd_rb > diff_rf_rb { rf + rc + 2 * rb } else { rd + rc + 2 * rb }; let code = read_code(pump, params, &mut gradients[grad.unsigned_abs() as usize], qtable); // Adjustments specific to even positions if grad < 0 { interp_val = (interp_val >> 2) - code * (2 * qtable.q_base as i32 + 1); } else { interp_val = (interp_val >> 2) + code * (2 * qtable.q_base as i32 + 1); }; // Generic adjustments if interp_val < -(qtable.q_base as i32) { interp_val += (qtable.total_values * (2 * qtable.q_base + 1)) as i32; } else if interp_val > qtable.q_base as i32 + params.max_value { interp_val -= (qtable.total_values * (2 * qtable.q_base + 1)) as i32; } if interp_val >= 0 { linebuf[line][1 + *pos] = interp_val.min(params.max_value) as u16 } else { linebuf[line][1 + *pos] = 0; } *pos += 2; } /// Decode samples for odd positions fn fuji_decode_sample_odd(pump: &mut BitPumpMSB, params: &Params, linebuf: &mut [Vec], line: usize, pos: &mut usize, grads: &mut GradientList) { // Line -2 | | f | | // Line -1 | c | b | d | // Line 0 | a | x | g | let ra = linebuf[line + 0][1 + *pos - 1] as i32; let rb = linebuf[line - 1][1 + *pos + 0] as i32; let rc = linebuf[line - 1][1 + *pos - 1] as i32; let rd = linebuf[line - 1][1 + *pos + 1] as i32; let rg = linebuf[line + 0][1 + *pos + 1] as i32; // Calculate horiz/vert. gradients around current sample x let diff_rc_ra = (rc - ra).abs(); let diff_rb_rc = (rb - rc).abs(); // Quantization table and Gradients to use let mut qtable = ¶ms.qtables[0]; let mut gradients = &mut grads.lossless_grads; for i in 1..4 { if params.qtables[0].q_base < i as i32 { break; } if diff_rb_rc + diff_rc_ra <= params.qtables[i].max_grad as i32 { qtable = ¶ms.qtables[i]; gradients = &mut grads.lossy_grads[i - 1]; break; } } // Determine gradient let grad = qtable.lookup_gradient(params, rb - rc, rc - ra); let mut interp_val = if (rb > rc && rb > rd) || (rb < rc && rb < rd) { (rg + ra + 2 * rb) >> 2 } else { (ra + rg) >> 1 }; let code = read_code(pump, params, &mut gradients[grad.unsigned_abs() as usize], qtable); // Adjustments specific to odd positions if grad < 0 { interp_val -= code * (2 * qtable.q_base as i32 + 1); } else { interp_val += code * (2 * qtable.q_base as i32 + 1); } // Generic adjustments if interp_val < -(qtable.q_base as i32) { interp_val += (qtable.total_values * (2 * qtable.q_base + 1)) as i32; } else if interp_val > qtable.q_base as i32 + params.max_value { interp_val -= (qtable.total_values * (2 * qtable.q_base + 1)) as i32; } if interp_val >= 0 { linebuf[line][1 + *pos] = interp_val.min(params.max_value) as u16 } else { linebuf[line][1 + *pos] = 0; } *pos += 2; } /// Interpolate x value from surrounding pixels fn fuji_decode_interpolation_even(block: &mut CompressedBlock, line: usize, pos: &mut usize) { // Line -2 | | f | | // Line -1 | c | b | d | // Line 0 | a | x | g | let rb = block.linebuf[line - 1][1 + *pos + 0] as i32; let rc = block.linebuf[line - 1][1 + *pos - 1] as i32; let rd = block.linebuf[line - 1][1 + *pos + 1] as i32; let rf = block.linebuf[line - 2][1 + *pos + 0] as i32; let x = &mut block.linebuf[line][1 + *pos]; let diff_rc_rb = (rc - rb).abs(); let diff_rf_rb = (rf - rb).abs(); let diff_rd_rb = (rd - rb).abs(); if diff_rc_rb > diff_rf_rb && diff_rc_rb > diff_rd_rb { *x = ((rf + rd + 2 * rb) >> 2) as u16; } else if diff_rd_rb > diff_rc_rb && diff_rd_rb > diff_rf_rb { *x = ((rf + rc + 2 * rb) >> 2) as u16; } else { *x = ((rd + rc + 2 * rb) >> 2) as u16; } *pos += 2; } const XT_LINE_R0: usize = 0; const XT_LINE_R1: usize = 1; const XT_LINE_R2: usize = 2; const XT_LINE_R3: usize = 3; const XT_LINE_R4: usize = 4; const XT_LINE_G0: usize = 5; const XT_LINE_G1: usize = 6; const XT_LINE_G2: usize = 7; const XT_LINE_G3: usize = 8; const XT_LINE_G4: usize = 9; const XT_LINE_G5: usize = 10; const XT_LINE_G6: usize = 11; const XT_LINE_G7: usize = 12; const XT_LINE_B0: usize = 13; const XT_LINE_B1: usize = 14; const XT_LINE_B2: usize = 15; const XT_LINE_B3: usize = 16; const XT_LINE_B4: usize = 17; const XT_LINE_TOTAL: usize = 18; rawler-0.7.1/src/decoders/raf.rs000064400000000000000000000614061046102023000146310ustar 00000000000000use byteorder::BigEndian; use byteorder::LittleEndian; use byteorder::ReadBytesExt; use image::DynamicImage; use std::collections::BTreeMap; use std::io::Cursor; use std::io::Seek; use std::io::SeekFrom; use std::mem::size_of; use crate::CFA; use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::alloc_image; use crate::alloc_image_plain; use crate::analyze::FormatDump; use crate::bits::BEu32; use crate::bits::Endian; use crate::decoders::raf::fuji_decompressor::decompress_fuji; use crate::exif::Exif; use crate::formats::jfif::Jfif; use crate::formats::tiff::ifd::OffsetMode; use crate::formats::tiff::*; use crate::imgop::Dim2; use crate::imgop::Point; use crate::imgop::Rect; use crate::packed::*; use crate::pixarray::PixU16; use crate::rawimage::BlackLevel; use crate::rawimage::CFAConfig; use crate::rawimage::RawPhotometricInterpretation; use crate::rawimage::WhiteLevel; use crate::rawsource::RawSource; use crate::tags::DngTag; use crate::tags::ExifTag; use crate::tags::TiffCommonTag; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; mod dbp; mod fuji_decompressor; /// RAF decoder #[derive(Debug, Clone)] #[allow(dead_code)] pub struct RafDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, ifd: IFD, makernotes: IFD, camera: Camera, } /// Check if file has RAF signature pub fn is_raf(file: &RawSource) -> bool { match file.subview(0, 8) { Ok(buf) => buf[0..8] == b"FUJIFILM"[..], Err(_) => false, } } /// We need to inject a virtual IFD into main IFD. /// The RAF data block is not a regular TIFF structure but /// a proprietary structure. This tag id should be unlikely /// to appear in main IFD. const RAF_TAG_VIRTUAL_RAF_DATA: u16 = 0xfaaa; /// Parse a proprietary RAF data structure and return a virtual IFD. /// Unfortunately, Fujifilm forgot to add a type field to these /// tags, so we need to match by tag. pub fn parse_raf_format(file: &RawSource, offset: u32) -> Result { let mut entries = BTreeMap::new(); let stream = &mut file.reader(); stream.seek(SeekFrom::Start(offset as u64))?; let num = stream.read_u32::()?; // Directory entries in this IFD if num > 4000 { return Err(format_args!("too many entries in IFD ({})", num).into()); } for _ in 0..num { let tag = stream.read_u16::()?; let len = stream.read_u16::()? as usize; //eprintln!("RAF tag: 0x{:X}, len: {}", tag, len); match RafTags::try_from(tag) { Ok(RafTags::RawImageFullSize) | Ok(RafTags::RawImageCropTopLeft) | Ok(RafTags::RawImageCroppedSize) | Ok(RafTags::RawImageAspectRatio) | Ok(RafTags::WB_GRGBLevels) => { let n = len / size_of::(); let entry = Entry { tag, value: Value::Short((0..n).map(|_| stream.read_u16::()).collect::>>()?), embedded: None, }; entries.insert(tag, entry); } Ok(RafTags::FujiLayout) | Ok(RafTags::XTransLayout) => { let n = len / size_of::(); let entry = Entry { tag, value: Value::Byte((0..n).map(|_| stream.read_u8()).collect::>>()?), embedded: None, }; entries.insert(tag, entry); } // This one is in other byte-order... Ok(RafTags::RAFData) => { let n = len / size_of::(); let entry = Entry { tag, value: Value::Long((0..n).map(|_| stream.read_u32::()).collect::>>()?), embedded: None, }; entries.insert(tag, entry); } // Skip other tags _ => { stream.seek(SeekFrom::Current(len as i64))?; } } } Ok(IFD { entries, endian: Endian::Big, offset: 0, base: offset as u32, corr: 0, next_ifd: 0, sub: Default::default(), chain: Default::default(), }) } /// RAF format contains multiple TIFF and TIFF-like structures. /// This creates a IFD with all other IFDs found collected as SubIFDs. fn parse_raf(file: &RawSource) -> Result { const RAF_TIFF1_PTR_OFFSET: u64 = 84; const RAF_TIFF2_PTR_OFFSET: u64 = 100; const RAF_TAGS_PTR_OFFSET: u64 = 92; //const RAF_BLOCK_PTR_OFFSET2: u64 = 120; TODO: ?!? log::debug!("parse RAF"); let stream = &mut file.reader(); stream.seek(SeekFrom::Start(RAF_TIFF1_PTR_OFFSET))?; let offset = stream.read_u32::()?; // Main IFD let mut main = IFD::new_root(stream, offset + 12)?; //main.dump::(10).iter().for_each(|line| eprintln!("MAIN: {}", line)); // There is a second TIFF structure, the pointer is stored at offset 100. // If it is not a valid TIFF structure, the pointer itself is the RAF offset. stream.seek(SeekFrom::Start(RAF_TIFF2_PTR_OFFSET))?; let ioffset = stream.read_u32::()?; match IFD::new_root_with_correction(stream, 0, ioffset, 0, 10, &[FujiIFD::FujiIFD.into()]) { Ok(val) => { log::debug!("Found valid FujiIFD (0xF000)"); //val.dump::(10).iter().for_each(|line| eprintln!("FujiIFD: {}", line)); main.sub.insert(FujiIFD::FujiIFD as u16, vec![val]); } Err(_) => { // We fake an FujiIFD to pass the StripOffsets log::debug!("Unable to find FujiIFD (0xF000), let's fake it"); let mut entries = BTreeMap::::new(); entries.insert( FujiIFD::StripOffsets as u16, Entry { tag: FujiIFD::StripOffsets as u16, value: Value::Long(vec![ioffset]), // The ioffset is absolute to the file start. embedded: Some(RAF_TIFF2_PTR_OFFSET as u32), }, ); let fake = IFD { offset: 0, base: 0, // For the faked IFD, the offsets are already absolute to the file start. corr: 0, next_ifd: 0, entries, endian: main.endian, sub: Default::default(), chain: Default::default(), }; main.sub.insert(FujiIFD::FujiIFD as u16, vec![fake]); } } // And we maybe have a RAF data block, try to parse it. stream.seek(SeekFrom::Start(RAF_TAGS_PTR_OFFSET))?; let raf_offset = stream.read_u32::()?; match parse_raf_format(file, raf_offset) { Ok(val) => { //val.dump::(10).iter().for_each(|line| eprintln!("RAFTAGS: {}", line)); main.sub.insert(RAF_TAG_VIRTUAL_RAF_DATA, vec![val]); } Err(_) => { log::debug!("RAF block pointer is not valid, ignoring"); } } Ok(main) } impl<'a> RafDecoder<'a> { pub fn new(file: &RawSource, rawloader: &'a RawLoader) -> Result> { let ifd = parse_raf(file)?; let camera = rawloader.check_supported(&ifd)?; let makernotes = if let Some(exif) = ifd.find_first_ifd_with_tag(ExifTag::MakerNotes) { exif.parse_makernote(&mut file.reader(), OffsetMode::Absolute, &[])? } else { None } .ok_or("File has not makernotes")?; //makernotes.dump::(10).iter().for_each(|line| eprintln!("MKND: {}", line)); Ok(RafDecoder { ifd, makernotes, rawloader, camera, }) } } impl<'a> Decoder for RafDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let raw = self.ifd.find_first_ifd_with_tag(FujiIFD::StripOffsets).ok_or("No StripOffsets found")?; let (width, height) = if raw.has_entry(FujiIFD::RawImageFullWidth) { ( fetch_tiff_tag!(raw, FujiIFD::RawImageFullWidth).force_usize(0), fetch_tiff_tag!(raw, FujiIFD::RawImageFullHeight).force_usize(0), ) } else { let raf = &self .ifd .sub_ifds() .get(&RAF_TAG_VIRTUAL_RAF_DATA) .and_then(|ifds| ifds.get(0)) .ok_or("No RAF data IFD found")?; let sizes = fetch_tiff_tag!(raf, TiffCommonTag::ImageWidth); (sizes.force_usize(1), sizes.force_usize(0)) }; let bps = match raw.get_entry(TiffCommonTag::RafBitsPerSample) { Some(val) => val.force_u32(0) as usize, None => 16, }; // Rotation is only used for SuperCCD sensors, so we handle X-Trans CFA only here. // Some cameras like X-T20 uses different CFA when compression is enabled, so we // read the correct pattern from metadata. let corrected_cfa = if let Some(cfa) = self.get_xtrans_cfa()? { log::debug!( "Found X-Trans CFA pattern in metadata, use this instead of camera config file. Pattern is: {}", cfa ); cfa } else { self.camera.cfa.clone() }; // Strip offset is relative to IFD base let offset = raw.base as u64 + fetch_tiff_tag!(raw, FujiIFD::StripOffsets).force_u64(0); let src = if raw.has_entry(FujiIFD::StripByteCounts) { let strip_count = fetch_tiff_tag!(raw, FujiIFD::StripByteCounts).force_u64(0); file.subview_padded(offset, strip_count)? } else { // Some models like DBP don't have a byte count, so we read until EOF file.subview_until_eof_padded(offset)? }; log::debug!("BPS: {}, width: {}, height: {}, offset: {}", bps, width, height, offset); let image = if self.camera.find_hint("double_width") { // Some fuji SuperCCD cameras include a second raw image next to the first one // that is identical but darker to the first. The two combined can produce // a higher dynamic range image. Right now we're ignoring it. decode_16le_skiplines(&src, width, height, dummy) } else if self.camera.find_hint("jpeg32") { match bps { 12 => decode_12be_msb32(&src, width, height, dummy), 14 => decode_14be_msb32(&src, width, height, dummy), _ => return Err(RawlerError::unsupported(&self.camera, format!("RAF: Don't know how to decode bps {}", bps))), } } else if self.camera.clean_model == "DBP for GX680" { assert_eq!(bps, 16); dbp::decode_dbp(&src, width, height, dummy)? } else if src.len() < bps * width * height / 8 { if !dummy { decompress_fuji(&src, width, height, bps, &corrected_cfa)? } else { alloc_image_plain!(width, height, dummy) } } else { match bps { 12 => decode_12le(&src, width, height, dummy), 14 => decode_14le_unpacked(&src, width, height, dummy), 16 => { if self.ifd.endian == Endian::Little { decode_16le(&src, width, height, dummy) } else { decode_16be(&src, width, height, dummy) } } _ => { return Err(RawlerError::unsupported(&self.camera, format!("RAF: Don't know how to decode bps {}", bps))); } } }; let blacklevel = self.get_blacklevel(&corrected_cfa)?; log::debug!("RAF Blacklevels: {:?}", blacklevel); // For now, we put the rotated data into DNG. Much better solution // would be to support staggered layouts, but this is not used much // and complicated to implement, because we need rectangular CFA patterns like 2x4. // The code path for staggered data is already implemented here, but remains unused. let rotate_for_dng = false; let cpp = 1; if self.camera.find_hint("fuji_rotation") || self.camera.find_hint("fuji_rotation_alt") { log::debug!("Apply Fuji image rotation"); let rotated = if rotate_for_dng { if self.camera.find_hint("fuji_rotation") { fuji_raw_rotate(&image, dummy) // Only required for fuji_rotation } else { image } } else { self.rotate_image(image.pixels(), &self.camera, width, height, dummy)? }; let mut camera = self.camera.clone(); camera.cfa = corrected_cfa; let photometric = RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&camera)); let mut image = RawImage::new( self.camera.clone(), rotated, cpp, normalize_wb(self.get_wb()?), photometric, blacklevel, None, dummy, ); if rotate_for_dng { image.add_dng_tag(TiffCommonTag::CFARepeatPatternDim, [2, 4]); image.add_dng_tag(DngTag::CFALayout, 2_u16); image.add_dng_tag(TiffCommonTag::CFAPattern, &[0_u8, 1, 2, 1, 2, 1, 0, 1][..]); todo!(); //image.add_dng_tag(DngTag::BlackLevel, image.blacklevel[0]); //image.add_dng_tag(DngTag::BlackLevelRepeatDim, [1_u16, 1_u16]); } // Reset crops because we have rotated the data. image.active_area = None; image.crop_area = None; Ok(image) } else { //ok_image(self.camera.clone(), width, height, cpp, self.get_wb()?, image.into_inner()) let mut camera = self.camera.clone(); camera.cfa = corrected_cfa; let whitelevel = if self.camera.whitelevel.is_none() { match bps { 12 | 14 | 16 => { let max_value: u32 = (1_u32 << bps) - 1; Some(WhiteLevel::new(vec![max_value; cpp])) } _ => None, } } else { None }; let photometric = RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&camera)); let mut image = RawImage::new(camera, image, cpp, normalize_wb(self.get_wb()?), photometric, blacklevel, whitelevel, dummy); // Overwrite crop if available in metadata if let Some(crop) = self.get_crop()? { log::debug!("RAW file metadata contains crop info, overriding toml definitions: {:?}", crop); image.crop_area = Some(crop); } // Ideally, someone would expect that area is at bayer pattern // boundary. This is not the case, so we don't check this here. // if let Some(_area) = image.active_area.as_ref() { // assert_eq!(area.d.w % image.cfa.width , 0); // assert_eq!(area.d.h % image.cfa.height , 0); // } Ok(image) } } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let mut exif = Exif::new(&self.ifd)?; // Fuji RAF has all EXIF tags we need and there is no LensID or something // we can lookup. So this is an exception, we just pass the information. // TODO: better imeplement LensData::from_exif()? if let Some(ifd) = self.ifd.get_sub_ifd(TiffCommonTag::ExifIFDPointer) { exif.lens_make = ifd.get_entry(ExifTag::LensMake).and_then(|entry| entry.as_string().cloned()); exif.lens_model = ifd.get_entry(ExifTag::LensModel).and_then(|entry| entry.as_string().cloned()); exif.lens_spec = ifd.get_entry(ExifTag::LensSpecification).and_then(|entry| match &entry.value { Value::Rational(data) => Some([data[0], data[1], data[2], data[3]]), _ => None, }); } let mdata = RawMetadata::new(&self.camera, exif); Ok(mdata) } fn xpacket(&self, file: &RawSource, _params: &RawDecodeParams) -> Result>> { let jpeg_buf = self.read_embedded_jpeg(file)?; let mut cur = Cursor::new(jpeg_buf); let jfif = Jfif::parse(&mut cur)?; match jfif.xpacket().cloned() { Some(xpacket) => { log::debug!("Found XPacket data in embedded JPEG preview"); Ok(Some(xpacket)) } None => { log::debug!("Found no XPacket data"); Ok(None) } } } fn full_image(&self, file: &RawSource, params: &RawDecodeParams) -> Result> { if params.image_index != 0 { return Ok(None); } let jpeg_buf = self.read_embedded_jpeg(file)?; let img = image::load_from_memory_with_format(jpeg_buf, image::ImageFormat::Jpeg) .map_err(|err| RawlerError::DecoderFailed(format!("Failed to read JPEG: {:?}", err)))?; Ok(Some(img)) } fn format_dump(&self) -> FormatDump { todo!() } fn format_hint(&self) -> FormatHint { FormatHint::RAF } } impl<'a> RafDecoder<'a> { fn get_wb(&self) -> Result<[f32; 4]> { let raw = self.ifd.find_first_ifd_with_tag(FujiIFD::StripOffsets).ok_or("No StripOffsets found")?; match raw.get_entry(FujiIFD::WB_GRBLevels) { Some(levels) => Ok([levels.force_f32(1), levels.force_f32(0), levels.force_f32(0), levels.force_f32(2)]), None => { let raf = &self .ifd .sub_ifds() .get(&RAF_TAG_VIRTUAL_RAF_DATA) .and_then(|ifds| ifds.get(0)) .ok_or("No RAF data IFD found")?; let levels = fetch_tiff_tag!(raf, TiffCommonTag::RafOldWB); Ok([levels.force_f32(1), levels.force_f32(0), levels.force_f32(0), levels.force_f32(3)]) } } } fn get_blacklevel(&self, cfa: &CFA) -> Result> { if let Some(fuji) = self.ifd.get_sub_ifd(FujiIFD::FujiIFD) { if let Some(Entry { value: Value::Long(black), .. }) = fuji.get_entry_recursive(FujiIFD::BlackLevel) { let levels: Vec = black.iter().copied().map(|v| v as u16).collect(); return Ok(Some(BlackLevel::new(&levels, cfa.width, cfa.height, 1))); } else { log::debug!("Unable to find black level data"); } } Ok(None) } /// Get crop from metadata /// Nearly all models have this parameter, except of FinePix HS10 fn get_crop(&self) -> Result> { if let Some(raf) = &self.ifd.sub_ifds().get(&RAF_TAG_VIRTUAL_RAF_DATA).and_then(|ifds| ifds.get(0)) { let crops = raf.get_entry(RafTags::RawImageCropTopLeft); let size = raf.get_entry(RafTags::RawImageCroppedSize); if let (Some(crops), Some(size)) = (crops, size) { return Ok(Some(Rect::new( Point::new(crops.force_usize(1), crops.force_usize(0)), Dim2::new(size.force_usize(1), size.force_usize(0)), ))); } } Ok(None) } /// Get the X-Trans CFA pattern /// This is encoded in RAF metadata block in XTransLayout. /// For unknown reason, the values are stored in reverse order and /// also falsely reported by exiftoool. fn get_xtrans_cfa(&self) -> Result> { Ok( if let Some(raf) = &self .ifd .sub_ifds() .get(&RAF_TAG_VIRTUAL_RAF_DATA) .and_then(|ifds| ifds.get(0).and_then(|ifd| ifd.get_entry(RafTags::XTransLayout))) { match &raf.value { Value::Byte(data) => { let patname: String = data .iter() .rev() .map(|v| match v { 0 => 'R', 1 => 'G', 2 => 'B', _ => 'X', // Unknown, let CFA::new() fail... }) .collect(); Some(CFA::new(&patname)) } _ => { return Err("Invalid XTransLayout data type".into()); } } } else { None }, ) } fn read_embedded_jpeg<'b>(&self, file: &'b RawSource) -> Result<&'b [u8]> { // The offset and len of JPEG preview is in the RAF structure let buf = file.subview(0, 84 + 8)?; let jpeg_off = BEu32(buf, 84) as u64; let jpeg_len = BEu32(buf, 84 + 4) as u64; log::debug!("JPEG off: {}, len: {}", jpeg_off, jpeg_len); Ok(file.subview(jpeg_off, jpeg_len)?) } fn rotate_image(&self, src: &[u16], camera: &Camera, width: usize, height: usize, dummy: bool) -> Result { if let Some(active_area) = self.camera.active_area { let x = active_area[0]; let y = active_area[1]; let cropwidth = width - active_area[2] - x; let cropheight = height - active_area[3] - y; // TODO: bug, invalid order of crop index if camera.find_hint("fuji_rotation_alt") { let rotatedwidth = cropheight + cropwidth / 2; let rotatedheight = rotatedwidth - 1; let mut out = alloc_image_plain!(rotatedwidth, rotatedheight, dummy); if !dummy { for row in 0..cropheight { let inb = &src[(row + y) * width + x..]; for col in 0..cropwidth { let out_row = rotatedwidth - (cropheight + 1 - row + (col >> 1)); let out_col = ((col + 1) >> 1) + row; out[out_row * rotatedwidth + out_col] = inb[col]; } } } Ok(out) } else { let rotatedwidth = cropwidth + cropheight / 2; let rotatedheight = rotatedwidth - 1; let mut out = alloc_image_plain!(rotatedwidth, rotatedheight, dummy); if !dummy { for row in 0..cropheight { let inb = &src[(row + y) * width + x..]; for col in 0..cropwidth { let out_row = cropwidth - 1 - col + (row >> 1); let out_col = ((row + 1) >> 1) + col; out[out_row * rotatedwidth + out_col] = inb[col]; } } } Ok(out) } } else { Err(RawlerError::DecoderFailed("no active_area for fuji_rotate".to_string())) } } } fn normalize_wb(raw_wb: [f32; 4]) -> [f32; 4] { log::debug!("RAF raw wb: {:?}", raw_wb); // We never have more then RGB colors so far (no RGBE etc.) // So we combine G1 and G2 to get RGB wb. let div = raw_wb[1]; let mut norm = raw_wb; norm.iter_mut().for_each(|v| { if v.is_normal() { *v /= div } }); [norm[0], (norm[1] + norm[2]) / 2.0, norm[3], f32::NAN] } crate::tags::tiff_tag_enum!(RafMakernotes); crate::tags::tiff_tag_enum!(FujiIFD); crate::tags::tiff_tag_enum!(RafTags); /// Specific RAF Makernotes tags. /// These are only related to the Makernote IFD. #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] #[allow(non_camel_case_types)] pub enum RafMakernotes { Version = 0x0000, InternalSerialNumber = 0x0010, Quality = 0x1000, Sharpness = 0x1001, WhiteBalance = 0x1002, Saturation = 0x1003, Contrast = 0x1004, ColorTemperature = 0x1005, Contrast2 = 0x1006, WhiteBalanceFineTune = 0x100a, NoiseReduction = 0x100b, NoiseReduction2 = 0x100e, FujiFlashMode = 0x1010, FlashExposureComp = 0x1011, Macro = 0x1020, FocusMode = 0x1021, AFMode = 0x1022, FocusPixel = 0x1023, PrioritySettings = 0x102b, FocusSettings = 0x102d, AFCSettings = 0x102e, SlowSync = 0x1030, PictureMode = 0x1031, ExposureCount = 0x1032, EXRAuto = 0x1033, EXRMode = 0x1034, ShadowTone = 0x1040, HighlightTone = 0x1041, DigitalZoom = 0x1044, LensModulationOptimizer = 0x1045, GrainEffect = 0x1047, ColorChromeEffect = 0x1048, BWAdjustment = 0x1049, CropMode = 0x104d, ColorChromeFXBlue = 0x104e, ShutterType = 0x1050, AutoBracketing = 0x1100, SequenceNumber = 0x1101, DriveSettings = 0x1103, PixelShiftShots = 0x1105, PixelShiftOffset = 0x1106, PanoramaAngle = 0x1153, PanoramaDirection = 0x1154, AdvancedFilter = 0x1201, ColorMode = 0x1210, BlurWarning = 0x1300, FocusWarning = 0x1301, ExposureWarning = 0x1302, GEImageSize = 0x1304, DynamicRange = 0x1400, FilmMode = 0x1401, DynamicRangeSetting = 0x1402, DevelopmentDynamicRange = 0x1403, MinFocalLength = 0x1404, MaxFocalLength = 0x1405, MaxApertureAtMinFocal = 0x1406, MaxApertureAtMaxFocal = 0x1407, AutoDynamicRange = 0x140b, ImageStabilization = 0x1422, SceneRecognition = 0x1425, Rating = 0x1431, ImageGeneration = 0x1436, ImageCount = 0x1438, DRangePriority = 0x1443, DRangePriorityAuto = 0x1444, DRangePriorityFixed = 0x1445, FlickerReduction = 0x1446, VideoRecordingMode = 0x3803, PeripheralLighting = 0x3804, VideoCompression = 0x3806, FrameRate = 0x3820, FrameWidth = 0x3821, FrameHeight = 0x3822, FullHDHighSpeedRec = 0x3824, FaceElementSelected = 0x4005, FacesDetected = 0x4100, FacePositions = 0x4103, NumFaceElements = 0x4200, FaceElementTypes = 0x4201, FaceElementPositions = 0x4203, FaceRecInfo = 0x4282, FileSource = 0x8000, OrderNumber = 0x8002, FrameNumber = 0x8003, Parallax = 0xb211, } /// These are only related to the additional FujiIFD in RAF files #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] #[allow(non_camel_case_types)] pub enum FujiIFD { FujiIFD = 0xf000, RawImageFullWidth = 0xf001, RawImageFullHeight = 0xf002, BitsPerSample = 0xf003, StripOffsets = 0xf007, StripByteCounts = 0xf008, BlackLevel = 0xf00a, GeometricDistortionParams = 0xf00b, WB_GRBLevelsStandard = 0xf00c, WB_GRBLevelsAuto = 0xf00d, WB_GRBLevels = 0xf00e, ChromaticAberrationParams = 0xf00f, VignettingParams = 0xf010, } /// These are only related to the additional RAF-tags in RAF files #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] #[allow(non_camel_case_types)] pub enum RafTags { RawImageFullSize = 0x0100, RawImageCropTopLeft = 0x0110, RawImageCroppedSize = 0x0111, RawImageAspectRatio = 0x0115, RawImageSize = 0x0121, FujiLayout = 0x0130, XTransLayout = 0x0131, WB_GRGBLevels = 0x2ff0, RelativeExposure = 0x9200, RawExposureBias = 0x9650, RAFData = 0xc000, } pub fn fuji_raw_rotate(img: &PixU16, dummy: bool) -> PixU16 { let mut out = alloc_image!(img.height, img.width, dummy); for row in 0..img.height { for col in 0..img.width { //*x.at_mut(row, col) = out[flip_index(row, col)]; //*x.at_mut(row, col) = out[(width - 1 - col) * height + (height - 1 - row)]; //*out.at_mut(img.width - 1 - col, img.height - 1 - row) = *img.at(row, col); // out[row * width + col]; *out.at_mut(col, row) = *img.at(row, col); // out[row * width + col]; } } out } rawler-0.7.1/src/decoders/rw2/v4decompressor.rs000064400000000000000000000043651046102023000175530ustar 00000000000000use crate::{bits::LEu16, decoders::*, pumps::BitPump}; pub(crate) fn decode_panasonic_v4(buf: &[u8], width: usize, height: usize, split: bool, dummy: bool) -> PixU16 { decode_threaded_multiline( width, height, 5, dummy, &(|out: &mut [u16], row| { let skip = ((width * row * 9) + (width / 14 * 2 * row)) / 8; let blocks = skip / 0x4000; let src = &buf[blocks * 0x4000..]; let mut pump = BitPumpPanasonic::new(src, split); for _ in 0..(skip % 0x4000) { pump.get_bits(8); } let mut sh: i32 = 0; for out in out.chunks_exact_mut(14) { let mut pred: [i32; 2] = [0, 0]; let mut nonz: [i32; 2] = [0, 0]; for i in 0..14 { if (i % 3) == 2 { sh = 4 >> (3 - pump.get_bits(2)); } if nonz[i & 1] != 0 { let j = pump.get_bits(8) as i32; if j != 0 { pred[i & 1] -= 0x80 << sh; if pred[i & 1] < 0 || sh == 4 { pred[i & 1] &= !(-1 << sh); } pred[i & 1] += j << sh; } } else { nonz[i & 1] = pump.get_bits(8) as i32; if nonz[i & 1] != 0 || i > 11 { pred[i & 1] = (nonz[i & 1] << 4) | (pump.get_bits(4) as i32); } } out[i] = pred[i & 1] as u16; } } Ok(()) }), ) .expect("Failed to decode") // Decoder should never fail } pub struct BitPumpPanasonic<'a> { buffer: &'a [u8], pos: usize, nbits: u32, split: bool, } impl<'a> BitPumpPanasonic<'a> { pub fn new(src: &'a [u8], split: bool) -> BitPumpPanasonic<'a> { BitPumpPanasonic { buffer: src, pos: 0, nbits: 0, split, } } } impl<'a> BitPump for BitPumpPanasonic<'a> { fn peek_bits(&mut self, num: u32) -> u32 { if num > self.nbits { self.nbits += 0x4000 * 8; self.pos += 0x4000; } let mut byte = ((self.nbits - num) >> 3) ^ 0x3ff0; if self.split { byte = (byte + 0x4000 - 0x2008) % 0x4000; } let bits = LEu16(self.buffer, byte as usize + self.pos - 0x4000) as u32; (bits >> ((self.nbits - num) & 7)) & (0x0ffffffffu32 >> (32 - num)) } fn consume_bits(&mut self, num: u32) { self.nbits -= num; } } rawler-0.7.1/src/decoders/rw2/v5decompressor.rs000064400000000000000000000035601046102023000175500ustar 00000000000000/// Ported from Libraw use crate::{ decoders::*, pumps::{BitPump, BitPumpLSB}, }; /// This works for 12 and 14 bit depth images pub(crate) fn decode_panasonic_v5(buf: &[u8], width: usize, height: usize, bps: u32, dummy: bool) -> PixU16 { // Raw data is divided into blocks of same size const V5_BLOCK_SIZE: usize = 0x4000; // Each block is splitted and swapped, we need to swap back const V5_SECTION_SPLIT_OFFSET: usize = 0x1FF8; // Each block contains multiple packets const V5_BYTES_PER_PACKET: usize = 16; // Count of packets in a block const V5_PACKETS_PER_BLOCK: usize = V5_BLOCK_SIZE / V5_BYTES_PER_PACKET; // Depending on bit depth, a packet forms different amount of pixels let pixels_per_packet = match bps { 12 => 10, 14 => 9, _ => unreachable!(), }; // Pixel count per full block let pixels_per_block = V5_PACKETS_PER_BLOCK * pixels_per_packet; log::debug!("RW2 V5 decoder: pixels per block: {}, bps: {}", pixels_per_block, bps); // We decode chunked at pixels_per_block boundary // Each block delivers the same amount of pixels. decode_threaded_chunked( width, height, pixels_per_block, dummy, &(|chunk, block_id| { // Block offset let src = &buf[block_id * V5_BLOCK_SIZE..block_id * V5_BLOCK_SIZE + V5_BLOCK_SIZE]; // Now swap the two parts of the block let mut swapped = Vec::with_capacity(V5_BLOCK_SIZE); swapped.extend_from_slice(&src[V5_SECTION_SPLIT_OFFSET..]); swapped.extend_from_slice(&src[..V5_SECTION_SPLIT_OFFSET]); // Transform the packets into final pixels for (out, bytes) in chunk.chunks_exact_mut(pixels_per_packet).zip(swapped.chunks_exact(V5_BYTES_PER_PACKET)) { // The packet is a bitstream in LSB order. let mut pump = BitPumpLSB::new(bytes); out.iter_mut().for_each(|p| *p = pump.get_bits(bps) as u16); } }), ) } rawler-0.7.1/src/decoders/rw2/v6decompressor.rs000064400000000000000000000143751046102023000175570ustar 00000000000000/// Ported from Libraw use crate::{ decoders::*, pumps::{BitPump, BitPumpLSB}, }; /// This works for 12 and 14 bit depth images pub(crate) fn decode_panasonic_v6(buf: &[u8], width: usize, height: usize, bps: u32, dummy: bool) -> PixU16 { log::debug!("width: {}", width); const V6_BYTES_PER_BLOCK: usize = 16; let pixels_per_block; let pixelbase0; let pixelbase_compare; let spix_compare; let pixel_mask; match bps { 12 => { pixels_per_block = 14; pixelbase0 = 0x80; pixelbase_compare = 0x800; spix_compare = 0x3fff; pixel_mask = 0xfff; } 14 => { pixels_per_block = 11; pixelbase0 = 0x200; pixelbase_compare = 0x2000; spix_compare = 0xffff; pixel_mask = 0x3fff; } _ => { unreachable!() } } let blocks_per_row = width / pixels_per_block; let bytes_per_row = V6_BYTES_PER_BLOCK * blocks_per_row; assert_eq!(width % pixels_per_block, 0); //log::debug!("RW2 V5 decoder: pixels per block: {}, bps: {}", pixels_per_block, bps); // We decode chunked at pixels_per_block boundary // Each block delivers the same amount of pixels. decode_threaded( width, height, dummy, &(|out, row| { let src = &buf[row * bytes_per_row..row * bytes_per_row + bytes_per_row]; for (block_id, block) in src.chunks_exact(V6_BYTES_PER_BLOCK).enumerate() { let out = &mut out[block_id * pixels_per_block..]; let mut pixelbuffer = [0_u16; 18]; let mut pump = BitPumpLSB::new(block); match bps { 14 => { // We fill from reverse, because bitstream is reversed pump.get_bits(4); // padding bits, ignore it pixelbuffer[13] = pump.get_bits(10) as u16; pixelbuffer[12] = pump.get_bits(10) as u16; pixelbuffer[11] = pump.get_bits(10) as u16; pixelbuffer[10] = pump.get_bits(2) as u16; pixelbuffer[9] = pump.get_bits(10) as u16; pixelbuffer[8] = pump.get_bits(10) as u16; pixelbuffer[7] = pump.get_bits(10) as u16; pixelbuffer[6] = pump.get_bits(2) as u16; pixelbuffer[5] = pump.get_bits(10) as u16; pixelbuffer[4] = pump.get_bits(10) as u16; pixelbuffer[3] = pump.get_bits(10) as u16; pixelbuffer[2] = pump.get_bits(2) as u16; pixelbuffer[1] = pump.get_bits(14) as u16; pixelbuffer[0] = pump.get_bits(14) as u16; } 12 => { pixelbuffer[17] = pump.get_bits(8) as u16; pixelbuffer[16] = pump.get_bits(8) as u16; pixelbuffer[15] = pump.get_bits(8) as u16; pixelbuffer[14] = pump.get_bits(2) as u16; pixelbuffer[13] = pump.get_bits(8) as u16; pixelbuffer[12] = pump.get_bits(8) as u16; pixelbuffer[11] = pump.get_bits(8) as u16; pixelbuffer[10] = pump.get_bits(2) as u16; pixelbuffer[9] = pump.get_bits(8) as u16; pixelbuffer[8] = pump.get_bits(8) as u16; pixelbuffer[7] = pump.get_bits(8) as u16; pixelbuffer[6] = pump.get_bits(2) as u16; pixelbuffer[5] = pump.get_bits(8) as u16; pixelbuffer[4] = pump.get_bits(8) as u16; pixelbuffer[3] = pump.get_bits(8) as u16; pixelbuffer[2] = pump.get_bits(2) as u16; pixelbuffer[1] = pump.get_bits(12) as u16; pixelbuffer[0] = pump.get_bits(12) as u16; } _ => unreachable!(), } let mut curr_pixel = 0; let mut next_pixel = || -> u16 { curr_pixel += 1; pixelbuffer[curr_pixel - 1] }; let mut oddeven = [0, 0]; let mut nonzero = [0, 0]; let mut pmul = 0; let mut pixel_base = 0; for pix in 0..pixels_per_block { if pix % 3 == 2 { let mut base = next_pixel(); if base == 3 { base = 4; } pixel_base = pixelbase0 << base; pmul = 1 << base; } let mut epixel: u16 = next_pixel(); if oddeven[pix % 2] != 0 { epixel *= pmul; if pixel_base < pixelbase_compare && nonzero[pix % 2] > pixel_base { epixel += nonzero[pix % 2] - pixel_base; } nonzero[pix % 2] = epixel; } else { oddeven[pix % 2] = epixel; if epixel != 0 { nonzero[pix % 2] = epixel; } else { epixel = nonzero[pix % 2]; } } let spix = (epixel as i32).wrapping_sub(0xf); if spix <= spix_compare { out[pix] = (spix & spix_compare) as u16; } else { // FIXME: this is a convoluted way to compute zero. // What was this code trying to do, actually? epixel = ((epixel as i32).wrapping_add(0x7ffffff1) >> 0x1f) as u16; //epixel = static_cast(epixel + 0x7ffffff1) >> 0x1f; //out(row, col) = epixel & 0x3fff; out[pix] = (epixel & pixel_mask) as u16; } } /* for (int pix = 0; pix < PanasonicV6Decompressor::PixelsPerBlock; pix++, col++) { if (pix % 3 == 2) { uint16_t base = page.nextpixel(); if (base == 3) base = 4; pixel_base = 0x200 << base; pmul = 1 << base; } uint16_t epixel = page.nextpixel(); if (oddeven[pix % 2]) { epixel *= pmul; if (pixel_base < 0x2000 && nonzero[pix % 2] > pixel_base) epixel += nonzero[pix % 2] - pixel_base; nonzero[pix % 2] = epixel; } else { oddeven[pix % 2] = epixel; if (epixel) nonzero[pix % 2] = epixel; else epixel = nonzero[pix % 2]; } auto spix = static_cast(static_cast(epixel) - 0xf); if (spix <= 0xffff) out(row, col) = spix & 0xffff; else { // FIXME: this is a convoluted way to compute zero. // What was this code trying to do, actually? epixel = static_cast(epixel + 0x7ffffff1) >> 0x1f; out(row, col) = epixel & 0x3fff; } } */ } }), ) } rawler-0.7.1/src/decoders/rw2/v7decompressor.rs000064400000000000000000000017751046102023000175600ustar 00000000000000/// Ported from Libraw use crate::{ decoders::*, pumps::{BitPump, BitPumpLSB}, }; /// This works for 12 and 14 bit depth images pub(crate) fn decode_panasonic_v7(buf: &[u8], width: usize, height: usize, bps: u32, dummy: bool) -> PixU16 { const V7_BYTES_PER_BLOCK: usize = 16; let pixels_per_block = match bps { 14 => 9, 12 => 10, _ => unreachable!(), }; let blocks_per_row = width / pixels_per_block; assert_eq!(width % pixels_per_block, 0); let bytes_per_row = V7_BYTES_PER_BLOCK * blocks_per_row; decode_threaded( width, height, dummy, &(|out, row| { let src = &buf[row * bytes_per_row..row * bytes_per_row + bytes_per_row]; for (block_id, block) in src.chunks_exact(V7_BYTES_PER_BLOCK).enumerate() { let start = block_id * pixels_per_block; let out = &mut out[start..start + pixels_per_block]; let mut pump = BitPumpLSB::new(block); out.iter_mut().for_each(|pixel| *pixel = pump.get_bits(14) as u16); } }), ) } rawler-0.7.1/src/decoders/rw2/v8decompressor.rs000064400000000000000000000403611046102023000175530ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2024 Daniel Vogelbacher // Originally written by LibRaw LLC // Copyright (C) 2022-2024 Alex Tutubalin, LibRaw LLC // Ported from C++ to Rust by Daniel Vogelbacher use itertools::Itertools; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use crate::{ alloc_image_ok, bits::{Endian, clamp}, decoders::{Result, rw2::PanasonicTag}, formats::tiff::IFD, pixarray::{PixU16, SharedPix2D}, pumps::{BitPump, BitPumpReverseBitsMSB, ByteStream}, rawsource::RawSource, }; /// Defines the offsets for the start of a strip. #[derive(Clone, Debug)] struct StripLineOffset { cols: u16, rows: u16, } #[derive(Clone, Debug)] struct CF2Params { /// Unknown value, it's labeled as strip_height but don't match any height #[allow(dead_code)] strip_height: u32, /// Unknown value, it's labeled as strip_width but don't match any width #[allow(dead_code)] strip_width: u32, /// Gamma point and slope value. gamma_point: Vec, gamma_slope: Vec, /// Max data value gamma_clip_val: u16, /// Initial values (base) for huffman coding huf_init_val0: u16, /// Initial values (base) for huffman coding huf_init_val1: u16, /// Initial values (base) for huffman coding huf_init_val2: u16, /// Initial values (base) for huffman coding huf_init_val3: u16, /// Stored huffman table, usually 17 entries /// /// This is a pair of (bitcnt, symbol). /// /// Example table: /// 0000000 10 1022 11 2046 8 254 9 510 /// 0000020 7 126 4 14 4 12 3 4 /// 0000040 3 2 2 0 3 3 3 5 /// 0000060 4 13 5 30 6 62 12 4094 /// 0000100 12 4095 /// 0000104 huf_table: Vec<(u16, u16)>, /// Shift down (0 in all samples...) huf_shift_down: Vec, /// Number of H strips num_of_strips_h: u16, /// Number of V strips num_of_strips_v: u16, /// Offset to bitstream strip_byte_offsets: Vec, /// Starting column offset in a output line strip_line_offsets: Vec, /// Size in bits of compressed bitstream strip_data_size: Vec, /// Strip widths in pixels strip_widths: Vec, /// Strip heights in pixels strip_heights: Vec, } impl CF2Params { fn new(ifd: &IFD) -> Result { let strip_height = fetch_tiff_tag!(ifd, PanasonicTag::CF2StripHeight).force_u32(0); let gamma_point = { let mut bs = ByteStream::new(fetch_tiff_tag!(ifd, PanasonicTag::CF2Unknown1).get_data(), Endian::Little); let count = bs.get_u16(); (0..count).map(|_| bs.get_u32()).collect() }; let gamma_slope = { let mut bs = ByteStream::new(fetch_tiff_tag!(ifd, PanasonicTag::CF2Unknown2).get_data(), Endian::Little); let count = bs.get_u16(); (0..count).map(|_| bs.get_u32()).collect() }; let gamma_clip_val = fetch_tiff_tag!(ifd, PanasonicTag::CF2ClipVal).force_u16(0); let huf_init_val0 = fetch_tiff_tag!(ifd, PanasonicTag::CF2HufInitVal0).force_u16(0); let huf_init_val1 = fetch_tiff_tag!(ifd, PanasonicTag::CF2HufInitVal1).force_u16(0); let huf_init_val2 = fetch_tiff_tag!(ifd, PanasonicTag::CF2HufInitVal2).force_u16(0); let huf_init_val3 = fetch_tiff_tag!(ifd, PanasonicTag::CF2HufInitVal3).force_u16(0); let huf_table = { let mut bs = ByteStream::new(fetch_tiff_tag!(ifd, PanasonicTag::CF2HufTable).get_data(), Endian::Little); let count = bs.get_u16(); (0..count).map(|_| (bs.get_u16(), bs.get_u16())).collect() }; let huf_shift_down = { let mut bs = ByteStream::new(fetch_tiff_tag!(ifd, PanasonicTag::CF2HufShiftDown).get_data(), Endian::Little); let count = bs.get_u16(); (0..count).map(|_| bs.get_u16()).collect() }; let num_of_strips_h = fetch_tiff_tag!(ifd, PanasonicTag::CF2NumberOfStripsH).force_u16(0); let num_of_strips_v = fetch_tiff_tag!(ifd, PanasonicTag::CF2NumberOfStripsV).force_u16(0); let strip_byte_offsets = { let mut bs = ByteStream::new(fetch_tiff_tag!(ifd, PanasonicTag::CF2StripByteOffsets).get_data(), Endian::Little); let count = bs.get_u16(); (0..count).map(|_| bs.get_u32()).collect() }; let strip_line_offsets = { let mut bs = ByteStream::new(fetch_tiff_tag!(ifd, PanasonicTag::CF2StripLineOffsets).get_data(), Endian::Little); let count = bs.get_u16(); (0..count) .map(|_| StripLineOffset { cols: bs.get_u16(), rows: bs.get_u16(), }) .collect() }; let strip_data_size = { let mut bs = ByteStream::new(fetch_tiff_tag!(ifd, PanasonicTag::CF2StripDataSize).get_data(), Endian::Little); let count = bs.get_u16(); (0..count).map(|_| bs.get_u32()).collect() }; let strip_widths = { let mut bs = ByteStream::new(fetch_tiff_tag!(ifd, PanasonicTag::CF2StripWidths).get_data(), Endian::Little); let count = bs.get_u16(); (0..count).map(|_| bs.get_u16()).collect() }; let strip_heights = { let mut bs = ByteStream::new(fetch_tiff_tag!(ifd, PanasonicTag::CF2StripHeights).get_data(), Endian::Little); let count = bs.get_u16(); (0..count).map(|_| bs.get_u16()).collect() }; let strip_width = fetch_tiff_tag!(ifd, PanasonicTag::CF2StripWidth).force_u32(0); Ok(Self { strip_height, gamma_point, gamma_slope, gamma_clip_val, huf_init_val0, huf_init_val1, huf_init_val2, huf_init_val3, huf_table, huf_shift_down, num_of_strips_h, num_of_strips_v, strip_byte_offsets, strip_line_offsets, strip_data_size, strip_widths, strip_heights, strip_width, }) } } #[derive(Clone, Debug, Default)] struct HuffmanSymbol { /// Length of the symbol in bits bitcnt: u8, /// Actual Huffman symbol, right-padded with 0 bits symbol: u16, /// Pre-calculated bitmask, actually (-1) << (16-bits) mask: u16, } #[derive(Clone, Debug, Default)] struct HuffmanDecoder { #[allow(dead_code)] huff_symbols: [HuffmanSymbol; 17], /// Lookup cache for all possible u16 values. /// If a 16 bit input value is invalid (the symbol is undefined), the /// value is None, otherwise it's (bitcnt, ssss) cache: Vec>, } impl HuffmanDecoder { fn new(symlens: impl Iterator, mut symbols: impl Iterator) -> Self { let mut huff_symbols: [HuffmanSymbol; 17] = Default::default(); for (i, symlen) in symlens.enumerate() { let symbol = symbols.next().expect("symbol iterator is shorter than symlens iterator"); let bitmask = 0xFFFFu16 >> (16 - symlen); debug_assert_eq!(symbol, symbol & bitmask); // Left-align symbol and mask huff_symbols[i] = HuffmanSymbol { bitcnt: symlen, symbol: (symbol) << (16 - symlen), mask: 0xFFFF << (16 - symlen), }; } // Generate lookup cache for all possible 16 bit input values. let cache = (0..=0xFFFFu16) .map(|x| Self::slow_lookup(&huff_symbols, x).map(|ssss| (huff_symbols[ssss as usize].bitcnt, ssss))) .collect_vec(); Self { huff_symbols, cache } } /// Slow lookup into Huffman symbol table fn slow_lookup(huff_symbols: &[HuffmanSymbol; 17], bits: u16) -> Option { for i in 0..17 { if (bits & huff_symbols[i].mask) == huff_symbols[i].symbol { return Some(i as u8); } } None } /// Extract Huffman symbol from bitstream pump and /// return index into symbol table. fn get_next(&self, pump: &mut dyn BitPump) -> u8 { let next_bits = pump.peek_bits(16); debug_assert_eq!(self.cache.len(), u16::MAX as usize + 1); if let Some((bits, ssss)) = unsafe { *self.cache.get_unchecked(next_bits as usize) } { pump.consume_bits(bits as u32); ssss } else { panic!("Input value {:016b} starts not with a valid huffman symbol", next_bits); } } } /// Internal decoder state struct State { huffdec: HuffmanDecoder, gamma_table: Option>, datamax: i32, line_base: CoeffBase, current_base: CoeffBase, } impl State { fn new(params: &CF2Params) -> Self { let initial = [params.huf_init_val0, params.huf_init_val1, params.huf_init_val2, params.huf_init_val3]; let gamma_table = make_gammatable(params); let line_base = CoeffBase::new([initial[0], initial[1], initial[2], initial[3]]); let current_base = line_base; let huffdec = HuffmanDecoder::new( params.huf_table.iter().map(|(bits, _symbol)| *bits as u8), params.huf_table.iter().map(|(_bits, symbol)| *symbol), ); Self { huffdec, gamma_table, datamax: params.gamma_clip_val as i32, line_base, current_base, } } } #[derive(Clone, Copy, Debug)] struct CoeffBase { coeff: [u16; 4], } impl CoeffBase { pub fn new(coeff: [u16; 4]) -> Self { Self { coeff } } pub fn update(&mut self, line: &[u16]) { self.coeff = [line[0], line[1], line[2], line[3]]; } } fn calc_gamma(params: &CF2Params, idx: u32) -> u16 { let gamma_base = 0; let gamma_points = ¶ms.gamma_point; // [65536, 65536, 65536, 65536, 65536, 65536] let gamma_slopes = ¶ms.gamma_slope; // 0 let clipping = params.gamma_clip_val; let mut x = { let mut tmp: u32 = idx | 0xFFFF0000; if (idx & 0x10000) == 0 { tmp = idx & 0x1FFFF; } u32::min(gamma_base + tmp, 0xFFFF) }; let mut idx = 0; if (x & 0x80000000) != 0 { x = 0; } if x >= (0xFFFF & gamma_slopes[1]) { idx = 1; if x >= (0xFFFF & gamma_slopes[2]) { idx = 2; if x >= (0xFFFF & gamma_slopes[3]) { idx = 3; if x >= (0xFFFF & gamma_slopes[4]) { idx = (((x as u64 | 0x5_00000000u64) - (0xFFFF & gamma_slopes[5]) as u64) >> 32) as usize; } } } } let point = gamma_points[idx]; let slope = gamma_slopes[idx]; let mut tmp: u32 = x - (slope & 0xFFFF); let result: u16; if (point & 0x1F) == 31 { result = if idx == 5 { 0xFFFF } else { (gamma_slopes[idx + 1] >> 16) & 0xFFFF } as u16; return u16::min(result, clipping); } if (point & 0x10) == 0 { if (point & 0x1F) == 15 { let result = ((slope >> 16) & 0xFFFF) as u16; return u16::min(result, clipping); } else if (point & 0x1F) != 0 { tmp = (tmp + (1 << ((point & 0x1F) - 1))) >> (point & 0x1F); } } else { tmp <<= point & 0xF; } result = (tmp + ((slope >> 16) & 0xFFFF)) as u16; u16::min(result, clipping) } fn make_gammatable(params: &CF2Params) -> Option> { const LINEAR_POINTS: [u32; 6] = [65536; 6]; const LINEAR_SLOPES: [u32; 6] = [0; 6]; if params.gamma_point == LINEAR_POINTS && params.gamma_slope == LINEAR_SLOPES { None } else { let mut table = vec![0; 0x10000]; let mut _linear = true; for idx in 0..0x10000 { table[idx] = calc_gamma(params, idx as u32); _linear = _linear && table[idx] == idx as u16; } Some(table) } } /// Decode Panasonic V8 bitstreams pub(crate) fn decode_panasonic_v8(rawfile: &RawSource, width: usize, height: usize, _bps: u32, ifd: &IFD, dummy: bool) -> Result { let out = alloc_image_ok!(width, height, dummy); let params = CF2Params::new(ifd)?; log::debug!("pana8: params: {:?}", params); assert_eq!( params.strip_widths.iter().map(|x| *x as i32).sum::() as usize / params.num_of_strips_v as usize, width ); // Shared output buffer, we need to write from multiple rayon threads to output image. let shared_pix = SharedPix2D::new(out); let total_strip_count = (params.num_of_strips_h * params.num_of_strips_v) as usize; let mut bitstreams = Vec::with_capacity(total_strip_count); for strip_id in 0..total_strip_count { bitstreams.push(rawfile.subview(params.strip_byte_offsets[strip_id] as u64, (params.strip_data_size[strip_id] as u64 + 7) / 8)?); } // Parallel decode multiple strips (0..total_strip_count).into_par_iter().for_each(|strip_id| { let buf = &bitstreams[strip_id]; decode_strip(buf, ¶ms, strip_id, unsafe { shared_pix.inner_mut() }); }); Ok(shared_pix.into_inner()) } /// Decode a single strip fn decode_strip(buf: &[u8], params: &CF2Params, strip_id: usize, out: &mut PixU16) { let mut pump = BitPumpReverseBitsMSB::new(buf); let width = params.strip_widths[strip_id] as usize; let height = params.strip_heights[strip_id] as usize; let halfheight = height >> 1; let halfwidth = width >> 1; let doublewidth = halfwidth * 4; let mut linebuf = vec![0_u16; doublewidth]; // for (i, item) in params.huf_table.iter().enumerate() { // let fmt = format!("{:#032b}", item.1); // log::debug!("Pana8 huf_table {i}: {} (bits: {})", fmt.split_at((32 - item.0) as usize).1, item.0); // //log::debug!("Pana8: huf_table {:02}: {}, {}", i, item.0, item.1); // } let mut state = State::new(params); // Data is encoded in RGRGRG..GBGBGB in a single line (like LJPEG92 4-7 predictors) for curr_row in 0..halfheight { state.current_base = state.line_base; for col in 0..doublewidth { // Calculate index let ssss = state.huffdec.get_next(&mut pump); // Shiftdown seems to be the count of bits shifted to right during encoding. // It's 0 for all existing samples so far, highly interested in samples that has let shift_down: u8 = (params.huf_shift_down[ssss as usize] & 0x1F) as u8; assert_eq!(shift_down, 0, "CF2HufShiftDown samples required"); // Calculate total required bits to read from bitstream. let req_bits: u32 = ssss.saturating_sub(shift_down as u8) as u32; let delta1: i32 = if req_bits == 0 { 0 } else { debug_assert_ne!(req_bits, 0); let rawbits: u32 = pump.get_bits(req_bits as u32); // Get additional bits let sign = rawbits >> (req_bits - 1); // Get leading sign bit let val = (rawbits << (params.huf_shift_down[ssss as usize] & 0xFF)) as i32; if sign == 1 { val } else if ssss > 0 { if shift_down != 0 { val + (-1 << ssss) } else { val + (-1 << ssss) + 1 } } else { 0 } }; let delta2 = if shift_down != 0 { 1 << (shift_down - 1) } else { 0 }; let delta = delta1 + delta2; // For each col iteration, we write to ONE pixel of of 4-pixel group. let destpixel = &mut linebuf[col & !0x3..]; if col & 3 == 2 { let val = state.current_base.coeff[1] as i32 + delta; destpixel[1] = clamp(val, 0, state.datamax) as u16; } else if col & 3 == 1 { let val = state.current_base.coeff[2] as i32 + delta; destpixel[2] = clamp(val, 0, state.datamax) as u16; } else if col & 3 != 0 { let val = state.current_base.coeff[3] as i32 + delta; destpixel[3] = clamp(val, 0, state.datamax) as u16; } else { let val = state.current_base.coeff[0] as i32 + delta; destpixel[0] = clamp(val, 0, state.datamax) as u16; } if col & 3 == 3 { state.current_base.update(destpixel); } if col == 3 { // base for next line (col == 3 -> first 4 pixels are complete in current row) state.line_base.update(&linebuf); } } // Copy line buffer into output image. // Line buffer contains two rows packed into one row with double width. assert_eq!(linebuf.len(), 2 * width); for col in (0..width).step_by(2) { let row_offset = params.strip_line_offsets[strip_id].rows as usize; let left_margin = params.strip_line_offsets[strip_id].cols as usize; let dest_row = row_offset + (curr_row * 2); if let Some(gamma_table) = &state.gamma_table { debug_assert!(!gamma_table.is_empty()); *out.at_mut(dest_row + 0, left_margin + col + 0) = gamma_table[linebuf[2 * col + 0] as usize]; *out.at_mut(dest_row + 0, left_margin + col + 1) = gamma_table[linebuf[2 * col + 1] as usize]; *out.at_mut(dest_row + 1, left_margin + col + 0) = gamma_table[linebuf[2 * col + 2] as usize]; *out.at_mut(dest_row + 1, left_margin + col + 1) = gamma_table[linebuf[2 * col + 3] as usize]; } else { *out.at_mut(dest_row + 0, left_margin + col + 0) = linebuf[2 * col + 0]; *out.at_mut(dest_row + 0, left_margin + col + 1) = linebuf[2 * col + 1]; *out.at_mut(dest_row + 1, left_margin + col + 0) = linebuf[2 * col + 2]; *out.at_mut(dest_row + 1, left_margin + col + 1) = linebuf[2 * col + 3]; } } } } rawler-0.7.1/src/decoders/rw2.rs000064400000000000000000000363051046102023000145730ustar 00000000000000use image::DynamicImage; use crate::CFA; use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::analyze::FormatDump; use crate::exif::Exif; use crate::formats::tiff::Entry; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::IFD; use crate::formats::tiff::Rational; use crate::formats::tiff::Value; use crate::formats::tiff::reader::TiffReader; use crate::imgop::Dim2; use crate::imgop::Point; use crate::imgop::Rect; use crate::lens::LensDescription; use crate::lens::LensResolver; use crate::packed::decode_12le_unpacked_left_aligned; use crate::packed::decode_12le_wcontrol; use crate::pixarray::PixU16; use crate::rawimage::CFAConfig; use crate::rawimage::RawPhotometricInterpretation; use crate::rawsource::RawSource; use crate::tags::ExifTag; use crate::tags::TiffCommonTag; use crate::tags::tiff_tag_enum; use self::v4decompressor::decode_panasonic_v4; use self::v5decompressor::decode_panasonic_v5; use self::v6decompressor::decode_panasonic_v6; use self::v7decompressor::decode_panasonic_v7; use self::v8decompressor::decode_panasonic_v8; use super::BlackLevel; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; pub(crate) mod v4decompressor; pub(crate) mod v5decompressor; pub(crate) mod v6decompressor; pub(crate) mod v7decompressor; pub(crate) mod v8decompressor; #[derive(Debug, Clone)] pub struct Rw2Decoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, camera_ifd: Option, camera: Camera, } impl<'a> Rw2Decoder<'a> { pub fn new(_file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { let raw = { let data = tiff.find_ifds_with_tag(TiffCommonTag::PanaOffsets); if !data.is_empty() { data[0] } else { tiff .find_first_ifd_with_tag(TiffCommonTag::StripOffsets) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with StripOffsets tag")))? } }; let width = fetch_tiff_tag!(raw, TiffCommonTag::PanaWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::PanaLength).force_usize(0); let mode = { let ratio = width * 100 / height; if ratio < 125 { "1:1" } else if ratio < 145 { "4:3" } else if ratio < 165 { "3:2" } else { "16:9" } }; let camera = rawloader.check_supported_with_mode(tiff.root_ifd(), mode)?; let camera_ifd = if let Some(ifd) = tiff.get_entry(PanasonicTag::CameraIFD) { let buf = ifd.get_data(); match IFD::new_root(&mut std::io::Cursor::new(buf), 0) { Ok(ifd) => Some(ifd), Err(_) => None, } } else { None }; Ok(Rw2Decoder { rawloader, tiff, camera_ifd, camera, }) } } impl<'a> Decoder for Rw2Decoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let width; let height; let (raw, split) = { let data = self.tiff.find_ifds_with_tag(TiffCommonTag::PanaOffsets); if !data.is_empty() { (data[0], true) } else { ( self .tiff .find_first_ifd_with_tag(TiffCommonTag::StripOffsets) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with StripOffsets tag")))?, false, ) } }; let compression = raw.get_entry(PanasonicTag::Compression).map(|entry| entry.force_u16(0)).unwrap_or_default(); // TODO BUG //let compression = fetch_tiff_tag!(raw, PanasonicTag::Compression).force_u16(0); let raw_format = raw.get_entry(PanasonicTag::RawFormat).map(|entry| entry.force_u16(0)).unwrap_or_default(); // TODO BUG let bps = fetch_tiff_tag!(raw, PanasonicTag::BitsPerSample).force_u32(0); let multishot = raw.get_entry(PanasonicTag::Multishot).map(|entry| entry.force_u32(0) == 65536).unwrap_or(false); let image = { let data = self.tiff.find_ifds_with_tag(TiffCommonTag::PanaOffsets); if !data.is_empty() { let raw = data[0]; width = fetch_tiff_tag!(raw, TiffCommonTag::PanaWidth).force_usize(0); height = fetch_tiff_tag!(raw, TiffCommonTag::PanaLength).force_usize(0); let offset = fetch_tiff_tag!(raw, TiffCommonTag::PanaOffsets).force_usize(0); //let size = fetch_tiff_tag!(raw, TiffCommonTag::StripByteCounts).force_usize(0); log::debug!("PanaOffset: {}", offset); let src = file.subview_until_eof_padded(offset as u64)?; // TODO add size and check all samples Rw2Decoder::decode_panasonic(file, &src, width, height, split, raw_format, bps, self.tiff.root_ifd(), dummy)? } else { let raw = self .tiff .find_first_ifd_with_tag(TiffCommonTag::StripOffsets) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with StripOffsets tag")))?; width = fetch_tiff_tag!(raw, TiffCommonTag::PanaWidth).force_usize(0); height = fetch_tiff_tag!(raw, TiffCommonTag::PanaLength).force_usize(0); let offset = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); //let size = fetch_tiff_tag!(raw, TiffCommonTag::StripByteCounts).force_usize(0); log::debug!("StripOffset: {}", offset); let src = file.subview_until_eof_padded(offset as u64)?; // TODO add size and check all samples if src.len() >= width * height * 2 { decode_12le_unpacked_left_aligned(&src, width, height, dummy) } else if src.len() >= width * height * 3 / 2 { decode_12le_wcontrol(&src, width, height, dummy) } else { Rw2Decoder::decode_panasonic(file, &src, width, height, split, raw_format, bps, self.tiff.root_ifd(), dummy)? } } }; log::debug!( "RW2 raw: {}, compression: {}, bps: {}, width: {}, height: {}, multishot: {}", raw_format, compression, bps, width, height, multishot ); let cpp = 1; let blacklevel = self.get_blacklevel()?; let mut camera = self.camera.clone(); if let Some(cfa) = self.get_cfa()? { camera.cfa = cfa; } let photometric = RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&camera)); let mut img = RawImage::new(camera, image, cpp, normalize_wb(self.get_wb()?), photometric, blacklevel, None, dummy); if let Some(area) = self.get_active_area()? { img.active_area = Some(area); img.crop_area = Some(area); } else if let Some(area) = self.get_crop()? { img.crop_area = Some(area); } Ok(img) } fn full_image(&self, _file: &RawSource, params: &RawDecodeParams) -> Result> { if params.image_index != 0 { return Ok(None); } if let Some(data) = self.tiff.get_entry(PanasonicTag::JpegData) { let buf = data.get_data(); let img = image::load_from_memory_with_format(buf, image::ImageFormat::Jpeg) .map_err(|e| RawlerError::DecoderFailed(format!("Unable to load jpeg preview: {:?}", e)))?; return Ok(Some(img)); } Ok(None) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let mut exif = Exif::new(self.tiff.root_ifd())?; if exif.iso_speed.unwrap_or(0) == 0 && exif.iso_speed_ratings.unwrap_or(0) == 0 && exif.recommended_exposure_index.unwrap_or(0) == 0 { // Use ISO from PanasonicRaw IFD if let Some(iso) = self.tiff.get_entry(PanasonicTag::ISO) { exif.iso_speed_ratings = Some(iso.force_u16(0)); } } let mdata = RawMetadata::new_with_lens(&self.camera, exif, self.get_lens_description()?.cloned()); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::RW2 } } impl<'a> Rw2Decoder<'a> { fn get_wb(&self) -> Result<[f32; 4]> { if self.tiff.has_entry(PanasonicTag::PanaWBsR) && self.tiff.has_entry(PanasonicTag::PanaWBsB) { let r = fetch_tiff_tag!(self.tiff, PanasonicTag::PanaWBsR).force_u32(0) as f32; let b = fetch_tiff_tag!(self.tiff, PanasonicTag::PanaWBsB).force_u32(0) as f32; Ok([r, 256.0, 256.0, b]) } else if self.tiff.has_entry(PanasonicTag::PanaWBs2R) && self.tiff.has_entry(PanasonicTag::PanaWBs2G) && self.tiff.has_entry(PanasonicTag::PanaWBs2B) { let r = fetch_tiff_tag!(self.tiff, PanasonicTag::PanaWBs2R).force_u32(0) as f32; let g = fetch_tiff_tag!(self.tiff, PanasonicTag::PanaWBs2G).force_u32(0) as f32; let b = fetch_tiff_tag!(self.tiff, PanasonicTag::PanaWBs2B).force_u32(0) as f32; Ok([r, g, g, b]) } else { Err(RawlerError::DecoderFailed("RW2: Couldn't find WB".to_string())) } } fn get_cfa(&self) -> Result> { if self.tiff.has_entry(PanasonicTag::CFAPattern) { let pattern = fetch_tiff_tag!(self.tiff, PanasonicTag::CFAPattern).force_u16(0); Ok(Some(match pattern { 1 => CFA::new("RGGB"), 2 => CFA::new("GRBG"), 3 => CFA::new("GBRG"), 4 => CFA::new("BGGR"), _ => return Err(format!("RW2: Unknown CFA pattern: {}", pattern).into()), })) } else { Ok(None) } } fn get_blacklevel(&self) -> Result> { if self.tiff.has_entry(PanasonicTag::BlackLevelRed) { let r = fetch_tiff_tag!(self.tiff, PanasonicTag::BlackLevelRed).force_u16(0); let g = fetch_tiff_tag!(self.tiff, PanasonicTag::BlackLevelGreen).force_u16(0); let b = fetch_tiff_tag!(self.tiff, PanasonicTag::BlackLevelBlue).force_u16(0); Ok(Some(BlackLevel::new(&[r, g, g, b], self.camera.cfa.width, self.camera.cfa.height, 1))) } else { Ok(None) } } /// Get lens description by analyzing TIFF tags and makernotes fn get_lens_description(&self) -> Result> { const MFT_MOUNT: &str = "MFT-mount"; if let Some(ifd) = &self.camera_ifd { if ifd.has_entry(CameraIfdTag::LensTypeMake) && ifd.has_entry(CameraIfdTag::LensTypeModel) { let make_id = fetch_tiff_tag!(ifd, CameraIfdTag::LensTypeMake); let model_id = fetch_tiff_tag!(ifd, CameraIfdTag::LensTypeModel); if make_id.value_type() == 3 && model_id.value_type() == 3 { let composite_id = format!( "{:02X} {:02X} {:02X}", make_id.force_u16(0) & 0xFF, model_id.force_u16(0) & 0xFF, model_id.force_u16(0) >> 8 ); log::debug!("RW2 lens composite ID: {}", composite_id); let resolver = LensResolver::new() .with_camera(&self.camera) .with_olympus_id(Some(composite_id)) .with_focal_len(self.get_focal_len()?) .with_mounts(&[MFT_MOUNT.into()]); return Ok(resolver.resolve()); } else { log::info!("Unknown value types for lens tags: {}, {}", make_id.value_type(), model_id.value_type()); } } } log::warn!("No lens data available"); Ok(None) } fn get_focal_len(&self) -> Result> { if let Some(exif) = self.tiff.find_first_ifd_with_tag(ExifTag::MakerNotes) { if let Some(Entry { value: Value::Short(focal), .. }) = exif.get_entry(ExifTag::FocalLength) { return Ok(focal.get(1).map(|v| Rational::new(*v as u32, 1))); } } Ok(None) } fn get_crop(&self) -> Result> { if self.tiff.has_entry(PanasonicTag::CropLeft) { let crop_left = fetch_tiff_tag!(self.tiff, PanasonicTag::CropLeft).force_usize(0); let crop_top = fetch_tiff_tag!(self.tiff, PanasonicTag::CropTop).force_usize(0); let crop_right = fetch_tiff_tag!(self.tiff, PanasonicTag::CropRight).force_usize(0); let crop_bottom = fetch_tiff_tag!(self.tiff, PanasonicTag::CropBottom).force_usize(0); Ok(Some(Rect::new( Point::new(crop_left, crop_top), Dim2::new(crop_right - crop_left, crop_bottom - crop_top), ))) } else { Ok(None) } } fn get_active_area(&self) -> Result> { if self.tiff.has_entry(PanasonicTag::SensorLeftBorder) { let sensor_left = fetch_tiff_tag!(self.tiff, PanasonicTag::SensorLeftBorder).force_usize(0); let sensor_top = fetch_tiff_tag!(self.tiff, PanasonicTag::SensorTopBorder).force_usize(0); let sensor_right = fetch_tiff_tag!(self.tiff, PanasonicTag::SensorRightBorder).force_usize(0); let sensor_bottom = fetch_tiff_tag!(self.tiff, PanasonicTag::SensorBottomBorder).force_usize(0); Ok(Some(Rect::new( Point::new(sensor_left, sensor_top), Dim2::new(sensor_right - sensor_left, sensor_bottom - sensor_top), ))) } else { Ok(None) } } pub(crate) fn decode_panasonic( file: &RawSource, buf: &[u8], width: usize, height: usize, split: bool, raw_format: u16, bps: u32, ifd: &IFD, dummy: bool, ) -> Result { log::debug!("width: {}, height: {}, bps: {}", width, height, bps); Ok(match raw_format { 3 => decode_panasonic_v4(buf, width, height, split, dummy), 4 => decode_panasonic_v4(buf, width, height, split, dummy), 5 => decode_panasonic_v5(buf, width, height, bps, dummy), 6 => decode_panasonic_v6(buf, width, height, bps, dummy), 7 => decode_panasonic_v7(buf, width, height, bps, dummy), 8 => decode_panasonic_v8(file, width, height, bps, ifd, dummy)?, _ => todo!("Format {} is not implemented", raw_format), // TODO: return error }) } } fn normalize_wb(raw_wb: [f32; 4]) -> [f32; 4] { log::debug!("RW2 raw wb: {:?}", raw_wb); let div = raw_wb[1]; let mut norm = raw_wb; norm.iter_mut().for_each(|v| { if v.is_normal() { *v /= div } }); [norm[0], (norm[1] + norm[2]) / 2.0, norm[3], f32::NAN] } tiff_tag_enum!(PanasonicTag); tiff_tag_enum!(CameraIfdTag); /// Common tags, generally used in root IFD or SubIFDs #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum PanasonicTag { PanaWidth = 0x0002, PanaLength = 0x0003, SensorTopBorder = 0x0004, SensorLeftBorder = 0x0005, SensorBottomBorder = 0x0006, SensorRightBorder = 0x0007, SamplesPerPixel = 0x0008, CFAPattern = 0x0009, BitsPerSample = 0x000a, Compression = 0x000b, PanaWBsR = 0x0011, PanaWBsB = 0x0012, ISO = 0x0017, BlackLevelRed = 0x001c, BlackLevelGreen = 0x001d, BlackLevelBlue = 0x001e, PanaWBs2R = 0x0024, PanaWBs2G = 0x0025, PanaWBs2B = 0x0026, RawFormat = 0x0002d, JpegData = 0x002e, CropTop = 0x002f, CropLeft = 0x0030, CropBottom = 0x0031, CropRight = 0x0032, CF2StripHeight = 0x0037, CF2Unknown1 = 0x0039, // Gamma table CF2_GammaSlope? CF2Unknown2 = 0x003a, // Gamma table CF2_GammaPoint? CF2ClipVal = 0x003b, // CF2_GammaClipVal CF2HufInitVal0 = 0x003c, CF2HufInitVal1 = 0x003d, CF2HufInitVal2 = 0x003e, CF2HufInitVal3 = 0x003f, CF2HufTable = 0x0040, CF2HufShiftDown = 0x0041, CF2NumberOfStripsH = 0x0042, CF2NumberOfStripsV = 0x0043, CF2StripByteOffsets = 0x0044, CF2StripLineOffsets = 0x0045, CF2StripDataSize = 0x0046, CF2StripWidths = 0x0047, CF2StripHeights = 0x0048, CF2StripWidth = 0x0064, CameraIFD = 0x0120, Multishot = 0x0121, } /// Common tags, generally used in root IFD or SubIFDs #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum CameraIfdTag { LensTypeMake = 0x1201, LensTypeModel = 0x1202, } rawler-0.7.1/src/decoders/srw.rs000064400000000000000000000447641046102023000147040ustar 00000000000000use log::warn; use std::cmp; use crate::RawImage; use crate::RawLoader; use crate::RawlerError; use crate::Result; use crate::alloc_image; use crate::analyze::FormatDump; use crate::bits::LEu32; use crate::bits::clampbits; use crate::exif::Exif; use crate::formats::tiff::GenericTiffReader; use crate::formats::tiff::IFD; use crate::formats::tiff::ifd::OffsetMode; use crate::formats::tiff::reader::TiffReader; use crate::lens::LensDescription; use crate::lens::LensResolver; use crate::packed::decode_12be; use crate::packed::decode_12le; use crate::packed::decode_12le_unpacked; use crate::packed::decode_14le_unpacked; use crate::pixarray::PixU16; use crate::pumps::BitPump; use crate::pumps::BitPumpMSB; use crate::pumps::BitPumpMSB32; use crate::rawsource::RawSource; use crate::tags::ExifTag; use crate::tags::TiffCommonTag; use super::Camera; use super::Decoder; use super::FormatHint; use super::RawDecodeParams; use super::RawMetadata; use super::ok_cfa_image_with_blacklevels; const NX_MOUNT: &str = "NX-mount"; #[derive(Debug, Clone)] pub struct SrwDecoder<'a> { #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, makernote: IFD, camera: Camera, } impl<'a> SrwDecoder<'a> { pub fn new(file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { let camera = rawloader.check_supported(tiff.root_ifd())?; let makernote = if let Some(exif) = tiff.find_first_ifd_with_tag(ExifTag::MakerNotes) { exif.parse_makernote(&mut file.reader(), OffsetMode::RelativeToIFD, &[])? } else { warn!("SRW makernote not found"); None } .ok_or("File has not makernotes")?; Ok(SrwDecoder { tiff, rawloader, camera, makernote, }) } } impl<'a> Decoder for SrwDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let raw = self .tiff .find_first_ifd_with_tag(TiffCommonTag::StripOffsets) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with StripOffsets tag")))?; let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let offset = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); let compression = fetch_tiff_tag!(raw, TiffCommonTag::Compression).force_u32(0); let bits = fetch_tiff_tag!(raw, TiffCommonTag::BitsPerSample).force_u32(0); let src = file.subview_until_eof_padded(offset as u64)?; let image = match compression { 32769 => match bits { 12 => decode_12le_unpacked(&src, width, height, dummy), 14 => decode_14le_unpacked(&src, width, height, dummy), x => return Err(RawlerError::unsupported(&self.camera, format!("SRW: Don't know how to handle bps {}", x))), }, 32770 => match raw.get_entry(TiffCommonTag::SrwSensorAreas) { None => match bits { 12 => { if self.camera.find_hint("little_endian") { decode_12le(&src, width, height, dummy) } else { decode_12be(&src, width, height, dummy) } } 14 => decode_14le_unpacked(&src, width, height, dummy), x => return Err(RawlerError::unsupported(&self.camera, format!("SRW: Don't know how to handle bps {}", x))), }, Some(x) => { let coffset = x.force_usize(0); assert!(coffset > 0, "Surely this can't be the start of the file"); let loffsets = file.subview_until_eof(coffset as u64)?; SrwDecoder::decode_srw1(&src, loffsets, width, height, dummy) } }, 32772 => SrwDecoder::decode_srw2(&src, width, height, dummy), 32773 => SrwDecoder::decode_srw3(&src, width, height, dummy), x => { return Err(RawlerError::unsupported( &self.camera, format!("SRW: Don't know how to handle compression {}", x), )); } }; let cpp = 1; ok_cfa_image_with_blacklevels(self.camera.clone(), cpp, self.get_wb()?, self.get_blacklevel()?, image, dummy) } fn format_dump(&self) -> FormatDump { todo!() } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; let mdata = RawMetadata::new_with_lens(&self.camera, exif, self.get_lens_description()?.cloned()); Ok(mdata) } fn format_hint(&self) -> FormatHint { FormatHint::SRW } } impl<'a> SrwDecoder<'a> { pub fn decode_srw1(buf: &[u8], loffsets: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { let mut out = alloc_image!(width, height, dummy); for row in 0..height { let mut len: [u32; 4] = [if row < 2 { 7 } else { 4 }; 4]; let loffset = LEu32(loffsets, row * 4) as usize; let mut pump = BitPumpMSB32::new(&buf[loffset..]); let img = width * row; let img_up = width * (cmp::max(1, row) - 1); let img_up2 = width * (cmp::max(2, row) - 2); // Image is arranged in groups of 16 pixels horizontally for col in (0..width).step_by(16) { let dir = pump.get_bits(1) == 1; let ops = [pump.get_bits(2), pump.get_bits(2), pump.get_bits(2), pump.get_bits(2)]; for (i, op) in ops.iter().enumerate() { match *op { 3 => len[i] = pump.get_bits(4), 2 => len[i] -= 1, 1 => len[i] += 1, _ => {} } } // First decode even pixels for c in (0..16).step_by(2) { let l = len[c >> 3]; let adj = pump.get_ibits_sextended(l); let predictor = if dir { // Upward prediction out[img_up + col + c] } else { // Left to right prediction if col == 0 { 128 } else { out[img + col - 2] } }; if col + c < width { // No point in decoding pixels outside the image out[img + col + c] = ((predictor as i32) + adj) as u16; } } // Now decode odd pixels for c in (1..16).step_by(2) { let l = len[2 | (c >> 3)]; let adj = pump.get_ibits_sextended(l); let predictor = if dir { // Upward prediction out[img_up2 + col + c] } else { // Left to right prediction if col == 0 { 128 } else { out[img + col - 1] } }; if col + c < width { // No point in decoding pixels outside the image out[img + col + c] = ((predictor as i32) + adj) as u16; } } } } // SRW1 apparently has red and blue swapped, just changing the CFA pattern to // match causes color fringing in high contrast areas because the actual pixel // locations would not match the CFA pattern for row in (0..height).step_by(2) { for col in (0..width).step_by(2) { out.pixels_mut().swap(row * width + col + 1, (row + 1) * width + col); } } out } pub fn decode_srw2(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { let mut out = alloc_image!(width, height, dummy); // This format has a variable length encoding of how many bits are needed // to encode the difference between pixels, we use a table to process it // that has two values, the first the number of bits that were used to // encode, the second the number of bits that come after with the difference // The table has 14 entries because the difference can have between 0 (no // difference) and 13 bits (differences between 12 bits numbers can need 13) let tab: [[u32; 2]; 14] = [ [3, 4], [3, 7], [2, 6], [2, 5], [4, 3], [6, 0], [7, 9], [8, 10], [9, 11], [10, 12], [10, 13], [5, 1], [4, 8], [4, 2], ]; // We generate a 1024 entry table (to be addressed by reading 10 bits) by // consecutively filling in 2^(10-N) positions where N is the variable number of // bits of the encoding. So for example 4 is encoded with 3 bits so the first // 2^(10-3)=128 positions are set with 3,4 so that any time we read 000 we // know the next 4 bits are the difference. We read 10 bits because that is // the maximum number of bits used in the variable encoding (for the 12 and // 13 cases) let mut tbl: [[u32; 2]; 1024] = [[0, 0]; 1024]; let mut n: usize = 0; for i in 0..14 { let mut c = 0; while c < (1024 >> tab[i][0]) { tbl[n][0] = tab[i][0]; tbl[n][1] = tab[i][1]; n += 1; c += 1; } } let mut vpred: [[i32; 2]; 2] = [[0, 0], [0, 0]]; let mut hpred: [i32; 2] = [0, 0]; let mut pump = BitPumpMSB::new(buf); for row in 0..height { for col in 0..width { let diff = SrwDecoder::srw2_diff(&mut pump, &tbl); if col < 2 { vpred[row & 1][col] += diff; hpred[col] = vpred[row & 1][col]; } else { hpred[col & 1] += diff; } out[row * width + col] = hpred[col & 1] as u16; } } out } pub fn srw2_diff(pump: &mut BitPumpMSB, tbl: &[[u32; 2]; 1024]) -> i32 { // We read 10 bits to index into our table let c = pump.peek_bits(10); // Skip the bits that were used to encode this case pump.consume_bits(tbl[c as usize][0]); // Read the number of bits the table tells me let len = tbl[c as usize][1]; let mut diff = pump.get_bits(len) as i32; // If the first bit is 0 we need to turn this into a negative number if len != 0 && (diff & (1 << (len - 1))) == 0 { diff -= (1 << len) - 1; } diff } pub fn decode_srw3(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { // Decoder for third generation compressed SRW files (NX1) // Seriously Samsung just use lossless jpeg already, it compresses better too :) // Thanks to Michael Reichmann (Luminous Landscape) for putting me in contact // and Loring von Palleske (Samsung) for pointing to the open-source code of // Samsung's DNG converter at http://opensource.samsung.com/ let mut out = alloc_image!(width, height, dummy); let mut pump = BitPumpMSB32::new(buf); // Process the initial metadata bits, we only really use initVal, width and // height (the last two match the TIFF values anyway) pump.get_bits(16); // NLCVersion pump.get_bits(4); // ImgFormat let bit_depth = pump.get_bits(4) + 1; pump.get_bits(4); // NumBlkInRCUnit pump.get_bits(4); // CompressionRatio pump.get_bits(16); // Width; pump.get_bits(16); // Height; pump.get_bits(16); // TileWidth pump.get_bits(4); // reserved // The format includes an optimization code that sets 3 flags to change the // decoding parameters let optflags = pump.get_bits(4); static OPT_SKIP: u32 = 1; // Skip checking if we need differences from previous line static OPT_MV: u32 = 2; // Simplify motion vector definition static OPT_QP: u32 = 4; // Don't scale the diff values pump.get_bits(8); // OverlapWidth pump.get_bits(8); // reserved pump.get_bits(8); // Inc pump.get_bits(2); // reserved let init_val = pump.get_bits(14) as u16; // The format is relatively straightforward. Each line gets encoded as a set // of differences from pixels from another line. Pixels are grouped in blocks // of 16 (8 green, 8 red or blue). Each block is encoded in three sections. // First 1 or 4 bits to specify which reference pixels to use, then a section // that specifies for each pixel the number of bits in the difference, then // the actual difference bits let mut line_offset = 0; for row in 0..height { line_offset += pump.get_pos(); // Align pump to 16byte boundary if (line_offset & 0x0f) != 0 { line_offset += 16 - (line_offset & 0xf); } pump = BitPumpMSB32::new(&buf[line_offset..]); let img = width * row; let img_up = width * (cmp::max(1, row) - 1); let img_up2 = width * (cmp::max(2, row) - 2); // Initialize the motion and diff modes at the start of the line let mut motion: usize = 7; // By default we are not scaling values at all let mut scale: i32 = 0; let mut diff_bits_mode: [[u32; 2]; 3] = [[0; 2]; 3]; for i in 0..3 { let init: u32 = if row < 2 { 7 } else { 4 }; diff_bits_mode[i][0] = init; diff_bits_mode[i][1] = init; } for col in (0..width).step_by(16) { // Calculate how much scaling the final values will need scale = if (optflags & OPT_QP) == 0 && (col & 63) == 0 { let scalevals: [i32; 3] = [0, -2, 2]; let i = pump.get_bits(2) as usize; if i < 3 { scale + scalevals[i] } else { pump.get_bits(12) as i32 } } else { scale // Keep value from previous iteration }; // First we figure out which reference pixels mode we're in if (optflags & OPT_MV) != 0 { motion = if pump.get_bits(1) != 0 { 3 } else { 7 }; } else if pump.get_bits(1) == 0 { motion = pump.get_bits(3) as usize; } if row < 2 && motion != 7 { panic!("SRW Decoder: At start of image and motion isn't 7. File corrupted?") } if motion == 7 { // The base case, just set all pixels to the previous ones on the same line // If we're at the left edge we just start at the initial value for i in 0..16 { out[img + col + i] = if col == 0 { init_val } else { out[img + col + i - 2] }; } } else { // The complex case, we now need to actually lookup one or two lines above if row < 2 { panic!("SRW: Got a previous line lookup on first two lines. File corrupted?"); } let motion_offset: [isize; 7] = [-4, -2, -2, 0, 0, 2, 4]; let motion_average: [i32; 7] = [0, 0, 1, 0, 1, 0, 0]; let slide_offset = motion_offset[motion]; for i in 0..16 { let refpixel: usize = if ((row + i) & 0x1) != 0 { // Red or blue pixels use same color two lines up ((img_up2 + col + i) as isize + slide_offset) as usize } else { // Green pixel N uses Green pixel N from row above (top left or top right) if (i % 2) != 0 { ((img_up + col + i - 1) as isize + slide_offset) as usize } else { ((img_up + col + i + 1) as isize + slide_offset) as usize } }; // In some cases we use as reference interpolation of this pixel and the next out[img + col + i] = if motion_average[motion] != 0 { (out[refpixel] + out[refpixel + 2] + 1) >> 1 } else { out[refpixel] } } } // Figure out how many difference bits we have to read for each pixel let mut diff_bits: [u32; 4] = [0; 4]; if (optflags & OPT_SKIP) != 0 || pump.get_bits(1) == 0 { let flags: [u32; 4] = [pump.get_bits(2), pump.get_bits(2), pump.get_bits(2), pump.get_bits(2)]; for i in 0..4 { // The color is 0-Green 1-Blue 2-Red let colornum: usize = if row % 2 != 0 { i >> 1 } else { ((i >> 1) + 2) % 3 }; match flags[i] { 0 => { diff_bits[i] = diff_bits_mode[colornum][0]; } 1 => { diff_bits[i] = diff_bits_mode[colornum][0] + 1; } 2 => { diff_bits[i] = diff_bits_mode[colornum][0] - 1; } 3 => { diff_bits[i] = pump.get_bits(4); } _ => {} } diff_bits_mode[colornum][0] = diff_bits_mode[colornum][1]; diff_bits_mode[colornum][1] = diff_bits[i]; if diff_bits[i] > bit_depth + 1 { panic!("SRW Decoder: Too many difference bits. File corrupted?"); } } } // Actually read the differences and write them to the pixels for i in 0..16 { let len = diff_bits[i >> 2]; let mut diff = pump.get_ibits_sextended(len); diff = diff * (scale * 2 + 1) + scale; // Apply the diff to pixels 0 2 4 6 8 10 12 14 1 3 5 7 9 11 13 15 let pos = if row % 2 != 0 { ((i & 0x7) << 1) + 1 - (i >> 3) } else { ((i & 0x7) << 1) + (i >> 3) } + img + col; out[pos] = clampbits((out[pos] as i32) + diff, bit_depth); } } } out } /// Get lens description by analyzing TIFF tags and makernotes fn get_lens_description(&self) -> Result> { if let Some(lens_id) = self.makernote.get_entry(SrwMakernote::LensModel) { let lens_id = lens_id.force_u16(0); let resolver = LensResolver::new() .with_lens_id((lens_id.into(), 0)) .with_camera(&self.camera) .with_mounts(&[NX_MOUNT.into()]); return Ok(resolver.resolve()); } Ok(None) } fn get_wb(&self) -> Result<[f32; 4]> { let rggb_levels = fetch_tiff_tag!(self.makernote, SrwMakernote::SrwRGGBLevels); let rggb_blacks = fetch_tiff_tag!(self.makernote, SrwMakernote::SrwRGGBBlacks); if rggb_levels.count() != 4 || rggb_blacks.count() != 4 { Err(RawlerError::DecoderFailed("SRW: RGGB Levels and Blacks don't have 4 elements".to_string())) } else { Ok([ (rggb_levels.force_u32(0) as f32 - rggb_blacks.force_u32(0) as f32) / 4096.0, (rggb_levels.force_u32(1) as f32 - rggb_blacks.force_u32(1) as f32) / 4096.0, (rggb_levels.force_u32(3) as f32 - rggb_blacks.force_u32(3) as f32) / 4096.0, f32::NAN, ]) } } /// Extract blacklevel /// Ironically, the data is already black level subtracted, but the /// WB coeffs are not. So we can return 0 here. The black level /// is subtracted in the get_wb() function. fn get_blacklevel(&self) -> Result<[u32; 4]> { Ok([0, 0, 0, 0]) /* let rggb_blacks = fetch_tiff_tag!(self.makernote, SrwMakernote::SrwRGGBBlacks); if rggb_blacks.count() != 4 { Err(RawlerError::General("SRW: RGGB Blacks don't have 4 elements".to_string())) } else { Ok([ rggb_blacks.force_u16(0), rggb_blacks.force_u16(1), rggb_blacks.force_u16(2), rggb_blacks.force_u16(3), ]) } */ } } crate::tags::tiff_tag_enum!(SrwMakernote); #[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum SrwMakernote { LensModel = 0xA003, SrwRGGBLevels = 0xA021, SrwRGGBBlacks = 0xA028, } rawler-0.7.1/src/decoders/tfr.rs000064400000000000000000000152121046102023000146460ustar 00000000000000use image::{DynamicImage, ImageBuffer, Rgb}; use log::debug; use serde::{Deserialize, Serialize}; use crate::analyze::FormatDump; use crate::decompressors::ljpeg::*; use crate::exif::Exif; use crate::formats::tiff::reader::TiffReader; use crate::formats::tiff::{Entry, GenericTiffReader, Rational, Value}; use crate::imgop::{Dim2, Rect}; use crate::lens::{LensDescription, LensResolver}; use crate::packed::decode_16le; use crate::pixarray::PixU16; use crate::rawsource::RawSource; use crate::tags::{DngTag, ExifTag, TiffCommonTag}; use crate::{RawImage, RawLoader, alloc_image_ok}; use crate::{RawlerError, Result}; use super::{BlackLevel, CFAConfig, Camera, Decoder, FormatHint, RawDecodeParams, RawMetadata, RawPhotometricInterpretation, WhiteLevel}; /// 3FR format encapsulation for analyzer #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TfrFormat { tiff: GenericTiffReader, } #[derive(Debug, Clone)] pub struct TfrDecoder<'a> { camera: Camera, #[allow(unused)] rawloader: &'a RawLoader, tiff: GenericTiffReader, } impl<'a> TfrDecoder<'a> { pub fn new(_file: &RawSource, tiff: GenericTiffReader, rawloader: &'a RawLoader) -> Result> { debug!("3FR decoder choosen"); let camera = rawloader.check_supported(tiff.root_ifd())?; //let makernotes = new_makernote(file, 8).map_err(|ioerr| RawlerError::with_io_error("load 3FR makernotes", file.path(), ioerr))?; Ok(TfrDecoder { camera, tiff, rawloader, // makernotes, }) } } impl<'a> Decoder for TfrDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let raw = self .tiff .find_first_ifd_with_tag(TiffCommonTag::WhiteLevel) .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a IFD with WhilteLevel tag")))?; let whitelevel = raw .get_entry(TiffCommonTag::WhiteLevel) .map(|tag| WhiteLevel::new(vec![tag.force_u16(0) as u32])); let blacklevel = raw .get_entry(TiffCommonTag::BlackLevels) .map(|tag| BlackLevel::new(&[tag.force_u16(0)], 1, 1, 1)); let width = fetch_tiff_tag!(raw, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(raw, TiffCommonTag::ImageLength).force_usize(0); let offset = fetch_tiff_tag!(raw, TiffCommonTag::StripOffsets).force_usize(0); let src = file.subview_until_eof(offset as u64)?; let image = if self.camera.find_hint("uncompressed") { decode_16le(src, width, height, dummy) } else { self.decode_compressed(src, width, height, dummy)? }; let crop = Rect::from_tiff(raw).or_else(|| self.camera.crop_area.map(|area| Rect::new_with_borders(Dim2::new(width, height), &area))); //crate::devtools::dump_image_u16(&image.data, width, height, "/tmp/tfrdump.pnm"); let cpp = 1; let photometric = RawPhotometricInterpretation::Cfa(CFAConfig::new_from_camera(&self.camera)); let mut img = RawImage::new(self.camera.clone(), image, cpp, self.get_wb()?, photometric, blacklevel, whitelevel, dummy); img.crop_area = crop; Ok(img) } fn full_image(&self, file: &RawSource, params: &RawDecodeParams) -> Result> { if params.image_index != 0 { return Ok(None); } let root_ifd = &self.tiff.root_ifd(); let buf = root_ifd .singlestrip_data_rawsource(file) .map_err(|e| RawlerError::DecoderFailed(format!("Failed to get strip data: {}", e)))?; let compression = root_ifd.get_entry(TiffCommonTag::Compression).ok_or("Missing tag")?.force_usize(0); let width = fetch_tiff_tag!(root_ifd, TiffCommonTag::ImageWidth).force_usize(0); let height = fetch_tiff_tag!(root_ifd, TiffCommonTag::ImageLength).force_usize(0); if compression == 1 { Ok(Some(DynamicImage::ImageRgb8( ImageBuffer::, Vec>::from_raw(width as u32, height as u32, buf.to_vec()).unwrap(), ))) } else { let img = image::load_from_memory_with_format(buf, image::ImageFormat::Jpeg) .map_err(|err| RawlerError::DecoderFailed(format!("Failed to read JPEG: {:?}", err)))?; Ok(Some(img)) } } fn format_dump(&self) -> FormatDump { FormatDump::Tfr(TfrFormat { tiff: self.tiff.clone() }) } fn format_hint(&self) -> FormatHint { FormatHint::TFR } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { let exif = Exif::new(self.tiff.root_ifd())?; let mut mdata = RawMetadata::new_with_lens(&self.camera, exif, self.get_lens_description()?.cloned()); // Read Unique ID if let Some(Entry { value: Value::Byte(unique_id), .. }) = self.tiff.root_ifd().get_entry(DngTag::RawDataUniqueID) { if let Ok(id) = unique_id.as_slice().try_into() { mdata.unique_image_id = Some(u128::from_le_bytes(id)); } } Ok(mdata) } fn xpacket(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result>> { match self.tiff.root_ifd().get_entry(TiffCommonTag::Xmp) { Some(Entry { value: Value::Byte(buf), .. }) => Ok(Some(buf.clone())), _ => Ok(None), } } } impl<'a> TfrDecoder<'a> { /// Get lens description by analyzing TIFF tags and makernotes fn get_lens_description(&self) -> Result> { if let Some(exif) = self.tiff.root_ifd().get_sub_ifd(TiffCommonTag::ExifIFDPointer) { let lens_make = exif.get_entry(ExifTag::LensMake).and_then(|entry| entry.as_string()); let lens_model = exif.get_entry(ExifTag::LensModel).and_then(|entry| entry.as_string()); let focal_len = match exif.get_entry(ExifTag::FocalLength) { Some(Entry { value: Value::Rational(x), .. }) => x.get(0).cloned(), Some(Entry { value: Value::Short(x), .. }) => x.get(0).copied().map(Rational::from), _ => None, }; let resolver = LensResolver::new() .with_camera(&self.camera) .with_lens_make(lens_make) .with_lens_model(lens_model) .with_focal_len(focal_len) .with_mounts(&["x-mount".into()]); return Ok(resolver.resolve()); } Ok(None) } fn get_wb(&self) -> Result<[f32; 4]> { let levels = fetch_tiff_tag!(self.tiff, TiffCommonTag::AsShotNeutral); assert_eq!(levels.count(), 3); Ok([1.0 / levels.force_f32(0), 1.0 / levels.force_f32(1), 1.0 / levels.force_f32(2), f32::NAN]) } fn decode_compressed(&self, src: &[u8], width: usize, height: usize, dummy: bool) -> Result { let mut out = alloc_image_ok!(width, height, dummy); let decompressor = LjpegDecompressor::new_full(src, true, false)?; decompressor.decode(out.pixels_mut(), 0, width, width, height, dummy)?; Ok(out) } } rawler-0.7.1/src/decoders/unwrapped.rs000064400000000000000000000202751046102023000160650ustar 00000000000000use crate::bits::Endian; use crate::bits::*; use crate::buffer::PaddedBuf; use crate::decoders::*; use crate::decompressors::ljpeg::LjpegDecompressor; use crate::packed::*; pub fn decode_unwrapped(file: &RawSource) -> Result { let buffer = file.subview_until_eof_padded(0)?; let decoder = LEu16(&buffer, 0); let width = LEu16(&buffer, 2) as usize; let height = LEu16(&buffer, 4) as usize; let data = &buffer[6..]; if width > 64 || height > 64 { panic!("Trying an image larger than 64x64"); } match decoder { 0 => { let table = { let mut t: [u16; 256] = [0; 256]; for i in 0..256 { t[i] = LEu16(data, i * 2); } LookupTable::new(&t) }; let data = &data[512..]; Ok(RawImageData::Integer(decode_8bit_wtable(data, &table, width, height, false).into_inner())) } 1 => Ok(RawImageData::Integer(decode_10le_lsb16(data, width, height, false).into_inner())), 2 => Ok(RawImageData::Integer(decode_10be(data, width, height, false).into_inner())), 3 => Ok(RawImageData::Integer(decode_12be(data, width, height, false).into_inner())), 4 => Ok(RawImageData::Integer(decode_12be_msb16(data, width, height, false).into_inner())), 5 => Ok(RawImageData::Integer(decode_12le_16bitaligned(data, width, height, false).into_inner())), 6 => Ok(RawImageData::Integer(decode_12be_msb32(data, width, height, false).into_inner())), 7 => Ok(RawImageData::Integer(decode_12le_wcontrol(data, width, height, false).into_inner())), 8 => Ok(RawImageData::Integer(decode_12be_wcontrol(data, width, height, false).into_inner())), 9 => Ok(RawImageData::Integer(decode_12be_interlaced(data, width, height, false).into_inner())), 10 => Ok(RawImageData::Integer(decode_12be_interlaced_unaligned(data, width, height, false).into_inner())), 11 => Ok(RawImageData::Integer(decode_12le(data, width, height, false).into_inner())), 12 => Ok(RawImageData::Integer(decode_12le_unpacked(data, width, height, false).into_inner())), 13 => Ok(RawImageData::Integer(decode_12be_unpacked(data, width, height, false).into_inner())), 14 => Ok(RawImageData::Integer( decode_12be_unpacked_left_aligned(data, width, height, false).into_inner(), )), 15 => Ok(RawImageData::Integer( decode_12le_unpacked_left_aligned(data, width, height, false).into_inner(), )), 16 => Ok(RawImageData::Integer(decode_14le_unpacked(data, width, height, false).into_inner())), 17 => Ok(RawImageData::Integer(decode_14be_unpacked(data, width, height, false).into_inner())), 18 => Ok(RawImageData::Integer(decode_16le(data, width, height, false).into_inner())), 19 => Ok(RawImageData::Integer(decode_16le_skiplines(data, width, height, false).into_inner())), 20 => Ok(RawImageData::Integer(decode_16be(data, width, height, false).into_inner())), 21 => Ok(RawImageData::Integer(arw::ArwDecoder::decode_arw1(data, width, height, false).into_inner())), 22 => { let mut curve: [usize; 6] = [0, 0, 0, 0, 0, 4095]; for i in 0..4 { curve[i + 1] = (LEu16(data, i * 2) & 0xfff) as usize; } let curve = arw::ArwDecoder::calculate_curve(curve); let data = &data[8..]; Ok(RawImageData::Integer( arw::ArwDecoder::decode_arw2(data, width, height, &curve, false).into_inner(), )) } 23 => { let key = LEu32(data, 0); let length = LEu16(data, 4) as usize; let data = &data[10..]; if length > 5000 { panic!("Trying an SRF style image that's too big"); } let image_data = arw::ArwDecoder::sony_decrypt(data, 0, length, key)?; Ok(RawImageData::Integer(decode_16be(&image_data, width, height, false).into_inner())) } 24 => Ok(RawImageData::Integer( orf::OrfDecoder::decode_compressed(&buffer, width, height, 12, false).into_inner(), )), 25 => { let loffsets = data; let data = &data[height * 4..]; Ok(RawImageData::Integer( srw::SrwDecoder::decode_srw1(data, loffsets, width, height, false).into_inner(), )) } 26 => Ok(RawImageData::Integer(srw::SrwDecoder::decode_srw2(data, width, height, false).into_inner())), 27 => Ok(RawImageData::Integer(srw::SrwDecoder::decode_srw3(data, width, height, false).into_inner())), 28 => Ok(RawImageData::Integer(kdc::KdcDecoder::decode_dc120(data, width, height, false).into_inner())), 29 => Ok(RawImageData::Integer( rw2::v4decompressor::decode_panasonic_v4(data, width, height, false, false).into_inner(), )), 30 => Ok(RawImageData::Integer( rw2::v4decompressor::decode_panasonic_v4(data, width, height, true, false).into_inner(), )), 31 => { let table = { let mut t = [0u16; 1024]; for i in 0..1024 { t[i] = LEu16(data, i * 2); } LookupTable::new(&t) }; let data = &data[2048..]; Ok(RawImageData::Integer( dcr::DcrDecoder::decode_kodak65000(data, &table, width, height, false).into_inner(), )) } 32 => decode_ljpeg(data, width, height, false, false), 33 => decode_ljpeg(data, width, height, false, true), 34 => decode_ljpeg(data, width, height, true, false), 35 => decode_ljpeg(data, width, height, true, true), 36 => Ok(RawImageData::Integer( pef::PefDecoder::do_decode(data, None, width, height, false).unwrap().into_inner(), )), 37 => { let huff = data; let data = &data[64..]; Ok(RawImageData::Integer( pef::PefDecoder::do_decode(data, Some((huff, Endian::Little)), width, height, false) .unwrap() .into_inner(), )) } 38 => { let huff = data; let data = &data[64..]; Ok(RawImageData::Integer( pef::PefDecoder::do_decode(data, Some((huff, Endian::Big)), width, height, false) .unwrap() .into_inner(), )) } 39 => Ok(RawImageData::Integer( crw::CrwDecoder::do_decode(file, false, 0, width, height, false).unwrap().into_inner(), )), 40 => Ok(RawImageData::Integer( crw::CrwDecoder::do_decode(file, false, 1, width, height, false).unwrap().into_inner(), )), 41 => Ok(RawImageData::Integer( crw::CrwDecoder::do_decode(file, false, 2, width, height, false).unwrap().into_inner(), )), 42 => Ok(RawImageData::Integer( crw::CrwDecoder::do_decode(file, true, 0, width, height, false).unwrap().into_inner(), )), 43 => Ok(RawImageData::Integer( crw::CrwDecoder::do_decode(file, true, 1, width, height, false).unwrap().into_inner(), )), 44 => Ok(RawImageData::Integer( crw::CrwDecoder::do_decode(file, true, 2, width, height, false).unwrap().into_inner(), )), 45 => Ok(RawImageData::Integer( mos::MosDecoder::do_decode(data, false, width, height, false).unwrap().into_inner(), )), 46 => Ok(RawImageData::Integer( mos::MosDecoder::do_decode(data, true, width, height, false).unwrap().into_inner(), )), //47 => Ok(RawImageData::Integer(iiq::IiqDecoder::decode_compressed(data, height*4, 0, width, height, false).into_inner())), 48 => decode_nef(data, width, height, Endian::Little, 12), 49 => decode_nef(data, width, height, Endian::Little, 14), 50 => decode_nef(data, width, height, Endian::Big, 12), 51 => decode_nef(data, width, height, Endian::Big, 14), 52 => { let coeffs = [LEf32(data, 0), LEf32(data, 4), LEf32(data, 8), LEf32(data, 12)]; let data = PaddedBuf::new_owned(data[16..].to_vec(), data.len() - 16); Ok(RawImageData::Integer( nef::NefDecoder::decode_snef_compressed(&data, coeffs, width, height, false).into_inner(), )) } _ => Err("No such decoder".into()), } } fn decode_ljpeg(src: &[u8], width: usize, height: usize, dng_bug: bool, csfix: bool) -> Result { let mut out = vec![0u16; width * height]; let decompressor = LjpegDecompressor::new_full(src, dng_bug, csfix)?; decompressor.decode(&mut out, 0, width, width, height, false)?; Ok(RawImageData::Integer(out)) } fn decode_nef(data: &[u8], width: usize, height: usize, endian: Endian, bps: usize) -> Result { let meta = data; let data = &data[4096..]; Ok(RawImageData::Integer( nef::NefDecoder::do_decode(data, meta, endian, width, height, bps, false).unwrap().into_inner(), )) } rawler-0.7.1/src/decoders/x3f.rs000064400000000000000000000077531046102023000145660ustar 00000000000000use std::io::Cursor; use crate::bits::*; use crate::decoders::*; pub fn is_x3f(file: &RawSource) -> bool { match file.subview(0, 4) { Ok(buf) => buf[0..4] == b"FOVb"[..], Err(_) => false, } } #[derive(Debug, Clone)] struct X3fFile { #[allow(dead_code)] dirs: Vec, images: Vec, } #[derive(Debug, Clone)] struct X3fDirectory { offset: usize, #[allow(dead_code)] len: usize, id: String, } #[derive(Debug, Clone)] struct X3fImage { typ: usize, format: usize, width: usize, height: usize, #[allow(dead_code)] pitch: usize, doffset: usize, } impl X3fFile { fn new(file: &RawSource) -> Result { let buf = file.as_vec()?; let offset = LEu32(&buf, buf.len() - 4) as usize; let data = &buf[offset..]; let version = LEu32(data, 4); if version < 0x00020000 { return Err(format_args!("X3F: Directory version too old {}", version).into()); } let entries = LEu32(data, 8) as usize; let mut dirs = Vec::new(); let mut images = Vec::new(); for i in 0..entries { let dir = X3fDirectory::new(data, 12 + i * 12)?; if dir.id == "IMA2" { let img = X3fImage::new(&buf, dir.offset)?; images.push(img); } dirs.push(dir); } Ok(X3fFile { dirs, images }) } } impl X3fDirectory { fn new(buf: &[u8], offset: usize) -> Result { let data = &buf[offset..]; let off = LEu32(data, 0) as usize; let len = LEu32(data, 4) as usize; let name = String::from_utf8_lossy(&data[8..12]).to_string(); Ok(X3fDirectory { offset: off, len, id: name }) } } impl X3fImage { fn new(buf: &[u8], offset: usize) -> Result { let data = &buf[offset..]; Ok(X3fImage { typ: LEu32(data, 8) as usize, format: LEu32(data, 12) as usize, width: LEu32(data, 16) as usize, height: LEu32(data, 20) as usize, pitch: LEu32(data, 24) as usize, doffset: offset + 28, }) } } #[derive(Debug, Clone)] pub struct X3fDecoder<'a> { rawloader: &'a RawLoader, dir: X3fFile, } impl<'a> X3fDecoder<'a> { pub fn new(file: &RawSource, rawloader: &'a RawLoader) -> Result> { let dir = X3fFile::new(file)?; Ok(X3fDecoder { rawloader, dir }) } } impl<'a> Decoder for X3fDecoder<'a> { fn raw_image(&self, file: &RawSource, _params: &RawDecodeParams, dummy: bool) -> Result { let buffer = file.as_vec()?; let caminfo = self .dir .images .iter() .find(|i| i.typ == 2 && i.format == 0x12) .ok_or("X3F: Couldn't find camera info")?; let data = &buffer[caminfo.doffset + 6..]; if data[0..4] != b"Exif"[..] { return Err("X3F: Couldn't find EXIF info".into()); } let tiff = IFD::new(&mut Cursor::new(&buffer), (caminfo.doffset + 12) as u32, 0, 0, Endian::Little, &[]).unwrap(); let camera = self.rawloader.check_supported(&tiff)?; let imginfo = self.dir.images.iter().find(|i| i.typ == 1 || i.typ == 3).ok_or("X3F: Couldn't find image")?; let width = imginfo.width; let height = imginfo.height; let offset = imginfo.doffset; let src = &buffer[offset..]; let image = match imginfo.format { 35 => self.decode_compressed(src, width, height, dummy)?, x => return Err(format_args!("X3F Don't know how to decode format {}", x).into()), }; let cpp = 3; let photometric = RawPhotometricInterpretation::LinearRaw; Ok(RawImage::new(camera, image, cpp, self.get_wb()?, photometric, None, None, dummy)) } fn format_dump(&self) -> FormatDump { todo!() } fn format_hint(&self) -> FormatHint { FormatHint::X3F } fn raw_metadata(&self, _file: &RawSource, _params: &RawDecodeParams) -> Result { todo!() } } impl<'a> X3fDecoder<'a> { fn get_wb(&self) -> Result<[f32; 4]> { Ok([f32::NAN, f32::NAN, f32::NAN, f32::NAN]) } fn decode_compressed(&self, _buf: &[u8], _width: usize, _height: usize, _dummy: bool) -> Result { Err("X3F decoding not implemented yet".into()) } } rawler-0.7.1/src/decompressors/crx/decoder.rs000064400000000000000000000712311046102023000173570ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher // Original Crx decoder crx.cpp was written by Alexey Danilchenko for libraw. // Rewritten in Rust by Daniel Vogelbacher, based on logic found in // crx.cpp and documentation done by Laurent Clévy (https://github.com/lclevy/canon_cr3). use super::{ BandParam, CodecParams, CrxError, Result, mdat::{Plane, Tile}, }; use crate::decompressors::crx::{idwt::WaveletTransform, mdat::parse_header, rice::RiceDecoder}; use bitstream_io::BitReader; use itertools::izip; use log::debug; use rayon::prelude::*; use std::{convert::TryInto, io::Cursor, time::Instant}; /// Maximum value for K during Adaptive Golomb-Rice for K prediction pub(super) const PREDICT_K_MAX: u32 = 15; pub(super) const PREDICT_K_ESCAPE: u32 = 41; pub(super) const PREDICT_K_ESCBITS: u32 = 21; struct PlaneLineIter<'a> { tile: &'a Tile, plane: &'a Plane, codec: CodecParams, params: Vec>, iwt_transforms: Vec, //plane_buf: Vec, next_row: usize, } impl<'a> PlaneLineIter<'a> { /// Create a new PlaneLine iterator for decoding fn new(codec: CodecParams, tile: &'a Tile, plane: &'a Plane, mdat: &'a [u8]) -> Result { // Some checks for correct input assert!(tile.plane_height > 0); assert!(tile.plane_width > 0); // Reference to data section in MDAT // All calculated offsets are relative to the data section. let data = codec.get_data(mdat); let plane_mdat_offset = tile.data_offset + tile.qp_data.as_ref().map(|qp| qp.mdat_qp_data_size + qp.mdat_extra_size as u32).unwrap_or(0) as usize + plane.data_offset; let mut params = Vec::with_capacity(plane.subbands.len()); for (band_id, band) in plane.subbands.iter().enumerate() { let band_mdat_offset = plane_mdat_offset + band.data_offset; debug!("Band {} has MDAT offset: {}", band_id, band_mdat_offset); let band_buf = &data[band_mdat_offset..band_mdat_offset + band.data_size]; // Line length is subband + one additional pixel at start and end let line_len = 1 + band.width + 1; let bitpump = BitReader::endian(Cursor::new(band_buf), bitstream_io::BigEndian); let param = BandParam { subband_width: band.width, subband_height: band.height, rounded_bits_mask: if plane.support_partial && band_id == 0 { plane.rounded_bits_mask } else { 0 }, rounded_bits: 0, cur_line: 0, line_buf: [vec![0; line_len], vec![0; line_len]], line_k: vec![0; line_len], line_pos: 0, line_len, s_param: 0, q_param: band.q_param, supports_partial: plane.support_partial && band_id == 0, rice: RiceDecoder::new(bitpump), }; params.push(param); } let mut iwt_transforms = Vec::with_capacity(codec.levels); if codec.levels > 0 { // create Wavelet transforms for level in 0..codec.levels { let band = 3 * level + 1; let (height, width) = if level >= codec.levels - 1 { (tile.plane_height, tile.plane_width) } else { (plane.subbands[band + 3].height, plane.subbands[band + 4].width) }; iwt_transforms.push(WaveletTransform::new(height, width)); } codec.idwt_53_filter_init(tile, plane, &mut params, &mut iwt_transforms, codec.levels)?; } Ok(Self { params, tile, plane, codec, iwt_transforms, next_row: 0, }) } /// Decode a single line from plane fn decode_plane_line(&mut self) -> Result<&[i32]> { if self.next_row < self.tile.plane_height { self.next_row += 1; if self.codec.levels > 0 { self .codec .idwt_53_filter_decode(self.tile, self.plane, &mut self.params, &mut self.iwt_transforms, self.codec.levels - 1)?; self .codec .idwt_53_filter_transform(self.tile, self.plane, &mut self.params, &mut self.iwt_transforms, self.codec.levels - 1)?; let line_data = self.iwt_transforms[self.codec.levels - 1].getline(); debug_assert_eq!(line_data.len(), self.tile.plane_width); Ok(line_data) } else { debug_assert_eq!(self.plane.subbands.len(), 1); let param = &mut self.params[0]; self.codec.decode_line(param)?; let line_data = param.decoded_buf(); debug_assert_eq!(line_data.len(), param.subband_width as usize); debug_assert_eq!(line_data.len(), self.tile.plane_width); Ok(line_data) } } else { Err(CrxError::General("All rows processed, can't decode more".to_string())) } } } /// Iterator over a plane, returning on each call a new decoded line impl<'a> Iterator for PlaneLineIter<'a> { type Item = Result; fn next(&mut self) -> Option { if self.next_row < self.tile.plane_height { match self.decode_plane_line() { Ok(line) => Some(Ok(line.into())), Err(e) => Some(Err(e)), } } else { None } } fn size_hint(&self) -> (usize, Option) { (0, Some(self.tile.plane_height)) } } /// A plane line is a vector if i32 values type PlaneLine = Vec; /// Wrapper for PlaneLineIter /// Decodes a complete plane and returns it as vector of lines fn decode_full_plane(codec: &CodecParams, tile: &Tile, plane: &Plane, mdat: &[u8]) -> Result> { //eprintln!("Process tile {}, plane: {}", tile.id, plane.id); let line_decoder = PlaneLineIter::new(*codec, tile, plane, mdat)?; line_decoder.collect() } impl CodecParams { /// Decode MDAT section into a single CFA image /// /// Decoding processes all planes in all tiles and assembles the /// decoded planes into proper tile output position and CFA pattern. pub fn decode(mut self, mdat: &[u8]) -> Result> { let instant = Instant::now(); debug!("Tile configuration: rows: {}, columns: {}", self.tile_rows, self.tile_cols); // Build nested Tiles/Planes/Bands let mut tiles = parse_header(self.get_header(mdat))?; self.process_tiles(&mut tiles); for tile in tiles.iter_mut() { tile.generate_qstep_table(&self, self.get_data(mdat))?; } // cfa output is of final resolution let mut cfa: Vec = vec![0; self.resolution()]; // Combine all tiles and planes into parallel iterators // and decode the full planes. let plane_bufs: Result>>> = tiles .par_iter() .map(|tile| tile.planes.par_iter().map(move |plane| decode_full_plane(&self, tile, plane, mdat)).collect()) .collect(); // Now we have a list of tiles->planes->plane-lines // and can combine them to the final CFA match plane_bufs { Ok(bufs) => { for (tile_id, tile) in bufs.into_iter().enumerate() { let plane_count = tile.len(); debug_assert_eq!(plane_count, 4); // Convert vector of planes to excact count of 4 planes - or fail let planes: [Vec; 4] = tile .try_into() .map_err(|_| CrxError::General(format!("Invalid plane count {} (expected 4) for tile {}", plane_count, tile_id)))?; // References to all 4 plane buffers let (p0, p1, p2, p3) = (&planes[0], &planes[1], &planes[2], &planes[3]); // Process each PlaneLine in all 4 buffers for (plane_row, (l0, l1, l2, l3)) in izip!(p0, p1, p2, p3).enumerate() { let (c0, c1, c2, c3) = convert_plane_line(&self, l0, l1, l2, l3)?; integrate_cfa(&self, &tiles, &mut cfa, tile_id, 0, plane_row, &c0)?; integrate_cfa(&self, &tiles, &mut cfa, tile_id, 1, plane_row, &c1)?; integrate_cfa(&self, &tiles, &mut cfa, tile_id, 2, plane_row, &c2)?; integrate_cfa(&self, &tiles, &mut cfa, tile_id, 3, plane_row, &c3)?; } } } Err(e) => { return Err(e); } } debug!("MDAT decoding and CFA build: {} s", instant.elapsed().as_secs_f32()); Ok(cfa) } /// Decode top line without a previous K buffer fn decode_top_line_no_ref_prev_line(&self, p: &mut BandParam) -> Result<()> { debug_assert_eq!(p.line_pos, 1); let mut remaining = p.subband_width as u32; // Init coef a and c (real image pixel starts at 1) p.line_buf[0][p.line_pos - 1] = 0; // is [0] because at start line_pos is 1 p.line_buf[1][p.line_pos - 1] = 0; // is [0] because at start line_pos is 1 while remaining > 1 { //println!("remaining: {}", remaining); // Loop over full width of line (backwards) if p.coeff_a() != 0 { //println!("coeff {} is != 0", p.coeff_a()); let bit_code = p.rice.adaptive_rice_decode(true, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, PREDICT_K_MAX)?; p.line_buf[1][p.line_pos] = error_code_signed(bit_code); } else { //println!("coeff {} = 0", p.coeff_a()); if p.rice.bitstream_get_bits(1)? == 1 { let n_syms = self.symbol_run_count(p, remaining)?; //println!("found {} syms", n_syms); remaining = remaining.saturating_sub(n_syms); // copy symbol n_syms times for _ in 0..n_syms { // For the first line, run-length coding uses only the symbol // value 0, so we can fill the line buffer and K buffer with 0. p.line_buf[1][p.line_pos] = 0; p.line_k[p.line_pos - 1] = 0; p.line_pos += 1; } if remaining == 0 { break; } } // if bitstream == 1 let bit_code = p.rice.adaptive_rice_decode(true, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, PREDICT_K_MAX)?; p.line_buf[1][p.line_pos] = error_code_signed(bit_code + 1); // Caution: + 1 //println!("code: {}", p.line_buf[1][p.line_pos]); } p.line_k[p.line_pos - 1] = p.rice.k(); p.line_pos += 1; remaining = remaining.saturating_sub(1); } // Remaining pixel? if remaining == 1 { let bit_code = p.rice.adaptive_rice_decode(true, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, PREDICT_K_MAX)?; p.line_buf[1][p.line_pos] = error_code_signed(bit_code); p.line_k[p.line_pos - 1] = p.rice.k(); p.line_pos += 1; } debug_assert!(p.line_pos < p.line_buf[1].len()); p.line_buf[1][p.line_pos] = 0; Ok(()) } /// Decode nontop line with a previous K buffer fn decode_nontop_line_no_ref_prev_line(&self, p: &mut BandParam) -> Result<()> { //println!("Decode nontop {}", p.cur_line); debug_assert_eq!(p.line_pos, 1); let mut remaining = p.subband_width as u32; while remaining > 1 { // Loop over full width of line (backwards) if (p.coeff_d() | p.coeff_b() | p.coeff_a()) != 0 { let bit_code = p.rice.adaptive_rice_decode(true, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, 0)?; p.line_buf[1][p.line_pos] = error_code_signed(bit_code); if p.line_k[p.line_pos].saturating_sub(p.rice.k()) <= 1 { if p.rice.k() >= 15 { p.rice.set_k(15); } } else { p.rice.set_k(p.rice.k() + 1); } } else { if p.rice.bitstream_get_bits(1)? == 1 { debug_assert!(remaining != 1); let n_syms = self.symbol_run_count(p, remaining)?; remaining = remaining.saturating_sub(n_syms); // copy symbol n_syms times for _ in 0..n_syms { // For the first line, run-length coding uses only the symbol // value 0, so we can fill the line buffer and K buffer with 0. p.line_buf[1][p.line_pos] = 0; p.line_k[p.line_pos - 1] = 0; p.line_pos += 1; } } // if bitstream == 1 if remaining <= 1 { if remaining == 1 { let bit_code = p.rice.adaptive_rice_decode(true, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, PREDICT_K_MAX)?; p.line_buf[1][p.line_pos] = error_code_signed(bit_code + 1); p.line_k[p.line_pos - 1] = p.rice.k(); p.line_pos += 1; remaining = remaining.saturating_sub(1); // skip remaining check at end of function } break; } else { let bit_code = p.rice.adaptive_rice_decode(true, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, 0)?; p.line_buf[1][p.line_pos] = error_code_signed(bit_code + 1); // Caution: + 1 if p.line_k[p.line_pos].saturating_sub(p.rice.k()) <= 1 { if p.rice.k() >= 15 { p.rice.set_k(15); } } else { p.rice.set_k(p.rice.k() + 1); } } } p.line_k[p.line_pos - 1] = p.rice.k(); p.line_pos += 1; remaining = remaining.saturating_sub(1); } // Remaining pixel? if remaining == 1 { let bit_code = p.rice.adaptive_rice_decode(true, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, PREDICT_K_MAX)?; p.line_buf[1][p.line_pos] = error_code_signed(bit_code); p.line_k[p.line_pos - 1] = p.rice.k(); p.line_pos += 1; } debug_assert!(p.line_pos < p.line_buf[1].len()); Ok(()) } /// Decode top line /// For the first line (top) in a plane, no MED is used because /// there is no previous line for coeffs b, c and d. /// So this decoding is a simplified version from decode_nontop_line(). fn decode_top_line(&self, p: &mut BandParam) -> Result<()> { debug_assert_eq!(p.line_pos, 1); let mut remaining = p.subband_width as u32; // Init coeff a (real image pixel starts at 1) p.line_buf[1][p.line_pos - 1] = 0; // is is [0] because at start line_pos is 1 while remaining > 1 { // Loop over full width of line (backwards) if p.coeff_a() != 0 { p.line_buf[1][p.line_pos] = p.coeff_a(); } else { if p.rice.bitstream_get_bits(1)? == 1 { let n_syms = self.symbol_run_count(p, remaining)?; remaining = remaining.saturating_sub(n_syms); // copy symbol n_syms times for _ in 0..n_syms { p.line_buf[1][p.line_pos] = p.coeff_a(); p.line_pos += 1; } if remaining == 0 { break; } } // if bitstream == 1 p.line_buf[1][p.line_pos] = 0; } let bit_code = p.rice.adaptive_rice_decode(true, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, PREDICT_K_MAX)?; p.line_buf[1][p.line_pos] += error_code_signed(bit_code); p.line_pos += 1; remaining = remaining.saturating_sub(1); } // Remaining pixel? if remaining == 1 { let x = p.coeff_a(); // no MED, just use coeff a let bit_code = p.rice.adaptive_rice_decode(true, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, PREDICT_K_MAX)?; p.line_buf[1][p.line_pos] = x + error_code_signed(bit_code); p.line_pos += 1; } debug_assert!(p.line_pos < p.line_buf[1].len()); p.line_buf[1][p.line_pos] = p.coeff_a() + 1; Ok(()) } /// Decode a line which is not a top line /// This used run length coding, Median Edge Detection (MED) and /// adaptive Golomb-Rice entropy encoding. /// Golomb-Rice becomes more efficient when using an adaptive K value /// instead of a fixed one. /// The K parameter is used as q = n >> k where n is the sample to encode. fn decode_nontop_line(&self, p: &mut BandParam) -> Result<()> { debug_assert_eq!(p.line_pos, 1); let mut remaining = p.subband_width as u32; // Init coeff a: a = b p.line_buf[1][p.line_pos - 1] = p.coeff_b(); // Loop over full width of line (backwards) while remaining > 1 { let mut x = 0; // c b d // a x n // Median Edge Detection to predict pixel x. Described in patent US2016/0323602 and T.87 if p.coeff_a() == p.coeff_b() && p.coeff_a() == p.coeff_d() { // different than step [0104], where Condition: "a=c and c=b and b=d", c not used if p.rice.bitstream_get_bits(1)? == 1 { let n_syms = self.symbol_run_count(p, remaining)?; remaining = remaining.saturating_sub(n_syms); // copy symbol n_syms times for _ in 0..n_syms { p.line_buf[1][p.line_pos] = p.coeff_a(); p.line_pos += 1; } } // if bitstream == 1 if remaining > 0 { x = p.coeff_b(); // use new coeff b because we moved line_pos! } } else { // no run length coding, use MED instead x = med(p.coeff_a(), p.coeff_b(), p.coeff_c()); } if remaining > 0 { let mut bit_code = p.rice.adaptive_rice_decode(false, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, PREDICT_K_MAX)?; // add converted (+/-) error code to predicted value p.line_buf[1][p.line_pos] = x + error_code_signed(bit_code); // for not end of the line - use one symbol ahead to estimate next K if remaining > 1 { let delta: i32 = (p.coeff_d() - p.coeff_b()) << 1; bit_code = (bit_code + delta.unsigned_abs()) >> 1; } p.rice.update_k_param(bit_code, PREDICT_K_MAX); p.line_pos += 1; } remaining = remaining.saturating_sub(1); } // end while length > 1 // Remaining pixel? if remaining == 1 { let x = med(p.coeff_a(), p.coeff_b(), p.coeff_c()); let bit_code = p.rice.adaptive_rice_decode(true, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, PREDICT_K_MAX)?; // add converted (+/-) error code to predicted value p.line_buf[1][p.line_pos] = x + error_code_signed(bit_code); p.line_pos += 1; } debug_assert!(p.line_pos < p.line_buf[1].len()); p.line_buf[1][p.line_pos] = p.coeff_a() + 1; Ok(()) } /// Decode a symbol x in rounded mode. /// Used only when levels==0 (lossless mode) fn decode_symbol_rounded(&self, p: &mut BandParam, use_med: bool, not_eol: bool) -> Result<()> { let sym = if use_med { med(p.coeff_a(), p.coeff_b(), p.coeff_c()) } else { p.coeff_b() }; let bit_code = p.rice.adaptive_rice_decode(false, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, PREDICT_K_MAX)?; let mut code = error_code_signed(bit_code); let x = p.rounded_bits_mask * 2 * code + (code >> 31); p.line_buf[1][p.line_pos] = x + sym; if not_eol { if p.coeff_d() > p.coeff_b() { code = (p.coeff_d() - p.coeff_b() + p.rounded_bits_mask - 1) >> p.rounded_bits; } else { code = -((p.coeff_b() - p.coeff_d() + p.rounded_bits_mask) >> p.rounded_bits); } p.rice.update_k_param((bit_code + 2 * code.unsigned_abs()) >> 1, PREDICT_K_MAX); } else { p.rice.update_k_param(bit_code, PREDICT_K_MAX); } p.line_pos += 1; Ok(()) } /// Decode a rounded line which is not a top line fn decode_top_line_rounded(&self, p: &mut BandParam) -> Result<()> { debug_assert_eq!(p.line_pos, 1); let mut remaining = p.subband_width as u32; // Init coeff a (real image pixel starts at 1) p.line_buf[1][p.line_pos - 1] = 0; // is is [0] because at start line_pos is 1 while remaining > 1 { // Loop over full width of line (backwards) if p.coeff_a().abs() > p.rounded_bits_mask { p.line_buf[1][p.line_pos] = p.coeff_a(); } else { if p.rice.bitstream_get_bits(1)? == 1 { let n_syms = self.symbol_run_count(p, remaining)?; remaining = remaining.saturating_sub(n_syms); // copy symbol n_syms times for _ in 0..n_syms { p.line_buf[1][p.line_pos] = p.coeff_a(); p.line_pos += 1; } if remaining == 0 { break; } } // if bitstream == 1 p.line_buf[1][p.line_pos] = 0; } let bit_code = p.rice.adaptive_rice_decode(true, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, PREDICT_K_MAX)?; let code = error_code_signed(bit_code); p.line_buf[1][p.line_pos] += p.rounded_bits_mask * 2 * code + (code >> 31); p.line_pos += 1; remaining = remaining.saturating_sub(1); } // Remaining pixel? if remaining == 1 { let bit_code = p.rice.adaptive_rice_decode(true, PREDICT_K_ESCAPE, PREDICT_K_ESCBITS, PREDICT_K_MAX)?; let code = error_code_signed(bit_code); p.line_buf[1][p.line_pos] += p.rounded_bits_mask * 2 * code + (code >> 31); p.line_pos += 1; } debug_assert!(p.line_pos < p.line_buf[1].len()); p.line_buf[1][p.line_pos] = p.coeff_a() + 1; Ok(()) } /// Decode a line which is not a top line /// This used run length coding, Median Edge Detection (MED) and /// adaptive Golomb-Rice entropy encoding. /// Golomb-Rice becomes more efficient when using an adaptive K value /// instead of a fixed one. /// The K parameter is used as q = n >> k where n is the sample to encode. #[allow(clippy::comparison_chain)] fn decode_nontop_line_rounded(&self, p: &mut BandParam) -> Result<()> { debug_assert_eq!(p.line_pos, 1); let mut remaining = p.subband_width as u32; let mut value_reached = false; p.line_buf[0][p.line_pos - 1] = p.coeff_b(); p.line_buf[1][p.line_pos - 1] = p.coeff_b(); // Loop over full width of line (backwards) while remaining > 1 { if (p.coeff_d() - p.coeff_b()).abs() > p.rounded_bits_mask { self.decode_symbol_rounded(p, true, true)?; value_reached = true; } else if value_reached || (p.coeff_c() - p.coeff_a()).abs() > p.rounded_bits_mask { self.decode_symbol_rounded(p, true, true)?; value_reached = false; } else { if p.rice.bitstream_get_bits(1)? == 1 { let n_syms = self.symbol_run_count(p, remaining)?; remaining = remaining.saturating_sub(n_syms); // copy symbol n_syms times for _ in 0..n_syms { p.line_buf[1][p.line_pos] = p.coeff_a(); p.line_pos += 1; } } // if bitstream == 1 if remaining > 1 { self.decode_symbol_rounded(p, false, true)?; value_reached = (p.coeff_b() - p.coeff_c()).abs() > p.rounded_bits_mask; } else if remaining == 1 { self.decode_symbol_rounded(p, false, false)?; } } remaining = remaining.saturating_sub(1); } // end while length > 1 // Remaining pixel? if remaining == 1 { self.decode_symbol_rounded(p, true, false)?; } debug_assert!(p.line_pos < p.line_buf[1].len()); p.line_buf[1][p.line_pos] = p.coeff_a() + 1; Ok(()) } /// Decode a single line from input band /// For decoding, two line buffers are required (except for the first line). /// After each decoding line, the two buffers are swapped, so the previous one /// is always in line_buf[0] (containing coefficents c, b, d) and the current /// line is in line_buf[1] (containing coefficents a, x, n). /// /// The line buffers has an extra sample on both ends. So the buffer layout is: /// /// |E|Samples........................|E| /// |c|bd cb|d| /// |a|xn ax|n| /// ^ ^ ^ /// | | |-- Extra sample to provide fake d coefficent /// | |---- First sample value /// |------ Extra sample to provide a fake a/c coefficent /// /// After line is decoded, the E samples are ignored when /// copied into the final plane buffer. /// /// For non-LL bands, decoding process differs a little bit /// because some value rounding is added. pub(super) fn decode_line(&self, param: &mut BandParam) -> Result<()> { debug_assert!(param.cur_line < param.subband_height); // We start at first real pixel value param.line_pos = 1; if param.cur_line == 0 { param.s_param = 0; param.rice.set_k(0); // TODO: required? if param.supports_partial { if param.rounded_bits_mask <= 0 { self.decode_top_line(param)?; } else { param.rounded_bits = 1; if (param.rounded_bits_mask & !1) != 0 { while param.rounded_bits_mask >> param.rounded_bits != 0 { param.rounded_bits += 1; } } self.decode_top_line_rounded(param)?; } } else { self.decode_top_line_no_ref_prev_line(param)?; } } else if !param.supports_partial { // Swap line buffers so previous decoded (1) is now above (0) param.line_buf.swap(0, 1); self.decode_nontop_line_no_ref_prev_line(param)?; } else if param.rounded_bits_mask <= 0 { // Swap line buffers so previous decoded (1) is now above (0) param.line_buf.swap(0, 1); self.decode_nontop_line(param)?; } else { // Swap line buffers so previous decoded (1) is now above (0) param.line_buf.swap(0, 1); self.decode_nontop_line_rounded(param)?; } param.cur_line += 1; Ok(()) } } /// Constrain a given value into min/max pub(super) fn constrain(value: i32, min: i32, max: i32) -> i32 { std::cmp::min(std::cmp::max(value, min), max) /* let res = if value < min { min } else if value > max { max } else { value }; debug_assert!(res <= u16::MAX as i32); res */ } /// The error code contains a sign bit at bit 0. /// Example: 10010 1 -> negative value, 10010 0 -> positive value /// This routine converts an unsigned bit_code to the correct /// signed integer value. /// For this, the sign bit is inverted and XOR with /// the shifted integer value. pub(super) fn error_code_signed(bit_code: u32) -> i32 { -((bit_code & 1) as i32) ^ (bit_code >> 1) as i32 } /// Median Edge Detection /// [0053] Obtains a predictive value p of the coefficient by using /// MED prediction, thereby performing predictive coding. pub(super) fn med(a: i32, b: i32, c: i32) -> i32 { if c >= std::cmp::max(a, b) { std::cmp::min(a, b) } else if c <= std::cmp::min(a, b) { std::cmp::max(a, b) } else { a + b - c // no edge detected } } /// Convert a decoded line to plane output /// Results from decode_line() are signed 32 bit integers. /// By using a median and max value, these are converted /// to unsigned 16 bit integers. #[allow(clippy::type_complexity)] fn convert_plane_line(codec: &CodecParams, l0: &[i32], l1: &[i32], l2: &[i32], l3: &[i32]) -> Result<(Vec, Vec, Vec, Vec)> { let mut p0 = vec![0; l0.len()]; let mut p1 = vec![0; l1.len()]; let mut p2 = vec![0; l2.len()]; let mut p3 = vec![0; l3.len()]; match codec.enc_type { 0 => { let median: i32 = 1 << (codec.median_bits - 1); let max_val: i32 = (1 << codec.median_bits) - 1; izip!(l0, l1, l2, l3).enumerate().for_each(|(i, (v0, v1, v2, v3))| { p0[i] = constrain(median + v0, 0, max_val) as u16; p1[i] = constrain(median + v1, 0, max_val) as u16; p2[i] = constrain(median + v2, 0, max_val) as u16; p3[i] = constrain(median + v3, 0, max_val) as u16; }); } 3 => { let median: i32 = 1 << (codec.median_bits - 1) << 10; let max_val: i32 = (1 << codec.median_bits) - 1; izip!(l0, l1, l2, l3).enumerate().for_each(|(i, (v0, v1, v2, v3))| { let mut gr: i32 = median + (v0 << 10) - 168 * v1 - 585 * v3; if gr < 0 { gr = -(((gr.abs() + 512) >> 9) & !1); } else { gr = ((gr.abs() + 512) >> 9) & !1; } p0[i] = constrain((median + (v0 << 10) + 1510 * v3 + 512) >> 10, 0, max_val) as u16; p1[i] = constrain((v2 + gr + 1) >> 1, 0, max_val) as u16; p2[i] = constrain((gr - v2 + 1) >> 1, 0, max_val) as u16; p3[i] = constrain((median + (v0 << 10) + 1927 * v1 + 512) >> 10, 0, max_val) as u16; }); } enc_type => { return Err(CrxError::General(format!("Unsupported encoding type {}", enc_type))); } } Ok((p0, p1, p2, p3)) } /// Integrate a plane buffer into CFA output image /// /// A plane is a single monochrome image for one of the four CFA colors. /// `plane_id` is 0, 1, 2 or 3 for R, G1, G2, B fn integrate_cfa(codec: &CodecParams, tiles: &[Tile], cfa_buf: &mut [u16], tile_id: usize, plane_id: usize, plane_row: usize, plane_buf: &[u16]) -> Result<()> { // 2x2 pixel for RGGB const CFA_DIM: usize = 2; debug_assert_ne!(plane_buf.len(), 0); debug_assert_ne!(cfa_buf.len(), 0); debug_assert!(codec.tile_cols > 0); debug_assert!(codec.tile_rows > 0); if plane_id > 3 { return Err(CrxError::Overflow(format!( "More then 4 planes detected, unable to process plane_id {}", plane_id ))); } let tile_row_idx = tile_id / codec.tile_cols; // round down let tile_col_idx = tile_id % codec.tile_cols; // round down // Offset from top let row_offset = tile_row_idx * codec.tile_width; // Offset from left let col_offset = tile_col_idx * codec.tile_width; let (row_shift, col_shift) = match plane_id { 0 => (0, 0), 1 => (0, 1), 2 => (1, 0), 3 => (1, 1), _ => { return Err(CrxError::General("Invalid plane id".to_string())); } }; //println!("plane_width: {}, buf_size: {}", tiles[tile_id].plane_width, plane_buf.len()); let row_idx = row_offset + (plane_row * CFA_DIM) + row_shift; for plane_col in 0..tiles[tile_id].plane_width { // Row index into CFA for untiled full area let col_idx = col_offset + (plane_col * CFA_DIM) + col_shift; // Copy from plane to CFA cfa_buf[(row_idx * codec.image_width) + col_idx] = plane_buf[plane_col]; } Ok(()) } rawler-0.7.1/src/decompressors/crx/idwt.rs000064400000000000000000000525371046102023000167310ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher // Original Crx decoder crx.cpp was written by Alexey Danilchenko for libraw. // Rewritten in Rust by Daniel Vogelbacher, based on logic found in // crx.cpp and documentation done by Laurent Clévy (https://github.com/lclevy/canon_cr3). use super::{ BandParam, CodecParams, Result, mdat::{Plane, Tile}, }; /// This structure holds the inverse transformation state /// Each level has it's own state, so for 3 levels of DWT /// 3 instances are required. #[derive(Debug, Clone)] pub(crate) struct WaveletTransform { /// Contains the decoded data from LL band /// or from a previous level decode. band0_buf: Vec, /// Contains the decoded data for HL band of current level band1_buf: Vec, /// Contains the decoded data for LH band of current level band2_buf: Vec, /// Contains the decoded data for HH band of current level band3_buf: Vec, /// 8 temporary buffers for inverse transformation (5/3?) band0_pos: usize, band1_pos: usize, band2_pos: usize, band3_pos: usize, line_buf: [Vec; 8], /// Current line position cur_line: usize, /// TODO ??? cur_h: usize, /// TODO ??? flt_tap_h: usize, /// Height of the final image for the current level height: usize, /// Width of the final image for the current level width: usize, } impl WaveletTransform { pub(crate) fn new(height: usize, width: usize) -> Self { // Line buffers for inverse transformation let line_buf = [ vec![0; width], vec![0; width], vec![0; width], vec![0; width], vec![0; width], vec![0; width], vec![0; width], vec![0; width], ]; Self { // We use empty vectors, they will be replaced // with the result of a line decode. band0_buf: Vec::new(), band1_buf: Vec::new(), band2_buf: Vec::new(), band3_buf: Vec::new(), band0_pos: 0, band1_pos: 0, band2_pos: 0, band3_pos: 0, line_buf, cur_line: 0, cur_h: 0, flt_tap_h: 0, height, width, } } pub(super) fn getline(&mut self) -> &Vec { let result = &self.line_buf[(self.flt_tap_h as i32 - self.cur_h as i32 + 5) as usize % 5 + 3]; debug_assert!(self.cur_h > 0); self.cur_h -= 1; result } pub(super) fn band0(&mut self, offset: usize) -> i32 { self.band0_buf[self.band0_pos + offset] } pub(super) fn band1(&mut self, offset: usize) -> i32 { self.band1_buf[self.band1_pos + offset] } pub(super) fn band2(&mut self, offset: usize) -> i32 { self.band2_buf[self.band2_pos + offset] } pub(super) fn band3(&mut self, offset: usize) -> i32 { self.band3_buf[self.band3_pos + offset] } pub(super) fn advance_bufs(&mut self, count: usize) { self.band0_pos += count; self.band1_pos += count; self.band2_pos += count; self.band3_pos += count; } pub(super) fn reset_bufs(&mut self) { self.band0_pos = 0; self.band1_pos = 0; self.band2_pos = 0; self.band3_pos = 0; } } impl CodecParams { pub(super) fn idwt_53_filter_decode( &self, tile: &Tile, plane: &Plane, params: &mut Vec, iwt_transforms: &mut Vec, level: usize, ) -> Result<()> { if iwt_transforms[level].cur_h > 0 { return Ok(()); } let cur_band = 3 * level; let q_step_level = tile.q_step.as_ref().map(|f| &f[level]); if iwt_transforms[level].height - 3 <= iwt_transforms[level].cur_line && !tile.tiles_bottom { if iwt_transforms[level].height & 1 == 1 { if level > 0 { self.idwt_53_filter_decode(tile, plane, params, iwt_transforms, level - 1)?; } else { let sband = &plane.subbands[cur_band]; iwt_transforms[level].band0_buf = self.decode_line_with_iquantization(sband, &mut params[cur_band], q_step_level)?; } let sband = &plane.subbands[cur_band + 1]; iwt_transforms[level].band1_buf = self.decode_line_with_iquantization(sband, &mut params[cur_band + 1], q_step_level)?; } } else { if level > 0 { self.idwt_53_filter_decode(tile, plane, params, iwt_transforms, level - 1)?; } else { // LL band let sband = &plane.subbands[cur_band]; iwt_transforms[level].band0_buf = self.decode_line_with_iquantization(sband, &mut params[cur_band], q_step_level)?; } // HL, LH and HH band iwt_transforms[level].band1_buf = self.decode_line_with_iquantization(&plane.subbands[cur_band + 1], &mut params[cur_band + 1], q_step_level)?; iwt_transforms[level].band2_buf = self.decode_line_with_iquantization(&plane.subbands[cur_band + 2], &mut params[cur_band + 2], q_step_level)?; iwt_transforms[level].band3_buf = self.decode_line_with_iquantization(&plane.subbands[cur_band + 3], &mut params[cur_band + 3], q_step_level)?; } Ok(()) } pub(super) fn idwt_53_horizontal(&self, tile: &Tile, la: usize, lb: usize, wvlt: &mut WaveletTransform) { //let mut b0pos = 0; //let mut b1pos = 0; //let mut b2pos = 0; //let mut b3pos = 0; let mut lapos = 0; let mut lbpos = 0; wvlt.reset_bufs(); if wvlt.width <= 1 { wvlt.line_buf[la][0] = wvlt.band0(0); wvlt.line_buf[lb][0] = wvlt.band2(0); } else { if tile.tiles_left { // Untested wvlt.line_buf[la][0] = wvlt.band0(0) - ((wvlt.band1(0) + wvlt.band1(1) + 2) >> 2); wvlt.line_buf[lb][0] = wvlt.band2(0) - ((wvlt.band3(0) + wvlt.band3(1) + 2) >> 2); wvlt.band1_pos += 1; wvlt.band3_pos += 1; } else { wvlt.line_buf[la][0] = wvlt.band0(0) - ((wvlt.band1(0) + 1) >> 1); wvlt.line_buf[lb][0] = wvlt.band2(0) - ((wvlt.band3(0) + 1) >> 1); } wvlt.band0_pos += 1; wvlt.band2_pos += 1; //println!("config: tile: {}, {}, band1 width: {}", tile.id, wvlt.width - 3, wvlt.band1_buf.len()); for _i in (0..(wvlt.width - 3)).step_by(2) { //println!("val: {}, band1_pos: {}, band1_size: {}", _i, wvlt.band1_pos, wvlt.band1_buf.len()); let delta = wvlt.band0(0) - ((wvlt.band1(0) + wvlt.band1(1) + 2) >> 2); wvlt.line_buf[la][lapos + 1] = wvlt.band1(0) + ((delta + wvlt.line_buf[la][lapos]) >> 1); wvlt.line_buf[la][lapos + 2] = delta; let delta = wvlt.band2(0) - ((wvlt.band3(0) + wvlt.band3(1) + 2) >> 2); wvlt.line_buf[lb][lbpos + 1] = wvlt.band3(0) + ((delta + wvlt.line_buf[lb][lbpos]) >> 1); wvlt.line_buf[lb][lbpos + 2] = delta; wvlt.advance_bufs(1); lapos += 2; lbpos += 2; } if tile.tiles_right { // Untested let delta_a = wvlt.band0(0) - ((wvlt.band1(0) + wvlt.band1(1) + 2) >> 2); wvlt.line_buf[la][lapos + 1] = wvlt.band1(0) + ((delta_a + wvlt.line_buf[la][lapos + 0]) >> 1); let delta_b = wvlt.band2(0) - ((wvlt.band3(0) + wvlt.band3(1) + 2) >> 2); wvlt.line_buf[lb][lbpos + 1] = wvlt.band3(0) + ((delta_b + wvlt.line_buf[lb][lbpos + 0]) >> 1); if wvlt.width & 1 == 1 { wvlt.line_buf[la][lapos + 2] = delta_a; wvlt.line_buf[lb][lbpos + 2] = delta_b; } } else if wvlt.width & 1 == 1 { wvlt.line_buf[la][lapos + 1] = wvlt.band1(0) + ((wvlt.line_buf[la][lapos] + wvlt.band0(0) - ((wvlt.band1(0) + 1) >> 1)) >> 1); wvlt.line_buf[la][lapos + 2] = wvlt.band0(0) - ((wvlt.band1(0) + 1) >> 1); wvlt.line_buf[lb][lbpos + 1] = wvlt.band3(0) + ((wvlt.line_buf[lb][lbpos] + wvlt.band2(0) - ((wvlt.band3(0) + 1) >> 1)) >> 1); wvlt.line_buf[lb][lbpos + 2] = wvlt.band2(0) - ((wvlt.band3(0) + 1) >> 1); } else { wvlt.line_buf[la][lapos + 1] = wvlt.line_buf[la][lapos + 0] + wvlt.band1(0); wvlt.line_buf[lb][lbpos + 1] = wvlt.line_buf[lb][lbpos + 0] + wvlt.band3(0); } } } pub(super) fn idwt_53_filter_init( &self, tile: &Tile, plane: &Plane, params: &mut Vec, iwt_transforms: &mut Vec, level: usize, ) -> Result<()> { assert!(level > 0); if level == 0 { // This code is not called from pathes where level is 0. But we keep this check. return Ok(()); } let mut cur_band = 0; for cur_level in 0..level { let q_step_level = tile.q_step.as_ref().map(|f| &f[cur_level]); if cur_level > 0 { iwt_transforms[cur_level].band0_buf = iwt_transforms[cur_level - 1].getline().clone(); } else { iwt_transforms[cur_level].band0_buf = self.decode_line_with_iquantization(&plane.subbands[cur_band], &mut params[cur_band], q_step_level)?; } let wvlt = &mut iwt_transforms[cur_level]; let h0 = wvlt.flt_tap_h + 3; if wvlt.height > 1 { wvlt.band1_buf = self.decode_line_with_iquantization(&plane.subbands[cur_band + 1], &mut params[cur_band + 1], q_step_level)?; wvlt.band2_buf = self.decode_line_with_iquantization(&plane.subbands[cur_band + 2], &mut params[cur_band + 2], q_step_level)?; wvlt.band3_buf = self.decode_line_with_iquantization(&plane.subbands[cur_band + 3], &mut params[cur_band + 3], q_step_level)?; let l0 = 0; let l1 = 1; let l2 = 2; let mut l2_pos = 0; if tile.tiles_top { self.idwt_53_horizontal(tile, l0, 1, wvlt); wvlt.band3_buf = self.decode_line_with_iquantization(&plane.subbands[cur_band + 3], &mut params[cur_band + 3], q_step_level)?; wvlt.band2_buf = self.decode_line_with_iquantization(&plane.subbands[cur_band + 2], &mut params[cur_band + 2], q_step_level)?; // process L band if wvlt.width <= 1 { wvlt.line_buf[l2][0] = wvlt.band2(0); } else { if tile.tiles_left { wvlt.line_buf[l2][0] = wvlt.band2(0) - ((wvlt.band3(0) + wvlt.band3(1) + 2) >> 2); wvlt.band3_pos += 1; } else { wvlt.line_buf[l2][0] = wvlt.band2(0) - ((wvlt.band3(0) + 1) >> 1); } wvlt.band2_pos += 1; for _i in (0..wvlt.width - 3).step_by(2) { let delta = wvlt.band2(0) - ((wvlt.band3(0) + wvlt.band3(1) + 2) >> 2); wvlt.line_buf[l2][1] = wvlt.band3(0) + ((wvlt.line_buf[l2][l2_pos] + delta) >> 1); wvlt.line_buf[l2][2] = delta; wvlt.band2_pos += 1; wvlt.band3_pos += 1; l2_pos += 2; } if tile.tiles_right { let delta = wvlt.band2(0) - ((wvlt.band3(0) + wvlt.band3(1) + 2) >> 2); wvlt.line_buf[l2][l2_pos + 1] = wvlt.band3(0) + ((wvlt.line_buf[l2][l2_pos + 0] + delta) >> 1); if wvlt.width & 1 == 1 { wvlt.line_buf[l2][l2_pos + 1] = delta; } } else if wvlt.width & 1 == 1 { let delta = wvlt.band2(0) - ((wvlt.band3(0) + 1) >> 1); wvlt.line_buf[l2][l2_pos + 1] = wvlt.band3(0) + ((wvlt.line_buf[l2][l2_pos + 0] + delta) >> 1); wvlt.line_buf[l2][l2_pos + 2] = delta; } else { wvlt.line_buf[l2][l2_pos + 1] = wvlt.band3(0) + wvlt.line_buf[l2][l2_pos + 0]; } } // process H band for i in 0..wvlt.width { wvlt.line_buf[h0][i] = wvlt.line_buf[l0][i] - ((wvlt.line_buf[l1][i] + wvlt.line_buf[l2][i] + 2) >> 2); } } else { self.idwt_53_horizontal(tile, l0, 2, wvlt); for i in 0..wvlt.width { wvlt.line_buf[h0][i] = wvlt.line_buf[l0][i] - ((wvlt.line_buf[l2][i] + 1) >> 1); } self.idwt_53_filter_decode(tile, plane, params, iwt_transforms, cur_level)?; self.idwt_53_filter_transform(tile, plane, params, iwt_transforms, cur_level)?; } } else { // This is unused in real world wvlt.band1_buf = self.decode_line_with_iquantization(&plane.subbands[cur_band + 1], &mut params[cur_band + 1], q_step_level)?; let mut h0_pos = 0; // process H band if wvlt.width <= 1 { wvlt.line_buf[h0][0] = wvlt.band0(0); } else { if tile.tiles_left { wvlt.line_buf[h0][h0_pos] = wvlt.band0(0) - ((wvlt.band1(0) + wvlt.band1(1) + 2) >> 2); wvlt.band1_pos += 1; } else { wvlt.line_buf[h0][h0_pos] = wvlt.band0(0) - ((wvlt.band1(0) + 1) >> 1); } wvlt.band0_pos += 1; for _i in (0..(wvlt.width - 3)).step_by(2) { let delta = wvlt.band0(0) - ((wvlt.band1(0) + wvlt.band1(1) + 2) >> 2); wvlt.line_buf[h0][h0_pos + 1] = wvlt.band1(0) + ((wvlt.line_buf[h0][h0_pos + 0] + delta) >> 1); wvlt.line_buf[h0][h0_pos + 2] = delta; wvlt.band0_pos += 1; wvlt.band1_pos += 1; h0_pos += 2; } if tile.tiles_right { // untested let delta = wvlt.band0(0) - ((wvlt.band1(0) + wvlt.band1(1) + 2) >> 2); wvlt.line_buf[h0][h0_pos + 1] = wvlt.band1(0) + ((wvlt.line_buf[h0][h0_pos + 0] + delta) >> 1); wvlt.line_buf[h0][h0_pos + 2] = delta; } else if wvlt.width & 1 == 1 { let delta = wvlt.band0(0) - ((wvlt.band1(0) + 1) >> 1); wvlt.line_buf[h0][h0_pos + 1] = wvlt.band1(0) + ((wvlt.line_buf[h0][h0_pos + 0] + delta) >> 1); wvlt.line_buf[h0][h0_pos + 2] = delta; } else { wvlt.line_buf[h0][h0_pos + 1] = wvlt.band1(0) + wvlt.line_buf[h0][h0_pos + 0]; } } wvlt.cur_line += 1; wvlt.cur_h += 1; wvlt.flt_tap_h = (wvlt.flt_tap_h + 1) % 5; } cur_band += 3; } Ok(()) } pub(super) fn idwt_53_filter_transform( &self, tile: &Tile, plane: &Plane, params: &mut Vec, iwt_transforms: &mut Vec, level: usize, ) -> Result<()> { if iwt_transforms[level].cur_h > 0 { return Ok(()); } if iwt_transforms[level].cur_line >= iwt_transforms[level].height - 3 { if !tile.tiles_bottom { if iwt_transforms[level].height & 1 == 1 { if level > 0 { if iwt_transforms[level - 1].cur_h == 0 { self.idwt_53_filter_transform(tile, plane, params, iwt_transforms, level - 1)?; } iwt_transforms[level].band0_buf = iwt_transforms[level - 1].getline().clone(); } let wvlt = &mut iwt_transforms[level]; wvlt.reset_bufs(); let h0 = wvlt.flt_tap_h + 3; let h1 = (wvlt.flt_tap_h + 1) % 5 + 3; let h2 = (wvlt.flt_tap_h + 2) % 5 + 3; let l0 = 0; let l1 = 1; let mut l0_pos = 0; //let mut l1_pos = 0; // process L bands if wvlt.width <= 1 { wvlt.line_buf[l0][0] = wvlt.band0(0); } else { if tile.tiles_left { // untested wvlt.line_buf[l0][l0_pos] = wvlt.band0(0) - ((wvlt.band1(0) + wvlt.band1(1) + 2) >> 2); wvlt.band1_pos += 1; } else { wvlt.line_buf[l0][l0_pos] = wvlt.band0(0) - ((wvlt.band1(0) + 1) >> 1); } wvlt.band0_pos += 1; for _i in (0..(wvlt.width - 3)).step_by(2) { let delta = wvlt.band0(0) - ((wvlt.band1(0) + wvlt.band1(1) + 2) >> 2); wvlt.line_buf[l0][l0_pos + 1] = wvlt.band1(0) + ((wvlt.line_buf[l0][l0_pos + 0] + delta) >> 1); wvlt.line_buf[l0][l0_pos + 2] = delta; wvlt.band0_pos += 1; wvlt.band1_pos += 1; l0_pos += 2; } if tile.tiles_right { // untested let delta = wvlt.band0(0) - ((wvlt.band1(0) + wvlt.band1(1) + 2) >> 2); wvlt.line_buf[l0][l0_pos + 1] = wvlt.band1(0) + ((wvlt.line_buf[l0][l0_pos + 0] + delta) >> 1); if wvlt.width & 1 == 1 { wvlt.line_buf[l0][l0_pos + 2] = delta; } } else if wvlt.width & 1 == 1 { let delta = wvlt.band0(0) - ((wvlt.band1(0) + 1) >> 1); wvlt.line_buf[l0][l0_pos + 1] = wvlt.band1(0) + ((wvlt.line_buf[l0][l0_pos + 0] + delta) >> 1); wvlt.line_buf[l0][l0_pos + 2] = delta; } else { wvlt.line_buf[l0][l0_pos + 1] = wvlt.band1(0) + wvlt.line_buf[l0][l0_pos + 0]; } } // process H bands //wvlt.reset_bufs(); wvlt.line_buf.swap(1, 2); for i in 0..wvlt.width { let delta = wvlt.line_buf[l0][i] - ((wvlt.line_buf[l1][i] + 1) >> 1); wvlt.line_buf[h1][i] = wvlt.line_buf[l1][i] + ((delta + wvlt.line_buf[h0][i]) >> 1); wvlt.line_buf[h2][i] = delta; } wvlt.cur_h += 3; wvlt.cur_line += 3; wvlt.flt_tap_h = (wvlt.flt_tap_h + 3) % 5; } else { let wvlt = &mut iwt_transforms[level]; let l2 = 2; let h0 = wvlt.flt_tap_h + 3; let h1 = (wvlt.flt_tap_h + 1) % 5 + 3; for i in 0..wvlt.width { wvlt.line_buf[h1][i] = wvlt.line_buf[h0][i] + wvlt.line_buf[l2][i]; } // The original libraw CRX decoder copies the pointer from line_buf[2] to [1]. // But it doesn't makes sense, so we swap the buffers as we do on other locations. wvlt.line_buf.swap(1, 2); //wvlt.line_buf[1] = wvlt.line_buf[2].clone(); wvlt.cur_h += 2; wvlt.cur_line += 2; wvlt.flt_tap_h = (wvlt.flt_tap_h + 2) % 5; } } // end if !tile.tiles_bottom } else { if level > 0 { if iwt_transforms[level - 1].cur_h == 0 { self.idwt_53_filter_transform(tile, plane, params, iwt_transforms, level - 1)?; } iwt_transforms[level].band0_buf = iwt_transforms[level - 1].getline().clone(); } let wvlt = &mut iwt_transforms[level]; wvlt.reset_bufs(); let l0 = 0; let l1 = 1; //let l2 = 2; let mut l0_pos = 0; let mut l1_pos = 0; //let mut l2_pos = 0; let h0 = wvlt.flt_tap_h + 3; let h1 = (wvlt.flt_tap_h + 1) % 5 + 3; let h2 = (wvlt.flt_tap_h + 2) % 5 + 3; // process L bands if wvlt.width <= 1 { wvlt.line_buf[l0][0] = wvlt.band0(0); wvlt.line_buf[l1][0] = wvlt.band2(0); } else { // untested if tile.tiles_left { wvlt.line_buf[l0][0] = wvlt.band0(0) - ((wvlt.band1(0) + wvlt.band1(1) + 2) >> 2); wvlt.line_buf[l1][0] = wvlt.band2(0) - ((wvlt.band3(0) + wvlt.band3(1) + 2) >> 2); wvlt.band1_pos += 1; wvlt.band3_pos += 1; } else { wvlt.line_buf[l0][0] = wvlt.band0(0) - ((wvlt.band1(0) + 1) >> 1); wvlt.line_buf[l1][0] = wvlt.band2(0) - ((wvlt.band3(0) + 1) >> 1); } wvlt.band0_pos += 1; wvlt.band2_pos += 1; for _i in (0..(wvlt.width - 3)).step_by(2) { let delta = wvlt.band0(0) - ((wvlt.band1(0) + wvlt.band1(1) + 2) >> 2); wvlt.line_buf[l0][l0_pos + 1] = wvlt.band1(0) + ((delta + wvlt.line_buf[l0][l0_pos + 0]) >> 1); wvlt.line_buf[l0][l0_pos + 2] = delta; let delta = wvlt.band2(0) - ((wvlt.band3(0) + wvlt.band3(1) + 2) >> 2); wvlt.line_buf[l1][l1_pos + 1] = wvlt.band3(0) + ((delta + wvlt.line_buf[l1][l1_pos + 0]) >> 1); wvlt.line_buf[l1][l1_pos + 2] = delta; wvlt.advance_bufs(1); l0_pos += 2; l1_pos += 2; } if tile.tiles_right { // untested let delta_a = wvlt.band0(0) - ((wvlt.band1(0) + wvlt.band1(1) + 2) >> 2); wvlt.line_buf[l0][l0_pos + 1] = wvlt.band1(0) + ((delta_a + wvlt.line_buf[l0][l0_pos + 0]) >> 1); let delta_b = wvlt.band2(0) - ((wvlt.band3(0) + wvlt.band3(1) + 2) >> 2); wvlt.line_buf[l1][l1_pos + 1] = wvlt.band3(0) + ((delta_b + wvlt.line_buf[l1][l1_pos + 0]) >> 1); if wvlt.width & 1 == 1 { wvlt.line_buf[l0][l0_pos + 2] = delta_a; wvlt.line_buf[l1][l1_pos + 2] = delta_b; } } else if wvlt.width & 1 == 1 { let delta = wvlt.band0(0) - ((wvlt.band1(0) + 1) >> 1); wvlt.line_buf[l0][l0_pos + 1] = wvlt.band1(0) + ((delta + wvlt.line_buf[l0][l0_pos + 0]) >> 1); wvlt.line_buf[l0][l0_pos + 2] = delta; let delta = wvlt.band2(0) - ((wvlt.band3(0) + 1) >> 1); wvlt.line_buf[l1][l1_pos + 1] = wvlt.band3(0) + ((delta + wvlt.line_buf[l1][l1_pos + 0]) >> 1); wvlt.line_buf[l1][l1_pos + 2] = delta; } else { wvlt.line_buf[l0][l0_pos + 1] = wvlt.line_buf[l0][l0_pos] + wvlt.band1(0); wvlt.line_buf[l1][l1_pos + 1] = wvlt.line_buf[l1][l1_pos] + wvlt.band3(0); } } // process H bands let wvlt = &mut iwt_transforms[level]; wvlt.line_buf.swap(1, 2); let l0 = 0; let l1 = 1; let l2 = 2; for i in 0..wvlt.width { let delta = wvlt.line_buf[l0][i] - ((wvlt.line_buf[l2][i] + wvlt.line_buf[l1][i] + 2) >> 2); wvlt.line_buf[h1][i] = wvlt.line_buf[l1][i] + ((delta + wvlt.line_buf[h0][i]) >> 1); wvlt.line_buf[h2][i] = delta; } if iwt_transforms[level].cur_line >= iwt_transforms[level].height - 3 && iwt_transforms[level].height & 1 == 1 { iwt_transforms[level].cur_h += 3; iwt_transforms[level].cur_line += 3; iwt_transforms[level].flt_tap_h = (iwt_transforms[level].flt_tap_h + 3) % 5; } else { iwt_transforms[level].cur_h += 2; iwt_transforms[level].cur_line += 2; iwt_transforms[level].flt_tap_h = (iwt_transforms[level].flt_tap_h + 2) % 5; } } Ok(()) } } rawler-0.7.1/src/decompressors/crx/iquant.rs000064400000000000000000000277531046102023000172650ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher // Original Crx decoder crx.cpp was written by Alexey Danilchenko for libraw. // Rewritten in Rust by Daniel Vogelbacher, based on logic found in // crx.cpp and documentation done by Laurent Clévy (https://github.com/lclevy/canon_cr3). use super::{ BandParam, CodecParams, CrxError, Result, decoder::constrain, mdat::{Subband, Tile}, }; use crate::decompressors::crx::{decoder::error_code_signed, rice::RiceDecoder}; use bitstream_io::BitReader; use log::warn; use std::io::Cursor; /// QStep table for QP [0,1,2,3,4,5] #[rustfmt::skip] pub(super) const Q_STEP_TBL: [u32; 6] = [0x28, 0x2D, 0x33, 0x39, 0x40, 0x48]; /// Holds the QStep information for a tile #[derive(Clone, Debug)] #[allow(unused)] pub struct QStep { /// QStep tables for each compression level pub q_step_tbl: Vec, pub width: usize, pub height: usize, } impl QStep { pub fn new(width: usize, height: usize) -> Self { Self { q_step_tbl: Vec::with_capacity(width * height), width, height, } } } impl CodecParams { /// Update Q parameter. /// Seems not to be used in real world (untested). pub(super) fn update_q_param(_band: &Subband, param: &mut BandParam) -> Result<()> { warn!("Untested routine, please send in a sample file"); let bit_code = param.rice.adaptive_rice_decode(true, 23, 8, 0)?; param.q_param = ((param.q_param as i32) + error_code_signed(bit_code)) as u32; if param.rice.k() > 7 { Err(CrxError::General(format!( "Overflow while updating Q parameter: K is out of range: {}", param.rice.k() ))) } else { Ok(()) } } /// Decode line with inverse quantization pub(super) fn decode_line_with_iquantization(&self, band: &Subband, param: &mut BandParam, q_step: Option<&QStep>) -> super::Result> { if band.data_size == 0 { return Ok(Vec::new()); } // only LL bands has support_partial, but quantization is not applied to // LL bands. So this never happen in real world. if band.support_partial && q_step.is_none() { debug_assert_eq!(1, 2); // make sure we detect such files, then this statement can be removed Self::update_q_param(band, param)?; } // Entropy decode the current line, then apply inverse quantization self.decode_line(param)?; match q_step { Some(q_step) => { // new version let q_step_tbl_ptr = &q_step.q_step_tbl[(q_step.width * band.get_subband_row(param.cur_line - 1))..]; for i in 0..band.col_start_addon { let quant_val = band.q_step_base + ((q_step_tbl_ptr[0] * band.q_step_multi as u32) >> 3) as i32; param.decoded_buf_mut()[i] *= constrain(quant_val, 1, 0x168000); } for i in band.col_start_addon..(band.width - band.col_end_addon) { let idx = (i - band.col_start_addon) >> band.level_shift; let quant_val = band.q_step_base + ((q_step_tbl_ptr[idx] * band.q_step_multi as u32) >> 3) as i32; //eprintln!("{}", quant_val); param.decoded_buf_mut()[i] *= constrain(quant_val, 1, 0x168000); } let last_idx = (band.width - band.col_end_addon - band.col_start_addon - 1) >> band.level_shift; for i in (band.width - band.col_end_addon)..band.width { let quant_val = band.q_step_base + ((q_step_tbl_ptr[last_idx] * band.q_step_multi as u32) >> 3) as i32; param.decoded_buf_mut()[i] *= constrain(quant_val, 1, 0x168000); } } None => { //eprintln!("q-param: {}", param.q_param); // prev. version let q_scale = if param.q_param / 6 >= 6 { Q_STEP_TBL[param.q_param as usize % 6] * (1 << (param.q_param / 6 + 26)) } else { Q_STEP_TBL[param.q_param as usize % 6] >> (6 - param.q_param / 6) }; // Optimization: if scale is 1, no multiplication is required if q_scale != 1 { //println!("scale width: {}", band.width); for i in 0..band.width { param.decoded_buf_mut()[i] *= q_scale as i32; } } } } Ok(Vec::from(param.decoded_buf())) } } impl Tile { /// Predict symbol for QP table /// This uses MED but depending on the column position, /// b-c or d-b is used as delta_h fn predict_qp_symbol(left: i32, top: i32, delta_h: i32, delta_v: i32) -> i32 { match ((delta_v < 0) ^ (delta_h < 0), (left < top) ^ (delta_h < 0)) { (false, false) | (false, true) => left + delta_h, (true, false) => left, (true, true) => top, } } /// Make the QStep table out of the QP table fn make_qstep(&self, params: &CodecParams, qp_table: Vec) -> Result> { debug_assert!(params.levels <= 3 && params.levels > 0); let qp_width = (self.plane_width >> 3) + if self.plane_width & 7 != 0 { 1 } else { 0 }; let qp_height = (self.plane_height >> 1) + (self.plane_height & 1); let qp_height4 = (self.plane_height >> 2) + if self.plane_height & 3 > 0 { 1 } else { 0 }; let qp_height8 = (self.plane_height >> 3) + if self.plane_height & 7 > 0 { 1 } else { 0 }; let mut q_steps = Vec::with_capacity(params.levels as usize); // Lookup function into Q_STEP_TBL let q_lookup = |quant_val: i32| -> u32 { //eprintln!("quant_val: {quant_val}"); if quant_val / 6 >= 6 { // Original code uses obscure calculation: // // Q_STEP_TBL[quant_val as usize % 6] * (1 << (quant_val as u32 / 6 + 26)) // // But this branch is only selected when (quant_val / 6) is >= 6, so the bit shift count // is always 6 + 26 = 32 or even higher! // The shl operand is a 32 bit value, so maximum count for shift is 31. x86 processors do mask // the shift count to 0x1F, so this calculation would lead to 0 - which produces // artifacts in decompressed image. // // To fix these artifacts and shl overflow, we skip the multiplication // and use wrapping_shl() which auto-apply bit masking. Q_STEP_TBL[quant_val as usize % 6].wrapping_shl(quant_val as u32 / 6 + 26) } else { Q_STEP_TBL[quant_val as usize % 6] >> (6 - quant_val / 6) } }; // Iterate 3, 2, 1 for level in (1..=params.levels).rev() { match level { 3 => { let mut q_step = QStep::new(qp_width, qp_height8); for qp_row in 0..qp_height8 { let mut row0_idx = qp_width * std::cmp::min(4 * qp_row + 0, qp_height - 1); let mut row1_idx = qp_width * std::cmp::min(4 * qp_row + 1, qp_height - 1); let mut row2_idx = qp_width * std::cmp::min(4 * qp_row + 2, qp_height - 1); let mut row3_idx = qp_width * std::cmp::min(4 * qp_row + 3, qp_height - 1); for _qp_col in 0..qp_width { let qp_sum = qp_table[row0_idx] + qp_table[row1_idx] + qp_table[row2_idx] + qp_table[row3_idx]; let quant_val = if qp_sum.is_negative() { (qp_sum + 3) / 4 // Round? } else { qp_sum / 4 }; let x = q_lookup(quant_val); //eprintln!("QSTEP 8: {:?}", x); q_step.q_step_tbl.push(x); row0_idx += 1; row1_idx += 1; row2_idx += 1; row3_idx += 1; } } debug_assert_eq!(q_step.q_step_tbl.len(), qp_width * qp_height8); q_steps.push(q_step); } 2 => { let mut q_step = QStep::new(qp_width, qp_height4); for qp_row in 0..qp_height4 { let mut row0_idx = qp_width * std::cmp::min(2 * qp_row + 0, qp_height - 1); let mut row1_idx = qp_width * std::cmp::min(2 * qp_row + 1, qp_height - 1); for _qp_col in 0..qp_width { let quant_val = (qp_table[row0_idx] + qp_table[row1_idx]) / 2; let x = q_lookup(quant_val); //eprintln!("QSTEP 4: {:?}", x); q_step.q_step_tbl.push(x); row0_idx += 1; row1_idx += 1; } } debug_assert_eq!(q_step.q_step_tbl.len(), qp_width * qp_height4); //eprintln!("4: {:?}, {:?}", q_step.q_step_tbl[405], q_step.q_step_tbl[8433]); q_steps.push(q_step); } 1 => { //println!("1 qp_height: {}, qp_width: {}", qp_height, qp_width); let mut q_step = QStep::new(qp_width, qp_height); for qp_row in 0..qp_height { for qp_col in 0..qp_width { let quant_val = qp_table[(qp_row * qp_width) + qp_col]; let x = q_lookup(quant_val); //eprintln!("QSTEP 0: {:?}", x); q_step.q_step_tbl.push(x); } } debug_assert_eq!(q_step.q_step_tbl.len(), qp_width * qp_height); q_steps.push(q_step); } _ => { return Err(CrxError::General(format!("Unsupported level while generating qstep data: {}", level))); } } } Ok(q_steps) } pub(super) fn generate_qstep_table(&mut self, params: &CodecParams, data: &[u8]) -> Result<()> { match self.qp_data.as_ref() { Some(qp_data) => { //println!("generate: size: {}", qp_data.mdat_qp_data_size); let mdat_qp = &data[self.data_offset..self.data_offset + qp_data.mdat_qp_data_size as usize]; let bitpump = BitReader::endian(Cursor::new(mdat_qp), bitstream_io::BigEndian); let mut rice = RiceDecoder::new(bitpump); let qp_width = (self.plane_width >> 3) + if self.plane_width & 7 != 0 { 1 } else { 0 }; let qp_height = (self.plane_height >> 1) + (self.plane_height & 1); let total_qp = qp_width * qp_height; //eprintln!("tile: {} {}", self.width, self.height); //eprintln!("qp_width: {}, qp_height: {}, total_qp: {}", qp_width, qp_height, total_qp); // Line length is width + one additional pixel at start end end (same as for pixel decoding) let line_len = 1 + qp_width + 1; let mut line_buf = [vec![0; line_len], vec![0; line_len]]; let mut qp_table = vec![0; total_qp]; for qp_row in 0..qp_height { let mut line_pos = 1; // start at first real coeff x (skip a) if qp_row == 0 { // For first top row line_buf[1][line_pos - 1] = 0; // init coeff a for _ in (0..qp_width).rev() { let x = line_buf[1][line_pos - 1]; // x = a let qp = rice.adaptive_rice_decode(true, 23, 8, 7)?; line_buf[1][line_pos] = x + error_code_signed(qp); line_pos += 1; } line_buf[1][line_pos] = line_buf[1][line_pos - 1] + 1; } else { // For all other rows line_buf[1][line_pos - 1] = line_buf[0][line_pos]; // init coeff a = b // delta_h = b-c let mut delta_h = line_buf[0][line_pos] - line_buf[0][line_pos - 1]; for width in (0..qp_width).rev() { let a = line_buf[1][line_pos - 1]; let b = line_buf[0][line_pos]; let c = line_buf[0][line_pos - 1]; let d = line_buf[0][line_pos + 1]; let x = Self::predict_qp_symbol(a, b, delta_h, c - a); let qp = rice.adaptive_rice_decode(false, 23, 8, 0)?; line_buf[1][line_pos] = x + error_code_signed(qp); if width > 0 { delta_h = d - b; rice.update_k_param((qp + 2 * delta_h.unsigned_abs()) >> 1, 7); } else { rice.update_k_param(qp, 7); } line_pos += 1; } line_buf[1][line_pos] = line_buf[1][line_pos - 1] + 1; } for qp_col in 0..qp_width { qp_table[(qp_row * qp_width) + qp_col] = line_buf[1][qp_col + 1] + 4; } line_buf.swap(0, 1); } //for qp in &qp_table { //eprintln!("QP: {}", qp); //} //eprintln!("QP: {:?}", &qp_table[..]); self.q_step = Some(self.make_qstep(params, qp_table)?); Ok(()) } None => Ok(()), } } } rawler-0.7.1/src/decompressors/crx/mdat.rs000064400000000000000000000307501046102023000167000ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher // Original Crx decoder crx.cpp was written by Alexey Danilchenko for libraw. // Rewritten in Rust by Daniel Vogelbacher, based on logic found in // crx.cpp and documentation done by Laurent Clévy (https://github.com/lclevy/canon_cr3). use super::{Result, iquant::QStep}; use crate::decompressors::crx::CrxError; use byteorder::{BigEndian, ReadBytesExt}; use std::io::{Cursor, Read}; #[derive(Debug, Clone)] pub struct Tile { // Header fields pub ind: u16, pub size: u16, pub tile_size: usize, pub flags: u32, pub qp_data: Option, // Calculated fields pub id: usize, pub counter: u32, pub tail_sign: u32, /// Offset of tile data relative to mdat header end pub data_offset: usize, pub tile_width: usize, pub tile_height: usize, pub plane_width: usize, pub plane_height: usize, pub tiles_top: bool, pub tiles_bottom: bool, pub tiles_left: bool, pub tiles_right: bool, /// Planes for tile pub planes: Vec, /// QStep table for this tile and for each level (1, 2, 3) pub q_step: Option>, } impl Tile { pub fn new(id: usize, hdr: &mut R, ind: u16, tile_offset: usize) -> Result { let size = hdr.read_u16::()?; let tile_size = hdr.read_u32::()? as usize; let flags = hdr.read_u32::()?; //let counter = flags >> 28; let counter = (flags >> 16) & 0xF; let tail_sign = flags & 0xFFFF; let qp_data = if size == 16 { let mdat_qp_data_size = hdr.read_u32::()?; let mdat_extra_size = hdr.read_u16::()?; let terminator = hdr.read_u16::()?; assert!(terminator == 0); Some(TileQPData { mdat_qp_data_size, mdat_extra_size, terminator, }) } else { None }; // TODO check on release assert!((size == 8 && tail_sign == 0) || (size == 16 && tail_sign == 0x4000)); Ok(Tile { id, ind, size, tile_size, flags, counter, tail_sign, data_offset: tile_offset, planes: vec![], tile_height: 0, tile_width: 0, plane_height: 0, plane_width: 0, qp_data, tiles_top: false, tiles_bottom: false, tiles_left: false, tiles_right: false, q_step: None, }) } pub fn descriptor_line(&self) -> String { let extra_data = match self.qp_data.as_ref() { Some(qp_data) => { format!( " qp_data_size: {:#x} extra_size: {:#x}, terminator: {:#x}", qp_data.mdat_qp_data_size, qp_data.mdat_extra_size, qp_data.terminator ) } None => String::from("NONE"), }; format!( "Tile {:#x} size: {:#x} tile_size: {:#x} flags: {:#x} counter: {:#x} tail_sign: {:#x} extra: {}\n top: {}, left: {}, bottom: {}, right: {}", self.ind, self.size, self.tile_size, self.flags, self.counter, self.tail_sign, extra_data, self.tiles_top, self.tiles_left, self.tiles_bottom, self.tiles_right, //mdatQPDataSize.unwrap_or_default() ) } /// Tile may contain some extra data for quantization pub fn extra_size(&self) -> usize { match self.qp_data.as_ref() { Some(qp_data) => qp_data.mdat_qp_data_size as usize + qp_data.mdat_extra_size as usize, None => 0, } } } #[derive(Debug, Clone)] pub struct TileQPData { /// Size in bytes of QP data for version 0x200 pub mdat_qp_data_size: u32, /// Unused bytes to extend tile size to 0x8 boundary pub mdat_extra_size: u16, /// 0 - Terminator pub terminator: u16, } #[derive(Debug, Clone)] #[allow(unused)] pub struct Plane { // Header fields pub ind: u16, pub size: u16, pub plane_size: usize, pub flags: u32, // Calculated fields pub id: usize, pub counter: u32, pub support_partial: bool, /// Rounded bits mask - only used for level=0 images /// with suuport_partial=true pub rounded_bits_mask: i32, pub data_offset: usize, pub parent_offset: usize, /// List of subbands pub subbands: Vec, } impl Plane { pub fn new(id: usize, hdr: &mut R, ind: u16, parent_offset: usize, plane_offset: usize) -> Result { let size = hdr.read_u16::()?; let plane_size = hdr.read_u32::()? as usize; let flags = hdr.read_u32::()?; let counter = (flags >> 28) & 0xf; // 4 bits //let support_partial = (flags >> 27) & 0x1; // 1 bit let support_partial: bool = (flags & 0x8000000) != 0; let mut rounded_bits_mask = ((flags >> 25) & 0x3) as i32; // 2 bit if rounded_bits_mask != 0 { rounded_bits_mask = 1 << (rounded_bits_mask - 1); } assert!(flags & 0x00FFFFFF == 0); Ok(Plane { id, ind, size, plane_size, flags, counter, support_partial, rounded_bits_mask, data_offset: plane_offset, parent_offset, subbands: vec![], }) } pub fn descriptor_line(&self) -> String { format!( " Plane {:#x} size: {:#x} plane_size: {:#x} flags: {:#x} counter: {:#x} support_partial: {} rounded_bits: {:#x}", self.ind, self.size, self.plane_size, self.flags, self.counter, self.support_partial, self.rounded_bits_mask ) } } /// Header information for a single subband /// /// Two indicators are known: 0xFF03 and 0xFF13 #[derive(Debug, Clone, Default)] #[allow(unused)] pub struct Subband { /// Indicator, 0xFF03 for version 1, 0xFF13 for version 2 pub ind: u16, /// Header size pub header_size: u16, /// Subband size, uncorrected, size boundary = 0x8 pub subband_size: usize, /// Flags like partial support or subband size correction value pub flags: u32, /// Q step base, used for inverse quantization (band != LL) pub q_step_base: i32, // Q step multiplicator, used for inverse quantization (band != LL) pub q_step_multi: u16, // --- Calculated fields /// Band ID (0-9) pub id: usize, /// Band counter (0-9) pub counter: u32, /// Partial decoding (only band LL) pub support_partial: bool, /// QP - quantization parameter for QStep /// Version 0x100 has no embedded QStep table, instead /// a predefined QStep table is used. pub q_param: u32, /// Unused bytes in band data at end pub unused_bytes: u32, /// Band data offset relative to plane offset pub data_offset: usize, /// Parent offset, TODO: Remove, it's not exact beacuse of tile extra data pub parent_offset: usize, /// Band data size, this is subband_size corrected by unused_bytes pub data_size: usize, /// Width of band in pixels pub width: usize, /// Height of band in pixels pub height: usize, // For Wavelets pub row_start_addon: usize, pub row_end_addon: usize, pub col_start_addon: usize, pub col_end_addon: usize, pub level_shift: i16, } impl Subband { pub fn new(id: usize, hdr: &mut R, ind: u16, parent_offset: usize, band_offset: usize) -> Result { let size = hdr.read_u16::()?; assert!((size == 8 && ind == 0xFF03) || (size == 16 && ind == 0xFF13)); let subband_size = hdr.read_u32::()? as usize; match ind { 0xFF03 => { let flags = hdr.read_u32::()?; let counter = (flags >> 28) & 0xf; // 4 bits let support_partial: bool = (flags & 0x8000000) != 0; let q_param = (flags >> 19) & 0xFF; // 8 bit q_aram let unused_bytes = flags & 0x7FFFF; // 19 bit, related to subband_size let data_size: usize = (subband_size as u32 - unused_bytes) as usize; let q_step_base = 0; let q_step_multi = 0; Ok(Subband { id, ind, header_size: size, subband_size, flags, counter, support_partial, q_param, q_step_base, q_step_multi, unused_bytes, data_offset: band_offset, parent_offset, data_size, ..Default::default() }) } 0xFF13 => { // support_partial and q_Param are not supported in this version let q_param = 0; let support_partial = false; let flags = hdr.read_u16::()? as u32; let q_step_multi = hdr.read_u16::()?; let q_step_base = hdr.read_i32::()?; let unused_bytes = hdr.read_u16::()? as u32; let end_marker = hdr.read_u16::()?; assert!(end_marker == 0); let counter = (flags >> 12) & 0xf; // 4 bits let data_size: usize = (subband_size as u32 - unused_bytes) as usize; Ok(Subband { id, ind, header_size: size, subband_size, flags, counter, support_partial, q_param, q_step_base, q_step_multi, unused_bytes, data_offset: band_offset, parent_offset, data_size, ..Default::default() }) } _ => Err(CrxError::General(format!("Unknown subband header indicator: {:?}", ind))), } } pub fn descriptor_line(&self) -> String { format!( " Subband {:#x} size: {:#x} subband_size: {:#x} flags: {:#x} counter: {:#x} support_partial: {} q_param: {:#x} unused_bytes: {:#x} qStepBase: {:#x} qStepMult: {:#x} ", self.ind, self.header_size, self.subband_size, self.flags, self.counter, self.support_partial, self.q_param, self.unused_bytes, self.q_step_base, self.q_step_multi ) } pub(super) fn get_subband_row(&self, row: usize) -> usize { if row < self.row_start_addon { 0 } else if row < self.height - self.row_end_addon { row - self.row_end_addon } else { self.height - self.row_end_addon - self.row_start_addon - 1 } } pub(super) fn setup_idx( &mut self, version: u16, level: usize, col_start_idx: usize, band_width_ex_coef: usize, row_start_idx: usize, band_height_ex_coef: usize, ) { //println!("Version: 0x{:x?}", version); if version == 0x200 { self.row_start_addon = row_start_idx; self.row_end_addon = band_height_ex_coef; self.col_start_addon = col_start_idx; self.col_end_addon = band_width_ex_coef; self.level_shift = 3 - level as i16; } else { self.row_start_addon = 0; self.row_end_addon = 0; self.col_start_addon = 0; self.col_end_addon = 0; self.level_shift = 0; } } } fn next_indicator(hdr: &mut T) -> Result { hdr .read_u16::() .map_err(|_| CrxError::General("Header indicator read failed".into())) } /// Parse MDAT header for structure of embedded data #[allow(clippy::while_let_loop)] pub(super) fn parse_header(mdat_hdr: &[u8]) -> Result> { let mut hdr = Cursor::new(mdat_hdr); let mut tiles = Vec::new(); let mut tile_offset: usize = 0; let mut plane_offset: usize = 0; let mut band_offset: usize = 0; let mut ind = next_indicator(&mut hdr)?; loop { match ind { 0xff01 | 0xff11 => { let mut tile = Tile::new(tiles.len(), &mut hdr, ind, tile_offset)?; ind = next_indicator(&mut hdr)?; loop { match ind { 0xff02 | 0xff12 => { let mut plane = Plane::new(tile.planes.len(), &mut hdr, ind, tile.data_offset, plane_offset)?; ind = next_indicator(&mut hdr)?; loop { match ind { 0xff03 | 0xff13 => { let subband = Subband::new(plane.subbands.len(), &mut hdr, ind, tile.data_offset + plane.data_offset, band_offset)?; band_offset += subband.subband_size; plane.subbands.push(subband); // Multi-tile files has no 0x0000 end marker, so we simulate it // on an read error. ind = next_indicator(&mut hdr).unwrap_or(0x0000); } _ => { break; } } } plane_offset += plane.plane_size as usize; band_offset = 0; // reset band offset tile.planes.push(plane); } _ => { break; } } } tile_offset += tile.tile_size; plane_offset = 0; // reset plane offset tiles.push(tile); } 0x0000 => { break; } _ => { return Err(CrxError::General(format!("Unexpected header record marker: {:x?}", ind))); } } } Ok(tiles) } rawler-0.7.1/src/decompressors/crx/mod.rs000064400000000000000000000353151046102023000165340ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher // Original Crx decoder crx.cpp was written by Alexey Danilchenko for libraw. // Rewritten in Rust by Daniel Vogelbacher, based on logic found in // crx.cpp and documentation done by Laurent Clévy (https://github.com/lclevy/canon_cr3). // Crx is based on JPEG-LS from ITU T.78 and described in US patent US 2016/0323602 A1. // It has two modes: // - Lossless compression // - Lossy compression // For lossless (only LL band exists) and LL band from lossy compression, // prediction is used combined with adaptive Golomb-Rice entropy encoding for compression. // For lossy bands other than LL a special value rounding is introduced // into Golomb-Rice encoded values. // // LL band compression uses for the first image line run-length encoding // from JPEG-LS and adaptive Golomb-Rice encoding. For other lines, // MED (Median Edge Detection) is added to the encoding routines. // // For Lossy compression, image input is wavelet-transformed into subbands. // The LL band for low frequency part // The LH band for horizontal-direction frequency characteristic // The HL band for vertical-direction frequency characteristic // The HH band for oblique-direction frequency characteristic // // Transformation is directed by i, number of wavelet transformations. // Crx uses i=3, so the output is LL(3), LH(3), HL(3), HH(3), LH(2), HL(2), HH(2), LH(1), HL(1), HH(1) // use self::{mdat::Tile, rice::RiceDecoder}; use crate::formats::bmff::ext_cr3::cmp1::Cmp1Box; use bitstream_io::BitReader; use log::debug; use std::io::Cursor; use thiserror::Error; mod decoder; mod idwt; mod iquant; mod mdat; mod rice; mod runlength; /// Each level has 6*8 = 0x30 = 48 ex coef values /// Not every level is used. For example, an image with level=3 /// only used the last level 3 values. #[rustfmt::skip] const EX_COEF_NUM_TBL:[usize; 0x30*3] = [ // Level 1 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // Level 2 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 2, 2, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 2, 2, 1, 0, 0, 1, 1, 1, 1, 0, 0, // Level 3 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 0, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1]; /// BitPump for Big Endian bit streams type BitPump<'a> = BitReader, bitstream_io::BigEndian>; /// Error variants for compressor #[derive(Debug, Error)] pub enum CrxError { /// Overflow of input, size constraints... #[error("Overflow error: {}", _0)] Overflow(String), /// General error #[error("General error: {}", _0)] General(String), /// General error #[error("Unsupported format: {}", _0)] Unsupp(String), /// Error on internal cursor type #[error("I/O error")] Io(#[from] std::io::Error), } /// Result type for Compressor results type Result = std::result::Result; /// Codec parameters for decoding #[derive(Default, Debug, Clone, Copy)] pub struct CodecParams { #[allow(dead_code)] sample_precision: u8, image_width: usize, image_height: usize, plane_count: u8, //plane_width: usize, //plane_height: usize, #[allow(dead_code)] subband_count: u8, levels: usize, /// Bit depth of image #[allow(dead_code)] n_bits: u8, /// Bit depth for median (enc_type == 3, otherwise it is same as n_bits) median_bits: u8, enc_type: u8, tile_cols: usize, tile_rows: usize, tile_width: usize, tile_height: usize, mdat_hdr_size: u32, version: u16, } impl CodecParams { #[inline(always)] fn get_header<'a>(&self, mdat: &'a [u8]) -> &'a [u8] { &mdat[..self.mdat_hdr_size as usize] } /// The MDAT section contains the raw pixel data. /// Multiple images and data can be embedded into MDAT. The offsets /// and size is located in co64 and stsz BMF boxes. The raw data /// starts with an header block describing the data and subband offsets. /// /// MDAT Layout: /// |-----|-----------|-----|-----------|------------|--------------|-----| /// | HDR | RAW-BANDS | HDR | RAW-BANDS | JPEG Thumb | JPEG Preview | ... | /// |-----|-----------|-----|-----------|------------|--------------|-----| #[inline(always)] fn get_data<'a>(&self, mdat: &'a [u8]) -> &'a [u8] { &mdat[self.mdat_hdr_size as usize..] } fn resolution(&self) -> usize { self.image_width * self.image_height } /// Create new codec parameters pub fn new(cmp1: &Cmp1Box) -> Result { const INCR_BIT_TABLE: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0]; if cmp1.n_planes != 4 { return Err(CrxError::General(format!("Plane configration {} is not supported", cmp1.n_planes))); } //let tile_cols: usize = (cmp1.f_width / cmp1.tile_width) as usize; //let tile_rows: usize = (cmp1.f_height / cmp1.tile_height) as usize; // Rounding for unbalanced sizes let tile_cols: usize = cmp1.f_width.div_ceil(cmp1.tile_width) as usize; let tile_rows: usize = cmp1.f_height.div_ceil(cmp1.tile_height) as usize; assert!(tile_cols > 0); assert!(tile_rows > 0); let params = Self { sample_precision: cmp1.n_bits as u8 + INCR_BIT_TABLE[4 * cmp1.enc_type as usize + 2] + 1, image_width: cmp1.f_width as usize, image_height: cmp1.f_height as usize, plane_count: cmp1.n_planes as u8, // 3 bands per level + one last LL // only 1 band for zero levels (uncompressed) subband_count: 3 * cmp1.image_levels as u8 + 1, levels: cmp1.image_levels as usize, n_bits: cmp1.n_bits, median_bits: cmp1.median_bits, enc_type: cmp1.enc_type as u8, tile_cols, tile_rows, tile_width: cmp1.tile_width as usize, tile_height: cmp1.tile_height as usize, mdat_hdr_size: cmp1.mdat_hdr_size, version: cmp1.version, }; if params.tile_cols > 0xff { return Err(CrxError::General(format!("Tile column count {} is not supported", tile_cols))); } if params.tile_rows > 0xff { return Err(CrxError::General(format!("Tile row count {} is not supported", tile_rows))); } //if params.tile_width < 0x16 || params.tile_height < 0x16 || params.plane_width > 0x7FFF || params.plane_height > 0x7FFF { // return Err(CrxError::General(format!("Invalid params for band decoding"))); //} Ok(params) } /// Process tiles and update values pub(super) fn process_tiles(&mut self, tiles: &mut Vec) { let tile_count = tiles.len(); // Update each tile for cur_tile in tiles.iter_mut() { if (cur_tile.id + 1) % self.tile_cols != 0 { // not the last tile in a tile row cur_tile.tile_width = self.tile_width; cur_tile.plane_width = cur_tile.tile_width >> if self.plane_count == 4 { 1 } else { 0 }; if self.tile_cols > 1 { cur_tile.tiles_right = true; if cur_tile.id % self.tile_cols != 0 { // not the first tile in tile row cur_tile.tiles_left = true; } } } else { // last tile in a tile row cur_tile.tile_width = self.image_width - self.tile_width * (self.tile_cols - 1); cur_tile.plane_width = cur_tile.tile_width >> if self.plane_count == 4 { 1 } else { 0 }; if self.tile_cols > 1 { cur_tile.tiles_left = true; } } if (cur_tile.id) < (tile_count - self.tile_cols) { // in first tile row cur_tile.tile_height = self.tile_height; cur_tile.plane_height = cur_tile.tile_height >> if self.plane_count == 4 { 1 } else { 0 }; if self.tile_rows > 1 { cur_tile.tiles_bottom = true; if cur_tile.id >= self.tile_cols { cur_tile.tiles_top = true; } } } else { // non first tile row cur_tile.tile_height = self.image_height - self.tile_height * (self.tile_rows - 1); cur_tile.plane_height = cur_tile.tile_height >> if self.plane_count == 4 { 1 } else { 0 }; if self.tile_rows > 1 { cur_tile.tiles_top = true; } } } // process subbands for tile in tiles { debug!("{}", tile.descriptor_line()); debug!("tile width: {}, tile height: {}", tile.tile_width, tile.tile_height); let mut plane_sizes = 0; self.process_subbands(tile); for plane in &mut tile.planes { debug!("{}", plane.descriptor_line()); let mut band_sizes = 0; for band in &mut plane.subbands { debug!("{}", band.descriptor_line()); assert!(band.subband_size != 0); assert_eq!(band.subband_size % 8, 0); band_sizes += band.subband_size; } assert_eq!(plane.plane_size, band_sizes); plane_sizes += plane.plane_size; } // Tile may contain some extra bytes for quantization // This extra size must be subtracted before comaring to the // sum of plane sizes. assert_eq!(tile.tile_size - tile.extra_size(), plane_sizes); } } /// Process tiles and update values pub(super) fn process_subbands(&self, tile: &mut Tile) { for plane in &mut tile.planes { let mut band_w = tile.plane_width; let mut band_h = tile.plane_height; let mut band_width_ex_coef = 0; let mut band_height_ex_coef = 0; if self.levels > 0 { let row_ex_coef = &EX_COEF_NUM_TBL[0x30 * (self.levels - 1) + 6 * (tile.plane_width & 7)..]; let col_ex_coef = &EX_COEF_NUM_TBL[0x30 * (self.levels - 1) + 6 * (tile.plane_height & 7)..]; for lev in 0..self.levels { let w_odd_pixel = band_w & 1; let h_odd_pixel = band_h & 1; // With each level, width and hight are divided by 2 band_w = (w_odd_pixel + band_w) >> 1; band_h = (h_odd_pixel + band_h) >> 1; let mut w_ex_coef0 = 0; let mut w_ex_coef1 = 0; let mut h_ex_coef0 = 0; let mut h_ex_coef1 = 0; let mut col_start = 0; let mut row_start = 0; if tile.tiles_right { w_ex_coef0 = row_ex_coef[2 * lev]; w_ex_coef1 = row_ex_coef[2 * lev + 1]; } if tile.tiles_left { w_ex_coef0 += 1; col_start = 1; } if tile.tiles_bottom { h_ex_coef0 = col_ex_coef[2 * lev]; h_ex_coef1 = col_ex_coef[2 * lev + 1]; } if tile.tiles_top { h_ex_coef0 += 1; row_start = 1; } // This sets the band width/height values. // Theoretically, it's just always plane_width/2. // But for multi-tile images, the band may contain // extra coefficents on any sides. Assumption is that // these extra coefficents are copied from the other tiles // over to improve compression or/and supress artefacts // on tile boundaries after tiles are assembled to full image. let i = (self.levels - lev) * 3; plane.subbands[i - 0].width = band_w + w_ex_coef0 - w_odd_pixel; plane.subbands[i - 0].height = band_h + h_ex_coef0 - h_odd_pixel; plane.subbands[i - 0].setup_idx(self.version, lev + 1, col_start, w_ex_coef0 - col_start, row_start, h_ex_coef0 - row_start); plane.subbands[i - 1].width = band_w + w_ex_coef1; plane.subbands[i - 1].height = band_h + h_ex_coef0 - h_odd_pixel; plane.subbands[i - 1].setup_idx(self.version, lev + 1, 0, w_ex_coef1, row_start, h_ex_coef0 - row_start); plane.subbands[i - 2].width = band_w + w_ex_coef0 - w_odd_pixel; plane.subbands[i - 2].height = band_h + h_ex_coef1; plane.subbands[i - 2].setup_idx(self.version, lev + 1, col_start, w_ex_coef0 - col_start, 0, h_ex_coef1); } band_width_ex_coef = 0; band_height_ex_coef = 0; if tile.tiles_right { band_width_ex_coef = row_ex_coef[2 * self.levels - 1]; } if tile.tiles_bottom { band_height_ex_coef = col_ex_coef[2 * self.levels - 1]; } } // LL3 band plane.subbands[0].width = band_width_ex_coef + band_w; plane.subbands[0].height = band_height_ex_coef + band_h; if self.levels > 0 { plane.subbands[0].setup_idx(self.version, self.levels, 0, band_width_ex_coef, 0, band_height_ex_coef); } } } } /// Parameter for a single Subband struct BandParam<'mdat> { /// Width of the band in pixels subband_width: usize, /// Height of the band in pixels subband_height: usize, /// Mask for bit rounding (unused) rounded_bits_mask: i32, /// Bits for rounding (unused) #[allow(dead_code)] rounded_bits: i32, /// Current line, starting with 0 cur_line: usize, /// Two lines to decode current line [1] and lookup into prev line [0] /// After each line iteration, the two items are just swapped. line_buf: [Vec; 2], /// Previous K values for Golomb-Rice adaptive decoding /// This buffer is only used for non-LL bands line_k: Vec, /// Current position line_pos: usize, /// Length of the current line (unused, but good to keep) #[allow(dead_code)] line_len: usize, /// Runlength control parameter s_param: u32, /// Q parameter for QP (see Subband for more details) /// The MDAT header contains a Q parameter which should be constant. /// But for some (unused) decoding routines, the Q param needs to be updated, /// so we need a mutable copy in the BandParam. pub q_param: u32, /// Unsure what partial means... supports_partial: bool, /// Rice decoder, provides bit access to the MDAT stream rice: RiceDecoder<'mdat>, } impl<'mdat> BandParam<'mdat> { /// Get coefficent `a` from line buffer /// c b d (buf 0) /// a x n (buf 1) fn coeff_a(&self) -> i32 { self.line_buf[1][self.line_pos - 1] } /// Get coefficent `b` from line buffer /// c b d (buf 0) /// a x n (buf 1) fn coeff_b(&self) -> i32 { self.line_buf[0][self.line_pos] } /// Get coefficent `c` from line buffer /// c b d (buf 0) /// a x n (buf 1) fn coeff_c(&self) -> i32 { self.line_buf[0][self.line_pos - 1] } /// Get coefficent `d` from line buffer /// c b d (buf 0) /// a x n (buf 1) fn coeff_d(&self) -> i32 { self.line_buf[0][self.line_pos + 1] } /// Get decoded buffer fn decoded_buf(&self) -> &[i32] { // Skip first and last extra pixel &self.line_buf[1][1..1 + self.subband_width] } /// Get decoded buffer fn decoded_buf_mut(&mut self) -> &mut [i32] { // Skip first and last extra pixel &mut self.line_buf[1][1..1 + self.subband_width] } } /// Decompress a MDAT image buffer by given CMP1 box parameters pub fn decompress_crx_image(buf: &[u8], cmp1: &Cmp1Box) -> Result> { let image = CodecParams::new(cmp1)?; debug!("CRX codec parameter: {:?}", image); image.decode(buf) } rawler-0.7.1/src/decompressors/crx/rice.rs000064400000000000000000000065671046102023000167060ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher // Original Crx decoder crx.cpp was written by Alexey Danilchenko for libraw. // Rewritten in Rust by Daniel Vogelbacher, based on logic found in // crx.cpp and documentation done by Laurent Clévy (https://github.com/lclevy/canon_cr3). use super::BitPump; use super::Result; use bitstream_io::BitRead; /// Adaptive Golomb-Rice decoder pub(super) struct RiceDecoder<'mdat> { /// Bitstream from MDAT bitpump: BitPump<'mdat>, k_param: u32, } impl<'mdat> RiceDecoder<'mdat> { /// Create new decoder for given bit pump pub(super) fn new(bitpump: BitPump<'mdat>) -> Self { Self { bitpump, k_param: 0 } } /// Get current K parameter #[inline(always)] pub(super) fn k(&self) -> u32 { self.k_param } /// Set K parameter #[inline(always)] pub(super) fn set_k(&mut self, k: u32) { self.k_param = k; } /// Return the positive number of 0-bits in bitstream. /// All 0-bits are consumed. #[inline(always)] pub(super) fn bitstream_zeros(&mut self) -> Result { Ok(self.bitpump.read_unary::<1>()?) } /// Return the requested bits // All bits are consumed. // The maximum number of bits are 32 #[inline(always)] pub(super) fn bitstream_get_bits(&mut self, bits: u32) -> Result { debug_assert!(bits <= 32); Ok(self.bitpump.read_var(bits)?) } /// Golomb-Rice decoding /// https://w3.ual.es/~vruiz/Docencia/Apuntes/Coding/Text/03-symbol_encoding/09-Golomb_coding/index.html /// escape and esc_bits are used to interrupt decoding when /// a value is not encoded using Golomb-Rice but directly encoded /// by esc_bits bits. fn rice_decode(&mut self, escape: u32, esc_bits: u32) -> Result { // q, quotient = n//m, with m = 2^k (Rice coding) let prefix = self.bitstream_zeros()?; if prefix >= escape { // n Ok(self.bitstream_get_bits(esc_bits)?) } else if self.k_param > 0 { // Golomb-Rice coding : n = q * 2^k + r, with r is next k bits. r is n - (q*2^k) Ok((prefix << self.k_param) | self.bitstream_get_bits(self.k_param)?) } else { // q Ok(prefix) } } /// Adaptive Golomb-Rice decoding, by adapting k value /// Sometimes adapting is based on the next coefficent (n) instead /// of current (x) coefficent. So you can disable it with `adapt_k` /// and update k later. pub(super) fn adaptive_rice_decode(&mut self, adapt_k: bool, escape: u32, esc_bits: u32, k_max: u32) -> Result { let val = self.rice_decode(escape, esc_bits)?; if adapt_k { self.k_param = Self::predict_k_param_max(self.k_param, val, k_max); } Ok(val) } /// Update current K parameter pub(super) fn update_k_param(&mut self, bit_code: u32, k_max: u32) { self.k_param = Self::predict_k_param_max(self.k_param, bit_code, k_max); } /// Predict K parameter with maximum constraint /// Golomb-Rice becomes more efficient when used with an adaptive /// K parameter. This is done by predicting the next K value for the /// next sample value. fn predict_k_param_max(prev_k: u32, value: u32, k_max: u32) -> u32 { let mut new_k = prev_k; if value >> prev_k > 2 { new_k += 1; } if value >> prev_k > 5 { new_k += 1; } if value < ((1 << prev_k) >> 1) { new_k -= 1; } if k_max > 0 { std::cmp::min(new_k, k_max) } else { new_k } } } rawler-0.7.1/src/decompressors/crx/runlength.rs000064400000000000000000000050611046102023000177560ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher // Original Crx decoder crx.cpp was written by Alexey Danilchenko for libraw. // Rewritten in Rust by Daniel Vogelbacher, based on logic found in // crx.cpp and documentation done by Laurent Clévy (https://github.com/lclevy/canon_cr3). use super::{BandParam, CodecParams, CrxError, Result}; /// See ITU T.78 Section A.2.1 Step 3 /// Initialise the variables for the run mode: RUNindex=0 and J[0..31] #[rustfmt::skip] const J: [u32; 32] = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15]; /// Precalculated values for (1 << J[0..31]) #[rustfmt::skip] const JSHIFT: [u32; 32] = [1 << J[0], 1 << J[1], 1 << J[2], 1 << J[3], 1 << J[4], 1 << J[5], 1 << J[6], 1 << J[7], 1 << J[8], 1 << J[9], 1 << J[10], 1 << J[11], 1 << J[12], 1 << J[13], 1 << J[14], 1 << J[15], 1 << J[16], 1 << J[17], 1 << J[18], 1 << J[19], 1 << J[20], 1 << J[21], 1 << J[22], 1 << J[23], 1 << J[24], 1 << J[25], 1 << J[26], 1 << J[27], 1 << J[28], 1 << J[29], 1 << J[30], 1 << J[31]]; impl CodecParams { /// Get symbol run count for run-length decoding /// See T.87 Section A.7.1.2 Run-length coding pub(super) fn symbol_run_count(&self, param: &mut BandParam, remaining: u32) -> Result { debug_assert!(remaining > 1); let mut run_cnt: u32 = 1; // See T.87 A.7.1.2 Code segment A.15 // Bitstream 111110... means 5 lookups into J to decode final RUNcnt while run_cnt != remaining && param.rice.bitstream_get_bits(1)? == 1 { // JS is precalculated (1 << J[RUNindex]) run_cnt += JSHIFT[param.s_param as usize]; if run_cnt > remaining { run_cnt = remaining; break; } param.s_param = std::cmp::min(param.s_param + 1, 31); } // See T.87 A.7.1.2 Code segment A.16 if run_cnt < remaining { if J[param.s_param as usize] > 0 { run_cnt += param.rice.bitstream_get_bits(J[param.s_param as usize])?; } param.s_param = param.s_param.saturating_sub(1); // prevent underflow if run_cnt > remaining { //println!("run_cnt: {}, remaining: {}", run_cnt, remaining); return Err(CrxError::General("Crx decoder error while decoding line".to_string())); } } Ok(run_cnt) } } rawler-0.7.1/src/decompressors/deflate.rs000064400000000000000000000045711046102023000165650ustar 00000000000000use std::io::Read; use libflate::zlib::Decoder; use crate::{ bits::{Binary16, Binary24, Binary32, Endian, FloatingPointParameters, extend_binary_floating_point}, decompressors::{Decompressor, LineIteratorMut}, }; #[derive(Debug)] pub struct DeflateDecompressor { pred_factor: usize, bps: u32, } impl DeflateDecompressor { pub fn new(cpp: usize, predictor: u16, bps: u32, _endian: Endian) -> Self { let pred_factor = cpp * match predictor { 3 => 1, 34894 => 2, 34895 => 4, _ => todo!(), }; Self { pred_factor, bps } } } fn decode_delta_bytes(src: &mut [u8], factor: usize) { for col in factor..src.len() { src[col] = src[col].wrapping_add(src[col - factor]); } } fn decode_fp_delta_row(line: &mut [f32], row: &[u8], line_width: usize) { for (col, pix) in line.iter_mut().enumerate() { let mut tmp = [0; 4]; assert!(NARROW::STORAGE_BYTES <= tmp.len()); for c in 0..NARROW::STORAGE_BYTES { tmp[c] = row[col + c * line_width]; } let value = u32::from_be_bytes(tmp) >> (u32::BITS as usize - NARROW::STORAGE_WIDTH); *pix = f32::from_bits(extend_binary_floating_point::(value)); } } impl<'a> Decompressor<'a, f32> for DeflateDecompressor { fn decompress(&self, src: &[u8], skip_rows: usize, lines: impl LineIteratorMut<'a, f32>, line_width: usize) -> std::result::Result<(), String> { //eprintln!("Deflate: {:?}", self); let mut decoder = Decoder::new(src).unwrap(); let mut decoded_data = Vec::new(); decoder.read_to_end(&mut decoded_data).unwrap(); let bytesps = self.bps as usize / 8; assert!(bytesps >= 2 && bytesps <= 4); assert_eq!(decoded_data.len(), bytesps * line_width * lines.len()); for (line, row) in lines.zip(decoded_data.chunks_exact_mut(bytesps as usize * line_width)).skip(skip_rows) { assert_eq!(line.len(), line_width); decode_delta_bytes(row, self.pred_factor); match self.bps { 16 => decode_fp_delta_row::(line, row, line_width), 24 => decode_fp_delta_row::(line, row, line_width), 32 => decode_fp_delta_row::(line, row, line_width), _ => unimplemented!(), } } Ok(()) //let packed = PackedDecompressor::new(self.bps, self.endian); //packed.decompress(&decoded_data, skip_rows, lines, line_width) } } rawler-0.7.1/src/decompressors/jpeg.rs000064400000000000000000000034001046102023000160740ustar 00000000000000use crate::decompressors::ljpeg::LjpegDecompressor; use crate::decompressors::{Decompressor, LineIteratorMut}; use crate::pixarray::PixU16; pub struct LJpegDecompressor {} impl LJpegDecompressor { pub fn new() -> Self { Self {} } } impl<'a> Decompressor<'a, u16> for LJpegDecompressor { fn decompress(&self, src: &[u8], skip_rows: usize, lines: impl LineIteratorMut<'a, u16>, line_width: usize) -> std::result::Result<(), String> { let decompressor = LjpegDecompressor::new(src)?; let mut pixbuf = PixU16::new(decompressor.width(), decompressor.height()); decompressor.decode(pixbuf.pixels_mut(), 0, decompressor.width(), decompressor.width(), decompressor.height(), false)?; for (dst, src) in lines.zip(pixbuf.pixels().chunks_exact(line_width).skip(skip_rows)) { dst.copy_from_slice(src); } Ok(()) } fn tile_optimized(&self) -> bool { true } } pub struct JpegDecompressor {} impl JpegDecompressor { pub fn new() -> Self { Self {} } } impl<'a> Decompressor<'a, u16> for JpegDecompressor { fn decompress(&self, src: &[u8], skip_rows: usize, lines: impl LineIteratorMut<'a, u16>, line_width: usize) -> std::result::Result<(), String> { let img = image::load_from_memory_with_format(src, image::ImageFormat::Jpeg).map_err(|err| format!("Lossy JPEG decompression failed: {:?}", err))?; match img { image::DynamicImage::ImageRgb8(image_buffer) => { for (dst, src) in lines.zip(image_buffer.chunks_exact(line_width).skip(skip_rows)) { for (dst, src) in dst.iter_mut().zip(src.iter()) { *dst = *src as u16; // Only change storage format, you MUST NOT scale up! } } } _ => todo!(), } Ok(()) } fn tile_optimized(&self) -> bool { true } } rawler-0.7.1/src/decompressors/jpegxl.rs000064400000000000000000000052351046102023000164500ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2025 Daniel Vogelbacher use jxl_oxide::JxlImage; use crate::decompressors::{Decompressor, LineIteratorMut}; pub struct JpegXLDecompressor { bps: u32, } impl JpegXLDecompressor { pub fn new(bps: u32) -> Self { Self { bps } } } impl<'a> Decompressor<'a, u16> for JpegXLDecompressor { fn decompress(&self, src: &[u8], mut skip_rows: usize, lines: impl LineIteratorMut<'a, u16>, line_width: usize) -> std::result::Result<(), String> { let image = JxlImage::builder() .read(src) .map_err(|err| format!("Failed to read JPEG-XL image: {:?}", err))?; if let Some(header) = image.frame_header(0) { if header.bit_depth.bits_per_sample() != 8 && header.bit_depth.bits_per_sample() != 16 { // jxl_oxide scales the pixels into full range of storage type. // If we get e.g. 12 bit compressed data, output is scaled to 16 bit. // This breaks blacklevel scaling. We need to scale back to given bps (from TIFF). unimplemented!("JPEG-XL bit-depth {} not supported yet", header.bit_depth.bits_per_sample()); } //eprintln!("JPEG-XL Bit-Depth: {:?}", header.bit_depth); } let frame = image.render_frame(0).map_err(|err| format!("Failed to render JPEG-XL image: {:?}", err))?; let mut stream = frame.stream_no_alpha(); match self.bps { 8 => { let mut tmp = vec![0_u8; line_width]; for line in lines.skip(skip_rows) { while skip_rows > 0 { let written = stream.write_to_buffer(&mut tmp); assert_eq!(line.len(), written); skip_rows -= 1; } let written = stream.write_to_buffer(&mut tmp); assert_eq!(line.len(), written); for (p, x) in line.iter_mut().zip(tmp.iter()) { *p = *x as u16; // Only change storage format, you MUST NOT scale up! } } } 9..=16 => { for line in lines.skip(skip_rows) { while skip_rows > 0 { let written = stream.write_to_buffer(line); assert_eq!(line.len(), written); skip_rows -= 1; } let written = stream.write_to_buffer(line); assert_eq!(line.len(), written); } } _ => unimplemented!(), } /* let all_ch = frame.image_all_channels(); let pixbuf = all_ch.buf(); for (line, buf) in lines.zip(pixbuf.chunks_exact(line_width).skip(skip_rows)) { for (p, f) in line.iter_mut().zip(buf.iter()) { //debug_assert!(*f <= (1.0 + f32::EPSILON)); // *p = (f * u16::MAX as f32) as u16; // *p = *f as u16; } } */ Ok(()) } } rawler-0.7.1/src/decompressors/ljpeg/decompressors.rs000064400000000000000000000327541046102023000211560ustar 00000000000000use super::LjpegDecompressor; use super::huffman::*; use crate::pumps::BitPumpJPEG; use crate::pumps::BitPumpMSB32; /// Decode the ljpeg stream to `out`. /// `x` is the start of output in `out`, usually 0. /// `stripwidth` is the count of pixels of a single output strip (may /// be larger than width if each row has padding bytes). /// `width` is the output image width in pixels. #[allow(clippy::let_and_return)] pub fn decode_ljpeg(ljpeg: &LjpegDecompressor, out: &mut [u16], x: usize, stripwidth: usize, width: usize, height: usize) -> Result<(), String> { let ncomp: usize = ljpeg.components(); if ljpeg.sof.width * ncomp < width || ljpeg.sof.height < height { return Err(format!( "ljpeg: trying to decode {}x{} into {}x{}", ljpeg.sof.width, ljpeg.sof.height, width, height )); } let htable = |index: usize| -> &HuffTable { &ljpeg.dhts[ljpeg.sof.components[index].dc_tbl_num] }; let mut pump = BitPumpJPEG::new(ljpeg.buffer); let base_prediction = 1 << (ljpeg.sof.precision - ljpeg.point_transform - 1); // initialize first pixel components for c in 0..ncomp { out[x + c] = (base_prediction + htable(c).huff_decode(&mut pump)?) as u16; } let skip_x = ljpeg.sof.width - width / ncomp; for row in 0..height { let startcol = if row == 0 { x + ncomp } else { x }; // skip first pixel in first row for col in (startcol..(width + x)).step_by(ncomp) { for c in 0..ncomp { let p: i32 = if col == x { // At start of line predictor starts with start of previous line out[(row - 1) * stripwidth + x + c] as i32 } else { // All other cases use the two previous pixels in the same line match (row, ljpeg.predictor) { (row @ 0, _) | (row, 1) => { let a = out[row * stripwidth + (col - ncomp) + c] as i32; a } (row, 2) => { let b = out[(row - 1) * stripwidth + col + c] as i32; b } (row, 3) => { let c = out[(row - 1) * stripwidth + (col - ncomp) + c] as i32; c } (row, 4) => { let a = out[row * stripwidth + (col - ncomp) + c] as i32; let b = out[(row - 1) * stripwidth + col + c] as i32; let c = out[(row - 1) * stripwidth + (col - ncomp) + c] as i32; a + b - c } (row, 5) => { let a = out[row * stripwidth + (col - ncomp) + c] as i32; let b = out[(row - 1) * stripwidth + col + c] as i32; let c = out[(row - 1) * stripwidth + (col - ncomp) + c] as i32; a + ((b - c) >> 1) } (row, 6) => { let a = out[row * stripwidth + (col - ncomp) + c] as i32; let b = out[(row - 1) * stripwidth + col + c] as i32; let c = out[(row - 1) * stripwidth + (col - ncomp) + c] as i32; b + ((a - c) >> 1) } (row, 7) => { let a = out[row * stripwidth + (col - ncomp) + c] as i32; let b = out[(row - 1) * stripwidth + col + c] as i32; (a + b) >> 1 // Adobe DNG SDK uses int32 and shifts, so we will do, too. } _ => { panic!("Unsupported prediction in LJPEG") } } }; let diff = htable(c).huff_decode(&mut pump)?; out[row * stripwidth + col + c] = (p + diff) as u16; } } for _ in 0..skip_x { for c in 0..ncomp { // Skip extra encoded differences if the ljpeg frame is wider than the output htable(c).huff_decode(&mut pump)?; } } } Ok(()) } fn set_yuv_420(out: &mut [u16], row: usize, col: usize, width: usize, y1: i32, y2: i32, y3: i32, y4: i32, cb: i32, cr: i32) { let pix1 = row * width + col; let pix2 = pix1 + 3; let pix3 = (row + 1) * width + col; let pix4 = pix3 + 3; debug_assert!(!y1.is_negative()); debug_assert!(!y2.is_negative()); debug_assert!(!y3.is_negative()); debug_assert!(!y4.is_negative()); debug_assert!(!cb.is_negative()); debug_assert!(!cr.is_negative()); out[pix1 + 0] = y1 as u16; out[pix1 + 1] = cb as u16; out[pix1 + 2] = cr as u16; out[pix2 + 0] = y2 as u16; out[pix2 + 1] = cb as u16; out[pix2 + 2] = cr as u16; out[pix3 + 0] = y3 as u16; out[pix3 + 1] = cb as u16; out[pix3 + 2] = cr as u16; out[pix4 + 0] = y4 as u16; out[pix4 + 1] = cb as u16; out[pix4 + 2] = cr as u16; } pub fn decode_sony_ljpeg_420(ljpeg: &LjpegDecompressor, out: &mut [u16], width: usize, height: usize) -> Result<(), String> { if ljpeg.sof.width * 3 != width || ljpeg.sof.height != height { return Err(format!( "ljpeg: trying to decode {}x{} into {}x{}", ljpeg.sof.width * 3, ljpeg.sof.height, width, height )); } debug_assert_eq!(width % 2, 0); debug_assert_eq!(width % 6, 0); // Ensure we have enough samples for .step_by(6) debug_assert_eq!(height % 2, 0); let htable1 = &ljpeg.dhts[ljpeg.sof.components[0].dc_tbl_num]; let htable2 = &ljpeg.dhts[ljpeg.sof.components[1].dc_tbl_num]; let htable3 = &ljpeg.dhts[ljpeg.sof.components[2].dc_tbl_num]; let mut pump = BitPumpJPEG::new(ljpeg.buffer); let base_prediction = 1 << (ljpeg.sof.precision - ljpeg.point_transform - 1); let y1 = base_prediction + htable1.huff_decode(&mut pump)?; let y2 = y1 + htable1.huff_decode(&mut pump)?; let y3 = y1 + htable1.huff_decode(&mut pump)?; // y1 is sample above current row, column 0 let y4 = y3 + htable1.huff_decode(&mut pump)?; let cb = base_prediction + htable2.huff_decode(&mut pump)?; let cr = base_prediction + htable3.huff_decode(&mut pump)?; set_yuv_420(out, 0, 0, width, y1, y2, y3, y4, cb, cr); // first column|second column // | Y, Cb, Cr | py1, pcb, pcr | y1, cb, cr | y2, cb, cr | <- first row // | Y, Cb, Cr | py3, pcb, pcr | y3, cb, cr | y4, cb, cr | <- second row for row in (0..height).step_by(2) { let startcol = if row == 0 { 6 } else { 0 }; for col in (startcol..width).step_by(6) { // Get previous values (for adding huff differnce) let (py1, py3, pcb, pcr) = if col == 0 { // This is possible broken 4:2:0 encoding by Sony, as the new row // has to use the sample from the second-previous row instead of the // first-previous row. let pos = (row - 2) * width; // reference is previous block, first row, first column (out[pos], 0, out[pos + 1], out[pos + 2]) // py3 is not required, instead py3 references to y1 on col == 0 } else { let pos1 = row * width + col - 3; // reference is current block, first row, second column let pos3 = (row + 1) * width + col - 3; // reference current block, second row, second column (out[pos1], out[pos3], out[pos1 + 1], out[pos1 + 2]) }; // Calculate 4 Y samples, 1 Cb sample, 1 Cr sample let y1 = (py1 as i32) + htable1.huff_decode(&mut pump)?; let y2 = (y1 as i32) + htable1.huff_decode(&mut pump)?; let y3 = if col == 0 { // y1 is sample above current row, column 0 (y1 as i32) + htable1.huff_decode(&mut pump)? } else { // py3 is previous sample in same line (py3 as i32) + htable1.huff_decode(&mut pump)? }; let y4 = (y3 as i32) + htable1.huff_decode(&mut pump)?; // Cb and Cr components let cb = (pcb as i32) + htable2.huff_decode(&mut pump)?; let cr = (pcr as i32) + htable3.huff_decode(&mut pump)?; set_yuv_420(out, row, col, width, y1, y2, y3, y4, cb, cr); } } Ok(()) } pub fn decode_ljpeg_420(ljpeg: &LjpegDecompressor, out: &mut [u16], width: usize, height: usize) -> Result<(), String> { if ljpeg.sof.width * 3 != width || ljpeg.sof.height != height { return Err(format!( "ljpeg: trying to decode {}x{} into {}x{}", ljpeg.sof.width * 3, ljpeg.sof.height, width, height )); } debug_assert_eq!(width % 2, 0); debug_assert_eq!(width % 6, 0); // Ensure we have enough samples for .step_by(6) debug_assert_eq!(height % 2, 0); let htable1 = &ljpeg.dhts[ljpeg.sof.components[0].dc_tbl_num]; let htable2 = &ljpeg.dhts[ljpeg.sof.components[1].dc_tbl_num]; let htable3 = &ljpeg.dhts[ljpeg.sof.components[2].dc_tbl_num]; let mut pump = BitPumpJPEG::new(ljpeg.buffer); let base_prediction = 1 << (ljpeg.sof.precision - ljpeg.point_transform - 1); let y1 = base_prediction + htable1.huff_decode(&mut pump)?; let y2 = y1 + htable1.huff_decode(&mut pump)?; let y3 = y2 + htable1.huff_decode(&mut pump)?; let y4 = y3 + htable1.huff_decode(&mut pump)?; let cb = base_prediction + htable2.huff_decode(&mut pump)?; let cr = base_prediction + htable3.huff_decode(&mut pump)?; set_yuv_420(out, 0, 0, width, y1, y2, y3, y4, cb, cr); for row in (0..height).step_by(2) { let startcol = if row == 0 { 6 } else { 0 }; for col in (startcol..width).step_by(6) { let pos = if col == 0 { // At start of line predictor starts with first pixel of start of previous line (row - 2) * width } else { // All other cases use the last pixel in the same two lines (row + 1) * width + col - 3 }; let (py, pcb, pcr) = (out[pos], out[pos + 1], out[pos + 2]); let y1 = (py as i32) + htable1.huff_decode(&mut pump)?; let y2 = (y1 as i32) + htable1.huff_decode(&mut pump)?; let y3 = (y2 as i32) + htable1.huff_decode(&mut pump)?; let y4 = (y3 as i32) + htable1.huff_decode(&mut pump)?; let cb = (pcb as i32) + htable2.huff_decode(&mut pump)?; let cr = (pcr as i32) + htable3.huff_decode(&mut pump)?; set_yuv_420(out, row, col, width, y1, y2, y3, y4, cb, cr); } } Ok(()) } fn set_yuv_422(out: &mut [u16], row: usize, col: usize, width: usize, y1: i32, y2: i32, cb: i32, cr: i32) { let pix1 = row * width + col; let pix2 = pix1 + 3; debug_assert!(!y1.is_negative()); debug_assert!(!y2.is_negative()); debug_assert!(!cb.is_negative()); debug_assert!(!cr.is_negative()); out[pix1 + 0] = y1 as u16; out[pix1 + 1] = cb as u16; out[pix1 + 2] = cr as u16; out[pix2 + 0] = y2 as u16; out[pix2 + 1] = cb as u16; out[pix2 + 2] = cr as u16; } pub fn decode_ljpeg_422(ljpeg: &LjpegDecompressor, out: &mut [u16], width: usize, height: usize) -> Result<(), String> { if ljpeg.sof.width * 3 != width || ljpeg.sof.height != height { return Err(format!( "ljpeg: trying to decode {}x{} into {}x{}", ljpeg.sof.width * 3, ljpeg.sof.height, width, height )); } let htable1 = &ljpeg.dhts[ljpeg.sof.components[0].dc_tbl_num]; let htable2 = &ljpeg.dhts[ljpeg.sof.components[1].dc_tbl_num]; let htable3 = &ljpeg.dhts[ljpeg.sof.components[2].dc_tbl_num]; let mut pump = BitPumpJPEG::new(ljpeg.buffer); let base_prediction = 1 << (ljpeg.sof.precision - ljpeg.point_transform - 1); let y1 = base_prediction + htable1.huff_decode(&mut pump)?; let y2 = y1 + htable1.huff_decode(&mut pump)?; let cb = base_prediction + htable2.huff_decode(&mut pump)?; let cr = base_prediction + htable3.huff_decode(&mut pump)?; set_yuv_422(out, 0, 0, width, y1, y2, cb, cr); for row in 0..height { let startcol = if row == 0 { 6 } else { 0 }; for col in (startcol..width).step_by(6) { let pos = if col == 0 { // At start of line predictor starts with first pixel of start of previous line (row - 1) * width } else { // All other cases use the last pixel in the same two lines row * width + col - 3 }; let (py, pcb, pcr) = (out[pos], out[pos + 1], out[pos + 2]); let y1 = (py as i32) + htable1.huff_decode(&mut pump)?; let y2 = (y1 as i32) + htable1.huff_decode(&mut pump)?; let cb = (pcb as i32) + htable2.huff_decode(&mut pump)?; let cr = (pcr as i32) + htable3.huff_decode(&mut pump)?; set_yuv_422(out, row, col, width, y1, y2, cb, cr); } } Ok(()) } pub fn decode_hasselblad(ljpeg: &LjpegDecompressor, out: &mut [u16], width: usize) -> Result<(), String> { // Pixels are packed two at a time, not like LJPEG: // [p1_length_as_huffman][p2_length_as_huffman][p0_diff_with_length][p1_diff_with_length]|NEXT PIXELS let mut pump = BitPumpMSB32::new(ljpeg.buffer); let htable = &ljpeg.dhts[ljpeg.sof.components[0].dc_tbl_num]; for line in out.chunks_exact_mut(width) { let mut p1: i32 = 0x8000; let mut p2: i32 = 0x8000; for o in line.chunks_exact_mut(2) { let len1 = htable.huff_len(&mut pump); let len2 = htable.huff_len(&mut pump); p1 += htable.huff_diff(&mut pump, len1); p2 += htable.huff_diff(&mut pump, len2); o[0] = p1 as u16; o[1] = p2 as u16; } } Ok(()) } pub fn decode_leaf_strip(src: &[u8], out: &mut [u16], width: usize, height: usize, htable1: &HuffTable, htable2: &HuffTable, bpred: i32) -> Result<(), String> { let mut pump = BitPumpJPEG::new(src); out[0] = (bpred + htable1.huff_decode(&mut pump)?) as u16; out[1] = (bpred + htable2.huff_decode(&mut pump)?) as u16; for row in 0..height { let startcol = if row == 0 { 2 } else { 0 }; for col in (startcol..width).step_by(2) { let pos = if col == 0 { // At start of line predictor starts with start of previous line (row - 1) * width } else { // All other cases use the two previous pixels in the same line row * width + col - 2 }; let (p1, p2) = (out[pos], out[pos + 1]); let diff1 = htable1.huff_decode(&mut pump)?; let diff2 = htable2.huff_decode(&mut pump)?; out[row * width + col] = ((p1 as i32) + diff1) as u16; out[row * width + col + 1] = ((p2 as i32) + diff2) as u16; } } Ok(()) } rawler-0.7.1/src/decompressors/ljpeg/huffman.rs000064400000000000000000000152771046102023000177130ustar 00000000000000use crate::pumps::BitPump; use std::fmt; const DECODE_CACHE_BITS: u32 = 13; pub struct HuffTable { // These two fields directly represent the contents of a JPEG DHT marker pub bits: [u32; 17], pub huffval: [u32; 256], // Represent the weird shifts that are needed for some NEF files pub shiftval: [u32; 256], // Enable the workaround for 16 bit decodes in DNG that need to consume those // bits instead of the value being implied pub dng_bug: bool, // In CRW we only use the len code so the cache is not needed pub disable_cache: bool, // The remaining fields are computed from the above to allow more // efficient coding and decoding and thus private // The max number of bits in a huffman code and the table that converts those // bits into how many bits to consume and the decoded length and shift pub nbits: u32, // Fast lookup for self.peek_bits(nbits). This contains the huffval // for all combinations of + // This is: (bits, len, shift) where: // bits: the actual count of bits to represent the code // len: extra bits for difference encoding // shift: special shift value for some Nikon models // // The huffman code (e.g. 0b1111111110) is the vector index inself, extended // with all possible extra bit values. For example: // nbits = 4 // code = 0b110 // bits: 3 // len: 1 // Then the array contains the values: // [0b110 0] = (3, 1, 0) // [0b110 1] = (3, 1, 0) pub hufftable: Vec<(u8, u8, u8)>, // A pregenerated table that goes straight to decoding a diff without first // finding a length, fetching bits, and sign extending them. The table is // sized by DECODE_CACHE_BITS and can have 99%+ hit rate with 13 bits decodecache: [Option<(u8, i16)>; 1 << DECODE_CACHE_BITS], initialized: bool, } struct MockPump { bits: u64, nbits: u32, } impl MockPump { pub fn empty() -> Self { MockPump { bits: 0, nbits: 0 } } pub fn set(&mut self, bits: u32, nbits: u32) { self.bits = (bits as u64) << 32; self.nbits = nbits + 32; } pub fn validbits(&self) -> i32 { self.nbits as i32 - 32 } } impl BitPump for MockPump { fn peek_bits(&mut self, num: u32) -> u32 { (self.bits >> (self.nbits - num)) as u32 } fn consume_bits(&mut self, num: u32) { self.nbits -= num; self.bits &= (1 << self.nbits) - 1; } } impl HuffTable { pub fn empty() -> HuffTable { HuffTable { bits: [0; 17], huffval: [0; 256], shiftval: [0; 256], dng_bug: false, disable_cache: false, nbits: 0, hufftable: Vec::new(), decodecache: [None; 1 << DECODE_CACHE_BITS], initialized: false, } } pub fn new(bits: [u32; 17], huffval: [u32; 256], dng_bug: bool) -> Result { let mut tbl = HuffTable { bits, huffval, shiftval: [0; 256], dng_bug, disable_cache: false, nbits: 0, hufftable: Vec::new(), decodecache: [None; 1 << DECODE_CACHE_BITS], initialized: false, }; tbl.initialize()?; Ok(tbl) } pub fn initialize(&mut self) -> Result<(), String> { // Find out the max code length and allocate a table with that size self.nbits = 16; for i in 0..16 { if self.bits[16 - i] != 0 { break; } self.nbits -= 1; } self.hufftable = vec![(0, 0, 0); 1 << self.nbits]; // Fill in the table itself let mut h = 0; let mut pos = 0; for len in 0..self.nbits { // Fill for each number of huffman codes of length i (=len+1) for _ in 0..self.bits[len as usize + 1] { // Fill for all possible extra bits, payload is always the same for fast lookup bases on peek_bits(self.nbits) for _ in 0..(1 << (self.nbits - len - 1)) { self.hufftable[h] = (len as u8 + 1, self.huffval[pos] as u8, self.shiftval[pos] as u8); h += 1; } pos += 1; } } // Create the decode cache by running the slow code over all the possible // values DECODE_CACHE_BITS wide if !self.disable_cache { let mut pump = MockPump::empty(); let mut i = 0; loop { pump.set(i, DECODE_CACHE_BITS); let (bits, decode) = self.huff_decode_slow(&mut pump); if pump.validbits() >= 0 { self.decodecache[i as usize] = Some((bits, decode as i16)); } i += 1; if i >= 1 << DECODE_CACHE_BITS { break; } } } self.initialized = true; Ok(()) } #[inline(always)] pub fn huff_decode(&self, pump: &mut dyn BitPump) -> Result { let code = pump.peek_bits(DECODE_CACHE_BITS) as usize; if let Some((bits, decode)) = self.decodecache[code] { match (decode, self.dng_bug) { // Special case: for -32768 no SSSS bits are stored (-32768, false) => { debug_assert!(bits > 16); pump.consume_bits(bits as u32 - 16); } _ => { pump.consume_bits(bits as u32); } } Ok(decode as i32) } else { let decode = self.huff_decode_slow(pump); Ok(decode.1) } } #[inline(always)] pub fn huff_decode_slow(&self, pump: &mut dyn BitPump) -> (u8, i32) { let len = self.huff_len(pump); (len.0 + len.1, self.huff_diff(pump, len)) } #[inline(always)] pub fn huff_len(&self, pump: &mut dyn BitPump) -> (u8, u8, u8) { let code = pump.peek_bits(self.nbits) as usize; let (bits, len, shift) = self.hufftable[code]; pump.consume_bits(bits as u32); (bits, len, shift) } #[inline(always)] pub fn huff_get_bits(&self, pump: &mut dyn BitPump) -> u32 { let code = pump.peek_bits(self.nbits) as usize; let (bits, len, _) = self.hufftable[code]; pump.consume_bits(bits as u32); len as u32 } #[inline(always)] pub fn huff_diff(&self, pump: &mut dyn BitPump, input: (u8, u8, u8)) -> i32 { let (_, len, shift) = input; match len { 0 => 0, 16 => { if self.dng_bug { pump.get_bits(16); // consume can fail because we haven't peeked yet } -32768 } len => { // decode the difference and extend sign bit let fulllen: i32 = len as i32 + shift as i32; let shift: i32 = shift as i32; let bits = pump.get_bits(len as u32) as i32; let mut diff: i32 = ((bits << 1) + 1) << shift >> 1; if (diff & (1 << (fulllen - 1))) == 0 { diff -= (1 << fulllen) - ((shift == 0) as i32); } diff } } } } impl fmt::Debug for HuffTable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.initialized { write!(f, "HuffTable {{ bits: {:?} huffval: {:?} }}", self.bits, &self.huffval[..]) } else { write!(f, "HuffTable {{ uninitialized }}") } } } rawler-0.7.1/src/decompressors/ljpeg/mod.rs000064400000000000000000000263761046102023000170500ustar 00000000000000use crate::bits::Endian; use crate::decoders::decode_threaded_multiline; use crate::decompressors::ljpeg::decompressors::*; use crate::decompressors::ljpeg::huffman::*; use crate::pixarray::PixU16; use crate::pumps::ByteStream; mod decompressors; pub mod huffman; enum Marker { Stuff = 0x00, SOF3 = 0xc3, // lossless DHT = 0xc4, // huffman tables SOI = 0xd8, // start of image EOI = 0xd9, // end of image SOS = 0xda, // start of scan DQT = 0xdb, // quantization tables Fill = 0xff, } fn m(marker: Marker) -> u8 { marker as u8 } #[derive(Debug, Copy, Clone)] struct JpegComponentInfo { // These values are fixed over the whole image, read from the SOF marker. id: usize, // identifier for this component (0..255) #[allow(dead_code)] index: usize, // its index in SOF or cPtr->compInfo[] // Huffman table selector (0..3). The value may vary between scans. // It is read from the SOS marker. dc_tbl_num: usize, super_h: usize, // Horizontal Supersampling super_v: usize, // Vertical Supersampling } #[derive(Debug, Clone)] struct SOFInfo { width: usize, height: usize, cps: usize, precision: usize, components: Vec, csfix: bool, } impl SOFInfo { fn empty(csfix: bool) -> SOFInfo { SOFInfo { width: 0, height: 0, cps: 0, precision: 0, components: Vec::new(), csfix, } } fn parse_sof(&mut self, input: &mut ByteStream) -> Result<(), String> { let header_length = input.get_u16() as usize; self.precision = input.get_u8() as usize; self.height = input.get_u16() as usize; self.width = input.get_u16() as usize; self.cps = input.get_u8() as usize; if self.precision > 16 { return Err("ljpeg: More than 16 bits per channel is not supported.".to_string()); } if self.cps > 4 || self.cps < 1 { return Err("ljpeg: Only from 1 to 4 components are supported.".to_string()); } if header_length != 8 + self.cps * 3 { return Err("ljpeg: Header size mismatch.".to_string()); } for i in 0..self.cps { let id = input.get_u8() as usize; let subs = input.get_u8() as usize; input.get_u8(); // Skip info about quantized self.components.push(JpegComponentInfo { id, index: i, dc_tbl_num: 0, super_v: subs & 0xf, super_h: subs >> 4, }); } Ok(()) } fn parse_sos(&mut self, input: &mut ByteStream) -> Result<(usize, usize), String> { if self.width == 0 { return Err("ljpeg: Trying to parse SOS before SOF".to_string()); } input.get_u16(); //skip header length let soscps = input.get_u8() as usize; if self.cps != soscps { return Err("ljpeg: component number mismatch in SOS".to_string()); } for cs in 0..self.cps { // At least some MOS cameras have this broken let readcs = input.get_u8() as usize; let cs = if self.csfix { cs } else { readcs }; let component = match self.components.iter_mut().find(|&&mut c| c.id == cs) { Some(val) => val, None => return Err(format!("ljpeg: invalid component selector {}", cs)), }; let td = (input.get_u8() as usize) >> 4; if td > 3 { return Err("ljpeg: Invalid Huffman table selection".to_string()); } component.dc_tbl_num = td; } let pred = input.get_u8() as usize; input.get_u8(); // Se + Ah Not used in LJPEG let pt = (input.get_u8() as usize) & 0xf; // Point Transform Ok((pred, pt)) } } #[derive(Debug)] pub struct LjpegDecompressor<'a> { buffer: &'a [u8], sof: SOFInfo, predictor: usize, point_transform: usize, dhts: Vec, } impl<'a> LjpegDecompressor<'a> { pub fn new(src: &'a [u8]) -> Result, String> { LjpegDecompressor::new_full(src, false, false) } pub fn new_full(src: &'a [u8], dng_bug: bool, csfix: bool) -> Result, String> { let mut input = ByteStream::new(src, Endian::Big); if LjpegDecompressor::get_next_marker(&mut input, false)? != m(Marker::SOI) { return Err("ljpeg: Image did not start with SOI. Probably not LJPEG".to_string()); } let mut sof = SOFInfo::empty(csfix); let mut dht_init = [false; 4]; let mut dht_bits = [[0_u32; 17]; 4]; let mut dht_huffval = [[0_u32; 256]; 4]; let pred; let pt; loop { let marker = LjpegDecompressor::get_next_marker(&mut input, true)?; if marker == m(Marker::SOF3) { // Start of the frame, giving us the basic info sof.parse_sof(&mut input)?; if sof.precision > 16 || sof.precision < 12 { return Err(format!("ljpeg: sof.precision {}", sof.precision)); } } else if marker == m(Marker::DHT) { // Huffman table settings LjpegDecompressor::parse_dht(&mut input, &mut dht_init, &mut dht_bits, &mut dht_huffval)?; } else if marker == m(Marker::SOS) { // Start of the actual stream, we can decode after this let (a, b) = sof.parse_sos(&mut input)?; pred = a; pt = b; break; } else if marker == m(Marker::EOI) { // Should never be reached as we stop at SOS return Err("ljpeg: reached EOI before SOS".to_string()); } else if marker == m(Marker::DQT) { return Err("ljpeg: not a valid raw file, found DQT".to_string()); } } let mut dhts = Vec::new(); for i in 0..4 { dhts.push(if dht_init[i] { HuffTable::new(dht_bits[i], dht_huffval[i], dng_bug)? } else { HuffTable::empty() }); } log::debug!( "LJPEGDecompressor: super_h: {}, super_v: {}, pred: {}, pt: {}, prec: {}, cps: {}", sof.components[0].super_h, sof.components[0].super_v, pred, pt, sof.precision, sof.cps, ); if sof.components[0].super_h == 2 && sof.components[0].super_v == 2 { log::debug!("LJPEG with YUV 4:2:0 encoding"); } else if sof.components[0].super_h == 2 && sof.components[0].super_v == 1 { log::debug!("LJPEG with YUV 4:2:2 encoding"); } let offset = input.get_pos(); Ok(LjpegDecompressor { buffer: &src[offset..], sof, predictor: pred, point_transform: pt, dhts, }) } fn get_next_marker(input: &mut ByteStream, allowskip: bool) -> Result { if !allowskip { let fill = input.get_u8(); if fill != m(Marker::Fill) { return Err(format!("ljpeg get_next_marker() (noskip) expected fill marker 0XFF but got 0x{:X}", fill)); } let mark = input.get_u8(); if mark == m(Marker::Stuff) || mark == m(Marker::Fill) { return Err(format!( "ljpeg get_next_marker() (noskip) expected marker but found STUFF or FILL (0x{:X})", mark )); } return Ok(mark); } input.skip_to_marker()?; Ok(input.get_u8()) } fn parse_dht(input: &mut ByteStream, init: &mut [bool; 4], bits: &mut [[u32; 17]; 4], huffval: &mut [[u32; 256]; 4]) -> Result<(), String> { let mut length = (input.get_u16() as usize) - 2; while length > 0 { let b = input.get_u8() as usize; let tc = b >> 4; let th = b & 0xf; if tc != 0 { return Err("ljpeg: unsuported table class in DHT".to_string()); } if th > 3 { return Err(format!("ljpeg: unsuported table id {}", th)); } let mut acc: usize = 0; for i in 0..16 { bits[th][i + 1] = input.get_u8() as u32; acc += bits[th][i + 1] as usize; } bits[th][0] = 0; if acc > 256 { return Err("ljpeg: invalid DHT table".to_string()); } if length < 1 + 16 + acc { return Err("ljpeg: invalid DHT table length".to_string()); } for i in 0..acc { huffval[th][i] = input.get_u8() as u32; } init[th] = true; length -= 1 + 16 + acc; } Ok(()) } /// Handle special SONY YUV 4:2:0 encoding in ILCE-7RM5 pub fn decode_sony(&self, out: &mut [u16], x: usize, stripwidth: usize, width: usize, height: usize, dummy: bool) -> Result<(), String> { if dummy { return Ok(()); } log::debug!("LJPEG decode with special Sony mode"); if self.sof.components[0].super_h == 2 && self.sof.components[0].super_v == 2 { decode_sony_ljpeg_420(self, out, width, height) } else if self.sof.components[0].super_h == 2 && self.sof.components[0].super_v == 1 { decode_ljpeg_422(self, out, width, height) } else if self.sof.components[0].super_h == 1 && self.sof.components[0].super_v == 1 { match self.predictor { 1 | 2 | 3 | 4 | 5 | 6 | 7 => decode_ljpeg(self, out, x, stripwidth, width, height), 8 => decode_hasselblad(self, out, width), p => Err(format!("ljpeg: predictor {} not supported", p)), } } else { Err(format!( "ljpeg: unsupported interleave configuration, super_h: {}, super_v: {}", self.sof.components[0].super_h, self.sof.components[0].super_v )) } } pub fn decode(&self, out: &mut [u16], x: usize, stripwidth: usize, width: usize, height: usize, dummy: bool) -> Result<(), String> { if dummy { return Ok(()); } if self.sof.components[0].super_h == 2 && self.sof.components[0].super_v == 2 { decode_ljpeg_420(self, out, width, height) } else if self.sof.components[0].super_h == 2 && self.sof.components[0].super_v == 1 { return decode_ljpeg_422(self, out, width, height); } else if self.sof.components[0].super_h == 1 && self.sof.components[0].super_v == 1 { match self.predictor { 1 | 2 | 3 | 4 | 5 | 6 | 7 => decode_ljpeg(self, out, x, stripwidth, width, height), 8 => decode_hasselblad(self, out, width), p => Err(format!("ljpeg: predictor {} not supported", p)), } } else { Err(format!( "ljpeg: unsupported interleave configuration, super_h: {}, super_v: {}", self.sof.components[0].super_h, self.sof.components[0].super_v )) } } pub fn decode_leaf(&self, width: usize, height: usize) -> Result { let mut offsets = vec![0_usize; 1]; let mut input = ByteStream::new(self.buffer, Endian::Big); while let Ok(marker) = LjpegDecompressor::get_next_marker(&mut input, true) { if marker == m(Marker::EOI) { break; } offsets.push(input.get_pos()); } let nstrips = (height - 1) / 8 + 1; if offsets.len() != nstrips { return Err(format!("MOS: expecting {} strips found {}", nstrips, offsets.len())); } let htable1 = &self.dhts[self.sof.components[0].dc_tbl_num]; let htable2 = &self.dhts[self.sof.components[1].dc_tbl_num]; let bpred = 1 << (self.sof.precision - self.point_transform - 1); decode_threaded_multiline( width, height, 8, false, &(|strip: &mut [u16], block| { let block = block / 8; let offset = offsets[block]; let nlines = strip.len() / width; decode_leaf_strip(&self.buffer[offset..], strip, width, nlines, htable1, htable2, bpred)?; Ok(()) }), ) } pub fn width(&self) -> usize { self.sof.width * self.sof.cps } pub fn height(&self) -> usize { self.sof.height } pub fn super_v(&self) -> usize { self.sof.components[0].super_v } pub fn super_h(&self) -> usize { self.sof.components[0].super_h } pub fn components(&self) -> usize { self.sof.components.len() } } rawler-0.7.1/src/decompressors/mod.rs000064400000000000000000000051341046102023000157340ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2025 Daniel Vogelbacher use crate::pixarray::SubPixel; pub mod crx; pub mod deflate; pub mod jpeg; pub mod jpegxl; pub mod ljpeg; pub mod packed; pub mod radc; /// Trait for mutable line iterators over image data. /// /// This trait is implemented for iterators that yield mutable slices of subpixel data. /// It is used to provide mutable access to each line of an image during decompression. /// /// # Type Parameters /// - `'a`: Lifetime of the data. /// - `T`: The subpixel type, which must implement [`SubPixel`]. pub trait LineIteratorMut<'a, T>: Iterator + ExactSizeIterator where T: SubPixel + 'a, { } impl<'a, T, I> LineIteratorMut<'a, T> for I where I: ExactSizeIterator, T: SubPixel + 'a, { } /// Trait for immutable line iterators over image data. /// /// This trait is implemented for iterators that yield immutable slices of subpixel data. /// It is used to provide read-only access to each line of an image. /// /// # Type Parameters /// - `'a`: Lifetime of the data. /// - `T`: The subpixel type, which must implement [`SubPixel`]. pub trait LineIterator<'a, T>: Iterator + ExactSizeIterator where T: SubPixel + 'a, { } /// Trait for decompressors handling raw image data. /// /// Implementors of this trait provide functionality to decompress raw image data into pixel lines (slices). /// The decompressor operates on a source byte slice and writes decompressed data into provided line buffers. /// /// # Type Parameters /// - `'a`: Lifetime of the data. /// - `T`: The subpixel type, which must implement [`SubPixel`]. pub trait Decompressor<'a, T>: Send + Sync where T: SubPixel + 'a, { /// Decompresses the source data into the provided line buffers. /// /// # Arguments /// * `src` - Source byte slice containing compressed image data. /// * `skip_rows` - Number of rows to skip before starting decompression. /// * `lines` - Mutable iterator over destination lines to write decompressed data. /// * `line_width` - The width of each line in pixels. /// /// # Returns /// * `Ok(())` on success. /// * `Err(String)` with an error message on failure. fn decompress(&self, src: &[u8], skip_rows: usize, lines: impl LineIteratorMut<'a, T>, line_width: usize) -> std::result::Result<(), String>; /// Returns `true` if the decompressor is optimized for strip-based processing. fn strips_optimized(&self) -> bool { false } /// Returns `true` if the decompressor is optimized for tile-based processing. fn tile_optimized(&self) -> bool { false } } rawler-0.7.1/src/decompressors/packed.rs000064400000000000000000000173641046102023000164140ustar 00000000000000use multiversion::multiversion; use crate::bits::{BEf16, BEf24, BEf32, BEu16, LEf16, LEf24, LEf32, LEu16}; use crate::decompressors::LineIteratorMut; use crate::pumps::{BitPump, BitPumpMSB}; use crate::{bits::Endian, decompressors::Decompressor}; /// Decompressor for packed data pub struct PackedDecompressor { bps: u32, endian: Endian, } impl PackedDecompressor { pub fn new(bps: u32, endian: Endian) -> Self { Self { bps, endian } } } impl<'a> Decompressor<'a, u16> for PackedDecompressor { fn decompress(&self, src: &[u8], skip_rows: usize, lines: impl LineIteratorMut<'a, u16>, line_width: usize) -> std::result::Result<(), String> { match (self.endian, self.bps) { // 16 bits, encoding depends on TIFF endianess (Endian::Big, 16) => unpack_16be(lines, src, skip_rows, line_width), (Endian::Little, 16) => unpack_16le(lines, src, skip_rows, line_width), // 12 Bits, DNG spec says it must be always encoded as big-endian (_, 12) => unpack_12be(lines, src, skip_rows, line_width), // 10 Bits, DNG spec says it must be always encoded as big-endian (_, 10) => unpack_10be(lines, src, skip_rows, line_width), // 8 bits (_, 8) => unpack_8bit(lines, src, skip_rows, line_width), // Generic MSB decoder for exotic packed bit sizes (_, bps) if bps > 0 && bps < 16 => unpack_generic_msb(lines, src, skip_rows, self.bps), // Unhandled bits (_, bps) => return Err(format_args!("DNG: Don't know how to handle DNG with {} bps", bps).to_string()), } Ok(()) } fn strips_optimized(&self) -> bool { true } fn tile_optimized(&self) -> bool { true } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn unpack_16be<'a>(lines: impl LineIteratorMut<'a, u16>, src: &[u8], skip_rows: usize, width: usize) { for (row, line) in lines.enumerate() { let inb = &src[((skip_rows + row) * width * 2)..]; for (out, bytes) in line.iter_mut().zip(inb.chunks_exact(2)) { *out = BEu16(bytes, 0); } } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn unpack_16le<'a>(lines: impl LineIteratorMut<'a, u16>, src: &[u8], skip_rows: usize, width: usize) { for (row, line) in lines.enumerate() { let inb = &src[((skip_rows + row) * width * 2)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(2)) { line[i] = LEu16(bytes, 0); } } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn unpack_12be<'a>(lines: impl LineIteratorMut<'a, u16>, src: &[u8], skip_rows: usize, width: usize) { for (row, line) in lines.enumerate() { let inb = &src[((skip_rows + row) * width * 12 / 8)..]; for (o, i) in line.chunks_exact_mut(2).zip(inb.chunks_exact(3)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; o[0] = (g1 << 4) | (g2 >> 4); o[1] = ((g2 & 0x0f) << 8) | g3; } } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn unpack_10be<'a>(lines: impl LineIteratorMut<'a, u16>, src: &[u8], skip_rows: usize, width: usize) { for (row, line) in lines.enumerate() { let inb = &src[((skip_rows + row) * width * 10 / 8)..]; for (o, i) in line.chunks_exact_mut(4).zip(inb.chunks_exact(5)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; let g4: u16 = i[3] as u16; let g5: u16 = i[4] as u16; o[0] = (g1 << 2) | (g2 >> 6); o[1] = ((g2 & 0x3f) << 4) | (g3 >> 4); o[2] = ((g3 & 0x0f) << 6) | (g4 >> 2); o[3] = ((g4 & 0x03) << 8) | g5; } } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn unpack_8bit<'a>(lines: impl LineIteratorMut<'a, u16>, src: &[u8], skip_rows: usize, width: usize) { for (row, line) in lines.enumerate() { let inb = &src[((skip_rows + row) * width)..]; for (o, i) in line.iter_mut().zip(inb.iter()) { *o = *i as u16; } } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn unpack_generic_msb<'a>(lines: impl LineIteratorMut<'a, u16>, src: &[u8], skip_rows: usize, bits: u32) { assert!(bits <= 16); assert!(skip_rows == 0, "pumps not supported yet for offset rows"); let mut pump = BitPumpMSB::new(src); for line in lines { for p in line { *p = pump.get_bits(bits) as u16; } } } impl<'a> Decompressor<'a, f32> for PackedDecompressor { fn decompress(&self, src: &[u8], skip_rows: usize, lines: impl LineIteratorMut<'a, f32>, line_width: usize) -> std::result::Result<(), String> { match (self.endian, self.bps) { // 16 bits, encoding depends on TIFF endianess (Endian::Big, 32) => unpack_f32be(lines, src, skip_rows, line_width), (Endian::Little, 32) => unpack_f32le(lines, src, skip_rows, line_width), (Endian::Big, 24) => unpack_f24be(lines, src, skip_rows, line_width), (Endian::Little, 24) => unpack_f24le(lines, src, skip_rows, line_width), (Endian::Big, 16) => unpack_f16be(lines, src, skip_rows, line_width), (Endian::Little, 16) => unpack_f16le(lines, src, skip_rows, line_width), // Unhandled bits (_, bps) => return Err(format_args!("DNG: Don't know how to handle FP DNG with {} bps", bps).to_string()), } Ok(()) } fn strips_optimized(&self) -> bool { true } fn tile_optimized(&self) -> bool { true } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn unpack_f32be<'a>(lines: impl LineIteratorMut<'a, f32>, src: &[u8], skip_rows: usize, width: usize) { for (row, line) in lines.enumerate() { let inb = &src[((skip_rows + row) * width * size_of::())..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(4)) { line[i] = BEf32(bytes, 0); } } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn unpack_f32le<'a>(lines: impl LineIteratorMut<'a, f32>, src: &[u8], skip_rows: usize, width: usize) { for (row, line) in lines.enumerate() { let inb = &src[((skip_rows + row) * width * size_of::())..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(4)) { line[i] = LEf32(bytes, 0); } } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn unpack_f24le<'a>(lines: impl LineIteratorMut<'a, f32>, src: &[u8], skip_rows: usize, width: usize) { const SIZEOF_FP24: usize = 3; for (row, line) in lines.enumerate() { let inb = &src[((skip_rows + row) * width * SIZEOF_FP24)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(SIZEOF_FP24)) { line[i] = LEf24(bytes, 0); } } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn unpack_f24be<'a>(lines: impl LineIteratorMut<'a, f32>, src: &[u8], skip_rows: usize, width: usize) { const SIZEOF_FP24: usize = 3; for (row, line) in lines.enumerate() { let inb = &src[((skip_rows + row) * width * SIZEOF_FP24)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(SIZEOF_FP24)) { line[i] = BEf24(bytes, 0); } } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn unpack_f16le<'a>(lines: impl LineIteratorMut<'a, f32>, src: &[u8], skip_rows: usize, width: usize) { const SIZEOF_FP16: usize = 2; for (row, line) in lines.enumerate() { let inb = &src[((skip_rows + row) * width * SIZEOF_FP16)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(SIZEOF_FP16)) { line[i] = LEf16(bytes, 0); } } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn unpack_f16be<'a>(lines: impl LineIteratorMut<'a, f32>, src: &[u8], skip_rows: usize, width: usize) { const SIZEOF_FP16: usize = 2; for (row, line) in lines.enumerate() { let inb = &src[((skip_rows + row) * width * SIZEOF_FP16)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(SIZEOF_FP16)) { line[i] = BEf16(bytes, 0); } } } rawler-0.7.1/src/decompressors/radc.rs000064400000000000000000000164721046102023000160750ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2024 Daniel Vogelbacher // Originally written in C in dcraw.c by Dave Coffin // // Kodak Run Adaptive Differential Coding (RADC) use rayon::iter::IndexedParallelIterator; use rayon::iter::ParallelIterator; use crate::Result; use crate::alloc_image_ok; use crate::bits::LookupTable; use crate::buffer::PaddedBuf; use crate::pixarray::PixU16; use crate::pumps::BitPump; use crate::pumps::BitPumpMSB; #[rustfmt::skip] const HUFF_INIT: [(u8, i8); 130] = [ (1,1), (2,3), (3,4), (4,2), (5,7), (6,5), (7,6), (7,8), (1,0), (2,1), (3,3), (4,4), (5,2), (6,7), (7,6), (8,5), (8,8), (2,1), (2,3), (3,0), (3,2), (3,4), (4,6), (5,5), (6,7), (6,8), (2,0), (2,1), (2,3), (3,2), (4,4), (5,6), (6,7), (7,5), (7,8), (2,1), (2,4), (3,0), (3,2), (3,3), (4,7), (5,5), (6,6), (6,8), (2,3), (3,1), (3,2), (3,4), (3,5), (3,6), (4,7), (5,0), (5,8), (2,3), (2,6), (3,0), (3,1), (4,4), (4,5), (4,7), (5,2), (5,8), (2,4), (2,7), (3,3), (3,6), (4,1), (4,2), (4,5), (5,0), (5,8), (2,6), (3,1), (3,3), (3,5), (3,7), (3,8), (4,0), (5,2), (5,4), (2,0), (2,1), (3,2), (3,3), (4,4), (4,5), (5,6), (5,7), (4,8), (1,0), (2,2), (2,-2), (1,-3), (1,3), (2,-17), (2,-5), (2,5), (2,17), (2,-7), (2,2), (2,9), (2,18), (2,-18), (2,-9), (2,-2), (2,7), (2,-28), (2,28), (3,-49), (3,-9), (3,9), (4,49), (5,-79), (5,79), (2,-1), (2,13), (2,26), (3,39), (4,-16), (5,55), (6,-37), (6,76), (2,-26), (2,-13), (2,1), (3,-39), (4,16), (5,-55), (6,-76), (6,37) ]; #[derive(Default, Clone, Copy, PartialEq, PartialOrd)] struct HuffSymbol { bitcnt: u8, value: u8, } struct HuffDecoder { cache: [[HuffSymbol; 256]; 19], } impl HuffDecoder { /// Create new HuffmanDecoder /// /// cbpp is Compressed Bits Per Pixel fn new(cbpp: u8) -> Self { let mut cache = [[HuffSymbol::default(); 256]; 19]; let mut a = 0; for x in HUFF_INIT { for _ in 0..(256 >> x.0) { // max bit value in cache cache.as_flattened_mut()[a].bitcnt = x.0; cache.as_flattened_mut()[a].value = x.1 as u8; a += 1; } } for c in 0..256 { cache[18][c].bitcnt = 8 - cbpp; cache[18][c].value = ((c as u8) >> cbpp << cbpp) | (1 << (cbpp - 1)); } Self { cache } } #[inline(always)] fn huff_decode(&self, pump: &mut dyn BitPump, tree: usize) -> i8 { let code = pump.peek_bits(8) as usize; let sym = self.cache[tree][code]; pump.consume_bits(sym.bitcnt as u32); sym.value as i8 } } /// Decompress a RADC buffer /// /// cbpp is Compressed Bits Per Pixel pub fn decompress(src: &PaddedBuf, width: usize, height: usize, cbpp: u8, dummy: bool) -> Result { log::debug!("RADC decompress with cbpp: {}, width: {}, height: {}", cbpp, width, height); let mut out = alloc_image_ok!(width, height, dummy); let mut last: [i16; 3] = [16, 16, 16]; let mut mul: [i16; 3]; let mut buf: [[[i16; 386]; 3]; 3] = [[[2048; 386]; 3]; 3]; let tbl = { const PT: [(usize, f32); 6] = [(0, 0.0), (1280, 1344.0), (2320, 3616.0), (3328, 8000.0), (4095, 16383.0), (65535, 16383.0)]; let mut curve = vec![0; 65536]; for i in 1..PT.len() { for c in PT[i - 1].0..=PT[i].0 { curve[c] = ((c - PT[i - 1].0) as f32 / (PT[i].0 - PT[i - 1].0) as f32 * (PT[i].1 - PT[i - 1].1) + PT[i - 1].1 + 0.5) as u16; } } LookupTable::new_with_bits(&curve, 16) }; let dec = HuffDecoder::new(cbpp); let mut pump = BitPumpMSB::new(src); for row in (0..height).step_by(4) { mul = [pump.get_bits(6) as i16, pump.get_bits(6) as i16, pump.get_bits(6) as i16]; for c in 0..3 { let predictor = |buf: &[[[i16; 386]; 3]; 3], x: usize, y: usize| -> i16 { (if c > 0 { (buf[c][y - 1][x] as i32 + buf[c][y][x + 1] as i32) / 2 } else { (buf[c][y - 1][x + 1] as i32 + 2 * buf[c][y - 1][x] as i32 + buf[c][y][x + 1] as i32) / 4 }) as i16 }; let mut val: i32 = ((0x1000000 / (last[c] as i32) + 0x7ff) >> 12) * mul[c] as i32; let s = if val > 65564 { 10 } else { 12 }; let x: i32 = (1 << (s - 1)) - 1; val <<= 12 - s; buf[c].as_flattened_mut().iter_mut().for_each(|i| *i = ((*i as i32 * val + x) >> s) as i16); last[c] = mul[c]; let max = if c == 0 { 1 } else { 0 }; for r in 0..=max { buf[c][1][width / 2] = mul[c] << 7; buf[c][2][width / 2] = mul[c] << 7; let mut tree = 1; let mut col = width / 2; while col > 0 { tree = dec.huff_decode(&mut pump, tree) as usize; if tree != 0 { col -= 2; if tree == 8 { for y in 1..3 { for x in (col..=(col + 1)).rev() { buf[c][y][x] = (dec.huff_decode(&mut pump, 18) as u8) as i16 * mul[c]; assert!(buf[c][y][x] >= 0); } } } else { for y in 1..3 { for x in (col..=(col + 1)).rev() { buf[c][y][x] = dec.huff_decode(&mut pump, tree + 10) as i16 * 16 + predictor(&buf, x, y); } } } } else { loop { let nreps = if col > 2 { dec.huff_decode(&mut pump, 9) + 1 } else { 1 }; for rep in 0..8 { if rep < nreps && col > 0 { col -= 2; for y in 1..3 { for x in (col..=(col + 1)).rev() { buf[c][y][x] = predictor(&buf, x, y); } } if rep & 1 > 0 { let step = dec.huff_decode(&mut pump, 10) << 4; for y in 1..3 { for x in (col..=(col + 1)).rev() { buf[c][y][x] += step as i16; } } } } } if nreps != 9 { break; } } } } for y in 0..2 { for x in 0..(width / 2) { let val = ((buf[c][y + 1][x] as i32) << 4) / mul[c] as i32; let val = if val < 0 { 0 } else { val }; if c > 0 { *out.at_mut(row + y * 2 + c - 1, x * 2 + 2 - c) = val as u16; } else { *out.at_mut(row + r * 2 + y, x * 2 + y) = val as u16; } } } // Copy buffer from buf[c][2] to buf[c][0] // Borrow checker needs this hack... let (dst, src) = buf[c].split_at_mut(2); if c == 0 { dst[0][1..].copy_from_slice(&src[2 - 2][..386 - 1]); } else { dst[0][..].copy_from_slice(&src[2 - 2][..]); } } } for y in row..row + 4 { for x in 0..width { if ((x + y) & 1) > 0 { let r = if x > 0 { x - 1 } else { x + 1 }; let s = if x + 1 < width { x + 1 } else { x - 1 }; let val = (*out.at(y, x) as i32 - 2048) * 2 + ((*out.at(y, r) as i32 + *out.at(y, s) as i32) / 2); if val < 0 { *out.at_mut(y, x) = 0; } else { *out.at_mut(y, x) = val as u16; } } } } } out.par_pixel_rows_mut().enumerate().for_each(|(_row, line)| { let mut random = ((line[0] as u32) << 16) | line[1] as u32; for x in line { *x = tbl.dither(*x, &mut random); } }); Ok(out) } rawler-0.7.1/src/devtools/inspector.rs000064400000000000000000000004341046102023000161300ustar 00000000000000// The debug version #[cfg(feature = "inspector")] #[macro_export] macro_rules! inspector { ($( $args:expr ),*) => { println!( $( $args ),* ); } } // Non-debug version #[cfg(not(feature = "inspector"))] #[macro_export] macro_rules! inspector { ($( $args:expr ),*) => {}; } rawler-0.7.1/src/devtools/mod.rs000064400000000000000000000025631046102023000147060ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher use std::{ fs::File, io::{BufWriter, Write}, }; use byteorder::{LittleEndian, WriteBytesExt}; use image::{ImageBuffer, ImageFormat, Luma, Rgb}; pub(crate) mod inspector; pub fn dump_image_u16(data: &[u16], width: usize, height: usize, path: impl AsRef) { let img = ImageBuffer::, Vec>::from_vec(width as u32, height as u32, data.to_vec()).unwrap(); img.save_with_format(path.as_ref(), ImageFormat::Tiff).unwrap(); } pub fn dump_image_u16_rgb(data: &[u16], width: usize, height: usize, path: impl AsRef) { let img = ImageBuffer::, Vec>::from_vec(width as u32, height as u32, data.to_vec()).unwrap(); img.save_with_format(path.as_ref(), ImageFormat::Tiff).unwrap(); } pub fn dump_buf(path: &str, buf: T) where T: AsRef<[u8]>, { let mut f = BufWriter::new(File::create(path).expect("Unable to create file")); f.write_all(buf.as_ref()).expect("Failed to dump buffer to file"); f.flush().expect("Failed to flush file"); } pub fn dump_buf_u16(path: &str, buf: T) where T: AsRef<[u16]>, { let mut f = BufWriter::new(File::create(path).expect("Unable to create file")); for v in buf.as_ref().iter() { f.write_u16::(*v).expect("Failed to dump buffer to file"); } f.flush().expect("Failed to flush file"); } rawler-0.7.1/src/dng/convert.rs000064400000000000000000000167671046102023000145330ustar 00000000000000use std::{ ffi::OsStr, io::{Cursor, Seek, Write}, path::Path, sync::Arc, thread::JoinHandle, }; use image::DynamicImage; use crate::{ RawImage, decoders::{Decoder, RawDecodeParams, WellKnownIFD}, dng::{DNG_VERSION_V1_4, PREVIEW_JPEG_QUALITY, original::OriginalCompressed, writer::DngWriter}, formats::tiff::Entry, imgop::develop::RawDevelop, rawsource::RawSource, tags::{DngTag, ExifTag, TiffCommonTag}, }; use super::{CropMode, DngCompression, DngPhotometricConversion}; /// Parameters for DNG conversion #[derive(Clone, Debug)] pub struct ConvertParams { pub embedded: bool, pub compression: DngCompression, pub photometric_conversion: DngPhotometricConversion, pub apply_scaling: bool, pub crop: CropMode, pub predictor: u8, pub preview: bool, pub thumbnail: bool, pub artist: Option, pub software: String, pub index: usize, pub keep_mtime: bool, } impl Default for ConvertParams { fn default() -> Self { Self { embedded: true, compression: DngCompression::Lossless, photometric_conversion: DngPhotometricConversion::Original, apply_scaling: false, crop: CropMode::Best, predictor: 1, preview: true, thumbnail: true, artist: None, software: "DNGLab".into(), index: 0, keep_mtime: false, } } } /// Convert a raw input file into DNG /// /// We don't accept a DNG file path here, because we don't know /// how to handle existing target files, buffering, etc. /// This is up to the caller. pub fn convert_raw_file(raw: &Path, dng: &mut W, params: &ConvertParams) -> crate::Result<()> { let original_filename = raw.file_name().and_then(OsStr::to_str).unwrap_or_default(); //let raw_stream = BufReader::new(File::open(raw)?); // TODO: add path hint to error? //let rawfile = RawFile::new(PathBuf::from(raw), raw_stream); let rawfile = Arc::new(RawSource::new(raw)?); let original_compress_thread = if params.embedded { let orig_source = rawfile.clone(); Some(std::thread::spawn(move || OriginalCompressed::compress(&mut orig_source.reader()))) } else { None }; internal_convert(&rawfile, dng, original_filename, original_compress_thread, params) } /// Convert a raw input file into DNG pub fn convert_raw_source(raw_source: &RawSource, dng: &mut W, original_filename: impl AsRef, params: &ConvertParams) -> crate::Result<()> where W: Write + Seek + Send, { let original_compress_thread = if params.embedded { let mut original_stream = Cursor::new(raw_source.as_vec()?); Some(std::thread::spawn(move || OriginalCompressed::compress(&mut original_stream))) } else { None }; internal_convert(raw_source, dng, original_filename, original_compress_thread, params) } fn internal_convert( rawfile: &RawSource, dng: &mut W, original_filename: impl AsRef, original_compress_thread: Option>>, params: &ConvertParams, ) -> crate::Result<()> where W: Write + Seek + Send, { let decoder = crate::get_decoder(rawfile)?; let raw_params = RawDecodeParams { image_index: params.index }; let mut rawimage = decoder.raw_image(rawfile, &raw_params, false)?; let metadata = decoder.raw_metadata(rawfile, &raw_params)?; log::info!( "DNG conversion: '{}', make: {}, model: {}, raw-image-count: {}", original_filename.as_ref(), rawimage.clean_make, rawimage.clean_model, decoder.raw_image_count()? ); if params.apply_scaling { rawimage.apply_scaling()?; } log::debug!("wb coeff: {:?}", rawimage.wb_coeffs); let mut dng = DngWriter::new(dng, DNG_VERSION_V1_4)?; // Write RAW image for subframe type 0 // If no thumbnail should be written to root IFD, we need to put the raw image into // root IFD instead. let mut raw = if params.thumbnail { dng.subframe(0) } else { dng.subframe_on_root(0) }; raw.raw_image(&rawimage, params.crop, params.compression, params.photometric_conversion, params.predictor)?; // Check for DNG raw IFD related tags if let Some(dng_raw_ifd) = decoder.ifd(WellKnownIFD::VirtualDngRawTags)? { raw.ifd_mut().copy(dng_raw_ifd.value_iter()); } raw.finalize()?; // Write preview and thumbnail if requested if params.preview || params.thumbnail { match generate_preview(rawfile, decoder.as_ref(), &rawimage, &raw_params) { Ok(image) => { if params.preview { let mut preview = dng.subframe(1); preview.preview(&image, PREVIEW_JPEG_QUALITY)?; preview.finalize()?; } if params.thumbnail { dng.thumbnail(&image)?; } } Err(err) => log::warn!("Failed to get review image, continue anyway: {:?}", err), } } // Write metadata dng.load_base_tags(&rawimage)?; dng.load_metadata(&metadata)?; if !dng.root_ifd().contains(ExifTag::Orientation) { dng.root_ifd_mut().add_tag(ExifTag::Orientation, rawimage.orientation.to_u16()); } // Check for DNG root IFD related tags if let Some(dng_root_ifd) = decoder.ifd(WellKnownIFD::VirtualDngRootTags)? { dng.root_ifd_mut().copy(dng_root_ifd.value_iter()); } // Check for TIFF root IFD related tags if let Some(tiff_root) = decoder.ifd(WellKnownIFD::Root)? { dng.root_ifd_mut().copy(tiff_root.value_iter().filter(|(tag, _)| { [ // Tags from CinemaDNG files TiffCommonTag::TimeCodes as u16, TiffCommonTag::FrameFrate as u16, TiffCommonTag::TStop as u16, ] .contains(tag) })); } // Remove makernotes from EXIF if MakerNoteSafety is not 1 (safe) if let Some(Entry { value: crate::formats::tiff::Value::Short(v), .. }) = decoder .ifd(WellKnownIFD::VirtualDngRootTags)? .and_then(|ifd| ifd.get_entry(DngTag::MakerNoteSafety).cloned()) { if v.get(0).copied().unwrap_or(0) == 0 { dng.exif_ifd_mut().remove_tag(ExifTag::MakerNotes); } } if let Some(xpacket) = decoder.xpacket(rawfile, &raw_params)? { dng.xpacket(&xpacket)?; } if let Some(handle) = original_compress_thread { let original = handle .join() .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to join compression thread: {:?}", err)))??; dng.original_file(&original, original_filename)?; } if let Some(artist) = ¶ms.artist { dng.root_ifd_mut().add_tag(TiffCommonTag::Artist, artist); } dng.root_ifd_mut().add_tag(TiffCommonTag::Software, ¶ms.software); dng .root_ifd_mut() .add_tag(ExifTag::ModifyDate, chrono::Local::now().format("%Y:%m:%d %H:%M:%S").to_string()); dng.close()?; Ok(()) } fn generate_preview(rawfile: &RawSource, decoder: &dyn Decoder, rawimage: &RawImage, params: &RawDecodeParams) -> crate::Result { match decoder.full_image(rawfile, params)? { Some(image) => Ok(image), None => { log::warn!("Preview image not found, try to generate sRGB from RAW"); let dev = RawDevelop::default(); let image = dev.develop_intermediate(rawimage)?; /* let params = rawimage.develop_params()?; let (srgbf, dim) = develop_raw_srgb(&rawimage.data, ¶ms)?; let output = convert_from_f32_scaled_u16(&srgbf, 0, u16::MAX); let image = if srgbf.len() == dim.w * dim.h { DynamicImage::ImageLuma16(ImageBuffer::from_raw(dim.w as u32, dim.h as u32, output).expect("Invalid ImageBuffer size")) } else { DynamicImage::ImageRgb16(ImageBuffer::from_raw(dim.w as u32, dim.h as u32, output).expect("Invalid ImageBuffer size")) }; */ Ok(image.to_dynamic_image().unwrap()) } } } rawler-0.7.1/src/dng/mod.rs000064400000000000000000000055631046102023000136220ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2023 Daniel Vogelbacher pub mod convert; pub mod original; pub mod writer; use crate::imgop::Rect; pub const DNG_VERSION_V1_0: [u8; 4] = [1, 0, 0, 0]; pub const DNG_VERSION_V1_1: [u8; 4] = [1, 1, 0, 0]; pub const DNG_VERSION_V1_2: [u8; 4] = [1, 2, 0, 0]; pub const DNG_VERSION_V1_3: [u8; 4] = [1, 3, 0, 0]; pub const DNG_VERSION_V1_4: [u8; 4] = [1, 4, 0, 0]; pub const DNG_VERSION_V1_5: [u8; 4] = [1, 5, 0, 0]; pub const DNG_VERSION_V1_6: [u8; 4] = [1, 6, 0, 0]; /// Convert internal crop rectangle to DNG active area /// /// DNG ActiveArea is: /// Top, Left, Bottom, Right pub fn rect_to_dng_area(area: &Rect) -> [u16; 4] { [ area.p.y as u16, area.p.x as u16, area.p.y as u16 + area.d.h as u16, area.p.x as u16 + area.d.w as u16, ] /* [ image.crops[0] as u16, // top image.crops[3] as u16, // left //(image.height-image.crops[0]-image.crops[2]) as u16, // bottom //(image.width-image.crops[1]-image.crops[3]) as u16, // Right (image.height - (image.crops[2])) as u16, // bottom coord (image.width - (image.crops[1])) as u16, // Right coord ] */ } #[cfg(feature = "clap")] impl clap::ValueEnum for DngCompression { fn value_variants<'a>() -> &'a [Self] { &[Self::Lossless, Self::Uncompressed] } fn to_possible_value(&self) -> Option { Some(match self { Self::Uncompressed => clap::builder::PossibleValue::new("uncompressed"), Self::Lossless => clap::builder::PossibleValue::new("lossless"), }) } } #[derive(Clone, Copy, Debug)] pub enum DngPhotometricConversion { Original, Linear, } impl Default for DngPhotometricConversion { fn default() -> Self { Self::Original } } #[derive(Clone, Copy, Debug)] pub enum CropMode { Best, ActiveArea, None, } #[cfg(feature = "clap")] impl clap::ValueEnum for CropMode { fn value_variants<'a>() -> &'a [Self] { &[Self::Best, Self::ActiveArea, Self::None] } fn to_possible_value(&self) -> Option { Some(match self { Self::Best => clap::builder::PossibleValue::new("best"), Self::ActiveArea => clap::builder::PossibleValue::new("activearea"), Self::None => clap::builder::PossibleValue::new("none"), }) } } /* impl FromStr for CropMode { type Err = String; fn from_str(mode: &str) -> std::result::Result { Ok(match mode { "best" => Self::Best, "activearea" => Self::ActiveArea, "none" => Self::None, _ => return Err(format!("Unknown CropMode value: {}", mode)), }) } } */ /// Quality of preview images const PREVIEW_JPEG_QUALITY: f32 = 0.75; #[derive(Clone, Copy, Debug, Eq, PartialEq)] /// Compression mode for DNG pub enum DngCompression { /// No compression is applied Uncompressed, /// Lossless JPEG-92 compression Lossless, // Lossy } rawler-0.7.1/src/dng/original.rs000064400000000000000000000167611046102023000146510ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher use byteorder::{BigEndian, ReadBytesExt}; use libflate::zlib::{Decoder, EncodeOptions, Encoder}; use log::debug; use rayon::prelude::*; use std::{ io::{self, Read, Seek, SeekFrom, Write}, mem::size_of, ops::Neg, }; // DNG requires this block size const COMPRESS_BLOCK_SIZE: u32 = 65536; pub type OriginalDigest = [u8; 16]; pub struct OriginalCompressed { raw_fork_size: u32, chunks: Vec, digest: Option, } impl OriginalCompressed { pub fn new(stream: &mut T, digest: Option) -> io::Result where T: Read + Seek, { let start = stream.stream_position()?; let raw_fork_size: u32 = stream.read_u32::()?; let raw_fork_blocks: u32 = raw_fork_size.div_ceil(COMPRESS_BLOCK_SIZE); // (raw_fork_size + (COMPRESS_BLOCK_SIZE - 1)) / COMPRESS_BLOCK_SIZE let mut index_list: Vec = Vec::with_capacity(raw_fork_blocks as usize + 1); for _ in 0..raw_fork_blocks + 1 { let idx = stream.read_u32::()?; index_list.push(idx); } let mut chunks = Vec::with_capacity(index_list.len()); let mut iter = index_list.into_iter().map(u64::from); if let Some(mut offset) = iter.next() { stream.seek(SeekFrom::Start(start + offset))?; for end in iter { let len = end .checked_sub(offset) .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "Offset underflow"))?; let mut chunk = vec![0; len as usize]; stream.read_exact(&mut chunk)?; chunks.push(ForkBlock::new(chunk)); offset = end; } } Ok(Self { chunks, raw_fork_size, digest }) } pub fn decompress(&self, stream: &mut T, verify_digest: bool) -> io::Result where T: Write, { let mut ctx = md5::Context::new(); let mut total = 0; for chunk in self.chunks.iter().map(ForkBlock::decompress) { let buf = chunk?; stream.write_all(&buf)?; total = buf.len(); ctx.consume(&buf); } let new_digest = ctx.finalize().into(); debug!("Encoded calculated original data digest: {:x?}", self.digest); debug!("New calculated original data digest: {:x?}", new_digest); if self.digest.ne(&Some(new_digest)) { if verify_digest { return Err(io::Error::new( io::ErrorKind::InvalidData, "Embedded original digest and output digest mismatch, data may be corrupt", )); } else { log::warn!("Embedded original digest and output digest mismatch, data may be corrupt, but verify checks are disabled"); } } Ok(total) } /// Read bytes from stream until EOF, split into chunks /// and compress each one. pub fn compress(stream: &mut T) -> io::Result where T: Seek + Read, { let pos = stream.stream_position()?; stream.seek(SeekFrom::End(0))?; let uncomp_len = stream.stream_position()? - pos; stream.seek(SeekFrom::Current((uncomp_len as i64).neg()))?; let raw_fork_size = u32::try_from(uncomp_len).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; let raw_fork_blocks = raw_fork_size.div_ceil(COMPRESS_BLOCK_SIZE); // (raw_fork_size + (COMPRESS_BLOCK_SIZE - 1)) / COMPRESS_BLOCK_SIZE let mut forks = Vec::with_capacity(raw_fork_blocks as usize); let mut ctx = md5::Context::new(); loop { let mut buf = Vec::with_capacity(COMPRESS_BLOCK_SIZE as usize); stream.take(COMPRESS_BLOCK_SIZE as u64).read_to_end(&mut buf)?; if buf.is_empty() { break; } ctx.consume(&buf); forks.push(buf); //chunks.push(ForkBlock::compress(&buf)?); } let chunks = forks.par_iter().flat_map(ForkBlock::compress).collect(); let digest = Some(ctx.finalize().into()); Ok(Self { raw_fork_size, chunks, digest }) } pub fn digest(&self) -> Option { self.digest } /// Write compressed chunks to output stream. pub fn write_to_stream(&self, stream: &mut T) -> io::Result<()> where T: Write, { stream.write_all(&self.raw_fork_size.to_be_bytes())?; // Fork 1 let chunks_start: u32 = (size_of::() + (self.chunks.len() + 1) * size_of::()) as u32; // Offset of first chunk stream.write_all(&chunks_start.to_be_bytes())?; // Write all other end offsets. for end in self.chunks.iter().map(ForkBlock::len).scan(chunks_start, |end, len| { *end += len as u32; Some(*end) }) { stream.write_all(&end.to_be_bytes())?; } for chunk in self.chunks.iter() { stream.write_all(&chunk.chunk)?; } stream.write_all(&0u32.to_be_bytes())?; stream.write_all(&0u32.to_be_bytes())?; stream.write_all(&0u32.to_be_bytes())?; stream.write_all(&0u32.to_be_bytes())?; stream.write_all(&0u32.to_be_bytes())?; stream.write_all(&0u32.to_be_bytes())?; stream.write_all(&0u32.to_be_bytes())?; Ok(()) } } /// Single chunk for compressed data struct ForkBlock { /// Compressed data for block chunk: Vec, } impl ForkBlock { fn new(chunk: Vec) -> Self { Self { chunk } } fn len(&self) -> usize { self.chunk.len() } fn compress(buf: impl AsRef<[u8]>) -> io::Result { let mut encoder = Encoder::with_options( Vec::with_capacity(COMPRESS_BLOCK_SIZE as usize), EncodeOptions::new().block_size(COMPRESS_BLOCK_SIZE as usize), ) .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; encoder.write_all(buf.as_ref()).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; Ok(ForkBlock { chunk: encoder.finish().into_result().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?, }) } fn decompress(&self) -> io::Result> { let mut decoder = Decoder::new(self.chunk.as_slice()).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; let mut chunk = Vec::new(); decoder.read_to_end(&mut chunk).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; Ok(chunk) } } #[cfg(test)] mod tests { use std::io::Cursor; use super::*; #[test] fn empty_data() -> std::result::Result<(), Box> { //let data = [0x00, 0xFF, 0xDD]; let data = []; let mut file = Cursor::new(data); // Compress let orig = OriginalCompressed::compress(&mut file)?; let digest = orig.digest; let mut out = Cursor::new(Vec::new()); orig.write_to_stream(&mut out)?; out.seek(SeekFrom::Start(0))?; // Reload let comp = OriginalCompressed::new(&mut out, digest)?; // Decompress let mut restored = Cursor::new(Vec::new()); comp.decompress(&mut restored, true)?; // Compare let unpacked = restored.into_inner(); assert_eq!(unpacked, data); assert_eq!(digest, Some(md5::compute(&unpacked).into())); Ok(()) } #[test] fn dummy_data() -> std::result::Result<(), Box> { let data = [0x00, 0xFF, 0xDD, 0x00, 0x00]; let mut file = Cursor::new(data); // Compress let orig = OriginalCompressed::compress(&mut file)?; let digest = orig.digest; let mut out = Cursor::new(Vec::new()); orig.write_to_stream(&mut out)?; out.seek(SeekFrom::Start(0))?; // Reload let comp = OriginalCompressed::new(&mut out, digest)?; // Decompress let mut restored = Cursor::new(Vec::new()); comp.decompress(&mut restored, true)?; // Compare let unpacked = restored.into_inner(); assert_eq!(unpacked, data); assert_eq!(digest, Some(md5::compute(&unpacked).into())); Ok(()) } } rawler-0.7.1/src/dng/writer.rs000064400000000000000000000665411046102023000143620ustar 00000000000000use std::{ borrow::Cow, io::{self, Seek, Write}, mem::size_of, time::Instant, }; use image::{DynamicImage, codecs::jpeg::JpegEncoder, imageops::FilterType}; use log::debug; use rayon::prelude::*; use crate::{ CFA, RawImage, RawImageData, decoders::{Camera, RawMetadata}, dng::rect_to_dng_area, formats::tiff::{ CompressionMethod, PhotometricInterpretation, PreviewColorSpace, Rational, TiffError, Value, writer::{DirectoryWriter, TiffWriter, transfer_entry}, }, imgop::{Dim2, Point, Rect}, ljpeg92::LjpegCompressor, pixarray::PixU16, rawimage::{BlackLevel, RawPhotometricInterpretation, WhiteLevel}, tags::ExifTag, tiles::ImageTiler, }; use crate::{ formats::tiff::SRational, imgop::xyz::Illuminant, tags::{DngTag, TiffCommonTag}, }; use super::{CropMode, DNG_VERSION_V1_6, DngCompression, DngPhotometricConversion, original::OriginalCompressed}; pub type DngError = TiffError; pub type Result = std::result::Result; pub struct DngWriter where B: Write + Seek, { pub dng: TiffWriter, root_ifd: DirectoryWriter, //raw_ifd: DirectoryWriter, //preview_ifd: DirectoryWriter, exif_ifd: DirectoryWriter, subs: Vec, } pub struct SubFrameWriter<'w, B> where B: Write + Seek, { writer: &'w mut DngWriter, ifd: Option, } impl<'w, B> SubFrameWriter<'w, B> where B: Write + Seek, { pub fn new(writer: &'w mut DngWriter, subtype: u32, use_root: bool) -> Self { let ifd = if use_root { writer.root_ifd_mut().add_tag(TiffCommonTag::NewSubFileType, subtype); None } else { let mut ifd = DirectoryWriter::new(); ifd.add_tag(TiffCommonTag::NewSubFileType, subtype); Some(ifd) }; Self { ifd, writer } } pub fn ifd(&mut self) -> &DirectoryWriter { self.ifd.as_ref().unwrap_or(self.writer.root_ifd()) } pub fn ifd_mut(&mut self) -> &mut DirectoryWriter { self.ifd.as_mut().unwrap_or(self.writer.root_ifd_mut()) } pub fn rgb_image_u8(&mut self, data: &[u8], width: usize, height: usize, compression: DngCompression, predictor: u8) -> Result<()> { let cpp = 3; let rawimagedata = PixU16::new_with(data.iter().copied().map(u16::from).collect(), width * cpp, height); let mut cam = Camera::new(); cam.cfa = CFA::new("RGGB"); let wb_coeffs = [1.0, 1.0, 1.0, 1.0]; let blacklevel = Some(BlackLevel::new(&[0_u32, 0, 0], 1, 1, 3)); let whitelevel = Some(WhiteLevel::new_bits(8, cpp)); let photometric = RawPhotometricInterpretation::LinearRaw; let rawimage = RawImage::new(cam, rawimagedata, cpp, wb_coeffs, photometric, blacklevel, whitelevel, false); self.raw_image(&rawimage, CropMode::None, compression, DngPhotometricConversion::Original, predictor) } pub fn rgb_image_u16(&mut self, data: &[u16], width: usize, height: usize, compression: DngCompression, predictor: u8) -> Result<()> { let cpp = 3; let rawimagedata = PixU16::new_with(data.to_vec(), width * cpp, height); let mut cam = Camera::new(); cam.cfa = CFA::new("RGGB"); let wb_coeffs = [1.0, 1.0, 1.0, 1.0]; let blacklevel = Some(BlackLevel::new(&[0_u32, 0, 0], 1, 1, 3)); let whitelevel = Some(WhiteLevel::new_bits(16, cpp)); let photometric = RawPhotometricInterpretation::LinearRaw; let rawimage = RawImage::new(cam, rawimagedata, cpp, wb_coeffs, photometric, blacklevel, whitelevel, false); self.raw_image(&rawimage, CropMode::None, compression, DngPhotometricConversion::Original, predictor) } pub fn image(&mut self, _image: &RawImageData, _width: u16, _height: u16) -> Result<()> { todo!() } pub fn raw_image( &mut self, rawimage: &RawImage, cropmode: CropMode, compression: DngCompression, photometric_conversion: DngPhotometricConversion, predictor: u8, ) -> Result<()> { match photometric_conversion { DngPhotometricConversion::Original => self.write_rawimage(Cow::Borrowed(rawimage), cropmode, compression, predictor)?, DngPhotometricConversion::Linear => { if rawimage.cpp == 3 { self.write_rawimage(Cow::Borrowed(rawimage), cropmode, compression, predictor)?; } else { let rawimage = rawimage.linearize().unwrap(); // TODO: implement me self.write_rawimage(Cow::Borrowed(&rawimage), cropmode, compression, predictor)?; } } } /* for (tag, value) in rawimage.dng_tags.iter() { self.ifd.add_untyped_tag(*tag, value.clone())?; } */ Ok(()) } fn write_rawimage(&mut self, mut rawimage: Cow, cropmode: CropMode, compression: DngCompression, predictor: u8) -> Result<()> { if compression == DngCompression::Lossless && matches!(rawimage.data, RawImageData::Float(_)) { // Lossless (LJPEG92) can only be used for 16 bit integer data. // If we have floats, convert them. rawimage.to_mut().data.force_integer(); rawimage.to_mut().whitelevel.0.iter_mut().for_each(|x| *x = u16::MAX as u32); rawimage.to_mut().bps = 16; // Reset bps as intgers are scaled to u16 range. } if rawimage.cpp > 1 || matches!(rawimage.photometric, RawPhotometricInterpretation::Cfa(_)) { self.writer.as_shot_neutral(wbcoeff_to_tiff_value(&rawimage)); // Add matrix and illumninant let mut available_matrices = rawimage.color_matrix.clone(); if let Some(first_key) = available_matrices.keys().next().cloned() { let first_matrix = available_matrices .remove_entry(&Illuminant::A) .or_else(|| available_matrices.remove_entry(&Illuminant::A)) .or_else(|| available_matrices.remove_entry(&first_key)) .expect("No matrix found"); self .writer .color_matrix(1, first_matrix.0, matrix_to_tiff_value(&first_matrix.1, 10_000).as_slice()); if let Some(second_matrix) = available_matrices .remove_entry(&Illuminant::D65) .or_else(|| available_matrices.remove_entry(&Illuminant::D50)) { self .writer .color_matrix(2, second_matrix.0, matrix_to_tiff_value(&second_matrix.1, 10_000).as_slice()); } } } let full_size = Rect::new(Point::new(0, 0), Dim2::new(rawimage.width, rawimage.height)); // Active area or uncropped let active_area: Rect = match cropmode { CropMode::ActiveArea | CropMode::Best => rawimage.active_area.unwrap_or(full_size), CropMode::None => full_size, }; assert!(active_area.p.x + active_area.d.w <= rawimage.width); assert!(active_area.p.y + active_area.d.h <= rawimage.height); //self.ifd.add_tag(TiffCommonTag::NewSubFileType, 0_u16)?; // Raw self.ifd_mut().add_tag(TiffCommonTag::ImageWidth, rawimage.width as u32); self.ifd_mut().add_tag(TiffCommonTag::ImageLength, rawimage.height as u32); self.ifd_mut().add_tag(DngTag::ActiveArea, rect_to_dng_area(&active_area)); match cropmode { CropMode::ActiveArea => { let crop = active_area; assert!(crop.p.x >= active_area.p.x); assert!(crop.p.y >= active_area.p.y); self.ifd_mut().add_tag( DngTag::DefaultCropOrigin, [(crop.p.x - active_area.p.x) as u16, (crop.p.y - active_area.p.y) as u16], ); self.ifd_mut().add_tag(DngTag::DefaultCropSize, [crop.d.w as u16, crop.d.h as u16]); } CropMode::Best => { let crop = rawimage.crop_area.unwrap_or(active_area); assert!(crop.p.x >= active_area.p.x); assert!(crop.p.y >= active_area.p.y); self.ifd_mut().add_tag( DngTag::DefaultCropOrigin, [(crop.p.x - active_area.p.x) as u16, (crop.p.y - active_area.p.y) as u16], ); self.ifd_mut().add_tag(DngTag::DefaultCropSize, [crop.d.w as u16, crop.d.h as u16]); } CropMode::None => {} } self.ifd_mut().add_tag(ExifTag::PlanarConfiguration, 1_u16); self.ifd_mut().add_tag( DngTag::DefaultScale, [ Rational::new(rawimage.camera.default_scale.0[0][0], rawimage.camera.default_scale.0[0][1]), Rational::new(rawimage.camera.default_scale.0[1][0], rawimage.camera.default_scale.0[1][1]), ], ); self.ifd_mut().add_tag( DngTag::BestQualityScale, Rational::new(rawimage.camera.best_quality_scale.0[0], rawimage.camera.best_quality_scale.0[1]), ); // Whitelevel assert_eq!(rawimage.whitelevel.0.len(), rawimage.cpp, "Whitelevel sample count must match cpp"); if rawimage.whitelevel.0.iter().all(|x| *x <= (u16::MAX as u32)) { // Add as u16 self .ifd_mut() .add_tag(DngTag::WhiteLevel, &rawimage.whitelevel.0.iter().map(|x| *x as u16).collect::>()); } else { self.ifd_mut().add_tag(DngTag::WhiteLevel, &rawimage.whitelevel.0); } // Blacklevel let blacklevel = rawimage.blacklevel.shift(active_area.p.x, active_area.p.y); self .ifd_mut() .add_tag(DngTag::BlackLevelRepeatDim, [blacklevel.height as u16, blacklevel.width as u16]); if blacklevel.levels.iter().all(|x| x.d == 1) { let payload: Vec = blacklevel.levels.iter().map(|x| x.n as u32).collect(); if payload.iter().all(|x| *x <= (u16::MAX as u32)) { // Add as u16 self .ifd_mut() .add_tag(DngTag::BlackLevel, &payload.into_iter().map(|x| x as u16).collect::>()); } else { // Add as u32 self.ifd_mut().add_tag(DngTag::BlackLevel, &payload); } } else { // Add as RATIONAL self.ifd_mut().add_tag(DngTag::BlackLevel, blacklevel.levels.as_slice()); } if !rawimage.blackareas.is_empty() { let data: Vec = rawimage.blackareas.iter().flat_map(rect_to_dng_area).collect(); self.ifd_mut().add_tag(DngTag::MaskedAreas, &data); } self.ifd_mut().add_tag(TiffCommonTag::SamplesPerPixel, rawimage.cpp as u16); match &rawimage.photometric { RawPhotometricInterpretation::BlackIsZero => { assert_eq!(rawimage.cpp, 1); self.ifd_mut().add_tag(TiffCommonTag::PhotometricInt, PhotometricInterpretation::BlackIsZero); } RawPhotometricInterpretation::Cfa(config) => { assert!(config.cfa.is_valid()); assert_eq!(rawimage.cpp, 1); let cfa = config.cfa.shift(active_area.p.x, active_area.p.y); self .ifd_mut() .add_tag(TiffCommonTag::CFARepeatPatternDim, [cfa.width as u16, cfa.height as u16]); self.ifd_mut().add_tag(TiffCommonTag::CFAPattern, &cfa.flat_pattern()[..]); self.ifd_mut().add_tag(TiffCommonTag::PhotometricInt, PhotometricInterpretation::CFA); self.ifd_mut().add_tag(DngTag::CFAPlaneColor, &config.colors); self.ifd_mut().add_tag(DngTag::CFALayout, 1_u16); // Square layout } RawPhotometricInterpretation::LinearRaw => { self.ifd_mut().add_tag(TiffCommonTag::PhotometricInt, PhotometricInterpretation::LinearRaw); } } match compression { DngCompression::Uncompressed => { self.ifd_mut().add_tag(TiffCommonTag::Compression, CompressionMethod::None); dng_put_raw_uncompressed(self, &rawimage)?; } DngCompression::Lossless => { self.ifd_mut().add_tag(TiffCommonTag::Compression, CompressionMethod::ModernJPEG); dng_put_raw_ljpeg(self, &rawimage, predictor)?; } } /* for (tag, value) in rawimage.dng_tags.iter() { self.ifd.add_untyped_tag(*tag, value.clone())?; } */ Ok(()) } pub fn preview(&mut self, img: &DynamicImage, quality: f32) -> Result<()> { let now = Instant::now(); let preview_img = DynamicImage::ImageRgb8(img.resize(1024, 768, FilterType::Nearest).to_rgb8()); debug!("preview downscale: {} s", now.elapsed().as_secs_f32()); self.ifd_mut().add_tag(TiffCommonTag::ImageWidth, Value::long(preview_img.width())); self.ifd_mut().add_tag(TiffCommonTag::ImageLength, Value::long(preview_img.height())); self.ifd_mut().add_tag(TiffCommonTag::Compression, CompressionMethod::ModernJPEG); self.ifd_mut().add_tag(TiffCommonTag::BitsPerSample, [8_u16, 8, 8]); self.ifd_mut().add_tag(TiffCommonTag::SampleFormat, [1_u16, 1, 1]); self.ifd_mut().add_tag(TiffCommonTag::PhotometricInt, PhotometricInterpretation::YCbCr); self.ifd_mut().add_tag(TiffCommonTag::RowsPerStrip, Value::long(preview_img.height())); self.ifd_mut().add_tag(TiffCommonTag::SamplesPerPixel, 3_u16); self.ifd_mut().add_tag(DngTag::PreviewColorSpace, PreviewColorSpace::SRgb); // ?? //ifd.add_tag(TiffRootTag::XResolution, Rational { n: 1, d: 1 })?; //ifd.add_tag(TiffRootTag::YResolution, Rational { n: 1, d: 1 })?; //ifd.add_tag(TiffRootTag::ResolutionUnit, ResolutionUnit::None.to_u16())?; let now = Instant::now(); let offset = self.writer.dng.position()?; // TODO: improve offsets? let jpeg_encoder = JpegEncoder::new_with_quality(&mut self.writer.dng.writer, (quality * 100.0).max(100.0) as u8); preview_img .write_with_encoder(jpeg_encoder) .map_err(|err| io::Error::new(io::ErrorKind::Other, format!("Failed to write jpeg preview: {:?}", err)))?; let data_len = self.writer.dng.position()? - offset; debug!("writing preview: {} s", now.elapsed().as_secs_f32()); self.ifd_mut().add_value(TiffCommonTag::StripOffsets, Value::Long(vec![offset])); self.ifd_mut().add_tag(TiffCommonTag::StripByteCounts, Value::Long(vec![data_len])); Ok(()) } pub fn finalize(self) -> Result<()> { if let Some(ifd) = self.ifd { let offset = ifd.build(&mut self.writer.dng)?; self.writer.subs.push(offset); } Ok(()) } } impl DngWriter where B: Write + Seek, { pub fn new(buf: B, backward_version: [u8; 4]) -> Result { let dng = TiffWriter::new(buf)?; let mut root_ifd = DirectoryWriter::new(); let mut exif_ifd = DirectoryWriter::new(); root_ifd.add_tag(DngTag::DNGBackwardVersion, backward_version); root_ifd.add_tag(DngTag::DNGVersion, DNG_VERSION_V1_6); // Add EXIF version 0220 exif_ifd.add_tag_undefined(ExifTag::ExifVersion, vec![48, 50, 50, 48]); Ok(Self { dng, root_ifd, exif_ifd, subs: Vec::new(), }) } pub fn as_shot_neutral(&mut self, wb: impl AsRef<[Rational]>) { // Only write tag if wb is valid if wb.as_ref()[0].n != 0 { self.root_ifd.add_tag(DngTag::AsShotNeutral, wb.as_ref()); } } pub fn color_matrix(&mut self, slot: usize, illu: Illuminant, matrix: impl AsRef<[SRational]>) { match slot { 1 => { self.root_ifd.add_tag(DngTag::CalibrationIlluminant1, u16::from(illu)); self.root_ifd.add_tag(DngTag::ColorMatrix1, matrix.as_ref()); } 2 => { self.root_ifd.add_tag(DngTag::CalibrationIlluminant2, u16::from(illu)); self.root_ifd.add_tag(DngTag::ColorMatrix2, matrix.as_ref()); } _ => todo!(), } } pub fn load_metadata(&mut self, metadata: &RawMetadata) -> Result<()> { metadata.write_exif_tags(&mut self.dng, &mut self.root_ifd, &mut self.exif_ifd)?; // DNG has a lens info tag that is identical to the LensSpec tag in EXIF IFD transfer_entry(&mut self.root_ifd, DngTag::LensInfo, &metadata.exif.lens_spec)?; if let Some(id) = &metadata.unique_image_id { self.root_ifd.add_tag(DngTag::RawDataUniqueID, id.to_le_bytes()); } Ok(()) } pub fn xpacket(&mut self, xpacket: impl AsRef<[u8]>) -> Result<()> { self.root_ifd.add_tag(ExifTag::ApplicationNotes, xpacket.as_ref()); Ok(()) } pub fn load_base_tags(&mut self, rawimage: &RawImage) -> Result<()> { self.root_ifd.add_tag(TiffCommonTag::Make, rawimage.clean_make.as_str()); self.root_ifd.add_tag(TiffCommonTag::Model, rawimage.clean_model.as_str()); let uq_model = format!("{} {}", rawimage.clean_make, rawimage.clean_model); self.root_ifd.add_tag(DngTag::UniqueCameraModel, uq_model.as_str()); Ok(()) } pub fn close(mut self) -> Result<()> { if !self.exif_ifd.is_empty() { let exif_ifd_offset = self.exif_ifd.build(&mut self.dng)?; self.root_ifd.add_tag(TiffCommonTag::ExifIFDPointer, exif_ifd_offset); } // Add SubIFDs if !self.subs.is_empty() { self.root_ifd.add_tag(TiffCommonTag::SubIFDs, &self.subs); } self.dng.build(self.root_ifd)?; Ok(()) } pub fn original_file(&mut self, original: &OriginalCompressed, filename: impl AsRef) -> Result<()> { let mut buf = std::io::Cursor::new(Vec::new()); original.write_to_stream(&mut buf)?; self.root_ifd.add_tag_undefined(DngTag::OriginalRawFileData, buf.into_inner()); self.root_ifd.add_tag(DngTag::OriginalRawFileName, filename.as_ref()); if let Some(digest) = original.digest() { self.root_ifd.add_tag(DngTag::OriginalRawFileDigest, digest); } Ok(()) } pub fn subframe(&mut self, id: u32) -> SubFrameWriter<'_, B> { SubFrameWriter::new(self, id, false) } pub fn subframe_on_root(&mut self, id: u32) -> SubFrameWriter<'_, B> { SubFrameWriter::new(self, id, true) } /// Write thumbnail image into DNG pub fn thumbnail(&mut self, img: &DynamicImage) -> Result<()> { let thumb_img = img.resize(240, 120, FilterType::Nearest).to_rgb8(); self.root_ifd.add_tag(TiffCommonTag::NewSubFileType, 1_u32); self.root_ifd.add_tag(TiffCommonTag::ImageWidth, thumb_img.width() as u32); self.root_ifd.add_tag(TiffCommonTag::ImageLength, thumb_img.height() as u32); self.root_ifd.add_tag(TiffCommonTag::Compression, CompressionMethod::None); self.root_ifd.add_tag(TiffCommonTag::BitsPerSample, [8_u16, 8, 8]); self.root_ifd.add_tag(TiffCommonTag::SampleFormat, [1_u16, 1, 1]); self.root_ifd.add_tag(TiffCommonTag::PhotometricInt, PhotometricInterpretation::RGB); self.root_ifd.add_tag(TiffCommonTag::SamplesPerPixel, 3_u16); //ifd.add_tag(TiffRootTag::XResolution, Rational { n: 1, d: 1 })?; //ifd.add_tag(TiffRootTag::YResolution, Rational { n: 1, d: 1 })?; //ifd.add_tag(TiffRootTag::ResolutionUnit, ResolutionUnit::None.to_u16())?; let offset = self.dng.write_data(&thumb_img)?; self.root_ifd.add_tag(TiffCommonTag::StripOffsets, offset); self.root_ifd.add_tag(TiffCommonTag::StripByteCounts, thumb_img.len() as u32); self.root_ifd.add_tag(TiffCommonTag::RowsPerStrip, thumb_img.height() as u32); Ok(()) } pub fn root_ifd(&mut self) -> &DirectoryWriter { &self.root_ifd } pub fn root_ifd_mut(&mut self) -> &mut DirectoryWriter { &mut self.root_ifd } pub fn exif_ifd(&mut self) -> &DirectoryWriter { &self.exif_ifd } pub fn exif_ifd_mut(&mut self) -> &mut DirectoryWriter { &mut self.exif_ifd } } /// DNG requires the WB values to be the reciprocal fn wbcoeff_to_tiff_value(rawimage: &RawImage) -> Vec { let wb = &rawimage.wb_coeffs; match &rawimage.photometric { RawPhotometricInterpretation::BlackIsZero => { vec![Rational::new(1, 1)] // TODO: is this useful? } RawPhotometricInterpretation::Cfa(config) => { assert!([1, 3, 4].contains(&config.cfa.unique_colors())); let mut values = Vec::with_capacity(4); values.push(Rational::new_f32(1.0 / wb[0], 100000)); values.push(Rational::new_f32(1.0 / wb[1], 100000)); values.push(Rational::new_f32(1.0 / wb[2], 100000)); if config.cfa.unique_colors() == 4 { values.push(Rational::new_f32(1.0 / wb[3], 100000)); } values } RawPhotometricInterpretation::LinearRaw => { //assert_eq!(rawimage.cpp, 3); match rawimage.cpp { 1 => { vec![Rational::new(1, 1)] } 3 => { let mut values = Vec::with_capacity(3); values.push(Rational::new_f32(1.0 / wb[0], 100000)); values.push(Rational::new_f32(1.0 / wb[1], 100000)); values.push(Rational::new_f32(1.0 / wb[2], 100000)); values } _ => todo!(), } } } } fn matrix_to_tiff_value(xyz_to_cam: &[f32], d: i32) -> Vec { xyz_to_cam.iter().map(|a| SRational::new((a * d as f32) as i32, d)).collect() } /// Compress RAW image with LJPEG-92 /// /// Data is split into multiple tiles, each tile is compressed seperately /// /// Predictor mode 4,5,6,7 is best for images where two images /// lines are merged, because then the image bayer pattern is: /// RGRGGBGB /// RGRGGBGB /// Instead of the default: /// RGRG /// GBGB /// RGRG /// GBGB fn dng_put_raw_ljpeg(subframe: &mut SubFrameWriter, rawimage: &RawImage, predictor: u8) -> Result<()> where W: Seek + Write, { let tile_w = 256 & !0b111; // ensure div 16 let tile_h = 256 & !0b111; let lj92_data = match rawimage.data { RawImageData::Integer(ref data) => { // Inject black pixel data for testing purposes. // let data = vec![0x0000; data.len()]; //let tiled_data = TiledData::new(&data, rawimage.width, rawimage.height, rawimage.cpp); // Only merge two lines into one for higher predictors, if image is CFA let tiled_data: Vec> = ImageTiler::new(data, rawimage.width, rawimage.height, rawimage.cpp, tile_w, tile_h).collect(); let (j_width, j_height, components, realign) = match &rawimage.photometric { RawPhotometricInterpretation::BlackIsZero => { assert_eq!(rawimage.cpp, 1); (tile_w, tile_h, 1, 1) } RawPhotometricInterpretation::Cfa(config) => { assert_eq!(rawimage.cpp, 1); let realign = if (4..=7).contains(&predictor) && config.cfa.width == 2 && config.cfa.height == 2 { 2 } else { 1 }; (tile_w / 2, tile_h, 2, realign) } RawPhotometricInterpretation::LinearRaw => { (tile_w, tile_h, rawimage.cpp, 1) /* RGB LinearRaw */ } }; debug!("LJPEG compression: bit depth: {}", rawimage.bps); let tiles_compr: Vec> = tiled_data .par_iter() .map(|tile| { //assert_eq!((tile_w * rawimage.cpp) % components, 0); //assert_eq!((tile_w * rawimage.cpp) % 2, 0); //assert_eq!(tile_h % 2, 0); let state = LjpegCompressor::new(tile, j_width * realign, j_height / realign, components, rawimage.bps as u8, predictor, 0, 0).unwrap(); state.encode().unwrap() }) .collect(); tiles_compr } RawImageData::Float(ref _data) => { panic!("invalid format"); } }; let mut tile_offsets: Vec = Vec::new(); let mut tile_sizes: Vec = Vec::new(); lj92_data.iter().for_each(|tile| { let offs = subframe.writer.dng.write_data(tile).unwrap(); tile_offsets.push(offs); tile_sizes.push((tile.len() * size_of::()) as u32); }); subframe .ifd_mut() .add_tag(TiffCommonTag::BitsPerSample, &vec![rawimage.bps as u16; rawimage.cpp]); subframe.ifd_mut().add_tag(TiffCommonTag::SampleFormat, &vec![1_u16; rawimage.cpp]); subframe.ifd_mut().add_tag(TiffCommonTag::TileOffsets, &tile_offsets); subframe.ifd_mut().add_tag(TiffCommonTag::TileByteCounts, &tile_sizes); subframe.ifd_mut().add_tag(TiffCommonTag::TileWidth, tile_w as u16); subframe.ifd_mut().add_tag(TiffCommonTag::TileLength, tile_h as u16); Ok(()) } /// Write RAW uncompressed into DNG /// /// This uses unsigned 16 bit values for storage /// Data is split into multiple strips fn dng_put_raw_uncompressed(subframe: &mut SubFrameWriter, rawimage: &RawImage) -> Result<()> where W: Write + Seek, { let mut strip_offsets: Vec = Vec::new(); let mut strip_sizes: Vec = Vec::new(); let mut strip_rows: Vec = Vec::new(); let rows_per_strip = if rawimage.height > 1000 { 256 } else { rawimage.height }; match rawimage.data { RawImageData::Integer(ref data) => { for strip in data.chunks(rows_per_strip * rawimage.width * rawimage.cpp) { let offset = subframe.writer.dng.write_data_u16_le(strip)?; strip_offsets.push(offset); strip_sizes.push(std::mem::size_of_val(strip) as u32); strip_rows.push((strip.len() / (rawimage.width * rawimage.cpp)) as u32); } subframe.ifd_mut().add_tag(TiffCommonTag::SampleFormat, &vec![1_u16; rawimage.cpp]); // Unsigned Integer subframe.ifd_mut().add_tag(TiffCommonTag::BitsPerSample, &vec![16_u16; rawimage.cpp]); } RawImageData::Float(ref data) => { for strip in data.chunks(rows_per_strip * rawimage.width * rawimage.cpp) { let offset = subframe.writer.dng.write_data_f32_le(strip)?; strip_offsets.push(offset); strip_sizes.push(std::mem::size_of_val(strip) as u32); strip_rows.push((strip.len() / (rawimage.width * rawimage.cpp)) as u32); } subframe.ifd_mut().add_tag(TiffCommonTag::SampleFormat, &vec![3_u16; rawimage.cpp]); // IEEE Float subframe.ifd_mut().add_tag(TiffCommonTag::BitsPerSample, &vec![32_u16; rawimage.cpp]); } }; subframe.ifd_mut().add_tag(TiffCommonTag::StripOffsets, &strip_offsets); subframe.ifd_mut().add_tag(TiffCommonTag::StripByteCounts, &strip_sizes); subframe.ifd_mut().add_tag(TiffCommonTag::RowsPerStrip, &strip_rows); Ok(()) } #[cfg(test)] mod tests { use std::io::Cursor; use crate::dng::DNG_VERSION_V1_4; use super::*; #[test] fn build_empty_dng() -> std::result::Result<(), Box> { let mut buf = Cursor::new(Vec::new()); let mut dng = DngWriter::new(&mut buf, DNG_VERSION_V1_4)?; dng.root_ifd_mut().add_tag(TiffCommonTag::Artist, "Test"); dng.close()?; let expected_output = [ 73, 73, 42, 0, 36, 0, 0, 0, 1, 0, 0, 144, 7, 0, 4, 0, 0, 0, 48, 50, 50, 48, 0, 0, 0, 0, 0, 0, 84, 101, 115, 116, 0, 0, 0, 0, 4, 0, 59, 1, 2, 0, 5, 0, 0, 0, 28, 0, 0, 0, 105, 135, 4, 0, 1, 0, 0, 0, 8, 0, 0, 0, 18, 198, 1, 0, 4, 0, 0, 0, 1, 6, 0, 0, 19, 198, 1, 0, 4, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, ]; assert_eq!(expected_output, buf.into_inner().as_slice()); Ok(()) } #[cfg(feature = "samplecheck")] #[test] fn convert_canon_cr3_to_dng() -> std::result::Result<(), Box> { use crate::{ decoders::RawDecodeParams, dng::{DNG_VERSION_V1_4, PREVIEW_JPEG_QUALITY}, rawsource::RawSource, }; use std::{ fs::File, io::{BufReader, BufWriter}, path::PathBuf, }; let mut rawdb = PathBuf::from(std::env::var("RAWLER_RAWDB").expect("RAWLER_RAWDB variable must be set in order to run RAW test!")); rawdb.push("cameras/Canon/EOS R6/raw_modes/Canon EOS R6_RAW_ISO_100_nocrop_nodual.CR3"); let rawfile = RawSource::new(&rawdb)?; let original_thread = std::thread::spawn(|| OriginalCompressed::compress(&mut BufReader::new(File::open(rawdb).unwrap()))); let decoder = crate::get_decoder(&rawfile)?; let rawimage = decoder.raw_image(&rawfile, &RawDecodeParams::default(), false)?; let full_image = decoder.full_image(&rawfile, &RawDecodeParams::default())?.unwrap(); let metadata = decoder.raw_metadata(&rawfile, &RawDecodeParams::default())?; let predictor = 1; let buf = BufWriter::new(Cursor::new(Vec::new())); //let buf = BufWriter::new(File::create("/tmp/dng_writer_simple_test.dng")?); let mut dng = DngWriter::new(buf, DNG_VERSION_V1_4)?; let mut raw = dng.subframe(0); raw.raw_image( &rawimage, CropMode::Best, DngCompression::Lossless, DngPhotometricConversion::Original, predictor, )?; raw.finalize()?; dng.thumbnail(&full_image)?; let mut preview = dng.subframe(1); preview.preview(&full_image, PREVIEW_JPEG_QUALITY)?; preview.finalize()?; dng.load_base_tags(&rawimage)?; dng.load_metadata(&metadata)?; if let Some(xpacket) = decoder.xpacket(&rawfile, &RawDecodeParams::default())? { dng.xpacket(xpacket)?; } let original = original_thread.join().unwrap()?; dng.original_file(&original, "test.CR3")?; dng.close()?; Ok(()) } } rawler-0.7.1/src/envparams.rs000064400000000000000000000012551046102023000142610ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher use log::warn; pub(crate) fn rawler_ignore_previews() -> bool { match std::env::var("RAWLER_IGNORE_PREVIEWS").map(|val| val.parse::()) { Ok(Ok(value)) => value == 1, Ok(Err(_)) => { warn!("Invalid value for RAWLER_IGNORE_PREVIEWS"); false } Err(_) => false, } } pub(crate) fn rawler_crx_raw_trak() -> Option { match std::env::var("RAWLER_CRX_RAW_TRAK").map(|val| val.parse::()) { Ok(Ok(value)) => Some(value), Ok(Err(_)) => { warn!("Invalid value for RAWLER_CRX_RAW_TRAK"); None } Err(_) => None, } } rawler-0.7.1/src/exif.rs000064400000000000000000000330751046102023000132250ustar 00000000000000use serde::{Deserialize, Serialize}; use crate::{ formats::tiff::{IFD, Rational, Result, SRational, Value}, lens::LensDescription, tags::{ExifGpsTag, ExifTag}, }; use std::convert::TryInto; /// This struct contains the EXIF information. /// If a property accepts diffent data types, the type with /// the best accuracy is choosen. #[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Exif { pub orientation: Option, pub copyright: Option, pub artist: Option, pub lens_spec: Option<[Rational; 4]>, pub exposure_time: Option, pub fnumber: Option, pub aperture_value: Option, pub brightness_value: Option, pub iso_speed_ratings: Option, pub iso_speed: Option, pub recommended_exposure_index: Option, pub sensitivity_type: Option, pub exposure_bias: Option, pub date_time_original: Option, pub create_date: Option, pub modify_date: Option, pub exposure_program: Option, pub timezone_offset: Option>, pub offset_time: Option, pub offset_time_original: Option, pub offset_time_digitized: Option, pub sub_sec_time: Option, pub sub_sec_time_original: Option, pub sub_sec_time_digitized: Option, pub shutter_speed_value: Option, pub max_aperture_value: Option, pub subject_distance: Option, pub metering_mode: Option, pub light_source: Option, pub flash: Option, pub focal_length: Option, pub image_number: Option, pub color_space: Option, pub flash_energy: Option, pub exposure_mode: Option, pub white_balance: Option, pub scene_capture_type: Option, pub subject_distance_range: Option, pub owner_name: Option, pub serial_number: Option, pub lens_serial_number: Option, pub lens_make: Option, pub lens_model: Option, pub gps: Option, pub user_comment: Option, //pub makernotes: Option>, } #[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct ExifGPS { pub gps_version_id: Option<[u8; 4]>, pub gps_latitude_ref: Option, pub gps_latitude: Option<[Rational; 3]>, pub gps_longitude_ref: Option, pub gps_longitude: Option<[Rational; 3]>, pub gps_altitude_ref: Option, pub gps_altitude: Option, pub gps_timestamp: Option<[Rational; 3]>, pub gps_satellites: Option, pub gps_status: Option, pub gps_measure_mode: Option, pub gps_dop: Option, pub gps_speed_ref: Option, pub gps_speed: Option, pub gps_track_ref: Option, pub gps_track: Option, pub gps_img_direction_ref: Option, pub gps_img_direction: Option, pub gps_map_datum: Option, pub gps_dest_latitude_ref: Option, pub gps_dest_latitude: Option<[Rational; 3]>, pub gps_dest_longitude_ref: Option, pub gps_dest_longitude: Option<[Rational; 3]>, pub gps_dest_bearing_ref: Option, pub gps_dest_bearing: Option, pub gps_dest_distance_ref: Option, pub gps_dest_distance: Option, pub gps_processing_method: Option>, pub gps_area_information: Option>, pub gps_date_stamp: Option, pub gps_differential: Option, pub gps_h_positioning_error: Option, } impl Exif { /// Read EXIF data. As some EXIF tags located in the root IFD, /// we accept both IFDs here. pub fn new(root_or_exif: &IFD) -> Result { let mut ins = Self::default(); ins.extend_from_ifd(root_or_exif)?; if let Some(exif_ifd) = root_or_exif.get_sub_ifd(ExifTag::ExifOffset) { ins.extend_from_ifd(exif_ifd)?; } // Search for GPSInfo tag, usually it is located in IFD0 if let Some(gpsinfo_ifd) = root_or_exif.get_sub_ifd(ExifTag::GPSInfo) { ins.extend_from_gps_ifd(gpsinfo_ifd)?; } Ok(ins) } /// Extend the EXIF info from this IFD. If the IFD contains a ExifIFD, /// extend from this IFD, too. pub fn extend_from_ifd(&mut self, ifd: &IFD) -> Result<()> { let trim = |a: &String| -> String { a.trim().into() }; for (tag, entry) in ifd.entries().iter() { // First try EXIF tags if let Ok(tag) = ExifTag::try_from(*tag) { match (tag, &entry.value) { (ExifTag::Orientation, Value::Short(data)) => self.orientation = data.get(0).cloned(), (ExifTag::Copyright, Value::Ascii(data)) => self.copyright = data.strings().get(0).map(trim), (ExifTag::Artist, Value::Ascii(data)) => self.artist = data.strings().get(0).map(trim), (ExifTag::ExposureTime, Value::Rational(data)) => self.exposure_time = data.get(0).cloned(), (ExifTag::FNumber, Value::Rational(data)) => self.fnumber = data.get(0).cloned(), (ExifTag::BrightnessValue, Value::SRational(data)) => self.brightness_value = data.get(0).cloned(), (ExifTag::ApertureValue, Value::Rational(data)) => self.aperture_value = data.get(0).cloned(), (ExifTag::ISOSpeedRatings, Value::Short(data)) => self.iso_speed_ratings = data.get(0).cloned(), (ExifTag::ISOSpeed, Value::Long(data)) => self.iso_speed = data.get(0).cloned(), (ExifTag::RecommendedExposureIndex, Value::Long(data)) => self.recommended_exposure_index = data.get(0).cloned(), (ExifTag::SensitivityType, Value::Short(data)) => self.sensitivity_type = data.get(0).cloned(), (ExifTag::ExposureBiasValue, Value::SRational(data)) => self.exposure_bias = data.get(0).cloned(), (ExifTag::DateTimeOriginal, Value::Ascii(data)) => self.date_time_original = data.strings().get(0).cloned(), (ExifTag::CreateDate, Value::Ascii(data)) => self.create_date = data.strings().get(0).cloned(), (ExifTag::ModifyDate, Value::Ascii(data)) => self.modify_date = data.strings().get(0).cloned(), (ExifTag::ExposureProgram, Value::Short(data)) => self.exposure_program = data.get(0).cloned(), (ExifTag::TimeZoneOffset, Value::SShort(data)) => self.timezone_offset = Some(data.clone()), (ExifTag::OffsetTime, Value::Ascii(data)) => self.offset_time = data.strings().get(0).cloned(), (ExifTag::OffsetTimeOriginal, Value::Ascii(data)) => self.offset_time_original = data.strings().get(0).cloned(), (ExifTag::OffsetTimeDigitized, Value::Ascii(data)) => self.offset_time_digitized = data.strings().get(0).cloned(), (ExifTag::SubSecTime, Value::Ascii(data)) => self.sub_sec_time = data.strings().get(0).cloned(), (ExifTag::SubSecTimeOriginal, Value::Ascii(data)) => self.sub_sec_time_original = data.strings().get(0).cloned(), (ExifTag::SubSecTimeDigitized, Value::Ascii(data)) => self.sub_sec_time_digitized = data.strings().get(0).cloned(), (ExifTag::ShutterSpeedValue, Value::SRational(data)) => self.shutter_speed_value = data.get(0).cloned(), (ExifTag::MaxApertureValue, Value::Rational(data)) => self.max_aperture_value = data.get(0).cloned(), (ExifTag::SubjectDistance, Value::Rational(data)) => self.subject_distance = data.get(0).cloned(), (ExifTag::MeteringMode, Value::Short(data)) => self.metering_mode = data.get(0).cloned(), (ExifTag::LightSource, Value::Short(data)) => self.light_source = data.get(0).cloned(), (ExifTag::Flash, Value::Short(data)) => self.flash = data.get(0).cloned(), (ExifTag::FocalLength, Value::Rational(data)) => self.focal_length = data.get(0).cloned(), (ExifTag::ImageNumber, Value::Long(data)) => self.image_number = data.get(0).cloned(), (ExifTag::ColorSpace, Value::Short(data)) => self.color_space = data.get(0).cloned(), (ExifTag::FlashEnergy, Value::Rational(data)) => self.flash_energy = data.get(0).cloned(), (ExifTag::ExposureMode, Value::Short(data)) => self.exposure_mode = data.get(0).cloned(), (ExifTag::WhiteBalance, Value::Short(data)) => self.white_balance = data.get(0).cloned(), (ExifTag::SceneCaptureType, Value::Short(data)) => self.scene_capture_type = data.get(0).cloned(), (ExifTag::SubjectDistanceRange, Value::Short(data)) => self.subject_distance_range = data.get(0).cloned(), (ExifTag::OwnerName, Value::Ascii(data)) => self.owner_name = data.strings().get(0).map(trim), (ExifTag::SerialNumber, Value::Ascii(data)) => self.serial_number = data.strings().get(0).map(trim), (ExifTag::LensSerialNumber, Value::Ascii(data)) => self.lens_serial_number = data.strings().get(0).map(trim), (ExifTag::UserComment, Value::Ascii(data)) => self.user_comment = data.strings().get(0).map(trim), //(ExifTag::MakerNotes, Value::Undefined(data)) => self.makernotes = Some(data.clone()), (tag, _value) => { log::debug!("Ignoring EXIF tag: {:?}", tag); } } } } Ok(()) } /// Extend the EXIF info from this IFD. If the IFD contains a ExifIFD, /// extend from this IFD, too. pub fn extend_from_gps_ifd(&mut self, ifd: &IFD) -> Result<()> { for (tag, entry) in ifd.entries().iter() { if let Ok(tag) = ExifGpsTag::try_from(*tag) { // We hit a GPS tag, make sure the gps property is initialized. if self.gps.is_none() { self.gps = Some(ExifGPS::default()); } if let Some(gps) = &mut self.gps { match (tag, &entry.value) { (ExifGpsTag::GPSVersionID, Value::Byte(data)) => gps.gps_version_id = data.clone().try_into().ok(), (ExifGpsTag::GPSLatitudeRef, Value::Ascii(data)) => gps.gps_latitude_ref = data.strings().get(0).cloned(), (ExifGpsTag::GPSLatitude, Value::Rational(data)) => gps.gps_latitude = data.clone().try_into().ok(), (ExifGpsTag::GPSLongitudeRef, Value::Ascii(data)) => gps.gps_longitude_ref = data.strings().get(0).cloned(), (ExifGpsTag::GPSLongitude, Value::Rational(data)) => gps.gps_longitude = data.clone().try_into().ok(), (ExifGpsTag::GPSAltitudeRef, Value::Byte(data)) => gps.gps_altitude_ref = data.get(0).cloned(), (ExifGpsTag::GPSAltitude, Value::Rational(data)) => gps.gps_altitude = data.get(0).cloned(), (ExifGpsTag::GPSTimeStamp, Value::Rational(data)) => gps.gps_timestamp = data.clone().try_into().ok(), (ExifGpsTag::GPSSatellites, Value::Ascii(data)) => gps.gps_satellites = data.strings().get(0).cloned(), (ExifGpsTag::GPSStatus, Value::Ascii(data)) => gps.gps_status = data.strings().get(0).cloned(), (ExifGpsTag::GPSMeasureMode, Value::Ascii(data)) => gps.gps_measure_mode = data.strings().get(0).cloned(), (ExifGpsTag::GPSDOP, Value::Rational(data)) => gps.gps_dop = data.get(0).cloned(), (ExifGpsTag::GPSSpeedRef, Value::Ascii(data)) => gps.gps_speed_ref = data.strings().get(0).cloned(), (ExifGpsTag::GPSSpeed, Value::Rational(data)) => gps.gps_speed = data.get(0).cloned(), (ExifGpsTag::GPSTrackRef, Value::Ascii(data)) => gps.gps_track_ref = data.strings().get(0).cloned(), (ExifGpsTag::GPSTrack, Value::Rational(data)) => gps.gps_track = data.get(0).cloned(), (ExifGpsTag::GPSImgDirectionRef, Value::Ascii(data)) => gps.gps_img_direction_ref = data.strings().get(0).cloned(), (ExifGpsTag::GPSImgDirection, Value::Rational(data)) => gps.gps_img_direction = data.get(0).cloned(), (ExifGpsTag::GPSMapDatum, Value::Ascii(data)) => gps.gps_map_datum = data.strings().get(0).cloned(), (ExifGpsTag::GPSDestLatitudeRef, Value::Ascii(data)) => gps.gps_dest_latitude_ref = data.strings().get(0).cloned(), (ExifGpsTag::GPSDestLatitude, Value::Rational(data)) => gps.gps_dest_latitude = data.clone().try_into().ok(), (ExifGpsTag::GPSDestLongitudeRef, Value::Ascii(data)) => gps.gps_dest_longitude_ref = data.strings().get(0).cloned(), (ExifGpsTag::GPSDestLongitude, Value::Rational(data)) => gps.gps_dest_longitude = data.clone().try_into().ok(), (ExifGpsTag::GPSDestBearingRef, Value::Ascii(data)) => gps.gps_dest_bearing_ref = data.strings().get(0).cloned(), (ExifGpsTag::GPSDestBearing, Value::Rational(data)) => gps.gps_dest_bearing = data.get(0).cloned(), (ExifGpsTag::GPSDestDistanceRef, Value::Ascii(data)) => gps.gps_dest_distance_ref = data.strings().get(0).cloned(), (ExifGpsTag::GPSDestDistance, Value::Rational(data)) => gps.gps_dest_distance = data.get(0).cloned(), (ExifGpsTag::GPSProcessingMethod, Value::Undefined(data)) => gps.gps_processing_method = Some(data.clone()), (ExifGpsTag::GPSAreaInformation, Value::Undefined(data)) => gps.gps_area_information = Some(data.clone()), (ExifGpsTag::GPSDateStamp, Value::Ascii(data)) => gps.gps_date_stamp = data.strings().get(0).cloned(), (ExifGpsTag::GPSDifferential, Value::Short(data)) => gps.gps_differential = data.get(0).cloned(), (ExifGpsTag::GPSHPositioningError, Value::Rational(data)) => gps.gps_h_positioning_error = data.get(0).cloned(), (tag, _value) => { log::debug!("Ignoring EXIF GPS tag: {:?}", tag); } } } } } Ok(()) } pub(crate) fn extend_from_lens(&mut self, lens: &LensDescription) { let lens_info: [Rational; 4] = [lens.focal_range[0], lens.focal_range[1], lens.aperture_range[0], lens.aperture_range[1]]; self.lens_spec = Some(lens_info); self.lens_make = Some(lens.lens_make.clone()); self.lens_model = Some(lens.lens_model.clone()); } } rawler-0.7.1/src/formats/bmff/co64.rs000064400000000000000000000021661046102023000154270ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; use super::{BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct Co64Box { pub header: BoxHeader, pub version: u8, pub flags: u32, pub entries: Vec, } impl Co64Box { pub const TYP: FourCC = FourCC::with(['c', 'o', '6', '4']); } impl ReadBox<&mut R> for Co64Box { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; let entry_count = reader.read_u32::()?; let mut entries = Vec::with_capacity(entry_count as usize); for _i in 0..entry_count { let chunk_offset = reader.read_u64::()?; entries.push(chunk_offset); } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags, entries, }) } } rawler-0.7.1/src/formats/bmff/dinf.rs000064400000000000000000000012171046102023000155700ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, FourCC, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct DinfBox { pub header: BoxHeader, } impl DinfBox { pub const TYP: FourCC = FourCC::with(['d', 'i', 'n', 'f']); } impl ReadBox<&mut R> for DinfBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/ccdt.rs000064400000000000000000000017061046102023000171370ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::super::{BoxHeader, FourCC, ReadBox, Result}; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct CcdtBox { pub header: BoxHeader, pub image_type: u64, pub dual_pixel: u32, pub trak_index: u32, } impl CcdtBox { pub const TYP: FourCC = FourCC::with(['C', 'C', 'D', 'T']); } impl ReadBox<&mut R> for CcdtBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let image_type = reader.read_u64::()?; let dual_pixel = reader.read_u32::()?; let trak_index = reader.read_u32::()?; reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, image_type, dual_pixel, trak_index, }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/cctp.rs000064400000000000000000000032211046102023000171450ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use byteorder::{BigEndian, ReadBytesExt}; use log::debug; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; use super::{ super::{BmffError, BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}, ccdt::CcdtBox, }; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct CctpBox { pub header: BoxHeader, pub version: u8, pub flags: u32, pub unknown1: u32, pub lines: u32, pub ccdts: Vec, } impl CctpBox { pub const TYP: FourCC = FourCC::with(['C', 'C', 'T', 'P']); } impl ReadBox<&mut R> for CctpBox { fn read_box(mut reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; let unknown1 = reader.read_u32::()?; let lines = reader.read_u32::()?; let mut ccdts = Vec::new(); let mut current = reader.stream_position()?; while current < header.end_offset() { // get box? let header = BoxHeader::parse(&mut reader)?; match header.typ { CcdtBox::TYP => { let ccdt = CcdtBox::read_box(&mut reader, header)?; ccdts.push(ccdt); } _ => { debug!("Vendor box found in CCTP: {:?}", header.typ); return Err(BmffError::Parse(format!("Invalid box found in CCTP: {:?}", header.typ))); } } current = reader.stream_position()?; } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags, unknown1, lines, ccdts, }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/cdi1.rs000064400000000000000000000027371046102023000170470ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::{ super::{BmffError, BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}, iad1::Iad1Box, }; use log::debug; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Cdi1Box { pub header: BoxHeader, pub version: u8, pub flags: u32, pub iad1: Iad1Box, } impl Cdi1Box { pub const TYP: FourCC = FourCC::with(['C', 'D', 'I', '1']); } impl ReadBox<&mut R> for Cdi1Box { fn read_box(mut reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; let mut iad1 = None; let mut current = reader.stream_position()?; while current < header.end_offset() { // get box? let header = BoxHeader::parse(&mut reader)?; match header.typ { Iad1Box::TYP => { iad1 = Some(Iad1Box::read_box(&mut reader, header)?); } _ => { debug!("Vendor box found in CDI1: {:?}", header.typ); return Err(BmffError::Parse(format!("Invalid box found in CDI1: {:?}", header.typ))); } } current = reader.stream_position()?; } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags, iad1: iad1.ok_or_else(|| BmffError::Parse("IAD1 box not found, corrupt file?".into()))?, }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/cmp1.rs000064400000000000000000000066041046102023000170640ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::super::{BoxHeader, FourCC, ReadBox, Result}; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Cmp1Box { pub header: BoxHeader, pub unknown1: i16, pub header_size: u16, pub version: u16, pub version_sub: u16, pub f_width: u32, pub f_height: u32, pub tile_width: u32, pub tile_height: u32, pub n_bits: u8, pub n_planes: u8, pub cfa_layout: u8, pub enc_type: u8, pub image_levels: u8, pub has_tile_cols: u8, pub has_tile_rows: u8, pub mdat_hdr_size: u32, pub ext_header: u32, pub median_bits: u8, // TODO: missing fields } impl Cmp1Box { pub const TYP: FourCC = FourCC::with(['C', 'M', 'P', '1']); } impl ReadBox<&mut R> for Cmp1Box { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let unknown1 = reader.read_i16::()?; let header_size = reader.read_u16::()?; let version = reader.read_u16::()?; let version_sub = reader.read_u16::()?; let f_width = reader.read_u32::()?; let f_height = reader.read_u32::()?; let tile_width = reader.read_u32::()?; let tile_height = reader.read_u32::()?; let n_bits = reader.read_u8()?; let (n_planes, cfa_layout) = { let tmp = reader.read_u8()?; (tmp >> 4, tmp & 0xF) }; let (enc_type, image_levels) = { let tmp = reader.read_u8()?; (tmp >> 4, tmp & 0xF) }; let (has_tile_cols, has_tile_rows) = { let tmp = reader.read_u8()?; (tmp >> 7, tmp & 1) }; let mdat_hdr_size = reader.read_u32::()?; let ext_header = reader.read_u32::()?; // 32 // Median bit precision for enc_type 3 is not always same as // image bit precision. For CRM movie files, there is an extended header. let mut median_bits = n_bits; // CRM Movie file if (ext_header & 0x80000000 != 0) && n_planes == 4 && header.size >= 56 { let _unknow = reader.read_u32::()?; // 36 let _unknow = reader.read_u32::()?; // 40 let _unknow = reader.read_u32::()?; // 44 let _unknow = reader.read_u32::()?; // 48 let _unknow = reader.read_u32::()?; // 52 let use_median_bits = reader.read_u32::()? & 0x40000000 != 0; // 56 if use_median_bits && header.size > 84 { let _unknow = reader.read_u32::()?; // 60 let _unknow = reader.read_u32::()?; // 64 let _unknow = reader.read_u32::()?; // 68 let _unknow = reader.read_u32::()?; // 72 let _unknow = reader.read_u32::()?; // 76 let _unknow = reader.read_u32::()?; // 80 median_bits = reader.read_u8()?; // 84 } } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, unknown1, header_size, version, version_sub, f_width, f_height, tile_width, tile_height, n_bits, n_planes, cfa_layout, enc_type, image_levels, has_tile_cols, has_tile_rows, mdat_hdr_size, ext_header, median_bits, }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/cmt1.rs000064400000000000000000000020331046102023000170600ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use crate::{formats::bmff::BmffError, formats::tiff::GenericTiffReader}; use super::super::{BoxHeader, FourCC, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Cmt1Box { pub header: BoxHeader, pub data: Vec, pub tiff: GenericTiffReader, } impl Cmt1Box { pub const TYP: FourCC = FourCC::with(['C', 'M', 'T', '1']); } impl ReadBox<&mut R> for Cmt1Box { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let current = reader.stream_position()?; let data_len = header.end_offset() - current; let mut data = vec![0; data_len as usize]; reader.read_exact(&mut data)?; reader.seek(SeekFrom::Start(header.end_offset()))?; let tiff = GenericTiffReader::new_with_buffer(&data, 0, 0, None).map_err(|e| BmffError::Parse(e.to_string()))?; Ok(Self { header, data, tiff }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/cmt2.rs000064400000000000000000000020331046102023000170610ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use crate::{formats::bmff::BmffError, formats::tiff::GenericTiffReader}; use super::super::{BoxHeader, FourCC, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Cmt2Box { pub header: BoxHeader, pub data: Vec, pub tiff: GenericTiffReader, } impl Cmt2Box { pub const TYP: FourCC = FourCC::with(['C', 'M', 'T', '2']); } impl ReadBox<&mut R> for Cmt2Box { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let current = reader.stream_position()?; let data_len = header.end_offset() - current; let mut data = vec![0; data_len as usize]; reader.read_exact(&mut data)?; reader.seek(SeekFrom::Start(header.end_offset()))?; let tiff = GenericTiffReader::new_with_buffer(&data, 0, 0, None).map_err(|e| BmffError::Parse(e.to_string()))?; Ok(Self { header, data, tiff }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/cmt3.rs000064400000000000000000000020331046102023000170620ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use crate::{formats::bmff::BmffError, formats::tiff::GenericTiffReader}; use super::super::{BoxHeader, FourCC, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Cmt3Box { pub header: BoxHeader, pub data: Vec, pub tiff: GenericTiffReader, } impl Cmt3Box { pub const TYP: FourCC = FourCC::with(['C', 'M', 'T', '3']); } impl ReadBox<&mut R> for Cmt3Box { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let current = reader.stream_position()?; let data_len = header.end_offset() - current; let mut data = vec![0; data_len as usize]; reader.read_exact(&mut data)?; reader.seek(SeekFrom::Start(header.end_offset()))?; let tiff = GenericTiffReader::new_with_buffer(&data, 0, 0, None).map_err(|e| BmffError::Parse(e.to_string()))?; Ok(Self { header, data, tiff }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/cmt4.rs000064400000000000000000000020331046102023000170630ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use crate::{formats::bmff::BmffError, formats::tiff::GenericTiffReader}; use super::super::{BoxHeader, FourCC, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Cmt4Box { pub header: BoxHeader, pub data: Vec, pub tiff: GenericTiffReader, } impl Cmt4Box { pub const TYP: FourCC = FourCC::with(['C', 'M', 'T', '4']); } impl ReadBox<&mut R> for Cmt4Box { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let current = reader.stream_position()?; let data_len = header.end_offset() - current; let mut data = vec![0; data_len as usize]; reader.read_exact(&mut data)?; reader.seek(SeekFrom::Start(header.end_offset()))?; let tiff = GenericTiffReader::new_with_buffer(&data, 0, 0, None).map_err(|e| BmffError::Parse(e.to_string()))?; Ok(Self { header, data, tiff }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/cncv.rs000064400000000000000000000014641046102023000171540ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::super::{BoxHeader, FourCC, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct CncvBox { pub header: BoxHeader, pub compressor: String, } impl CncvBox { pub const TYP: FourCC = FourCC::with(['C', 'N', 'C', 'V']); } impl ReadBox<&mut R> for CncvBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let mut buf = [0_u8; 30]; reader.read_exact(&mut buf)?; let compressor = String::from_utf8_lossy(&buf); reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, compressor: compressor.into(), }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/cnop.rs000064400000000000000000000014671046102023000171650ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::super::{BoxHeader, FourCC, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct CnopBox { pub header: BoxHeader, pub data: Vec, } impl CnopBox { pub const TYP: FourCC = FourCC::with(['C', 'N', 'O', 'P']); } impl ReadBox<&mut R> for CnopBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let current = reader.stream_position()?; let data_len = header.end_offset() - current; let mut data = vec![0; data_len as usize]; reader.read_exact(&mut data)?; reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, data }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/cr3desc.rs000064400000000000000000000067641046102023000175610ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::{ super::{BmffError, BoxHeader, ReadBox, Result}, cctp::CctpBox, cmt1::Cmt1Box, cmt2::Cmt2Box, cmt3::Cmt3Box, cmt4::Cmt4Box, cncv::CncvBox, cnop::CnopBox, ctbo::CtboBox, thmb::ThmbBox, }; use crate::formats::bmff::{free::FreeBox, skip::SkipBox}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Cr3DescBox { pub header: BoxHeader, pub cncv: CncvBox, pub cctp: CctpBox, pub ctbo: CtboBox, pub cmt1: Cmt1Box, pub cmt2: Cmt2Box, pub cmt3: Cmt3Box, pub cmt4: Cmt4Box, pub thmb: ThmbBox, } impl Cr3DescBox { //pub const TYP: FourCC = FourCC::with(['u', 'u', 'i', 'd']); pub const UUID: [u8; 16] = [0x85, 0xc0, 0xb6, 0x87, 0x82, 0x0f, 0x11, 0xe0, 0x81, 0x11, 0xf4, 0xce, 0x46, 0x2b, 0x6a, 0x48]; } impl ReadBox<&mut R> for Cr3DescBox { fn read_box(mut reader: &mut R, header: BoxHeader) -> Result { let mut cncv = None; let mut cctp = None; let mut ctbo = None; let mut cmt1 = None; let mut cmt2 = None; let mut cmt3 = None; let mut cmt4 = None; let mut thmb = None; let mut current = reader.stream_position()?; while current < header.end_offset() { // get box? let header = BoxHeader::parse(&mut reader)?; match header.typ { CncvBox::TYP => { cncv = Some(CncvBox::read_box(&mut reader, header)?); } CctpBox::TYP => { cctp = Some(CctpBox::read_box(&mut reader, header)?); } CtboBox::TYP => { ctbo = Some(CtboBox::read_box(&mut reader, header)?); } Cmt1Box::TYP => { cmt1 = Some(Cmt1Box::read_box(&mut reader, header)?); } Cmt2Box::TYP => { cmt2 = Some(Cmt2Box::read_box(&mut reader, header)?); } Cmt3Box::TYP => { cmt3 = Some(Cmt3Box::read_box(&mut reader, header)?); } Cmt4Box::TYP => { cmt4 = Some(Cmt4Box::read_box(&mut reader, header)?); } CnopBox::TYP => { let _ignore = Some(CnopBox::read_box(&mut reader, header)?); } ThmbBox::TYP => { thmb = Some(ThmbBox::read_box(&mut reader, header)?); } SkipBox::TYP => { let _ignore = SkipBox::read_box(&mut reader, header)?; } FreeBox::TYP => { let _ignore = FreeBox::read_box(&mut reader, header)?; } _ => return Err(BmffError::Parse(format!("Unknown box in Cr3desc: {}", header.typ))), } current = reader.stream_position()?; } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, cncv: cncv.ok_or_else(|| BmffError::Parse("cncv box not found, corrupt file?".into()))?, cctp: cctp.ok_or_else(|| BmffError::Parse("cctp box not found, corrupt file?".into()))?, ctbo: ctbo.ok_or_else(|| BmffError::Parse("ctbo box not found, corrupt file?".into()))?, cmt1: cmt1.ok_or_else(|| BmffError::Parse("cmt1 box not found, corrupt file?".into()))?, cmt2: cmt2.ok_or_else(|| BmffError::Parse("cmt2 box not found, corrupt file?".into()))?, cmt3: cmt3.ok_or_else(|| BmffError::Parse("cmt3 box not found, corrupt file?".into()))?, cmt4: cmt4.ok_or_else(|| BmffError::Parse("cmt4 box not found, corrupt file?".into()))?, thmb: thmb.ok_or_else(|| BmffError::Parse("thmb box not found, corrupt file?".into()))?, }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/cr3xpacket.rs000064400000000000000000000013761046102023000202740ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::super::{BoxHeader, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct Cr3XpacketBox { pub header: BoxHeader, } impl Cr3XpacketBox { //pub const TYP: FourCC = FourCC::with(['u', 'u', 'i', 'd']); pub const UUID: [u8; 16] = [0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8, 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac]; } impl ReadBox<&mut R> for Cr3XpacketBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/craw.rs000064400000000000000000000070471046102023000171620ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::{ super::{BmffError, BoxHeader, FourCC, ReadBox, Result}, cdi1::Cdi1Box, cmp1::Cmp1Box, hevc::HevcBox, jpeg::JpegBox, }; use crate::formats::bmff::free::FreeBox; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct CrawBox { pub header: BoxHeader, //pub version: u8, //pub flags: u32, pub reserved: [u8; 6], pub data_ref_index: u16, pub unknown1: [u8; 16], pub width: u16, pub height: u16, pub x_resolution: [u16; 2], pub y_resolution: [u16; 2], pub unknown2: u32, pub unknown3: u16, pub compr_name: [u8; 32], pub bit_depth: u16, pub unknown4: u16, pub img_flags: u16, pub img_type: u16, pub jpeg: Option, pub hevc: Option, pub cmp1: Option, pub cdi1: Option, } impl CrawBox { pub const TYP: FourCC = FourCC::with(['C', 'R', 'A', 'W']); } impl ReadBox<&mut R> for CrawBox { fn read_box(mut reader: &mut R, header: BoxHeader) -> Result { //let (version, flags) = read_box_header_ext(reader)?; let mut reserved = [0_u8; 6]; reader.read_exact(&mut reserved)?; let data_ref_index = reader.read_u16::()?; let mut unknown1 = [0; 16]; reader.read_exact(&mut unknown1)?; //let _sample_entry = reader.read_u64::()?; let width = reader.read_u16::()?; let height = reader.read_u16::()?; let x_resolution = [reader.read_u16::()?, reader.read_u16::()?]; let y_resolution = [reader.read_u16::()?, reader.read_u16::()?]; let unknown2 = reader.read_u32::()?; let unknown3 = reader.read_u16::()?; let mut compr_name = [0_u8; 32]; reader.read_exact(&mut compr_name)?; let bit_depth = reader.read_u16::()?; let unknown4 = reader.read_u16::()?; let img_flags = reader.read_u16::()?; let img_type = reader.read_u16::()?; let mut jpeg = None; let mut hevc = None; let mut cmp1 = None; let mut cdi1 = None; let mut current = reader.stream_position()?; while current < header.end_offset() { // get box? let header = BoxHeader::parse(&mut reader)?; match header.typ { JpegBox::TYP => { jpeg = Some(JpegBox::read_box(&mut reader, header)?); } HevcBox::TYP => { hevc = Some(HevcBox::read_box(&mut reader, header)?); } Cmp1Box::TYP => { cmp1 = Some(Cmp1Box::read_box(&mut reader, header)?); } Cdi1Box::TYP => { cdi1 = Some(Cdi1Box::read_box(&mut reader, header)?); } FreeBox::TYP => { let _ = Some(FreeBox::read_box(&mut reader, header)?); } _ => { //debug!("Unknown box???"); return Err(BmffError::Parse(format!("Invalid box found in CRAW: {:?}", header.typ))); } } current = reader.stream_position()?; } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, //version, //flags, reserved, data_ref_index, unknown1, width, height, x_resolution, y_resolution, unknown2, unknown3, compr_name, bit_depth, unknown4, img_flags, img_type, jpeg, hevc, cmp1, cdi1, }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/ctbo.rs000064400000000000000000000012221046102023000171420ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::super::{BoxHeader, FourCC, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct CtboBox { pub header: BoxHeader, } impl CtboBox { pub const TYP: FourCC = FourCC::with(['C', 'T', 'B', 'O']); } impl ReadBox<&mut R> for CtboBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { // TODO: add CTBO records reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/ctmd.rs000064400000000000000000000040401046102023000171430ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::super::{BoxHeader, FourCC, ReadBox, Result}; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct CtmdBox { pub header: BoxHeader, //pub version: u8, //pub flags: u32, pub reserved: [u8; 6], pub data_ref_index: u16, pub rec_count: u32, pub records: Vec, } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct CtmdRecord { pub unknown1: u8, // 0x00, sometimes 0x01 pub unknown2: u8, // 0x00, seomtimes 0x01 pub rec_type: u16, pub rec_size: u32, } impl CtmdBox { pub const TYP: FourCC = FourCC::with(['C', 'T', 'M', 'D']); } impl ReadBox<&mut R> for CtmdBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { //let (version, flags) = read_box_header_ext(reader)?; //let mut reserved = [0_u8; 6]; //reader.read_exact(&mut reserved)?; //let _reference_index = reader.read_u16::()?; let mut reserved = [0_u8; 6]; reader.read_exact(&mut reserved)?; let data_ref_index = reader.read_u16::()?; let rec_count = reader.read_u32::()?; let mut records = Vec::with_capacity(rec_count as usize); //let mut current = reader.seek(SeekFrom::Current(0))?; for _ in 0..rec_count { // get box? let record = CtmdRecord { unknown1: reader.read_u8()?, unknown2: reader.read_u8()?, rec_type: reader.read_u16::()?, rec_size: reader.read_u32::()?, }; records.push(record); //current = reader.seek(SeekFrom::Current(0))?; } assert!(reader.stream_position()? == header.end_offset()); reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, //version, //flags, reserved, data_ref_index, rec_count, records, }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/hevc.rs000064400000000000000000000011521046102023000171420ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::super::{BoxHeader, FourCC, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct HevcBox { pub header: BoxHeader, } impl HevcBox { pub const TYP: FourCC = FourCC::with(['H', 'E', 'V', 'C']); } impl ReadBox<&mut R> for HevcBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/iad1.rs000064400000000000000000000077441046102023000170500ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::super::{BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Iad1Box { pub header: BoxHeader, pub version: u8, pub flags: u32, pub img_width: u16, pub img_height: u16, pub unknown1: u16, pub image_type: u16, pub unknown2: u16, pub unknown3: u16, pub iad1_type: Iad1Type, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum Iad1Type { Small(Iad1Small), Big(Iad1Big), } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct Iad1Small { pub crop_left_offset: u16, pub crop_top_offset: u16, pub crop_right_offset: u16, pub crop_bottom_offset: u16, pub sensor_x_start: u16, pub sensor_y_start: u16, pub sensor_x_end: u16, pub sensor_y_end: u16, } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct Iad1Big { pub crop_left_offset: u16, pub crop_top_offset: u16, pub crop_right_offset: u16, pub crop_bottom_offset: u16, pub lob_left_offset: u16, pub lob_top_offset: u16, pub lob_right_offset: u16, pub lob_bottom_offset: u16, pub tob_left_offset: u16, pub tob_top_offset: u16, pub tob_right_offset: u16, pub tob_bottom_offset: u16, pub active_area_left_offset: u16, pub active_area_top_offset: u16, pub active_area_right_offset: u16, pub active_area_bottom_offset: u16, } impl Iad1Box { pub const TYP: FourCC = FourCC::with(['I', 'A', 'D', '1']); } impl ReadBox<&mut R> for Iad1Box { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; let img_width = reader.read_u16::()?; let img_height = reader.read_u16::()?; let unknown1 = reader.read_u16::()?; let image_type = reader.read_u16::()?; let unknown2 = reader.read_u16::()?; let unknown3 = reader.read_u16::()?; let iad1_type = match image_type { 0 => Iad1Type::Small(Iad1Small { crop_left_offset: reader.read_u16::()?, crop_top_offset: reader.read_u16::()?, crop_right_offset: reader.read_u16::()?, crop_bottom_offset: reader.read_u16::()?, sensor_x_start: reader.read_u16::()?, sensor_y_start: reader.read_u16::()?, sensor_x_end: reader.read_u16::()?, sensor_y_end: reader.read_u16::()?, }), 2 => Iad1Type::Big(Iad1Big { crop_left_offset: reader.read_u16::()?, crop_top_offset: reader.read_u16::()?, crop_right_offset: reader.read_u16::()?, crop_bottom_offset: reader.read_u16::()?, lob_left_offset: reader.read_u16::()?, lob_top_offset: reader.read_u16::()?, lob_right_offset: reader.read_u16::()?, lob_bottom_offset: reader.read_u16::()?, tob_left_offset: reader.read_u16::()?, tob_top_offset: reader.read_u16::()?, tob_right_offset: reader.read_u16::()?, tob_bottom_offset: reader.read_u16::()?, active_area_left_offset: reader.read_u16::()?, active_area_top_offset: reader.read_u16::()?, active_area_right_offset: reader.read_u16::()?, active_area_bottom_offset: reader.read_u16::()?, }), _ => { panic!("Invalid iad1 type"); // TODO } }; reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags, img_width, img_height, unknown1, image_type, unknown2, unknown3, iad1_type, }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/jpeg.rs000064400000000000000000000013671046102023000171520ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::super::{BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct JpegBox { pub header: BoxHeader, pub version: u8, pub flags: u32, } impl JpegBox { pub const TYP: FourCC = FourCC::with(['J', 'P', 'E', 'G']); } impl ReadBox<&mut R> for JpegBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags }) } } rawler-0.7.1/src/formats/bmff/ext_cr3/mod.rs000064400000000000000000000006121046102023000167740ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher pub mod ccdt; pub mod cctp; pub mod cdi1; pub mod cmp1; pub mod cmt1; pub mod cmt2; pub mod cmt3; pub mod cmt4; pub mod cncv; pub mod cnop; pub mod cr3desc; // TODO rename to cr3box pub mod cr3xpacket; pub mod craw; pub mod ctbo; pub mod ctmd; pub mod hevc; pub mod iad1; pub mod jpeg; pub mod thmb; rawler-0.7.1/src/formats/bmff/ext_cr3/thmb.rs000064400000000000000000000012001046102023000171410ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::super::{BoxHeader, FourCC, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct ThmbBox { pub header: BoxHeader, } impl ThmbBox { pub const TYP: FourCC = FourCC::with(['T', 'H', 'M', 'B']); } impl ReadBox<&mut R> for ThmbBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { // TODO reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header }) } } rawler-0.7.1/src/formats/bmff/free.rs000064400000000000000000000011631046102023000155710ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, FourCC, ReadBox, Result}; use serde::Serialize; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize)] pub struct FreeBox { pub header: BoxHeader, } impl FreeBox { pub const TYP: FourCC = FourCC::with(['f', 'r', 'e', 'e']); } impl ReadBox<&mut R> for FreeBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header }) } } rawler-0.7.1/src/formats/bmff/ftyp.rs000064400000000000000000000024631046102023000156360ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BmffError, BoxHeader, FourCC, ReadBox, Result}; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct FtypBox { pub header: BoxHeader, pub major_brand: FourCC, pub minor_version: u32, pub compatible_brands: Vec, } impl FtypBox { pub const TYP: FourCC = FourCC::with(['f', 't', 'y', 'p']); } impl ReadBox<&mut R> for FtypBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let major = reader.read_u32::()?; let minor = reader.read_u32::()?; if header.size % 4 != 0 { return Err(BmffError::Parse("invalid ftyp size".into())); } let brand_count = (header.size - 16) / 4; // header + major + minor let mut brands = Vec::new(); for _ in 0..brand_count { let b = reader.read_u32::()?; brands.push(From::from(b)); } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, major_brand: From::from(major), minor_version: minor, compatible_brands: brands, }) } } rawler-0.7.1/src/formats/bmff/hdlr.rs000064400000000000000000000014411046102023000156000ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct HdlrBox { pub header: BoxHeader, pub version: u8, pub flags: u32, } impl HdlrBox { pub const TYP: FourCC = FourCC::with(['h', 'd', 'l', 'r']); } impl ReadBox<&mut R> for HdlrBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; // TODO? reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags }) } } rawler-0.7.1/src/formats/bmff/mdat.rs000064400000000000000000000012171046102023000155750ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, FourCC, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct MdatBox { pub header: BoxHeader, } impl MdatBox { pub const TYP: FourCC = FourCC::with(['m', 'd', 'a', 't']); } impl ReadBox<&mut R> for MdatBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header }) } } rawler-0.7.1/src/formats/bmff/mdhd.rs000064400000000000000000000033231046102023000155640ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct MdhdBox { pub header: BoxHeader, pub version: u8, pub flags: u32, pub creation_time: u64, pub modification_time: u64, pub timescale: u32, pub duration: u64, pub language: String, } impl MdhdBox { pub const TYP: FourCC = FourCC::with(['m', 'd', 'h', 'd']); } impl ReadBox<&mut R> for MdhdBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; let (creation_time, modification_time, timescale, duration) = if version == 1 { ( reader.read_u64::()?, reader.read_u64::()?, reader.read_u32::()?, reader.read_u64::()?, ) } else { assert_eq!(version, 0); ( reader.read_u32::()? as u64, reader.read_u32::()? as u64, reader.read_u32::()?, reader.read_u32::()? as u64, ) }; let _language_code = reader.read_u16::()?; //let language = language_string(language_code); // TODO let language = String::from("FIXME"); reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags, creation_time, modification_time, timescale, duration, language, }) } } rawler-0.7.1/src/formats/bmff/mdia.rs000064400000000000000000000040311046102023000155570ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BmffError, BoxHeader, FourCC, ReadBox, Result, hdlr::HdlrBox, mdhd::MdhdBox, minf::MinfBox, vendor::VendorBox}; use log::debug; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct MdiaBox { pub header: BoxHeader, pub mdhd: MdhdBox, pub hdlr: HdlrBox, pub minf: MinfBox, pub vendor: Vec, } impl MdiaBox { pub const TYP: FourCC = FourCC::with(['m', 'd', 'i', 'a']); } impl ReadBox<&mut R> for MdiaBox { fn read_box(mut reader: &mut R, header: BoxHeader) -> Result { let mut mdhd = None; let mut hdlr = None; let mut minf = None; let mut vendors = Vec::new(); let mut current = reader.stream_position()?; while current < header.end_offset() { // get box? let header = BoxHeader::parse(&mut reader)?; //let ftyp = Some(FtypBox::read_box(&mut file, header)?); match header.typ { MdhdBox::TYP => { mdhd = Some(MdhdBox::read_box(&mut reader, header)?); } HdlrBox::TYP => { hdlr = Some(HdlrBox::read_box(&mut reader, header)?); } MinfBox::TYP => { minf = Some(MinfBox::read_box(&mut reader, header)?); } _ => { debug!("Vendor box found in mdia: {:?}", header.typ); let vendor = VendorBox::read_box(&mut reader, header)?; vendors.push(vendor); } } current = reader.stream_position()?; } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, mdhd: mdhd.ok_or_else(|| BmffError::Parse("mdhd box not found, corrupt file?".into()))?, hdlr: hdlr.ok_or_else(|| BmffError::Parse("hdlr box not found, corrupt file?".into()))?, minf: minf.ok_or_else(|| BmffError::Parse("minf box not found, corrupt file?".into()))?, vendor: vendors, }) } } rawler-0.7.1/src/formats/bmff/minf.rs000064400000000000000000000037751046102023000156140ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BmffError, BoxHeader, FourCC, ReadBox, Result, dinf::DinfBox, stbl::StblBox, vendor::VendorBox, vmhd::VmhdBox}; use log::debug; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct MinfBox { pub header: BoxHeader, pub vmhd: Option, //#[serde(skip_serializing_if = "Option::is_none")] //pub smhd: Option, pub dinf: DinfBox, pub stbl: StblBox, pub vendor: Vec, } impl MinfBox { pub const TYP: FourCC = FourCC::with(['m', 'i', 'n', 'f']); } impl ReadBox<&mut R> for MinfBox { fn read_box(mut reader: &mut R, header: BoxHeader) -> Result { let mut vmhd = None; //let mut smhd = None; let mut dinf = None; let mut stbl = None; let mut vendors = Vec::new(); let mut current = reader.stream_position()?; while current < header.end_offset() { // get box? let header = BoxHeader::parse(&mut reader)?; match header.typ { VmhdBox::TYP => { vmhd = Some(VmhdBox::read_box(&mut reader, header)?); } DinfBox::TYP => { dinf = Some(DinfBox::read_box(&mut reader, header)?); } StblBox::TYP => { stbl = Some(StblBox::read_box(&mut reader, header)?); } _ => { debug!("Vendor box found in minf: {:?}", header.typ); let vendor = VendorBox::read_box(&mut reader, header)?; vendors.push(vendor); } } current = reader.stream_position()?; } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, vmhd, dinf: dinf.ok_or_else(|| BmffError::Parse("dinf box not found, corrupt file?".into()))?, stbl: stbl.ok_or_else(|| BmffError::Parse("stbl box not found, corrupt file?".into()))?, vendor: vendors, }) } } rawler-0.7.1/src/formats/bmff/mod.rs000064400000000000000000000174261046102023000154400ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use std::{ fmt, fs::File, io::{self, Cursor, Read, Seek, SeekFrom}, }; use byteorder::{BigEndian, ReadBytesExt}; use log::debug; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use thiserror::Error; pub mod co64; pub mod dinf; pub mod ext_cr3; pub mod free; pub mod ftyp; pub mod hdlr; pub mod mdat; pub mod mdhd; pub mod mdia; pub mod minf; pub mod moov; pub mod mvhd; pub mod skip; pub mod stbl; pub mod stsc; pub mod stsd; pub mod stsz; pub mod stts; pub mod tkhd; pub mod trak; pub mod vendor; pub mod vmhd; use ftyp::FtypBox; use mdat::MdatBox; use moov::MoovBox; use uuid::Uuid; use vendor::VendorBox; use self::ext_cr3::cr3xpacket::Cr3XpacketBox; type BoxUuid = Uuid; pub const UUID_TYP: FourCC = FourCC::with(['u', 'u', 'i', 'd']); pub fn read_box_header_ext(reader: &mut R) -> Result<(u8, u32)> { let version = reader.read_u8()?; let flags = reader.read_u24::()?; Ok((version, flags)) } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct BoxHeader { pub size: u64, pub typ: FourCC, pub uuid: Option, pub offset: u64, // File offset pub header_len: u64, // Full Box fields //pub version: Option, //pub flags: Option, } impl BoxHeader { pub fn parse(mut reader: R) -> Result { let start = reader.stream_position()?; let mut size = reader.read_u32::()? as u64; let typ = reader.read_u32::()?.into(); if size == 1 { size = reader.read_u64::()?; } let mut uuid = None; if typ == UUID_TYP { let mut buf = [0; 16]; reader.read_exact(&mut buf)?; uuid = Some(Uuid::from_bytes(buf)); } let current = reader.stream_position()?; Ok(BoxHeader { size, typ, uuid, offset: start, header_len: current - start, }) } pub fn end_offset(&self) -> u64 { self.offset + self.size } pub fn make_view<'a>(&self, buffer: &'a [u8], skip: usize, limit: usize) -> &'a [u8] { let start = (self.offset + self.header_len) as usize + skip; if limit == 0 { &buffer[start..start + (self.size - self.header_len) as usize - skip] } else { &buffer[start..start + limit] } } } pub trait BmffBox: Sized { fn size(&self) -> u64; fn data_size(&self) -> u64; fn box_offset(&self) -> usize; fn box_data_offset(&self) -> usize; } #[derive(Error, Debug)] pub enum BmffError { #[error("I/O error while writing DNG")] Io(#[from] io::Error), #[error("Parser error: {}", _0)] Parse(String), } type Result = std::result::Result; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct FileBox { pub ftyp: FtypBox, pub moov: MoovBox, pub mdat: MdatBox, pub vendor: Vec, pub cr3xpacket: Option, } impl FileBox { pub fn parse(mut file: R) -> Result { let size = file.seek(SeekFrom::End(0))?; let mut current = file.seek(SeekFrom::Start(0))?; let mut ftyp = None; let mut moov = None; let mut mdat = None; let mut vendors = Vec::new(); let mut cr3xpacket = None; while current < size { // get box? let header = BoxHeader::parse(&mut file)?; //let ftyp = Some(FtypBox::read_box(&mut file, header)?); match header.typ { FtypBox::TYP => { debug!("Found ftyp box"); ftyp = Some(FtypBox::read_box(&mut file, header)?); } MoovBox::TYP => { debug!("Found moov box"); moov = Some(MoovBox::read_box(&mut file, header)?); } MdatBox::TYP => { debug!("Found mdat box"); mdat = Some(MdatBox::read_box(&mut file, header)?); } _ => { if let Some(uuid) = header.uuid { if uuid == Uuid::from_bytes(Cr3XpacketBox::UUID) { cr3xpacket = Some(Cr3XpacketBox::read_box(&mut file, header)?); } else { debug!("Vendor box found in filebox: {:?}", header.typ); let vendor = VendorBox::read_box(&mut file, header)?; vendors.push(vendor); } } else { debug!("Vendor box found in filebox: {:?}", header.typ); let vendor = VendorBox::read_box(&mut file, header)?; vendors.push(vendor); } } } if file.stream_position()? != current { current = file.stream_position()?; } else { // If parsing has not moved cursor, we probably have a corrupt file or it's not a BMFF at all. return Err(BmffError::Parse("Unable to find valid BMFF box, corrupt file?".into())); } } Ok(Self { ftyp: ftyp.ok_or_else(|| BmffError::Parse("ftyp box not found, corrupt file?".into()))?, moov: moov.ok_or_else(|| BmffError::Parse("moov box not found, corrupt file?".into()))?, mdat: mdat.ok_or_else(|| BmffError::Parse("mdat box not found, corrupt file?".into()))?, vendor: vendors, cr3xpacket, }) } } pub fn parse_file(file: &mut File) -> Result { let filebox = FileBox::parse(file)?; Ok(filebox) } pub fn parse_buffer(buf: &[u8]) -> Result { // TODO: add AsRef let mut cursor = Cursor::new(buf); let filebox = FileBox::parse(&mut cursor)?; Ok(filebox) } #[derive(Default, PartialEq, Eq, Clone, Copy)] pub struct FourCC { pub value: [u8; 4], } impl Serialize for FourCC { fn serialize(&self, serializer: S) -> std::result::Result where S: Serializer, { serializer.serialize_str(&self.to_string()) } } impl<'de> Deserialize<'de> for FourCC { fn deserialize(deserializer: D) -> std::result::Result where D: Deserializer<'de>, { use serde::de::Error; let s = String::deserialize(deserializer)?; if s.len() != 4 { Err(D::Error::custom(format!("Invalid FourCC value: {}", s))) } else { Ok(FourCC { value: [s.as_bytes()[0], s.as_bytes()[1], s.as_bytes()[2], s.as_bytes()[3]], }) } } } impl FourCC { const fn with(v: [char; 4]) -> Self { Self { value: [v[0] as u8, v[1] as u8, v[2] as u8, v[3] as u8], } } } impl From for FourCC { fn from(number: u32) -> Self { FourCC { value: number.to_be_bytes() } } } impl From for u32 { fn from(fourcc: FourCC) -> u32 { (&fourcc).into() } } impl From<&FourCC> for u32 { fn from(fourcc: &FourCC) -> u32 { u32::from_be_bytes(fourcc.value) } } impl std::str::FromStr for FourCC { type Err = BmffError; fn from_str(s: &str) -> Result { if let [a, b, c, d] = s.as_bytes() { Ok(Self { value: [*a, *b, *c, *d] }) } else { Err(BmffError::Parse("expected exactly four bytes in string".into())) } } } impl From<[u8; 4]> for FourCC { fn from(value: [u8; 4]) -> FourCC { FourCC { value } } } impl fmt::Debug for FourCC { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let code: u32 = self.into(); let string = String::from_utf8_lossy(&self.value[..]); write!(f, "{} / {:#010X}", string, code) } } impl fmt::Display for FourCC { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", String::from_utf8_lossy(&self.value[..])) } } pub trait ReadBox: Sized { fn read_box(_: T, header: BoxHeader) -> Result; } #[derive(Clone, Debug)] pub struct Bmff { pub filebox: FileBox, } impl Bmff { pub fn new(file: R) -> Result { let filebox = FileBox::parse(file)?; Ok(Self { filebox }) } pub fn new_buf(buf: &[u8]) -> Result { let filebox = parse_buffer(buf)?; Ok(Self { filebox }) } pub fn compatible_brand(&self, _brand: &str) -> bool { true // FIXME } } rawler-0.7.1/src/formats/bmff/moov.rs000064400000000000000000000042661046102023000156370ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BmffError, BoxHeader, FourCC, ReadBox, Result, ext_cr3::cr3desc::Cr3DescBox, mvhd::MvhdBox, trak::TrakBox, vendor::VendorBox}; use log::debug; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; use uuid::Uuid; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct MoovBox { pub header: BoxHeader, pub mvhd: MvhdBox, //#[serde(skip_serializing_if = "Option::is_none")] //pub mvex: Option, #[serde(rename = "trak")] pub traks: Vec, // UUID Box 85c0b687-820f-11e0-8111-f4ce462b6a48 pub cr3desc: Option, pub vendor: Vec, } impl MoovBox { pub const TYP: FourCC = FourCC::with(['m', 'o', 'o', 'v']); } impl ReadBox<&mut R> for MoovBox { fn read_box(mut reader: &mut R, header: BoxHeader) -> Result { let mut mvhd = None; let mut traks = Vec::new(); let mut cr3desc = None; let mut vendors = Vec::new(); let mut current = reader.stream_position()?; while current < header.end_offset() { // get box? let header = BoxHeader::parse(&mut reader)?; match header.typ { MvhdBox::TYP => { mvhd = Some(MvhdBox::read_box(&mut reader, header)?); } TrakBox::TYP => { let trak = TrakBox::read_box(&mut reader, header)?; traks.push(trak); } _ => { if let Some(uuid) = header.uuid { if uuid == Uuid::from_bytes(Cr3DescBox::UUID) { cr3desc = Some(Cr3DescBox::read_box(&mut reader, header)?); } } else { debug!("Vendor box found in moov: {:?}", header.typ); let vendor = VendorBox::read_box(&mut reader, header)?; vendors.push(vendor); } } } current = reader.stream_position()?; } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, mvhd: mvhd.ok_or_else(|| BmffError::Parse("mdhd box not found, corrupt file?".into()))?, traks, cr3desc, vendor: vendors, }) } } rawler-0.7.1/src/formats/bmff/mvhd.rs000064400000000000000000000032501046102023000156050ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct MvhdBox { pub header: BoxHeader, pub version: u8, pub flags: u32, pub creation_time: u64, pub modification_time: u64, pub timescale: u32, pub duration: u64, //#[serde(with = "value_u32")] //pub rate: FixedPointU16, } impl MvhdBox { pub const TYP: FourCC = FourCC::with(['m', 'v', 'h', 'd']); } impl ReadBox<&mut R> for MvhdBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; let (creation_time, modification_time, timescale, duration) = if version == 1 { ( reader.read_u64::()?, reader.read_u64::()?, reader.read_u32::()?, reader.read_u64::()?, ) } else { assert_eq!(version, 0); ( reader.read_u32::()? as u64, reader.read_u32::()? as u64, reader.read_u32::()?, reader.read_u32::()? as u64, ) }; //let rate = FixedPointU16::new_raw(reader.read_u32::()?); // TODO reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags, creation_time, modification_time, timescale, duration, //rate, }) } } rawler-0.7.1/src/formats/bmff/skip.rs000064400000000000000000000011631046102023000156160ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, FourCC, ReadBox, Result}; use serde::Serialize; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize)] pub struct SkipBox { pub header: BoxHeader, } impl SkipBox { pub const TYP: FourCC = FourCC::with(['s', 'k', 'i', 'p']); } impl ReadBox<&mut R> for SkipBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header }) } } rawler-0.7.1/src/formats/bmff/stbl.rs000064400000000000000000000067771046102023000156340ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BmffError, BoxHeader, FourCC, ReadBox, Result, co64::Co64Box, stsc::StscBox, stsd::StsdBox, stsz::StszBox, stts::SttsBox, vendor::VendorBox}; use log::debug; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct StblBox { pub header: BoxHeader, pub stsd: StsdBox, pub stts: SttsBox, //pub ctts: Option, pub stsc: StscBox, pub stsz: StszBox, pub co64: Option, pub vendor: Vec, } impl StblBox { pub const TYP: FourCC = FourCC::with(['s', 't', 'b', 'l']); pub fn get_sample_offset(&self, sample: u32) -> Option<(usize, usize)> { if let Some(co64) = self.co64.as_ref() { assert!(sample > 0, "sample number must be greater than 0"); let desc = self.stsc.get_entry_for_sample(sample); // Chunk number for our sample let chunk = desc.first_chunk + (((sample - 1) - (desc.first_sample - 1)) / desc.samples_per_chunk); // Index of sample inside chunk let chunk_sample_idx = (sample - desc.first_sample) % desc.samples_per_chunk; // Offset of chunk let chunk_offset = co64.entries[chunk as usize - 1]; // Offset of sample in chunk let mut sample_offset = 0; for i in 0..chunk_sample_idx { sample_offset += self.stsz.sample_size(sample - chunk_sample_idx + i); } let sample_size = self.stsz.sample_size(sample); Some((chunk_offset as usize + sample_offset as usize, sample_size as usize)) } else { None } } } impl ReadBox<&mut R> for StblBox { fn read_box(mut reader: &mut R, header: BoxHeader) -> Result { let mut stsd = None; let mut stts = None; // let mut ctts = None; //let mut stss = None; let mut stsc = None; let mut stsz = None; //let mut stco = None; let mut co64 = None; let mut vendors = Vec::new(); let mut current = reader.stream_position()?; while current < header.end_offset() { // get box? let header = BoxHeader::parse(&mut reader)?; //let ftyp = Some(FtypBox::read_box(&mut file, header)?); match header.typ { StsdBox::TYP => { stsd = Some(StsdBox::read_box(&mut reader, header)?); } SttsBox::TYP => { stts = Some(SttsBox::read_box(&mut reader, header)?); } StscBox::TYP => { stsc = Some(StscBox::read_box(&mut reader, header)?); } StszBox::TYP => { stsz = Some(StszBox::read_box(&mut reader, header)?); } Co64Box::TYP => { co64 = Some(Co64Box::read_box(&mut reader, header)?); } _ => { debug!("Vendor box found in stbl: {:?}", header.typ); let vendor = VendorBox::read_box(&mut reader, header)?; vendors.push(vendor); } } current = reader.stream_position()?; } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, stsd: stsd.ok_or_else(|| BmffError::Parse("stsd box not found, corrupt file?".into()))?, stts: stts.ok_or_else(|| BmffError::Parse("stts box not found, corrupt file?".into()))?, stsc: stsc.ok_or_else(|| BmffError::Parse("stsc box not found, corrupt file?".into()))?, stsz: stsz.ok_or_else(|| BmffError::Parse("stsz box not found, corrupt file?".into()))?, co64, vendor: vendors, }) } } rawler-0.7.1/src/formats/bmff/stsc.rs000064400000000000000000000050401046102023000156220ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct StscBox { pub header: BoxHeader, pub version: u8, pub flags: u32, pub entries: Vec, } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct StscEntry { pub first_chunk: u32, pub samples_per_chunk: u32, pub sample_description_index: u32, pub first_sample: u32, } impl StscBox { pub const TYP: FourCC = FourCC::with(['s', 't', 's', 'c']); pub fn get_entry_for_sample(&self, sample: u32) -> &StscEntry { assert!(sample > 0, "Sample numbering starts with 1"); assert_eq!(self.entries.is_empty(), false, "stsc box must contains at least one entry"); assert_eq!(self.entries[0].first_sample, 1, "First entry must start with first sample"); match self.entries.binary_search_by(|entry| entry.first_sample.cmp(&sample)) { Ok(i) => &self.entries[i], Err(i) => &self.entries[i - 1], } } } impl ReadBox<&mut R> for StscBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; let entry_count = reader.read_u32::()?; let mut entries = Vec::with_capacity(entry_count as usize); // Reader for a single stsc entry let mut read_entry = || -> Result { Ok(StscEntry { first_chunk: reader.read_u32::()?, samples_per_chunk: reader.read_u32::()?, sample_description_index: reader.read_u32::()?, first_sample: 0, }) }; if entry_count > 0 { // Read first entry and hold it back let mut holdback = read_entry()?; holdback.first_sample = 1; for _ in 1..entry_count { let mut entry = read_entry()?; // Now we know the chunk count to calc the amount of samples in holdback entry.first_sample = holdback.first_sample + ((entry.first_chunk - holdback.first_sample) * holdback.samples_per_chunk); entries.push(holdback); holdback = entry; } // Finalize entry list entries.push(holdback); } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags, entries, }) } } rawler-0.7.1/src/formats/bmff/stsd.rs000064400000000000000000000040731046102023000156300ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{ BoxHeader, FourCC, ReadBox, Result, ext_cr3::{craw::CrawBox, ctmd::CtmdBox}, read_box_header_ext, vendor::VendorBox, }; use byteorder::{BigEndian, ReadBytesExt}; use log::debug; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct StsdBox { pub header: BoxHeader, pub version: u8, pub flags: u32, pub craw: Option, pub ctmd: Option, pub vendor: Vec, } impl StsdBox { pub const TYP: FourCC = FourCC::with(['s', 't', 's', 'd']); } impl ReadBox<&mut R> for StsdBox { fn read_box(mut reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; // Canon CR3 boxes let mut craw = None; let mut ctmd = None; let mut vendors = Vec::new(); reader.read_u32::()?; // FIXME XXX entry_count let mut current = reader.stream_position()?; while current < header.end_offset() { // get box? let header = BoxHeader::parse(&mut reader)?; match header.typ { CrawBox::TYP => { assert_eq!(craw, None, "Found second CRAW box"); craw = Some(CrawBox::read_box(&mut reader, header)?); } CtmdBox::TYP => { assert_eq!(ctmd, None, "Found second CTMD box"); ctmd = Some(CtmdBox::read_box(&mut reader, header)?); } // TODO: Multiple CRAW boxes can occour in CRM files?! BMFF Spec says the SampleBox is an array. _ => { debug!("Vendor box found in stsd: {:?}", header.typ); let vendor = VendorBox::read_box(&mut reader, header)?; vendors.push(vendor); } } current = reader.stream_position()?; } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags, craw, ctmd, vendor: vendors, }) } } rawler-0.7.1/src/formats/bmff/stsz.rs000064400000000000000000000031471046102023000156570ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct StszBox { pub header: BoxHeader, pub version: u8, pub flags: u32, pub sample_size: u32, pub sample_count: u32, pub sample_sizes: Vec, } impl StszBox { pub const TYP: FourCC = FourCC::with(['s', 't', 's', 'z']); pub fn sample_size(&self, sample: u32) -> u32 { if self.sample_size > 0 { self.sample_size } else { self.sample_sizes[sample as usize - 1] } } } impl ReadBox<&mut R> for StszBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; let sample_size = reader.read_u32::()?; let sample_count = reader.read_u32::()?; let mut sample_sizes = Vec::with_capacity(sample_count as usize); if sample_size == 0 { for _ in 0..sample_count { let sample_number = reader.read_u32::()?; sample_sizes.push(sample_number); } } else { // If the sample_size is non-zero, it is the only sample_size sample_sizes.push(sample_size); } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags, sample_size, sample_count, sample_sizes, }) } } rawler-0.7.1/src/formats/bmff/stts.rs000064400000000000000000000025371046102023000156530ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct SttsBox { pub header: BoxHeader, pub version: u8, pub flags: u32, pub entries: Vec, } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct SttsEntry { pub sample_count: u32, pub sample_delta: u32, } impl SttsBox { pub const TYP: FourCC = FourCC::with(['s', 't', 't', 's']); } impl ReadBox<&mut R> for SttsBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; let entry_count = reader.read_u32::()?; let mut entries = Vec::with_capacity(entry_count as usize); for _i in 0..entry_count { let entry = SttsEntry { sample_count: reader.read_u32::()?, sample_delta: reader.read_u32::()?, }; entries.push(entry); } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags, entries, }) } } rawler-0.7.1/src/formats/bmff/tkhd.rs000064400000000000000000000014411046102023000156010ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct TkhdBox { pub header: BoxHeader, pub version: u8, pub flags: u32, } impl TkhdBox { pub const TYP: FourCC = FourCC::with(['t', 'k', 'h', 'd']); } impl ReadBox<&mut R> for TkhdBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; // TODO? reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags }) } } rawler-0.7.1/src/formats/bmff/trak.rs000064400000000000000000000035571046102023000156220ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BmffError, BoxHeader, FourCC, ReadBox, Result, mdia::MdiaBox, tkhd::TkhdBox, vendor::VendorBox}; use log::debug; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct TrakBox { pub header: BoxHeader, pub tkhd: TkhdBox, //#[serde(skip_serializing_if = "Option::is_none")] //pub edts: Option, pub mdia: MdiaBox, pub vendor: Vec, } impl TrakBox { pub const TYP: FourCC = FourCC::with(['t', 'r', 'a', 'k']); } impl ReadBox<&mut R> for TrakBox { fn read_box(mut reader: &mut R, header: BoxHeader) -> Result { let mut tkhd = None; let mut mdia = None; let mut vendors = Vec::new(); let mut current = reader.stream_position()?; while current < header.end_offset() { // get box? let header = BoxHeader::parse(&mut reader)?; //let ftyp = Some(FtypBox::read_box(&mut file, header)?); match header.typ { TkhdBox::TYP => { tkhd = Some(TkhdBox::read_box(&mut reader, header)?); } MdiaBox::TYP => { mdia = Some(MdiaBox::read_box(&mut reader, header)?); } _ => { debug!("Vendor box found in trak: {:?}", header.typ); let vendor = VendorBox::read_box(&mut reader, header)?; vendors.push(vendor); } } current = reader.stream_position()?; } reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, tkhd: tkhd.ok_or_else(|| BmffError::Parse("tkhd box not found, corrupt file?".into()))?, mdia: mdia.ok_or_else(|| BmffError::Parse("mdia box not found, corrupt file?".into()))?, vendor: vendors, }) } } rawler-0.7.1/src/formats/bmff/vendor.rs000064400000000000000000000010401046102023000161370ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, ReadBox, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct VendorBox { pub header: BoxHeader, } impl ReadBox<&mut R> for VendorBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { reader.seek(SeekFrom::Start(header.offset + header.size))?; Ok(Self { header }) } } rawler-0.7.1/src/formats/bmff/vmhd.rs000064400000000000000000000024431046102023000156100ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2020 Alfred Gutierrez // Copyright 2021 Daniel Vogelbacher use super::{BoxHeader, FourCC, ReadBox, Result, read_box_header_ext}; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Read, Seek, SeekFrom}; #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct VmhdBox { pub header: BoxHeader, pub version: u8, pub flags: u32, pub graphics_mode: u16, pub op_color: RgbColor, } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct RgbColor { pub red: u16, pub green: u16, pub blue: u16, } impl VmhdBox { pub const TYP: FourCC = FourCC::with(['v', 'm', 'h', 'd']); } impl ReadBox<&mut R> for VmhdBox { fn read_box(reader: &mut R, header: BoxHeader) -> Result { let (version, flags) = read_box_header_ext(reader)?; let graphics_mode = reader.read_u16::()?; let op_color = RgbColor { red: reader.read_u16::()?, green: reader.read_u16::()?, blue: reader.read_u16::()?, }; reader.seek(SeekFrom::Start(header.end_offset()))?; Ok(Self { header, version, flags, graphics_mode, op_color, }) } } rawler-0.7.1/src/formats/ciff/mod.rs000064400000000000000000000103011046102023000154160ustar 00000000000000use std::collections::HashMap; use crate::{bits::*, rawsource::RawSource}; #[derive(Debug, Copy, Clone, PartialEq)] pub enum CiffTag { //Null = 0x0000, ColorInfo1 = 0x0032, MakeModel = 0x080a, //ShotInfo = 0x102a, ColorInfo2 = 0x102c, WhiteBalance = 0x10a9, SensorInfo = 0x1031, //ImageInfo = 0x1810, DecoderTable = 0x1835, //RawData = 0x2005, //SubIFD = 0x300a, //Exif = 0x300b, } fn ct(tag: CiffTag) -> u16 { tag as u16 } #[derive(Debug, Clone)] pub struct CiffEntry { pub tag: u16, pub typ: u16, pub count: usize, pub bytesize: usize, pub data_offset: usize, pub data: Vec, } #[derive(Debug, Clone)] pub struct CiffIFD { entries: HashMap, subifds: Vec, } pub fn is_ciff(file: &RawSource) -> bool { match file.subview(0, 14) { Ok(buf) => buf[6..14] == b"HEAPCCDR"[..], Err(_) => false, } } impl CiffIFD { pub fn new_file(file: &RawSource) -> Result { let data = file.as_vec().map_err(|err| format!("Failed to read whole file: {:?}", err))?; CiffIFD::new(&data, LEu32(&data, 2) as usize, data.len(), 1) } pub fn new(buf: &[u8], start: usize, end: usize, depth: u32) -> Result { let mut entries = HashMap::new(); let mut subifds = Vec::new(); let valuedata_size = LEu32(buf, end - 4) as usize; let dircount = LEu16(buf, start + valuedata_size) as usize; for i in 0..dircount { let entry_offset: usize = start + valuedata_size + 2 + i * 10; let e = CiffEntry::new(buf, start, entry_offset)?; if e.typ == 0x2800 || e.typ == 0x3000 { // SubIFDs if depth < 10 { // Avoid infinite looping IFDs let ifd = CiffIFD::new(buf, e.data_offset, e.data_offset + e.bytesize, depth + 1); match ifd { Ok(val) => { subifds.push(val); } Err(_) => { entries.insert(e.tag, e); } // Ignore unparsable IFDs } } } else { entries.insert(e.tag, e); } } Ok(CiffIFD { entries, subifds }) } pub fn find_entry(&self, tag: CiffTag) -> Option<&CiffEntry> { if self.entries.contains_key(&ct(tag)) { self.entries.get(&ct(tag)) } else { for ifd in &self.subifds { if let Some(x) = ifd.find_entry(tag) { return Some(x); } } None } } } impl CiffEntry { pub fn new(buf: &[u8], value_data: usize, offset: usize) -> Result { let p = LEu16(buf, offset); let tag = p & 0x3fff; let datalocation = (p & 0xc000) as usize; let typ = p & 0x3800; let (bytesize, data_offset) = match datalocation { // Data is offset in value_data 0x0000 => (LEu32(buf, offset + 2) as usize, LEu32(buf, offset + 6) as usize + value_data), // Data is stored directly in entry 0x4000 => (8, offset + 2), val => return Err(format!("CIFF: Don't know about data location {:x}", val)), }; let data = &buf[data_offset..data_offset + bytesize]; let count = bytesize >> CiffEntry::element_shift(typ); Ok(CiffEntry { tag, typ, count, bytesize, data_offset, data: Vec::from(data), }) } pub fn element_shift(typ: u16) -> usize { match typ { // Byte and ASCII 0x0000 | 0x8000 => 0, // Short 0x1000 => 1, // Long, Mix, Sub1 and Sub2 0x1800 | 0x2000 | 0x2800 | 0x3000 => 2, // Default to 0 _ => 0, } } pub fn get_strings(&self) -> Vec { String::from_utf8_lossy(&self.data).split_terminator('\0').map(|x| x.to_string()).collect() } pub fn get_u32(&self, idx: usize) -> u32 { match self.typ { 0x0000 | 0x8000 => self.data[idx] as u32, 0x1000 => LEu16(&self.data, idx * 2) as u32, 0x1800 | 0x2000 | 0x2800 | 0x3000 => LEu32(&self.data, idx * 4), _ => panic!("{}", format!("Trying to read typ {} for a u32", self.typ)), } } pub fn get_usize(&self, idx: usize) -> usize { self.get_u32(idx) as usize } pub fn get_f32(&self, idx: usize) -> f32 { self.get_u32(idx) as f32 } pub fn get_force_u16(&self, idx: usize) -> u16 { LEu16(&self.data, idx * 2) } } rawler-0.7.1/src/formats/jfif.rs000064400000000000000000000202771046102023000146630ustar 00000000000000use byteorder::{BigEndian, ReadBytesExt}; use std::io::{Read, Seek, SeekFrom}; use thiserror::Error; use crate::formats::tiff::IFD; use crate::rawsource::RawSource; pub type Result = std::result::Result; /// Error variants for JFIF parser #[derive(Debug, Error)] pub enum JfifError { /// Overflow of input, size constraints... #[error("Overflow error: {}", _0)] Overflow(String), #[error("General error: {}", _0)] General(String), #[error("Format mismatch: {}", _0)] FormatMismatch(String), /// Error on internal cursor type #[error("I/O error: {:?}", _0)] Io(#[from] std::io::Error), } pub trait ReadSegment: Sized { fn read_segment(_: T, symbol: u16) -> Result; } #[derive(Debug, Clone, Default)] pub struct App0 { pub len: u64, pub version: u16, pub density_units: u8, pub xdensity: u16, pub ydensity: u16, pub xthumbnail: u8, pub ythumbnail: u8, pub thumbnail: Option>, } impl ReadSegment<&mut R> for App0 { fn read_segment(reader: &mut R, _symbol: u16) -> Result { //let pos = reader.stream_position()?; let len: u64 = reader.read_u16::()? as u64; const APP1_JFIF_MARKER: [u8; 5] = [b'J', b'F', b'I', b'F', b'\0']; if len as usize >= APP1_JFIF_MARKER.len() { let mut jfif_str = [0; 5]; reader.read_exact(&mut jfif_str)?; if jfif_str == APP1_JFIF_MARKER { let version = reader.read_u16::()?; let density_units = reader.read_u8()?; let xdensity = reader.read_u16::()?; let ydensity = reader.read_u16::()?; let xthumbnail = reader.read_u8()?; let ythumbnail = reader.read_u8()?; let thumbnail = if xthumbnail * ythumbnail > 0 { let mut data = vec![0; (3 * xthumbnail * ythumbnail) as usize]; reader.read_exact(&mut data)?; Some(data) } else { None }; Ok(Self { len, version, density_units, xdensity, ydensity, xthumbnail, ythumbnail, thumbnail, }) } else { Err(JfifError::FormatMismatch("Failed to find JFIF marker in APP0 segment".into())) } } else { Err(JfifError::FormatMismatch("APP0 segment is too short".into())) } } } #[derive(Debug, Clone)] pub struct App1 { pub len: u64, pub payload: Payload, } #[derive(Debug, Clone)] pub struct SOS { pub len: u64, } impl ReadSegment<&mut R> for SOS { fn read_segment(reader: &mut R, _symbol: u16) -> Result { let pos = reader.stream_position()?; let mut prev = 0; loop { let v = reader.read_u8()?; if prev == 0xFF && v == 0xFF { prev = 0; continue; } if prev == 0xFF && (v & !0x7) == 0xD0 { prev = 0; continue; } if prev == 0xFF && v == 0 { prev = 0; continue; } if prev == 0xFF { reader.seek(SeekFrom::Current(-2))?; break; } prev = v; } let len = reader.stream_position()? - pos; Ok(Self { len }) } } #[derive(Debug, Clone)] pub enum Payload { Exif(IFD), Xpacket(Vec), Unknown, } impl ReadSegment<&mut R> for App1 { fn read_segment(reader: &mut R, _symbol: u16) -> Result { let pos = reader.stream_position()?; let len: u64 = reader.read_u16::()? as u64; const APP1_EXIF_MARKER: [u8; 6] = [b'E', b'x', b'i', b'f', b'\0', b'\0']; if len as usize >= APP1_EXIF_MARKER.len() { let mut exif_str = [0; 6]; reader.read_exact(&mut exif_str)?; if exif_str == APP1_EXIF_MARKER { let ifd = IFD::new_root(reader, pos as u32 + 2 + 6); reader.seek(SeekFrom::Start(pos + len))?; /* for i in ifd.dump::(10) { println!("{}", i); } for i in ifd.get_sub_ifds(TiffCommonTag::ExifIFDPointer).unwrap()[0].dump::(10) { println!("{}", i); } */ if let Ok(ifd) = ifd { return Ok(Self { len, payload: Payload::Exif(ifd), }); } return Err(JfifError::General("Failed to read exif".into())); } else { reader.seek(SeekFrom::Current(-(exif_str.len() as i64)))?; } } const APP1_XMP_MARKER: &str = concat!("http://ns.adobe.com/xap/1.0/", '\0'); if len as usize >= APP1_XMP_MARKER.len() { let mut xmp_str = [0; APP1_XMP_MARKER.len()]; reader.read_exact(&mut xmp_str)?; if xmp_str == APP1_XMP_MARKER.as_bytes() { log::debug!("Found APP1 XMP marker"); let mut xpacket = vec![0; len as usize - xmp_str.len() - 2]; reader.read_exact(&mut xpacket)?; reader.seek(SeekFrom::Start(pos + len))?; return Ok(Self { len, payload: Payload::Xpacket(xpacket), }); } else { reader.seek(SeekFrom::Current(-(xmp_str.len() as i64)))?; } } reader.seek(SeekFrom::Start(pos + len))?; Ok(Self { len, payload: Payload::Unknown, }) } } #[derive(Debug, Clone)] pub enum Segment { SOI { offset: u64 }, APP0 { offset: u64, app0: App0 }, APP1 { offset: u64, app1: App1 }, SOS { offset: u64, sos: SOS }, EOI, Unknown { offset: u64, marker: u16 }, } #[derive(Debug, Clone)] pub struct Jfif { pub segments: Vec, } impl Jfif { pub fn parse(mut reader: R) -> Result { let mut segments = Vec::new(); let mut pos = reader.stream_position()?; let mut sym = Some(reader.read_u16::()?); while let Some(symbol) = sym { log::debug!("Found symbol: {:X}", symbol); let segment = match symbol { 0xFFD8 => Segment::SOI { offset: pos }, 0xFFD9 => Segment::EOI, 0xFFE0 => Segment::APP0 { offset: pos, app0: App0::read_segment(&mut reader, symbol)?, }, 0xFFE1 => match App1::read_segment(&mut reader, symbol) { Ok(app1) => Segment::APP1 { offset: pos, app1 }, Err(err) => { log::warn!("Failed to read APP1 (EXIF) segement, maybe corrupt: {:?}", err); continue; } }, 0xFFDA => Segment::SOS { offset: pos, sos: SOS::read_segment(&mut reader, symbol)?, }, _ => { log::debug!("Unhandled JFIF segment marker: {:X}", symbol); let len: u64 = reader.read_u16::()? as u64; reader.seek(SeekFrom::Current(len as i64 - 2))?; Segment::Unknown { offset: pos, marker: symbol } } }; if segments.is_empty() && sym != Some(0xFFD8) { return Err(JfifError::General("first marker must be SOI".into())); } segments.push(segment); if symbol == 0xFFD9 { break; // EOI reached } pos = reader.stream_position()?; sym = reader.read_u16::().ok(); } if !segments.is_empty() { Ok(Self { segments }) } else { Err(JfifError::FormatMismatch("JFIF contains no segements".into())) } } pub fn new(file: &RawSource) -> Result { Self::parse(&mut file.reader()) } pub fn exif_ifd(&self) -> Option<&IFD> { self.segments.iter().find_map(|seg| match seg { Segment::APP1 { app1: App1 { payload: Payload::Exif(ifd), .. }, .. } => Some(ifd), _ => None, }) } pub fn xpacket(&self) -> Option<&Vec> { self.segments.iter().find_map(|seg| match seg { Segment::APP1 { app1: App1 { payload: Payload::Xpacket(xpacket), .. }, .. } => Some(xpacket), _ => None, }) } } pub fn is_jfif(file: &RawSource) -> bool { match file.subview(0, 4) { Ok(buf) => { let result = buf[0..4] == [0xFF, 0xD8, 0xFF, 0xE0]; if !result { //panic!("Failed: {:x} {:x} {:x} {:x}", buf[0], buf[1], buf[2], buf[3]); } result } Err(err) => { log::error!("is_jfif(): {:?}", err); false } } } pub fn is_exif(file: &RawSource) -> bool { match file.subview(0, 4) { Ok(buf) => buf[0..4] == [0xFF, 0xD8, 0xFF, 0xE1], Err(err) => { log::error!("is_exif(): {:?}", err); false } } } rawler-0.7.1/src/formats/mod.rs000064400000000000000000000002331046102023000145120ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher pub mod bmff; pub mod ciff; pub mod jfif; pub mod tiff; rawler-0.7.1/src/formats/tiff/entry.rs000064400000000000000000000144661046102023000160410ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use std::io::{Read, Seek}; use log::debug; use serde::{Deserialize, Serialize}; use crate::{ bits::Endian, formats::tiff::{Rational, SRational, TiffAscii, TiffError, Value, apply_corr, reader::ReadByteOrder}, }; use super::{Result, reader::EndianReader}; const TYPE_BYTE: u16 = 1; const TYPE_ASCII: u16 = 2; const TYPE_SHORT: u16 = 3; const TYPE_LONG: u16 = 4; const TYPE_RATIONAL: u16 = 5; const TYPE_SBYTE: u16 = 6; const TYPE_UNDEFINED: u16 = 7; const TYPE_SSHORT: u16 = 8; const TYPE_SLONG: u16 = 9; const TYPE_SRATIONAL: u16 = 10; const TYPE_FLOAT: u16 = 11; const TYPE_DOUBLE: u16 = 12; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Entry { pub tag: u16, pub value: Value, // Embedded value for writer, offset for reader // This is only None when building an IFD for writing. pub embedded: Option, // TODO: rename it } impl std::ops::Deref for Entry { type Target = Value; fn deref(&self) -> &Self::Target { &self.value } } pub struct RawEntry<'a> { pub entry: &'a Entry, pub endian: Endian, pub data: Vec, } impl<'a> RawEntry<'a> { pub fn get_force_u32(&self, idx: usize) -> u32 { self.endian.read_u32(&self.data, idx * 4) } pub fn get_force_u16(&self, idx: usize) -> u16 { self.endian.read_u16(&self.data, idx * 2) } } // 0-1-2-3-4-5-6-7-8-9-10-11-12-13 const DATASHIFTS: [u8; 14] = [0, 0, 0, 1, 2, 3, 0, 0, 1, 2, 3, 2, 3, 2]; impl Entry { pub fn value_type(&self) -> u16 { self.value.value_type() } pub fn count(&self) -> u32 { self.value.count() as u32 } /// Returns the offset /// It is already corrected by `corr` but needs to be summed /// with `base` offset. pub fn offset(&self) -> Option { self.embedded.map(|v| v as usize) } pub fn parse(reader: &mut EndianReader, base: u32, corr: i32, tag: u16) -> Result { let pos = reader.position()? - 2; // TODO -2 because tag is already read let typ = reader.read_u16()?; let count = reader.read_u32()?; // If we don't know the type assume byte data (undefined) let compat_typ = if typ == 0 || typ > 12 { 7 } else { typ }; let bytesize: usize = (count as usize) << DATASHIFTS[compat_typ as usize]; let offset: u32 = if bytesize <= 4 { reader.position()? - base } else { apply_corr(reader.read_u32()?, corr) }; debug!( "Tag: {:#x}, Typ: {:#x}, count: {}, offset: {}, base: {}, corr: {}", tag, typ, count, offset, base, corr ); if offset == u32::MAX || base.checked_add(offset).is_none() { // We hit an invalid offset, ignoring this tag // This happens for Olympus E-P2 images in ImageProc IFD for example. return Err(TiffError::Overflow(format!("Offset {} is invalid for tag 0x{:X}", offset, tag))); } reader.goto(base + offset)?; let entry = match typ { TYPE_BYTE => { let mut v = vec![0; count as usize]; reader.read_u8_into(&mut v)?; Entry { tag, value: Value::Byte(v), embedded: Some(offset), } } TYPE_ASCII => { let mut v = vec![0; count as usize]; reader.read_u8_into(&mut v)?; Entry { tag, value: Value::Ascii(TiffAscii::new_from_raw(&v)), embedded: Some(offset), } } TYPE_SHORT => { let mut v = vec![0; count as usize]; reader.read_u16_into(&mut v)?; Entry { tag, value: Value::Short(v), embedded: Some(offset), } } TYPE_LONG => { let mut v = vec![0; count as usize]; reader.read_u32_into(&mut v)?; Entry { tag, value: Value::Long(v), embedded: Some(offset), } } TYPE_RATIONAL => { let mut tmp = vec![0; count as usize * 2]; // Rational is 2x u32 reader.read_u32_into(&mut tmp)?; let mut v = Vec::with_capacity(count as usize); for chunk in tmp.chunks_exact(2) { v.push(Rational::new(chunk[0], chunk[1])); } Entry { tag, value: Value::Rational(v), embedded: Some(offset), } } TYPE_SBYTE => { let mut v = vec![0; count as usize]; reader.read_i8_into(&mut v)?; Entry { tag, value: Value::SByte(v), embedded: Some(offset), } } TYPE_UNDEFINED => { let mut v = vec![0; count as usize]; reader.read_u8_into(&mut v)?; Entry { tag, value: Value::Undefined(v), embedded: Some(offset), } } TYPE_SSHORT => { let mut v = vec![0; count as usize]; reader.read_i16_into(&mut v)?; Entry { tag, value: Value::SShort(v), embedded: Some(offset), } } TYPE_SLONG => { let mut v = vec![0; count as usize]; reader.read_i32_into(&mut v)?; Entry { tag, value: Value::SLong(v), embedded: Some(offset), } } TYPE_SRATIONAL => { let mut tmp = vec![0; count as usize * 2]; // SRational is 2x i32 reader.read_i32_into(&mut tmp)?; let mut v = Vec::with_capacity(count as usize); for chunk in tmp.chunks_exact(2) { v.push(SRational::new(chunk[0], chunk[1])); } Entry { tag, value: Value::SRational(v), embedded: Some(offset), } } TYPE_FLOAT => { let mut v = vec![0.0; count as usize]; reader.read_f32_into(&mut v)?; Entry { tag, value: Value::Float(v), embedded: Some(offset), } } TYPE_DOUBLE => { let mut v = vec![0.0; count as usize]; reader.read_f64_into(&mut v)?; Entry { tag, value: Value::Double(v), embedded: Some(offset), } } x => { let mut v = vec![0; count as usize]; reader.read_u8_into(&mut v)?; Entry { tag, value: Value::Unknown(x, v), embedded: Some(offset), } } }; reader.goto(pos + 12)?; // Size of IFD entry Ok(entry) } pub fn type_name(&self) -> String { self.value.value_type_name() } } rawler-0.7.1/src/formats/tiff/file.rs000064400000000000000000000012251046102023000156040ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::IFD; use serde::{Deserialize, Serialize}; /// Reader for TIFF files #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct TiffFile { /// Chain of all IFDs in TIFF pub chain: Vec, /// Base offset, starting from file or buffer (good for embedded TIFF in other structures) pub base: u32, /// Offset correction value pub corr: i32, } impl TiffFile { pub fn new(base: u32, corr: i32) -> Self { Self { base, corr, chain: Vec::new() } } pub fn push_ifd(&mut self, ifd: IFD) { self.chain.push(ifd); } } rawler-0.7.1/src/formats/tiff/ifd.rs000064400000000000000000000477031046102023000154420ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::{ Entry, Result, TiffError, Value, apply_corr, entry::RawEntry, read_from_file, reader::{EndianReader, ReadByteOrder}, }; use crate::{ bits::Endian, rawsource::RawSource, tags::{ExifTag, TiffCommonTag, TiffTag}, }; use byteorder::{LittleEndian, ReadBytesExt}; use log::debug; use serde::{Deserialize, Serialize}; use std::{ collections::{BTreeMap, HashMap}, io::{Read, Seek, SeekFrom}, }; #[derive(Debug)] pub enum OffsetMode { Absolute, RelativeToIFD, } #[derive(Debug)] pub enum DataMode { Strips, Tiles, } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct IFD { pub offset: u32, pub base: u32, pub corr: i32, pub next_ifd: u32, pub entries: BTreeMap, pub endian: Endian, pub sub: HashMap>, pub chain: Vec, } // TODO: fixme impl IFD { /// Construct new IFD from reader at specific base pub fn new_root(reader: &mut R, base: u32) -> Result { Self::new_root_with_correction(reader, 0, base, 0, 10, &[TiffCommonTag::SubIFDs.into(), TiffCommonTag::ExifIFDPointer.into()]) } pub fn new_root_with_correction(reader: &mut R, offset: u32, base: u32, corr: i32, max_chain: usize, sub_tags: &[u16]) -> Result { reader.seek(SeekFrom::Start((base + offset) as u64))?; let endian = match reader.read_u16::()? { 0x4949 => Endian::Little, 0x4d4d => Endian::Big, x => { return Err(TiffError::General(format!("TIFF: don't know marker 0x{:x}", x))); } }; let mut reader = EndianReader::new(reader, endian); let magic = reader.read_u16()?; if magic != 42 { return Err(TiffError::General(format!("Invalid magic marker for TIFF: {}", magic))); } let mut next_ifd = reader.read_u32()?; if next_ifd == 0 { return Err(TiffError::General("Invalid TIFF header, contains no root IFD".to_string())); } let reader = reader.into_inner(); let mut multi_sub_tags = vec![]; multi_sub_tags.extend_from_slice(sub_tags); next_ifd = apply_corr(next_ifd, corr); let mut root = IFD::new(reader, next_ifd, base, corr, endian, &multi_sub_tags)?; if root.entries.is_empty() { return Err(TiffError::General("TIFF is invalid, IFD must contain at least one entry".to_string())); } next_ifd = root.next_ifd; while next_ifd != 0 { next_ifd = apply_corr(next_ifd, corr); let ifd = IFD::new(reader, next_ifd, base, corr, endian, &multi_sub_tags)?; if ifd.entries.is_empty() { return Err(TiffError::General("TIFF is invalid, IFD must contain at least one entry".to_string())); } next_ifd = ifd.next_ifd; root.chain.push(ifd); if root.chain.len() > max_chain && max_chain > 0 { break; } } Ok(root) } pub fn new(reader: &mut R, offset: u32, base: u32, corr: i32, endian: Endian, sub_tags: &[u16]) -> Result { reader.seek(SeekFrom::Start((base + offset) as u64))?; let mut sub_ifd_offsets = HashMap::new(); let mut reader = EndianReader::new(reader, endian); let entry_count = reader.read_u16()?; let mut entries = BTreeMap::new(); let mut sub = HashMap::new(); let mut next_pos = reader.position()?; debug!("Parse entries"); for _ in 0..entry_count { reader.goto(next_pos)?; next_pos += 12; //let embedded = reader.read_u32()?; let tag = reader.read_u16()?; match Entry::parse(&mut reader, base, corr, tag) { Ok(entry) => { if sub_tags.contains(&tag) { //let entry = Entry::parse(&mut reader, base, corr, tag)?; match &entry.value { Value::Long(offsets) => { sub_ifd_offsets.insert(tag, offsets.clone()); //sub_ifd_offsets.extend_from_slice(&offsets); } Value::Unknown(tag, offsets) => { sub_ifd_offsets.insert(*tag, vec![offsets[0] as u32]); //sub_ifd_offsets.extend_from_slice(&offsets); } Value::Undefined(_) => { sub_ifd_offsets.insert(tag, vec![entry.offset().unwrap() as u32]); } val => { log::info!( "Found IFD offset tag, but type mismatch: {:?}. Ignoring SubIFD parsing for tag 0x{:X}", val, tag ); } } } entries.insert(entry.tag, entry); } Err(err) => { log::info!("Failed to parse TIFF tag 0x{:X}, skipping: {:?}", tag, err); } } } // Some TIFF writers skip the next ifd pointer // If we get an I/O error, we fallback to 0, signaling the end of IFD chains. let next_ifd = match reader.read_u32() { Ok(ptr) => ptr, Err(e) => { debug!( "TIFF IFD reader failed to get next IFD pointer, fallback to 0 and continue. Original error was: {}", e ); 0 } }; // Process SubIFDs let pos = reader.position()?; let reader = reader.into_inner(); for subs in sub_ifd_offsets { let mut ifds = Vec::new(); for offset in subs.1 { match Self::new(reader, apply_corr(offset, corr), base, corr, endian, &[]) { Ok(ifd) => ifds.push(ifd), Err(err) => { log::warn!("Error while processing TIFF sub-IFD for tag 0x{:X}, ignoring it: {}", subs.0, err); } }; } sub.insert(subs.0, ifds); } EndianReader::new(reader, endian).goto(pos)?; // restore Ok(IFD { offset, base, corr, next_ifd: if next_ifd == 0 { 0 } else { apply_corr(next_ifd, corr) }, entries, endian, sub, chain: vec![], }) } pub fn copy_tag(dst: &mut Self, src: &Self, tag: impl Into) { if let Some(entry) = src.get_entry(tag.into()) { dst.entries.insert(entry.tag, entry.clone()); } } pub fn value_iter(&self) -> impl Iterator { self.entries().iter().map(|(tag, entry)| (tag, &entry.value)) } /* pub fn new(reader: &mut R, offset: u32, base: u32, corr: i32, endian: Endian, sub_tags: &[u16]) -> Result { reader.seek(SeekFrom::Start((base + offset) as u64))?; let mut sub_ifd_offsets = Vec::new(); let mut reader = EndianReader::new(reader, endian); let entry_count = reader.read_u16()?; let mut entries = BTreeMap::new(); let mut sub = Vec::new(); for _ in 0..entry_count { //let embedded = reader.read_u32()?; let tag = reader.read_u16()?; if tag == LegacyTiffRootTag::SubIFDs.into() || sub_tags.contains(&tag) { let entry = Entry::parse(&mut reader, base, corr, tag)?; match entry.value { Value::Long(offsets) => { sub_ifd_offsets.extend_from_slice(&offsets); } _ => { todo!() } } } else { let entry = Entry::parse(&mut reader, base, corr, tag)?; entries.insert(entry.tag, entry); } } let next_ifd = reader.read_u32()?; // Process SubIFDs let pos = reader.position()?; let reader = reader.into_inner(); for offset in sub_ifd_offsets { let ifd = IFD::new(reader, apply_corr(offset, corr), base, corr, endian, sub_tags)?; sub.push(ifd); } EndianReader::new(reader, endian).goto(pos)?; // restore Ok(Self { offset, base, corr, next_ifd: if next_ifd == 0 { 0 } else { apply_corr(next_ifd, corr) }, entries, endian, sub, }) } */ /// Extend the IFD with sub-IFDs from a specific tag. /// The IFD corrections are used from current IFD. pub fn extend_sub_ifds(&mut self, reader: &mut R, tag: u16) -> Result>> { if let Some(entry) = self.get_entry(tag) { let mut subs = Vec::new(); match &entry.value { Value::Long(offsets) => { for off in offsets { let ifd = Self::new_root_with_correction(reader, *off, self.base, self.corr, 10, &[])?; subs.push(ifd); } self.sub.insert(tag, subs); Ok(self.sub.get(&tag)) } val => { debug!("Found IFD offset tag, but type mismatch: {:?}", val); todo!() } } } else { Ok(None) } } pub fn extend_sub_ifds_custom(&mut self, reader: &mut R, tag: u16, op: F) -> Result>> where R: Read + Seek, F: FnOnce(&mut R, &IFD, &Entry) -> Result>>, { if let Some(entry) = self.get_entry(tag) { if let Some(subs) = op(reader, self, entry)? { self.sub.insert(tag, subs); Ok(self.sub.get(&tag)) } else { Ok(None) } } else { Ok(None) } } pub fn sub_ifds(&self) -> &HashMap> { &self.sub } pub fn entry_count(&self) -> u16 { self.entries.len() as u16 } pub fn next_ifd(&self) -> u32 { self.next_ifd } pub fn entries(&self) -> &BTreeMap { &self.entries } pub fn get_entry(&self, tag: T) -> Option<&Entry> { self.entries.get(&tag.into()) } pub fn get_entry_subs(&self, tag: T) -> Option<&Entry> { for subs in &self.sub { for ifd in subs.1 { if let Some(entry) = ifd.get_entry_recursive(tag) { return Some(entry); } } } None } pub fn get_entry_recursive(&self, tag: T) -> Option<&Entry> { self.entries.get(&tag.into()).or_else(|| self.get_entry_subs(tag)) } pub fn get_entry_raw<'a, T: TiffTag, R: Read + Seek>(&'a self, tag: T, file: &mut R) -> Result>> { if let Some(entry) = self.get_entry(tag) { return Ok(Some(RawEntry { entry, endian: self.endian, data: read_from_file(file, self.base + entry.offset().unwrap() as u32, entry.byte_size())?, })); } Ok(None) } /// Get the data of a tag by just reading as many `len` bytes from offet. pub fn get_entry_raw_with_len<'a, T: TiffTag, R: Read + Seek>(&'a self, tag: T, file: &mut R, len: usize) -> Result>> { if let Some(entry) = self.get_entry(tag) { return Ok(Some(RawEntry { entry, endian: self.endian, data: read_from_file(file, self.base + entry.offset().unwrap() as u32, len)?, })); } Ok(None) } pub fn get_sub_ifd_all(&self, tag: T) -> Option<&Vec> { self.sub.get(&tag.into()) } pub fn get_sub_ifd(&self, tag: T) -> Option<&IFD> { if let Some(ifds) = self.get_sub_ifd_all(tag) { if ifds.len() == 1 { ifds.get(0) } else { log::warn!( "get_sub_ifd() for tag {:?} found more IFDs than expected: {}. Fallback to first IFD!", tag, ifds.len() ); ifds.get(0) } } else { None } } pub fn find_ifds_with_tag(&self, tag: T) -> Vec<&IFD> { let mut ifds = Vec::new(); if self.get_entry(tag).is_some() { ifds.push(self); } // Now search in all sub IFDs for subs in self.sub_ifds() { for ifd in subs.1 { ifds.append(&mut ifd.find_ifds_with_tag(tag)); } } ifds } pub fn find_first_ifd_with_tag(&self, tag: T) -> Option<&IFD> { self.find_ifds_with_tag(tag).get(0).copied() } /* pub fn get_ifd(&self, tag: T, reader: &mut R) -> Result> { if let Some(offset) = self.get_entry(tag) { match &offset.value { Value::Long(v) => { debug!("IFD offset: {}", v[0]); Ok(Some(IFD::new(reader, apply_corr(v[0], self.corr), self.base, self.corr, self.endian, &[])?)) } _ => { return Err(TiffError::General(format!( "TIFF tag {:?} is not of type LONG, thus can not be used as IFD offset in get_ifd().", tag ))); } } } else { Ok(None) } } */ pub fn has_entry(&self, tag: T) -> bool { self.get_entry(tag).is_some() } pub fn sub_buf(&self, reader: &mut R, offset: usize, len: usize) -> Result> { //&buf[self.start_offset+offset..self.start_offset+offset+len] let mut buf = vec![0; len]; reader.seek(SeekFrom::Start(self.base as u64 + offset as u64))?; reader.read_exact(&mut buf)?; Ok(buf) } pub fn contains_singlestrip_image(&self) -> bool { self.get_entry(TiffCommonTag::StripOffsets).map(Entry::count).unwrap_or(0) == 1 } pub fn singlestrip_data_rawsource<'a>(&self, rawsource: &'a RawSource) -> Result<&'a [u8]> { assert!(self.contains_singlestrip_image()); let offset = self .get_entry(TiffCommonTag::StripOffsets) .ok_or_else(|| TiffError::General(("tag not found").to_string()))? .value .force_u32(0); let len = self .get_entry(TiffCommonTag::StripByteCounts) .ok_or_else(|| TiffError::General(("tag not found").to_string()))? .value .force_usize(0); Ok(rawsource.subview((self.base + offset) as u64, len as u64)?) } /// Return byte slices to strip data. /// If there exists a single strip only or if all strips are continous, /// the second return value contains the whole strip data in a single slice. pub fn strip_data<'a>(&self, rawsource: &'a RawSource) -> Result<(Vec<&'a [u8]>, Option<&'a [u8]>)> { if !self.has_entry(TiffCommonTag::StripOffsets) { return Err(TiffError::General("IFD contains no strip data".into())); } let offsets = if let Some(Entry { value: Value::Long(data), .. }) = self.get_entry(TiffCommonTag::StripOffsets) { data } else { return Err(TiffError::General("Invalid datatype for StripOffsets".to_string())); }; let sizes = if let Some(Entry { value: Value::Long(data), .. }) = self.get_entry(TiffCommonTag::StripByteCounts) { data } else { return Err(TiffError::General("Invalid datatype for StripByteCounts".to_string())); }; if offsets.len() != sizes.len() { return Err(TiffError::General(format!( "Can't get data from strips: offsets has len {} but sizes has len {}", offsets.len(), sizes.len() ))); } // Check if all slices are continous let (is_continous, end_off) = offsets.iter().zip(sizes.iter()).fold( (true, offsets[0]), |acc, val| { if acc.0 && acc.1 == *val.0 { (true, acc.1 + *val.1) } else { (false, 0) } }, ); let mut subviews = Vec::with_capacity(offsets.len()); for (offset, size) in offsets.iter().zip(sizes.iter()) { subviews.push(rawsource.subview((self.base + *offset) as u64, *size as u64)?); } let continous = if is_continous { Some(rawsource.subview((self.base + offsets[0]) as u64, (end_off - offsets[0]) as u64)?) } else { None }; Ok((subviews, continous)) } pub fn tile_data<'a>(&self, rawsource: &'a RawSource) -> Result> { let offsets = if let Some(Entry { value: Value::Long(data), .. }) = self.get_entry(TiffCommonTag::TileOffsets) { data } else { return Err(TiffError::General("Invalid datatype for TileOffsets".to_string())); }; let byte_counts = if let Some(Entry { value: Value::Long(data), .. }) = self.get_entry(TiffCommonTag::TileByteCounts) { data } else { return Err(TiffError::General("Invalid datatype for TileByteCounts".to_string())); }; let mut tile_slices = Vec::with_capacity(offsets.len()); offsets.iter().zip(byte_counts.iter()).for_each(|(offset, size)| { tile_slices.push(rawsource.subview(*offset as u64, *size as u64).map_err(TiffError::Io)); }); Ok(tile_slices.into_iter().collect::>>()?) } /// Check for the data mode (Strips or Tiles) pub fn data_mode(&self) -> Result { if self.has_entry(TiffCommonTag::StripOffsets) { Ok(DataMode::Strips) } else if self.has_entry(TiffCommonTag::TileOffsets) { Ok(DataMode::Tiles) } else { Err(TiffError::General("IFD has no StripOffsets or TileOffsets tag".into())) } } pub fn parse_makernote(&self, reader: &mut R, offset_mode: OffsetMode, sub_tags: &[u16]) -> Result> { if let Some(exif) = self.get_entry(ExifTag::MakerNotes) { let offset = exif.offset().unwrap() as u32; debug!("Makernote offset: {}", offset); match &exif.value { Value::Undefined(data) => { let mut off = 0; let mut endian = self.endian; // Olympus starts the makernote with their own name, sometimes truncated if data[0..5] == b"OLYMP"[..] { off += 8; if data[0..7] == b"OLYMPUS"[..] { off += 4; } } // Epson starts the makernote with its own name if data[0..5] == b"EPSON"[..] { off += 8; } // Fujifilm has 12 extra bytes if data[0..8] == b"FUJIFILM"[..] { off += 12; } // Sony has 12 extra bytes if data[0..9] == b"SONY DSC "[..] { off += 12; } // Pentax makernote starts with AOC\0 - If it's there, skip it if data[0..4] == b"AOC\0"[..] { off += 4; } // Pentax can also start with PENTAX and in that case uses different offsets if data[0..6] == b"PENTAX"[..] { off += 8; let endian = if data[off..off + 2] == b"II"[..] { Endian::Little } else { Endian::Big }; // All offsets in this IFD are relative to the start of this tag, // so wie use the offset as correction value. let corr = offset as i32; // The IFD itself starts 10 bytes after tag offset. return Ok(Some(IFD::new(reader, offset + 10, self.base, corr, endian, sub_tags)?)); } if data[0..7] == b"Nikon\0\x02"[..] { off += 10; let endian = if data[off..off + 2] == b"II"[..] { Endian::Little } else { Endian::Big }; return Ok(Some(IFD::new(reader, 8, self.base + offset + 10, 0, endian, sub_tags)?)); } // Some have MM or II to indicate endianness - read that if data[off..off + 2] == b"II"[..] { off += 2; endian = Endian::Little; } if data[off..off + 2] == b"MM"[..] { off += 2; endian = Endian::Big; } match offset_mode { OffsetMode::Absolute => Ok(Some(IFD::new(reader, offset + off as u32, self.base, self.corr, endian, sub_tags)?)), OffsetMode::RelativeToIFD => { // Value offsets are relative to IFD offset let corr = offset + off as u32; Ok(Some(IFD::new(reader, offset + off as u32, self.base, corr as i32, endian, sub_tags)?)) } } } _ => Err(TiffError::General("EXIF makernote has unknown type".to_string())), } } else { Ok(None) } } pub fn dump(&self, limit: usize) -> Vec { let mut out = Vec::new(); out.push(format!("IFD entries: {}\n", self.entries.len())); out.push(format!("{0:<34} | {1:<10} | {2:<6} | {3}\n", "Tag", "Type", "Count", "Data")); for (tag, entry) in &self.entries { let mut line = String::new(); let tag_name = { if let Ok(name) = T::try_from(*tag) { format!("{:?}", name) } else { format!("", tag) } }; line.push_str(&format!( "{0:#06x} : {0:<6} {1:<20}| {2:<10} | {3:<6} | ", tag, tag_name, entry.type_name(), entry.count() )); line.push_str(&entry.visual_rep(limit)); out.push(line); } for subs in self.sub_ifds().iter() { for (i, sub) in subs.1.iter().enumerate() { out.push(format!("SubIFD({}:{})", subs.0, i)); for line in sub.dump::(limit) { out.push(format!(" {}", line)); } } } out } } rawler-0.7.1/src/formats/tiff/mod.rs000064400000000000000000000216621046102023000154530ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use std::io::{Read, Seek, SeekFrom}; use thiserror::Error; pub mod entry; pub mod file; pub mod ifd; pub mod reader; pub mod value; pub mod writer; pub use entry::Entry; pub use ifd::IFD; pub use reader::GenericTiffReader; pub use value::{IntoTiffValue, Rational, SRational, TiffAscii, Value}; pub use writer::{DirectoryWriter, TiffWriter}; const TIFF_MAGIC: u16 = 42; #[allow(clippy::upper_case_acronyms)] #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum CompressionMethod { None = 1, Huffman = 2, Fax3 = 3, Fax4 = 4, LZW = 5, OldJPEG = 6, // TODO: RENAME // "Extended JPEG" or "new JPEG" style ModernJPEG = 7, Deflate = 8, OldDeflate = 0x80B2, PackBits = 0x8005, // DNG Extensions LossyJPEG = 34892, JPEGXL = 52546, } impl ExtractFromIFD for CompressionMethod { fn extract(ifd: &IFD) -> Result> { let tag = TiffCommonTag::Compression; if let Some(entry) = ifd.get_entry(tag) { let x = entry.value.force_u16(0); Ok(Some( Self::n(x).ok_or_else(|| TiffError::General(format!("Unknown value {} for {:?}", x, tag)))?, )) } else { Ok(None) } } } impl From for Value { fn from(value: CompressionMethod) -> Self { Value::Short(vec![value as u16]) } } #[allow(clippy::upper_case_acronyms)] #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum PhotometricInterpretation { WhiteIsZero = 0, BlackIsZero = 1, RGB = 2, RGBPalette = 3, TransparencyMask = 4, CMYK = 5, YCbCr = 6, CIELab = 8, // Defined by DNG CFA = 32803, LinearRaw = 34892, } impl ExtractFromIFD for PhotometricInterpretation { fn extract(ifd: &IFD) -> Result> { let tag = TiffCommonTag::PhotometricInt; if let Some(entry) = ifd.get_entry(tag) { let x = entry.value.force_u16(0); Ok(Some( Self::n(x).ok_or_else(|| TiffError::General(format!("Unknown value {} for {:?}", x, tag)))?, )) } else { Ok(None) } } } impl From for Value { fn from(value: PhotometricInterpretation) -> Self { Value::Short(vec![value as u16]) } } #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum PreviewColorSpace { Unknown = 0, GrayGamma = 1, SRgb = 2, AdobeRGB = 3, ProPhotoRGB = 5, } impl ExtractFromIFD for PreviewColorSpace { fn extract(ifd: &IFD) -> Result> { let tag = DngTag::PreviewColorSpace; if let Some(entry) = ifd.get_entry(tag) { let x = entry.value.force_u16(0); Ok(Some( Self::n(x).ok_or_else(|| TiffError::General(format!("Unknown value {} for {:?}", x, tag)))?, )) } else { Ok(None) } } } impl From for Value { fn from(value: PreviewColorSpace) -> Self { Value::Long(vec![value as u32]) } } #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum PlanarConfiguration { Chunky = 1, Planar = 2, } impl ExtractFromIFD for PlanarConfiguration { fn extract(ifd: &IFD) -> Result> { let tag = ExifTag::PlanarConfiguration; if let Some(entry) = ifd.get_entry(tag) { let x = entry.value.force_u16(0); Ok(Some( Self::n(x).ok_or_else(|| TiffError::General(format!("Unknown value {} for {:?}", x, tag)))?, )) } else { Ok(None) } } } impl From for Value { fn from(value: PlanarConfiguration) -> Self { Value::Short(vec![value as u16]) } } #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum Predictor { None = 1, Horizontal = 2, } impl ExtractFromIFD for Predictor { fn extract(ifd: &IFD) -> Result> { let tag = TiffCommonTag::Predictor; if let Some(entry) = ifd.get_entry(tag) { let x = entry.value.force_u16(0); Ok(Some( Self::n(x).ok_or_else(|| TiffError::General(format!("Unknown value {} for {:?}", x, tag)))?, )) } else { Ok(None) } } } impl From for Value { fn from(value: Predictor) -> Self { Value::Short(vec![value as u16]) } } /// Type to represent resolution units #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum ResolutionUnit { None = 1, Inch = 2, Centimeter = 3, } impl ExtractFromIFD for ResolutionUnit { fn extract(ifd: &IFD) -> Result> { let tag = TiffCommonTag::Predictor; if let Some(entry) = ifd.get_entry(tag) { let x = entry.value.force_u16(0); Ok(Some( Self::n(x).ok_or_else(|| TiffError::General(format!("Unknown value {} for {:?}", x, tag)))?, )) } else { Ok(None) } } } impl From for Value { fn from(value: ResolutionUnit) -> Self { Value::Short(vec![value as u16]) } } #[allow(clippy::upper_case_acronyms)] #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum SampleFormat { Uint = 1, Int = 2, IEEEFP = 3, Void = 4, } impl From for Value { fn from(value: SampleFormat) -> Self { Value::Short(vec![value as u16]) } } impl ExtractFromIFD for SampleFormat { fn extract(ifd: &IFD) -> Result> { let tag = TiffCommonTag::SampleFormat; if let Some(entry) = ifd.get_entry(tag) { let x = entry.value.force_u16(0); Ok(Some( Self::n(x).ok_or_else(|| TiffError::General(format!("Unknown value {} for {:?}", x, tag)))?, )) } else { Ok(None) } } } pub trait ExtractFromIFD where Self: Sized, { fn extract(ifd: &IFD) -> Result>; } /// Error variants for compressor #[derive(Debug, Error)] pub enum TiffError { /// Overflow of input, size constraints... #[error("Overflow error: {}", _0)] Overflow(String), #[error("General error: {}", _0)] General(String), #[error("Format mismatch: {}", _0)] FormatMismatch(String), /// Error on internal cursor type #[error("I/O error: {:?}", _0)] Io(#[from] std::io::Error), } /// Result type for Compressor results pub type Result = std::result::Result; use crate::tags::{DngTag, ExifTag, TiffCommonTag}; /* impl From for Entry { fn from(value: Value) -> Self { Entry { value, embedded: None } } } */ pub struct DataOffset { pub offset: usize, } fn apply_corr(offset: u32, corr: i32) -> u32 { ((offset as i64) + (corr as i64)) as u32 } pub struct DirReader {} fn read_from_file(file: &mut R, offset: u32, size: usize) -> Result> { file.seek(SeekFrom::Start(offset as u64))?; let mut buf = vec![0; size]; file.read_exact(&mut buf)?; Ok(buf) } #[cfg(test)] mod tests { use std::io::{Cursor, Seek, SeekFrom}; use crate::{formats::tiff::reader::TiffReader, tags::TiffCommonTag}; use super::*; #[test] fn encode_tiff_test() -> std::result::Result<(), Box> { let mut buf = Cursor::new(Vec::new()); let mut tiff = TiffWriter::new(&mut buf)?; let mut dir = tiff.new_directory(); let offset = { let mut dir2 = tiff.new_directory(); dir2.add_tag(32_u16, 23_u16); dir2.build(&mut tiff)? }; dir.add_tag(TiffCommonTag::ActiveArea, offset as u16); dir.add_tag(TiffCommonTag::ActiveArea, [23_u16, 45_u16]); dir.add_tag(TiffCommonTag::ActiveArea, &[23_u16, 45_u16][..]); dir.add_tag(TiffCommonTag::ActiveArea, "Fobbar"); Ok(()) } #[test] fn write_tiff_file_basic() -> std::result::Result<(), Box> { let mut output = Cursor::new(Vec::new()); let mut tiff = TiffWriter::new(&mut output)?; let mut dir = tiff.new_directory(); let offset = { let mut dir2 = tiff.new_directory(); dir2.add_tag(32_u16, 23_u16); dir2.build(&mut tiff)? }; dir.add_tag(TiffCommonTag::ExifIFDPointer, offset); dir.add_tag(TiffCommonTag::ActiveArea, [9_u16, 10_u16, 11_u16, 12, 13, 14]); dir.add_tag(TiffCommonTag::BlackLevels, [9_u16, 10_u16]); dir.add_tag(TiffCommonTag::WhiteLevel, [11_u16]); dir.add_tag(TiffCommonTag::BitsPerSample, [12_u32]); dir.add_tag(TiffCommonTag::ResolutionUnit, [-5_i32]); dir.add_tag(TiffCommonTag::Artist, "AT"); tiff.build(dir)?; //assert!(TiffReader::is_tiff(&mut output) == true); let mut garbage_output: Vec = vec![0x4a, 0xee]; // Garbage garbage_output.extend_from_slice(&output.into_inner()); let mut garbage_output = Cursor::new(garbage_output); garbage_output.seek(SeekFrom::Start(2))?; let reader = GenericTiffReader::new(&mut garbage_output, 1, 1, Some(16), &[])?; // 1 byte offset correction assert_eq!(reader.root_ifd().entry_count(), 7); assert!(reader.root_ifd().get_entry(TiffCommonTag::WhiteLevel).is_some()); assert!(matches!( reader.root_ifd().get_entry(TiffCommonTag::ExifIFDPointer).unwrap().value, Value::Long { .. } )); assert!(matches!( reader.root_ifd().get_entry(TiffCommonTag::WhiteLevel).unwrap().value, Value::Short { .. } )); Ok(()) } } rawler-0.7.1/src/formats/tiff/reader.rs000064400000000000000000000306561046102023000161410ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use super::{Entry, IFD, Result, TiffError, apply_corr, entry::RawEntry, file::TiffFile}; use crate::{ bits::Endian, tags::{ExifTag, TiffCommonTag, TiffTag}, }; use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use std::io::{Cursor, Read, Seek, SeekFrom}; pub trait TiffReader { fn file(&self) -> &TiffFile; fn file_mut(&mut self) -> &mut TiffFile; fn chains(&self) -> &Vec { &self.file().chain } fn get_endian(&self) -> Endian { self.root_ifd().endian } /// Returns a list of well-known tags representing SubIFDs. fn wellknown_sub_ifd_tags(&self) -> Vec { vec![ TiffCommonTag::SubIFDs.into(), TiffCommonTag::ExifIFDPointer.into(), ExifTag::GPSInfo.into(), ExifTag::IccProfile.into(), ] } fn root_ifd(&self) -> &IFD { if self.file().chain.is_empty() { panic!("TIFF must have at least one root IFD but the IFD list is empty"); } &self.file().chain[0] } fn get_entry(&self, tag: T) -> Option<&Entry> { for ifd in &self.file().chain { if let Some(x) = ifd.get_entry(tag) { return Some(x); } } None } fn get_entry_raw<'a, T: TiffTag, R: Read + Seek>(&'a self, tag: T, file: &mut R) -> Result>> { for ifd in &self.file().chain { if let Some(entry) = ifd.get_entry_raw(tag, file)? { return Ok(Some(entry)); } } Ok(None) } fn has_entry(&self, tag: T) -> bool { self.get_entry(tag).is_some() } fn find_ifds_with_tag(&self, tag: T) -> Vec<&IFD> { let mut ifds = Vec::new(); for ifd in &self.file().chain { if ifd.has_entry(tag) { ifds.push(ifd); } // Now search in all sub IFDs for subs in ifd.sub_ifds() { for ifd in subs.1 { if ifd.has_entry(tag) { ifds.push(ifd); } } } } ifds } fn find_ifd_with_new_subfile_type(&self, typ: u32) -> Option<&IFD> { let list = self.find_ifds_with_tag(TiffCommonTag::NewSubFileType); list .iter() .find(|ifd| ifd.get_entry(TiffCommonTag::NewSubFileType).expect("IFD must contain this entry").force_u32(0) == typ) .copied() } // TODO: legacy wrapper fn find_first_ifd(&self, tag: T) -> Option<&IFD> { self.find_first_ifd_with_tag(tag) } fn find_first_ifd_with_tag(&self, tag: T) -> Option<&IFD> { let ifds = self.find_ifds_with_tag(tag); if ifds.is_empty() { None } else { Some(ifds[0]) } } fn get_first_entry(&self, _tag: u16) -> Option { unimplemented!(); /* Some(Entry { value: (32 as u16).into(), embedded: None, }) */ } fn read_data(&self, file: &mut R, uncorr_offset: u32, buffer: &mut [u8]) -> Result<()> { file.seek(SeekFrom::Start(apply_corr(uncorr_offset, self.file().corr) as u64))?; file.read_exact(buffer)?; Ok(()) } fn parse_ifd(&self, reader: &mut R, offset: u32, base: u32, corr: i32, endian: Endian, sub_tags: &[u16]) -> Result { IFD::new(reader, offset, base, corr, endian, sub_tags) } /// Construct a TIFF reader from Read capable objects /// /// `corr` is a correction value that should be applied to offsets received /// from file structure. fn parse_file(&mut self, file: &mut R, max_chained: Option, sub_tags: &[u16]) -> Result<()> { let endian = match file.read_u16::()? { 0x4949 => Endian::Little, 0x4d4d => Endian::Big, x => { return Err(TiffError::General(format!("TIFF: don't know marker 0x{:x}", x))); } }; let mut reader = EndianReader::new(file, endian); let magic = reader.read_u16()?; if magic != 42 { //return Err(TiffError::General(format!("Invalid magic marker for TIFF: {}", magic))); } let mut next_ifd = reader.read_u32()?; if next_ifd == 0 { return Err(TiffError::General("Invalid TIFF header, contains no root IFD".to_string())); } let reader = reader.into_inner(); next_ifd = apply_corr(next_ifd, self.file().corr); let mut chain = Vec::new(); while next_ifd != 0 { // TODO: check if offset is in range let mut multi_sub_tags = self.wellknown_sub_ifd_tags(); multi_sub_tags.extend_from_slice(sub_tags); let ifd = IFD::new(reader, next_ifd, self.file().base, self.file().corr, endian, &multi_sub_tags)?; if ifd.entries.is_empty() { return Err(TiffError::General("TIFF is invalid, IFD must contain at least one entry".to_string())); } next_ifd = ifd.next_ifd; chain.push(ifd); if let Some(max) = max_chained { if chain.len() > max { break; } } } if chain.is_empty() { return Err(TiffError::General("TIFF is invalid, must contain at least one IFD".to_string())); } self.file_mut().chain = chain; Ok(()) } } /// Reader for TIFF files #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct GenericTiffReader { file: TiffFile, } impl TiffReader for GenericTiffReader { fn file(&self) -> &TiffFile { &self.file } fn file_mut(&mut self) -> &mut TiffFile { &mut self.file } } impl GenericTiffReader { /// Check if buffer looks like a TIFF file pub fn is_tiff>(buffer: T) -> bool { let buffer = buffer.as_ref(); buffer[0] == 0x49 || buffer[0] == 0x4d // TODO } pub fn little_endian(&self) -> bool { self.file.chain.first().unwrap().endian == Endian::Little } /// Construct a TIFF reader from a byte buffer /// /// Byte buffer must be a full TIFF file structure, endianess is detected from TIFF /// header. /// /// `corr` is a correction value that should be applied to offsets received /// from file structure. pub fn new_with_buffer>(buffer: T, base: u32, corr: i32, max_chained: Option) -> Result { let mut cursor = Cursor::new(buffer.as_ref()); cursor.seek(SeekFrom::Start(base as u64))?; Self::new(&mut cursor, base, corr, max_chained, &[]) } /// Construct a TIFF reader from Read capable objects /// /// `corr` is a correction value that should be applied to offsets received /// from file structure. pub fn new(file: &mut R, base: u32, corr: i32, max_chained: Option, sub_tags: &[u16]) -> Result { let mut ins = Self { file: TiffFile::new(base, corr), }; ins.parse_file(file, max_chained, sub_tags)?; Ok(ins) } } pub trait ReadByteOrder { fn read_u8(&mut self) -> std::io::Result; fn read_i8(&mut self) -> std::io::Result; fn read_u16(&mut self) -> std::io::Result; fn read_i16(&mut self) -> std::io::Result; fn read_u32(&mut self) -> std::io::Result; fn read_i32(&mut self) -> std::io::Result; fn read_u64(&mut self) -> std::io::Result; fn read_i64(&mut self) -> std::io::Result; fn read_f32(&mut self) -> std::io::Result; fn read_f64(&mut self) -> std::io::Result; fn read_u8_into(&mut self, dst: &mut [u8]) -> std::io::Result<()>; fn read_i8_into(&mut self, dst: &mut [i8]) -> std::io::Result<()>; fn read_u16_into(&mut self, dst: &mut [u16]) -> std::io::Result<()>; fn read_i16_into(&mut self, dst: &mut [i16]) -> std::io::Result<()>; fn read_u32_into(&mut self, dst: &mut [u32]) -> std::io::Result<()>; fn read_i32_into(&mut self, dst: &mut [i32]) -> std::io::Result<()>; fn read_u64_into(&mut self, dst: &mut [u64]) -> std::io::Result<()>; fn read_i64_into(&mut self, dst: &mut [i64]) -> std::io::Result<()>; fn read_f32_into(&mut self, dst: &mut [f32]) -> std::io::Result<()>; fn read_f64_into(&mut self, dst: &mut [f64]) -> std::io::Result<()>; } pub struct EndianReader<'a, R: Read + Seek + 'a> { endian: Endian, inner: &'a mut R, } impl<'a, R: Read + Seek + 'a> EndianReader<'a, R> { pub fn new(inner: &'a mut R, endian: Endian) -> Self { Self { endian, inner } } pub fn into_inner(self) -> &'a mut R { self.inner } pub fn inner(&'a mut self) -> &'a mut R { self.inner } pub fn position(&mut self) -> Result { Ok(self.inner.stream_position().map(|v| v as u32)?) } // TODO: try_from? pub fn goto(&mut self, offset: u32) -> Result<()> { self.inner.seek(SeekFrom::Start(offset as u64))?; Ok(()) // TODO: try_from? } } impl<'a, R: Read + Seek + 'a> ReadByteOrder for EndianReader<'a, R> { fn read_u16(&mut self) -> std::io::Result { match self.endian { Endian::Little => self.inner.read_u16::(), Endian::Big => self.inner.read_u16::(), } } fn read_u8(&mut self) -> std::io::Result { self.inner.read_u8() } fn read_i8(&mut self) -> std::io::Result { match self.endian { Endian::Little => self.inner.read_i8(), Endian::Big => self.inner.read_i8(), } } fn read_i16(&mut self) -> std::io::Result { match self.endian { Endian::Little => self.inner.read_i16::(), Endian::Big => self.inner.read_i16::(), } } fn read_u32(&mut self) -> std::io::Result { match self.endian { Endian::Little => self.inner.read_u32::(), Endian::Big => self.inner.read_u32::(), } } fn read_i32(&mut self) -> std::io::Result { match self.endian { Endian::Little => self.inner.read_i32::(), Endian::Big => self.inner.read_i32::(), } } fn read_u64(&mut self) -> std::io::Result { match self.endian { Endian::Little => self.inner.read_u64::(), Endian::Big => self.inner.read_u64::(), } } fn read_i64(&mut self) -> std::io::Result { match self.endian { Endian::Little => self.inner.read_i64::(), Endian::Big => self.inner.read_i64::(), } } fn read_f32(&mut self) -> std::io::Result { match self.endian { Endian::Little => self.inner.read_f32::(), Endian::Big => self.inner.read_f32::(), } } fn read_f64(&mut self) -> std::io::Result { match self.endian { Endian::Little => self.inner.read_f64::(), Endian::Big => self.inner.read_f64::(), } } fn read_u8_into(&mut self, dst: &mut [u8]) -> std::io::Result<()> { self.inner.read_exact(dst) } fn read_i8_into(&mut self, dst: &mut [i8]) -> std::io::Result<()> { self.inner.read_i8_into(dst) } fn read_u16_into(&mut self, dst: &mut [u16]) -> std::io::Result<()> { match self.endian { Endian::Little => self.inner.read_u16_into::(dst), Endian::Big => self.inner.read_u16_into::(dst), } } fn read_i16_into(&mut self, dst: &mut [i16]) -> std::io::Result<()> { match self.endian { Endian::Little => self.inner.read_i16_into::(dst), Endian::Big => self.inner.read_i16_into::(dst), } } fn read_u32_into(&mut self, dst: &mut [u32]) -> std::io::Result<()> { match self.endian { Endian::Little => self.inner.read_u32_into::(dst), Endian::Big => self.inner.read_u32_into::(dst), } } fn read_i32_into(&mut self, dst: &mut [i32]) -> std::io::Result<()> { match self.endian { Endian::Little => self.inner.read_i32_into::(dst), Endian::Big => self.inner.read_i32_into::(dst), } } fn read_u64_into(&mut self, dst: &mut [u64]) -> std::io::Result<()> { match self.endian { Endian::Little => self.inner.read_u64_into::(dst), Endian::Big => self.inner.read_u64_into::(dst), } } fn read_i64_into(&mut self, dst: &mut [i64]) -> std::io::Result<()> { match self.endian { Endian::Little => self.inner.read_i64_into::(dst), Endian::Big => self.inner.read_i64_into::(dst), } } fn read_f32_into(&mut self, dst: &mut [f32]) -> std::io::Result<()> { match self.endian { Endian::Little => self.inner.read_f32_into::(dst), Endian::Big => self.inner.read_f32_into::(dst), } } fn read_f64_into(&mut self, dst: &mut [f64]) -> std::io::Result<()> { match self.endian { Endian::Little => self.inner.read_f64_into::(dst), Endian::Big => self.inner.read_f64_into::(dst), } } } rawler-0.7.1/src/formats/tiff/value.rs000064400000000000000000001247051046102023000160120ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use byteorder::{NativeEndian, WriteBytesExt}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::{convert::Infallible, ffi::CString, fmt::Display, io::Write, num::TryFromIntError}; use super::{Result, TiffError}; /// Type to represent tiff values of type `RATIONAL` #[derive(Clone, Debug, Default, Copy)] pub struct Rational { pub n: u32, pub d: u32, } impl PartialEq for Rational { fn eq(&self, other: &Self) -> bool { let n1: u64 = self.n as u64 * other.d as u64; let n2: u64 = self.d as u64 * other.n as u64; n1.eq(&n2) } } impl Eq for Rational {} #[allow(clippy::non_canonical_partial_ord_impl)] impl PartialOrd for Rational { fn partial_cmp(&self, other: &Self) -> Option { let n1: u64 = self.n as u64 * other.d as u64; let n2: u64 = self.d as u64 * other.n as u64; Some(n1.cmp(&n2)) } } impl Ord for Rational { fn cmp(&self, other: &Self) -> std::cmp::Ordering { let n1: u64 = self.n as u64 * other.d as u64; let n2: u64 = self.d as u64 * other.n as u64; n1.cmp(&n2) } } impl Display for Rational { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!("{}/{}", self.n, self.d)) } } impl Display for SRational { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!("{}/{}", self.n, self.d)) } } impl TryFrom for usize { type Error = TryFromIntError; fn try_from(value: Rational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as usize) // TODO } } impl TryFrom for u8 { type Error = TryFromIntError; fn try_from(value: Rational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as u8) // TODO } } impl TryFrom for u16 { type Error = TryFromIntError; fn try_from(value: Rational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as u16) // TODO } } impl TryFrom for u32 { type Error = TryFromIntError; fn try_from(value: Rational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as u32) // TODO } } impl TryFrom for u64 { type Error = TryFromIntError; fn try_from(value: Rational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as u64) // TODO } } impl TryFrom for i8 { type Error = TryFromIntError; fn try_from(value: Rational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as i8) // TODO } } impl TryFrom for i16 { type Error = TryFromIntError; fn try_from(value: Rational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as i16) // TODO } } impl TryFrom for i32 { type Error = TryFromIntError; fn try_from(value: Rational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as i32) // TODO } } impl TryFrom for i64 { type Error = TryFromIntError; fn try_from(value: Rational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as i64) // TODO } } impl TryFrom for f32 { type Error = TryFromIntError; fn try_from(value: Rational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as f32) // TODO } } impl TryFrom for usize { type Error = TryFromIntError; fn try_from(value: SRational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as usize) // TODO } } impl TryFrom for u8 { type Error = TryFromIntError; fn try_from(value: SRational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as u8) // TODO } } impl TryFrom for u16 { type Error = TryFromIntError; fn try_from(value: SRational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as u16) // TODO } } impl TryFrom for u32 { type Error = TryFromIntError; fn try_from(value: SRational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as u32) // TODO } } impl TryFrom for u64 { type Error = TryFromIntError; fn try_from(value: SRational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as u64) // TODO } } impl TryFrom for i8 { type Error = TryFromIntError; fn try_from(value: SRational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as i8) // TODO } } impl TryFrom for i16 { type Error = TryFromIntError; fn try_from(value: SRational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as i16) // TODO } } impl TryFrom for i32 { type Error = TryFromIntError; fn try_from(value: SRational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as i32) // TODO } } impl TryFrom for i64 { type Error = TryFromIntError; fn try_from(value: SRational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as i64) // TODO } } impl TryFrom for f32 { type Error = TryFromIntError; fn try_from(value: SRational) -> std::result::Result { Ok(((value.n as f32) / (value.d as f32)) as f32) // TODO } } impl From for Rational { fn from(value: u16) -> Self { Self::new(value as u32, 1) } } impl From for Rational { fn from(value: u8) -> Self { Self::new(value as u32, 1) } } impl From for Rational { fn from(value: u32) -> Self { Self::new(value, 1) } } impl From for Rational { fn from(value: f32) -> Self { if value.is_sign_negative() { panic!("Can not convert {} to Rational type", value); } let ratio = num::rational::Ratio::from_float(value).expect("Failed to convert float"); // TODO: This is a workaround, need to implement better routine Self::new(ratio.numer().try_into().unwrap(), ratio.denom().try_into().unwrap()) } } impl Rational { pub fn new(n: u32, d: u32) -> Self { Self { n, d } } pub fn new_f32(n: f32, d: u32) -> Self { Self::new((n * d as f32) as u32, d) } pub fn new_f64(n: f64, d: u32) -> Self { Self::new((n * d as f64) as u32, d) } pub fn as_f32(&self) -> f32 { self.n as f32 / self.d as f32 } } impl Serialize for Rational { fn serialize(&self, serializer: S) -> std::result::Result where S: Serializer, { let s = format!("{}/{}", self.n, self.d); serializer.serialize_str(&s) } } impl<'de> Deserialize<'de> for Rational { fn deserialize(deserializer: D) -> std::result::Result where D: Deserializer<'de>, { use serde::de::Error; let s = String::deserialize(deserializer)?; let values: Vec<&str> = s.split('/').collect(); if values.len() != 2 { Err(D::Error::custom(format!("Invalid rational value: {}", s))) } else { Ok(Rational::new( values[0].parse::().map_err(D::Error::custom)?, values[1].parse::().map_err(D::Error::custom)?, )) } } } /// Type to represent tiff values of type `SRATIONAL` #[derive(Clone, Debug, Default, Copy)] pub struct SRational { pub n: i32, pub d: i32, } impl SRational { pub fn new(n: i32, d: i32) -> Self { Self { n, d } } } impl PartialEq for SRational { fn eq(&self, other: &Self) -> bool { let n1: i64 = self.n as i64 * other.d as i64; let n2: i64 = self.d as i64 * other.n as i64; n1.eq(&n2) } } impl Eq for SRational {} #[allow(clippy::non_canonical_partial_ord_impl)] impl PartialOrd for SRational { fn partial_cmp(&self, other: &Self) -> Option { let n1: i64 = self.n as i64 * other.d as i64; let n2: i64 = self.d as i64 * other.n as i64; n1.partial_cmp(&n2) } } impl Ord for SRational { fn cmp(&self, other: &Self) -> std::cmp::Ordering { let n1: i64 = self.n as i64 * other.d as i64; let n2: i64 = self.d as i64 * other.n as i64; n1.cmp(&n2) } } impl Serialize for SRational { fn serialize(&self, serializer: S) -> std::result::Result where S: Serializer, { let s = format!("{}/{}", self.n, self.d); serializer.serialize_str(&s) } } impl<'de> Deserialize<'de> for SRational { fn deserialize(deserializer: D) -> std::result::Result where D: Deserializer<'de>, { use serde::de::Error; let s = String::deserialize(deserializer)?; let values: Vec<&str> = s.split('/').collect(); if values.len() != 2 { Err(D::Error::custom(format!("Invalid srational value: {}", s))) } else { Ok(SRational::new( values[0].parse::().map_err(D::Error::custom)?, values[1].parse::().map_err(D::Error::custom)?, )) } } } pub struct ValueConvertError(pub(crate) ()); impl From for ValueConvertError { fn from(_: TryFromIntError) -> Self { todo!() } } impl From for ValueConvertError { fn from(_: Infallible) -> Self { todo!() } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum Value { /// 8-bit unsigned integer Byte(Vec), /// 8-bit byte that contains a 7-bit ASCII code; the last byte must be zero Ascii(TiffAscii), /// 16-bit unsigned integer Short(Vec), /// 32-bit unsigned integer Long(Vec), /// Fraction stored as two 32-bit unsigned integers Rational(Vec), /// 8-bit signed integer SByte(Vec), /// 8-bit byte that may contain anything, depending on the field Undefined(Vec), /// 16-bit signed integer SShort(Vec), /// 32-bit signed integer SLong(Vec), /// Fraction stored as two 32-bit signed integers SRational(Vec), /// 32-bit IEEE floating point Float(Vec), /// 64-bit IEEE floating point Double(Vec), /// Unknown type, wrapped in u8 Unknown(u16, Vec), } impl Value { pub fn long(v: u32) -> Self { Self::from(v) } pub fn short(v: u16) -> Self { Self::from(v) } pub fn as_string(&self) -> Option<&String> { match self { Self::Ascii(v) => Some(&v.strings()[0]), _ => None, } } pub fn get_string(&self) -> Result<&String> { match self { Self::Ascii(v) => Ok(&v.strings()[0]), _ => todo!(), } } pub fn get_data(&self) -> &Vec { match self { Value::Ascii(data) => data.as_bytes(), Value::Byte(data) => data, Value::Undefined(data) => data, Value::Unknown(_, data) => data, _ => { panic!("Unable to call get_data() on this value type"); } } } pub fn force_usize(&self, idx: usize) -> usize { match self.get_usize(idx) { Ok(Some(v)) => v, Ok(None) => { log::error!("TIFF value index out of range, index is {} but length is {}", idx, self.count()); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } Err(_) => { log::error!("TIFF value cast error, but forced to default value!"); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } } } pub fn force_u8(&self, idx: usize) -> u8 { match self.get_u8(idx) { Ok(Some(v)) => v, Ok(None) => { log::error!("TIFF value index out of range, index is {} but length is {}", idx, self.count()); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } Err(_) => { log::error!("TIFF value cast error, but forced to default value!"); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } } } pub fn force_u16(&self, idx: usize) -> u16 { match self.get_u16(idx) { Ok(Some(v)) => v, Ok(None) => { log::error!("TIFF value index out of range, index is {} but length is {}", idx, self.count()); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } Err(_) => { log::error!("TIFF value cast error, but forced to default value!"); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } } } pub fn force_u32(&self, idx: usize) -> u32 { match self.get_u32(idx) { Ok(Some(v)) => v, Ok(None) => { log::error!("TIFF value index out of range, index is {} but length is {}", idx, self.count()); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } Err(_) => { log::error!("TIFF value cast error, but forced to default value!"); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } } } pub fn force_u64(&self, idx: usize) -> u64 { match self.get_u64(idx) { Ok(Some(v)) => v, Ok(None) => { log::error!("TIFF value index out of range, index is {} but length is {}", idx, self.count()); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } Err(_) => { log::error!("TIFF value cast error, but forced to default value!"); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } } } pub fn force_i8(&self, idx: usize) -> i8 { match self.get_i8(idx) { Ok(Some(v)) => v, Ok(None) => { log::error!("TIFF value index out of range, index is {} but length is {}", idx, self.count()); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } Err(_) => { log::error!("TIFF value cast error, but forced to default value!"); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } } } pub fn force_i16(&self, idx: usize) -> i16 { match self.get_i16(idx) { Ok(Some(v)) => v, Ok(None) => { log::error!("TIFF value index out of range, index is {} but length is {}", idx, self.count()); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } Err(_) => { log::error!("TIFF value cast error, but forced to default value!"); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } } } pub fn force_i32(&self, idx: usize) -> i32 { match self.get_i32(idx) { Ok(Some(v)) => v, Ok(None) => { log::error!("TIFF value index out of range, index is {} but length is {}", idx, self.count()); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } Err(_) => { log::error!("TIFF value cast error, but forced to default value!"); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } } } pub fn force_i64(&self, idx: usize) -> i64 { match self.get_i64(idx) { Ok(Some(v)) => v, Ok(None) => { log::error!("TIFF value index out of range, index is {} but length is {}", idx, self.count()); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } Err(_) => { log::error!("TIFF value cast error, but forced to default value!"); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } } } pub fn force_f32(&self, idx: usize) -> f32 { match self.get_f32(idx) { Ok(Some(v)) => v, Ok(None) => { log::error!("TIFF value index out of range, index is {} but length is {}", idx, self.count()); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } Err(_) => { log::error!("TIFF value cast error, but forced to default value!"); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Default::default() } } } pub fn get_usize(&self, idx: usize) -> std::result::Result, ValueConvertError> { Ok(match self { Value::Byte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Short(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Long(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SByte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SShort(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SLong(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Rational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SRational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Float(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as usize), Value::Double(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as usize), Value::Ascii(_) => return Err(ValueConvertError(())), Value::Undefined(_) => return Err(ValueConvertError(())), Value::Unknown(_, _) => return Err(ValueConvertError(())), }) } pub fn get_u8(&self, idx: usize) -> std::result::Result, ValueConvertError> { Ok(match self { Value::Byte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Short(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Long(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SByte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SShort(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SLong(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Rational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SRational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Float(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as u8), Value::Double(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as u8), Value::Ascii(_) => return Err(ValueConvertError(())), Value::Undefined(_) => return Err(ValueConvertError(())), Value::Unknown(_, _) => return Err(ValueConvertError(())), }) } pub fn get_u16(&self, idx: usize) -> std::result::Result, ValueConvertError> { Ok(match self { Value::Byte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Short(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Long(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SByte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SShort(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SLong(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Rational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SRational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Float(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as u16), Value::Double(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as u16), Value::Ascii(_) => return Err(ValueConvertError(())), Value::Undefined(_) => return Err(ValueConvertError(())), Value::Unknown(_, _) => return Err(ValueConvertError(())), }) } pub fn get_u32(&self, idx: usize) -> std::result::Result, ValueConvertError> { Ok(match self { Value::Byte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Short(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Long(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SByte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SShort(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SLong(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Rational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SRational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Float(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as u32), Value::Double(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as u32), Value::Ascii(_) => return Err(ValueConvertError(())), Value::Undefined(_) => return Err(ValueConvertError(())), Value::Unknown(_, _) => return Err(ValueConvertError(())), }) } pub fn get_u64(&self, idx: usize) -> std::result::Result, ValueConvertError> { Ok(match self { Value::Byte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Short(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Long(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SByte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SShort(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SLong(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Rational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SRational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Float(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as u64), Value::Double(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as u64), Value::Ascii(_) => return Err(ValueConvertError(())), Value::Undefined(_) => return Err(ValueConvertError(())), Value::Unknown(_, _) => return Err(ValueConvertError(())), }) } pub fn get_i8(&self, idx: usize) -> std::result::Result, ValueConvertError> { Ok(match self { Value::Byte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Short(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Long(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SByte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SShort(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SLong(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Rational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SRational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Float(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as i8), Value::Double(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as i8), Value::Ascii(_) => return Err(ValueConvertError(())), Value::Undefined(_) => return Err(ValueConvertError(())), Value::Unknown(_, _) => return Err(ValueConvertError(())), }) } pub fn get_i16(&self, idx: usize) -> std::result::Result, ValueConvertError> { Ok(match self { Value::Byte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Short(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Long(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SByte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SShort(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SLong(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Rational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SRational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Float(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as i16), Value::Double(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as i16), Value::Ascii(_) => return Err(ValueConvertError(())), Value::Undefined(_) => return Err(ValueConvertError(())), Value::Unknown(_, _) => return Err(ValueConvertError(())), }) } pub fn get_i32(&self, idx: usize) -> std::result::Result, ValueConvertError> { Ok(match self { Value::Byte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Short(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Long(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SByte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SShort(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SLong(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Rational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SRational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Float(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as i32), Value::Double(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as i32), Value::Ascii(_) => return Err(ValueConvertError(())), Value::Undefined(_) => return Err(ValueConvertError(())), Value::Unknown(_, _) => return Err(ValueConvertError(())), }) } pub fn get_i64(&self, idx: usize) -> std::result::Result, ValueConvertError> { Ok(match self { Value::Byte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Short(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Long(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SByte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SShort(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SLong(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Rational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SRational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Float(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as i64), Value::Double(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as i64), Value::Ascii(_) => return Err(ValueConvertError(())), Value::Undefined(_) => return Err(ValueConvertError(())), Value::Unknown(_, _) => return Err(ValueConvertError(())), }) } pub fn get_f32(&self, idx: usize) -> std::result::Result, ValueConvertError> { Ok(match self { Value::Byte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Short(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Long(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as f32), Value::SByte(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SShort(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SLong(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as f32), Value::Rational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::SRational(v) => v.get(idx).map(ToOwned::to_owned).map(TryInto::try_into).transpose()?, Value::Float(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as f32), Value::Double(v) => v.get(idx).map(ToOwned::to_owned).map(|x| x as f32), Value::Ascii(_) => return Err(ValueConvertError(())), Value::Undefined(_) => return Err(ValueConvertError(())), Value::Unknown(_, _) => return Err(ValueConvertError(())), }) } pub fn visual_rep(&self, limit: usize) -> String { match self { Value::Byte(v) => v.iter().take(limit).map(|a| format!("{:X}", a)).collect::>().join(" "), Value::Short(v) => v.iter().take(limit).map(|a| format!("{}", a)).collect::>().join(" "), Value::Long(v) => v.iter().take(limit).map(|a| format!("{}", a)).collect::>().join(" "), Value::Rational(v) => v.iter().take(limit).map(|a| format!("{}", a)).collect::>().join(" "), Value::SByte(v) => v.iter().take(limit).map(|a| format!("{}", a)).collect::>().join(" "), Value::SShort(v) => v.iter().take(limit).map(|a| format!("{}", a)).collect::>().join(" "), Value::SLong(v) => v.iter().take(limit).map(|a| format!("{}", a)).collect::>().join(" "), Value::SRational(v) => v.iter().take(limit).map(|a| format!("{}", a)).collect::>().join(" "), Value::Float(v) => v.iter().take(limit).map(|a| format!("{}", a)).collect::>().join(" "), Value::Double(v) => v.iter().take(limit).map(|a| format!("{}", a)).collect::>().join(" "), Value::Undefined(v) => v.iter().take(limit).map(|a| format!("{:X}", a)).collect::>().join(" "), Value::Unknown(_t, v) => v.iter().take(limit).map(|a| format!("{:X}", a)).collect::>().join(" "), Value::Ascii(v) => v.first().clone(), } } pub fn count(&self) -> usize { match self { Self::Byte(v) => v.len(), Self::Ascii(v) => v.count(), Self::Short(v) => v.len(), Self::Long(v) => v.len(), Self::Rational(v) => v.len(), Self::SByte(v) => v.len(), Self::Undefined(v) => v.len(), Self::SShort(v) => v.len(), Self::SLong(v) => v.len(), Self::SRational(v) => v.len(), Self::Float(v) => v.len(), Self::Double(v) => v.len(), Self::Unknown(_, v) => v.len(), } } pub fn byte_size(&self) -> usize { match self { Self::Byte(v) => v.len() * std::mem::size_of::(), Self::Ascii(v) => v.count(), Self::Short(v) => v.len() * std::mem::size_of::(), Self::Long(v) => v.len() * std::mem::size_of::(), Self::Rational(v) => v.len() * 8, Self::SByte(v) => v.len() * std::mem::size_of::(), Self::Undefined(v) => v.len() * std::mem::size_of::(), Self::SShort(v) => v.len() * std::mem::size_of::(), Self::SLong(v) => v.len() * std::mem::size_of::(), Self::SRational(v) => v.len() * 8, Self::Float(v) => v.len() * std::mem::size_of::(), Self::Double(v) => v.len() * std::mem::size_of::(), Self::Unknown(_, v) => v.len() * std::mem::size_of::(), } } pub fn as_embedded(&self) -> Result { if self.count() == 0 { panic!("Embedded TIFF value data must not be empty"); //return Err(TiffError::General("Embedded data is empty".into())); } if self.byte_size() > 4 { Err(TiffError::Overflow("Invalid data".to_string())) } else { match self { Self::Byte(v) => Ok( (*v.get(0).unwrap_or(&0) as u32) | ((*v.get(1).unwrap_or(&0) as u32) << 8) | ((*v.get(2).unwrap_or(&0) as u32) << 16) | ((*v.get(3).unwrap_or(&0) as u32) << 24), ), Self::Ascii(v) => { //let cstr = CString::new(v.as_str()).unwrap(); let v = v.as_vec_with_nul(); Ok( (*v.get(0).unwrap_or(&0) as u32) | ((*v.get(1).unwrap_or(&0) as u32) << 8) | ((*v.get(2).unwrap_or(&0) as u32) << 16) | ((*v.get(3).unwrap_or(&0) as u32) << 24), ) } Self::Short(v) => Ok((v[0] as u32) | ((*v.get(1).unwrap_or(&0) as u32) << 16)), Self::Long(v) => Ok(v[0]), Self::SByte(v) => Ok( (*v.get(0).unwrap_or(&0) as u32) | ((*v.get(1).unwrap_or(&0) as u32) << 8) | ((*v.get(2).unwrap_or(&0) as u32) << 16) | ((*v.get(3).unwrap_or(&0) as u32) << 24), ), Self::Undefined(v) => Ok( (*v.get(0).unwrap_or(&0) as u32) | ((*v.get(1).unwrap_or(&0) as u32) << 8) | ((*v.get(2).unwrap_or(&0) as u32) << 16) | ((*v.get(3).unwrap_or(&0) as u32) << 24), ), Self::SShort(v) => Ok((v[0] as u32) | ((*v.get(1).unwrap_or(&0) as u32) << 16)), Self::SLong(v) => Ok(v[0] as u32), Self::Float(v) => Ok(v[0] as u32), Self::Unknown(_, v) => Ok( (*v.get(0).unwrap_or(&0) as u32) | ((*v.get(1).unwrap_or(&0) as u32) << 8) | ((*v.get(2).unwrap_or(&0) as u32) << 16) | ((*v.get(3).unwrap_or(&0) as u32) << 24), ), _ => { panic!("unsupported: {:?}", self); } } } } pub fn write(&self, w: &mut dyn Write) -> Result<()> { match self { Self::Byte(val) => { w.write_all(val)?; } Self::Ascii(val) => { //let cstr = CString::new(val.as_str()).unwrap(); let bytes = val.as_vec_with_nul(); w.write_all(&bytes)?; } Self::Short(val) => { for x in val { w.write_u16::(*x)?; } } Self::Long(val) => { for x in val { w.write_u32::(*x)?; } } Self::Rational(val) => { for x in val { w.write_u32::(x.n)?; w.write_u32::(x.d)?; } } Self::SByte(val) => { for x in val { w.write_i8(*x)?; } } Self::Undefined(val) => { w.write_all(val)?; } Self::SShort(val) => { for x in val { w.write_i16::(*x)?; } } Self::SLong(val) => { for x in val { w.write_i32::(*x)?; } } Self::SRational(val) => { for x in val { w.write_i32::(x.n)?; w.write_i32::(x.d)?; } } Self::Float(val) => { for x in val { w.write_f32::(*x)?; } } Self::Double(val) => { for x in val { w.write_f64::(*x)?; } } Self::Unknown(_, val) => { w.write_all(val)?; } } Ok(()) } pub fn value_type(&self) -> u16 { match self { Self::Byte(_) => 1, Self::Ascii(_) => 2, Self::Short(_) => 3, Self::Long(_) => 4, Self::Rational(_) => 5, Self::SByte(_) => 6, Self::Undefined(_) => 7, Self::SShort(_) => 8, Self::SLong(_) => 9, Self::SRational(_) => 10, Self::Float(_) => 11, Self::Double(_) => 12, Self::Unknown(t, _) => *t, } } pub fn value_type_name(&self) -> String { match self { Self::Byte(_) => "BYTE".into(), Self::Ascii(_) => "ASCII".into(), Self::Short(_) => "SHORT".into(), Self::Long(_) => "LONG".into(), Self::Rational(_) => "RATIONAL".into(), Self::SByte(_) => "SBYTE".into(), Self::Undefined(_) => "UNDEF".into(), Self::SShort(_) => "SSHORT".into(), Self::SLong(_) => "SLONG".into(), Self::SRational(_) => "SRATIONAL".into(), Self::Float(_) => "FLOAT".into(), Self::Double(_) => "DOUBLE".into(), Self::Unknown(t, _) => { format!("UNKNOWN ({})", t) } } } } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct TiffAscii { strings: Vec, plain: Vec, } impl TiffAscii { pub fn new>(value: T) -> Self { Self { strings: vec![String::from(value.as_ref())], plain: Default::default(), } } pub fn new_from_vec(values: Vec) -> Self { Self { strings: values, plain: Default::default(), } } pub fn strings(&self) -> &Vec { &self.strings } pub fn as_bytes(&self) -> &Vec { &self.plain } pub fn first(&self) -> &String { &self.strings[0] } pub fn count(&self) -> usize { self.strings.iter().map(|s| s.len() + 1).sum::() } pub fn as_vec_with_nul(&self) -> Vec { let mut out = Vec::new(); for s in &self.strings { let cstr = CString::new(s.as_bytes()).unwrap(); out.extend_from_slice(cstr.to_bytes_with_nul()); } out } pub fn new_from_raw(raw: &[u8]) -> Self { let mut strings = Vec::new(); let mut nul_range_end = 0; // TODO: fixme multiple strings //while nul_range_end < raw.len() { nul_range_end = raw[nul_range_end..].iter().position(|&c| c == b'\0').unwrap_or(raw.len()); // default to length if no `\0` present let s = ::std::str::from_utf8(&raw[0..nul_range_end]).unwrap_or("!!!INVALID UTF8!!!"); strings.push(String::from(s)); //nul_range_end += 1; // } Self { strings, plain: Vec::from(raw), } } } pub trait IntoTiffValue { fn count(&self) -> usize; fn size(&self) -> usize; fn bytes(&self) -> usize { self.count() * self.size() } } impl From for Value { fn from(value: Rational) -> Self { Value::Rational(vec![value]) } } impl From<&[Rational]> for Value { fn from(value: &[Rational]) -> Self { Value::Rational(value.into()) } } impl From<[Rational; N]> for Value { fn from(value: [Rational; N]) -> Self { Value::Rational(value.into()) } } impl From for Value { fn from(value: SRational) -> Self { Value::SRational(vec![value]) } } impl From<&[SRational]> for Value { fn from(value: &[SRational]) -> Self { Value::SRational(value.into()) } } impl From<[SRational; N]> for Value { fn from(value: [SRational; N]) -> Self { Value::SRational(value.into()) } } impl From<&str> for Value { fn from(value: &str) -> Self { Value::Ascii(TiffAscii::new(value)) } } impl From<&String> for Value { fn from(value: &String) -> Self { Value::Ascii(TiffAscii::new(value)) } } impl From for Value { fn from(value: String) -> Self { Value::Ascii(TiffAscii::new(value)) } } impl From for Value { fn from(value: f32) -> Self { Value::Float(vec![value]) } } impl From<&[f32]> for Value { fn from(value: &[f32]) -> Self { Value::Float(value.into()) } } impl From<[f32; N]> for Value { fn from(value: [f32; N]) -> Self { Value::Float(value.into()) } } impl From for Value { fn from(value: f64) -> Self { Value::Double(vec![value]) } } impl From<&[f64]> for Value { fn from(value: &[f64]) -> Self { Value::Double(value.into()) } } impl From<[f64; N]> for Value { fn from(value: [f64; N]) -> Self { Value::Double(value.into()) } } impl From for Value { fn from(value: u8) -> Self { Value::Byte(vec![value]) } } impl From<&[u8]> for Value { fn from(value: &[u8]) -> Self { Value::Byte(value.into()) } } impl From<[u8; N]> for Value { fn from(value: [u8; N]) -> Self { Value::Byte(value.into()) } } impl From for Value { fn from(value: u16) -> Self { Value::Short(vec![value]) } } impl From<&[u16]> for Value { fn from(value: &[u16]) -> Self { Value::Short(value.into()) } } impl From<&Vec> for Value { fn from(value: &Vec) -> Self { Value::Short(value.clone()) } } impl From<[u16; N]> for Value { fn from(value: [u16; N]) -> Self { Value::Short(value.into()) } } impl From for Value { fn from(value: u32) -> Self { Value::Long(vec![value]) } } impl From<&[u32]> for Value { fn from(value: &[u32]) -> Self { Value::Long(value.into()) } } impl From> for Value { fn from(value: Vec) -> Self { Value::SShort(value) } } impl From<&Vec> for Value { fn from(value: &Vec) -> Self { Value::SShort(value.clone()) } } impl From<&Vec> for Value { fn from(value: &Vec) -> Self { Value::Long(value.clone()) } } impl From<[u32; N]> for Value { fn from(value: [u32; N]) -> Self { Value::Long(value.into()) } } impl From for Value { fn from(value: i8) -> Self { Value::SByte(vec![value]) } } impl From<&[i8]> for Value { fn from(value: &[i8]) -> Self { Value::SByte(value.into()) } } impl From<[i8; N]> for Value { fn from(value: [i8; N]) -> Self { Value::SByte(value.into()) } } impl From for Value { fn from(value: i16) -> Self { Value::SShort(vec![value]) } } impl From<&[i16]> for Value { fn from(value: &[i16]) -> Self { Value::SShort(value.into()) } } impl From<[i16; N]> for Value { fn from(value: [i16; N]) -> Self { Value::SShort(value.into()) } } impl From for Value { fn from(value: i32) -> Self { Value::SLong(vec![value]) } } impl From<&[i32]> for Value { fn from(value: &[i32]) -> Self { Value::SLong(value.into()) } } impl From<[i32; N]> for Value { fn from(value: [i32; N]) -> Self { Value::SLong(value.into()) } } #[cfg(test)] mod tests { use super::*; #[test] fn rational_type_equal() { let a = Rational::new(257, 10); let b = Rational::new(257, 10); assert_eq!(a, b); let a = Rational::new(257, 5); let b = Rational::new(2570, 50); assert_eq!(a, b); } #[test] fn rational_type_nequal() { let a = Rational::new(257, 10); let b = Rational::new(2570, 10); assert_ne!(a, b); } #[test] fn rational_type_greater() { let a = Rational::new(200, 1); let b = Rational::new(300, 10); assert!(a > b); } #[test] fn rational_type_lesser() { let a = Rational::new(200, 1); let b = Rational::new(300, 10); assert!(b < a); } #[test] fn srational_type_equal() { let a = SRational::new(-257, 10); let b = SRational::new(-257, 10); assert_eq!(a, b); let a = SRational::new(-257, 10); let b = SRational::new(-2570, 100); assert_eq!(a, b); } #[test] fn srational_type_nequal() { let a = SRational::new(-257, 10); let b = SRational::new(-2570, 10); assert_ne!(a, b); } #[test] fn srational_type_greater() { let a = SRational::new(-200, 1); let b = SRational::new(-300, 10); assert!(a < b); } #[test] fn srational_type_lesser() { let a = SRational::new(-200, 1); let b = SRational::new(-300, 10); assert!(a < b); } } rawler-0.7.1/src/formats/tiff/writer.rs000064400000000000000000000346411046102023000162110ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use std::{ collections::BTreeMap, io::{Seek, SeekFrom, Write}, }; use byteorder::{LittleEndian, NativeEndian, WriteBytesExt}; use image::EncodableLayout; use rayon::prelude::*; use weezl::LzwError; use crate::{ exif::Exif, imgop::Dim2, tags::{ExifGpsTag, ExifTag, TiffTag}, }; use super::{Entry, Result, TIFF_MAGIC, TiffError, Value}; pub struct TiffWriter { ifd_location: u64, pub writer: W, } impl TiffWriter where W: Write + Seek, { pub fn new(writer: W) -> Result { let mut tmp = Self { writer, ifd_location: 0 }; tmp.write_header()?; Ok(tmp) } pub fn new_directory(&self) -> DirectoryWriter { DirectoryWriter::new() } fn write_header(&mut self) -> Result<()> { #[cfg(target_endian = "little")] let boi: u8 = 0x49; #[cfg(not(target_endian = "little"))] let boi: u8 = 0x4d; self.writer.write_all(&[boi, boi])?; self.writer.write_u16::(TIFF_MAGIC)?; self.ifd_location = self.writer.stream_position()?; self.writer.write_u32::(0_u32)?; Ok(()) } pub fn write_strips_lzw(&mut self, data: &[u16], cpp: usize, dim: Dim2, mut strip_lines: usize) -> Result<(u32, Vec<(u32, u32)>)> { if strip_lines == 0 { if dim.h > 256 { strip_lines = 256; } else { strip_lines = dim.h; // Use single strip } } let mut tag_data = Vec::with_capacity(dim.h / strip_lines + 1); let strips = data .par_chunks(cpp * dim.w * strip_lines) .map(|strip| { let mut encoder = weezl::encode::Encoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8); encoder.encode(strip.as_bytes()) }) .collect::>, LzwError>>() .map_err(|err| TiffError::General(err.to_string()))?; for strip in strips { let offset = self.write_data(&strip)?; let bytes = strip.len() as u32; tag_data.push((offset, bytes)); } Ok((strip_lines as u32, tag_data)) } pub fn write_data(&mut self, data: &[u8]) -> Result where W: Seek + Write, { self.pad_word_boundary()?; let offset = self.position()?; self.writer.write_all(data)?; Ok(offset) } pub fn write_data_u16_le(&mut self, data: &[u16]) -> Result where W: Seek + Write, { self.pad_word_boundary()?; let offset = self.position()?; for v in data { self.writer.write_u16::(*v)?; } Ok(offset) } pub fn write_data_f32_le(&mut self, data: &[f32]) -> Result where W: Seek + Write, { self.pad_word_boundary()?; let offset = self.position()?; for v in data { self.writer.write_f32::(*v)?; } Ok(offset) } pub(crate) fn pad_word_boundary(&mut self) -> Result<()> { if self.position()? % 4 != 0 { let padding = [0, 0, 0]; let padd_len = 4 - (self.position()? % 4); self.writer.write_all(&padding[..padd_len as usize])?; } Ok(()) } pub fn build(mut self, root_ifd: DirectoryWriter) -> Result<()> { let ifd0_offset = root_ifd.build(&mut self)?; self.writer.seek(SeekFrom::Start(self.ifd_location))?; self.writer.write_u32::(ifd0_offset)?; Ok(()) } } impl TiffWriter where W: Seek, { pub fn position(&mut self) -> Result { Ok(self.writer.stream_position().map(|v| v as u32)?) // TODO: try_from? } } #[derive(Default)] pub struct DirectoryWriter { // We use BTreeMap to make sure tags are written in correct order entries: BTreeMap, next_ifd: u32, } impl DirectoryWriter { pub fn remove_tag(&mut self, tag: T) { let tag: u16 = tag.into(); self.entries.remove(&tag); } pub fn add_tag>(&mut self, tag: T, value: V) { let tag: u16 = tag.into(); self.entries.insert( tag, Entry { tag, value: value.into(), embedded: None, }, ); } pub fn add_untyped_tag>(&mut self, tag: u16, value: V) { self.entries.insert( tag, Entry { tag, value: value.into(), embedded: None, }, ); } pub fn contains(&self, tag: T) -> bool { self.entries.contains_key(&tag.into()) } pub fn copy<'a>(&mut self, iter: impl Iterator) { for entry in iter { if !self.entries.contains_key(entry.0) { self.add_untyped_tag(*entry.0, entry.1.clone()); } } } pub fn copy_with_override<'a>(&mut self, iter: impl Iterator) { for entry in iter { self.add_untyped_tag(*entry.0, entry.1.clone()); } } pub fn add_tag_undefined(&mut self, tag: T, data: Vec) { let tag: u16 = tag.into(); //let data = data.as_ref(); //let offset = self.write_data(data)?; self.entries.insert( tag, Entry { tag, value: Value::Undefined(data), embedded: None, }, ); } pub fn add_value(&mut self, tag: T, value: Value) { let tag: u16 = tag.into(); self.entries.insert(tag, Entry { tag, value, embedded: None }); } pub fn entry_count(&self) -> u16 { self.entries.len() as u16 } pub fn new() -> Self { Self { entries: BTreeMap::new(), next_ifd: 0, } } pub fn is_empty(&self) -> bool { self.entries.is_empty() } pub fn build(mut self, tiff: &mut TiffWriter) -> Result where W: Seek + Write, { if self.entries.is_empty() { return Err(TiffError::General("IFD is empty, not allowed by TIFF specification".to_string())); } for &mut Entry { ref mut value, ref mut embedded, ref tag, } in self.entries.values_mut() { let data_bytes = 4; if value.byte_size() > data_bytes { tiff.pad_word_boundary()?; let offset = tiff.position()?; value.write(&mut tiff.writer)?; embedded.replace(offset as u32); } else { if value.count() == 0 { panic!("TIFF value is empty, tag: {:?}", tag); } embedded.replace(value.as_embedded()?); } } tiff.pad_word_boundary()?; let offset = tiff.position()?; tiff.writer.write_all(&self.entry_count().to_ne_bytes())?; for (tag, entry) in self.entries { tiff.writer.write_u16::(tag)?; tiff.writer.write_u16::(entry.value_type())?; tiff.writer.write_u32::(entry.count())?; tiff .writer .write_u32::(entry.embedded.expect("embedded attribute must contain a value"))?; } tiff.writer.write_u32::(self.next_ifd)?; // Next IFD Ok(offset) } /* pub fn add_entry(&mut self, entry: Entry) { self.ifd.insert(tag.into(), entry); } */ } impl crate::decoders::RawMetadata { pub fn write_exif_tags(&self, tiff: &mut TiffWriter, root_ifd: &mut DirectoryWriter, exif_ifd: &mut DirectoryWriter) -> crate::formats::tiff::Result<()> where W: Write + Seek, { self.fill_exif_root(tiff, root_ifd)?; Self::fill_exif_ifd(&self.exif, exif_ifd)?; Ok(()) } pub fn fill_exif_ifd(exif: &Exif, exif_ifd: &mut DirectoryWriter) -> Result<()> { transfer_entry(exif_ifd, ExifTag::FNumber, &exif.fnumber)?; transfer_entry(exif_ifd, ExifTag::ApertureValue, &exif.aperture_value)?; transfer_entry(exif_ifd, ExifTag::BrightnessValue, &exif.brightness_value)?; transfer_entry(exif_ifd, ExifTag::ExposureBiasValue, &exif.exposure_bias)?; transfer_entry(exif_ifd, ExifTag::RecommendedExposureIndex, &exif.recommended_exposure_index)?; transfer_entry(exif_ifd, ExifTag::ExposureTime, &exif.exposure_time)?; transfer_entry(exif_ifd, ExifTag::ISOSpeedRatings, &exif.iso_speed_ratings)?; transfer_entry(exif_ifd, ExifTag::ISOSpeed, &exif.iso_speed)?; transfer_entry(exif_ifd, ExifTag::SensitivityType, &exif.sensitivity_type)?; transfer_entry(exif_ifd, ExifTag::ExposureProgram, &exif.exposure_program)?; transfer_entry(exif_ifd, ExifTag::TimeZoneOffset, &exif.timezone_offset)?; transfer_entry(exif_ifd, ExifTag::DateTimeOriginal, &exif.date_time_original)?; transfer_entry(exif_ifd, ExifTag::CreateDate, &exif.create_date)?; transfer_entry(exif_ifd, ExifTag::OffsetTime, &exif.offset_time)?; transfer_entry(exif_ifd, ExifTag::OffsetTimeOriginal, &exif.offset_time_original)?; transfer_entry(exif_ifd, ExifTag::OffsetTimeDigitized, &exif.offset_time_digitized)?; transfer_entry(exif_ifd, ExifTag::SubSecTime, &exif.sub_sec_time)?; transfer_entry(exif_ifd, ExifTag::SubSecTimeOriginal, &exif.sub_sec_time_original)?; transfer_entry(exif_ifd, ExifTag::SubSecTimeDigitized, &exif.sub_sec_time_digitized)?; transfer_entry(exif_ifd, ExifTag::ShutterSpeedValue, &exif.shutter_speed_value)?; transfer_entry(exif_ifd, ExifTag::MaxApertureValue, &exif.max_aperture_value)?; transfer_entry(exif_ifd, ExifTag::SubjectDistance, &exif.subject_distance)?; transfer_entry(exif_ifd, ExifTag::MeteringMode, &exif.metering_mode)?; transfer_entry(exif_ifd, ExifTag::LightSource, &exif.light_source)?; transfer_entry(exif_ifd, ExifTag::Flash, &exif.flash)?; transfer_entry(exif_ifd, ExifTag::FocalLength, &exif.focal_length)?; transfer_entry(exif_ifd, ExifTag::ImageNumber, &exif.image_number)?; transfer_entry(exif_ifd, ExifTag::ColorSpace, &exif.color_space)?; transfer_entry(exif_ifd, ExifTag::FlashEnergy, &exif.flash_energy)?; transfer_entry(exif_ifd, ExifTag::ExposureMode, &exif.exposure_mode)?; transfer_entry(exif_ifd, ExifTag::WhiteBalance, &exif.white_balance)?; transfer_entry(exif_ifd, ExifTag::SceneCaptureType, &exif.scene_capture_type)?; transfer_entry(exif_ifd, ExifTag::SubjectDistanceRange, &exif.subject_distance_range)?; transfer_entry(exif_ifd, ExifTag::OwnerName, &exif.owner_name)?; transfer_entry(exif_ifd, ExifTag::SerialNumber, &exif.serial_number)?; transfer_entry(exif_ifd, ExifTag::LensSerialNumber, &exif.lens_serial_number)?; transfer_entry(exif_ifd, ExifTag::LensSpecification, &exif.lens_spec)?; transfer_entry(exif_ifd, ExifTag::LensMake, &exif.lens_make)?; transfer_entry(exif_ifd, ExifTag::LensModel, &exif.lens_model)?; transfer_entry(exif_ifd, ExifTag::UserComment, &exif.user_comment)?; //transfer_entry(exif_ifd, ExifTag::MakerNotes, &exif.makernotes.as_ref().map(|x| Value::Undefined(x.clone())))?; Ok(()) } fn fill_exif_root(&self, tiff: &mut TiffWriter, root_ifd: &mut DirectoryWriter) -> Result<()> where W: Write + Seek, { transfer_entry(root_ifd, ExifTag::Orientation, &self.exif.orientation)?; transfer_entry(root_ifd, ExifTag::ModifyDate, &self.exif.modify_date)?; transfer_entry(root_ifd, ExifTag::Copyright, &self.exif.copyright)?; transfer_entry(root_ifd, ExifTag::Artist, &self.exif.artist)?; if let Some(gps) = &self.exif.gps { let gps_offset = { let mut gps_ifd = DirectoryWriter::new(); transfer_entry(&mut gps_ifd, ExifGpsTag::GPSVersionID, &gps.gps_version_id)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSLatitudeRef, &gps.gps_latitude_ref)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSLatitude, &gps.gps_latitude)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSLongitudeRef, &gps.gps_longitude_ref)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSLongitude, &gps.gps_longitude)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSAltitudeRef, &gps.gps_altitude_ref)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSAltitude, &gps.gps_altitude)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSTimeStamp, &gps.gps_timestamp)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSSatellites, &gps.gps_satellites)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSStatus, &gps.gps_status)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSMeasureMode, &gps.gps_measure_mode)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSDOP, &gps.gps_dop)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSSpeedRef, &gps.gps_speed_ref)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSSpeed, &gps.gps_speed)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSTrackRef, &gps.gps_track_ref)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSTrack, &gps.gps_track)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSImgDirectionRef, &gps.gps_img_direction_ref)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSImgDirection, &gps.gps_img_direction)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSMapDatum, &gps.gps_map_datum)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSDestLatitudeRef, &gps.gps_dest_latitude_ref)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSDestLatitude, &gps.gps_dest_latitude)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSDestLongitudeRef, &gps.gps_dest_longitude_ref)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSDestLongitude, &gps.gps_dest_longitude)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSDestBearingRef, &gps.gps_dest_bearing_ref)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSDestBearing, &gps.gps_dest_bearing)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSDestDistanceRef, &gps.gps_dest_distance_ref)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSDestDistance, &gps.gps_dest_distance)?; transfer_entry_undefined(&mut gps_ifd, ExifGpsTag::GPSProcessingMethod, &gps.gps_processing_method)?; transfer_entry_undefined(&mut gps_ifd, ExifGpsTag::GPSAreaInformation, &gps.gps_area_information)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSDateStamp, &gps.gps_date_stamp)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSDifferential, &gps.gps_differential)?; transfer_entry(&mut gps_ifd, ExifGpsTag::GPSHPositioningError, &gps.gps_h_positioning_error)?; if gps_ifd.entry_count() > 0 { Some(gps_ifd.build(tiff)?) } else { None } }; if let Some(gps_offset) = gps_offset { root_ifd.add_tag(ExifTag::GPSInfo, [gps_offset]); } } Ok(()) } } pub(crate) fn transfer_entry(ifd: &mut DirectoryWriter, tag: T, entry: &Option) -> Result<()> where T: TiffTag, V: Into + Clone, { if let Some(entry) = entry { ifd.add_tag(tag, entry.clone()); } Ok(()) } pub(crate) fn transfer_entry_undefined(ifd: &mut DirectoryWriter, tag: T, entry: &Option>) -> Result<()> where T: TiffTag, { if let Some(entry) = entry { ifd.add_tag_undefined(tag, entry.clone()); } Ok(()) } rawler-0.7.1/src/imgop/chromatic_adaption.rs000064400000000000000000000067501046102023000172350ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2025 Daniel Vogelbacher use crate::imgop::{ matrix::{multiply, multiply_row1}, xyz::*, }; #[allow(clippy::excessive_precision)] pub const BRADFORD_ADAPTION: [[f32; 3]; 3] = [ [0.8951000, 0.2664000, -0.1614000], [-0.7502000, 1.7135000, 0.0367000], [0.0389000, -0.0685000, 1.0296000], ]; #[allow(clippy::excessive_precision)] pub const BRADFORD_ADAPTION_INVERSE: [[f32; 3]; 3] = [ [0.9869929, -0.1470543, 0.1599627], [0.4323053, 0.5183603, 0.0492912], [-0.0085287, 0.0400428, 0.9684867], ]; fn whitepoint_to_lms(whitepoint: &[f32; 3], adaption: &[[f32; 3]; 3]) -> [f32; 3] { multiply_row1(adaption, whitepoint) } #[allow(non_snake_case)] fn illuminant_to_XYZ_tristimulus(illuminant: &Illuminant) -> [f32; 3] { match illuminant { Illuminant::Unknown => todo!(), Illuminant::Daylight => { // There is no official CIE XYZ tristimulus white point for "Daylight" illuminants. // We use D65 as an approximation CIE_1931_TRISTIMULUS_D65 } Illuminant::Fluorescent => todo!(), Illuminant::Tungsten => todo!(), Illuminant::Flash => { // There is no official CIE XYZ tristimulus white point for "Flash" illuminants. // We use D55 as an approximation assuming flash CCT ≈ 5500 K CIE_1931_TRISTIMULUS_D55 } Illuminant::FineWeather => todo!(), Illuminant::CloudyWeather => todo!(), Illuminant::Shade => todo!(), Illuminant::DaylightFluorescent => todo!(), Illuminant::DaylightWhiteFluorescent => todo!(), Illuminant::CoolWhiteFluorescent => todo!(), Illuminant::WhiteFluorescent => todo!(), Illuminant::A => CIE_1931_TRISTIMULUS_A, Illuminant::B => CIE_1931_TRISTIMULUS_B, Illuminant::C => CIE_1931_TRISTIMULUS_C, Illuminant::D55 => CIE_1931_TRISTIMULUS_D55, Illuminant::D65 => CIE_1931_TRISTIMULUS_D65, Illuminant::D75 => CIE_1931_TRISTIMULUS_D75, Illuminant::D50 => CIE_1931_TRISTIMULUS_D50, Illuminant::IsoStudioTungsten => todo!(), } } // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html pub fn bradford_adaption_matrix(src_illu: &Illuminant, dst_illu: &Illuminant) -> [[f32; 3]; 3] { let tristimulus_src = illuminant_to_XYZ_tristimulus(src_illu); let tristimulus_dst = illuminant_to_XYZ_tristimulus(dst_illu); let lms_src = whitepoint_to_lms(&tristimulus_src, &BRADFORD_ADAPTION); let lms_dst = whitepoint_to_lms(&tristimulus_dst, &BRADFORD_ADAPTION); let diag = [ [lms_dst[0] / lms_src[0], 0.0, 0.0], // [0.0, lms_dst[1] / lms_src[1], 0.0], // [0.0, 0.0, lms_dst[2] / lms_src[2]], // ]; multiply(&multiply(&BRADFORD_ADAPTION_INVERSE, &diag), &BRADFORD_ADAPTION) } pub fn adapt_bradford(src_illu: &Illuminant, dst_illu: &Illuminant, src_matrix: &[[f32; 3]; 3]) -> [[f32; 3]; 3] { let adaption = bradford_adaption_matrix(src_illu, dst_illu); multiply(src_matrix, &adaption) } #[cfg(test)] mod tests { use approx::assert_relative_eq; use crate::imgop::matrix::transform_2d; use super::*; #[test] fn adaption_test() -> std::result::Result<(), Box> { let m = bradford_adaption_matrix(&Illuminant::A, &Illuminant::B); eprintln!("Matrix: {:?}", m); let expected = [ [0.89051634_f32, -0.08291367, 0.2680946], [-0.09715235, 1.0754263, 0.08794621], [0.053896993, -0.0908558, 2.4838552], ]; assert_relative_eq!(transform_2d(&m).as_slice(), transform_2d(&expected).as_slice(), epsilon = f32::EPSILON); Ok(()) } } rawler-0.7.1/src/imgop/develop.rs000064400000000000000000000272731046102023000150460ustar 00000000000000use std::io; use image::{DynamicImage, ImageBuffer}; use crate::{ RawImage, decoders::RawMetadata, formats::tiff::{DirectoryWriter, TiffWriter}, pixarray::{Color2D, PixF32}, rawimage::RawPhotometricInterpretation, tags::{ExifTag, TiffCommonTag}, }; use super::{ Dim2, Rect, convert_from_f32_scaled_u16, raw::{map_3ch_to_rgb, map_4ch_to_rgb}, sensor::bayer::{Demosaic, bilinear::Bilinear4Channel, ppg::PPGDemosaic}, xyz::Illuminant, }; #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum ProcessingStep { Rescale, Demosaic, CropActiveArea, WhiteBalance, Calibrate, CropDefault, SRgb, } pub struct RawDevelopBuilder {} #[derive(Clone)] pub enum Intermediate { Monochrome(PixF32), ThreeColor(Color2D), FourColor(Color2D), } impl Intermediate { pub fn dim(&self) -> Dim2 { match self { Intermediate::Monochrome(pixels) => pixels.dim(), Intermediate::ThreeColor(pixels) => pixels.dim(), Intermediate::FourColor(pixels) => pixels.dim(), } } pub fn rect(&self) -> Rect { match self { Intermediate::Monochrome(pixels) => pixels.rect(), Intermediate::ThreeColor(pixels) => pixels.rect(), Intermediate::FourColor(pixels) => pixels.rect(), } } pub fn to_dynamic_image(self) -> Option { Some(match self { Intermediate::Monochrome(pixels) => { let data = convert_from_f32_scaled_u16(&pixels.data, 0, u16::MAX); DynamicImage::ImageLuma16(ImageBuffer::from_raw(pixels.dim().w as u32, pixels.dim().h as u32, data)?) } Intermediate::ThreeColor(pixels) => { let data = convert_from_f32_scaled_u16(&pixels.flatten(), 0, u16::MAX); DynamicImage::ImageRgb16(ImageBuffer::from_raw(pixels.dim().w as u32, pixels.dim().h as u32, data)?) } Intermediate::FourColor(pixels) => { let data = convert_from_f32_scaled_u16(&pixels.flatten(), 0, u16::MAX); DynamicImage::ImageRgba16(ImageBuffer::from_raw(pixels.dim().w as u32, pixels.dim().h as u32, data)?) } }) } } #[derive(Clone)] pub struct RawDevelop { pub steps: Vec, } impl Default for RawDevelop { fn default() -> Self { Self { steps: vec![ ProcessingStep::Rescale, ProcessingStep::Demosaic, ProcessingStep::CropActiveArea, ProcessingStep::WhiteBalance, ProcessingStep::Calibrate, ProcessingStep::CropDefault, ProcessingStep::SRgb, ], } } } impl RawDevelop { /* pub fn linearize(rawimage: &RawImage) -> crate::Result { todo!() } pub fn develop_monochrome_image(&self, rawimage: &RawImage) -> crate::Result { todo!() } pub fn develop_rgb_image(&self, rawimage: &RawImage) -> crate::Result { todo!() } */ /// Develop raw image and write result into TIFF. /// If demosaic is disabled or camera raw is monochrome, the TIFF /// has only one color channel. pub fn develop_intermediate(&self, rawimage: &RawImage) -> crate::Result { let mut rawimage = rawimage.clone(); if self.steps.contains(&ProcessingStep::Rescale) { rawimage.apply_scaling()?; } let mut intermediate = match rawimage.cpp { 1 => Intermediate::Monochrome(PixF32::new_with(rawimage.data.as_f32().into_owned(), rawimage.width, rawimage.height)), 3 => Intermediate::ThreeColor(Color2D::::new_with( rawimage.data.as_f32().chunks_exact(3).map(|x| [x[0], x[1], x[2]]).collect(), rawimage.width, rawimage.height, )), 4 => Intermediate::FourColor(Color2D::::new_with( rawimage.data.as_f32().chunks_exact(4).map(|x| [x[0], x[1], x[2], x[3]]).collect(), rawimage.width, rawimage.height, )), _ => todo!(), }; if self.steps.contains(&ProcessingStep::Demosaic) { intermediate = match &rawimage.photometric { RawPhotometricInterpretation::Cfa(config) => { if let Intermediate::Monochrome(pixels) = intermediate { let roi = if self.steps.contains(&ProcessingStep::CropActiveArea) { rawimage.active_area.unwrap_or(pixels.rect()) } else { pixels.rect() }; if config.cfa.is_rgb() { let ppg = PPGDemosaic::new(); Intermediate::ThreeColor(ppg.demosaic(&pixels, &config.cfa, &config.colors, roi)) } else if config.cfa.unique_colors() == 4 { let linear = Bilinear4Channel::new(); Intermediate::FourColor(linear.demosaic(&pixels, &config.cfa, &config.colors, roi)) } else { todo!() } } else { intermediate } } _ => intermediate, }; } if self.steps.contains(&ProcessingStep::Calibrate) { let mut xyz2cam: [[f32; 3]; 4] = [[0.0; 3]; 4]; let color_matrix = rawimage .color_matrix .iter() .find(|(illuminant, _m)| **illuminant == Illuminant::D65) .ok_or("Illuminant matrix D65 not found")? .1; assert_eq!(color_matrix.len() % 3, 0); // this is not so nice... let components = color_matrix.len() / 3; for i in 0..components { for j in 0..3 { xyz2cam[i][j] = color_matrix[i * 3 + j]; } } // Some old images may not provide WB coeffs. Assume 1.0 in this case. let mut wb = if rawimage.wb_coeffs[0].is_nan() { [1.0, 1.0, 1.0, 1.0] } else { rawimage.wb_coeffs }; if !self.steps.contains(&ProcessingStep::WhiteBalance) { wb = [1.0, 1.0, 1.0, 1.0]; } log::debug!("wb: {:?}, coeff: {:?}", wb, xyz2cam); intermediate = match intermediate { Intermediate::Monochrome(_) => intermediate, Intermediate::ThreeColor(pixels) => Intermediate::ThreeColor(map_3ch_to_rgb(&pixels, &wb, xyz2cam)), Intermediate::FourColor(pixels) => Intermediate::ThreeColor(map_4ch_to_rgb(&pixels, &wb, xyz2cam)), }; } if self.steps.contains(&ProcessingStep::CropDefault) { if let Some(mut crop) = rawimage.crop_area.or(rawimage.active_area) { if self.steps.contains(&ProcessingStep::Demosaic) && self.steps.contains(&ProcessingStep::CropActiveArea) { // If active area crop was already applied during demosaic, we need to // adapt default crop to active area crop. crop = crop.adapt(&rawimage.active_area.unwrap_or(crop)); } if intermediate.dim().w == rawimage.active_area.map(|area| area.d).unwrap_or(rawimage.dim()).w / 2 { // Superpixel debayer used crop.scale(0.5); } // Only apply crop if dimensions differ. if crop.d != intermediate.dim() { log::debug!("crop: {:?}, intermediate dim: {:?}, rawimage: {:?}", crop, intermediate.dim(), rawimage.dim()); intermediate = match intermediate { Intermediate::Monochrome(pixels) => Intermediate::Monochrome(pixels.crop(crop)), Intermediate::ThreeColor(pixels) => Intermediate::ThreeColor(pixels.crop(crop)), Intermediate::FourColor(pixels) => Intermediate::FourColor(pixels.crop(crop)), }; } } } if self.steps.contains(&ProcessingStep::SRgb) { match &mut intermediate { Intermediate::Monochrome(pixels) => pixels.for_each(super::srgb::srgb_apply_gamma), Intermediate::ThreeColor(pixels) => pixels.for_each(super::srgb::srgb_apply_gamma_n), Intermediate::FourColor(pixels) => pixels.for_each(super::srgb::srgb_apply_gamma_n), }; } Ok(intermediate) } /// Develop raw image and write result into TIFF. /// If demosaic is disabled or camera raw is monochrome, the TIFF /// has only one color channel. pub fn develop(&self, rawimage: &RawImage, md: &RawMetadata, writer: W) -> crate::Result<()> where W: io::Write + io::Seek, { let intermediate = self.develop_intermediate(rawimage)?; let mut tiff = TiffWriter::new(writer)?; let mut root_ifd = DirectoryWriter::new(); let mut exif_ifd = DirectoryWriter::new(); // Add EXIF version 0220 exif_ifd.add_tag_undefined(ExifTag::ExifVersion, vec![48, 50, 50, 48]); md.write_exif_tags(&mut tiff, &mut root_ifd, &mut exif_ifd)?; root_ifd.add_tag(TiffCommonTag::Make, rawimage.clean_make.as_str()); root_ifd.add_tag(TiffCommonTag::Model, rawimage.clean_model.as_str()); let exif_offset = exif_ifd.build(&mut tiff)?; root_ifd.add_tag(TiffCommonTag::ExifIFDPointer, exif_offset); match intermediate { Intermediate::Monochrome(pixels) => { let data = convert_from_f32_scaled_u16(&pixels.data, 0, u16::MAX); let (strip_rows, strips) = tiff.write_strips_lzw(&data, 1, pixels.dim(), 0)?; let strip_offsets: Vec = strips.iter().map(|(offset, _)| *offset).collect(); let strip_bytes: Vec = strips.iter().map(|(_, bytes)| *bytes).collect(); root_ifd.add_tag(TiffCommonTag::Compression, 5); root_ifd.add_tag(TiffCommonTag::Predictor, 1); root_ifd.add_tag(TiffCommonTag::StripOffsets, &strip_offsets); root_ifd.add_tag(TiffCommonTag::StripByteCounts, &strip_bytes); root_ifd.add_tag(TiffCommonTag::BitsPerSample, [16_u16]); root_ifd.add_tag(TiffCommonTag::SamplesPerPixel, [1_u16]); root_ifd.add_tag(TiffCommonTag::PhotometricInt, [1_u16]); root_ifd.add_tag(TiffCommonTag::RowsPerStrip, strip_rows); root_ifd.add_tag(TiffCommonTag::ImageWidth, pixels.width as u16); root_ifd.add_tag(TiffCommonTag::ImageLength, pixels.height as u16); } Intermediate::ThreeColor(pixels) => { let data = convert_from_f32_scaled_u16(&pixels.flatten(), 0, u16::MAX); let (strip_rows, strips) = tiff.write_strips_lzw(&data, 3, pixels.dim(), 0)?; let strip_offsets: Vec = strips.iter().map(|(offset, _)| *offset).collect(); let strip_bytes: Vec = strips.iter().map(|(_, bytes)| *bytes).collect(); root_ifd.add_tag(TiffCommonTag::Compression, 5); root_ifd.add_tag(TiffCommonTag::Predictor, 1); root_ifd.add_tag(TiffCommonTag::StripOffsets, &strip_offsets); root_ifd.add_tag(TiffCommonTag::StripByteCounts, &strip_bytes); root_ifd.add_tag(TiffCommonTag::BitsPerSample, [16_u16, 16, 16]); root_ifd.add_tag(TiffCommonTag::SamplesPerPixel, [3_u16]); root_ifd.add_tag(TiffCommonTag::PhotometricInt, [2_u16]); root_ifd.add_tag(TiffCommonTag::RowsPerStrip, strip_rows); root_ifd.add_tag(TiffCommonTag::ImageWidth, pixels.width as u16); root_ifd.add_tag(TiffCommonTag::ImageLength, pixels.height as u16); } Intermediate::FourColor(pixels) => { let data = convert_from_f32_scaled_u16(&pixels.flatten(), 0, u16::MAX); let (strip_rows, strips) = tiff.write_strips_lzw(&data, 4, pixels.dim(), 0)?; let strip_offsets: Vec = strips.iter().map(|(offset, _)| *offset).collect(); let strip_bytes: Vec = strips.iter().map(|(_, bytes)| *bytes).collect(); root_ifd.add_tag(TiffCommonTag::Compression, 5); root_ifd.add_tag(TiffCommonTag::Predictor, 1); root_ifd.add_tag(TiffCommonTag::StripOffsets, &strip_offsets); root_ifd.add_tag(TiffCommonTag::StripByteCounts, &strip_bytes); root_ifd.add_tag(TiffCommonTag::BitsPerSample, [16_u16, 16, 16, 16]); // Extra-channel, even if PhotometricInt is RGB! root_ifd.add_tag(TiffCommonTag::SamplesPerPixel, [4_u16]); root_ifd.add_tag(TiffCommonTag::PhotometricInt, [2_u16]); root_ifd.add_tag(TiffCommonTag::RowsPerStrip, strip_rows); root_ifd.add_tag(TiffCommonTag::ImageWidth, pixels.width as u16); root_ifd.add_tag(TiffCommonTag::ImageLength, pixels.height as u16); } } tiff.build(root_ifd)?; Ok(()) } } rawler-0.7.1/src/imgop/gamma.rs000064400000000000000000000003571046102023000144640ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher pub fn apply_gamma(v: f32, gamma: f32) -> f32 { v.powf(1.0 / gamma) } pub fn invert_gamma(v: f32, gamma: f32) -> f32 { v.powf(gamma) } rawler-0.7.1/src/imgop/matrix.rs000064400000000000000000000065351046102023000147120ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher pub const IDENTITY_MATRIX_3: [[f32; 3]; 3] = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]; /// Multiply two matrices a and b pub fn multiply(a: &[[f32; X]; A], b: &[[f32; B]; X]) -> [[f32; B]; A] { let mut r = [[0.0; B]; A]; for i in 0..A { for j in 0..B { for x in 0..X { r[i][j] += a[i][x] * b[x][j]; } } } r } pub fn multiply_row1(a: &[[f32; 3]; 3], b: &[f32; 3]) -> [f32; 3] { [ a[0][0] * b[0] + a[0][1] * b[1] + a[0][2] * b[2], a[1][0] * b[0] + a[1][1] * b[1] + a[1][2] * b[2], a[2][0] * b[0] + a[2][1] * b[1] + a[2][2] * b[2], ] } /// Normalize a matrix so that the sum of each row equals to 1.0 pub fn normalize(rgb2cam: [[f32; N]; M]) -> [[f32; N]; M] { let mut result = [[0.0; N]; M]; for m in 0..M { let sum: f32 = rgb2cam[m].iter().sum(); if sum.abs() != 0.0 { for n in 0..N { result[m][n] = rgb2cam[m][n] / sum; } } } result } /// Calculate pseudo-inverse of a given matrix pub fn pseudo_inverse(matrix: [[f32; 3]; N]) -> [[f32; N]; 3] { let mut tmp: [[f32; 3]; N] = [Default::default(); N]; let mut result: [[f32; N]; 3] = [[Default::default(); N]; 3]; let mut work: [[f32; 6]; 3] = [Default::default(); 3]; for i in 0..3 { for j in 0..6 { work[i][j] = if j == i + 3 { 1.0 } else { 0.0 }; } for j in 0..3 { for k in 0..N { work[i][j] += matrix[k][i] * matrix[k][j]; } } } for i in 0..3 { let mut num = work[i][i]; for j in 0..6 { work[i][j] /= num; } for k in 0..3 { if k == i { continue; } num = work[k][i]; for j in 0..6 { work[k][j] -= work[i][j] * num; } } } for i in 0..N { for j in 0..3 { tmp[i][j] = 0.0; for k in 0..3 { tmp[i][j] += work[j][k + 3] * matrix[i][k]; } } } for i in 0..3 { for j in 0..N { result[i][j] = tmp[j][i]; } } result } /// Transpose a given input matrix pub fn transpose(matrix: &[[f32; M]; N]) -> [[f32; N]; M] { let mut transposed = [[f32::NAN; N]; M]; for n in 0..N { for m in 0..M { transposed[m][n] = matrix[n][m]; } } transposed } /// Transform a 2D matrix representation to 1D pub fn transform_2d(matrix: &[[f32; M]; N]) -> Vec { matrix.iter().flat_map(|n| n.iter().cloned()).collect() } /// Transform a 1D matrix representation to 2D pub fn transform_1d(matrix: &[f32]) -> Option<[[f32; M]; N]> { if matrix.len() != (N * M) { return None; }; let mut transformed = [[f32::NAN; M]; N]; for (i, v) in matrix.iter().cloned().enumerate() { *transformed.get_mut(i / M).and_then(|inner| inner.get_mut(i % M))? = v; } Some(transformed) } #[cfg(test)] mod tests { use super::*; #[test] fn transform_1d_to_2d() -> std::result::Result<(), Box> { let m1d = vec![1.3, 5.3, 6.1, 4.2, 8.3, 8.2]; assert!(transform_1d::<2, 3>(&m1d).is_some()); assert!(transform_1d::<3, 2>(&m1d).is_some()); assert!(transform_1d::<1, 1>(&m1d).is_none()); assert!(transform_1d::<6, 7>(&m1d).is_none()); Ok(()) } } rawler-0.7.1/src/imgop/mod.rs000064400000000000000000000173731046102023000141670ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher pub mod chromatic_adaption; pub mod develop; pub mod gamma; pub mod matrix; pub mod raw; pub mod sensor; pub mod spline; pub mod srgb; pub mod xyz; pub mod yuv; use multiversion::multiversion; use serde::{Deserialize, Serialize}; use crate::{formats::tiff::IFD, tags::DngTag}; pub type Result = std::result::Result; /* macro_rules! max { ($x: expr) => ($x); ($x: expr, $($z: expr),+) => {{ let y = max!($($z),*); if $x > y { $x } else { y } }} } macro_rules! min { ($x: expr) => ($x); ($x: expr, $($z: expr),+) => {{ let y = min!($($z),*); if $x < y { $x } else { y } }} } */ /// Descriptor of a two-dimensional area #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] pub struct Dim2 { pub w: usize, pub h: usize, } impl Dim2 { pub fn new(w: usize, h: usize) -> Self { Self { w, h } } pub fn is_empty(&self) -> bool { self.w == 0 && self.h == 0 } } /// Clip a value with min/max value #[allow(clippy::if_same_then_else)] pub fn clip(p: f32, min: f32, max: f32) -> f32 { if p > max { max } else if p < min { min } else if p.is_nan() { min } else { p } } /// A simple x/y point #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] pub struct Point { pub x: usize, pub y: usize, } impl Point { pub fn new(x: usize, y: usize) -> Self { Self { x, y } } pub fn zero() -> Self { Self { x: 0, y: 0 } } } /// Rectangle by a point and dimension #[derive(Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] pub struct Rect { pub p: Point, pub d: Dim2, } impl std::fmt::Debug for Rect { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { //f.debug_struct("Rect").field("p", &self.p).field("d", &self.d).finish()?; f.write_fmt(format_args!( "Rect{{{}:{}, {}x{}, LTRB=[{}, {}, {}, {}]}}", self.p.x, self.p.y, self.d.w, self.d.h, self.p.x, self.p.y, self.p.x + self.d.w, self.p.y + self.d.h )) } } impl Rect { pub fn new(p: Point, d: Dim2) -> Self { Self { p, d } } // left, top, right, bottom pub fn new_with_points(p1: Point, p2: Point) -> Self { assert!(p1.x <= p2.x); assert!(p1.y <= p2.y); Self { p: p1, d: Dim2 { w: p2.x - p1.x, h: p2.y - p1.y, }, } } pub fn new_with_borders(dim: Dim2, borders: &[usize; 4]) -> Self { Self::new_with_points(Point::new(borders[0], borders[1]), Point::new(dim.w - borders[2], dim.h - borders[3])) } /// DNG used top-left-bottom-right for all rectangles pub fn new_with_dng(rect: &[usize; 4]) -> Rect { Self::new_with_points(Point::new(rect[1], rect[0]), Point::new(rect[3], rect[2])) } pub fn is_empty(&self) -> bool { self.d.is_empty() } /// Return in LTRB coordinates pub fn as_ltrb(&self) -> [usize; 4] { [self.p.x, self.p.y, self.p.x + self.d.w, self.p.y + self.d.h] } /// Return in TLBR pub fn as_tlbr(&self) -> [usize; 4] { [self.p.y, self.p.x, self.p.y + self.d.h, self.p.x + self.d.w] } /// Return as offsets from each side (LTRB) pub fn as_ltrb_offsets(&self, width: usize, height: usize) -> [usize; 4] { [self.p.x, self.p.y, width - (self.p.x + self.d.w), height - (self.p.y + self.d.h)] } /// Return as offsets from each side (TLBR) pub fn as_tlbr_offsets(&self, width: usize, height: usize) -> [usize; 4] { [self.p.y, self.p.x, height - (self.p.y + self.d.h), width - (self.p.x + self.d.w)] } // Read Crop params from IFD pub fn from_tiff(ifd: &IFD) -> Option { if let Some(crop) = ifd.get_entry(DngTag::DefaultCropOrigin) { if let Some(dim) = ifd.get_entry(DngTag::DefaultCropSize) { let p = Point::new(crop.force_usize(0), crop.force_usize(1)); let d = Dim2::new(dim.force_usize(0), dim.force_usize(1)); return Some(Self::new(p, d)); } } None } pub fn width(&self) -> usize { self.d.w } pub fn height(&self) -> usize { self.d.h } pub fn x(&self) -> usize { self.p.x } pub fn y(&self) -> usize { self.p.y } pub fn adapt(&self, master: &Self) -> Self { assert!(self.p.x >= master.p.x); assert!(self.p.y >= master.p.y); assert!(self.d.w <= master.d.w); assert!(self.d.h <= master.d.h); Self { p: Point::new(self.p.x - master.p.x, self.p.y - master.p.y), d: self.d, } } pub fn scale(&mut self, scale: f32) { self.d.w = ((self.d.w as f32) * scale) as usize; self.d.h = ((self.d.h as f32) * scale) as usize; self.p.x = ((self.p.x as f32) * scale) as usize; self.p.y = ((self.p.y as f32) * scale) as usize; } } /// Crop image to specific area pub fn crop(input: &[T], dim: Dim2, area: Rect) -> Vec { let mut output = Vec::with_capacity(area.d.h * area.d.w); output.extend( input .chunks_exact(dim.w) .skip(area.p.y) .take(area.d.h) .flat_map(|row| row[area.p.x..area.p.x + area.d.w].iter()) .cloned(), ); output } pub fn scale_u16_to_double(x: u16) -> f32 { x as f32 / u16::MAX as f32 } pub fn scale_double_to_u16(x: f32) -> u16 { (x.abs() * u16::MAX as f32) as u16 } pub fn scale_u8_to_double(x: u8) -> f32 { x as f32 / u8::MAX as f32 } pub fn scale_double_to_u8(x: f32) -> u8 { (x.abs() * u8::MAX as f32) as u8 } /* /// Rescale to u16 value #[multiversion] #[clone(target = "[x86|x86_64]+avx+avx2")] #[clone(target = "x86+sse")] pub fn rescale_f32_to_u16(input: &[f32], black: u16, white: u16) -> Vec { if black == 0 { input.par_iter().map(|p| (p * white as f32) as u16).collect() } else { input.par_iter().map(|p| (p * (white - black) as f32) as u16 + black).collect() } } /// Rescale to u8 value #[multiversion] #[clone(target = "[x86|x86_64]+avx+avx2")] #[clone(target = "x86+sse")] pub fn rescale_f32_to_u8(input: &[f32], black: u8, white: u8) -> Vec { if black == 0 { input.par_iter().map(|p| (p * white as f32) as u8).collect() } else { input.par_iter().map(|p| (p * (white - black) as f32) as u8 + black).collect() } } */ #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] pub fn convert_to_f32_unscaled(pix: &[T]) -> Vec where T: Copy, f32: From, { pix.iter().copied().map(f32::from).collect() } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] pub fn convert_to_f32_scaled(pix: &[T], black: T, white: T) -> Vec where T: Copy + Eq + PartialEq + Default + std::ops::Sub, f32: From, { if black == T::default() { pix.iter().copied().map(f32::from).map(|x| x / f32::from(white)).collect() } else { pix .iter() .copied() .map(|x| x - black) .map(f32::from) .map(|x| x / f32::from(white - black)) .collect() } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] pub fn convert_from_f32_unscaled_u16(pix: &[f32]) -> Vec { pix.iter().copied().map(|x| x as u16).collect() } /// Rescale to u8 value #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] pub fn convert_from_f32_scaled_u16(input: &[f32], black: u16, white: u16) -> Vec { if black == u16::default() { input.iter().map(|p| ((p * f32::from(white)) as u16)).collect() } else { input.iter().map(|p| ((p * f32::from(white - black)) as u16) + black).collect() } } #[cfg(test)] mod tests { use super::*; #[test] fn rect_from_points() -> std::result::Result<(), Box> { let rect1 = Rect::new(Point::new(0, 0), Dim2::new(1, 1)); let rect2 = Rect::new_with_points(Point::new(0, 0), Point::new(1, 1)); assert_eq!(rect1, rect2); Ok(()) } } rawler-0.7.1/src/imgop/raw.rs000064400000000000000000000215521046102023000141730ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher use super::xyz::Illuminant; use crate::imgop::Rect; use crate::imgop::matrix::{multiply, normalize, pseudo_inverse}; use crate::imgop::xyz::SRGB_TO_XYZ_D65; use crate::pixarray::{Color2D, RgbF32}; use crate::rawimage::{BlackLevel, RawPhotometricInterpretation, WhiteLevel}; use multiversion::multiversion; use rayon::prelude::*; /// Conversion matrix for a specific illuminant #[derive(Debug)] pub struct ColorMatrix { pub illuminant: Illuminant, pub matrix: [[f32; 3]; 4], } /// Parameters for raw image development #[derive(Debug)] pub struct DevelopParams { pub width: usize, pub height: usize, pub cpp: usize, pub color_matrices: Vec, pub whitelevel: WhiteLevel, pub blacklevel: BlackLevel, //pub pattern: Option, pub photometric: RawPhotometricInterpretation, pub wb_coeff: [f32; 4], pub active_area: Option, pub crop_area: Option, //pub gamma: f32, } /// CLip only underflow values < 0.0 pub fn clip_negative(pix: &[f32; N]) -> [f32; N] { pix.map(|p| if p < 0.0 { 0.0 } else { p }) } /// Clip only overflow values > 1.0 pub fn clip_overflow(pix: &[f32; N]) -> [f32; N] { pix.map(|p| if p > 1.0 { 1.0 } else { p }) } /// Clip into range of 0.0 - 1.0 pub fn clip(pix: &[f32; N]) -> [f32; N] { clip_range(pix, 0.0, 1.0) } /// Clip into range of lower and upper bound pub fn clip_range(pix: &[f32; N], lower: f32, upper: f32) -> [f32; N] { pix.map(|p| clip_value(p, lower, upper)) } pub fn clip_value(p: f32, lower: f32, upper: f32) -> f32 { if p < lower { lower } else if p > upper { upper } else { p } } /// Clip pixel with N components by: /// 1. Normalize pixel by max(pix) if any component is > 1.0 /// 2. Compute euclidean norm of the pixel, normalized by sqrt(N) /// 3. Compute channel-wise average of normalized pixel + euclidean norm pub fn clip_euclidean_norm_avg(pix: &[f32; N]) -> [f32; N] { let pix = clip_negative(pix); let max_val = pix.iter().copied().reduce(f32::max).unwrap_or(f32::NAN); if max_val > 1.0 { // Retains color let color = pix.map(|p| p / max_val); // Euclidean norm let eucl = pix.map(|p| p.powi(2)).iter().sum::().sqrt() / (N as f32).sqrt(); // Take average of both color.map(|p| (p + eucl) / 2.0) } else { pix } } /// Correct data by blacklevel and whitelevel on CFA (bayer) data. /// /// The output is between 0.0 .. 1.0. /// /// This version is optimized vor vectorization, so please check /// modifications on godbolt before committing. #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn correct_blacklevel_channels(raw: &mut [f32], blacklevel: &[f32; CH], whitelevel: &[f32; CH]) { // max value can be pre-computed for all channels. let mut max = *whitelevel; max.iter_mut().enumerate().for_each(|(i, x)| *x -= blacklevel[i]); let clip = |v: f32| { if v.is_sign_negative() { 0.0 } else { v } }; if CH == 1 { let max = max[0]; let blacklevel = blacklevel[0]; raw.iter_mut().for_each(|p| *p = clip(*p - blacklevel) / max); } else { raw.chunks_exact_mut(CH).for_each(|block| { for i in 0..CH { block[i] = clip(block[i] - blacklevel[i]) / max[i]; } }); } } /// Correct data by blacklevel and whitelevel on CFA (bayer) data. /// /// The output is between 0.0 .. 1.0. /// /// This version is optimized vor vectorization, so please check /// modifications on godbolt before committing. #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] pub fn correct_blacklevel(raw: &mut [f32], blacklevel: &[f32], whitelevel: &[f32]) { match (blacklevel.len(), whitelevel.len()) { (1, 1) => correct_blacklevel_channels::<1>( raw, blacklevel.try_into().expect("Array size mismatch"), whitelevel.try_into().expect("Array size mismatch"), ), (3, 3) => correct_blacklevel_channels::<3>( raw, blacklevel.try_into().expect("Array size mismatch"), whitelevel.try_into().expect("Array size mismatch"), ), (a, b) if a == b => { // max value can be pre-computed for all channels. let mut max = whitelevel.to_vec(); max.iter_mut().enumerate().for_each(|(i, x)| *x -= blacklevel[i]); let clip = |v: f32| { if v.is_sign_negative() { 0.0 } else { v } }; let ch = blacklevel.len(); raw.chunks_exact_mut(ch).for_each(|block| { for i in 0..ch { block[i] = clip(block[i] - blacklevel[i]) / max[i]; } }); } _ => panic!("Blacklevel ({}) and Whitelevel ({})count mismatch", blacklevel.len(), whitelevel.len()), } } /// Correct data by blacklevel and whitelevel on CFA (bayer) data. /// /// The output is between 0.0 .. 1.0. /// /// This version is optimized vor vectorization, so please check /// modifications on godbolt before committing. #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] pub fn correct_blacklevel_cfa(raw: &mut [f32], width: usize, _height: usize, blacklevel: &[f32; 4], whitelevel: &[f32; 4]) { //assert_eq!(width % 2, 0, "width is {}", width); //assert_eq!(height % 2, 0, "height is {}", height); // max value can be pre-computed for all channels. let max = [ whitelevel[0] - blacklevel[0], whitelevel[1] - blacklevel[1], whitelevel[2] - blacklevel[2], whitelevel[3] - blacklevel[3], ]; let clip = |v: f32| { if v.is_sign_negative() { 0.0 } else { v } }; // Process two bayer lines at once. raw.par_chunks_exact_mut(width * 2).for_each(|lines| { // It's bayer data, so we have two lines for sure. let (line0, line1) = lines.split_at_mut(width); //line0.array_chunks_mut::<2>().zip(line1.array_chunks_mut::<2>()).for_each(|(a, b)| { line0.chunks_exact_mut(2).zip(line1.chunks_exact_mut(2)).for_each(|(a, b)| { a[0] = clip(a[0] - blacklevel[0]) / max[0]; a[1] = clip(a[1] - blacklevel[1]) / max[1]; b[0] = clip(b[0] - blacklevel[2]) / max[2]; b[1] = clip(b[1] - blacklevel[3]) / max[3]; }); }); } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] pub(crate) fn map_3ch_to_rgb(src: &Color2D, wb_coeff: &[f32; 4], xyz2cam: [[f32; 3]; 4]) -> RgbF32 { let rgb2cam = normalize(multiply(&xyz2cam, &SRGB_TO_XYZ_D65)); let cam2rgb = pseudo_inverse(rgb2cam); let mut out = Vec::with_capacity(src.data.len()); src .pixels() .par_iter() .map(|pix| { // We apply wb coeffs on the fly let r = pix[0] * wb_coeff[0]; let g = pix[1] * wb_coeff[1]; let b = pix[2] * wb_coeff[2]; let srgb = [ cam2rgb[0][0] * r + cam2rgb[0][1] * g + cam2rgb[0][2] * b, cam2rgb[1][0] * r + cam2rgb[1][1] * g + cam2rgb[1][2] * b, cam2rgb[2][0] * r + cam2rgb[2][1] * g + cam2rgb[2][2] * b, ]; clip_euclidean_norm_avg(&srgb) }) .collect_into_vec(&mut out); RgbF32::new_with(out, src.width, src.height) } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] pub(crate) fn map_4ch_to_rgb(src: &Color2D, wb_coeff: &[f32; 4], xyz2cam: [[f32; 3]; 4]) -> RgbF32 { let rgb2cam = normalize(multiply(&xyz2cam, &SRGB_TO_XYZ_D65)); let cam2rgb = pseudo_inverse(rgb2cam); let mut out = Vec::with_capacity(src.data.len()); src .pixels() .par_iter() .map(|pix| { // We apply wb coeffs on the fly let ch0 = pix[0] * wb_coeff[0]; let ch1 = pix[1] * wb_coeff[1]; let ch2 = pix[2] * wb_coeff[2]; let ch3 = pix[3] * wb_coeff[3]; let srgb = [ cam2rgb[0][0] * ch0 + cam2rgb[0][1] * ch1 + cam2rgb[0][2] * ch2 + cam2rgb[0][3] * ch3, cam2rgb[1][0] * ch0 + cam2rgb[1][1] * ch1 + cam2rgb[1][2] * ch2 + cam2rgb[1][3] * ch3, cam2rgb[2][0] * ch0 + cam2rgb[2][1] * ch1 + cam2rgb[2][2] * ch2 + cam2rgb[2][3] * ch3, ]; clip_euclidean_norm_avg(&srgb) }) .collect_into_vec(&mut out); RgbF32::new_with(out, src.width, src.height) } /// Collect iterator into array pub fn collect_array(itr: I) -> [T; N] where T: Default + Copy, I: IntoIterator, { let mut res = [T::default(); N]; for (it, elem) in res.iter_mut().zip(itr) { *it = elem } res } /// Calculate the multiplicative invert of an array /// (sum of each row equals to 1.0) pub fn mul_invert_array(a: &[f32; N]) -> [f32; N] { let mut b = [f32::default(); N]; b.iter_mut().zip(a.iter()).for_each(|(x, y)| *x = 1.0 / y); b } pub fn rotate_90(src: &[u16], dst: &mut [u16], width: usize, height: usize) { let dst = &mut dst[..src.len()]; // optimize len hints for compiler let owidth = height; for (row, line) in src.chunks_exact(width).enumerate() { for (col, pix) in line.iter().enumerate() { let orow = col; let ocol = (owidth - 1) - row; // inverse dst[orow * owidth + ocol] = *pix; } } } rawler-0.7.1/src/imgop/sensor/bayer/bilinear.rs000064400000000000000000000110671046102023000176020ustar 00000000000000use multiversion::multiversion; use crate::{ CFA, cfa::PlaneColor, imgop::Rect, pixarray::{Color2D, PixF32}, }; use super::Demosaic; #[derive(Default)] pub struct Bilinear4Channel {} impl Bilinear4Channel { pub fn new() -> Self { Self {} } } impl Demosaic for Bilinear4Channel { /// Debayer image by using bilinear method. fn demosaic(&self, pixels: &PixF32, cfa: &CFA, colors: &PlaneColor, roi: Rect) -> Color2D { Self::demosaic_4ch(pixels, cfa, colors, roi) } } impl Bilinear4Channel { #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn demosaic_4ch(pixels: &PixF32, cfa: &CFA, colors: &PlaneColor, roi: Rect) -> Color2D { if colors.plane_count() != 4 { panic!("Demosaic for 4 channels needs 4 color planes, but {} given", colors.plane_count()); } log::debug!("Bilinear debayer ROI: {:?}", roi); let cfa = cfa.shift(roi.p.x, roi.p.y); let plane_map = colors.plane_lookup_table(); let ch = |row: usize, col: usize| -> usize { plane_map[cfa.color_at(row, col)] }; let pixels = pixels.crop(roi); let dim = pixels.dim(); let mut out = Color2D::new(pixels.dim().w, pixels.dim().h); // Process edges out.at_mut(0, 0)[ch(0, 0)] = *pixels.at(0, 0); out.at_mut(0, 0)[ch(0, 1)] = *pixels.at(0, 1); out.at_mut(0, 0)[ch(1, 0)] = *pixels.at(1, 0); out.at_mut(0, 0)[ch(1, 1)] = *pixels.at(1, 1); out.at_mut(0, dim.w - 1)[ch(0, dim.w - 1)] = *pixels.at(0, dim.w - 1); out.at_mut(0, dim.w - 1)[ch(0, dim.w - 2)] = *pixels.at(0, dim.w - 2); out.at_mut(0, dim.w - 1)[ch(1, dim.w - 1)] = *pixels.at(1, dim.w - 1); out.at_mut(0, dim.w - 1)[ch(1, dim.w - 2)] = *pixels.at(1, dim.w - 2); out.at_mut(dim.h - 1, 0)[ch(dim.h - 1, 0)] = *pixels.at(dim.h - 1, 0); out.at_mut(dim.h - 1, 0)[ch(dim.h - 1, 1)] = *pixels.at(dim.h - 1, 1); out.at_mut(dim.h - 1, 0)[ch(dim.h - 2, 0)] = *pixels.at(dim.h - 2, 0); out.at_mut(dim.h - 1, 0)[ch(dim.h - 2, 1)] = *pixels.at(dim.h - 2, 1); out.at_mut(dim.h - 1, dim.w - 1)[ch(dim.h - 1, dim.w - 1)] = *pixels.at(dim.h - 1, dim.w - 1); out.at_mut(dim.h - 1, dim.w - 1)[ch(dim.h - 1, dim.w - 2)] = *pixels.at(dim.h - 1, dim.w - 2); out.at_mut(dim.h - 1, dim.w - 1)[ch(dim.h - 2, dim.w - 1)] = *pixels.at(dim.h - 2, dim.w - 1); out.at_mut(dim.h - 1, dim.w - 1)[ch(dim.h - 2, dim.w - 2)] = *pixels.at(dim.h - 2, dim.w - 2); // Process borders for i in 1..out.width - 1 { // Top line out.at_mut(0, i)[ch(0, i)] = *pixels.at(0, i); out.at_mut(0, i)[ch(0, i + 1)] = (*pixels.at(0, i - 1) + *pixels.at(0, i + 1)) / 2.0; out.at_mut(0, i)[ch(1, i)] = *pixels.at(1, i); out.at_mut(0, i)[ch(1, i + 1)] = (*pixels.at(1, i - 1) + *pixels.at(1, i + 1)) / 2.0; // Bottom line out.at_mut(dim.h - 1, i)[ch(dim.h - 1, i)] = *pixels.at(dim.h - 1, i); out.at_mut(dim.h - 1, i)[ch(dim.h - 1, i + 1)] = (*pixels.at(dim.h - 1, i - 1) + *pixels.at(dim.h - 1, i + 1)) / 2.0; out.at_mut(dim.h - 1, i)[ch(dim.h - 2, i)] = *pixels.at(dim.h - 2, i); out.at_mut(dim.h - 1, i)[ch(dim.h - 2, i + 1)] = (*pixels.at(dim.h - 2, i - 1) + *pixels.at(dim.h - 2, i + 1)) / 2.0; } for i in 1..out.height - 1 { // Left out.at_mut(i, 0)[ch(i, 0)] = *pixels.at(i, 0); out.at_mut(i, 0)[ch(i + 1, 0)] = (*pixels.at(i - 1, 0) + *pixels.at(i + 1, 0)) / 2.0; out.at_mut(i, 0)[ch(i, 1)] = *pixels.at(i, 1); out.at_mut(i, 0)[ch(i + 1, 1)] = (*pixels.at(i - 1, 1) + *pixels.at(i + 1, 1)) / 2.0; // Right out.at_mut(i, dim.w - 1)[ch(i, dim.w - 1)] = *pixels.at(i, dim.w - 1); out.at_mut(i, dim.w - 1)[ch(i + 1, dim.w - 1)] = (*pixels.at(i - 1, dim.w - 1) + *pixels.at(i + 1, dim.w - 1)) / 2.0; out.at_mut(i, dim.w - 1)[ch(i, dim.w - 2)] = *pixels.at(i, dim.w - 2); out.at_mut(i, dim.w - 1)[ch(i + 1, dim.w - 2)] = (*pixels.at(i - 1, dim.w - 2) + *pixels.at(i + 1, dim.w - 2)) / 2.0; } /* A B A B C D C D A B A B C D C D */ out.for_each_row(|row, pix| { if row == 0 || row == dim.h - 1 { return; // Skip border rows } for col in 1..dim.w - 1 { pix[col][ch(row, col)] = *pixels.at(row, col); pix[col][ch(row + 1, col)] = (*pixels.at(row - 1, col) + *pixels.at(row + 1, col)) / 2.0; pix[col][ch(row, col + 1)] = (*pixels.at(row, col - 1) + *pixels.at(row, col + 1)) / 2.0; pix[col][ch(row + 1, col + 1)] = (*pixels.at(row - 1, col - 1) + *pixels.at(row - 1, col + 1) + *pixels.at(row + 1, col - 1) + *pixels.at(row + 1, col + 1)) / 4.0; } }); out } } rawler-0.7.1/src/imgop/sensor/bayer/mod.rs000064400000000000000000000030031046102023000165630ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher pub mod bilinear; pub mod ppg; pub mod superpixel; use multiversion::multiversion; use rayon::prelude::*; use crate::{ cfa::{CFA, PlaneColor}, imgop::{Dim2, Rect}, pixarray::{Color2D, Pix2D, RgbF32, SubPixel}, }; pub trait Demosaic { fn demosaic(&self, pixels: &Pix2D, cfa: &CFA, colors: &PlaneColor, roi: Rect) -> Color2D; } /// Extend a single pixel component from bayer pattern to RGB /// /// The other channels (missing colors) are set to 0.0. #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn expand_bayer_rgb(raw: &[f32], dim: Dim2, cfa: &CFA, roi: Rect) -> RgbF32 { // The ROI changes the pattern if not perfectly aligned on the origin pattern let cfa_roi = cfa.shift(roi.x(), roi.y()); let mut out = RgbF32::new(roi.width(), roi.height()); out.pixels_mut().par_chunks_exact_mut(roi.width()).enumerate().for_each(|(row_out, buf)| { assert_eq!(roi.width() % cfa.width, 0); // Area must be bound to CFA bounds let row_in = roi.p.y + row_out; let start_in = row_in * dim.w + roi.p.x; let line = &raw[start_in..start_in + roi.width()]; for (col, (p_out, p_in)) in buf.iter_mut().zip(line.iter()).enumerate() { p_out[cfa_roi.color_at(row_out, col)] = *p_in; } }); out } /// Bayer matrix pattern #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum RgbBayerPattern { RGGB, BGGR, GBRG, GRBG, //ERBG, //RGEB, } rawler-0.7.1/src/imgop/sensor/bayer/ppg.rs000064400000000000000000000247431046102023000166100ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2022 Daniel Vogelbacher use multiversion::multiversion; use rayon::prelude::*; use std::{ops::Add, time::Instant}; use crate::{ cfa::{CFA, CFA_COLOR_B, CFA_COLOR_G, CFA_COLOR_R, PlaneColor}, imgop::Rect, pixarray::{Color2D, PixF32, RgbF32}, }; use super::Demosaic; #[derive(Default)] pub struct PPGDemosaic {} impl PPGDemosaic { pub fn new() -> Self { Self {} } } /// PPG demosaic a raw image (f32 values) /// /// The PPG - Pattern Pixel Grouping - alogrithm was developed by Chuan-kai Lin /// Source on Internet Archive: /// https://web.archive.org/web/20160923211135/https://sites.google.com/site/chklin/demosaic/ /// /// This is a simple algorithm but provides acceptable results. /// /// # Panics /// /// This function panics for CFA pattern that are not RGGB or variants. You need /// to check the pattern before calling. impl Demosaic for PPGDemosaic { /// Debayer image by using superpixel method. /// Each output pixel RGB tuple is generated by 4 pixels from input. /// The result image is 1/4 of size. fn demosaic(&self, pixels: &PixF32, cfa: &CFA, _colors: &PlaneColor, roi: Rect) -> Color2D { // PPG can only applied to pure RGGB or variants. if !cfa.is_rgb() { panic!("CFA pattern '{}' is not a RGB pattern, can not demosaic with PPG", cfa); } // Measure time let now = Instant::now(); // The ROI changes the pattern if not perfectly aligned on the origin pattern let cfa_roi = cfa.shift(roi.p.x, roi.p.y); // Expand the bayer data to full RGB channel image, but only for ROI let mut rgb = super::expand_bayer_rgb(pixels.pixels(), pixels.dim(), cfa, roi); // Now interpolate the missing channels interpolate_borders(&mut rgb, &cfa_roi); interpolate_green(&mut rgb, &cfa_roi); interpolate_rb_at_green(&mut rgb, &cfa_roi); interpolate_rb_at_non_green(&mut rgb, &cfa_roi); log::debug!("PPG total debayer time: {:.5}s", now.elapsed().as_secs_f32()); rgb } } /// PPG Demosaic: Interpolate borders /// We take 3 pixels on each border and interpolate by bilinear interpolation. /// Bilinear interpolation is done by `(x1 + x2 + x3 + x4) / 4` or a /// reduced sum and count if not all samples are available like on borders. /// /// Basically, for each pixel position, we iterate around it and collect /// all channel values. Then apply interpolation to calculate the missing /// two channel colors for the origin pixel position. #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn interpolate_borders(input: &mut RgbF32, shifted: &CFA) { let w = input.width; let h = input.height; // Iterate over all rows for row in 0..h { let mut col = 0; while col < w { // Full process first 3 and last 3 rows, process only left and right 3 pixels for all other if col == 3 && row >= 3 && row < h - 3 { col = w - 3 // go to right border } // Store the pixel sum and count for each RGB channel (R=0, G=1, B=2) let mut sum = [(0.0, 0_usize); 3]; // We iterate around the current pixel, 8+1 pixels total in ideal cases (less on edges) for y in row.saturating_sub(1)..=row.add(1) { for x in col.saturating_sub(1)..=col.add(1) { // We have ensured that the target is not out of range for north and west, let's check for east and south. if y < h && x < w { let ch = shifted.color_at(y, x); sum[ch].0 += input.at(y, x)[ch]; sum[ch].1 += 1; } } } // Now we have collected all surrounding pixels, let's interpolate missing 2 channels let ch = shifted.color_at(row, col); for (color, p) in input.at_mut(row, col).iter_mut().enumerate() { // Check if the color is one of the missing 2 channels (ch is the known on) if color != ch && sum[color].1 > 0 { *p = sum[color].0 / sum[color].1 as f32; // Bilinear interpolation } } col += 1; } } } /// PPG Demosaic: Interpolate missing G channels /// After this procedure, all green values are known. #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn interpolate_green(img: &mut RgbF32, shifted: &CFA) { let w = img.width; let h = img.height; // Secondary data pointer, so we can have a mutable subslice reference // inside the par_* methods and a second immutable reference to the whole // image. This is not possible in Rust without unsafe code. let dataptr = img.data_ptr(); img.pixels_mut().par_chunks_exact_mut(w).enumerate().skip(3).take(h - 6).for_each(|(row, buf)| { for (col, pixel) in buf.iter_mut().enumerate().skip(3).take(w - 6) { if shifted.color_at(row, col) != CFA_COLOR_G { let ch = shifted.color_at(row, col); // It's R or B let x = pixel[ch]; let n_1 = unsafe { dataptr.at(row - 1, col)[CFA_COLOR_G] }; let n_2 = unsafe { dataptr.at(row - 2, col)[ch] }; let e_1 = unsafe { dataptr.at(row, col + 1)[CFA_COLOR_G] }; let e_2 = unsafe { dataptr.at(row, col + 2)[ch] }; let s_1 = unsafe { dataptr.at(row + 1, col)[CFA_COLOR_G] }; let s_2 = unsafe { dataptr.at(row + 2, col)[ch] }; let w_1 = unsafe { dataptr.at(row, col - 1)[CFA_COLOR_G] }; let w_2 = unsafe { dataptr.at(row, col - 2)[ch] }; // Calculate the gradients for each direction. let n = (x - n_2).abs() * 2.0 + (n_1 - s_1); let e = (x - e_2).abs() * 2.0 + (w_1 - e_1); let w = (x - w_2).abs() * 2.0 + (w_1 - e_1); let s = (x - s_2).abs() * 2.0 + (n_1 - s_1); // Find the minimum value of the gradients. let mut min = n; if e < min { min = e }; if w < min { min = w }; if s < min { min = s }; // The minimum gradient wins. let p_green = if min == n { (n_1 * 3.0 + s_1 + x - n_2) / 4.0 } else if min == e { (e_1 * 3.0 + w_1 + x - e_2) / 4.0 } else if min == w { (w_1 * 3.0 + e_1 + x - w_2) / 4.0 } else { (s_1 * 3.0 + n_1 + x - s_2) / 4.0 }; pixel[CFA_COLOR_G] = p_green; } } }); } /// PPG Demosaic: Interpolate R/B channel at G channels #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn interpolate_rb_at_green(img: &mut RgbF32, shifted: &CFA) { let w = img.width; let h = img.height; // Secondary data pointer, so we can have a mutable subslice reference // inside the par_* methods and a second immutable reference to the whole // image. This is not possible in Rust without unsafe code. let dataptr = img.data_ptr(); img.pixels_mut().par_chunks_exact_mut(w).enumerate().skip(3).take(h - 6).for_each(|(row, buf)| { for (col, pixel) in buf.iter_mut().enumerate().skip(3).take(w - 6) { if shifted.color_at(row, col) == CFA_COLOR_G { let h_ch = shifted.color_at(row, col + 1); // horizontal corresponding channel let v_ch = shifted.color_at(row + 1, col); // vertical corresponding channel // Green samples in all directions let g_x = pixel[CFA_COLOR_G]; let g_w = unsafe { dataptr.at(row, col - 1)[CFA_COLOR_G] }; let g_e = unsafe { dataptr.at(row, col + 1)[CFA_COLOR_G] }; let g_n = unsafe { dataptr.at(row - 1, col)[CFA_COLOR_G] }; let g_s = unsafe { dataptr.at(row + 1, col)[CFA_COLOR_G] }; // Horizontal samples for channel (R or B) let h_w = unsafe { dataptr.at(row, col - 1).get_unchecked(h_ch) }; let h_e = unsafe { dataptr.at(row, col + 1).get_unchecked(h_ch) }; // Vertial samples for channel (R or B) let v_n = unsafe { dataptr.at(row - 1, col).get_unchecked(v_ch) }; let v_s = unsafe { dataptr.at(row + 1, col).get_unchecked(v_ch) }; *unsafe { pixel.get_unchecked_mut(h_ch) } = hue_transit(g_w, g_x, g_e, *h_w, *h_e); *unsafe { pixel.get_unchecked_mut(v_ch) } = hue_transit(g_n, g_x, g_s, *v_n, *v_s); } } }); } /// PPG Demosaic: Interpolate R/B channel at non-G channels #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn interpolate_rb_at_non_green(img: &mut RgbF32, shifted: &CFA) { let w = img.width; let h = img.height; // Secondary data pointer, so we can have a mutable subslice reference // inside the par_* methods and a second immutable reference to the whole // image. This is not possible in Rust without unsafe code. let dataptr = img.data_ptr(); img.pixels_mut().par_chunks_exact_mut(w).enumerate().skip(3).take(h - 6).for_each(|(row, buf)| { for (col, pixel) in buf.iter_mut().enumerate().skip(3).take(w - 6) { if shifted.color_at(row, col) != CFA_COLOR_G { let x_ch = shifted.color_at(row, col); // current let y_ch = if x_ch == CFA_COLOR_R { CFA_COLOR_B } else { CFA_COLOR_R }; let y_ne_1 = unsafe { dataptr.at(row - 1, col + 1)[y_ch] }; let y_sw_1 = unsafe { dataptr.at(row + 1, col - 1)[y_ch] }; let x_ne_2 = unsafe { dataptr.at(row - 2, col + 2)[x_ch] }; let x_center = pixel[x_ch]; let x_sw_2 = unsafe { dataptr.at(row + 2, col - 2)[x_ch] }; let g_ne_1 = unsafe { dataptr.at(row - 1, col + 1)[CFA_COLOR_G] }; let g_center = pixel[CFA_COLOR_G]; let g_sw_1 = unsafe { dataptr.at(row + 1, col - 1)[CFA_COLOR_G] }; let y_nw_1 = unsafe { dataptr.at(row - 1, col - 1)[y_ch] }; let y_se_1 = unsafe { dataptr.at(row + 1, col + 1)[y_ch] }; let x_nw_2 = unsafe { dataptr.at(row - 2, col - 2)[x_ch] }; let x_se_2 = unsafe { dataptr.at(row + 2, col + 2)[x_ch] }; let g_nw_1 = unsafe { dataptr.at(row - 1, col - 1)[CFA_COLOR_G] }; let g_se_1 = unsafe { dataptr.at(row + 1, col + 1)[CFA_COLOR_G] }; let ne = (y_ne_1 - y_sw_1).abs() + (x_ne_2 - x_center).abs() + (x_center - x_sw_2).abs() + (g_ne_1 - g_center).abs() + (g_center - g_sw_1).abs(); let nw = (y_nw_1 - y_se_1).abs() + (x_nw_2 - x_center).abs() + (x_center - x_se_2).abs() + (g_nw_1 + g_center).abs() + (g_center - g_se_1).abs(); pixel[y_ch] = if ne < nw { hue_transit(g_ne_1, g_center, g_sw_1, y_ne_1, y_sw_1) } else { hue_transit(g_nw_1, g_center, g_se_1, y_nw_1, y_se_1) }; } } }); } /// PPG helper procedure to calculate hue transit #[inline(always)] fn hue_transit(l1: f32, l2: f32, l3: f32, v1: f32, v3: f32) -> f32 { if (l1 < l2 && l2 < l3) || (l1 > l2 && l2 > l3) { v1 + (v3 - v1) * (l2 - l1) / (l3 - l1) } else { (v1 + v3) / 2.0 + (l2 * 2.0 - l1 - l3) / 4.0 } } rawler-0.7.1/src/imgop/sensor/bayer/superpixel.rs000064400000000000000000000106411046102023000202120ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher use crate::{ CFA, cfa::PlaneColor, imgop::{Dim2, Rect, sensor::bayer::RgbBayerPattern}, pixarray::{Color2D, PixF32}, }; use rayon::prelude::*; use super::Demosaic; #[derive(Default)] pub struct Superpixel3Channel {} impl Superpixel3Channel { pub fn new() -> Self { Self {} } } impl Demosaic for Superpixel3Channel { /// Debayer image by using superpixel method. /// Each output pixel RGB tuple is generated by 4 pixels from input. /// The result image is 1/4 of size. fn demosaic(&self, pixels: &PixF32, cfa: &CFA, colors: &PlaneColor, roi: Rect) -> Color2D { if colors.plane_count() != 3 { panic!("Demosaic for 3 channels needs 3 color planes, but {} given", colors.plane_count()); } if !cfa.is_rgb() { panic!("Demosaic for 3 channels requires RGB CFA pattern, but CFA {} given", cfa); } // ROI width / height must be align on bayer pattern size, so deleting the rightmost bit will do the job. let roi = Rect::new(roi.p, Dim2::new(roi.width() & !1, roi.height() & !1)); let dim = pixels.dim(); log::debug!("Superpixel debayer ROI: {:?}", roi); let cfa = cfa.shift(roi.p.x, roi.p.y); let pattern = match cfa.name.as_str() { "RGGB" => RgbBayerPattern::RGGB, "BGGR" => RgbBayerPattern::BGGR, "GBRG" => RgbBayerPattern::GBRG, "GRBG" => RgbBayerPattern::GRBG, _ => unreachable!(), // Guarded by is_rgb() }; // Truncate ROI outer lines let window = &pixels[roi.y() * dim.w..roi.y() * dim.w + roi.height() * dim.w]; let out = window .par_chunks_exact(dim.w * 2) .map(|s| { let (r1, r2) = s.split_at(dim.w); // Truncate ROI outer columns let (r1, r2) = (&r1[roi.x()..roi.x() + roi.width()], &r2[roi.x()..roi.x() + roi.width()]); r1.chunks_exact(2) .zip(r2.chunks_exact(2)) .map(|(a, b)| { let p = [a[0], a[1], b[0], b[1]]; match pattern { RgbBayerPattern::RGGB => [p[0], (p[1] + p[2]) / 2.0, p[3]], RgbBayerPattern::BGGR => [p[3], (p[1] + p[2]) / 2.0, p[0]], RgbBayerPattern::GBRG => [p[2], (p[0] + p[3]) / 2.0, p[1]], RgbBayerPattern::GRBG => [p[1], (p[0] + p[3]) / 2.0, p[2]], } }) .collect::>() }) .flatten() .collect(); Color2D::new_with(out, roi.d.w >> 1, roi.d.h >> 1) } } #[derive(Default)] pub struct Superpixel4Channel {} impl Superpixel4Channel { pub fn new() -> Self { Self {} } } impl Demosaic for Superpixel4Channel { /// Debayer image by using superpixel method. /// Each output pixel RGB tuple is generated by 4 pixels from input. /// The result image is 1/4 of size. fn demosaic(&self, pixels: &PixF32, cfa: &CFA, colors: &PlaneColor, roi: Rect) -> Color2D { if colors.plane_count() != 4 { panic!("Demosaic for 4 channels needs 4 color planes, but {} given", colors.plane_count()); } // ROI width / height must be align on bayer pattern size, so deleting the rightmost bit will do the job. let roi = Rect::new(roi.p, Dim2::new(roi.width() & !1, roi.height() & !1)); log::debug!("Superpixel debayer ROI: {:?}", roi); let cfa = cfa.shift(roi.p.x, roi.p.y); let dim = pixels.dim(); // Index into colormap is plane number, value is the index into 2x2 Bayer superpixel. let colormap: [usize; 4] = colors.plane_colors::<4>().map(|c| PlaneColor::cfa_index(&cfa, c)); // Truncate ROI outer lines let window = &pixels[roi.y() * dim.w..roi.y() * dim.w + roi.height() * dim.w]; let out = window .par_chunks_exact(dim.w * 2) .map(|s| { let (r1, r2) = s.split_at(dim.w); // Truncate ROI outer columns let (r1, r2) = (&r1[roi.x()..roi.x() + roi.width()], &r2[roi.x()..roi.x() + roi.width()]); r1.chunks_exact(2) .zip(r2.chunks_exact(2)) .map(|(a, b)| { let superpixel = [a[0], a[1], b[0], b[1]]; // Map superpixel into correct ordering (CFAPlaneColor) [ superpixel[colormap[0]], superpixel[colormap[1]], superpixel[colormap[2]], superpixel[colormap[3]], ] }) .collect::>() }) .flatten() .collect(); Color2D::new_with(out, roi.d.w >> 1, roi.d.h >> 1) } } rawler-0.7.1/src/imgop/sensor/mod.rs000064400000000000000000000002021046102023000154570ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher pub mod bayer; pub mod xtrans; rawler-0.7.1/src/imgop/sensor/xtrans/mod.rs000064400000000000000000000002361046102023000170050ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher // This file is reserved for X-Trans specific sensor code. rawler-0.7.1/src/imgop/spline.rs000064400000000000000000000070111046102023000146660ustar 00000000000000use super::Point; // These are the constant factors for each segment of the curve. // Each segment i will have the formula: // f(x) = a[i] + b[i]*(x - x[i]) + c[i]*(x - x[i])^2 + d[i]*(x - x[i])^3 #[derive(Clone, Debug, Default)] struct Segment { a: f32, b: f32, c: f32, d: f32, } // This is a Natural Cubic Spline. The second derivative at curve ends are zero. // See https://en.wikipedia.org/wiki/Spline_(mathematics) // section "Algorithm for computing natural cubic splines" pub struct Spline { num_coords: usize, num_segments: usize, xcp: Vec, segments: Vec, } impl Spline { fn prepare(&mut self) { // Extra values used during computation let mut h = vec![0.0; self.num_segments]; let mut alpha = vec![0.0; self.num_segments]; let mut mu = vec![0.0; self.num_coords]; let mut z = vec![0.0; self.num_coords]; for i in 0..self.num_segments { h[i] = (self.xcp[i + 1] - self.xcp[i]) as f32; } for i in 1..self.num_segments { let sp = &self.segments[i - 1]; let s = &self.segments[i]; let sn = &self.segments[i + 1]; alpha[i] = (3. / h[i]) * (sn.a - s.a) - (3. / h[i - 1]) * (s.a - sp.a); } mu[0] = 1.0; z[0] = 0.0; for i in (0..self.num_segments).rev() { let sn = self.segments[i + 1].clone(); let s = &mut self.segments[i]; s.c = z[i] - mu[i] * sn.c; s.b = (sn.a - s.a) / h[i] - h[i] * (sn.c + 2. * s.c) / 3.; s.d = (sn.c - s.c) / (3. * h[i]); } // The last segment is nonsensical, and was only used to temporarily store // the a and c to simplify calculations, so drop that 'segment' now self.segments.pop(); assert_eq!(self.num_segments, self.segments.len()); } pub fn new(control_points: &[Point]) -> Self { assert!(control_points.len() >= 2, "Need at least two points to interpolate between"); assert_eq!(control_points.first().map(|p| p.x as u16), Some(u16::MIN)); assert_eq!(control_points.last().map(|p| p.x as u16), Some(u16::MAX)); let mut prev = 0; for p in control_points { if p.x < prev { panic!("err, p.x {} must be >= {}", p.x, prev); } prev = p.x; } // TODO: "The X coordinates must all be strictly increasing" // TODO: The Y coords must be limited to the range of value_type let num_coords = control_points.len(); let num_segments = num_coords - 1; let mut xcp = vec![0; num_coords]; let mut segments = vec![Segment::default(); num_coords]; for (i, cpoint) in control_points.iter().enumerate() { xcp[i] = cpoint.x; segments[i].a = cpoint.y as f32; } let mut val = Self { num_coords, num_segments, xcp, segments, }; val.prepare(); val } pub fn calculate_curve(self) -> Vec { let mut curve = vec![0; u16::MAX as usize + 1]; for (i, s) in self.segments.iter().enumerate() { for x in self.xcp[i]..=self.xcp[i + 1] { let diff = (x - self.xcp[i]) as f32; let diff_2 = (diff * diff) as f32; let diff_3 = (diff * diff * diff) as f32; let interpolated = s.a + s.b * diff + s.c * diff_2 + s.d * diff_3; curve[x] = interpolated as u16; } } curve } } #[cfg(test)] mod tests { use super::*; #[test] fn spline_test() -> std::result::Result<(), Box> { crate::init_test_logger(); let points = [Point::new(0, 0), Point::new(u16::MAX as usize, 10)]; let spline = Spline::new(&points); let _data = spline.calculate_curve(); Ok(()) } } rawler-0.7.1/src/imgop/srgb.rs000064400000000000000000000032071046102023000143340ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher use rayon::prelude::*; // Reference for sRGB: // // https://onlinelibrary.wiley.com/doi/pdf/10.1002/9781119021780.app8 // // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html // http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html // /// http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html // /// sRGB gamma const SRGB_GAMMA: f32 = 2.4; /// sRGB crossover point between linear and exponential part const SRGB_CROSSOVER_POINT: f32 = 0.00304; /// sRGB gain for linear part, specified for gamma 2.4 const LINEAR_GAIN: f32 = 12.92; /// sRGB gain for exponential part const SRGB_GAIN: f32 = 1.055; /// sRGB offset for exponential part const SRGB_OFFSET: f32 = SRGB_GAIN - 1.0; // 0.055 /// Apply sRGB gamma pub fn srgb_apply_gamma(v: f32) -> f32 { if v <= SRGB_CROSSOVER_POINT { v * LINEAR_GAIN } else { v.powf(1.0 / SRGB_GAMMA) * SRGB_GAIN - SRGB_OFFSET } } /// Apply sRGB gamma pub fn srgb_apply_gamma_n(v: [f32; N]) -> [f32; N] { v.map(srgb_apply_gamma) } /// Invert sRGB gamma correction pub fn srgb_invert_gamma(v: f32) -> f32 { if v <= SRGB_CROSSOVER_POINT * LINEAR_GAIN { v / LINEAR_GAIN } else { ((v + SRGB_OFFSET) / SRGB_GAIN).powf(SRGB_GAMMA) } } /// Apply gamma correction to whole buffer pub fn srgb_apply_gamma_inplace(pixels: &mut [f32]) { pixels.par_iter_mut().for_each(|p| *p = srgb_apply_gamma(*p)); } /// Invert gamma correction to whole buffer pub fn srgb_invert_gamma_inplace(pixels: &mut [f32]) { pixels.par_iter_mut().for_each(|p| *p = srgb_invert_gamma(*p)); } rawler-0.7.1/src/imgop/xyz.rs000064400000000000000000000147351046102023000142410ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher use std::convert::TryFrom; /// Illuminants for XYZ #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Illuminant { Unknown = 0, Daylight = 1, Fluorescent = 2, Tungsten = 3, Flash = 4, FineWeather = 9, CloudyWeather = 10, Shade = 11, DaylightFluorescent = 12, DaylightWhiteFluorescent = 13, CoolWhiteFluorescent = 14, WhiteFluorescent = 15, A = 17, B = 18, C = 19, D55 = 20, D65 = 21, D75 = 22, D50 = 23, IsoStudioTungsten = 24, } pub type FlatColorMatrix = Vec; impl TryFrom for Illuminant { type Error = String; fn try_from(v: u16) -> Result { Ok(match v { 0 => Self::Unknown, 1 => Self::Daylight, 2 => Self::Fluorescent, 3 => Self::Tungsten, 4 => Self::Flash, 9 => Self::FineWeather, 10 => Self::CloudyWeather, 11 => Self::Shade, 12 => Self::DaylightFluorescent, 13 => Self::DaylightWhiteFluorescent, 14 => Self::CoolWhiteFluorescent, 15 => Self::WhiteFluorescent, 17 => Self::A, 18 => Self::B, 19 => Self::C, 20 => Self::D55, 21 => Self::D65, 22 => Self::D75, 23 => Self::D50, 24 => Self::IsoStudioTungsten, _ => { return Err(format!("Unknown illuminant value: {}", v)); } }) } } impl From for u16 { fn from(value: Illuminant) -> Self { value as u16 } } impl Illuminant { pub fn new_from_str(s: &str) -> Result { match s { "Unknown" => Ok(Self::Unknown), "Daylight" => Ok(Self::Daylight), "Fluorescent" => Ok(Self::Fluorescent), "Tungsten" => Ok(Self::Tungsten), "Flash" => Ok(Self::Flash), "FineWeather" => Ok(Self::FineWeather), "CloudyWeather" => Ok(Self::CloudyWeather), "Shade" => Ok(Self::Shade), "DaylightFluorescent" => Ok(Self::DaylightFluorescent), "DaylightWhiteFluorescent" => Ok(Self::DaylightWhiteFluorescent), "CoolWhiteFluorescent" => Ok(Self::CoolWhiteFluorescent), "WhiteFluorescent" => Ok(Self::WhiteFluorescent), "A" => Ok(Self::A), "B" => Ok(Self::B), "C" => Ok(Self::C), "D55" => Ok(Self::D55), "D65" => Ok(Self::D65), "D75" => Ok(Self::D75), "D50" => Ok(Self::D50), "IsoStudioTungsten" => Ok(Self::IsoStudioTungsten), _ => Err(format!("Unknown illuminant name: '{}'", s)), } } } // Constant matrix for converting sRGB to XYZ(D65): // http://www.brucelindbloom.com/Eqn_RGB_XYZ_Matrix.html #[allow(clippy::excessive_precision)] pub const SRGB_TO_XYZ_D65: [[f32; 3]; 3] = [ [0.4124564, 0.3575761, 0.1804375], [0.2126729, 0.7151522, 0.0721750], [0.0193339, 0.1191920, 0.9503041], ]; #[allow(clippy::excessive_precision)] pub const XYZ_TO_ADOBERGB_D65: [[f32; 3]; 3] = [ [2.0413690, -0.5649464, -0.3446944], [-0.9692660, 1.8760108, 0.0415560], [0.0134474, -0.1183897, 1.0154096], ]; #[allow(clippy::excessive_precision)] pub const XYZ_TO_ADOBERGB_D50: [[f32; 3]; 3] = [ [1.9624274, -0.6105343, -0.3413404], [-0.9787684, 1.9161415, 0.0334540], [0.0286869, -0.1406752, 1.3487655], ]; #[allow(clippy::excessive_precision)] pub const XYZ_TO_SRGB_D50: [[f32; 3]; 3] = [ [3.1338561, -1.6168667, -0.4906146], [-0.9787684, 1.9161415, 0.0334540], [0.0719453, -0.2289914, 1.4052427], ]; #[allow(clippy::excessive_precision)] pub const XYZ_TO_SRGB_D65: [[f32; 3]; 3] = [ [3.2404542, -1.5371385, -0.4985314], [-0.9692660, 1.8760108, 0.0415560], [0.0556434, -0.2040259, 1.0572252], ]; #[allow(clippy::excessive_precision)] pub const XYZ_TO_PROFOTORGB_D50: [[f32; 3]; 3] = [ [1.3459433, -0.2556075, -0.0511118], [-0.5445989, 1.5081673, 0.0205351], [0.0000000, 0.0000000, 1.2118128], ]; pub const CIE_1931_TRISTIMULUS_A: [f32; 3] = [1.09850, 1.00000, 0.35585]; // X, Y, Z pub const CIE_1931_TRISTIMULUS_B: [f32; 3] = [0.99072, 1.00000, 0.85223]; // X, Y, Z pub const CIE_1931_TRISTIMULUS_C: [f32; 3] = [0.98074, 1.00000, 1.18232]; // X, Y, Z pub const CIE_1931_TRISTIMULUS_D50: [f32; 3] = [0.96422, 1.00000, 0.82521]; // X, Y, Z pub const CIE_1931_TRISTIMULUS_D55: [f32; 3] = [0.95682, 1.00000, 0.92149]; // X, Y, Z pub const CIE_1931_TRISTIMULUS_D65: [f32; 3] = [0.95047, 1.00000, 1.08883]; // X, Y, Z pub const CIE_1931_TRISTIMULUS_D75: [f32; 3] = [0.94972, 1.00000, 1.22638]; // X, Y, Z pub const CIE_1931_TRISTIMULUS_E: [f32; 3] = [1.00000, 1.00000, 1.00000]; // X, Y, Z pub const CIE_1931_TRISTIMULUS_F2: [f32; 3] = [0.99186, 1.00000, 0.67393]; // X, Y, Z pub const CIE_1931_TRISTIMULUS_F7: [f32; 3] = [0.95041, 1.00000, 1.08747]; // X, Y, Z pub const CIE_1931_TRISTIMULUS_F11: [f32; 3] = [1.00962, 1.00000, 0.64350]; // X, Y, Z /// incandescent / tungsten pub const CIE_1931_WHITE_POINT_A: (f32, f32) = (0.44757, 0.40745); /// obsolete, direct sunlight at noon pub const CIE_1931_WHITE_POINT_B: (f32, f32) = (0.34842, 0.35161); /// obsolete, average / North sky daylight pub const CIE_1931_WHITE_POINT_C: (f32, f32) = (0.31006, 0.31616); /// horizon light, ICC profile PCS pub const CIE_1931_WHITE_POINT_D50: (f32, f32) = (0.34567, 0.35850); /// mid-morning / mid-afternoon daylight pub const CIE_1931_WHITE_POINT_D55: (f32, f32) = (0.33242, 0.34743); /// noon daylight: television, sRGB color space pub const CIE_1931_WHITE_POINT_D65: (f32, f32) = (0.31271, 0.32902); /// North sky daylight pub const CIE_1931_WHITE_POINT_D75: (f32, f32) = (0.29902, 0.31485); /// high-efficiency blue phosphor monitors, BT.2035 pub const CIE_1931_WHITE_POINT_D93: (f32, f32) = (0.28315, 0.29711); /// equal energy pub const CIE_1931_WHITE_POINT_E: (f32, f32) = (0.33333, 0.33333); #[allow(non_snake_case)] pub fn xyY_to_XYZ(x: f32, y: f32, Y: f32) -> [f32; 3] { if y.is_normal() && y.is_sign_positive() { [x * Y / y, Y, (1.0 - x - y) * Y / y] } else { panic!("xy_to_XYZ(): 'y' argument must be greater than zero"); } } #[allow(non_snake_case)] pub fn xy_to_XYZ(x: f32, y: f32) -> [f32; 3] { const Y: f32 = 1.0; xyY_to_XYZ(x, y, Y) } /// Convert a given xy whitepoint to white balance coefficents, /// adapted to pub fn xy_whitepoint_to_wb_coeff(x: f32, y: f32, colormatrix: &[[f32; 3]; 3]) -> [f32; 3] { let mut result = [0.0, 0.0, 0.0]; if y > 0.0 { let as_shot_white = xy_to_XYZ(x, y); for i in 0..3 { let c = colormatrix[i][0] * as_shot_white[0] + colormatrix[i][1] * as_shot_white[1] + colormatrix[i][2] * as_shot_white[2]; if c > 0.0 { result[i] = 1.0 / c; } } } result } rawler-0.7.1/src/imgop/yuv.rs000064400000000000000000000054151046102023000142250ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2022 Daniel Vogelbacher use crate::bits::clampbits; use rayon::prelude::*; /// Color conversion for Y Cb Cr to RGB /// /// Matrix source: https://web.archive.org/web/20180421030430/http://www.equasys.de/colorconversion.html pub fn ycbcr_to_rgb(buf: &mut [u16]) { let cpp = 3; assert_eq!(buf.len() % cpp, 0, "pixel buffer must contains 3 samples/pixel"); // Correction value to bring cb and cr into range. // This assumes the range is 2^15. For a 2^8 range this would be 128. let corr: i32 = 16383; //let corr: i32 = (16383 << 1) | 1; buf.par_chunks_exact_mut(cpp).for_each(|pix| { let y = pix[0] as f32; let cb = (pix[1] as i32 - corr) as f32; let cr = (pix[2] as i32 - corr) as f32; //let cb = 100.0; //let cr = 100.0; let r = y + 1.4 * cr; let g = y + (-0.343 * cb) + (-0.711 * cr); let b = y + 1.765 * cb; pix[0] = clampbits(r as i32, 16); pix[1] = clampbits(g as i32, 16); pix[2] = clampbits(b as i32, 16); }) } /// Interpolate YCbCr (YUV) data pub fn interpolate_yuv(super_h: usize, super_v: usize, width: usize, _height: usize, image: &mut [u16]) { if super_h == 1 && super_v == 1 { return; // No interpolation needed } // Iterate over a block of 3 rows, smaller chunks are okay // but must always a multiple of row width. image.par_chunks_mut(width * 3).for_each(|slice| { // Do horizontal interpolation. // [y1 Cb Cr ] [ y2 . . ] [y1 Cb Cr ] [ y2 . . ] ... if super_h == 2 { debug_assert_eq!(slice.len() % width, 0); for row in 0..(slice.len() / width) { for col in (6..width).step_by(6) { let pix1 = row * width + col - 6; let pix2 = pix1 + 3; let pix3 = row * width + col; slice[pix2 + 1] = ((slice[pix1 + 1] as i32 + slice[pix3 + 1] as i32 + 1) / 2) as u16; slice[pix2 + 2] = ((slice[pix1 + 2] as i32 + slice[pix3 + 2] as i32 + 1) / 2) as u16; } } } // Do vertical interpolation // pixel n pixel n+1 pixel n+2 pixel n+3 ... // row i : [y1 Cb Cr ] [ y2 Cb* Cr* ] [y1 Cb Cr ] [ y2 Cb* Cr* ] ... // row i+1: [y3 Cb* Cr*] [ y4 Cb** Cr**] [y3 Cb* Cr*] [ y4 Cb** Cr**] ... // row i+2: [y1 Cb Cr ] [ y2 Cb* Cr* ] [y1 Cb Cr ] [ y2 Cb* Cr* ] ... // row i+3: [y3 Cb* Cr*] [ y4 Cb** Cr**] [y3 Cb* Cr*] [ y4 Cb** Cr**] ... if super_v == 2 && slice.len() == width * 3 { for col in (0..width).step_by(3) { let pix1 = col; let pix2 = width + col; let pix3 = 2 * width + col; slice[pix2 + 1] = ((slice[pix1 + 1] as i32 + slice[pix3 + 1] as i32 + 1) / 2) as u16; slice[pix2 + 2] = ((slice[pix1 + 2] as i32 + slice[pix3 + 2] as i32 + 1) / 2) as u16; } } }); } rawler-0.7.1/src/lens.rs000064400000000000000000000312251046102023000132260ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher use std::fmt::Display; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; use toml::Value; use crate::{decoders::Camera, formats::tiff::Rational}; pub static LENSES_TOML: &str = include_str!(concat!(env!("OUT_DIR"), "/lenses.toml")); const FAIL: &str = "Invalid lens database"; lazy_static! { static ref LENSES_DB: Vec = build_lens_database().expect(FAIL); } pub fn get_lenses() -> &'static Vec { &LENSES_DB } /// Resolver for Lens information #[derive(Default, Debug, Clone)] pub struct LensResolver { /// Unique lens keyname, if known lens_keyname: Option, /// Name of the lens make, if known lens_make: Option, /// Name of the lens model, if known lens_model: Option, /// Lens ID, if known lens_id: Option, /// Nikon ID nikon_id: Option, /// Olympus ID olympus_id: Option, /// Lens EXIF info, if known lens_info: Option<[Rational; 4]>, /// Camera make, if known camera_make: Option, /// Camera model, if known camera_model: Option, /// Mounts, if known mounts: Option>, /// Focal lenth for taken photo focal_len: Option, /// Aperture for taken photo aperture: Option, } #[allow(dead_code)] struct LensMatcher<'a> { /// Name of the lens model, if known lens_name: Option<&'a str>, /// Name of the lens make, if known lens_make: Option<&'a str>, /// Lens ID, if known lens_id: Option, /// Nikon ID nikon_id: Option, /// Olympus ID olympus_id: Option, /// Lens EXIF info, if known lens_info: Option<[Rational; 4]>, /// Camera make, if known camera_make: Option<&'a str>, /// Camera model, if known camera_model: Option<&'a str>, /// Mounts, if known mounts: Option<&'a [String]>, /// Focal lenth for taken photo #[allow(dead_code)] focal_len: Option, } impl LensResolver { /// Create new empty LensResolver pub fn new() -> Self { Self::default() } pub fn with_camera(mut self, camera: &Camera) -> Self { self.camera_make = Some(camera.clean_make.clone()); self.camera_model = Some(camera.clean_model.clone()); // For cameras with fixed lens, an optional camera param can be specified // which is the key into the lens database. if let Some(key) = camera.param_str("fixed_lens_key").map(String::from) { self.lens_keyname = Some(key); } self } pub fn with_lens_keyname>(mut self, lens_name: Option) -> Self { self.lens_keyname = lens_name.map(|v| v.as_ref().into()); self } pub fn with_lens_make>(mut self, lens_make: Option) -> Self { self.lens_make = lens_make.map(|v| v.as_ref().into()); self } pub fn with_lens_model>(mut self, lens_model: Option) -> Self { self.lens_model = lens_model.map(|v| v.as_ref().into()); self } pub fn with_mounts(mut self, mounts: &[String]) -> Self { self.mounts = Some(mounts.to_vec()); self } pub fn with_lens_id(mut self, lens_id: LensId) -> Self { self.lens_id = Some(lens_id); self } pub fn with_nikon_id(mut self, nikon_id: Option) -> Self { self.nikon_id = nikon_id; self } pub fn with_olympus_id(mut self, olympus_id: Option) -> Self { self.olympus_id = olympus_id; self } pub fn with_focal_len(mut self, focal_len: Option) -> Self { self.focal_len = focal_len; self } pub fn with_aperture(mut self, aperture: Option) -> Self { self.aperture = aperture; self } pub fn with_lens_info(mut self, lens_info: [Rational; 4]) -> Self { self.lens_info = Some(lens_info); self } pub fn with_camera_make>(mut self, camera_make: T) -> Self { self.camera_make = Some(camera_make.as_ref().into()); self } pub fn with_camera_model>(mut self, camera_model: T) -> Self { self.camera_model = Some(camera_model.as_ref().into()); self } fn lens_matcher(&self) -> LensMatcher<'_> { LensMatcher { lens_name: self.lens_keyname.as_deref(), lens_make: self.lens_make.as_deref(), lens_id: self.lens_id, nikon_id: self.nikon_id.clone(), olympus_id: self.olympus_id.clone(), lens_info: self.lens_info, camera_make: self.camera_make.as_deref(), camera_model: self.camera_model.as_deref(), mounts: self.mounts.as_deref(), focal_len: self.focal_len, } } /// Resolve to a final LensDescription /// /// Returns None, if resolver was unable to find a lens. pub fn resolve(&self) -> Option<&'static LensDescription> { let first_try = self.resolve_internal(); if first_try.is_some() { first_try } else { let second_try = match self.lens_matcher() { // Pentax *ist D and DS reports some lens as id=4 while it should be 7. LensMatcher { camera_model: Some("*ist DS"), lens_id: Some((4, subid)), .. } | LensMatcher { camera_model: Some("*ist D"), lens_id: Some((4, subid)), .. } => self.clone().with_lens_id((7, subid)).resolve_internal(), _ => None, }; if second_try.is_none() { log::warn!("No lens definition found in database, search parameters: {}. {}", self, crate::ISSUE_HINT); if std::env::var("RAWLER_FAIL_NO_LENS").ok().map(|val| val == "1").unwrap_or(false) { panic!("No lens definition found in database, search parameters: {}.", self); } } second_try } } /// Resolve the lens internally. fn resolve_internal(&self) -> Option<&'static LensDescription> { // First try, if we have an exact name, we use just this if let Some(name) = self.lens_keyname.as_ref().filter(|s| !s.is_empty()) { if let Some(db_entry) = LENSES_DB.iter().find(|entry| entry.identifiers.name == Some(name.into())) { return Some(db_entry); } } // Nikon lens IDs are special, try this next if let Some(nikon_id) = &self.nikon_id { if let Some(db_entry) = LENSES_DB.iter().find(|entry| entry.identifiers.nikon_id == Some(nikon_id.clone())) { return Some(db_entry); } } // Olympus lens IDs are special, try this next if let Some(olympus_id) = &self.olympus_id { if let Some(db_entry) = LENSES_DB.iter().find(|entry| entry.identifiers.olympus_id == Some(olympus_id.clone())) { return Some(db_entry); } } // If we have a lens id (common) then we can filter as much as possible let matches: Vec<&LensDescription> = LENSES_DB .iter() .filter(|entry| self.mounts.as_ref().is_none_or(|mounts| mounts.contains(&entry.mount))) .filter(|entry| { self .lens_id .as_ref() .is_none_or(|id| entry.identifiers.id.as_ref().is_some_and(|entry_id| *entry_id == *id)) }) .filter(|entry| self.lens_make.as_ref().is_none_or(|make| entry.lens_make == *make)) .filter(|entry| self.lens_model.as_ref().is_none_or(|model| entry.lens_model == *model)) .filter(|entry| { self .focal_len .as_ref() .is_none_or(|focal| *focal >= entry.focal_range[0] && *focal <= entry.focal_range[1]) }) .filter(|entry| { self .aperture .as_ref() .is_none_or(|ap| *ap >= entry.aperture_range[0] || *ap <= entry.aperture_range[1]) }) .collect(); match matches.len() { 1 => return Some(matches[0]), c if c > 1 => { log::warn!( "Found multiple ({}) lens definitions, unable to determine which lens to use. {}", c, crate::ISSUE_HINT ); for lens in matches { log::warn!("Possible lens: {} {}", lens.lens_make, lens.lens_model); } } _ => {} } None } } impl Display for LensResolver { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut s = Vec::new(); if let Some(mount) = &self.mounts { s.push(format!("Mounts: {:?}", mount)); } if let Some(id) = &self.lens_id { s.push(format!("ID: '{}:{}'", id.0, id.1)); } if let Some(name) = &self.lens_keyname { s.push(format!("Keyname: '{}'", name)); } if let Some(name) = &self.lens_make { s.push(format!("Make: '{}", name)); } if let Some(name) = &self.lens_model { s.push(format!("Model: '{}'", name)); } if let Some(name) = &self.focal_len { s.push(format!("Focal len: '{}'", name)); } if s.is_empty() { f.write_str("") } else { f.write_str(&s.join(", ")) } } } pub type LensId = (u32, u32); #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct LensIdentifier { pub name: Option, pub id: Option, pub nikon_id: Option, pub olympus_id: Option, } impl LensIdentifier { pub(crate) fn new(name: Option, id: Option, nikon_id: Option, olympus_id: Option) -> Self { if name.is_some() || id.is_some() || nikon_id.is_some() || olympus_id.is_some() { Self { name, id, nikon_id, olympus_id, } } else { panic!("LensIdentifier must contain a name or id"); } } } /// Description of a lens #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct LensDescription { /// Identifiers pub identifiers: LensIdentifier, /// Lens mount pub mount: String, /// Lens make pub lens_make: String, /// Lens model (without make) pub lens_model: String, /// Focal range (min, max) pub focal_range: [Rational; 2], /// Aperture range (for min focal and max focal) pub aperture_range: [Rational; 2], /// Full qualified model name (with make) pub lens_name: String, } /// Internal function to parse and build global lens database fn build_lens_database() -> Option> { let toml = match LENSES_TOML.parse::() { Ok(val) => val, Err(e) => panic!("{}", format!("Error parsing lenses.toml: {:?}", e)), }; let mut lenses = Vec::new(); for lens in toml.get("lenses")?.as_array()? { //let key = lens.get("key")?.as_str()?.into(); let id_name = lens.get("key").and_then(Value::as_str).map(String::from); let id_val1 = lens.get("lens_id").and_then(Value::as_integer).map(|v| v as u32); let id_val2 = lens.get("lens_subid").and_then(Value::as_integer).map(|v| v as u32); let id_id = id_val1.map(|id| (id, id_val2.unwrap_or(0))); let nikon_id = lens.get("nikon_id").and_then(Value::as_str).map(String::from); let olympus_id = lens.get("olympus_id").and_then(Value::as_str).map(String::from); let mount = lens.get("mount").and_then(|val| val.as_str()).expect(FAIL); let lens_make = lens.get("make")?.as_str()?.into(); let lens_model = lens.get("model")?.as_str()?.into(); let focal_range: Vec = lens .get("focal_range")? .as_array()? .iter() .map(|v| { let v = v.as_array().expect(FAIL); let r1 = v.get(0).expect("Invalid lens database").as_integer().expect(FAIL) as u32; let r2 = v.get(1).expect(FAIL).as_integer().expect(FAIL) as u32; Rational::new(r1, r2) }) .collect(); let aperture_range: Vec = lens .get("aperture_range")? .as_array()? .iter() .map(|v| { let v = v.as_array().expect(FAIL); let r1 = v.get(0).expect(FAIL).as_integer().expect(FAIL) as u32; let r2 = v.get(1).expect(FAIL).as_integer().expect(FAIL) as u32; Rational::new(r1, r2) }) .collect(); let lens_name = lens.get("name").map(|s| s.as_str().expect(FAIL)); lenses.push(LensDescription { identifiers: LensIdentifier::new(id_name, id_id, nikon_id, olympus_id), lens_name: lens_name.unwrap_or(&format!("{} {}", lens_make, lens_model)).into(), mount: String::from(mount), lens_make, lens_model, focal_range: [focal_range[0], focal_range[1]], aperture_range: [aperture_range[0], aperture_range[1]], }); } Some(lenses) } #[cfg(test)] mod tests { use super::*; #[test] fn resolve_single_lens() -> std::result::Result<(), Box> { let resolver = LensResolver::new() .with_lens_make(Some("Canon")) .with_lens_keyname(Some("RF15-35mm F2.8 L IS USM")); let lens = resolver.resolve(); assert!(lens.is_some()); assert_eq!(lens.expect("No lens").lens_make, "Canon"); assert_eq!(lens.expect("No lens").lens_model, "RF 15-35mm F2.8L IS USM"); assert_eq!(lens.expect("No lens").lens_name, "Canon RF 15-35mm F2.8L IS USM"); Ok(()) } } rawler-0.7.1/src/lib.rs000064400000000000000000000156001046102023000130320ustar 00000000000000//! Library to extract the raw data and some metadata from digital camera //! images. Given an image in a supported format and camera you will be able to get //! everything needed to process the image //! //! # Example //! ```rust,no_run //! use std::env; //! use std::fs::File; //! use std::io::prelude::*; //! use std::io::BufWriter; //! //! fn main() { //! let args: Vec<_> = env::args().collect(); //! if args.len() != 2 { //! println!("Usage: {} ", args[0]); //! std::process::exit(2); //! } //! let file = &args[1]; //! let image = rawler::decode_file(file).unwrap(); //! //! // Write out the image as a grayscale PPM //! let mut f = BufWriter::new(File::create(format!("{}.ppm",file)).unwrap()); //! let preamble = format!("P6 {} {} {}\n", image.width, image.height, 65535).into_bytes(); //! f.write_all(&preamble).unwrap(); //! if let rawler::RawImageData::Integer(data) = image.data { //! for pix in data { //! // Do an extremely crude "demosaic" by setting R=G=B //! let pixhigh = (pix>>8) as u8; //! let pixlow = (pix&0x0f) as u8; //! f.write_all(&[pixhigh, pixlow, pixhigh, pixlow, pixhigh, pixlow]).unwrap() //! } //! } else { //! eprintln!("Don't know how to process non-integer raw files"); //! } //! } //! ``` #![deny( //missing_docs, unstable_features, //unused_import_braces, //unused_qualifications )] // Clippy configuration #![allow( clippy::needless_doctest_main, clippy::identity_op, // we often use x + 0 to better document an algorithm clippy::too_many_arguments, clippy::bool_assert_comparison, clippy::upper_case_acronyms, clippy::eq_op, clippy::needless_range_loop, clippy::manual_range_patterns, clippy::unnecessary_cast, clippy::get_first, clippy::vec_init_then_push, clippy::only_used_in_recursion, //clippy::seek_from_current, // TODO clippy::needless_lifetimes, clippy::type_complexity, //clippy::cast_abs_to_unsigned, //clippy::needless_return, //clippy::derivable_impls, //clippy::useless_vec, )] use decoders::Camera; use decoders::Decoder; use decoders::RawDecodeParams; use formats::jfif::JfifError; use lazy_static::lazy_static; pub mod analyze; pub mod bitarray; pub mod bits; pub mod buffer; pub mod cfa; pub mod decoders; pub mod decompressors; pub mod devtools; pub mod dng; pub(crate) mod envparams; pub mod exif; pub mod formats; pub mod imgop; pub mod lens; pub mod ljpeg92; pub mod packed; pub mod pixarray; pub mod pumps; pub mod rawimage; pub mod rawsource; pub mod tags; pub mod tiles; #[doc(hidden)] pub use cfa::CFA; pub use decoders::Orientation; #[doc(hidden)] pub use decoders::RawLoader; use formats::tiff::TiffError; pub use rawimage::RawImage; pub use rawimage::RawImageData; use rawsource::RawSource; lazy_static! { static ref LOADER: RawLoader = decoders::RawLoader::new(); } use std::io::Read; use std::io::Seek; use std::path::Path; use thiserror::Error; pub(crate) const ISSUE_HINT: &str = "Please open an issue at https://github.com/dnglab/dnglab/issues and provide this message (optionally the RAW file, if you can license it under CC0-license)."; pub trait ReadTrait: Read + Seek {} impl ReadTrait for T {} #[derive(Error, Debug)] pub enum RawlerError { #[error("Error: {}, model '{}', make: '{}', mode: '{}'", what, model, make, mode)] Unsupported { what: String, model: String, make: String, mode: String }, #[error("Failed to decode image, possibly corrupt image. Origin error was: {}", _0)] DecoderFailed(String), } pub type Result = std::result::Result; impl RawlerError { pub fn unsupported(camera: &Camera, what: impl AsRef) -> Self { Self::Unsupported { what: what.as_ref().to_string(), model: camera.model.clone(), make: camera.make.clone(), mode: camera.mode.clone(), } } pub fn with_io_error(context: impl AsRef, path: impl AsRef, error: std::io::Error) -> Self { Self::DecoderFailed(format!( "I/O error in context '{}', {} on file: {}", context.as_ref(), error, path.as_ref().display() )) } } impl From for RawlerError { fn from(err: std::io::Error) -> Self { log::error!("I/O error: {}", err.to_string()); log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new()); Self::DecoderFailed(format!("I/O Error without context: {}", err)) } } impl From<&String> for RawlerError { fn from(str: &String) -> Self { Self::DecoderFailed(str.clone()) } } impl From<&str> for RawlerError { fn from(str: &str) -> Self { Self::DecoderFailed(str.to_string()) } } impl From> for RawlerError { fn from(fmt: std::fmt::Arguments) -> Self { Self::DecoderFailed(fmt.to_string()) } } impl From for RawlerError { fn from(str: String) -> Self { Self::DecoderFailed(str) } } impl From for RawlerError { fn from(err: TiffError) -> Self { Self::DecoderFailed(err.to_string()) } } impl From for RawlerError { fn from(err: JfifError) -> Self { Self::DecoderFailed(err.to_string()) } } /// Take a path to a raw file and return a decoded image or an error /// /// # Example /// ```rust,ignore /// let image = match rawler::decode_file("path/to/your/file.RAW") { /// Ok(val) => val, /// Err(e) => ... some appropriate action when the file is unreadable ... /// }; /// ``` pub fn decode_file>(path: P) -> Result { LOADER.decode_file(path.as_ref()) } /// Take a readable source and return a decoded image or an error /// /// # Example /// ```rust,ignore /// let mut file = match File::open(path).unwrap(); /// let image = match rawler::decode(&mut file) { /// Ok(val) => val, /// Err(e) => ... some appropriate action when the file is unreadable ... /// }; /// ``` pub fn decode(rawfile: &RawSource, params: &RawDecodeParams) -> Result { LOADER.decode(rawfile, params, false) } // Used to force lazy_static initializations. Useful for fuzzing. #[doc(hidden)] pub fn force_initialization() { lazy_static::initialize(&LOADER); } // Used for fuzzing targets that just want to test the actual decoders instead of the full formats // with all their TIFF and other crazyness #[doc(hidden)] pub fn decode_unwrapped(rawfile: &RawSource) -> Result { LOADER.decode_unwrapped(rawfile) } // Used for fuzzing everything but the decoders themselves #[doc(hidden)] pub fn decode_dummy(rawfile: &RawSource) -> Result { LOADER.decode(rawfile, &RawDecodeParams::default(), true) } pub fn get_decoder(rawfile: &RawSource) -> Result> { LOADER.get_decoder(rawfile) } pub fn raw_image_count_file>(path: P) -> Result { LOADER.raw_image_count_file(path.as_ref()) } pub fn global_loader() -> &'static RawLoader { &LOADER } #[cfg(test)] pub(crate) fn init_test_logger() { let _ = env_logger::builder().is_test(true).filter_level(log::LevelFilter::Debug).try_init(); } rawler-0.7.1/src/ljpeg92.rs000064400000000000000000001354571046102023000135550ustar 00000000000000// Lossless JPEG encoder for 1-component // ITU T.81 Annex H from 1992 // // Originally written by Andrew Baldwin as lj92.c // Ported to Rust by Daniel Vogelbacher // // (c) 2014 Andrew Baldwin // (c) 2021 Daniel Vogelbacher // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies // of the Software, and to permit persons to whom the Software is furnished to do // so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. use byteorder::{BigEndian, WriteBytesExt}; use multiversion::multiversion; use std::{ cmp::min, io::{Cursor, Write}, }; use thiserror::Error; use crate::{bitarray::BitArray16, inspector}; /// Cache for bit count table. const NUM_BITS_TBL: [u16; 256] = build_num_bits_tbl(); /// Construct a cache table for bit count lookup. /// Code logic copied from Adobe DNG SDK. const fn build_num_bits_tbl() -> [u16; 256] { let mut tbl = [0; 256]; let mut i = 1; loop { if i < 256 { let mut nbits = 1; let mut tmp = i; loop { tmp >>= 1; if tmp != 0 { nbits += 1; } else { break; } } tbl[i] = nbits; i += 1; } else { break; } } tbl } /// Find the number of bits needed for the magnitude of the coefficient /// This utilizes the caching table which should be faster than /// calculating it manually. fn lookup_ssss(diff: i16) -> u16 { let diff_abs = (diff as i32).unsigned_abs() as usize; // Convert to i32 because abs() can be overflow i16 if diff_abs >= 256 { NUM_BITS_TBL[(diff_abs >> 8) & 0xFF] + 8 } else { NUM_BITS_TBL[diff_abs & 0xFF] } // manual way: // let ssss = if diff == 0 { 0 } else { 32 - (diff as i32).abs().leading_zeros() }; } #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] pub enum Predictor { P1 = 1, P2 = 2, P3 = 3, P4 = 4, P5 = 5, P6 = 6, P7 = 7, } impl Predictor { fn as_u8(&self) -> u8 { *self as u8 } } impl From for Predictor { fn from(v: u8) -> Self { match v { 1 => Self::P1, 2 => Self::P2, 3 => Self::P3, 4 => Self::P4, 5 => Self::P5, 6 => Self::P6, 7 => Self::P7, mode => panic!("Invalid predictor mode: {}", mode), } } } /// Error variants for compressor #[derive(Debug, Error)] pub enum CompressorError { /// Overflow of input, size constraints... #[error("Overflow error: {}", _0)] Overflow(String), /// Error on internal cursor type #[error("I/O error")] Io(#[from] std::io::Error), } /// Result type for Compressor results type Result = std::result::Result; /// Encoder for Lossless JPEG /// /// With this type you can get a instance of `LjpegCompressor`. /// The encode() method consumes the instance and /// returns the encoded JPEG data. pub struct LjpegCompressor<'a> { /// Raw image input image: &'a [u16], /// Width of input image width: usize, /// height of input image height: usize, /// Number of components (1-4, only 1 is supported) components: usize, /// Bitdepth of input image bitdepth: u8, /// Point transformation parameter /// **Warning:** This is untested, use with caution point_transform: u8, /// Predictor predictor: Predictor, /// Extra width after each line before next line starts padding: usize, /// Component state (histogram, hufftable) comp_state: Vec, cache: Vec, } /// HUFFENC and HUFFBITS #[derive(Debug, Default, Clone)] struct HuffCode { enc: u16, bits: u16, } /// Huffman table builder /// /// Builds an optimal Huffman table for encoding for a given /// list of frequencies and total resolution. #[derive(Default, Debug)] struct HuffTableBuilder { /// Frequency of occurrence of symbol V /// Used while building the table. Initialized with the /// frequencies for each ssss (0-16). /// Reserving one code point guarantees that no code word can ever be all “1” bits. freq: [f32; Self::CLASSES + 1], /// Code size of symbol V /// Size (in bits) for each ssss. codesize: [usize; Self::CLASSES + 1], /// Index to next symbol in chain of all symbols in current branch of code tree /// Other frequencies, used during table buildup. others: [Option; Self::CLASSES + 1], /// Numbers of codes of each size bits: Vec, /// List of values (ssss) sorted in ascending /// code length. /// Unused values (at the end of array) are set /// to `None`. huffval: [Option; Self::CLASSES], /// Code for each symbol /// Is is a combination of Huffbits and Huffenc huffcode: [HuffCode; Self::CLASSES + 1], /// Maps a value (ssss) to a symbol. /// This symbol can be used as index into /// `huffcode` to get the actual code for encoding. huffsym: [Option; Self::CLASSES], } impl HuffTableBuilder { /// Count of classes for Lossless JPEG /// For regular JPEG, V goes from 0 to 256. For lossless, /// we only have 17 classes for ssss (0-16). const CLASSES: usize = 17; // Sample classes for Lossless JPEG /// Construct new Huffman table for given histogram /// and image resolution fn new(histogram: [usize; Self::CLASSES], resolution: f32) -> Self { let mut ins = Self::default(); ins.bits.resize(33, 0); for (i, freq) in histogram.iter().map(|f| *f as f32 / resolution).enumerate() { ins.freq[i] = freq; } // Last freq must be 1 ins.freq[Self::CLASSES] = 1.0; ins } /// Figure K.1 - Procedure to find Huffman code sizes fn gen_codesizes(&mut self) { loop { // smallest frequencies found in loop let mut v1freq: f32 = 3.0; // just a value larger then 1.0 let mut v2freq: f32 = 3.0; // Indices into frequency table let mut v1: Option = None; let mut v2: Option = None; // Search v1 for (i, f) in self.freq.iter().enumerate().filter(|(_i, f)| **f > 0.0) { if *f <= v1freq { v1freq = *f; v1 = Some(i); } } // Search v2 for (i, f) in self.freq.iter().enumerate().filter(|(i, f)| **f > 0.0 && Some(*i) != v1) { if *f <= v2freq { v2freq = *f; v2 = Some(i); } } inspector!("V1: {:?}, V2: {:?}", v1, v2); match (&mut v1, &mut v2) { (Some(v1), Some(v2)) => { // Combine frequency values self.freq[*v1] += self.freq[*v2]; self.freq[*v2] = 0.0; // Increment code sizes for all codewords in this tree branch loop { self.codesize[*v1] += 1; if let Some(other) = self.others[*v1] { *v1 = other } else { break; } } self.others[*v1] = Some(*v2); loop { self.codesize[*v2] += 1; if let Some(other) = self.others[*v2] { *v2 = other; } else { break; } } } _ => { break; // exit loop, all frequencies are processed } } } #[cfg(feature = "inspector")] for (i, codesize) in self.codesize.iter().enumerate() { inspector!("codesize[{}]={}", i, codesize); } } /// Figure K.2 - Procedure to find the number of codes of each size fn count_bits(&mut self) { // K2 for i in 0..18 { if self.codesize[i] > 0 { self.bits[self.codesize[i] as usize] += 1; } } // end of K2 self.adjust_bits(); #[cfg(feature = "inspector")] for (i, bit) in self.bits.iter().enumerate() { inspector!("bits[{}]={}", i, bit); } } /// Section K.2 Figure K.4 Sorting of input values according to code size /// The input values are sorted according to code size as shown in Figure /// K.4. HUFFVAL is the list containing the input values associated with /// each code word, in order of increasing code length. /// /// At this point, the list of code lengths (BITS) and the list of values /// (HUFFVAL) can be used to generate the code tables. These procedures /// are described in Annex C. fn sort_input(&mut self) { let mut k = 0; for i in 1..=32 { for j in 0..=16 { // ssss if self.codesize[j] == i { self.huffval[k] = Some(j as u8); k += 1; } } } } /// Section C.2 Figure C.1 Generation of table of Huffman code sizes fn gen_size_table(&mut self) -> usize { let mut k = 0; let mut i = 1; while i <= 16 { let mut j = 1; while j <= self.bits[i] { self.huffcode[k].bits = i as u16; j += 1; k += 1; } i += 1; } self.huffcode[k].bits = 0; k } /// Section C.2 Figure C.2 Generation of table of Huffman codes fn gen_code_table(&mut self) { let mut k = 0; let mut code = 0; let mut si = self.huffcode[0].bits; loop { loop { self.huffcode[k].enc = code; code += 1; k += 1; if self.huffcode[k].bits != si { break; } } if self.huffcode[k].bits == 0 { break; } loop { code <<= 1; si += 1; if self.huffcode[k].bits == si { break; } } } } /// Section C.2 Figure C.3 Ordering procedure for encoding code tables fn order_codes(&mut self, _lastk: usize) { for (i, ssss) in self.huffval.iter().enumerate() { if let Some(ssss) = ssss { self.huffsym[*ssss as usize] = Some(i); } } } /// Section K.2 Figure K.3 Procedure for limiting code lengths to 16 bits /// /// Figure K.3 gives the procedure for adjusting the BITS list so that no /// code is longer than 16 bits. Since symbols are paired for the /// longest Huffman code, the symbols are removed from this length /// category two at a time. The prefix for the pair (which is one bit /// shorter) is allocated to one of the pair; then (skipping the BITS /// entry for that prefix length) a code word from the next shortest /// non-zero BITS entry is converted into a prefix for two code words one /// bit longer. After the BITS list is reduced to a maximum code length /// of 16 bits, the last step removes the reserved code point from the /// code length count. fn adjust_bits(&mut self) { let mut i = 32; while i > 16 { if self.bits[i] > 0 { let mut j = i - 2; // See K.3: J = I - 1; J = J - 1; while self.bits[j] == 0 { j -= 1; } self.bits[i] -= 2; self.bits[i - 1] += 1; self.bits[j + 1] += 2; self.bits[j] -= 1; } else { i -= 1; } } while self.bits[i] == 0 { i -= 1; } self.bits[i] -= 1; } /// Build Huffman table fn build(mut self) -> [BitArray16; HuffTableBuilder::CLASSES] { inspector!("Start building table"); self.gen_codesizes(); self.count_bits(); self.sort_input(); let lastk = self.gen_size_table(); self.gen_code_table(); self.order_codes(lastk); let mut table = [BitArray16::default(); HuffTableBuilder::CLASSES]; for ssss in 0..=16 { if let Some(code) = self.huffsym[ssss] { let enc = &self.huffcode[code]; inspector!("ssss: {}, enc.bits: {}", ssss, enc.bits); table[ssss as usize] = BitArray16::from_lsb(enc.bits as usize, enc.enc); } } #[cfg(feature = "inspector")] { for (class, val) in self.huffcode.iter().enumerate() { inspector!("huffcode: idx: {}, bitlen: {}, {:b}", class, val.bits, val.enc); } for (class, val) in self.huffval.iter().enumerate() { inspector!("huffval: idx: {}, ssss: {:?}", class, val); } for (idx, bitlen) in self.bits.iter().enumerate() { inspector!("bits: codelen: {}, value_count: {}", idx, bitlen); } for (class, val) in self.huffsym.iter().enumerate() { inspector!("hufsym: ssss: {}, code_idx: {:?}", class, val); } } table } /// This is a manual optimized table for most regular images /// Useful for testing only. fn _generic_table(histogram: [usize; Self::CLASSES], _resolution: f32) -> [BitArray16; HuffTableBuilder::CLASSES] { let mut dist: Vec<(usize, usize)> = histogram.iter().enumerate().map(|(a, b)| (a, *b)).collect(); dist.sort_by(|a, b| b.1.cmp(&a.1)); #[cfg(feature = "inspector")] for (i, f) in &dist { inspector!("Freq: {}: {}, {}", i, f, *f as f32 / _resolution); } let mut table = [BitArray16::default(); HuffTableBuilder::CLASSES]; table[dist[0].0] = BitArray16::from_lsb(2, 0b00); table[dist[1].0] = BitArray16::from_lsb(3, 0b010); table[dist[2].0] = BitArray16::from_lsb(3, 0b011); table[dist[3].0] = BitArray16::from_lsb(3, 0b100); table[dist[4].0] = BitArray16::from_lsb(3, 0b101); table[dist[5].0] = BitArray16::from_lsb(3, 0b110); table[dist[6].0] = BitArray16::from_lsb(4, 0b1110); table[dist[7].0] = BitArray16::from_lsb(5, 0b11110); table[dist[8].0] = BitArray16::from_lsb(6, 0b111110); table[dist[9].0] = BitArray16::from_lsb(7, 0b1111110); table[dist[10].0] = BitArray16::from_lsb(8, 0b11111110); table[dist[11].0] = BitArray16::from_lsb(9, 0b111111110); table[dist[12].0] = BitArray16::from_lsb(10, 0b1111111110); table[dist[13].0] = BitArray16::from_lsb(11, 0b11111111110); table[dist[14].0] = BitArray16::from_lsb(12, 0b111111111110); table[dist[15].0] = BitArray16::from_lsb(13, 0b1111111111110); table[dist[16].0] = BitArray16::from_lsb(14, 0b11111111111110); table } } /// State for one component of the image #[derive(Default, Clone, Debug)] struct ComponentState { /// Histogram of component histogram: [usize; 17], /// Huffman table for component hufftable: [BitArray16; HuffTableBuilder::CLASSES], } /// Bitstream for JPEG encoded data pub struct BitstreamJPEG<'a> { inner: &'a mut dyn Write, next: u8, used: usize, } impl<'a> BitstreamJPEG<'a> { pub fn new(inner: &'a mut dyn Write) -> Self { Self { inner, next: 0, used: 0 } } pub fn write_bit(&mut self, value: bool) -> std::io::Result<()> { self.write(1, if value { 1 } else { 0 }) } pub fn write(&mut self, mut bits: usize, value: u64) -> std::io::Result<()> { while bits > 0 { // flush buffer if full if self.used == 8 { self.internal_flush()?; } // how many bits are free? let free = 8 - self.used; // take exactly let take = min(bits, free); // peeked bits from value let peek = ((value >> (bits - take)) & ((1 << take) - 1)) as u8; // add peeked bits to buffer self.next |= peek << (free - take); // reduce consumed bits bits -= take; self.used += take; } Ok(()) } fn internal_flush(&mut self) -> std::io::Result<()> { self.inner.write_u8(self.next)?; if self.next == 0xFF { // Byte stuffing self.inner.write_u8(0x00)?; } self.used = 0; self.next = 0; Ok(()) } pub fn flush(&mut self) -> std::io::Result<()> { if self.used > 0 { self.internal_flush()?; } Ok(()) } } impl<'a> LjpegCompressor<'a> { /// Create a new LJPEG encoder /// /// skip_len is given as byte count after a row width. pub fn new( image: &'a [u16], width: usize, height: usize, components: usize, bitdepth: u8, predictor: u8, point_transform: u8, padding: usize, ) -> Result { if !(1..=7).contains(&predictor) { return Err(CompressorError::Overflow(format!("Unsupported predictor: {}", predictor))); } if image.len() < height * ((width + padding) * components) { return Err(CompressorError::Overflow( "Image input buffer is not large enough for given dimensions".to_string(), )); } if !(2..=16).contains(&bitdepth) { return Err(CompressorError::Overflow(format!( "Overflow for bit depth {}, only 2 >= bp <= 16 is supported", bitdepth ))); } if height > 65_535 { return Err(CompressorError::Overflow(format!( "Overflow for height {}, only h <= 65.535 is supported", height ))); } if width > 65_535 { return Err(CompressorError::Overflow(format!( "Overflow for width {}, only h <= 65.535 is supported", width ))); } Ok(Self { image, width, height, components, bitdepth, point_transform, predictor: Predictor::from(predictor), padding, comp_state: vec![ComponentState::default(); components], cache: Vec::default(), }) } /// Get the components as Range fn component_range(&self) -> std::ops::Range { 0..self.components } /// Encode input data and consume instance pub fn encode(mut self) -> Result> { let mut encoded = Cursor::new(Vec::with_capacity(self.resolution() * self.components)); self.scan_frequency()?; for comp in self.component_range() { self.build_hufftable(comp); //self.create_default_table(comp)?; //self.create_encode_table(comp)?; } self.write_header(&mut encoded)?; self.write_body(&mut encoded)?; self.write_post(&mut encoded)?; Ok(encoded.into_inner()) } /// Resolution of input image #[inline(always)] fn resolution(&self) -> usize { self.height * self.width } /// Scan frequency for Huff table fn scan_frequency(&mut self) -> Result<()> { let mut cache = vec![0; self.resolution() * self.components]; let rowsize = self.width * self.components; let linesize = (self.width + self.padding) * self.components; let mut row_prev = &self.image[0..]; let mut row_curr = &self.image[0..]; let mut diffs = vec![0_i16; linesize]; macro_rules! match_predictor { ($comp:expr, $pred:expr) => { match $pred { Predictor::P1 => ljpeg92_diff::<$comp, 1>(row_prev, row_curr, &mut diffs, linesize, self.point_transform, self.bitdepth), Predictor::P2 => ljpeg92_diff::<$comp, 2>(row_prev, row_curr, &mut diffs, linesize, self.point_transform, self.bitdepth), Predictor::P3 => ljpeg92_diff::<$comp, 3>(row_prev, row_curr, &mut diffs, linesize, self.point_transform, self.bitdepth), Predictor::P4 => ljpeg92_diff::<$comp, 4>(row_prev, row_curr, &mut diffs, linesize, self.point_transform, self.bitdepth), Predictor::P5 => ljpeg92_diff::<$comp, 5>(row_prev, row_curr, &mut diffs, linesize, self.point_transform, self.bitdepth), Predictor::P6 => ljpeg92_diff::<$comp, 6>(row_prev, row_curr, &mut diffs, linesize, self.point_transform, self.bitdepth), Predictor::P7 => ljpeg92_diff::<$comp, 7>(row_prev, row_curr, &mut diffs, linesize, self.point_transform, self.bitdepth), } }; } for row in 0..self.height { match self.components { 1 => match_predictor!(1, self.predictor), 2 => match_predictor!(2, self.predictor), 3 => match_predictor!(3, self.predictor), 4 => match_predictor!(4, self.predictor), _ => unreachable!(), } // Only copy rowsize values and ignore padding. cache[row * rowsize..row * rowsize + rowsize].copy_from_slice(&diffs[..rowsize]); for (i, diff) in diffs.iter().take(rowsize).enumerate() { let comp = i % self.components; let ssss = lookup_ssss(*diff); self.comp_state[comp].histogram[ssss as usize] += 1; } row_prev = row_curr; row_curr = &row_curr[linesize..]; } #[cfg(feature = "inspector")] for comp in 0..self.components { inspector!("Huffman table {}", comp); for i in 0..17 { inspector!("scan: self.huffman[{}].hist[{}]={}", comp, i, self.comp_state[comp].histogram[i]); } } self.cache = cache; Ok(()) } fn build_hufftable(&mut self, comp: usize) { #[cfg(feature = "inspector")] { let distibution: Vec<(u16, usize)> = self.comp_state[comp].histogram.iter().enumerate().map(|(a, b)| (a as u16, b.clone())).collect(); for (i, f) in &distibution { inspector!("unsorted freq: {}: {}, {}", i, f, *f as f32 / (self.resolution() as f32)); } } let huffgen = HuffTableBuilder::new(self.comp_state[comp].histogram, self.resolution() as f32); let table = huffgen.build(); //let table = HuffTableBuilder::_generic_table(self.comp_state[comp].histogram.clone(), self.resolution() as f32); #[cfg(feature = "inspector")] for (i, code) in table.iter().enumerate() { inspector!("table[{}]={}", i, code); } self.comp_state[comp].hufftable = table; } /// Write JPEG header fn write_header(&mut self, encoded: &mut dyn Write) -> Result<()> { encoded.write_u16::(0xffd8)?; // SOI encoded.write_u16::(0xffc3)?; // SOF_3 Lossless (sequential), Huffman coding // Write SOF encoded.write_u16::(2 + 6 + self.components as u16 * 3)?; // Lf, frame header length encoded.write_u8(self.bitdepth)?; // Sample precision P encoded.write_u16::(self.height as u16)?; encoded.write_u16::(self.width as u16)?; encoded.write_u8(self.components as u8)?; // Components Nf for c in self.component_range() { encoded.write_u8(c as u8)?; // Component ID encoded.write_u8(0x11)?; // H_i / V_i, Sampling factor 0001 0001 encoded.write_u8(0)?; // Quantisation table Tq (not used for lossless) } for comp in self.component_range() { // Write HUFF encoded.write_u16::(0xffc4)?; let bit_sum: u16 = self.comp_state[comp].hufftable.iter().filter(|e| !e.is_empty()).count() as u16; inspector!("Bitsum: {}", bit_sum); encoded.write_u16::(2 + (1 + 16) + bit_sum)?; // Lf, frame header length encoded.write_u8(comp as u8)?; // Table ID // Write for each of the 16 possible code lengths how many codes // exists with the correspoding length. for bit_len in 1..=16 { let count = self.comp_state[comp].hufftable.iter().filter(|entry| entry.len() == bit_len).count(); inspector!("COUNT: {}={}", bit_len, count); encoded.write_u8(count as u8)?; } for bit_len in 1..=16 { let mut codes: Vec<(u16, BitArray16)> = self.comp_state[comp] .hufftable .iter() .enumerate() .filter(|(_, code)| code.len() == bit_len) .map(|(ssss, code)| (ssss as u16, *code)) .collect(); codes.sort_by(|a, b| a.1.cmp(&b.1)); for (ssss, _) in codes.iter() { encoded.write_u8(*ssss as u8)?; inspector!("VAL: {}", ssss); } } } // Write SCAN encoded.write_u16::(0xffda)?; // SCAN encoded.write_u16::(0x0006 + (self.components as u16 * 2))?; // Ls, scan header length encoded.write_u8(self.components as u8)?; // Ns, Component count for c in self.component_range() { encoded.write_u8(c as u8)?; // Cs_i, Component selector encoded.write_u8((c as u8) << 4)?; // Td, Ta, DC/AC entropy table selector } encoded.write_u8(self.predictor.as_u8())?; // Ss, Predictor for lossless encoded.write_u8(0)?; // Se, ignored for lossless debug_assert!(self.point_transform <= 15); encoded.write_u8(0x00 | (self.point_transform & 0xF))?; // Ah=0, Al=Point transform Ok(()) } /// Write JPEG post fn write_post(&mut self, encoded: &mut dyn Write) -> Result<()> { encoded.write_u16::(0xffd9)?; // EOI Ok(()) } /// Write JPEG body fn write_body(&mut self, encoded: &mut dyn Write) -> Result<()> { let mut bitstream = BitstreamJPEG::new(encoded); for (i, diff) in self.cache.iter().enumerate() { let comp = i % self.components; let ssss = lookup_ssss(*diff); let enc = self.comp_state[comp].hufftable[ssss as usize]; let (bits, value) = (enc.len(), enc.get_lsb() as u64); debug_assert!(bits > 0); bitstream.write(bits, value)?; //inspector!("huff bits: {}, value: {:b}", bits, value); // If the number of bits is 16, there is only one possible difference // value (-32786), so the lossless JPEG spec says not to output anything // in that case. So we only need to output the diference value if // the number of bits is between 1 and 15. This also writes nothing // for ssss==0. debug_assert!(ssss <= 16); if (ssss & 15) != 0 { // sign encoding let diff = if *diff < 0 { *diff as i32 - 1 } else { *diff as i32 }; bitstream.write(ssss as usize, (diff & (0x0FFFF >> (16 - ssss))) as u64)?; } } // Flush the final bits bitstream.flush()?; Ok(()) } } /// Calculate the difference value between a sample and the predictor /// value. This function is optimized for one and two component input /// as this the case for most image data. /// `linesize` is the count of values including padding data at the end #[multiversion(targets("x86_64+avx+avx2+fma+bmi1+bmi2", "x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] //#[clone(target = "[x86|x86_64]+avx+avx2+fma+bmi1+bmi2+avx512f+avx512bw")] fn ljpeg92_diff( row_prev: &[u16], // Previous row (for index 0 it's the same reference as row_curr) row_curr: &[u16], // Current row diffs: &mut [i16], // Output buffer for difference values linesize: usize, // Count of values including padding data at the end point_transform: u8, // Point transform bitdepth: u8, // Bit depth ) { debug_assert_eq!(linesize % NCOMP, 0); let pixels = linesize / NCOMP; // How many pixels are in the line let samplecnt = pixels * NCOMP; let row_prev = &row_prev[..samplecnt]; // Hint for compiler: each slice has identical bounds (SIMD). let row_curr = &row_curr[..samplecnt]; // Slice range must be identical for SIMD optimizations. let diffs = &mut diffs[..samplecnt]; // In debug, check that no sample overflows max_value #[cfg(debug_assertions)] row_curr.iter().for_each(|sample| { let max_value = ((1u32 << (bitdepth - point_transform)) - 1) as u16; if (*sample >> point_transform) > max_value { panic!("Sample overflow, sample is {:#x} but max value is {:#x}", sample, max_value); } }); // First row always use predictor 1 // Set first column to initial values if row_curr.as_ptr() == row_prev.as_ptr() { for comp in 0..NCOMP { let px = (1u16 << (bitdepth - point_transform - 1)) as i32; let sample = pred_x::(row_prev, row_curr, comp, point_transform); diffs[0 + comp] = (sample - px) as i16; } // Process remaining pixels for idx in NCOMP..samplecnt { let px = pred_a::(row_prev, row_curr, idx, point_transform); let sample = pred_x::(row_prev, row_curr, idx, point_transform); diffs[idx] = (sample - px) as i16; } } else { // Not on first row, the first column uses predictor 2 for comp in 0..NCOMP { let px = pred_b::(row_prev, row_curr, 0 + comp, point_transform); let sample = pred_x::(row_prev, row_curr, comp, point_transform); diffs[0 + comp] = (sample - px) as i16; } let predictor = match PX { 1 => pred_a::, 2 => pred_b::, 3 => pred_c::, 4 => |prev: &[u16], curr: &[u16], idx: usize, pt: u8| -> i32 { let ra = pred_a::(prev, curr, idx, pt); let rb = pred_b::(prev, curr, idx, pt); let rc = pred_c::(prev, curr, idx, pt); ra + rb - rc }, 5 => |prev: &[u16], curr: &[u16], idx: usize, pt: u8| -> i32 { let ra = pred_a::(prev, curr, idx, pt); let rb = pred_b::(prev, curr, idx, pt); let rc = pred_c::(prev, curr, idx, pt); ra + ((rb - rc) >> 1) // Adobe DNG SDK uses int32 and shifts, so we will do, too. }, 6 => |prev: &[u16], curr: &[u16], idx: usize, pt: u8| -> i32 { let ra = pred_a::(prev, curr, idx, pt); let rb = pred_b::(prev, curr, idx, pt); let rc = pred_c::(prev, curr, idx, pt); rb + ((ra - rc) >> 1) // Adobe DNG SDK uses int32 and shifts, so we will do, too. }, 7 => |prev: &[u16], curr: &[u16], idx: usize, pt: u8| -> i32 { let ra = pred_a::(prev, curr, idx, pt); let rb = pred_b::(prev, curr, idx, pt); (ra + rb) >> 1 // Adobe DNG SDK uses int32 and shifts, so we will do, too. }, // Other predictors are not supported and catched in previous code path. _ => unreachable!(), }; // First pixel is processed, now process the remaining pixels. for idx in NCOMP..samplecnt { let px = predictor(row_prev, row_curr, idx, point_transform); let sample = pred_x::(row_prev, row_curr, idx, point_transform); // The difference between the prediction value and // the input is calculated modulo 2^16. So we can cast i32 // down to i16 to truncate the upper 16 bits (H.1.2.1, last paragraph). diffs[idx] = (sample - px) as i16; } } } /// Get Rx by current line /// Figure H.1 /// | c | b | /// | a | x | #[inline(always)] fn pred_x(_prev: &[u16], curr: &[u16], idx: usize, point_transform: u8) -> i32 { unsafe { (curr.get_unchecked(idx) >> point_transform) as i32 } } /// Get Ra predictor by current line /// Figure H.1 /// | c | b | /// | a | x | #[inline(always)] fn pred_a(_prev: &[u16], curr: &[u16], idx: usize, point_transform: u8) -> i32 { unsafe { (curr.get_unchecked(idx - NCOMP) >> point_transform) as i32 } } /// Get Rb predictor by previous line /// Figure H.1 /// | c | b | /// | a | x | #[inline(always)] fn pred_b(prev: &[u16], _curr: &[u16], idx: usize, point_transform: u8) -> i32 { unsafe { (prev.get_unchecked(idx) >> point_transform) as i32 } } /// Get Rc predictor by previous line /// Figure H.1 /// | c | b | /// | a | x | #[inline(always)] fn pred_c(prev: &[u16], _curr: &[u16], idx: usize, point_transform: u8) -> i32 { unsafe { (prev.get_unchecked(idx - NCOMP) >> point_transform) as i32 } } #[cfg(test)] mod tests { use super::*; /// We reuse the decompressor to check both... use crate::decompressors::ljpeg::LjpegDecompressor; #[test] fn bitstream_test1() -> std::result::Result<(), Box> { crate::init_test_logger(); let mut buf = Vec::new(); let mut bs = BitstreamJPEG::new(&mut buf); bs.write(1, 0b1)?; bs.flush()?; bs.write(1, 0b0)?; bs.write(3, 0b101)?; bs.write(4, 0b11111101)?; bs.write(2, 0b101)?; bs.flush()?; bs.write(16, 0b1111111111111111)?; bs.flush()?; bs.write(16, 0b0)?; bs.flush()?; assert_eq!(buf[0], 0b10000000); assert_eq!(buf[1], 0b01011101); assert_eq!(buf[2], 0b01000000); assert_eq!(buf[3], 0xFF); assert_eq!(buf[4], 0x00); // stuffing assert_eq!(buf[5], 0xFF); assert_eq!(buf[6], 0x00); // stuffing assert_eq!(buf[7], 0x00); Ok(()) } #[test] fn encode_16x16_16bit_black_decode_single() -> std::result::Result<(), Box> { crate::init_test_logger(); let h = 16; let w = 16; let c = 1; let input_image = vec![0x0000; w * h * c]; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 1, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new(&jpeg)?; let mut outbuf = vec![0; h * w]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; assert_eq!(outbuf[0], input_image[0]); assert_eq!(outbuf[1], input_image[1]); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } // #[test] // fn encode_4x4() -> std::result::Result<(), Box> { // let _ = SimpleLogger::new().init().unwrap_or(()); // let h = 4; // let w = 4; // let c = 1; // let input_image = [ // 0x4321, 0xde54, 0x8432, 0xed94, 0xb465, 0x2342, 0xaa02, 0x0054, 0x5487, 0xbb09, 0xe323, 0x9954, 0x8adc, 0x8000, 0x8001, 0xbd09, // ]; // let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 1, 0)?; // let result = enc.encode(); // assert!(result.is_ok()); // let jpeg = result?; // let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; // let mut outbuf = vec![0; w * h * c]; // dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; // assert_eq!(outbuf[0], input_image[0]); // assert_eq!(outbuf[1], input_image[1]); // for i in 0..outbuf.len() { // assert_eq!(outbuf[i], input_image[i]); // } // Ok(()) // } #[test] fn encode_16x16_16bit_black_decode_2component() -> std::result::Result<(), Box> { crate::init_test_logger(); let h = 2; let w = 2; let c = 2; let input_image = vec![0x0000; w * h * c]; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 1, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; w * h * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; assert_eq!(outbuf[0], input_image[0]); assert_eq!(outbuf[1], input_image[1]); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_16x16_16bit_black() -> std::result::Result<(), Box> { crate::init_test_logger(); let h = 16; let w = 16; let c = 1; let input_image = vec![0x0000; w * h * c]; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 1, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); Ok(()) } #[test] fn encode_16x16_16bit_white() -> std::result::Result<(), Box> { crate::init_test_logger(); let h = 16; let w = 16; let c = 1; let input_image = vec![0xffff; w * h * c]; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 1, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); Ok(()) } #[cfg(debug_assertions)] #[test] #[should_panic(expected = "Sample overflow, sample is 0xfffe but max value is 0x3fff")] fn encode_16x16_bitdepth_error() { crate::init_test_logger(); let h = 16; let w = 16; let c = 1; let input_image = vec![0xfffe; w * h * c]; let enc = LjpegCompressor::new(&input_image, w, h, c, 14, 1, 0, 0).expect("Compressor failed"); let _ = enc.encode(); } #[test] fn encode_16x16_short_buffer_error() -> std::result::Result<(), Box> { crate::init_test_logger(); let h = 16; let w = 16; let c = 1; let input_image = vec![0x9999_u16; (w * h * c) - 1]; let result = LjpegCompressor::new(&input_image, w, h, c, 16, 1, 0, 0); assert!(result.is_err()); Ok(()) } #[test] fn encode_16x16_16bit_incr() -> std::result::Result<(), Box> { crate::init_test_logger(); let h = 16; let w = 16; let c = 2; let mut input_image = vec![0; h * w * c]; for i in 0..input_image.len() { input_image[i] = i as u16; } let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 1, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("input: {:?}", input_image); //debug!("output: {:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_all_differences() -> std::result::Result<(), Box> { crate::init_test_logger(); // This simulates an input where every 17 SSSS classes are used because each difference // value exists (see ITU-T81 H.1.2.2 Table H.2, p. 138). let input_image = vec![ 0, 0, 1, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32, 0, 64, 0, 128, 0, 256, 0, 512, 0, 1024, 0, 2048, 0, 4096, 0, 8192, 0, 16384, 0, 32768, ]; let h = 1; let w = input_image.len(); let c = 1; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 1, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_ssss_16() -> std::result::Result<(), Box> { crate::init_test_logger(); // This simulates an input where every 17 SSSS classes are used because each difference // value exists (see ITU-T81 H.1.2.2 Table H.2, p. 138). //let input_image = vec![0, 0, 0, 32768, 0, 0]; let input_image = vec![0, 0, 0, 32768]; let h = 1; let w = input_image.len(); let c = 1; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 1, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_difference_above_32768() -> std::result::Result<(), Box> { crate::init_test_logger(); // Test values larger than i16::MAX let input_image = vec![0, 0, 0, 32768 + 1, 0, 0, 0, u16::MAX, u16::MAX, 1, u16::MAX, 1, 0]; let h = 1; let w = input_image.len(); let c = 1; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 1, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_predictor2_1comp() -> std::result::Result<(), Box> { crate::init_test_logger(); let input_image = vec![0, 0, u16::MAX, 0, 0, 0, u16::MAX - 5, 0]; let h = 2; let w = 4; let c = 1; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 2, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_predictor1_2comp_padding() -> std::result::Result<(), Box> { crate::init_test_logger(); let input_image = vec![1, 2, 5, 6, 3, 7, 0, 0, 7, 8, 3, 4, 6, 2, 0, 0]; let expected_image = [1, 2, 5, 6, 3, 7, 7, 8, 3, 4, 6, 2]; let h = 2; let w = 3; let c = 2; let padding = 1; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 1, 0, padding)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], expected_image[i]); } Ok(()) } #[test] fn encode_predictor3_1comp() -> std::result::Result<(), Box> { crate::init_test_logger(); let input_image = vec![0, u16::MAX, 0, 0, 0, 0, u16::MAX - 5, 0]; let h = 2; let w = 4; let c = 1; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 3, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_predictor4_1comp() -> std::result::Result<(), Box> { crate::init_test_logger(); let input_image = vec![0, 0, u16::MAX, 0, 0, u16::MAX, 0, 0]; let h = 2; let w = 4; let c = 1; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 4, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_predictor5_1comp() -> std::result::Result<(), Box> { crate::init_test_logger(); let input_image = vec![0, u16::MAX, u16::MAX, 0, 0, u16::MAX, 0, 0]; let h = 2; let w = 4; let c = 1; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 5, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_predictor6_1comp() -> std::result::Result<(), Box> { crate::init_test_logger(); let input_image = vec![0, u16::MAX, u16::MAX, 0, 0, u16::MAX, 0, 0]; let h = 2; let w = 4; let c = 1; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 6, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_predictor6_3comp() -> std::result::Result<(), Box> { crate::init_test_logger(); let input_image = vec![56543, 45, 65000, 0, 0, 35632]; let h = 2; let w = 1; let c = 3; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 6, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_predictor6_3comp_ssss16() -> std::result::Result<(), Box> { crate::init_test_logger(); let input_image = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 32768, 32768, 32768, 0, 0, 0, 0, 0, 0]; let h = 3; let w = 2; let c = 3; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 6, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_predictor7_1comp() -> std::result::Result<(), Box> { crate::init_test_logger(); let input_image = vec![0, 0, u16::MAX, 0, 0, u16::MAX, 0, 0]; let h = 2; let w = 4; let c = 1; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 7, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_predictor1_ljpeg_width_larger_than_output() -> std::result::Result<(), Box> { crate::init_test_logger(); let input_image = vec![100, 105, 200, 207, 50, 48, 34, 45, 50, 45, 23, 100, 34, 76, 23, 99]; let expected_output = vec![100, 105, 200, 207, 50, 45, 23, 100]; let h = 2; let w = 4; let c = 2; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 1, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let w = w / 2; // we only want the first part of the image let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); assert_eq!(outbuf, expected_output); Ok(()) } #[test] fn encode_predictor4_trigger_minus1_prediction() -> std::result::Result<(), Box> { crate::init_test_logger(); let input_image = vec![0, 0, 5, 2, 0, 0, 0, 0, 2, 9, 0, 0]; let h = 2; let w = 6; let c = 1; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 4, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } #[test] fn encode_predictor5_trigger_minus1_prediction() -> std::result::Result<(), Box> { crate::init_test_logger(); let input_image = vec![0, 0, 2, 1, 0, 0, 1, 9]; let h = 2; let w = 4; let c = 1; let enc = LjpegCompressor::new(&input_image, w, h, c, 16, 5, 0, 0)?; let result = enc.encode(); assert!(result.is_ok()); let jpeg = result?; let dec = LjpegDecompressor::new_full(&jpeg, false, false)?; let mut outbuf = vec![0; h * w * c]; dec.decode(&mut outbuf, 0, w * c, w * c, h, false)?; //debug!("{:?}", outbuf); for i in 0..outbuf.len() { assert_eq!(outbuf[i], input_image[i]); } Ok(()) } } rawler-0.7.1/src/packed.rs000064400000000000000000000374031046102023000135200ustar 00000000000000use crate::{ alloc_image, bits::*, decoders::decode_threaded, pixarray::PixU16, pumps::{BitPump, BitPumpLSB, BitPumpMSB}, }; pub fn decode_8bit_wtable(buf: &[u8], tbl: &LookupTable, width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width)..]; let mut random = LEu32(inb, 0); for (o, i) in out.chunks_exact_mut(1).zip(inb.chunks_exact(1)) { o[0] = tbl.dither(i[0] as u16, &mut random); } }), ) } pub fn decode_8bit(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width)..]; for (o, i) in out.iter_mut().zip(inb.iter()) { *o = *i as u16; } }), ) } pub fn decode_10le_lsb16(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 10 / 8)..]; for (o, i) in out.chunks_exact_mut(8).zip(inb.chunks_exact(10)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; let g4: u16 = i[3] as u16; let g5: u16 = i[4] as u16; let g6: u16 = i[5] as u16; let g7: u16 = i[6] as u16; let g8: u16 = i[7] as u16; let g9: u16 = i[8] as u16; let g10: u16 = i[9] as u16; o[0] = (g2 << 2) | (g1 >> 6); o[1] = ((g1 & 0x3f) << 4) | (g4 >> 4); o[2] = ((g4 & 0x0f) << 6) | (g3 >> 2); o[3] = ((g3 & 0x03) << 8) | g6; o[4] = (g5 << 2) | (g8 >> 6); o[5] = ((g8 & 0x3f) << 4) | (g7 >> 4); o[6] = ((g7 & 0x0f) << 6) | (g10 >> 2); o[7] = ((g10 & 0x03) << 8) | g9; } }), ) } pub fn decode_10be(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 10 / 8)..]; for (o, i) in out.chunks_exact_mut(4).zip(inb.chunks_exact(5)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; let g4: u16 = i[3] as u16; let g5: u16 = i[4] as u16; o[0] = (g1 << 2) | (g2 >> 6); o[1] = ((g2 & 0x3f) << 4) | (g3 >> 4); o[2] = ((g3 & 0x0f) << 6) | (g4 >> 2); o[3] = ((g4 & 0x03) << 8) | g5; } }), ) } pub fn decode_12be(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 12 / 8)..]; for (o, i) in out.chunks_exact_mut(2).zip(inb.chunks_exact(3)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; o[0] = (g1 << 4) | (g2 >> 4); o[1] = ((g2 & 0x0f) << 8) | g3; } }), ) } pub fn decode_12be_msb16(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { let mut out = alloc_image!(width, height, dummy); for (o, i) in out.pixels_mut().chunks_exact_mut(4).zip(buf.chunks_exact(6)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; let g4: u16 = i[3] as u16; let g5: u16 = i[4] as u16; let g6: u16 = i[5] as u16; o[0] = (g2 << 4) | (g1 >> 4); o[1] = ((g1 & 0x0f) << 8) | g4; o[2] = (g3 << 4) | (g6 >> 4); o[3] = ((g6 & 0x0f) << 8) | g5; } out } pub fn decode_12le_16bitaligned(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { let stride = ((width * 12 / 8 + 1) >> 1) << 1; decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[row * stride..]; for (o, i) in out.chunks_exact_mut(2).zip(inb.chunks_exact(3)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; o[0] = (g1 << 4) | (g2 >> 4); o[1] = ((g2 & 0x0f) << 8) | g3; } }), ) } pub fn decode_12be_msb32(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { let mut out = alloc_image!(width, height, dummy); for (o, i) in out.pixels_mut().chunks_exact_mut(8).zip(buf.chunks_exact(12)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; let g4: u16 = i[3] as u16; let g5: u16 = i[4] as u16; let g6: u16 = i[5] as u16; let g7: u16 = i[6] as u16; let g8: u16 = i[7] as u16; let g9: u16 = i[8] as u16; let g10: u16 = i[9] as u16; let g11: u16 = i[10] as u16; let g12: u16 = i[11] as u16; // | G1 | G2 | G3 | G4 | G5 | G6 | G7 | G8 | G9 | G10 | G11 | G12 | // 2 1 1 0 4 4 3 2 7 6 6 5 o[0] = (g4 << 4) | (g3 >> 4); o[1] = ((g3 & 0x0f) << 8) | g2; o[2] = (g1 << 4) | (g8 >> 4); o[3] = ((g8 & 0x0f) << 8) | g7; o[4] = (g6 << 4) | (g5 >> 4); o[5] = ((g5 & 0x0f) << 8) | g12; o[6] = (g11 << 4) | (g10 >> 4); o[7] = ((g10 & 0x0f) << 8) | g9; } out } /// This is packed by 32 bits in reverse order, so the concatenation /// of 14 bit pairs is byte index: 3, 2, 1, 0, 7, 6, 5, 4, ... pub fn decode_14be_msb32(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { let mut out = alloc_image!(width, height, dummy); for (o, i) in out.pixels_mut().chunks_exact_mut(16).zip(buf.chunks_exact(28)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; let g4: u16 = i[3] as u16; let g5: u16 = i[4] as u16; let g6: u16 = i[5] as u16; let g7: u16 = i[6] as u16; let g8: u16 = i[7] as u16; let g9: u16 = i[8] as u16; let g10: u16 = i[9] as u16; let g11: u16 = i[10] as u16; let g12: u16 = i[11] as u16; let g13: u16 = i[12] as u16; let g14: u16 = i[13] as u16; let g15: u16 = i[14] as u16; let g16: u16 = i[15] as u16; let g17: u16 = i[16] as u16; let g18: u16 = i[17] as u16; let g19: u16 = i[18] as u16; let g20: u16 = i[19] as u16; let g21: u16 = i[20] as u16; let g22: u16 = i[21] as u16; let g23: u16 = i[22] as u16; let g24: u16 = i[23] as u16; let g25: u16 = i[24] as u16; let g26: u16 = i[25] as u16; let g27: u16 = i[26] as u16; let g28: u16 = i[27] as u16; o[0] = (g4 << 6) | (g3 >> 2); o[1] = ((g3 & 0x3) << 12) | (g2 << 4) | (g1 >> 4); o[2] = ((g1 & 0xf) << 10) | (g8 << 2) | (g7 >> 6); o[3] = ((g7 & 0x3f) << 8) | g6; o[4] = (g5 << 6) | (g12 >> 2); o[5] = ((g12 & 0x3) << 12) | (g11 << 4) | (g10 >> 4); o[6] = ((g10 & 0xf) << 10) | (g9 << 2) | (g16 >> 6); o[7] = ((g16 & 0x3f) << 8) | g15; o[8] = (g14 << 6) | (g13 >> 2); o[9] = ((g13 & 0x3) << 12) | (g20 << 4) | (g19 >> 4); o[10] = ((g19 & 0xf) << 10) | (g18 << 2) | (g17 >> 6); o[11] = ((g17 & 0x3f) << 8) | g24; o[12] = (g23 << 6) | (g22 >> 2); o[13] = ((g22 & 0x3) << 12) | (g21 << 4) | (g28 >> 4); o[14] = ((g28 & 0xf) << 10) | (g27 << 2) | (g26 >> 6); o[15] = ((g26 & 0x3f) << 8) | g25; } out } pub fn decode_12le_wcontrol(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { // Calulate expected bytes per line. let perline = width * 12 / 8 + ((width + 2) / 10); decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * perline)..]; for (oc, ic) in out.chunks_exact_mut(10).zip(inb.chunks_exact(16)) { for (o, i) in oc.chunks_exact_mut(2).zip(ic.chunks_exact(3)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; o[0] = ((g2 & 0x0f) << 8) | g1; o[1] = (g3 << 4) | (g2 >> 4); } } }), ) } pub fn decode_12be_wcontrol(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { // Calulate expected bytes per line. let perline = width * 12 / 8 + ((width + 2) / 10); decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * perline)..]; for (oc, ic) in out.chunks_exact_mut(10).zip(inb.chunks_exact(16)) { for (o, i) in oc.chunks_exact_mut(2).zip(ic.chunks_exact(3)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; o[0] = (g1 << 4) | (g2 >> 4); o[1] = ((g2 & 0x0f) << 8) | g3; } } }), ) } pub fn decode_12be_interlaced(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { let half = (height + 1) >> 1; // Second field is 2048 byte aligned let second_field_offset = (((half * width * 3 / 2) >> 11) + 1) << 11; let second_field = &buf[second_field_offset..]; decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let off = row / 2 * width * 12 / 8; let inb = if (row % 2) == 0 { &buf[off..] } else { &second_field[off..] }; for (o, i) in out.chunks_exact_mut(2).zip(inb.chunks_exact(3)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; o[0] = (g1 << 4) | (g2 >> 4); o[1] = ((g2 & 0x0f) << 8) | g3; } }), ) } pub fn decode_12be_interlaced_unaligned(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { let half = (height + 1) >> 1; let second_field = &buf[half * width * 12 / 8..]; decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let off = row / 2 * width * 12 / 8; let inb = if (row % 2) == 0 { &buf[off..] } else { &second_field[off..] }; for (o, i) in out.chunks_exact_mut(2).zip(inb.chunks_exact(3)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; o[0] = (g1 << 4) | (g2 >> 4); o[1] = ((g2 & 0x0f) << 8) | g3; } }), ) } pub fn decode_12le(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 12 / 8)..]; for (o, i) in out.chunks_exact_mut(2).zip(inb.chunks_exact(3)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; o[0] = ((g2 & 0x0f) << 8) | g1; o[1] = (g3 << 4) | (g2 >> 4); } }), ) } pub fn decode_12le_padded(buf: &[u8], width: usize, height: usize, stripesize: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * stripesize)..]; for (o, i) in out.chunks_exact_mut(2).zip(inb.chunks_exact(3)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; o[0] = ((g2 & 0x0f) << 8) | g1; o[1] = (g3 << 4) | (g2 >> 4); } }), ) } pub fn decode_14le_padded(buf: &[u8], width: usize, height: usize, stripesize: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * stripesize)..]; for (o, i) in out.chunks_exact_mut(4).zip(inb.chunks_exact(7)) { let g1: u16 = i[0] as u16; let g2: u16 = i[1] as u16; let g3: u16 = i[2] as u16; let g4: u16 = i[3] as u16; let g5: u16 = i[4] as u16; let g6: u16 = i[5] as u16; let g7: u16 = i[6] as u16; o[0] = ((g2 & 0x3f) << 8) | g1; o[1] = ((g4 & 0xf) << 10) | (g3 << 2) | (g2 >> 6); o[2] = ((g6 & 0x3) << 12) | (g5 << 4) | (g4 >> 4); o[3] = (g7 << 6) | (g6 >> 2); } }), ) } pub fn decode_12le_unpacked(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 2)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(2)) { out[i] = LEu16(bytes, 0) & 0x0fff; } }), ) } pub fn decode_12be_unpacked(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 2)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(2)) { out[i] = BEu16(bytes, 0) & 0x0fff; } }), ) } pub fn decode_12be_unpacked_left_aligned(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 2)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(2)) { out[i] = BEu16(bytes, 0) >> 4; } }), ) } pub fn decode_12le_unpacked_left_aligned(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 2)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(2)) { out[i] = LEu16(bytes, 0) >> 4; } }), ) } pub fn decode_14le_unpacked(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 2)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(2)) { out[i] = LEu16(bytes, 0) & 0x3fff; } }), ) } pub fn decode_14le_unpacked_padded(buf: &[u8], width: usize, height: usize, stripsize: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * stripsize)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(2)) { out[i] = LEu16(bytes, 0) & 0x3fff; } }), ) } pub fn decode_14be_unpacked(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 2)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(2)) { out[i] = BEu16(bytes, 0) & 0x3fff; } }), ) } pub fn decode_16le(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 2)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(2)) { out[i] = LEu16(bytes, 0); } }), ) } pub fn decode_16le_skiplines(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 4)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(2)) { out[i] = LEu16(bytes, 0); } }), ) } pub fn decode_16be(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, dummy, &(|out: &mut [u16], row| { let inb = &buf[(row * width * 2)..]; for (i, bytes) in (0..width).zip(inb.chunks_exact(2)) { out[i] = BEu16(bytes, 0); } }), ) } pub fn decode_generic_msb(buf: &[u8], width: usize, height: usize, bits: u32, dummy: bool) -> PixU16 { assert!(bits <= 16); let mut pix: PixU16 = alloc_image!(width, height, dummy); assert!(8 * buf.len() >= width * height * bits as usize, "buf has not enough bits"); let mut pump = BitPumpMSB::new(buf); for p in pix.pixels_mut() { *p = pump.get_bits(bits) as u16; } pix } pub fn decode_generic_lsb(buf: &[u8], width: usize, height: usize, bits: u32, dummy: bool) -> PixU16 { assert!(bits <= 16); let mut pix: PixU16 = alloc_image!(width, height, dummy); assert!(8 * buf.len() >= width * height * bits as usize, "buf has not enough bits"); let mut pump = BitPumpLSB::new(buf); for p in pix.pixels_mut() { *p = pump.get_bits(bits) as u16; } pix } rawler-0.7.1/src/pixarray.rs000064400000000000000000000321111046102023000141170ustar 00000000000000use std::cell::UnsafeCell; use multiversion::multiversion; use rayon::prelude::*; use crate::{ decoders::decode_threaded_prealloc, formats::tiff::Rational, imgop::{Dim2, Point, Rect}, }; pub trait SubPixel: Default + std::fmt::Debug + Clone + Copy + Send + Sync + Into { fn as_f32(self) -> f32; fn as_u16(self) -> u16; } impl SubPixel for u16 { fn as_f32(self) -> f32 { self as f32 } fn as_u16(self) -> u16 { self as u16 } } impl SubPixel for f32 { fn as_f32(self) -> f32 { self as f32 } fn as_u16(self) -> u16 { self as u16 } } pub type LineMut<'a, T> = &'a mut [T]; pub type Line<'a, T> = &'a [T]; #[derive(Clone)] pub struct Pix2D { pub width: usize, pub height: usize, pub data: Vec, pub initialized: bool, } pub type PixU16 = Pix2D; pub type PixF32 = Pix2D; impl Pix2D where T: SubPixel, { pub fn new_with(data: Vec, width: usize, height: usize) -> Self { assert_eq!(data.len(), height * width); Self { data, width, height, initialized: true, } } pub fn new(width: usize, height: usize) -> Self { let data = vec![T::default(); width * height]; Self { data, width, height, initialized: true, } } pub fn new_uninit(width: usize, height: usize) -> Self { let data = Vec::with_capacity(width * height); Self { data, width, height, initialized: false, } } pub fn is_initialized(&self) -> bool { self.initialized } pub fn into_inner(self) -> Vec { self.data } pub fn len(&self) -> usize { self.data.len() } pub fn dim(&self) -> Dim2 { Dim2::new(self.width, self.height) } pub fn rect(&self) -> Rect { Rect::new(Point::default(), Dim2::new(self.width, self.height)) } pub fn update_dimension(&mut self, dim: Dim2) { if self.width * self.height == dim.w * dim.h { self.width = dim.w; self.height = dim.h; } else { panic!("Can not change dimension: mismatch with old dimension: {:?} vs. {:?}", self.dim(), dim); } } pub fn pixels(&self) -> &[T] { debug_assert!(self.initialized); &self.data } pub fn pixels_mut(&mut self) -> &mut [T] { debug_assert!(self.initialized); &mut self.data } pub fn pixel_rows(&self) -> std::slice::ChunksExact<'_, T> { debug_assert!(self.initialized); self.data.chunks_exact(self.width) } pub fn pixel_rows_mut(&mut self) -> std::slice::ChunksExactMut<'_, T> { debug_assert!(self.initialized); self.data.chunks_exact_mut(self.width) } pub fn par_pixel_rows_mut(&mut self) -> rayon::slice::ChunksExactMut<'_, T> { debug_assert!(self.initialized); self.data.par_chunks_exact_mut(self.width) } #[inline(always)] pub fn row(&self, row: usize) -> &[T] { debug_assert!(self.initialized); let start = row * self.width; &self.data[start..start + self.width] } #[inline(always)] pub fn row_mut(&mut self, row: usize) -> &mut [T] { debug_assert!(self.initialized); let start = row * self.width; &mut self.data[start..start + self.width] } #[inline(always)] pub fn at(&self, row: usize, col: usize) -> &T { debug_assert!(self.initialized); #[cfg(debug_assertions)] { &self.data[row * self.width + col] } #[cfg(not(debug_assertions))] unsafe { self.data.get_unchecked(row * self.width + col) } } #[inline(always)] pub fn at_mut(&mut self, row: usize, col: usize) -> &mut T { debug_assert!(self.initialized); #[cfg(debug_assertions)] { &mut self.data[row * self.width + col] } #[cfg(not(debug_assertions))] unsafe { self.data.get_unchecked_mut(row * self.width + col) } } #[inline(always)] pub fn for_each(&mut self, op: F) where F: Fn(T) -> T + Send + Sync, { assert!(self.initialized); self.data.par_iter_mut().for_each(|v| *v = op(*v)); } #[inline(always)] pub fn for_each_index(&mut self, op: F) where F: Fn(T, usize, usize) -> T, { assert!(self.initialized); self .pixel_rows_mut() .enumerate() .for_each(|(row, rowbuf)| rowbuf.iter_mut().enumerate().for_each(|(col, v)| *v = op(*v, row, col))); } pub fn crop(&self, area: Rect) -> Self { assert!(self.initialized); crop(&self, area) } pub fn into_crop(self, area: Rect) -> Self { if self.dim() == area.d && area.p == Point::zero() { self // No-Op } else { crop(&self, area) } } } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] fn crop(pixbuf: &Pix2D, area: Rect) -> Pix2D where T: SubPixel, { let mut output; if pixbuf.initialized { output = Pix2D::::new(area.width(), area.height()); output.par_pixel_rows_mut().enumerate().for_each(|(row, line)| { let src_row = pixbuf.row(area.y() + row); line.copy_from_slice(&src_row[area.x()..area.x() + line.len()]); }); } else { output = Pix2D::::new_uninit(area.width(), area.height()); } output } #[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] pub(crate) fn deinterleave2x2(pixbuf: &Pix2D) -> crate::Result> where T: SubPixel, { if pixbuf.initialized { let mut output = Pix2D::::new(pixbuf.width, pixbuf.height); let line_width = pixbuf.width; let half_width = line_width / 2; let line_distance = line_width; let ch0 = &pixbuf[..]; let ch1 = &pixbuf[half_width..]; let ch2 = &pixbuf[pixbuf.len() / 2..]; let ch3 = &pixbuf[pixbuf.len() / 2 + half_width..]; decode_threaded_prealloc(&mut output, &|line, row| { let src_row = row / 2; let offset = src_row * line_distance; let ch_a; let ch_b; if row & 1 == 0 { // For even rows, we take top-left and top-right channel data. ch_a = &ch0[offset..offset + half_width]; ch_b = &ch1[offset..offset + half_width]; } else { // For odd rows, we take bottom-left and bottom-right channel data. ch_a = &ch2[offset..offset + half_width]; ch_b = &ch3[offset..offset + half_width]; } debug_assert_eq!(ch_a.len(), ch_b.len()); debug_assert_eq!(ch_a.len() + ch_b.len(), line.len()); debug_assert_eq!(line_width, line.len()); line.chunks_exact_mut(2).zip(ch_a.iter().zip(ch_b.iter())).for_each(|(dst, (a, b))| { dst[0] = *a; dst[1] = *b; }); Ok(()) })?; Ok(output) } else { Ok(pixbuf.clone()) } } /* impl Index for Pix2D { type Output = T; fn index<'a>(&'a self, i: usize) -> &'a T { &self.data[i] } } */ impl std::ops::Index for Pix2D where I: std::slice::SliceIndex<[T]>, T: SubPixel, { type Output = I::Output; fn index(&self, index: I) -> &Self::Output { &self.data[index] } } impl std::ops::IndexMut for Pix2D where I: std::slice::SliceIndex<[T]>, T: SubPixel, { fn index_mut<'a>(&mut self, index: I) -> &mut Self::Output { &mut self.data[index] } } /* impl Default for Pix2D where T: Default, { fn default() -> Self { Self { width: 0, height: 0, data: Default::default(), initialized: false, } } } */ /// An ugly hack to get multiple mutable references to Pix2D pub struct SharedPix2D { pub inner: UnsafeCell>, } impl SharedPix2D where T: SubPixel, { pub fn new(inner: Pix2D) -> Self { Self { inner: inner.into() } } /// Get inner Pix2D<> reference /// /// # Safety /// Only use this inside Rayon parallel iterators. #[allow(clippy::mut_from_ref)] pub unsafe fn inner_mut(&self) -> &mut Pix2D { unsafe { &mut *self.inner.get() } } pub fn into_inner(self) -> Pix2D { self.inner.into_inner() } } unsafe impl Sync for SharedPix2D where T: SubPixel {} #[derive(Clone)] pub struct Color2D { pub width: usize, pub height: usize, pub data: Vec<[T; N]>, } pub type RgbF32 = Color2D; pub type Ch4F32 = Color2D; impl Color2D where T: Copy + Clone + Default + Send, [T; N]: Default, { pub fn new_with(data: Vec<[T; N]>, width: usize, height: usize) -> Self { debug_assert_eq!(data.len(), height * width); Self { data, width, height } } pub fn new(width: usize, height: usize) -> Self { let data = vec![<[T; N]>::default(); width * height]; Self { data, width, height } } pub fn into_inner(self) -> Vec<[T; N]> { self.data } pub fn dim(&self) -> Dim2 { Dim2::new(self.width, self.height) } pub fn rect(&self) -> Rect { Rect::new(Point::default(), Dim2::new(self.width, self.height)) } pub fn flatten(&self) -> Vec { self.data.iter().flatten().copied().collect::>() } pub fn data_ptr(&self) -> Color2DPtr { Color2DPtr::new(self) } pub fn pixels(&self) -> &[[T; N]] { &self.data } pub fn pixels_mut(&mut self) -> &mut [[T; N]] { &mut self.data } pub fn pixel_rows(&self) -> std::slice::ChunksExact<'_, [T; N]> { self.data.chunks_exact(self.width) } pub fn pixel_rows_mut(&mut self) -> std::slice::ChunksExactMut<'_, [T; N]> { self.data.chunks_exact_mut(self.width) } #[inline(always)] pub fn at(&self, row: usize, col: usize) -> &[T; N] { #[cfg(debug_assertions)] { &self.data[row * self.width + col] } #[cfg(not(debug_assertions))] unsafe { self.data.get_unchecked(row * self.width + col) } } #[inline(always)] pub fn at_mut(&mut self, row: usize, col: usize) -> &mut [T; N] { #[cfg(debug_assertions)] { &mut self.data[row * self.width + col] } #[cfg(not(debug_assertions))] unsafe { self.data.get_unchecked_mut(row * self.width + col) } } #[inline(always)] pub fn for_each(&mut self, op: F) where F: Fn([T; N]) -> [T; N] + Send + Sync, { self.data.par_iter_mut().for_each(|v| *v = op(*v)); } #[inline(always)] pub fn for_each_row(&mut self, op: F) where F: Fn(usize, &mut [[T; N]]) + Send + Sync, { self.data.par_chunks_exact_mut(self.width).enumerate().for_each(|(row, data)| op(row, data)); } // TODO: use par_iterator #[inline(always)] pub fn for_each_index(&mut self, op: F) where F: Fn([T; N], usize, usize) -> [T; N], { self .pixel_rows_mut() .enumerate() .for_each(|(row, rowbuf)| rowbuf.iter_mut().enumerate().for_each(|(col, v)| *v = op(*v, row, col))); } pub fn crop(&self, area: Rect) -> Self { let mut output = Vec::with_capacity(area.d.h * area.d.w); assert!(area.p.y + area.d.h <= self.height); assert!(area.p.x + area.d.w <= self.width); output.extend( self .pixels() .chunks_exact(self.width) .skip(area.p.y) .take(area.d.h) .flat_map(|row| row[area.p.x..area.p.x + area.d.w].iter()) .cloned(), ); Self::new_with(output, area.d.w, area.d.h) } } impl Default for Color2D where T: Default, { fn default() -> Self { Self { width: 0, height: 0, data: Default::default(), } } } #[derive(Clone, Debug)] pub struct Color2DPtr { ptr: *const [T; N], pub width: usize, pub height: usize, } impl Color2DPtr where T: Copy + Clone, { fn new(orig: &Color2D) -> Self { Self { ptr: orig.data.as_slice().as_ptr(), width: orig.width, height: orig.height, } } /// Get a pixel from raw pointer /// # Safety /// TODO #[inline(always)] pub unsafe fn at(&self, row: usize, col: usize) -> &[T; N] { unsafe { debug_assert!(row * col < self.height * self.width); &*self.ptr.add(row * self.width + col) } } } unsafe impl Sync for Color2DPtr {} #[macro_export] macro_rules! alloc_image_f32_plain { ($width:expr, $height:expr, $dummy: expr) => {{ if $width * $height > 500000000 || $width > 50000 || $height > 50000 { panic!("rawler: surely there's no such thing as a >500MP or >50000 px wide/tall image!"); } if $dummy { $crate::pixarray::PixF32::new_uninit($width, $height) } else { $crate::pixarray::PixF32::new($width, $height) } }}; } #[macro_export] macro_rules! alloc_image_plain { ($width:expr, $height:expr, $dummy: expr) => {{ if $width * $height > 500000000 || $width > 50000 || $height > 50000 { panic!("rawler: surely there's no such thing as a >500MP or >50000 px wide/tall image!"); } if $dummy { $crate::pixarray::PixU16::new_uninit($width, $height) } else { $crate::pixarray::PixU16::new($width, $height) } }}; } #[macro_export] macro_rules! alloc_image { ($width:expr, $height:expr, $dummy: expr) => {{ if $dummy { return $crate::pixarray::PixU16::new_uninit($width, $height); } else { $crate::alloc_image_plain!($width, $height, $dummy) } }}; } #[macro_export] macro_rules! alloc_image_ok { ($width:expr, $height:expr, $dummy: expr) => {{ if $dummy { return Ok($crate::pixarray::PixU16::new_uninit($width, $height)); } else { $crate::alloc_image_plain!($width, $height, $dummy) } }}; } rawler-0.7.1/src/pumps.rs000064400000000000000000000226311046102023000134320ustar 00000000000000use crate::bits::*; #[derive(Debug, Copy, Clone)] pub struct BitPumpLSB<'a> { buffer: &'a [u8], pos: usize, bits: u64, nbits: u32, } impl<'a> BitPumpLSB<'a> { pub fn new(src: &'a [u8]) -> Self { Self { buffer: src, pos: 0, bits: 0, nbits: 0, } } } #[derive(Debug, Copy, Clone)] pub struct BitPumpMSB<'a> { buffer: &'a [u8], pos: usize, bits: u64, nbits: u32, } impl<'a> BitPumpMSB<'a> { pub fn new(src: &'a [u8]) -> Self { Self { buffer: src, pos: 0, bits: 0, nbits: 0, } } } #[derive(Debug, Copy, Clone)] pub struct BitPumpMSB32<'a> { buffer: &'a [u8], pos: usize, bits: u64, nbits: u32, } impl<'a> BitPumpMSB32<'a> { pub fn new(src: &'a [u8]) -> Self { Self { buffer: src, pos: 0, bits: 0, nbits: 0, } } #[inline(always)] pub fn get_pos(&self) -> usize { self.pos - ((self.nbits >> 3) as usize) } } #[derive(Debug, Copy, Clone)] pub struct BitPumpJPEG<'a> { buffer: &'a [u8], pos: usize, bits: u64, nbits: u32, finished: bool, } impl<'a> BitPumpJPEG<'a> { pub fn new(src: &'a [u8]) -> Self { Self { buffer: src, pos: 0, bits: 0, nbits: 0, finished: false, } } } pub trait BitPump { fn peek_bits(&mut self, num: u32) -> u32; fn consume_bits(&mut self, num: u32); #[inline(always)] fn get_bits(&mut self, num: u32) -> u32 { if num == 0 { return 0; } let val = self.peek_bits(num); self.consume_bits(num); val } #[inline(always)] fn peek_ibits(&mut self, num: u32) -> i32 { self.peek_bits(num) as i32 } #[inline(always)] fn get_ibits(&mut self, num: u32) -> i32 { self.get_bits(num) as i32 } // Sign extend ibits #[inline(always)] fn get_ibits_sextended(&mut self, num: u32) -> i32 { let val = self.get_ibits(num); val.wrapping_shl(32 - num).wrapping_shr(32 - num) } /// Count the leading zeroes block-wise in 31 bits /// per block and returns the count. /// All zero bits are consumed. #[inline(always)] fn consume_zerobits(&mut self) -> u32 { // Take one bit less because leading_zeros() is undefined // when all bits in register are zero. const BITS_PER_LOOP: u32 = u32::BITS - 1; let mut count = 0; // Count-and-skip all the leading `0`s. loop { let batch: u32 = (self.peek_bits(BITS_PER_LOOP) << 1) | 0x1; let n = batch.leading_zeros(); self.consume_bits(n); count += n; if n != BITS_PER_LOOP { break; } } count } } impl<'a> BitPump for BitPumpLSB<'a> { #[inline(always)] fn peek_bits(&mut self, num: u32) -> u32 { if num > self.nbits { let inbits: u64 = LEu32(self.buffer, self.pos) as u64; self.bits = ((inbits << 32) | (self.bits << (32 - self.nbits))) >> (32 - self.nbits); self.pos += 4; self.nbits += 32; } (self.bits & (0x0ffffffffu64 >> (32 - num))) as u32 } #[inline(always)] fn consume_bits(&mut self, num: u32) { self.nbits -= num; self.bits >>= num; } } impl<'a> BitPump for BitPumpMSB<'a> { #[inline(always)] fn peek_bits(&mut self, num: u32) -> u32 { if num > self.nbits { let inbits: u64 = BEu32(self.buffer, self.pos) as u64; self.bits = (self.bits << 32) | inbits; self.pos += 4; self.nbits += 32; } (self.bits >> (self.nbits - num)) as u32 } #[inline(always)] fn consume_bits(&mut self, num: u32) { self.nbits -= num; self.bits &= (1 << self.nbits) - 1; } } impl<'a> BitPump for BitPumpMSB32<'a> { #[inline(always)] fn peek_bits(&mut self, num: u32) -> u32 { if num > self.nbits { let inbits: u64 = LEu32(self.buffer, self.pos) as u64; self.bits = (self.bits << 32) | inbits; self.pos += 4; self.nbits += 32; } (self.bits >> (self.nbits - num)) as u32 } #[inline(always)] fn consume_bits(&mut self, num: u32) { self.nbits -= num; self.bits &= (1 << self.nbits) - 1; } } impl<'a> BitPump for BitPumpJPEG<'a> { #[inline(always)] fn peek_bits(&mut self, num: u32) -> u32 { if num > self.nbits && !self.finished { if (self.buffer.len() >= 4) && self.pos < self.buffer.len() - 4 && self.buffer[self.pos + 0] != 0xff && self.buffer[self.pos + 1] != 0xff && self.buffer[self.pos + 2] != 0xff && self.buffer[self.pos + 3] != 0xff { let inbits: u64 = BEu32(self.buffer, self.pos) as u64; self.bits = (self.bits << 32) | inbits; self.pos += 4; self.nbits += 32; } else { // Read 32 bits the hard way let mut read_bytes = 0; while read_bytes < 4 && !self.finished { let byte = { if self.pos >= self.buffer.len() { self.finished = true; 0 } else { let nextbyte = self.buffer[self.pos]; if nextbyte != 0xff { nextbyte } else if self.buffer[self.pos + 1] == 0x00 { self.pos += 1; // Skip the extra byte used to mark 255 nextbyte } else { self.finished = true; 0 } } }; self.bits = (self.bits << 8) | (byte as u64); self.pos += 1; self.nbits += 8; read_bytes += 1; } } } if num > self.nbits && self.finished { // Stuff with zeroes to not fail to read self.bits <<= 32; self.nbits += 32; } (self.bits >> (self.nbits - num)) as u32 } #[inline(always)] fn consume_bits(&mut self, num: u32) { debug_assert!(num <= self.nbits); self.nbits -= num; self.bits &= (1 << self.nbits) - 1; } } #[derive(Debug, Copy, Clone)] pub struct ByteStream<'a> { buffer: &'a [u8], pos: usize, endian: Endian, } impl<'a> ByteStream<'a> { pub fn new(src: &'a [u8], endian: Endian) -> Self { Self { buffer: src, pos: 0, endian } } #[inline(always)] pub fn remaining_bytes(&self) -> usize { self.buffer.len() - self.pos } #[inline(always)] pub fn get_pos(&self) -> usize { self.pos } #[inline(always)] pub fn peek_u8(&self) -> u8 { self.buffer[self.pos] } #[inline(always)] pub fn get_u8(&mut self) -> u8 { let val = self.peek_u8(); self.pos += 1; val } #[inline(always)] pub fn peek_i8(&self) -> i8 { self.buffer[self.pos] as i8 } #[inline(always)] pub fn get_i8(&mut self) -> i8 { let val = self.peek_i8(); self.pos += 1; val } #[inline(always)] pub fn peek_u16(&self) -> u16 { self.endian.read_u16(self.buffer, self.pos) } #[inline(always)] pub fn get_u16(&mut self) -> u16 { let val = self.peek_u16(); self.pos += 2; val } #[inline(always)] pub fn peek_i16(&self) -> i16 { self.endian.read_i16(self.buffer, self.pos) } #[inline(always)] pub fn get_i16(&mut self) -> i16 { let val = self.peek_i16(); self.pos += 2; val } #[inline(always)] pub fn peek_u32(&self) -> u32 { self.endian.read_u32(self.buffer, self.pos) } #[inline(always)] pub fn get_u32(&mut self) -> u32 { let val = self.peek_u32(); self.pos += 4; val } #[inline(always)] pub fn get_bytes(&mut self, n: usize) -> Vec { let mut val = Vec::with_capacity(n); val.extend_from_slice(&self.buffer[self.pos..self.pos + n]); self.pos += n; val } // #[inline(always)] // pub fn peek_u32(&self) -> u32 { self.endian.ru32(self.buffer, self.pos) } // #[inline(always)] // pub fn get_u32(&mut self) -> u32 { // let val = self.peek_u32(); // self.pos += 4; // val // } #[inline(always)] pub fn consume_bytes(&mut self, num: usize) { self.pos += num } #[inline(always)] pub fn skip_to_marker(&mut self) -> Result { let mut skip_count = 0; while !(self.buffer[self.pos] == 0xFF && self.buffer[self.pos + 1] != 0 && self.buffer[self.pos + 1] != 0xFF) { self.pos += 1; skip_count += 1; if self.pos >= self.buffer.len() { return Err("No marker found inside rest of buffer".to_string()); } } self.pos += 1; // Make the next byte the marker Ok(skip_count + 1) } } /// This pump is for bitstreams where values are stored in LSB bit order. /// During refill, bits are converted from LSB to MSB so peaking /// is done by reading in MSB mode. /// /// Input bitstream is: 1011 0101 0010 1110... /// Output for peek(10) is: 1010 1101 01 #[derive(Debug, Copy, Clone)] pub struct BitPumpReverseBitsMSB<'a> { buffer: &'a [u8], pos: usize, bits: u64, nbits: u32, } impl<'a> BitPumpReverseBitsMSB<'a> { pub fn new(src: &'a [u8]) -> Self { Self { buffer: src, pos: 0, bits: 0, nbits: 0, } } } impl<'a> BitPump for BitPumpReverseBitsMSB<'a> { #[inline(always)] fn peek_bits(&mut self, num: u32) -> u32 { debug_assert!(num <= 32); if num > self.nbits { let mut raw: [u8; 4] = BEu32(self.buffer, self.pos).to_ne_bytes(); raw[0] = raw[0].reverse_bits(); raw[1] = raw[1].reverse_bits(); raw[2] = raw[2].reverse_bits(); raw[3] = raw[3].reverse_bits(); let inbits: u64 = u32::from_ne_bytes(raw) as u64; self.bits = (self.bits << 32) | inbits; self.pos += 4; self.nbits += 32; } (self.bits >> (self.nbits - num)) as u32 } #[inline(always)] fn consume_bits(&mut self, num: u32) { self.nbits -= num; self.bits &= (1 << self.nbits) - 1; } } rawler-0.7.1/src/rawimage.rs000064400000000000000000000506651046102023000140720ustar 00000000000000use std::borrow::Cow; use std::collections::HashMap; use itertools::Itertools; use log::debug; use serde::{Deserialize, Serialize}; use crate::Result; use crate::cfa::PlaneColor; use crate::imgop::raw::{correct_blacklevel, correct_blacklevel_cfa}; use crate::imgop::{convert_from_f32_scaled_u16, convert_to_f32_unscaled}; use crate::pixarray::SubPixel; use crate::{ CFA, decoders::*, formats::tiff::{Rational, Value}, imgop::{ Dim2, Point, Rect, raw::{ColorMatrix, DevelopParams}, xyz::{FlatColorMatrix, Illuminant}, }, pixarray::PixU16, tags::TiffTag, }; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct WhiteLevel(pub Vec); impl Default for WhiteLevel { fn default() -> Self { Self(vec![u16::MAX as u32; 1]) } } impl WhiteLevel { pub fn new(level: impl Into>) -> Self { Self(level.into()) } pub fn new_bits(bits: u32, cpp: usize) -> Self { if bits > 32 { panic!("Whitelevel can only be calculated for max. 32 bits, but {} bits given", bits); } let level: u32 = ((1_u64 << bits) - 1) as u32; Self(vec![level; cpp]) } pub fn as_vec(&self) -> Vec { self.0.iter().cloned().map(|x| x as f32).collect_vec() } pub fn as_bayer_array(&self) -> [f32; 4] { if self.0.len() == 4 { [self.0[0] as f32, self.0[1] as f32, self.0[2] as f32, self.0[3] as f32] } else { [self.0[0] as f32, self.0[0] as f32, self.0[0] as f32, self.0[0] as f32] } } } #[derive(Clone, PartialEq, Serialize, Deserialize)] pub struct BlackLevel { pub levels: Vec, pub cpp: usize, pub width: usize, pub height: usize, } impl Default for BlackLevel { fn default() -> Self { Self { levels: [Rational::from(0_u32)].into(), width: 1, height: 1, cpp: 1, } } } impl std::fmt::Debug for BlackLevel { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let levels: Vec = self.levels.iter().map(|x| x.as_f32()).collect(); f.write_fmt(format_args!("RepeatDim: {}:{}, cpp: {}, {:?}", self.height, self.width, self.cpp, levels)) } } impl BlackLevel { pub fn new(levels: &[T], width: usize, height: usize, cpp: usize) -> Self where T: Copy + Into, { assert_eq!(levels.len(), width * height * cpp); Self { levels: levels.iter().map(|x| (*x).into()).collect(), width, height, cpp, } } pub fn zero(width: usize, height: usize, cpp: usize) -> Self { if width == 0 || height == 0 || cpp == 0 { panic!( "Blacklevel::zero() must not be called with zero value arguments: width: {}, height: {}, cpp: {}", width, height, cpp ); } Self { levels: vec![0_u16; cpp * width * height].iter().map(|x| Rational::from(*x)).collect(), width, height, cpp, } } pub fn as_vec(&self) -> Vec { self.levels.iter().map(Rational::as_f32).collect_vec() } pub fn as_bayer_array(&self) -> [f32; 4] { if self.levels.len() == 4 { [ self.levels[0].as_f32(), self.levels[1].as_f32(), self.levels[2].as_f32(), self.levels[3].as_f32(), ] } else { [ self.levels[0].as_f32(), self.levels[0].as_f32(), self.levels[0].as_f32(), self.levels[0].as_f32(), ] } } pub fn sample_count(&self) -> usize { self.cpp * self.width * self.height } // TODO: write test pub fn shift(&self, x: usize, y: usize) -> Self { if self.sample_count() == 1 { self.clone() } else { let mut trans = self.clone(); let (w, h, cpp) = (trans.width, trans.height, trans.cpp); for yn in 0..h { for xn in 0..w { let ys = (yn + y) % h; let xs = (xn + x) % w; trans.levels[yn * w * cpp + xn * cpp..yn * w * cpp + xn * cpp + cpp] .copy_from_slice(&self.levels[ys * w * cpp + xs * cpp..ys * w * cpp + xs * cpp + cpp]); } } trans } } } #[allow(clippy::large_enum_variant)] #[derive(Debug, Clone, PartialEq)] pub enum RawPhotometricInterpretation { BlackIsZero, // Defined by DNG Cfa(CFAConfig), LinearRaw, } #[derive(Debug, Clone, PartialEq)] pub struct CFAConfig { pub cfa: CFA, pub colors: PlaneColor, } impl CFAConfig { pub fn new(cfa: &CFA, colors: &PlaneColor) -> Self { Self { cfa: cfa.clone(), colors: colors.clone(), } } pub fn new_from_camera(cam: &Camera) -> Self { Self { cfa: cam.cfa.clone(), colors: cam.plane_color.clone(), } } } /// All the data needed to process this raw image, including the image data itself as well /// as all the needed metadata #[derive(Debug, Clone)] pub struct RawImage { /// Camera definition pub camera: Camera, /// camera make as encoded in the file pub make: String, /// camera model as encoded in the file pub model: String, /// make cleaned up to be consistent and short pub clean_make: String, /// model cleaned up to be consistent and short pub clean_model: String, /// width of the full image pub width: usize, /// height of the full image pub height: usize, /// number of components per pixel (1 for bayer, 3 for RGB images) pub cpp: usize, /// Bits per pixel pub bps: usize, /// whitebalance coefficients encoded in the file in RGBE order pub wb_coeffs: [f32; 4], /// image whitelevels in RGBE order pub whitelevel: WhiteLevel, /// image blacklevels in RGBE order pub blacklevel: BlackLevel, /// matrix to convert XYZ to camera RGBE pub xyz_to_cam: [[f32; 3]; 4], // TODO: deprecated, use color_matrix /// Photometric interpretation pub photometric: RawPhotometricInterpretation, /// how much to crop the image to get all the usable (non-black) area pub active_area: Option, /// how much to crop the image to get all the recommended area pub crop_area: Option, /// Areas of the sensor that is masked to prevent it from receiving light. Used to calculate /// black levels and noise. pub blackareas: Vec, /// orientation of the image as indicated by the image metadata pub orientation: Orientation, /// image data itself, has `width`\*`height`\*`cpp` elements pub data: RawImageData, pub color_matrix: HashMap, pub dng_tags: HashMap, } /// The actual image data, after decoding #[derive(Debug, Clone)] pub enum RawImageData { /// The most usual u16 output of almost all formats Integer(Vec), /// Some formats are directly encoded as f32, most notably some DNGs Float(Vec), } impl RawImageData { pub fn as_f32<'a>(&'a self) -> Cow<'a, Vec> { match self { Self::Integer(data) => Cow::Owned(convert_to_f32_unscaled(data)), Self::Float(data) => Cow::Borrowed(data), } } pub fn force_integer(&mut self) { if let Self::Float(data) = self { *self = Self::Integer(convert_from_f32_scaled_u16(data, 0, u16::MAX)); } } } impl RawImage { pub fn calc_black_levels(cfa: &CFA, blackareas: &[Rect], width: usize, _height: usize, image: &[T]) -> Option where T: SubPixel, { let x = cfa.width * cfa.height; if x == 0 { return None; } assert!(!image.is_empty()); #[derive(Clone, Copy)] struct Sample { avg: f32, count: usize, } if !blackareas.is_empty() { let mut samples = vec![Sample { avg: 0.0, count: 0 }; x]; for area in blackareas { for row in area.p.y..area.p.y + area.d.h { for col in area.p.x..area.p.x + area.d.w { //let color = cfa.color_at(row, col); let color = (row % cfa.height) * cfa.width + (col % cfa.width); samples[color].avg += image[row * width + col].as_f32(); samples[color].count += 1; } } } let blacklevels: Vec = samples.into_iter().map(|s| (s.avg / s.count as f32)).collect(); debug!("Calculated blacklevels: {:?}", blacklevels); // TODO: support other then RGGB levels assert_eq!(cfa.width * cfa.height, 4); Some(BlackLevel::new(&[blacklevels[0], blacklevels[1], blacklevels[2], blacklevels[3]], 2, 2, 1)) } else { None } } #[doc(hidden)] pub fn new( cam: Camera, image: PixU16, cpp: usize, wb_coeffs: [f32; 4], photometric: RawPhotometricInterpretation, blacklevel: Option, whitelevel: Option, dummy: bool, ) -> RawImage { assert_eq!(image.width % cpp, 0); assert_eq!(dummy, !image.is_initialized()); let sample_width = image.width; let pixel_width = image.width / cpp; let mut blackareas: Vec = Vec::new(); let active_area = cam.active_area.map(|area| Rect::new_with_borders(Dim2::new(pixel_width, image.height), &area)); let blackarea_base = active_area.unwrap_or_else(|| Rect::new(Point::zero(), Dim2::new(sample_width, image.height))); // For now, we only use masked areas when cpp is 1. For color images (RGB) // like Canon SRAW, we ignore it (it isn't provided anyway). if cpp == 1 { // Build black areas // First value (.0) is start and (.1) is length! if let Some(ah) = cam.blackareah { blackareas.push(Rect::new_with_points( Point::new(blackarea_base.p.x, ah.0), Point::new(blackarea_base.p.x + blackarea_base.d.w, ah.0 + ah.1), )); } if let Some(av) = cam.blackareav { blackareas.push(Rect::new_with_points( Point::new(av.0, blackarea_base.p.y), Point::new(av.0 + av.1, blackarea_base.p.y + blackarea_base.d.h), )); } } let blacklevel = cam .make_blacklevel(cpp) .or_else(|| if cam.find_hint("invalid_blacklevel") { None } else { blacklevel }) .or_else(|| { if dummy { Some(BlackLevel::default()) } else { Self::calc_black_levels::(&cam.cfa, &blackareas, image.width, image.height, image.pixels()) } }) .unwrap_or_else(|| BlackLevel::zero(1, 1, cpp)); let whitelevel = cam .make_whitelevel(cpp) .or(whitelevel) .unwrap_or_else(|| panic!("Need whitelevel in config: {}", cam.clean_model)); let crop_area = cam.crop_area.map(|area| Rect::new_with_borders(Dim2::new(pixel_width, image.height), &area)); RawImage { camera: cam.clone(), make: cam.make.clone(), model: cam.model.clone(), clean_make: cam.clean_make.clone(), clean_model: cam.clean_model.clone(), width: image.width / cpp, height: image.height, cpp, bps: cam.real_bps, wb_coeffs, data: RawImageData::Integer(image.into_inner()), blacklevel, whitelevel, xyz_to_cam: cam.xyz_to_cam, photometric, active_area, crop_area, blackareas, orientation: Orientation::Normal, //cam.orientation, // TODO fixme color_matrix: cam.color_matrix, dng_tags: HashMap::new(), } } #[doc(hidden)] pub fn new_with_data( cam: Camera, image: RawImageData, sample_width: usize, height: usize, cpp: usize, wb_coeffs: [f32; 4], photometric: RawPhotometricInterpretation, blacklevel: Option, whitelevel: Option, dummy: bool, ) -> RawImage { //assert_eq!(image.width % cpp, 0); //assert_eq!(dummy, !image.is_initialized()); let pixel_width = sample_width / cpp; let mut blackareas: Vec = Vec::new(); let active_area = cam.active_area.map(|area| Rect::new_with_borders(Dim2::new(pixel_width, height), &area)); let blackarea_base = active_area.unwrap_or_else(|| Rect::new(Point::zero(), Dim2::new(sample_width, height))); // For now, we only use masked areas when cpp is 1. For color images (RGB) // like Canon SRAW, we ignore it (it isn't provided anyway). if cpp == 1 { // Build black areas // First value (.0) is start and (.1) is length! if let Some(ah) = cam.blackareah { blackareas.push(Rect::new_with_points( Point::new(blackarea_base.p.x, ah.0), Point::new(blackarea_base.p.x + blackarea_base.d.w, ah.0 + ah.1), )); } if let Some(av) = cam.blackareav { blackareas.push(Rect::new_with_points( Point::new(av.0, blackarea_base.p.y), Point::new(av.0 + av.1, blackarea_base.p.y + blackarea_base.d.h), )); } } let blacklevel = cam .make_blacklevel(cpp) .or_else(|| if cam.find_hint("invalid_blacklevel") { None } else { blacklevel }) .or_else(|| { if dummy { Some(BlackLevel::default()) } else { match &image { RawImageData::Integer(pix) => Self::calc_black_levels(&cam.cfa, &blackareas, sample_width, height, pix), RawImageData::Float(pix) => Self::calc_black_levels(&cam.cfa, &blackareas, sample_width, height, pix), } } }) .unwrap_or_else(|| BlackLevel::zero(1, 1, cpp)); let whitelevel = cam .make_whitelevel(cpp) .or(whitelevel) .unwrap_or_else(|| panic!("Need whitelvel in config: {}", cam.clean_model)); let crop_area = cam.crop_area.map(|area| Rect::new_with_borders(Dim2::new(pixel_width, height), &area)); RawImage { camera: cam.clone(), make: cam.make.clone(), model: cam.model.clone(), clean_make: cam.clean_make.clone(), clean_model: cam.clean_model.clone(), width: pixel_width, height: height, cpp, bps: cam.real_bps, wb_coeffs, data: image, blacklevel, whitelevel, xyz_to_cam: cam.xyz_to_cam, photometric, active_area, crop_area, blackareas, orientation: Orientation::Normal, //cam.orientation, // TODO fixme color_matrix: cam.color_matrix, dng_tags: HashMap::new(), } } pub fn dim(&self) -> Dim2 { Dim2::new(self.width, self.height) } pub fn pixels_u16(&self) -> &[u16] { if let RawImageData::Integer(data) = &self.data { data } else { panic!("Data ist not u16"); } } pub fn pixels_u16_mut(&mut self) -> &mut [u16] { if let RawImageData::Integer(data) = &mut self.data { data } else { panic!("Data ist not u16"); } } /// Apply blacklevel and whitelevel scaling, replacing raw image data /// with floating point values in range 0.0 .. 1.0. /// Internal blacklevel and whitelevel is reset to 0.0 and 1.0 to match image data. pub fn apply_scaling(&mut self) -> crate::Result<()> { let mut pixels = self.data.as_f32(); match &self.photometric { RawPhotometricInterpretation::BlackIsZero => todo!(), RawPhotometricInterpretation::Cfa(_) => { correct_blacklevel_cfa( pixels.to_mut(), self.width, self.height, &self.blacklevel.as_bayer_array(), &self.whitelevel.as_bayer_array(), ); self.data = RawImageData::Float(pixels.into_owned()); } RawPhotometricInterpretation::LinearRaw => { correct_blacklevel(pixels.to_mut(), &self.blacklevel.as_vec(), &self.whitelevel.as_vec()); self.data = RawImageData::Float(pixels.into_owned()); } } self.blacklevel.levels.iter_mut().for_each(|x| *x = Rational::new(0, 1)); self.whitelevel.0.iter_mut().for_each(|x| *x = 1); Ok(()) } pub fn develop_params(&self) -> Result { let mut xyz2cam: [[f32; 3]; 4] = [[0.0; 3]; 4]; //let color_matrix = self.color_matrix.get(&Illuminant::D65).unwrap(); // TODO fixme let color_matrix = self .color_matrix .values() .next() .cloned() .unwrap_or(vec![1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]); // TODO: invalid assert_eq!(color_matrix.len() % 3, 0); // this is not so nice... let components = color_matrix.len() / 3; for i in 0..components { for j in 0..3 { xyz2cam[i][j] = color_matrix[i * 3 + j]; } } /* let active_area = Rect::new( Point::new(self.crops[3], self.crops[0]), Dim2::new(self.width - self.crops[3] - self.crops[1], self.height - self.crops[0] - self.crops[2]), ); */ debug!("RAW developing active area: {:?}", self.active_area); let wb_coeff = if self.wb_coeffs[0].is_nan() { [1.0, 1.0, 1.0, 1.0] } else { self.wb_coeffs }; let params = DevelopParams { width: self.width, height: self.height, color_matrices: vec![ColorMatrix { illuminant: Illuminant::D65, // TODO: need CAT matrix: xyz2cam, }], whitelevel: self.whitelevel.clone(), blacklevel: self.blacklevel.clone(), //pattern, photometric: self.photometric.clone(), wb_coeff, cpp: self.cpp, active_area: self.active_area, crop_area: self.crop_area, //gamma: 2.4, }; Ok(params) } /// Add a DNG tag override pub fn add_dng_tag>(&mut self, tag: T, value: V) { let tag: u16 = tag.into(); self.dng_tags.insert(tag, value.into()); } pub fn linearize(&self) -> Result { todo!() } /// Outputs the inverted matrix that converts pixels in the camera colorspace into /// XYZ components. pub fn cam_to_xyz(&self) -> [[f32; 4]; 3] { self.pseudoinverse(self.xyz_to_cam) } /// Outputs the inverted matrix that converts pixels in the camera colorspace into /// XYZ components normalized to be easily used to convert to Lab or a RGB output space pub fn cam_to_xyz_normalized(&self) -> [[f32; 4]; 3] { let mut xyz_to_cam = self.xyz_to_cam; // Normalize xyz_to_cam so that xyz_to_cam * (1,1,1) is (1,1,1,1) for i in 0..4 { let mut num = 0.0; for j in 0..3 { num += xyz_to_cam[i][j]; } for j in 0..3 { xyz_to_cam[i][j] = if num == 0.0 { 0.0 } else { xyz_to_cam[i][j] / num }; } } self.pseudoinverse(xyz_to_cam) } /// Not all cameras encode a whitebalance so in those cases just using a 6500K neutral one /// is a good compromise pub fn neutralwb(&self) -> [f32; 4] { let rgb_to_xyz = [ // sRGB D65 [0.412453, 0.357580, 0.180423], [0.212671, 0.715160, 0.072169], [0.019334, 0.119193, 0.950227], ]; // Multiply RGB matrix let mut rgb_to_cam = [[0.0; 3]; 4]; for i in 0..4 { for j in 0..3 { rgb_to_cam[i][j] = 0.0; for k in 0..3 { rgb_to_cam[i][j] += self.xyz_to_cam[i][k] * rgb_to_xyz[k][j]; } } } let mut neutralwb = [0 as f32; 4]; for i in 0..4 { let mut num = 0.0; for j in 0..3 { num += rgb_to_cam[i][j]; } neutralwb[i] = 1.0 / num; } [ neutralwb[0] / neutralwb[1], neutralwb[1] / neutralwb[1], neutralwb[2] / neutralwb[1], neutralwb[3] / neutralwb[1], ] } fn pseudoinverse(&self, inm: [[f32; 3]; 4]) -> [[f32; 4]; 3] { let mut temp: [[f32; 6]; 3] = [[0.0; 6]; 3]; for i in 0..3 { for j in 0..6 { temp[i][j] = if j == i + 3 { 1.0 } else { 0.0 }; } for j in 0..3 { for k in 0..4 { temp[i][j] += inm[k][i] * inm[k][j]; } } } for i in 0..3 { let mut num = temp[i][i]; for j in 0..6 { temp[i][j] /= num; } for k in 0..3 { if k == i { continue; } num = temp[k][i]; for j in 0..6 { temp[k][j] -= temp[i][j] * num; } } } let mut out: [[f32; 4]; 3] = [[0.0; 4]; 3]; for i in 0..4 { for j in 0..3 { out[j][i] = 0.0; for k in 0..3 { out[j][i] += temp[j][k + 3] * inm[i][k]; } } } out } /// Returns the CFA pattern after the crop has been applied (and thus the pattern /// potentially shifted) pub fn cropped_cfa(&self) -> CFA { //self.cfa.shift(self.crops[3], self.crops[0]) todo!() // Need to specify which crop, active or DefaultCrop } /// Checks if the image is monochrome pub fn is_monochrome(&self) -> bool { self.photometric == RawPhotometricInterpretation::BlackIsZero //self.cpp == 1 && !self.cfa.is_valid() } } #[cfg(test)] mod tests { use super::*; #[test] fn blacklevel_shift() -> std::result::Result<(), Box> { let black = BlackLevel::new(&[1_u16, 2, 3, 4], 2, 2, 1).shift(1, 1); assert_eq!(black.levels, vec![4_u16, 3, 2, 1].into_iter().map(Rational::from).collect::>()); let black = BlackLevel::new(&[1_u16, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], 2, 2, 3).shift(3, 3); assert_eq!( black.levels, vec![4_u16, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1] .into_iter() .map(Rational::from) .collect::>() ); Ok(()) } } rawler-0.7.1/src/rawsource.rs000064400000000000000000000073711046102023000143040ustar 00000000000000use std::{ fmt::Debug, fs::File, io::Cursor, iter::repeat, ops::Deref, path::{Path, PathBuf}, sync::Arc, }; use md5::Digest; use memmap2::MmapOptions; use crate::buffer::PaddedBuf; pub struct RawSource { path: PathBuf, inner: RawSourceImpl, } enum RawSourceImpl { Memmap(memmap2::Mmap), Memory(Arc>), } impl RawSource { pub fn new(path: &Path) -> std::io::Result { let file = File::open(path)?; let mmap = unsafe { MmapOptions::new().populate().map(&file)? }; #[cfg(unix)] { mmap.advise(memmap2::Advice::WillNeed)?; mmap.advise(memmap2::Advice::Sequential)?; } Ok(Self { path: path.canonicalize().unwrap_or_else(|_| path.to_owned()), inner: RawSourceImpl::Memmap(mmap), }) } pub fn new_from_shared_vec(buf: Arc>) -> Self { Self { path: PathBuf::default(), inner: RawSourceImpl::Memory(buf), } } pub fn with_path(self, path: impl AsRef) -> Self { Self { path: path.as_ref().to_owned(), inner: self.inner, } } pub fn new_from_slice(buf: &[u8]) -> Self { Self::new_from_shared_vec(Arc::new(Vec::from(buf))) } /// Calculate digest for file pub fn digest(&self) -> Digest { md5::compute(self.buf()) } pub fn path(&self) -> &Path { &self.path } pub fn buf(&self) -> &[u8] { self.deref() } pub fn subview(&self, offset: u64, size: u64) -> std::io::Result<&[u8]> { self.buf().get(offset as usize..(offset + size) as usize).ok_or(std::io::Error::new( std::io::ErrorKind::UnexpectedEof, format!("subview(): Offset {}+{} is behind EOF", offset, size), )) } pub fn subview_padded(&self, offset: u64, size: u64) -> std::io::Result> { if offset + size <= self.len() as u64 { if offset + size + 16 <= self.len() as u64 { self.subview(offset, size + 16).map(|buf| PaddedBuf::new_ref(buf, size as usize)) } else { let mut buf = Vec::with_capacity((size + 16) as usize); buf.extend_from_slice(self.subview(offset, size)?); buf.extend(repeat(0).take(16)); Ok(PaddedBuf::new_owned(buf, size as usize)) } } else { Err(std::io::Error::new( std::io::ErrorKind::UnexpectedEof, format!("subview_padded(): Offset {}+{} is behind EOF", offset, size), )) } } pub fn subview_until_eof(&self, offset: u64) -> std::io::Result<&[u8]> { self.buf().get(offset as usize..).ok_or(std::io::Error::new( std::io::ErrorKind::UnexpectedEof, format!("subview_until_eof(): Offset {} is behind EOF", offset), )) } pub fn subview_until_eof_padded(&self, offset: u64) -> std::io::Result> { if offset < self.len() as u64 { let mut buf = Vec::with_capacity((self.len() - offset as usize + 16) as usize); buf.extend_from_slice(self.subview_until_eof(offset)?); buf.extend(repeat(0).take(16)); Ok(PaddedBuf::new_owned(buf, self.len() - offset as usize)) } else { Err(std::io::Error::new( std::io::ErrorKind::UnexpectedEof, format!("subview_until_eof_padded(): Offset {} is behind EOF", offset), )) } } pub fn reader(&self) -> Cursor<&[u8]> { Cursor::new(self.buf()) } pub fn as_vec(&self) -> std::io::Result> { Ok(self.buf().to_vec()) } pub fn stream_len(&mut self) -> u64 { self.buf().len() as u64 } } impl Deref for RawSource { type Target = [u8]; fn deref(&self) -> &Self::Target { match &self.inner { RawSourceImpl::Memmap(mmap) => mmap.deref(), RawSourceImpl::Memory(mem) => mem.deref(), } } } impl Debug for RawSource { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("RawSource").field("path", &self.path).finish() } } rawler-0.7.1/src/tags.rs000064400000000000000000000404671046102023000132330ustar 00000000000000// SPDX-License-Identifier: MIT // Copyright 2021 Daniel Vogelbacher use std::convert::TryFrom; use std::fmt::Debug; macro_rules! tiff_tag_enum { ($e:ty) => { impl From<$e> for u16 { fn from(val: $e) -> u16 { val as u16 } } impl TryFrom for $e { type Error = String; fn try_from(value: u16) -> std::result::Result { Self::n(value).ok_or(format!("Unable to convert tag: {}, not defined in enum", value)) } } impl crate::tags::TiffTag for $e {} }; } pub(crate) use tiff_tag_enum; /// A TIFF compatible tag identifier pub trait TiffTag: Into + TryFrom + Debug + Sized + Copy {} impl TiffTag for u16 {} tiff_tag_enum!(TiffCommonTag); tiff_tag_enum!(ExifTag); tiff_tag_enum!(ExifGpsTag); tiff_tag_enum!(DngTag); /// Common tags, generally used in root IFD or SubIFDs #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum TiffCommonTag { PanaWidth = 0x0002, PanaLength = 0x0003, NefWB0 = 0x000C, //PanaWBsR = 0x0011, //PanaWBsB = 0x0012, NrwWB = 0x0014, NefSerial = 0x001d, //PanaWBs2R = 0x0024, //PanaWBs2G = 0x0025, //PanaWBs2B = 0x0026, Cr2PowerShotWB = 0x0029, NewSubFileType = 0x00FE, Cr2OldOffset = 0x0081, NefMeta1 = 0x008c, NefMeta2 = 0x0096, NefWB1 = 0x0097, Cr2OldWB = 0x00A4, NefKey = 0x00a7, ImageWidth = 0x0100, ImageLength = 0x0101, BitsPerSample = 0x0102, SampleFormat = 339, RowsPerStrip = 278, XResolution = 282, YResolution = 283, ResolutionUnit = 296, // TODO add support Artist = 315, Compression = 0x0103, PhotometricInt = 0x0106, Make = 0x010F, Model = 0x0110, StripOffsets = 0x0111, Orientation = 0x0112, SamplesPerPixel = 0x0115, StripByteCounts = 0x0117, PanaOffsets = 0x0118, GrayResponse = 0x0123, Software = 0x0131, Predictor = 0x013D, TileWidth = 0x0142, TileLength = 0x0143, TileOffsets = 0x0144, TileByteCounts = 0x0145, SubIFDs = 0x014A, PefBlackLevels = 0x0200, PefWB = 0x0201, PefHuffman = 0x0220, Xmp = 0x02BC, DcrWB = 0x03FD, DcrLinearization = 0x090D, EpsonWB = 0x0E80, KodakWB = 0x0F00, RafOldWB = 0x2ff0, Cr2ColorData = 0x4001, SonyCurve = 0x7010, SonyOffset = 0x7200, SonyLength = 0x7201, SonyKey = 0x7221, KodakIFD = 0x8290, LeafMetadata = 0x8606, ExifIFDPointer = 0x8769, Makernote = 0x927C, SrwSensorAreas = 0xA010, Cr2Id = 0xc5d8, DNGVersion = 0xC612, Linearization = 0xC618, BlackLevels = 0xC61A, WhiteLevel = 0xC61D, ColorMatrix1 = 0xC621, ColorMatrix2 = 0xC622, AsShotNeutral = 0xC628, DNGPrivateArea = 0xC634, Cr2StripeWidths = 0xC640, ActiveArea = 0xC68D, MaskedAreas = 0xC68E, TimeCodes = 0xC763, FrameFrate = 0xC764, TStop = 0xC772, RafRawSubIFD = 0xF000, RafImageWidth = 0xF001, RafImageLength = 0xF002, RafBitsPerSample = 0xF003, //RafOffsets = 0xF007, RafWBGRB = 0xF00E, KdcWB = 0xFA2A, KdcWidth = 0xFD00, KdcLength = 0xFD01, KdcOffset = 0xFD04, KdcIFD = 0xFE00, // TIFF-EP CFAPattern = 0x828E, CFARepeatPatternDim = 33421, } /// EXIF GPS tags #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum ExifGpsTag { GPSVersionID = 0x0000, GPSLatitudeRef = 0x0001, GPSLatitude = 0x0002, GPSLongitudeRef = 0x0003, GPSLongitude = 0x0004, GPSAltitudeRef = 0x0005, GPSAltitude = 0x0006, GPSTimeStamp = 0x0007, GPSSatellites = 0x0008, GPSStatus = 0x0009, GPSMeasureMode = 0x000a, GPSDOP = 0x000b, GPSSpeedRef = 0x000c, GPSSpeed = 0x000d, GPSTrackRef = 0x000e, GPSTrack = 0x000f, GPSImgDirectionRef = 0x0010, GPSImgDirection = 0x0011, GPSMapDatum = 0x0012, GPSDestLatitudeRef = 0x0013, GPSDestLatitude = 0x0014, GPSDestLongitudeRef = 0x0015, GPSDestLongitude = 0x0016, GPSDestBearingRef = 0x0017, GPSDestBearing = 0x0018, GPSDestDistanceRef = 0x0019, GPSDestDistance = 0x001a, GPSProcessingMethod = 0x001b, GPSAreaInformation = 0x001c, GPSDateStamp = 0x001d, GPSDifferential = 0x001e, GPSHPositioningError = 0x001f, } /// EXIF tags #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum ExifTag { InteropIndex = 0x0001, InteropVersion = 0x0002, ProcessingSoftware = 0x000b, SubfileType = 0x00fe, OldSubfileType = 0x00ff, ImageWidth = 0x100, ImageHeight = 0x101, BitsPerSample = 0x0102, Compression = 0x0103, PhotometricInterpretation = 0x0106, Thresholding = 0x0107, CellWidth = 0x0108, CellLength = 0x0109, FillOrder = 0x010a, DocumentName = 0x010d, ImageDescription = 0x010e, Make = 0x010f, Model = 0x0110, StripOffsets = 0x0111, Orientation = 0x0112, SamplesPerPixel = 0x0115, RowsPerStrip = 0x0116, StripByteCounts = 0x0117, MinSampleValue = 0x0118, MaxSampleValue = 0x0119, XResolution = 0x011a, YResolution = 0x011b, PlanarConfiguration = 0x011c, PageName = 0x011d, XPosition = 0x011e, YPosition = 0x011f, FreeOffsets = 0x0120, FreeByteCounts = 0x0121, GrayResponseUnit = 0x0122, GrayResponseCurve = 0x0123, T4Options = 0x0124, T6Options = 0x0125, ResolutionUnit = 0x0128, PageNumber = 0x0129, ColorResponseUnit = 0x012c, TransferFunction = 0x012d, Software = 0x0131, ModifyDate = 0x0132, Artist = 0x013b, HostComputer = 0x0103c, Predictor = 0x013d, WhitePoint = 0x013e, PrimaryChromaticities = 0x013f, ColorMap = 0x0140, HalftoneHints = 0x0141, TileWidth = 0x0142, TileLength = 0x0143, TileOffsets = 0x0144, TileByteCounts = 0x0145, BadFaxLines = 0x0146, CleanFaxData = 0x0147, ConsecutiveBadFaxLines = 0x0148, A100DataOffset = 0x014a, InkSet = 0x014c, InkNames = 0x014d, NumberofInks = 0x014e, DotRange = 0x0150, TargetPrinter = 0x0151, ExtraSamples = 0x0152, SampleFormat = 0x0153, SMinSampleValue = 0x0154, SMaxSampleValue = 0x0155, TransferRange = 0x0156, ClipPath = 0x0157, XClipPathUnits = 0x0158, YClipPathUnits = 0x0159, Indexed = 0x015a, JPEGTables = 0x015b, OPIProxy = 0x015f, GlobalParametersIFD = 0x0190, ProfileType = 0x0191, FaxProfile = 0x0192, CodingMethods = 0x0193, VersionYear = 0x0194, ModeNumber = 0x0195, Decode = 0x01b1, DefaultImageColor = 0x01b2, T82Options = 0x01b3, JPEGTables2 = 0x01b5, JPEGProc = 0x0200, JPEGInterchangeFormat = 0x0201, JPEGInterchangeFormatLength = 0x0202, JPEGRestartInterval = 0x0203, JPEGLosslessPredictors = 0x0205, JPEGPointTransforms = 0x0206, JPEGQTables = 0x0207, JPEGDCTables = 0x0208, JPEGACTables = 0x0209, YCbCrCoefficients = 0x0211, YCbCrSubSampling = 0x0212, YCbCrPositioning = 0x0213, ReferenceBlackWhite = 0x0214, StripRowCounts = 0x022f, ApplicationNotes = 0x02bc, USPTOMiscellaneous = 0x03e7, RelatedImageFileFormat = 0x1000, RelatedImageWidth = 0x1001, RelatedImageHeight = 0x1002, Rating = 0x4746, XpDipXml = 0x4747, StitchInfo = 0x4748, RatingPercent = 0x4749, SonyRawFileType = 0x7000, SonyToneCurve = 0x7010, VignettingCorrection = 0x7031, VignettingCorrParams = 0x7032, ChromaticAberrationCorrection = 0x7034, ChromaticAberrationCorrParams = 0x7035, DistortionCorrection = 0x7036, DistortionCorrParams = 0x7037, SonyRawImageSize = 0x7038, SonyCropTopLeft = 0x74c7, SonyCropSize = 0x74c8, ImageID = 0x800d, WangTag1 = 0x80a3, WangAnnotation = 0x80a4, WangTag3 = 0x80a5, WangTag4 = 0x80a6, ImageReferencePoints = 0x80b9, RegionXformTackPoint = 0x80ba, WarpQuadrilateral = 0x80bb, AffineTransformMat = 0x80bc, Matteing = 0x80e3, DataType = 0x80e4, ImageDepth = 0x80e5, TileDepth = 0x80e6, ImageFullWidth = 0x8214, ImageFullHeight = 0x8215, TextureFormat = 0x8216, WrapModes = 0x8217, FovCot = 0x8218, MatrixWorldToScreen = 0x8219, MatrixWorldToCamera = 0x821a, Model2 = 0x827d, CFARepeatPatternDim = 0x828d, CFAPattern2 = 0x828e, BatteryLevel = 0x828f, KodakIFD = 0x8290, Copyright = 0x8298, ExposureTime = 0x829a, FNumber = 0x829d, MDFileTag = 0x82a5, MDScalePixel = 0x82a6, MDColorTable = 0x82a7, MDLabName = 0x82a8, MDSampleInfo = 0x82a9, MDPrepDate = 0x82aa, MDPrepTime = 0x82ab, MDFileUnits = 0x82ac, PixelScale = 0x830e, AdventScale = 0x8335, AdventRevision = 0x8336, UIC1Tag = 0x835c, UIC2Tag = 0x835d, UIC3Tag = 0x835e, UIC4Tag = 0x835f, IptcNaa = 0x83bb, IntergraphPacketData = 0x847e, IntergraphFlagRegisters = 0x847f, IntergraphMatrix = 0x8480, INGRReserved = 0x8481, ModelTiePoint = 0x8482, Site = 0x84e0, ColorSequence = 0x84e1, IT8Header = 0x84e2, RasterPadding = 0x84e3, BitsPerRunLength = 0x84e4, BitsPerExtendedRunLength = 0x84e5, ColorTable = 0x84e6, ImageColorIndicator = 0x84e7, BackgroundColorIndicator = 0x84e8, ImageColorValue = 0x84e9, BackgroundColorValue = 0x84ea, PixelIntensityRange = 0x84eb, TransparencyIndicator = 0x84ec, ColorCharacterization = 0x84ed, HCUsage = 0x84ee, TrapIndicator = 0x84ef, CMYKEquivalent = 0x84f0, SEMInfo = 0x8546, AfcpIPTC = 0x8568, PixelMagicJBIGOptions = 0x85b8, JPLCartoIFD = 0x85d7, ModelTransform = 0x85d8, WbGRGBLevels = 0x8602, LeafData = 0x8606, PhotoshopSettings = 0x8649, ExifOffset = 0x8769, IccProfile = 0x8773, TiffFXExtensions = 0x877f, MultiProfiles = 0x8780, SharedData = 0x8781, T88Options = 0x8782, ImageLayer = 0x87ac, GeoTiffDirectory = 0x87af, GeoTiffDoubleParams = 0x87b0, GeoTiffAsciiParams = 0x87b1, JBIGOptions = 0x87be, ExposureProgram = 0x8822, SpectralSensitivity = 0x8824, GPSInfo = 0x8825, ISOSpeedRatings = 0x8827, ElectricConvFactor = 0x8828, Interlace = 0x8829, TimeZoneOffset = 0x882a, SelfTimerMode = 0x882b, SensitivityType = 0x8830, StandardOutputSensitivity = 0x8831, RecommendedExposureIndex = 0x8832, ISOSpeed = 0x8833, ISOSpeedLatitudeyyy = 0x8834, ISOSpeedLatitudezzz = 0x8835, LeafSubIFD = 0x888a, ExifVersion = 0x9000, DateTimeOriginal = 0x9003, CreateDate = 0x9004, GooglePlusUploadCode = 0x9009, OffsetTime = 0x9010, OffsetTimeOriginal = 0x9011, OffsetTimeDigitized = 0x9012, ComponentsConfiguration = 0x9101, CompressedBitsPerPixel = 0x9102, ShutterSpeedValue = 0x9201, ApertureValue = 0x9202, BrightnessValue = 0x9203, ExposureBiasValue = 0x9204, MaxApertureValue = 0x9205, SubjectDistance = 0x9206, MeteringMode = 0x9207, LightSource = 0x9208, Flash = 0x9209, FocalLength = 0x920a, FlashEnergy = 0x920b, SpatialFrequencyResponse = 0x920c, Noise2 = 0x920d, FocalPlaneXResolution = 0x920e, FocalPlaneYResolution = 0x920f, FocalPlaneResolutionUnit = 0x9210, ImageNumber = 0x9211, SecurityClassification = 0x9212, ImageHistory = 0x9213, SubjectArea = 0x9214, ExposureIndex = 0x9215, TiffEPStandardID = 0x9216, SensingMethod = 0x9217, CIP3DataFile = 0x923a, CIP3Sheet = 0x923b, CIP3Side = 0x923c, StoNits = 0x923f, MakerNotes = 0x927c, UserComment = 0x9286, SubSecTime = 0x9290, SubSecTimeOriginal = 0x9291, SubSecTimeDigitized = 0x9292, MSDocumentText = 0x932f, MSPropertySetStorage = 0x9330, MSDocumentTextPosition = 0x9331, ImageSourceData = 0x935c, AmbientTemperature = 0x9400, Humidity = 0x9401, Pressure = 0x9402, WaterDepth = 0x9403, Acceleration = 0x9404, CameraElevationAngle = 0x9405, XPTitle = 0x9c9b, XPComment = 0x9c9c, XPAuthor = 0x9c9d, XPKeywords = 0x9c9e, XPSubject = 0x9c9f, FlashpixVersion = 0xa000, ColorSpace = 0xa001, ExifImageWidth = 0xa002, ExifImageHeight = 0xa003, RelatedSoundFile = 0xa004, InteropOffset = 0xa005, SamsungRawPointersOffset = 0xa010, SamsungRawPointersLength = 0xa011, SamsungRawByteOrder = 0xa101, SamsungRawUnknown = 0xa102, FlashEnergy2 = 0xa20b, SpatialFrequencyResponse2 = 0xa20c, Noise = 0xa20d, FocalPlaneXResolution2 = 0xa20e, FocalPlaneYResolution2 = 0xa20f, FocalPlaneResolutionUnit2 = 0xa210, ImageNumber2 = 0xa211, SecurityClassification2 = 0xa212, ImageHistory2 = 0xa213, SubjectLocation = 0xa214, ExposureIndex2 = 0xa215, TiffEPStandardID2 = 0xa216, SensingMethod2 = 0xa217, FileSource = 0xa300, SceneType = 0xa301, CFAPattern = 0xa302, CustomRendered = 0xa401, ExposureMode = 0xa402, WhiteBalance = 0xa403, DigitalZoomRatio = 0xa404, FocalLengthIn35mmFormat = 0xa405, SceneCaptureType = 0xa406, GainControl = 0xa407, Contrast = 0xa408, Saturation = 0xa409, Sharpness = 0xa40a, DeviceSettingDescription = 0xa40b, SubjectDistanceRange = 0xa40c, ImageUniqueID = 0xa420, OwnerName = 0xa430, SerialNumber = 0xa431, LensSpecification = 0xa432, LensMake = 0xa433, LensModel = 0xa434, LensSerialNumber = 0xa435, CompositeImage = 0xa460, CompositeImageCount = 0xa461, CompositeImageExposureTimes = 0xa462, GDALMetadata = 0xa480, GDALNoData = 0xa481, Gamma = 0xa500, ExpandSoftware = 0xafc0, ExpandLens = 0xafc1, ExpandFilm = 0xafc2, ExpandFilterLens = 0xafc3, ExpandScanner = 0xafc4, ExpandFlashLamp = 0xafc5, HasselbladRawImage = 0xb4c3, PixelFormat = 0xbc01, Transformation = 0xbc02, Uncompressed = 0xbc03, ImageType = 0xbc04, Annotations = 0xc44f, PrintIM = 0xc4a5, HasselbladExif = 0xc51b, OriginalFileName = 0xc573, //ExifExposureTime = 0x829a, //ExifFNumber = 0x829d, //ExifISOSpeedRatings = 0x8827, //ExifVersion = 0x9000, //ExifLensModel = 0xa434, //ExifFocalLen = 0x920a, } /// DNG specific tags #[derive(Debug, Copy, Clone, PartialEq, enumn::N)] #[repr(u16)] pub enum DngTag { DNGVersion = 50706, DNGBackwardVersion = 50707, UniqueCameraModel = 50708, LocalizedCameraModel = 50709, CFAPlaneColor = 50710, CFALayout = 50711, LinearizationTable = 50712, BlackLevelRepeatDim = 50713, BlackLevel = 50714, BlackLevelDeltaH = 50715, BlackLevelDeltaV = 50716, WhiteLevel = 50717, DefaultScale = 50718, BestQualityScale = 50780, DefaultCropOrigin = 50719, DefaultCropSize = 50720, CalibrationIlluminant1 = 50778, CalibrationIlluminant2 = 50779, ColorMatrix1 = 50721, ColorMatrix2 = 50722, CameraCalibration1 = 50723, CameraCalibration2 = 50724, ReductionMatrix1 = 50725, ReductionMatrix2 = 50726, AnalogBalance = 50727, AsShotNeutral = 50728, AsShotWhiteXY = 50729, BaselineExposure = 50730, BaselineNoise = 50731, BaselineSharpness = 50732, BayerGreenSplit = 50733, LinearResponseLimit = 50734, CameraSerialNumber = 50735, LensInfo = 50736, ChromaBlurRadius = 50737, AntiAliasStrength = 50738, ShadowScale = 50739, DNGPrivateData = 50740, MakerNoteSafety = 50741, RawDataUniqueID = 50781, OriginalRawFileName = 50827, OriginalRawFileData = 50828, ActiveArea = 50829, MaskedAreas = 50830, AsShotICCProfile = 50831, AsShotPreProfileMatrix = 50832, CurrentICCProfile = 50833, CurrentPreProfileMatrix = 50834, // 1.2.0 ColorimetricReference = 50879, CameraCalibrationSignature = 50931, ProfileCalibrationSignature = 50932, ExtraCameraProfiles = 50933, AsShotProfileName = 50934, NoiseReductionApplied = 50935, ProfileName = 50936, ProfileHueSatMapDims = 50937, ProfileHueSatMapData1 = 50938, ProfileHueSatMapData2 = 50939, ProfileToneCurve = 50940, ProfileEmbedPolicy = 50941, ProfileCopyright = 50942, ForwardMatrix1 = 50964, ForwardMatrix2 = 50965, PreviewApplicationName = 50966, PreviewApplicationVersion = 50967, PreviewSettingsName = 50968, PreviewSettingsDigest = 50969, PreviewColorSpace = 50970, PreviewDateTime = 50971, RawImageDigest = 50972, OriginalRawFileDigest = 50973, SubTileBlockSize = 50974, RowInterleaveFactor = 50975, ProfileLookTableDims = 50981, ProfileLookTableData = 50982, // 1.3.0 OpcodeList1 = 51008, OpcodeList2 = 51009, OpcodeList3 = 51022, NoiseProfile = 51041, // 1.4.0 DefaultUserCrop = 51125, DefaultBlackRender = 51110, BaselineExposureOffset = 51109, ProfileLookTableEncoding = 51108, ProfileHueSatMapEncoding = 51107, OriginalDefaultFinalSize = 51089, OriginalBestQualityFinalSize = 51090, OriginalDefaultCropSize = 51091, NewRawImageDigest = 51111, RawToPreviewGain = 51112, // 1.5.0 DepthFormat = 51177, DepthNear = 51178, DepthFar = 51179, DepthUnits = 51180, DepthMeasureType = 51181, EnhanceParams = 51182, // 1.6.0 ProfileGainTableMap = 52525, SemanticName = 52526, SemanticInstanceID = 52528, MaskSubArea = 52536, RGBTables = 52543, CalibrationIlluminant3 = 52529, ColorMatrix3 = 52531, CameraCalibration3 = 52530, ReductionMatrix3 = 52538, ProfileHueSatMapData3 = 52537, ForwardMatrix3 = 52532, IlluminantData1 = 52533, IlluminantData2 = 52534, IlluminantData3 = 52535, // 1.7.1 ColumnInterleaveFactor = 52547, } rawler-0.7.1/src/tiles.rs000064400000000000000000000261121046102023000134040ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher use std::{iter, ops::Range}; use crate::pixarray::{LineMut, SubPixel}; #[derive(Debug)] pub struct ErrorNotTileable; /// Image tile generator pub struct ImageTiler<'a, T> { data: &'a [T], width: usize, #[allow(dead_code)] height: usize, cpp: usize, tiles: Range, tw: usize, th: usize, tcols: usize, trows: usize, } impl<'a, T> ImageTiler<'a, T> { pub fn new(data: &'a [T], width: usize, height: usize, cpp: usize, tw: usize, th: usize) -> Self { assert!(data.len() >= height * width * cpp); let tcols = width.div_ceil(tw); let trows = height.div_ceil(th); Self { data, width, height, cpp, tiles: Range { start: 0, end: trows * tcols }, tw, th, tcols, trows, } } pub fn tile_cols(&self) -> usize { self.tcols } pub fn tile_rows(&self) -> usize { self.trows } pub fn tile_count(&self) -> usize { self.tile_rows() * self.tile_cols() } fn needs_padding(&self) -> bool { self.width % self.tw > 0 } } impl<'a, T> Iterator for ImageTiler<'a, T> where T: Copy + Default, { type Item = Vec; fn next(&mut self) -> Option { if let Some(i) = self.tiles.next() { let mut buf = Vec::with_capacity(self.th * self.tw * self.cpp); let tile_row = i / self.tile_cols(); let tile_col = i % self.tile_cols(); //println!("Tile row: {}, col: {}", tile_row, tile_col); for row in 0..self.th { let off_row = (tile_row * self.th) + row; let offset = off_row * self.width * self.cpp + (tile_col * self.tw * self.cpp); if offset < self.data.len() { //println!("Fill row: {}", row); if tile_col < self.tile_cols() - 1 || !self.needs_padding() { let sub = &self.data[offset..offset + self.tw * self.cpp]; buf.extend_from_slice(sub); } else { buf.extend_from_slice(&self.data[offset..offset + (self.width % self.tw) * self.cpp]); let last_pix = buf.last().copied().unwrap_or_default(); buf.extend(iter::repeat(last_pix).take((self.tw - (self.width % self.tw)) * self.cpp)); }; } else { //println!("extend row: {}", row); buf.extend_from_within((row - 1) * self.tw * self.cpp..((row - 1) * self.tw * self.cpp) + self.tw * self.cpp); } } Some(buf) } else { None } } fn size_hint(&self) -> (usize, Option) { (self.tile_count(), Some(self.tile_count())) } } /// A trait for types that can be partitioned into mutable tiles. /// /// This trait allows splitting a collection or buffer of subpixels into /// mutable tiles of specified dimensions, returning an iterator over the tiles. /// /// # Type Parameters /// - `'a`: Lifetime of the data being tiled. /// - `T`: The subpixel type, which must implement the `SubPixel` trait. /// /// # Required Methods /// - `into_tiles_iter_mut`: Consumes `self` and returns a mutable iterator over tiles, /// or an error if the data cannot be tiled with the given dimensions. /// /// # Errors /// Returns `ErrorNotTileable` if the data cannot be partitioned into tiles /// with the specified width, tile width, or tile height. pub trait TilesMut<'a, T> where T: SubPixel, { fn into_tiles_iter_mut(self, width: usize, cpp: usize, tile_width: usize, tile_height: usize) -> std::result::Result, ErrorNotTileable>; } /// Implementation for mutable slices of T: SubPixel impl<'a, T> TilesMut<'a, T> for &'a mut [T] where T: SubPixel, { fn into_tiles_iter_mut(self, width: usize, cpp: usize, tile_width: usize, tile_height: usize) -> std::result::Result, ErrorNotTileable> { assert!(width > 0, "Width and height must be greater than zero"); assert!(tile_width * tile_height > 0, "Tile width and height must be greater than zero"); assert!(cpp > 0, "cpp must be greater than zero"); if !self.len().is_multiple_of(tile_width * cpp * tile_height) { return Err(ErrorNotTileable); } Ok(IntoTilesIter { count: 0, width, cpp, tile_width, tile_height, original: self, }) } } /// An iterator that splits a mutable slice into tiles of specified width and height. /// /// # Type Parameters /// - `T`: The type of elements in the slice. /// /// # Fields /// - `count`: The current tile index or count of tiles processed. /// - `width`: The width of the original image or data slice. /// - `tile_width`: The width of each tile. /// - `tile_height`: The height of each tile. /// - `original`: A mutable reference to the original data slice to be tiled. /// /// This iterator yields mutable references to tiles within the original slice, /// allowing for in-place modification of each tile. pub struct IntoTilesIter<'a, T> { count: usize, width: usize, cpp: usize, tile_width: usize, tile_height: usize, original: &'a mut [T], } impl<'a, T> IntoTilesIter<'a, T> { /// Returns the total tile count fn tile_count(&self) -> usize { self.original.len() / self.cpp / (self.tile_height * self.tile_width) } } /// We know the exact amount of tiles that can be /// produced, so we mark the iterator as ExactSizeIterator impl<'a, T> ExactSizeIterator for IntoTilesIter<'a, T> where T: Send {} // unsafe impl<'a, T> TrustedLen for IntoTilesIter<'a, T> where T: Send {} /// A iterator that gives owned Tiles impl<'a, T> Iterator for IntoTilesIter<'a, T> { type Item = Tile<'a, T>; fn next(&mut self) -> Option { let tile_cols = self.width / self.tile_width; let _tile_rows = self.original.len() / self.cpp / (self.tile_height * self.width); let tile_x = self.count % tile_cols; let tile_y = self.count / tile_cols; assert!(self.count <= self.tile_count()); let start_index = tile_x * (self.tile_width * self.cpp) + tile_y * (self.width * self.cpp) * self.tile_height; self.count += 1; if start_index >= self.original.len() { return None; } else { // The next tile line has always a distance equal to full image width. let next_line_distance = self.width * self.cpp; let first_line_begin = &mut self.original[start_index..]; if first_line_begin.len() < self.tile_height * next_line_distance - (tile_x * self.tile_width * self.cpp) { // The tile input buffer is too small. Maybe an issue with component-per-pixels? panic!("Tile buffer too small.") } let first_line = &mut first_line_begin[..self.tile_width * self.cpp]; Some(Tile { first_line, tile_height: self.tile_height, width: self.width, cpp: self.cpp, _phantom: std::marker::PhantomData, }) } } fn size_hint(&self) -> (usize, Option) { (self.tile_count() - self.count, Some(self.tile_count() - self.count)) } } /// Represents a rectangular tile within an image buffer. /// /// # Type Parameters /// - `'a`: Lifetime of the data the tile references. /// - `T`: Pixel type contained in the tile. /// /// # Fields /// - `first_line`: Pointer to the first line (row) of the tile's pixel data. /// - `tile_height`: Number of rows in the tile. /// - `width`: Width of the entire pixel buffer (not just the tile). /// - `_phantom`: Marker to associate the lifetime `'a` and type `[T]` with the struct. pub struct Tile<'a, T> { // contains tile_width as well first_line: *mut [T], tile_height: usize, width: usize, // of the pixbuf cpp: usize, _phantom: std::marker::PhantomData<&'a [T]>, } impl<'a, T> Tile<'a, T> { pub fn into_iter_mut(self) -> TileIterMut<'a, T> { TileIterMut { tile: self, current_line: 0 } } } // TODO: Add safety note unsafe impl Send for Tile<'_, T> {} /// An iterator that allows mutable access to the lines of a `Tile`. /// /// # Type Parameters /// * `T` - The type of the elements contained in the tile. /// /// # Fields /// * `tile` - The tile being iterated over. /// * `current_line` - The index of the current line in the tile. pub struct TileIterMut<'a, T> { tile: Tile<'a, T>, current_line: usize, } impl<'a, T> Iterator for TileIterMut<'a, T> where T: SubPixel + 'a, { type Item = LineMut<'a, T>; fn next(&mut self) -> Option { if self.current_line >= self.tile.tile_height { return None; } // Calculating the next line offset is easy - each tile has same width/height, // so the distance is simply the full width of the image. let next_line_distance = self.tile.width * self.tile.cpp; let line_ptr = unsafe { (self.tile.first_line as *mut T).offset((self.current_line * next_line_distance) as isize) }; self.current_line += 1; // This is safe because we check in the constructor if the line_ptr // can be advanced until tile end line. Some(unsafe { std::slice::from_raw_parts_mut(line_ptr, self.tile.first_line.len()) }) } fn size_hint(&self) -> (usize, Option) { (self.tile.tile_height - self.current_line, Some(self.tile.tile_height - self.current_line)) } } impl<'a, T> ExactSizeIterator for TileIterMut<'a, T> where T: SubPixel + 'a {} #[cfg(test)] mod tests { use super::*; use rayon::prelude::*; #[test] fn tile_1x1() -> std::result::Result<(), Box> { crate::init_test_logger(); let w = 1; let h = 1; let c = 3; let buf = vec![0_u16; w * h * c]; let tiles: Vec> = ImageTiler::new(&buf, w, h, c, 20, 20).collect(); assert_eq!(tiles.len(), 1); assert_eq!(tiles[0].len(), c * 20 * 20); Ok(()) } #[test] fn test_par_bridge() { #[rustfmt::skip] let mut vec = vec![ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, ]; let cpp = 1; let tiles = vec.into_tiles_iter_mut(6, cpp, 2, 2); assert!(tiles.is_ok()); let tiles = tiles.expect("Tiling failed"); tiles.par_bridge().for_each(|tile| { tile.into_iter_mut().for_each(|line| { for p in line { *p *= 2; } }); }); } #[test] fn test_par_bridge_without_collect() { #[rustfmt::skip] let mut vec = vec![ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, ]; let expected_vec: Vec = vec.iter().map(|p| p * 2).collect(); let cpp = 1; let tiles = vec.into_tiles_iter_mut(6, cpp, 2, 2); assert!(tiles.is_ok()); let tiles = tiles.expect("Tiling failed"); tiles.par_bridge().for_each(|tile| { tile.into_iter_mut().for_each(|line| { for p in line { *p *= 2; } }); }); assert_eq!(vec, expected_vec); } #[test] fn test_tiles_mut() { #[rustfmt::skip] let mut vec = vec![ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, ]; let cpp = 1; let tiles = vec.into_tiles_iter_mut(6, cpp, 2, 2); assert!(tiles.is_ok()); let tiles = tiles.expect("Tiling failed"); let tiles: Vec> = tiles.collect(); assert_eq!(tiles.len(), 6); } } rawler-0.7.1/tests/cameras/mod.rs000064400000000000000000007224641046102023000150460ustar 00000000000000use crate::common::camera_file_check; mod camera_quicktake_100_raw_modes { super::camera_file_check!("Apple", "QuickTake 100", cam_apple_quicktake_100_320x240_qtk, "raw_modes/Apple_QuickTake_100_320x240.qtk"); super::camera_file_check!("Apple", "QuickTake 100", cam_apple_quicktake_100_480x640_qtk, "raw_modes/Apple_QuickTake_100_480x640.qtk"); } mod camera_quicktake_150_raw_modes { super::camera_file_check!("Apple", "QuickTake 150", cam_apple_quicktake_150_480x640_qtk, "raw_modes/Apple_QuickTake_150_480x640.qtk"); } mod camera_eos_1000d_raw_modes { super::camera_file_check!("Canon", "EOS 1000D", cam_canon_eos_1000d_iso_200_raw_cr2, "raw_modes/Canon EOS 1000D_ISO_200_RAW.CR2"); } mod camera_eos_100d_raw_modes { super::camera_file_check!("Canon", "EOS 100D", cam_canon_eos_100d_iso_100_raw_cr2, "raw_modes/Canon EOS 100D_ISO_100_RAW.CR2"); } mod camera_eos_10d_raw_modes { super::camera_file_check!("Canon", "EOS 10D", cam_canon_eos_10d_iso_100_decodertablenum2_crw, "raw_modes/Canon EOS 10D_ISO_100_DecoderTableNum2.CRW"); super::camera_file_check!("Canon", "EOS 10D", cam_canon_eos_10d_iso_200_decodertablenum2_crw, "raw_modes/Canon EOS 10D_ISO_200_DecoderTableNum2.CRW"); super::camera_file_check!("Canon", "EOS 10D", cam_eos_10d_crw, "raw_modes/EOS 10D.CRW"); } mod camera_eos_1100d_raw_modes { super::camera_file_check!("Canon", "EOS 1100D", cam_canon_eos_1100d_iso_160_raw_cr2, "raw_modes/Canon EOS 1100D_ISO_160_RAW.CR2"); } mod camera_eos_1200d_raw_modes { super::camera_file_check!("Canon", "EOS 1200D", cam_canon_eos_1200d_iso_100_raw_cr2, "raw_modes/Canon EOS 1200D_ISO_100_RAW.CR2"); } mod camera_eos_1300d_raw_modes { super::camera_file_check!("Canon", "EOS 1300D", cam_canon_eos_1300d_iso_100_raw_cr2, "raw_modes/Canon EOS 1300D_ISO_100_RAW.CR2"); } mod camera_eos_1d_mark_iii_raw_modes { super::camera_file_check!("Canon", "EOS-1D Mark III", cam_canon_eos_1d_mark_iii_iso_1000_raw_cr2, "raw_modes/Canon EOS-1D Mark III_ISO_1000_RAW.CR2"); } mod camera_eos_1d_mark_ii_n_raw_modes { super::camera_file_check!("Canon", "EOS-1D Mark II N", cam_canon_eos_1d_mark_ii_n_iso_100_cr2, "raw_modes/Canon EOS-1D Mark II N_ISO_100.CR2"); } mod camera_eos_1d_mark_ii_raw_modes { super::camera_file_check!("Canon", "EOS-1D Mark II", cam_canon_eos_1d_mark_ii_iso_100_cr2, "raw_modes/Canon EOS-1D Mark II_ISO_100.CR2"); } mod camera_eos_1d_mark_iv_raw_modes { super::camera_file_check!("Canon", "EOS-1D Mark IV", cam_canon_eos_1d_mark_iv_iso_400_raw_cr2, "raw_modes/Canon EOS-1D Mark IV_ISO_400_RAW.CR2"); super::camera_file_check!("Canon", "EOS-1D Mark IV", cam_canon_eos_1d_mark_iv_iso_400_mraw_cr2, "raw_modes/Canon EOS-1D Mark IV_ISO_400_mRAW.CR2"); super::camera_file_check!("Canon", "EOS-1D Mark IV", cam_canon_eos_1d_mark_iv_iso_400_sraw_cr2, "raw_modes/Canon EOS-1D Mark IV_ISO_400_sRAW.CR2"); } mod camera_eos_1d_raw_modes { super::camera_file_check!("Canon", "EOS-1D", cam_canon_eos_1d_iso_200_tif, "raw_modes/Canon EOS-1D_ISO_200.TIF"); } mod camera_eos_1ds_mark_iii_raw_modes { super::camera_file_check!("Canon", "EOS-1Ds Mark III", cam_canon_eos_1ds_mark_iii_iso_100_raw_cr2, "raw_modes/Canon EOS-1Ds Mark III_ISO_100_RAW.CR2"); } mod camera_eos_1ds_mark_ii_raw_modes { super::camera_file_check!("Canon", "EOS-1Ds Mark II", cam_canon_eos_1ds_mark_ii_iso_640_cr2, "raw_modes/Canon EOS-1Ds Mark II_ISO_640.CR2"); } mod camera_eos_1ds_raw_modes { super::camera_file_check!("Canon", "EOS-1Ds", cam_canon_eos_1ds_iso_100_tif, "raw_modes/Canon EOS-1DS_ISO_100.TIF"); } mod camera_eos_1d_x_mark_iii_raw_modes { super::camera_file_check!("Canon", "EOS-1D X Mark III", cam_canon_eos_1d_x_mark_iii_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS-1D X Mark III_RAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS-1D X Mark III", cam_canon_eos_1d_x_mark_iii_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS-1D X Mark III_CRAW_ISO_100_nocrop_nodual.CR3"); } mod camera_eos_1d_x_mark_iii_crm { super::camera_file_check!("Canon", "EOS-1D X Mark III", cam_canon_1dx_mk3_crm_iso_800_raw_crm, "crm/Canon_1DX_MK3_CRM_ISO_800_RAW.CRM"); super::camera_file_check!("Canon", "EOS-1D X Mark III", cam_canon_1dx_mk3_crm_iso_800_lite_raw_crm, "crm/Canon_1DX_MK3_CRM_ISO_800_LITE_RAW.CRM"); super::camera_file_check!("Canon", "EOS-1D X Mark III", cam_canon_1dx_mk3_crm_iso_100_lite_raw_crm, "crm/Canon_1DX_MK3_CRM_ISO_100_LITE_RAW.CRM"); super::camera_file_check!("Canon", "EOS-1D X Mark III", cam_canon_1dx_mk3_crm_iso_max_lite_raw_crm, "crm/Canon_1DX_MK3_CRM_ISO_MAX_LITE_RAW.CRM"); } mod camera_eos_1d_x_mark_ii_raw_modes { super::camera_file_check!("Canon", "EOS-1D X Mark II", cam_canon_eos_1d_x_mark_ii_iso_500_mraw_cr2, "raw_modes/Canon EOS-1D X Mark II_ISO_500_mRAW.CR2"); super::camera_file_check!("Canon", "EOS-1D X Mark II", cam_canon_eos_1d_x_mark_ii_iso_500_sraw_cr2, "raw_modes/Canon EOS-1D X Mark II_ISO_500_sRAW.CR2"); super::camera_file_check!("Canon", "EOS-1D X Mark II", cam_canon_eos_1d_x_mark_ii_iso_500_raw_cr2, "raw_modes/Canon EOS-1D X Mark II_ISO_500_RAW.CR2"); } mod camera_eos_1d_x_raw_modes { super::camera_file_check!("Canon", "EOS-1D X", cam_canon_eos_1d_x_iso_1600_raw_cr2, "raw_modes/Canon EOS-1D X_ISO_1600_RAW.CR2"); } mod camera_eos_2000d_raw_modes { super::camera_file_check!("Canon", "EOS 2000D", cam_canon_eos_2000d_iso_400_raw_cr2, "raw_modes/Canon EOS 2000D_ISO_400_RAW.CR2"); } mod camera_eos_200d_raw_modes { super::camera_file_check!("Canon", "EOS 200D", cam_canon_eos_200d_iso_100_raw_cr2, "raw_modes/Canon EOS 200D_ISO_100_RAW.CR2"); } mod camera_eos_20d_raw_modes { super::camera_file_check!("Canon", "EOS 20D", cam_canon_eos_20d_iso_800_cr2, "raw_modes/Canon EOS 20D_ISO_800.CR2"); } mod camera_eos_250d_raw_modes { super::camera_file_check!("Canon", "EOS 250D", cam_canon_eos_250d_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS 250D_CRAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS 250D", cam_canon_eos_250d_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS 250D_RAW_ISO_100_nocrop_nodual.CR3"); } mod camera_eos_300d_raw_modes { super::camera_file_check!("Canon", "EOS 300D", cam_canon_eos_300d_digital_iso_100_crw, "raw_modes/Canon EOS 300D DIGITAL_ISO_100.CRW"); super::camera_file_check!("Canon", "EOS 300D", cam_eos_300d_crw, "raw_modes/EOS 300D.CRW"); } mod camera_eos_30d_raw_modes { super::camera_file_check!("Canon", "EOS 30D", cam_canon_eos_30d_iso_100_cr2, "raw_modes/Canon EOS 30D_ISO_100.CR2"); } mod camera_eos_350d_raw_modes { super::camera_file_check!("Canon", "EOS 350D", cam_canon_eos_350d_digital_iso_100_cr2, "raw_modes/Canon EOS 350D DIGITAL_ISO_100.CR2"); } mod camera_eos_4000d_raw_modes { super::camera_file_check!("Canon", "EOS 4000D", cam_canon_eos_4000d_iso_100_raw_cr2, "raw_modes/Canon EOS 4000D_ISO_100_RAW.CR2"); } mod camera_eos_400d_raw_modes { super::camera_file_check!("Canon", "EOS 400D", cam_canon_eos_400d_digital_iso_100_cr2, "raw_modes/Canon EOS 400D DIGITAL_ISO_100.CR2"); } mod camera_eos_40d_raw_modes { super::camera_file_check!("Canon", "EOS 40D", cam_canon_eos_40d_iso_100_raw_cr2, "raw_modes/Canon EOS 40D_ISO_100_RAW.CR2"); super::camera_file_check!("Canon", "EOS 40D", cam_canon_eos_40d_iso_100_sraw_cr2, "raw_modes/Canon EOS 40D_ISO_100_sRAW.CR2"); } mod camera_eos_450d_raw_modes { super::camera_file_check!("Canon", "EOS 450D", cam_canon_eos_450d_iso_400_raw_cr2, "raw_modes/Canon EOS 450D_ISO_400_RAW.CR2"); } mod camera_eos_500d_raw_modes { super::camera_file_check!("Canon", "EOS 500D", cam_canon_eos_500d_iso_200_raw_cr2, "raw_modes/Canon EOS 500D_ISO_200_RAW.CR2"); } mod camera_eos_50d_raw_modes { super::camera_file_check!("Canon", "EOS 50D", cam_canon_eos_50d_iso_100_raw_cr2, "raw_modes/Canon EOS 50D_ISO_100_RAW.CR2"); super::camera_file_check!("Canon", "EOS 50D", cam_canon_eos_50d_iso_100_sraw_cr2, "raw_modes/Canon EOS 50D_ISO_100_sRAW.CR2"); super::camera_file_check!("Canon", "EOS 50D", cam_canon_eos_50d_iso_100_mraw_cr2, "raw_modes/Canon EOS 50D_ISO_100_mRAW.CR2"); } mod camera_eos_550d_raw_modes { super::camera_file_check!("Canon", "EOS 550D", cam_canon_eos_550d_iso_100_raw_cr2, "raw_modes/Canon EOS 550D_ISO_100_RAW.CR2"); } mod camera_eos_5d_mark_iii_raw_modes { super::camera_file_check!("Canon", "EOS 5D Mark III", cam_canon_eos_5d_mark_iii_sraw1_iso_200_cr2, "raw_modes/Canon EOS 5D Mark III_sRAW1_ISO_200.CR2"); super::camera_file_check!("Canon", "EOS 5D Mark III", cam_canon_eos_5d_mark_iii_sraw2_iso_200_cr2, "raw_modes/Canon EOS 5D Mark III_sRAW2_ISO_200.CR2"); super::camera_file_check!("Canon", "EOS 5D Mark III", cam_canon_eos_5d_mark_iii_raw_iso_200_cr2, "raw_modes/Canon EOS 5D Mark III_RAW_ISO_200.CR2"); } mod camera_eos_5d_mark_ii_raw_modes { super::camera_file_check!("Canon", "EOS 5D Mark II", cam_canon_eos_5d_mark_ii_iso_800_mraw_cr2, "raw_modes/Canon EOS 5D Mark II_ISO_800_mRAW.CR2"); super::camera_file_check!("Canon", "EOS 5D Mark II", cam_canon_eos_5d_mark_ii_iso_100_raw_cr2, "raw_modes/Canon EOS 5D Mark II_ISO_100_RAW.CR2"); super::camera_file_check!("Canon", "EOS 5D Mark II", cam_canon_eos_5d_mark_ii_iso_800_raw_cr2, "raw_modes/Canon EOS 5D Mark II_ISO_800_RAW.CR2"); super::camera_file_check!("Canon", "EOS 5D Mark II", cam_canon_eos_5d_mark_ii_iso_800_sraw_cr2, "raw_modes/Canon EOS 5D Mark II_ISO_800_sRAW.CR2"); } mod camera_eos_5d_mark_iv_raw_modes { super::camera_file_check!("Canon", "EOS 5D Mark IV", cam_canon_eos_5d_mark_iv_iso_100_sraw_cr2, "raw_modes/Canon EOS 5D Mark IV_ISO_100_sRAW.CR2"); super::camera_file_check!("Canon", "EOS 5D Mark IV", cam_canon_eos_5d_mark_iv_iso_100_mraw_cr2, "raw_modes/Canon EOS 5D Mark IV_ISO_100_mRAW.CR2"); super::camera_file_check!("Canon", "EOS 5D Mark IV", cam_canon_eos_5d_mark_iv_iso_100_raw_cr2, "raw_modes/Canon EOS 5D Mark IV_ISO_100_RAW.CR2"); } mod camera_eos_5d_raw_modes { super::camera_file_check!("Canon", "EOS 5D", cam_canon_eos_5d_iso_400_cr2, "raw_modes/Canon EOS 5D_ISO_400.CR2"); } mod camera_eos_5ds_raw_modes { super::camera_file_check!("Canon", "EOS 5DS", cam_canon_eos_5ds_iso_1000_mraw_cr2, "raw_modes/Canon EOS 5DS_ISO_1000_mRAW.CR2"); super::camera_file_check!("Canon", "EOS 5DS", cam_canon_eos_5ds_iso_1000_sraw_cr2, "raw_modes/Canon EOS 5DS_ISO_1000_sRAW.CR2"); super::camera_file_check!("Canon", "EOS 5DS", cam_canon_eos_5ds_iso_1000_raw_cr2, "raw_modes/Canon EOS 5DS_ISO_1000_RAW.CR2"); } mod camera_eos_5ds_r_raw_modes { super::camera_file_check!("Canon", "EOS 5DS R", cam_canon_eos_5ds_r_iso_100_mraw_cr2, "raw_modes/Canon EOS 5DS R_ISO_100_mRAW.CR2"); super::camera_file_check!("Canon", "EOS 5DS R", cam_canon_eos_5ds_r_iso_100_sraw_cr2, "raw_modes/Canon EOS 5DS R_ISO_100_sRAW.CR2"); super::camera_file_check!("Canon", "EOS 5DS R", cam_canon_eos_5ds_r_iso_100_raw_cr2, "raw_modes/Canon EOS 5DS R_ISO_100_RAW.CR2"); } mod camera_eos_600d_raw_modes { super::camera_file_check!("Canon", "EOS 600D", cam_canon_eos_600d_iso_200_raw_cr2, "raw_modes/Canon EOS 600D_ISO_200_RAW.CR2"); } mod camera_eos_60d_raw_modes { super::camera_file_check!("Canon", "EOS 60D", cam_canon_eos_60d_iso_100_mraw_cr2, "raw_modes/Canon EOS 60D_ISO_100_mRAW.CR2"); super::camera_file_check!("Canon", "EOS 60D", cam_canon_eos_60d_iso_100_sraw_cr2, "raw_modes/Canon EOS 60D_ISO_100_sRAW.CR2"); super::camera_file_check!("Canon", "EOS 60D", cam_canon_eos_60d_iso_100_raw_cr2, "raw_modes/Canon EOS 60D_ISO_100_RAW.CR2"); } mod camera_eos_650d_raw_modes { super::camera_file_check!("Canon", "EOS 650D", cam_canon_eos_650d_iso_100_raw_cr2, "raw_modes/Canon EOS 650D_ISO_100_RAW.CR2"); } mod camera_eos_6d_mark_ii_raw_modes { super::camera_file_check!("Canon", "EOS 6D Mark II", cam_canon_eos_6d_mark_ii_iso_100_raw_cr2, "raw_modes/Canon EOS 6D Mark II_ISO_100_RAW.CR2"); super::camera_file_check!("Canon", "EOS 6D Mark II", cam_canon_eos_6d_mark_ii_iso_100_sraw_cr2, "raw_modes/Canon EOS 6D Mark II_ISO_100_sRAW.CR2"); super::camera_file_check!("Canon", "EOS 6D Mark II", cam_canon_eos_6d_mark_ii_iso_100_mraw_cr2, "raw_modes/Canon EOS 6D Mark II_ISO_100_mRAW.CR2"); } mod camera_eos_6d_raw_modes { super::camera_file_check!("Canon", "EOS 6D", cam_canon_eos_6d_iso_100_raw_cr2, "raw_modes/Canon EOS 6D_ISO_100_RAW.CR2"); super::camera_file_check!("Canon", "EOS 6D", cam_canon_eos_6d_iso_400_raw_cr2, "raw_modes/Canon EOS 6D_ISO_400_RAW.CR2"); super::camera_file_check!("Canon", "EOS 6D", cam_canon_eos_6d_iso_100_sraw_cr2, "raw_modes/Canon EOS 6D_ISO_100_sRAW.CR2"); super::camera_file_check!("Canon", "EOS 6D", cam_canon_eos_6d_iso_100_mraw_cr2, "raw_modes/Canon EOS 6D_ISO_100_mRAW.CR2"); } mod camera_eos_700d_raw_modes { super::camera_file_check!("Canon", "EOS 700D", cam_canon_eos_700d_iso_200_raw_cr2, "raw_modes/Canon EOS 700D_ISO_200_RAW.CR2"); } mod camera_eos_70d_raw_modes { super::camera_file_check!("Canon", "EOS 70D", cam_canon_eos_70d_iso_100_mraw_cr2, "raw_modes/Canon EOS 70D_ISO_100_mRAW.CR2"); super::camera_file_check!("Canon", "EOS 70D", cam_canon_eos_70d_iso_100_sraw_cr2, "raw_modes/Canon EOS 70D_ISO_100_sRAW.CR2"); super::camera_file_check!("Canon", "EOS 70D", cam_canon_eos_70d_iso_100_raw_cr2, "raw_modes/Canon EOS 70D_ISO_100_RAW.CR2"); } mod camera_eos_750d_raw_modes { super::camera_file_check!("Canon", "EOS 750D", cam_canon_eos_750d_iso_100_raw_cr2, "raw_modes/Canon EOS 750D_ISO_100_RAW.CR2"); } mod camera_eos_760d_raw_modes { super::camera_file_check!("Canon", "EOS 760D", cam_canon_eos_760d_iso_200_raw_cr2, "raw_modes/Canon EOS 760D_ISO_200_RAW.CR2"); } mod camera_eos_77d_raw_modes { super::camera_file_check!("Canon", "EOS 77D", cam_canon_eos_77d_iso_3200_raw_cr2, "raw_modes/Canon EOS 77D_ISO_3200_RAW.CR2"); } mod camera_eos_7d_mark_ii_raw_modes { super::camera_file_check!("Canon", "EOS 7D Mark II", cam_canon_eos_7d_mark_ii_iso_100_sraw_cr2, "raw_modes/Canon EOS 7D Mark II_ISO_100_sRAW.CR2"); super::camera_file_check!("Canon", "EOS 7D Mark II", cam_canon_eos_7d_mark_ii_iso_100_mraw_cr2, "raw_modes/Canon EOS 7D Mark II_ISO_100_mRAW.CR2"); super::camera_file_check!("Canon", "EOS 7D Mark II", cam_canon_eos_7d_mark_ii_iso_100_raw_cr2, "raw_modes/Canon EOS 7D Mark II_ISO_100_RAW.CR2"); } mod camera_eos_7d_raw_modes { super::camera_file_check!("Canon", "EOS 7D", cam_canon_eos_7d_iso_1250_sraw_cr2, "raw_modes/Canon EOS 7D_ISO_1250_sRAW.CR2"); super::camera_file_check!("Canon", "EOS 7D", cam_canon_eos_7d_iso_1250_mraw_cr2, "raw_modes/Canon EOS 7D_ISO_1250_mRAW.CR2"); super::camera_file_check!("Canon", "EOS 7D", cam_canon_eos_7d_iso_1250_raw_cr2, "raw_modes/Canon EOS 7D_ISO_1250_RAW.CR2"); super::camera_file_check!("Canon", "EOS 7D", cam_canon_eos_7d_iso_100_raw_cr2, "raw_modes/Canon EOS 7D_ISO_100_RAW.CR2"); } mod camera_eos_800d_raw_modes { super::camera_file_check!("Canon", "EOS 800D", cam_canon_eos_800d_iso_100_raw_cr2, "raw_modes/Canon EOS 800D_ISO_100_RAW.CR2"); } mod camera_eos_80d_raw_modes { super::camera_file_check!("Canon", "EOS 80D", cam_canon_eos_80d_iso_100_sraw_cr2, "raw_modes/Canon EOS 80D_ISO_100_sRAW.CR2"); super::camera_file_check!("Canon", "EOS 80D", cam_canon_eos_80d_iso_100_raw_cr2, "raw_modes/Canon EOS 80D_ISO_100_RAW.CR2"); super::camera_file_check!("Canon", "EOS 80D", cam_canon_eos_80d_iso_100_mraw_cr2, "raw_modes/Canon EOS 80D_ISO_100_mRAW.CR2"); } mod camera_eos_850d_raw_modes { super::camera_file_check!("Canon", "EOS 850D", cam_canon_eos_850d_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS 850D_CRAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS 850D", cam_canon_eos_850d_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS 850D_RAW_ISO_100_nocrop_nodual.CR3"); } mod camera_eos_90d_raw_modes { super::camera_file_check!("Canon", "EOS 90D", cam_canon_eos_90d_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS 90D_RAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS 90D", cam_canon_eos_90d_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS 90D_CRAW_ISO_100_nocrop_nodual.CR3"); } mod camera_eos_d2000c_raw_modes { super::camera_file_check!("Canon", "EOS D2000C", cam_canon_d2000c_raw_iso_200_tif, "raw_modes/Canon D2000C_RAW_ISO_200.TIF"); } mod camera_eos_d30_raw_modes { super::camera_file_check!("Canon", "EOS D30", cam_canon_eos_d30_iso_1600_crw, "raw_modes/Canon EOS D30_ISO_1600.CRW"); } mod camera_eos_d60_raw_modes { super::camera_file_check!("Canon", "EOS D60", cam_canon_eos_d60_iso_100_crw, "raw_modes/Canon EOS D60_ISO_100.CRW"); } mod camera_eos_digital_rebel_raw_modes { super::camera_file_check!("Canon", "EOS Digital Rebel", cam_canon_eos_digital_rebel_iso_1600_crw, "raw_modes/Canon EOS DIGITAL REBEL_ISO_1600.CRW"); } mod camera_eos_digital_rebel_xsi_raw_modes { super::camera_file_check!("Canon", "EOS Digital Rebel XSi", cam_canon_eos_digital_rebel_xsi_iso_400_raw_cr2, "raw_modes/Canon EOS DIGITAL REBEL XSi_ISO_400_RAW.CR2"); } mod camera_eos_digital_rebel_xs_raw_modes { super::camera_file_check!("Canon", "EOS Digital Rebel XS", cam_canon_eos_digital_rebel_xs_iso_100_raw_cr2, "raw_modes/Canon EOS DIGITAL REBEL XS_ISO_100_RAW.CR2"); } mod camera_eos_digital_rebel_xti_raw_modes { super::camera_file_check!("Canon", "EOS Digital Rebel XTi", cam_canon_eos_digital_rebel_xti_iso_400_cr2, "raw_modes/Canon EOS DIGITAL REBEL XTi_ISO_400.CR2"); } mod camera_eos_digital_rebel_xt_raw_modes { super::camera_file_check!("Canon", "EOS Digital Rebel XT", cam_canon_eos_digital_rebel_xt_iso_100_cr2, "raw_modes/Canon EOS DIGITAL REBEL XT_ISO_100.CR2"); } mod camera_eos_kiss_digital_n_raw_modes { super::camera_file_check!("Canon", "EOS Kiss Digital N", cam_canon_eos_kiss_digital_n_iso_100_cr2, "raw_modes/Canon EOS Kiss Digital N_ISO_100.CR2"); } mod camera_eos_kiss_x3_raw_modes { super::camera_file_check!("Canon", "EOS Kiss X3", cam_canon_eos_kiss_x3_iso_400_raw_cr2, "raw_modes/Canon EOS Kiss X3_ISO_400_RAW.CR2"); } mod camera_eos_kiss_x4_raw_modes { super::camera_file_check!("Canon", "EOS Kiss X4", cam_canon_eos_kiss_x4_iso_100_raw_cr2, "raw_modes/Canon EOS Kiss X4_ISO_100_RAW.CR2"); } mod camera_eos_kiss_x80_raw_modes { super::camera_file_check!("Canon", "EOS Kiss X80", cam_canon_eos_kiss_x80_iso_100_raw_cr2, "raw_modes/Canon EOS Kiss X80_ISO_100_RAW.CR2"); } mod camera_eos_kiss_x9_raw_modes { super::camera_file_check!("Canon", "EOS Kiss X9", cam_canon_eos_kiss_x9_iso_6400_raw_cr2, "raw_modes/Canon EOS Kiss X9_ISO_6400_RAW.CR2"); } mod camera_eos_m100_raw_modes { super::camera_file_check!("Canon", "EOS M100", cam_canon_eos_m100_iso_640_raw_cr2, "raw_modes/Canon EOS M100_ISO_640_RAW.CR2"); } mod camera_eos_m10_raw_modes { super::camera_file_check!("Canon", "EOS M10", cam_canon_eos_m10_iso_200_raw_cr2, "raw_modes/Canon EOS M10_ISO_200_RAW.CR2"); } mod camera_eos_m200_raw_modes { super::camera_file_check!("Canon", "EOS M200", cam_canon_eos_m200_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS M200_CRAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS M200", cam_canon_eos_m200_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS M200_RAW_ISO_100_nocrop_nodual.CR3"); } mod camera_eos_m2_raw_modes { super::camera_file_check!("Canon", "EOS M2", cam_canon_eos_m2_iso_500_raw_cr2, "raw_modes/Canon EOS M2_ISO_500_RAW.CR2"); } mod camera_eos_m3_raw_modes { super::camera_file_check!("Canon", "EOS M3", cam_canon_eos_m3_iso_5000_raw_cr2, "raw_modes/Canon EOS M3_ISO_5000_RAW.CR2"); } mod camera_eos_m50m2_raw_modes { super::camera_file_check!("Canon", "EOS M50m2", cam_canon_eos_m50m2_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS M50m2_RAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS M50m2", cam_canon_eos_m50m2_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS M50m2_CRAW_ISO_100_nocrop_nodual.CR3"); } mod camera_eos_m50_raw_modes { super::camera_file_check!("Canon", "EOS M50", cam_canon_eos_m50_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS M50_RAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS M50", cam_canon_eos_m50_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS M50_CRAW_ISO_100_nocrop_nodual.CR3"); } mod camera_eos_m5_raw_modes { super::camera_file_check!("Canon", "EOS M5", cam_canon_eos_m5_iso_100_raw_cr2, "raw_modes/Canon EOS M5_ISO_100_RAW.CR2"); } mod camera_eos_m6_mark_ii_raw_modes { super::camera_file_check!("Canon", "EOS M6 Mark II", cam_canon_eos_m6_mark_ii_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS M6 Mark II_RAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS M6 Mark II", cam_canon_eos_m6_mark_ii_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS M6 Mark II_CRAW_ISO_100_nocrop_nodual.CR3"); } mod camera_eos_m6_raw_modes { super::camera_file_check!("Canon", "EOS M6", cam_canon_eos_m6_iso_100_raw_cr2, "raw_modes/Canon EOS M6_ISO_100_RAW.CR2"); } mod camera_eos_m_raw_modes { super::camera_file_check!("Canon", "EOS M", cam_canon_eos_m_iso_1600_raw_cr2, "raw_modes/Canon EOS M_ISO_1600_RAW.CR2"); } mod camera_eos_r5_raw_modes { super::camera_file_check!("Canon", "EOS R5", cam_canon_eos_r5_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS R5_CRAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS R5", cam_canon_eos_r5_raw_iso_100_crop_dual_cr3, "raw_modes/Canon EOS R5_RAW_ISO_100_crop_dual.CR3"); super::camera_file_check!("Canon", "EOS R5", cam_canon_eos_r5_raw_iso_100_nocrop_dual_cr3, "raw_modes/Canon EOS R5_RAW_ISO_100_nocrop_dual.CR3"); super::camera_file_check!("Canon", "EOS R5", cam_canon_eos_r5_craw_iso_100_nocrop_dual_cr3, "raw_modes/Canon EOS R5_CRAW_ISO_100_nocrop_dual.CR3"); super::camera_file_check!("Canon", "EOS R5", cam_canon_eos_r5_craw_iso_100_crop_dual_cr3, "raw_modes/Canon EOS R5_CRAW_ISO_100_crop_dual.CR3"); super::camera_file_check!("Canon", "EOS R5", cam_canon_eos_r5_craw_iso_100_crop_nodual_cr3, "raw_modes/Canon EOS R5_CRAW_ISO_100_crop_nodual.CR3"); super::camera_file_check!("Canon", "EOS R5", cam_canon_eos_r5_raw_iso_100_crop_nodual_cr3, "raw_modes/Canon EOS R5_RAW_ISO_100_crop_nodual.CR3"); super::camera_file_check!("Canon", "EOS R5", cam_canon_eos_r5_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS R5_RAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS R5", cam_standardraw_iso400_tungsten_clog_neutral_bt2020_crm, "raw_modes/StandardRaw_ISO400_Tungsten_CLOG_Neutral_BT2020.CRM"); } mod camera_eos_r5_mark_ii_raw_modes { super::camera_file_check!("Canon", "EOS R5 Mark II", cam_canon_eos_r5m2_raw_iso_640_nocrop_cr3, "raw_modes/Canon EOS R5m2_RAW_ISO_640_nocrop.CR3"); super::camera_file_check!("Canon", "EOS R5 Mark II", cam_canon_eos_r5m2_raw_iso_65535_nocrop_es_cr3, "raw_modes/Canon EOS R5m2_RAW_ISO_65535_nocrop_ES.CR3"); super::camera_file_check!("Canon", "EOS R5 Mark II", cam_canon_eos_r5m2_raw_iso_125_nocrop_dustdata_cr3, "raw_modes/Canon EOS R5m2_RAW_ISO_125_nocrop_DUSTDATA.CR3"); super::camera_file_check!("Canon", "EOS R5 Mark II", cam_canon_eos_r5m2_raw_iso_125_crop_cr3, "raw_modes/Canon EOS R5m2_RAW_ISO_125_crop.CR3"); super::camera_file_check!("Canon", "EOS R5 Mark II", cam_canon_eos_r5m2_craw_iso_640_nocrop_cr3, "raw_modes/Canon EOS R5m2_CRAW_ISO_640_nocrop.CR3"); super::camera_file_check!("Canon", "EOS R5 Mark II", cam_canon_eos_r5m2_craw_iso_125_crop_cr3, "raw_modes/Canon EOS R5m2_CRAW_ISO_125_crop.CR3"); } mod camera_eos_r5_mark_ii_crm_movie_modes { super::camera_file_check!("Canon", "EOS R5 Mark II", cam_r5mk2_lightraw_crm, "crm_movie_modes/R5MK2_LightRaw.CRM"); super::camera_file_check!("Canon", "EOS R5 Mark II", cam_r5mk2_standardraw_crm, "crm_movie_modes/R5MK2_StandardRaw.CRM"); } mod camera_eos_r5_c_raw_modes { super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_craw_iso_65535_nocrop_nodual_ms_cr3, "raw_modes/Canon EOS R5 C_CRAW_ISO_65535_nocrop_nodual_MS.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_raw_iso_100_nocrop_nodual_ms_burst_cr3, "raw_modes/Canon EOS R5 C_RAW_ISO_100_nocrop_nodual_MS_BURST.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_craw_iso_800_nocrop_nodual_ms_cr3, "raw_modes/Canon EOS R5 C_CRAW_ISO_800_nocrop_nodual_MS.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_craw_iso_800_nocrop_nodual_es_cr3, "raw_modes/Canon EOS R5 C_CRAW_ISO_800_nocrop_nodual_ES.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_craw_iso_65535_nocrop_nodual_es_cr3, "raw_modes/Canon EOS R5 C_CRAW_ISO_65535_nocrop_nodual_ES.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_raw_iso_100_nocrop_dual_cr3, "raw_modes/Canon EOS R5 C_RAW_ISO_100_nocrop_dual.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_craw_iso_100_nocrop_nodual_es_cr3, "raw_modes/Canon EOS R5 C_CRAW_ISO_100_nocrop_nodual_ES.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_craw_iso_100_nocrop_nodual_ms_cr3, "raw_modes/Canon EOS R5 C_CRAW_ISO_100_nocrop_nodual_MS.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_craw_iso_100_nocrop_dual_cr3, "raw_modes/Canon EOS R5 C_CRAW_ISO_100_nocrop_dual.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_raw_iso_100_nocrop_nodual_es_cr3, "raw_modes/Canon EOS R5 C_RAW_ISO_100_nocrop_nodual_ES.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_raw_iso_100_nocrop_nodual_ms_cr3, "raw_modes/Canon EOS R5 C_RAW_ISO_100_nocrop_nodual_MS.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_raw_iso_100_nocrop_nodual_es_burst_cr3, "raw_modes/Canon EOS R5 C_RAW_ISO_100_nocrop_nodual_ES_BURST.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_raw_iso_800_nocrop_nodual_ms_cr3, "raw_modes/Canon EOS R5 C_RAW_ISO_800_nocrop_nodual_MS.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_raw_iso_65535_nocrop_nodual_es_cr3, "raw_modes/Canon EOS R5 C_RAW_ISO_65535_nocrop_nodual_ES.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_raw_iso_800_nocrop_nodual_es_cr3, "raw_modes/Canon EOS R5 C_RAW_ISO_800_nocrop_nodual_ES.CR3"); super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_raw_iso_65535_nocrop_nodual_ms_cr3, "raw_modes/Canon EOS R5 C_RAW_ISO_65535_nocrop_nodual_MS.CR3"); } mod camera_eos_r5_c_crm { super::camera_file_check!("Canon", "EOS R5 C", cam_canon_eos_r5_c_standard__raw__iso_100_crm, "crm/Canon EOS R5 C_Standard (RAW)_ISO_100.CRM"); } mod camera_eos_r6_raw_modes { super::camera_file_check!("Canon", "EOS R6", cam_canon_eos_r6_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS R6_RAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS R6", cam_canon_eos_r6_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS R6_CRAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS R6", cam_canon_eos_r6_raw_iso_100_crop_nodual_cr3, "raw_modes/Canon EOS R6_RAW_ISO_100_crop_nodual.CR3"); super::camera_file_check!("Canon", "EOS R6", cam_canon_eos_r6_craw_iso_100_crop_nodual_cr3, "raw_modes/Canon EOS R6_CRAW_ISO_100_crop_nodual.CR3"); } mod camera_eos_r6_mark_ii_raw_modes { super::camera_file_check!("Canon", "EOS R6 Mark II", cam_canon_eos_r6m2_raw_iso_100_dual_nocrop_cr3, "raw_modes/Canon EOS R6m2_RAW_ISO_100_dual_nocrop.CR3"); super::camera_file_check!("Canon", "EOS R6 Mark II", cam_canon_eos_r6m2_craw_iso_100_dual_crop_cr3, "raw_modes/Canon EOS R6m2_CRAW_ISO_100_dual_crop.CR3"); super::camera_file_check!("Canon", "EOS R6 Mark II", cam_canon_eos_r6m2_craw_iso_100_dual_nocrop_cr3, "raw_modes/Canon EOS R6m2_CRAW_ISO_100_dual_nocrop.CR3"); super::camera_file_check!("Canon", "EOS R6 Mark II", cam_canon_eos_r6m2_raw_iso_100_nodual_crop_cr3, "raw_modes/Canon EOS R6m2_RAW_ISO_100_nodual_crop.CR3"); super::camera_file_check!("Canon", "EOS R6 Mark II", cam_canon_eos_r6m2_craw_iso_100_nodual_crop_cr3, "raw_modes/Canon EOS R6m2_CRAW_ISO_100_nodual_crop.CR3"); super::camera_file_check!("Canon", "EOS R6 Mark II", cam_canon_eos_r6m2_raw_iso_100_nodual_nocrop_cr3, "raw_modes/Canon EOS R6m2_RAW_ISO_100_nodual_nocrop.CR3"); super::camera_file_check!("Canon", "EOS R6 Mark II", cam_canon_eos_r6m2_craw_iso_100_nodual_nocrop_cr3, "raw_modes/Canon EOS R6m2_CRAW_ISO_100_nodual_nocrop.CR3"); super::camera_file_check!("Canon", "EOS R6 Mark II", cam_canon_eos_r6m2_raw_iso_100_dual_crop_cr3, "raw_modes/Canon EOS R6m2_RAW_ISO_100_dual_crop.CR3"); } mod camera_eos_r7_raw_modes { super::camera_file_check!("Canon", "EOS R7", cam_canon_eos_r7_raw_iso_100_nodual_cr3, "raw_modes/Canon EOS R7_RAW_ISO_100_nodual.CR3"); super::camera_file_check!("Canon", "EOS R7", cam_canon_eos_r7_raw_iso_800_nodual_cr3, "raw_modes/Canon EOS R7_RAW_ISO_800_nodual.CR3"); super::camera_file_check!("Canon", "EOS R7", cam_canon_eos_r7_raw_iso_32000_nodual_cr3, "raw_modes/Canon EOS R7_RAW_ISO_32000_nodual.CR3"); super::camera_file_check!("Canon", "EOS R7", cam_canon_eos_r7_burst_iso_100_nodual_cr3, "raw_modes/Canon EOS R7_BURST_ISO_100_nodual.CR3"); super::camera_file_check!("Canon", "EOS R7", cam_canon_eos_r7_craw_iso_100_nodual_cr3, "raw_modes/Canon EOS R7_CRAW_ISO_100_nodual.CR3"); super::camera_file_check!("Canon", "EOS R7", cam_canon_eos_r7_raw_iso_800_dual_cr3, "raw_modes/Canon EOS R7_RAW_ISO_800_dual.CR3"); super::camera_file_check!("Canon", "EOS R7", cam_canon_eos_r7_craw_iso_32000_nodual_cr3, "raw_modes/Canon EOS R7_CRAW_ISO_32000_nodual.CR3"); super::camera_file_check!("Canon", "EOS R7", cam_canon_eos_r7_raw_iso_100_dual_cr3, "raw_modes/Canon EOS R7_RAW_ISO_100_dual.CR3"); super::camera_file_check!("Canon", "EOS R7", cam_canon_eos_r7_craw_iso_800_nodual_cr3, "raw_modes/Canon EOS R7_CRAW_ISO_800_nodual.CR3"); super::camera_file_check!("Canon", "EOS R7", cam_canon_eos_r7_raw_iso_32000_dual_cr3, "raw_modes/Canon EOS R7_RAW_ISO_32000_dual.CR3"); } mod camera_eos_r8_raw_modes { super::camera_file_check!("Canon", "EOS R8", cam_canon_eos_r8_craw_dual_cr3, "raw_modes/Canon_EOS_R8_CRAW_dual.CR3"); super::camera_file_check!("Canon", "EOS R8", cam_canon_eos_r8_burst_cr3, "raw_modes/Canon_EOS_R8_BURST.CR3"); super::camera_file_check!("Canon", "EOS R8", cam_canon_eos_r8_raw_dual_cr3, "raw_modes/Canon_EOS_R8_RAW_dual.CR3"); super::camera_file_check!("Canon", "EOS R8", cam_canon_eos_r8_craw_nodual_cr3, "raw_modes/Canon_EOS_R8_CRAW_nodual.CR3"); super::camera_file_check!("Canon", "EOS R8", cam_canon_eos_r8_raw_nodual_cr3, "raw_modes/Canon_EOS_R8_RAW_nodual.CR3"); } mod camera_eos_r10_raw_modes { super::camera_file_check!("Canon", "EOS R10", cam_canon_eos_r10_raw_iso_800_cr3, "raw_modes/Canon EOS R10_RAW_ISO_800.CR3"); super::camera_file_check!("Canon", "EOS R10", cam_canon_eos_r10_craw_iso_800_cr3, "raw_modes/Canon EOS R10_CRAW_ISO_800.CR3"); super::camera_file_check!("Canon", "EOS R10", cam_canon_eos_r10_craw_iso_32000_cr3, "raw_modes/Canon EOS R10_CRAW_ISO_32000.CR3"); super::camera_file_check!("Canon", "EOS R10", cam_canon_eos_r10_raw_iso_32000_cr3, "raw_modes/Canon EOS R10_RAW_ISO_32000.CR3"); super::camera_file_check!("Canon", "EOS R10", cam_canon_eos_r10_burst_iso_100_cr3, "raw_modes/Canon EOS R10_BURST_ISO_100.CR3"); super::camera_file_check!("Canon", "EOS R10", cam_canon_eos_r10_raw_iso_100_cr3, "raw_modes/Canon EOS R10_RAW_ISO_100.CR3"); super::camera_file_check!("Canon", "EOS R10", cam_canon_eos_r10_craw_iso_100_cr3, "raw_modes/Canon EOS R10_CRAW_ISO_100.CR3"); } mod camera_eos_r50_raw_modes { super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso800_craw_ms_cr3, "raw_modes/Canon_R50_ISO800_CRAW_ms.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso100_raw_ms_cr3, "raw_modes/Canon_R50_ISO100_RAW_ms.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso200_raw_ms_hdr_cr3, "raw_modes/Canon_R50_ISO200_RAW_ms_HDR.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso800_craw_es_cr3, "raw_modes/Canon_R50_ISO800_CRAW_es.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso100_raw_es_cr3, "raw_modes/Canon_R50_ISO100_RAW_es.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso800_raw_es_cr3, "raw_modes/Canon_R50_ISO800_RAW_es.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso200_craw_ms_hdr_cr3, "raw_modes/Canon_R50_ISO200_CRAW_ms_HDR.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso800_raw_ms_cr3, "raw_modes/Canon_R50_ISO800_RAW_ms.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso100_craw_es_cr3, "raw_modes/Canon_R50_ISO100_CRAW_es.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso32000_raw_es_cr3, "raw_modes/Canon_R50_ISO32000_RAW_es.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso100_craw_ms_cr3, "raw_modes/Canon_R50_ISO100_CRAW_ms.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso32000_raw_ms_cr3, "raw_modes/Canon_R50_ISO32000_RAW_ms.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso32000_craw_ms_cr3, "raw_modes/Canon_R50_ISO32000_CRAW_ms.CR3"); super::camera_file_check!("Canon", "EOS R50", cam_canon_r50_iso32000_craw_es_cr3, "raw_modes/Canon_R50_ISO32000_CRAW_es.CR3"); } mod camera_eos_r100_raw_modes { super::camera_file_check!("Canon", "EOS R100", cam_canon_eos_r100_craw_cr3, "raw_modes/Canon_EOS_R100_CRAW.CR3"); super::camera_file_check!("Canon", "EOS R100", cam_canon_eos_r100_raw_cr3, "raw_modes/Canon_EOS_R100_RAW.CR3"); } mod camera_eos_rebel_sl1_raw_modes { super::camera_file_check!("Canon", "EOS Rebel SL1", cam_canon_eos_rebel_sl1_iso_400_raw_cr2, "raw_modes/Canon EOS REBEL SL1_ISO_400_RAW.CR2"); } mod camera_eos_rebel_sl2_raw_modes { super::camera_file_check!("Canon", "EOS Rebel SL2", cam_canon_eos_rebel_sl2_iso_400_raw_cr2, "raw_modes/Canon EOS Rebel SL2_ISO_400_RAW.CR2"); } mod camera_eos_rebel_sl3_raw_modes { super::camera_file_check!("Canon", "EOS Rebel SL3", cam_eos_rebel_sl3_cr3, "raw_modes/EOS Rebel SL3.CR3"); } mod camera_eos_rebel_t100_raw_modes { super::camera_file_check!("Canon", "EOS Rebel T100", cam_canon_eos_rebel_t100_iso_100_raw_cr2, "raw_modes/Canon EOS Rebel T100_ISO_100_RAW.CR2"); } mod camera_eos_rebel_t1i_raw_modes { super::camera_file_check!("Canon", "EOS Rebel T1i", cam_canon_eos_rebel_t1i_iso_1600_raw_cr2, "raw_modes/Canon EOS REBEL T1i_ISO_1600_RAW.CR2"); } mod camera_eos_rebel_t2i_raw_modes { super::camera_file_check!("Canon", "EOS Rebel T2i", cam_canon_eos_rebel_t2i_iso_1600_raw_cr2, "raw_modes/Canon EOS REBEL T2i_ISO_1600_RAW.CR2"); } mod camera_eos_rebel_t3i_raw_modes { super::camera_file_check!("Canon", "EOS Rebel T3i", cam_canon_eos_rebel_t3i_iso_100_raw_cr2, "raw_modes/Canon EOS REBEL T3i_ISO_100_RAW.CR2"); } mod camera_eos_rebel_t3_raw_modes { super::camera_file_check!("Canon", "EOS Rebel T3", cam_canon_eos_rebel_t3_iso_800_raw_cr2, "raw_modes/Canon EOS REBEL T3_ISO_800_RAW.CR2"); } mod camera_eos_rebel_t4i_raw_modes { super::camera_file_check!("Canon", "EOS Rebel T4i", cam_canon_eos_rebel_t4i_iso_100_raw_cr2, "raw_modes/Canon EOS REBEL T4i_ISO_100_RAW.CR2"); } mod camera_eos_rebel_t5i_raw_modes { super::camera_file_check!("Canon", "EOS Rebel T5i", cam_canon_eos_rebel_t5i_iso_400_raw_cr2, "raw_modes/Canon EOS REBEL T5i_ISO_400_RAW.CR2"); } mod camera_eos_rebel_t5_raw_modes { super::camera_file_check!("Canon", "EOS Rebel T5", cam_canon_eos_rebel_t5_iso_800_raw_cr2, "raw_modes/Canon EOS REBEL T5_ISO_800_RAW.CR2"); } mod camera_eos_rebel_t6i_raw_modes { super::camera_file_check!("Canon", "EOS Rebel T6i", cam_canon_eos_rebel_t6i_iso_100_raw_cr2, "raw_modes/Canon EOS Rebel T6i_ISO_100_RAW.CR2"); } mod camera_eos_rebel_t6_raw_modes { super::camera_file_check!("Canon", "EOS Rebel T6", cam_canon_eos_rebel_t6_iso_200_raw_cr2, "raw_modes/Canon EOS Rebel T6_ISO_200_RAW.CR2"); } mod camera_eos_rebel_t6s_raw_modes { super::camera_file_check!("Canon", "EOS Rebel T6s", cam_canon_eos_rebel_t6s_iso_200_raw_cr2, "raw_modes/Canon EOS Rebel T6s_ISO_200_RAW.CR2"); } mod camera_eos_rebel_t7i_raw_modes { super::camera_file_check!("Canon", "EOS REBEL T7i", cam_canon_eos_rebel_t7i_iso_800_raw_cr2, "raw_modes/Canon EOS REBEL T7i_ISO_800_RAW.CR2"); } mod camera_eos_rebel_t7_raw_modes { super::camera_file_check!("Canon", "EOS Rebel T7", cam_canon_eos_rebel_t7_iso_200_raw_cr2, "raw_modes/Canon EOS Rebel T7_ISO_200_RAW.CR2"); } mod camera_eos_rp_raw_modes { super::camera_file_check!("Canon", "EOS RP", cam_canon_eos_rp_craw_iso_100_crop_nodual_cr3, "raw_modes/Canon EOS RP_CRAW_ISO_100_crop_nodual.CR3"); super::camera_file_check!("Canon", "EOS RP", cam_canon_eos_rp_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS RP_RAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS RP", cam_canon_eos_rp_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS RP_CRAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS RP", cam_canon_eos_rp_raw_iso_100_crop_nodual_cr3, "raw_modes/Canon EOS RP_RAW_ISO_100_crop_nodual.CR3"); } mod camera_eos_r_raw_modes { super::camera_file_check!("Canon", "EOS R", cam_canon_eos_r_raw_iso_100_crop_dual_cr3, "raw_modes/Canon EOS R_RAW_ISO_100_crop_dual.CR3"); super::camera_file_check!("Canon", "EOS R", cam_canon_eos_r_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS R_RAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS R", cam_canon_eos_r_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon EOS R_CRAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "EOS R", cam_canon_eos_r_raw_iso_100_crop_nodual_cr3, "raw_modes/Canon EOS R_RAW_ISO_100_crop_nodual.CR3"); super::camera_file_check!("Canon", "EOS R", cam_canon_eos_r_craw_iso_100_crop_nodual_cr3, "raw_modes/Canon EOS R_CRAW_ISO_100_crop_nodual.CR3"); super::camera_file_check!("Canon", "EOS R", cam_canon_eos_r_raw_iso_100_nocrop_dual_cr3, "raw_modes/Canon EOS R_RAW_ISO_100_nocrop_dual.CR3"); super::camera_file_check!("Canon", "EOS R", cam_canon_eos_r_craw_iso_100_crop_dual_cr3, "raw_modes/Canon EOS R_CRAW_ISO_100_crop_dual.CR3"); super::camera_file_check!("Canon", "EOS R", cam_canon_eos_r_craw_iso_100_nocrop_dual_cr3, "raw_modes/Canon EOS R_CRAW_ISO_100_nocrop_dual.CR3"); } mod camera_ixus900ti_raw_modes { super::camera_file_check!("Canon", "IXUS900Ti", cam_canon_ixus900ti_crw, "raw_modes/Canon IXUS900Ti.CRW"); } mod camera_ixy_220f_raw_modes { super::camera_file_check!("Canon", "IXY 220F", cam_canon_ixy_220f_crw, "raw_modes/canon_ixy_220f.CRW"); } mod camera_powershot_a480_raw_modes { super::camera_file_check!("Canon", "PowerShot A480", cam_powershot_a480_crw, "raw_modes/PowerShot A480.CRW"); } mod camera_powershot_a540_raw_modes { super::camera_file_check!("Canon", "PowerShot A540", cam_canon_powershot_a540_crw, "raw_modes/Canon PowerShot A540.CRW"); } mod camera_powershot_a550_raw_modes { super::camera_file_check!("Canon", "PowerShot A550", cam_powershot_a550_crw, "raw_modes/PowerShot A550.CRW"); } mod camera_powershot_a570_is_raw_modes { super::camera_file_check!("Canon", "PowerShot A570 IS", cam_powershot_a570_is_crw, "raw_modes/PowerShot A570 IS.CRW"); } mod camera_powershot_a610_raw_modes { super::camera_file_check!("Canon", "PowerShot A610", cam_canon_powershot_a610_crw, "raw_modes/Canon PowerShot A610.CRW"); } mod camera_powershot_a620_raw_modes { super::camera_file_check!("Canon", "PowerShot A620", cam_powershot_a620_crw, "raw_modes/Powershot A620.CRW"); } mod camera_powershot_a630_raw_modes { super::camera_file_check!("Canon", "PowerShot A630", cam_canon_powershot_a630_crw, "raw_modes/Canon PowerShot A630.CRW"); } mod camera_powershot_a640_raw_modes { super::camera_file_check!("Canon", "PowerShot A640", cam_powershot_a640_crw, "raw_modes/Powershot A640.CRW"); } mod camera_powershot_a650_raw_modes { super::camera_file_check!("Canon", "PowerShot A650", cam_canon_powershot_a650_crw, "raw_modes/Canon Powershot A650.CRW"); } mod camera_powershot_a710_is_raw_modes { super::camera_file_check!("Canon", "PowerShot A710 IS", cam_canon_powershot_a710_is_crw, "raw_modes/Canon PowerShot A710 IS.CRW"); } mod camera_powershot_a720_is_raw_modes { super::camera_file_check!("Canon", "PowerShot A720 IS", cam_powershot_a720is_crw, "raw_modes/Powershot A720IS.CRW"); } mod camera_powershot_d10_raw_modes { super::camera_file_check!("Canon", "PowerShot D10", cam_powershot_d10_crw, "raw_modes/PowerShot D10.CRW"); } mod camera_powershot_elph_130_is_raw_modes { super::camera_file_check!("Canon", "PowerShot ELPH 130 IS", cam_canon_powershot_elph_130_is_crw, "raw_modes/Canon PowerShot ELPH 130 IS.CRW"); } mod camera_powershot_g10_raw_modes { super::camera_file_check!("Canon", "PowerShot G10", cam_canon_powershot_g10_iso_80_raw_cr2, "raw_modes/Canon PowerShot G10_ISO_80_RAW.CR2"); } mod camera_powershot_g11_raw_modes { super::camera_file_check!("Canon", "PowerShot G11", cam_canon_powershot_g11_iso_400_raw_cr2, "raw_modes/Canon PowerShot G11_ISO_400_RAW.CR2"); } mod camera_powershot_g12_raw_modes { super::camera_file_check!("Canon", "PowerShot G12", cam_canon_powershot_g12_iso_200_raw_cr2, "raw_modes/Canon PowerShot G12_ISO_200_RAW.CR2"); } mod camera_powershot_g15_raw_modes { super::camera_file_check!("Canon", "PowerShot G15", cam_canon_powershot_g15_iso_80_raw_cr2, "raw_modes/Canon PowerShot G15_ISO_80_RAW.CR2"); } mod camera_powershot_g16_raw_modes { super::camera_file_check!("Canon", "PowerShot G16", cam_canon_powershot_g16_iso_80_raw_cr2, "raw_modes/Canon PowerShot G16_ISO_80_RAW.CR2"); } mod camera_powershot_g1_raw_modes { super::camera_file_check!("Canon", "PowerShot G1", cam_canon_powershot_g1_iso_50_crw, "raw_modes/Canon PowerShot G1_ISO_50.CRW"); } mod camera_powershot_g1_x_mark_iii_raw_modes { super::camera_file_check!("Canon", "PowerShot G1 X Mark III", cam_canon_powershot_g1_x_mark_iii_iso_100_raw_cr2, "raw_modes/Canon PowerShot G1 X Mark III_ISO_100_RAW.CR2"); } mod camera_powershot_g1_x_mark_ii_raw_modes { super::camera_file_check!("Canon", "PowerShot G1 X Mark II", cam_canon_powershot_g1_x_mark_ii_iso_100_raw_cr2, "raw_modes/Canon PowerShot G1 X Mark II_ISO_100_RAW.CR2"); } mod camera_powershot_g1_x_raw_modes { super::camera_file_check!("Canon", "PowerShot G1 X", cam_canon_powershot_g1_x_iso_100_raw_cr2, "raw_modes/Canon PowerShot G1 X_ISO_100_RAW.CR2"); } mod camera_powershot_g2_raw_modes { super::camera_file_check!("Canon", "PowerShot G2", cam_canon_powershot_g2_iso_100_crw, "raw_modes/Canon PowerShot G2_ISO_100.CRW"); } mod camera_powershot_g3_raw_modes { super::camera_file_check!("Canon", "PowerShot G3", cam_canon_powershot_g3_iso_50_crw, "raw_modes/Canon PowerShot G3_ISO_50.CRW"); } mod camera_powershot_g3_x_raw_modes { super::camera_file_check!("Canon", "PowerShot G3 X", cam_canon_powershot_g3_x_iso_200_raw_cr2, "raw_modes/Canon PowerShot G3 X_ISO_200_RAW.CR2"); } mod camera_powershot_g5_raw_modes { super::camera_file_check!("Canon", "PowerShot G5", cam_canon_powershot_g5_iso_100_crw, "raw_modes/Canon PowerShot G5_ISO_100.CRW"); } mod camera_powershot_g5_x_mark_ii_raw_modes { super::camera_file_check!("Canon", "PowerShot G5 X Mark II", cam_canon_powershot_g5_x_mark_ii_craw_iso_200_nocrop_nodual_cr3, "raw_modes/Canon PowerShot G5 X Mark II_CRAW_ISO_200_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "PowerShot G5 X Mark II", cam_canon_powershot_g5_x_mark_ii_raw_iso_200_nocrop_nodual_cr3, "raw_modes/Canon PowerShot G5 X Mark II_RAW_ISO_200_nocrop_nodual.CR3"); } mod camera_powershot_g5_x_raw_modes { super::camera_file_check!("Canon", "PowerShot G5 X", cam_canon_powershot_g5_x_iso_400_raw_cr2, "raw_modes/Canon PowerShot G5 X_ISO_400_RAW.CR2"); } mod camera_powershot_g6_raw_modes { super::camera_file_check!("Canon", "PowerShot G6", cam_canon_powershot_g6_iso_100_crw, "raw_modes/Canon PowerShot G6_ISO_100.CRW"); } mod camera_powershot_g7_x_mark_iii_raw_modes { super::camera_file_check!("Canon", "PowerShot G7 X Mark III", cam_canon_powershot_g7_x_mark_iii_raw_iso_200_nocrop_nodual_cr3, "raw_modes/Canon PowerShot G7 X Mark III_RAW_ISO_200_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "PowerShot G7 X Mark III", cam_canon_powershot_g7_x_mark_iii_craw_iso_200_nocrop_nodual_cr3, "raw_modes/Canon PowerShot G7 X Mark III_CRAW_ISO_200_nocrop_nodual.CR3"); } mod camera_powershot_g7_x_mark_ii_raw_modes { super::camera_file_check!("Canon", "PowerShot G7 X Mark II", cam_canon_powershot_g7_x_mark_ii_iso_125_raw_cr2, "raw_modes/Canon PowerShot G7 X Mark II_ISO_125_RAW.CR2"); } mod camera_powershot_g7_x_raw_modes { super::camera_file_check!("Canon", "PowerShot G7 X", cam_canon_powershot_g7_x_iso_125_raw_cr2, "raw_modes/Canon PowerShot G7 X_ISO_125_RAW.CR2"); super::camera_file_check!("Canon", "PowerShot G7 X", cam_powershot_g7_x_crw, "raw_modes/PowerShot G7 X.CRW"); } mod camera_powershot_g9_raw_modes { super::camera_file_check!("Canon", "PowerShot G9", cam_canon_powershot_g9_iso_80_raw_cr2, "raw_modes/Canon PowerShot G9_ISO_80_RAW.CR2"); } mod camera_powershot_g9_x_mark_ii_raw_modes { super::camera_file_check!("Canon", "PowerShot G9 X Mark II", cam_canon_powershot_g9_x_mark_ii_iso_125_raw_cr2, "raw_modes/Canon PowerShot G9 X Mark II_ISO_125_RAW.CR2"); } mod camera_powershot_g9_x_raw_modes { super::camera_file_check!("Canon", "PowerShot G9 X", cam_canon_powershot_g9_x_iso_640_raw_cr2, "raw_modes/Canon PowerShot G9 X_ISO_640_RAW.CR2"); } mod camera_powershot_pro1_raw_modes { super::camera_file_check!("Canon", "PowerShot Pro1", cam_canon_powershot_pro1_iso_50_crw, "raw_modes/Canon PowerShot Pro1_ISO_50.CRW"); } mod camera_powershot_s100_raw_modes { super::camera_file_check!("Canon", "PowerShot S100", cam_canon_powershot_s100_iso_80_raw_cr2, "raw_modes/Canon PowerShot S100_ISO_80_RAW.CR2"); } mod camera_powershot_s100v_raw_modes { super::camera_file_check!("Canon", "PowerShot S100V", cam_canon_powershot_s100v_iso_200_raw_cr2, "raw_modes/Canon PowerShot S100V_ISO_200_RAW.CR2"); } mod camera_powershot_s110_raw_modes { super::camera_file_check!("Canon", "PowerShot S110", cam_canon_powershot_s110_iso_100_raw_cr2, "raw_modes/Canon PowerShot S110_ISO_100_RAW.CR2"); } mod camera_powershot_s120_raw_modes { super::camera_file_check!("Canon", "PowerShot S120", cam_canon_powershot_s120_iso_250_raw_cr2, "raw_modes/Canon PowerShot S120_ISO_250_RAW.CR2"); } mod camera_powershot_s2_is_raw_modes { super::camera_file_check!("Canon", "PowerShot S2 IS", cam_canon_powershot_s2_is_crw, "raw_modes/Canon PowerShot S2 IS.CRW"); } mod camera_powershot_s30_raw_modes { super::camera_file_check!("Canon", "PowerShot S30", cam_canon_powershot_s30_iso_50_crw, "raw_modes/Canon PowerShot S30_ISO_50.CRW"); } mod camera_powershot_s3is_raw_modes { super::camera_file_check!("Canon", "PowerShot S3IS", cam_canon_powershot_s3is_crw, "raw_modes/Canon PowerShot S3IS.CRW"); super::camera_file_check!("Canon", "PowerShot S3IS", cam_powershot_s3is_crw, "raw_modes/PowerShot S3IS.CRW"); } mod camera_powershot_s40_raw_modes { super::camera_file_check!("Canon", "PowerShot S40", cam_canon_powershot_s40_iso_50_crw, "raw_modes/Canon PowerShot S40_ISO_50.CRW"); } mod camera_powershot_s45_raw_modes { super::camera_file_check!("Canon", "PowerShot S45", cam_canon_powershot_s45_iso_50_crw, "raw_modes/Canon PowerShot S45_ISO_50.CRW"); } mod camera_powershot_s50_raw_modes { super::camera_file_check!("Canon", "PowerShot S50", cam_canon_powershot_s50_iso_50_crw, "raw_modes/Canon PowerShot S50_ISO_50.CRW"); } mod camera_powershot_s5_is_raw_modes { super::camera_file_check!("Canon", "PowerShot S5 IS", cam_canon_powershot_s5_is_crw, "raw_modes/Canon PowerShot S5 IS.CRW"); } mod camera_powershot_s60_raw_modes { super::camera_file_check!("Canon", "PowerShot S60", cam_canon_powershot_s60_iso_50_crw, "raw_modes/Canon PowerShot S60_ISO_50.CRW"); } mod camera_powershot_s70_raw_modes { super::camera_file_check!("Canon", "PowerShot S70", cam_canon_powershot_s70_iso_100_crw, "raw_modes/Canon PowerShot S70_ISO_100.CRW"); } mod camera_powershot_s90_raw_modes { super::camera_file_check!("Canon", "PowerShot S90", cam_canon_powershot_s90_iso_80_raw_cr2, "raw_modes/Canon PowerShot S90_ISO_80_RAW.CR2"); } mod camera_powershot_s95_raw_modes { super::camera_file_check!("Canon", "PowerShot S95", cam_canon_powershot_s95_iso_400_raw_cr2, "raw_modes/Canon PowerShot S95_ISO_400_RAW.CR2"); } mod camera_powershot_sd750_raw_modes { super::camera_file_check!("Canon", "PowerShot SD750", cam_canon_powershot_sd750_crw, "raw_modes/Canon PowerShot SD750.CRW"); } mod camera_powershot_sx110_is_raw_modes { super::camera_file_check!("Canon", "PowerShot SX110 IS", cam_powershot_sx110_is_crw, "raw_modes/PowerShot SX110 IS.CRW"); } mod camera_powershot_sx160_is_raw_modes { super::camera_file_check!("Canon", "PowerShot SX160 IS", cam_canon_powershot_sx160_is_crw, "raw_modes/Canon PowerShot SX160 IS.CRW"); } mod camera_powershot_sx1_is_raw_modes { super::camera_file_check!("Canon", "PowerShot SX1 IS", cam_canon_powershot_sx1_is_iso_80_raw_cr2, "raw_modes/Canon PowerShot SX1 IS_ISO_80_RAW.CR2"); } mod camera_powershot_sx260_hs_raw_modes { super::camera_file_check!("Canon", "PowerShot SX260 HS", cam_powershot_sx260_hs_crw, "raw_modes/PowerShot SX260 HS.CRW"); } mod camera_powershot_sx40_hs_raw_modes { super::camera_file_check!("Canon", "PowerShot SX40 HS", cam_crw_6036_cr2, "raw_modes/CRW_6036.CR2"); } mod camera_powershot_sx50_hs_raw_modes { super::camera_file_check!("Canon", "PowerShot SX50 HS", cam_canon_powershot_sx50_hs_iso_80_raw_cr2, "raw_modes/Canon PowerShot SX50 HS_ISO_80_RAW.CR2"); } mod camera_powershot_sx60_hs_raw_modes { super::camera_file_check!("Canon", "PowerShot SX60 HS", cam_canon_powershot_sx60_hs_iso_100_raw_cr2, "raw_modes/Canon PowerShot SX60 HS_ISO_100_RAW.CR2"); super::camera_file_check!("Canon", "PowerShot SX60 HS", cam_raw_canon_powershot_sx60_hs_cr2, "raw_modes/RAW_CANON_POWERSHOT_SX60-HS.CR2"); } mod camera_powershot_sx70_hs_raw_modes { super::camera_file_check!("Canon", "PowerShot SX70 HS", cam_canon_powershot_sx70_hs_raw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon PowerShot SX70 HS_RAW_ISO_100_nocrop_nodual.CR3"); super::camera_file_check!("Canon", "PowerShot SX70 HS", cam_canon_powershot_sx70_hs_craw_iso_100_nocrop_nodual_cr3, "raw_modes/Canon PowerShot SX70 HS_CRAW_ISO_100_nocrop_nodual.CR3"); } mod camera_sx150is_raw_modes { super::camera_file_check!("Canon", "SX150IS", cam_sx150is_crw, "raw_modes/SX150IS.CRW"); } mod camera_ist_dl2_raw_modes { super::camera_file_check!("Pentax", "ist DL2", cam_pentax_ist_dl2_raw_iso_200_pef, "raw_modes/PENTAX ist DL2_RAW_ISO_200.PEF"); } mod camera_k_5_ii_raw_modes { super::camera_file_check!("Pentax", "K-5 II", cam_pentax_k_5_ii_raw_iso_500_pef, "raw_modes/PENTAX K-5 II_RAW_ISO_500.PEF"); } mod camera_645d_raw_modes { super::camera_file_check!("Pentax", "645D", cam_pentax_645d_raw_iso_200_pef, "raw_modes/PENTAX 645D_RAW_ISO_200.PEF"); } mod camera_645z_raw_modes { super::camera_file_check!("Pentax", "645Z", cam_pentax_645z_raw_iso_100_pef, "raw_modes/PENTAX 645Z_RAW_ISO_100.PEF"); } mod camera_ist_dl_raw_modes { super::camera_file_check!("Pentax", "ist DL", cam_pentax_ist_dl_raw_iso_200_pef, "raw_modes/PENTAX ist DL_RAW_ISO_200.PEF"); } mod camera_k_3_raw_modes { super::camera_file_check!("Pentax", "K-3", cam_pentax_k_3_raw_iso_100_pef, "raw_modes/PENTAX K-3_RAW_ISO_100.PEF"); } mod camera_k_3_iii_monochrome_raw_modes { super::camera_file_check!("Pentax", "K-3 III Monochrome", cam_pentax_k_3_mark_iii_monochrome_iso_200_14bits_pef, "raw_modes/PENTAX K-3 Mark III Monochrome_ISO_200_14bits.PEF"); } mod camera_k_7_raw_modes { super::camera_file_check!("Pentax", "K-7", cam_pentax_k_7_raw_iso_3200_pef, "raw_modes/PENTAX K-7_RAW_ISO_3200.PEF"); } mod camera_k_3_ii_raw_modes { super::camera_file_check!("Pentax", "K-3 II", cam_pentax_k_3_ii_raw_iso_100_pef, "raw_modes/PENTAX K-3 II_RAW_ISO_100.PEF"); } mod camera_k_3_iii_raw_modes { super::camera_file_check!("Pentax", "K-3 III", cam_pentax_k_3_mark_iii_iso_800_14bits_pixelshift_without_motion_corr_pef, "raw_modes/PENTAX K-3 Mark III_ISO_800_14bits_pixelshift_without_motion_corr.PEF"); super::camera_file_check!("Pentax", "K-3 III", cam_pentax_k_3_mark_iii_iso_800_14bits_pixelshift_with_motion_corr_pef, "raw_modes/PENTAX K-3 Mark III_ISO_800_14bits_pixelshift_with_motion_corr.PEF"); super::camera_file_check!("Pentax", "K-3 III", cam_pentax_k_3_mark_iii_iso_800_14bits_automode_pef, "raw_modes/PENTAX K-3 Mark III_ISO_800_14bits_automode.PEF"); super::camera_file_check!("Pentax", "K-3 III", cam_pentax_k_3_mark_iii_iso_800_14bits_hdr_advanced_pef, "raw_modes/PENTAX K-3 Mark III_ISO_800_14bits_hdr_advanced.PEF"); } mod camera_k_70_raw_modes { super::camera_file_check!("Pentax", "K-70", cam_pentax_k_70_raw_iso_400_pef, "raw_modes/PENTAX K-70_RAW_ISO_400.PEF"); } mod camera_k_m_raw_modes { super::camera_file_check!("Pentax", "K-m", cam_pentax_k_m_raw_iso_200_pef, "raw_modes/PENTAX K-m_RAW_ISO_200.PEF"); } mod camera_k_r_raw_modes { super::camera_file_check!("Pentax", "K-r", cam_pentax_k_r_raw_iso_200_pef, "raw_modes/PENTAX K-r_RAW_ISO_200.PEF"); } mod camera_kf_raw_modes { super::camera_file_check!("Pentax", "Kf", cam_pentax_kf_iso_200_14bits_pef, "raw_modes/PENTAX KF_ISO_200_14bits.PEF"); } mod camera_k_5_ii_s_raw_modes { super::camera_file_check!("Pentax", "K-5 II s", cam_pentax_k_5_ii_s_raw_iso_200_pef, "raw_modes/PENTAX K-5 II s_RAW_ISO_200.PEF"); } mod camera_ist_ds_raw_modes { super::camera_file_check!("Pentax", "ist DS", cam_pentax_ist_ds_raw_iso_200_pef, "raw_modes/PENTAX ist DS_RAW_ISO_200.PEF"); } mod camera_k_1_mark_ii_raw_modes { super::camera_file_check!("Pentax", "K-1 Mark II", cam_pentax_k_1_mark_ii_raw__pixel_shift_enabled__iso_125_pef, "raw_modes/PENTAX K-1 Mark II_RAW (pixel shift enabled)_ISO_125.PEF"); super::camera_file_check!("Pentax", "K-1 Mark II", cam_pentax_k_1_mark_ii_raw_iso_125_pef, "raw_modes/PENTAX K-1 Mark II_RAW_ISO_125.PEF"); } mod camera_ist_d_raw_modes { super::camera_file_check!("Pentax", "ist D", cam_pentax_ist_d_raw_iso_200_pef, "raw_modes/PENTAX ist D_RAW_ISO_200.PEF"); } mod camera_k100d_super_raw_modes { super::camera_file_check!("Pentax", "K100D Super", cam_pentax_k100d_super_raw_iso_200_pef, "raw_modes/PENTAX K100D Super_RAW_ISO_200.PEF"); } mod camera_k_s2_raw_modes { super::camera_file_check!("Pentax", "K-S2", cam_pentax_k_s2_raw_iso_1250_pef, "raw_modes/PENTAX K-S2_RAW_ISO_1250.PEF"); } mod camera_k_5_raw_modes { super::camera_file_check!("Pentax", "K-5", cam_pentax_k_5_raw_iso_160_pef, "raw_modes/PENTAX K-5_RAW_ISO_160.PEF"); } mod camera_k10d_raw_modes { super::camera_file_check!("Pentax", "K10D", cam_pentax_k10d_raw_iso_100_pef, "raw_modes/PENTAX K10D_RAW_ISO_100.PEF"); } mod camera_k100d_raw_modes { super::camera_file_check!("Pentax", "K100D", cam_pentax_k100d_raw_iso_200_pef, "raw_modes/PENTAX K100D_RAW_ISO_200.PEF"); } mod camera_k_1_raw_modes { super::camera_file_check!("Pentax", "K-1", cam_pentax_k_1_raw__pixel_shift_enabled__iso_160_pef, "raw_modes/PENTAX K-1_RAW (pixel shift enabled)_ISO_160.PEF"); super::camera_file_check!("Pentax", "K-1", cam_pentax_k_1_raw_iso_160_pef, "raw_modes/PENTAX K-1_RAW_ISO_160.PEF"); } mod camera_kp_raw_modes { super::camera_file_check!("Pentax", "KP", cam_pentax_kp_raw_iso_400_pef, "raw_modes/PENTAX KP_RAW_ISO_400.PEF"); } mod camera_k200d_raw_modes { super::camera_file_check!("Pentax", "K200D", cam_pentax_k200d_raw_iso_100_pef, "raw_modes/PENTAX K200D_RAW_ISO_100.PEF"); } mod camera_k_s1_raw_modes { super::camera_file_check!("Pentax", "K-S1", cam_pentax_k_s1_raw_iso_100_pef, "raw_modes/PENTAX K-S1_RAW_ISO_100.PEF"); } mod camera_k_x_raw_modes { super::camera_file_check!("Pentax", "K-x", cam_pentax_k_x_raw_iso_2000_pef, "raw_modes/PENTAX K-x_RAW_ISO_2000.PEF"); } mod camera_k20d_raw_modes { super::camera_file_check!("Pentax", "K20D", cam_pentax_k20d_raw_iso_200_pef, "raw_modes/PENTAX K20D_RAW_ISO_200.PEF"); } mod camera_k110d_raw_modes { super::camera_file_check!("Pentax", "K110D", cam_pentax_k110d_raw_iso_200_pef, "raw_modes/PENTAX K110D_RAW_ISO_200.PEF"); } mod camera_iq3_100mp_raw_modes { super::camera_file_check!("Phase One", "IQ3 100MP", cam_iq3_100mp_l16_iso_50_iiq, "raw_modes/IQ3 100MP_L16_ISO_50.IIQ"); super::camera_file_check!("Phase One", "IQ3 100MP", cam_iq3_100mp_iiq_l_iso_50_iiq, "raw_modes/IQ3 100MP_IIQ L_ISO_50.IIQ"); super::camera_file_check!("Phase One", "IQ3 100MP", cam_iq3_100mp_iiq_sv2_iso_50_iiq, "raw_modes/IQ3 100MP_IIQ Sv2_ISO_50.IIQ"); } mod camera_h_25_raw_modes { super::camera_file_check!("Phase One", "H 25", cam_h_25_iiq_s_iso_100_iiq, "raw_modes/H 25_IIQ S_ISO_100.IIQ"); super::camera_file_check!("Phase One", "H 25", cam_h_25_raw0_iso_50_iiq, "raw_modes/H 25_Raw0_ISO_50.IIQ"); } mod camera_ixm_100_raw_modes { super::camera_file_check!("Phase One", "iXM-100", cam_ixm_100_iiq_l_iso_100_iiq, "raw_modes/iXM-100_IIQ L_ISO_100.IIQ"); super::camera_file_check!("Phase One", "iXM-100", cam_ixm_100_iiq_sv2_iso_100_iiq, "raw_modes/iXM-100_IIQ Sv2_ISO_100.IIQ"); } mod camera_iq180_raw_modes { super::camera_file_check!("Phase One", "IQ180", cam_iq180_iiq_l_iso_100_iiq, "raw_modes/IQ180_IIQ L_ISO_100.IIQ"); } mod camera_iq4_150mp_raw_modes { super::camera_file_check!("Phase One", "IQ4 150MP", cam_iq4_150mp_iiq_l16_iso_100_iiq, "raw_modes/IQ4 150MP_IIQ L16_ISO_100.IIQ"); super::camera_file_check!("Phase One", "IQ4 150MP", cam_iq4_150mp_iiq_l16ex_iso_100_iiq, "raw_modes/IQ4 150MP_IIQ L16ex_ISO_100.IIQ"); super::camera_file_check!("Phase One", "IQ4 150MP", cam_iq4_150mp_iiq_l_iso_100_iiq, "raw_modes/IQ4 150MP_IIQ L_ISO_100.IIQ"); } mod camera_iq140_raw_modes { super::camera_file_check!("Phase One", "IQ140", cam_iq140_iiq_l_iso_50_iiq, "raw_modes/IQ140_IIQ L_ISO_50.IIQ"); super::camera_file_check!("Phase One", "IQ140", cam_iq140_iiq_l_iso_200_sensorplus_iiq, "raw_modes/IQ140_IIQ L_ISO_200_SensorPlus.IIQ"); super::camera_file_check!("Phase One", "IQ140", cam_iq140_iiq_sv2_iso_50_iiq, "raw_modes/IQ140_IIQ Sv2_ISO_50.IIQ"); super::camera_file_check!("Phase One", "IQ140", cam_iq140_iiq_sv2_iso_200_sensorplus_iiq, "raw_modes/IQ140_IIQ Sv2_ISO_200_SensorPlus.IIQ"); } mod camera_p30_raw_modes { super::camera_file_check!("Phase One", "P30", cam_p30_iiq_l_iso_100_iiq, "raw_modes/P30_IIQ L_ISO_100.IIQ"); } mod camera_iq3_100mp_trichr_raw_modes { super::camera_file_check!("Phase One", "IQ3 100MP Trichr", cam_iq3_100mp_trichr_l16_iso_50_iiq, "raw_modes/IQ3 100MP Trichr_L16_ISO_50.IIQ"); } mod camera_iq150_raw_modes { super::camera_file_check!("Phase One", "IQ150", cam_iq150_iiq_l_iso_400_iiq, "raw_modes/IQ150_IIQ L_ISO_400.IIQ"); } mod camera_ixm_rs150f_raw_modes { super::camera_file_check!("Phase One", "iXM-RS150F", cam_ixm_rs150f_iiq_sv2_iso_160_iiq, "raw_modes/iXM-RS150F_IIQ Sv2_ISO_160.IIQ"); } mod camera_ixu_rs1000_nir_raw_modes { super::camera_file_check!("Phase One", "iXU-RS1000 NIR", cam_ixu_rs1000_iiq, "raw_modes/iXU-RS1000.IIQ"); } mod camera_p65_raw_modes { super::camera_file_check!("Phase One", "P65", cam_p65_plus_iiq_l_iso_200_iiq, "raw_modes/P65 Plus_IIQ L_ISO_200.IIQ"); super::camera_file_check!("Phase One", "P65", cam_p65_plus_iiq_s_iso_200_iiq, "raw_modes/P65 Plus_IIQ S_ISO_200.IIQ"); } mod camera_p20_raw_modes { super::camera_file_check!("Phase One", "P20", cam_p20_plus_iiq_s_iso_50_iiq, "raw_modes/P20 Plus_IIQ S_ISO_50.IIQ"); super::camera_file_check!("Phase One", "P20", cam_p20_plus_iiq_l_iso_50_iiq, "raw_modes/P20 Plus_IIQ L_ISO_50.IIQ"); } mod camera_p25_raw_modes { super::camera_file_check!("Phase One", "P25", cam_p25_4x3_s_iiq, "raw_modes/P25_4x3_S.IIQ"); super::camera_file_check!("Phase One", "P25", cam_p25_4x3_l_iiq, "raw_modes/P25_4x3_L.IIQ"); } mod camera_p25plus_raw_modes { super::camera_file_check!("Phase One", "P25+", cam_p25__s_4x3_iiq, "raw_modes/P25+_S_4x3.IIQ"); super::camera_file_check!("Phase One", "P25+", cam_p25__l_4x3_iiq, "raw_modes/P25+_L_4x3.IIQ"); } mod camera_p45plus_raw_modes { super::camera_file_check!("Phase One", "P45+", cam_p45__l_4x3_iiq, "raw_modes/P45+_L_4x3.IIQ"); super::camera_file_check!("Phase One", "P45+", cam_p45__s_4x3_iiq, "raw_modes/P45+_S_4x3.IIQ"); } mod camera_d3500_raw_modes { super::camera_file_check!("Nikon", "D3500", cam_nikon_d3500_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON D3500_ISO_100_12bits_Lossy (type 2).NEF"); } mod camera_1_v2_raw_modes { super::camera_file_check!("Nikon", "1 V2", cam_nikon_1_v2_iso_200_12bits_lossy__type_2__nef, "raw_modes/NIKON 1 V2_ISO_200_12bits_Lossy (type 2).NEF"); } mod camera_d40x_raw_modes { super::camera_file_check!("Nikon", "D40X", cam_nikon_d40x_iso_250_12bits_lossy__type_1__nef, "raw_modes/NIKON D40X_ISO_250_12bits_Lossy (type 1).NEF"); } mod camera_d5600_raw_modes { super::camera_file_check!("Nikon", "D5600", cam_nikon_d5600_iso_12800_12bits_lossy__type_2__nef, "raw_modes/NIKON D5600_ISO_12800_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D5600", cam_nikon_d5600_iso_200_14bits_lossy__type_2__nef, "raw_modes/NIKON D5600_ISO_200_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D5600", cam_nikon_d5600_iso_12800_14bits_lossy__type_2__nef, "raw_modes/NIKON D5600_ISO_12800_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D5600", cam_nikon_d5600_iso_200_12bits_lossy__type_2__nef, "raw_modes/NIKON D5600_ISO_200_12bits_Lossy (type 2).NEF"); } mod camera_d70s_raw_modes { super::camera_file_check!("Nikon", "D70s", cam_nikon_d70s_iso_200_12bits_lossy__type_1__nef, "raw_modes/NIKON D70s_ISO_200_12bits_Lossy (type 1).NEF"); } mod camera_coolpix_p7100_raw_modes { super::camera_file_check!("Nikon", "Coolpix P7100", cam_coolpix_p7100_iso_100_12bits_uncompressed_nrw, "raw_modes/COOLPIX P7100_ISO_100_12bits_Uncompressed.NRW"); } mod camera_d600_raw_modes { super::camera_file_check!("Nikon", "D600", cam_nikon_d600_iso_400_14bits_lossless_nef, "raw_modes/NIKON D600_ISO_400_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D600", cam_nikon_d600_iso_400_12bits_lossy__type_2__nef, "raw_modes/NIKON D600_ISO_400_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D600", cam_nikon_d600_iso_400_12bits_lossless_nef, "raw_modes/NIKON D600_ISO_400_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D600", cam_nikon_d600_iso_400_14bits_lossy__type_2__nef, "raw_modes/NIKON D600_ISO_400_14bits_Lossy (type 2).NEF"); } mod camera_d2x_raw_modes { super::camera_file_check!("Nikon", "D2X", cam_nikon_d2x_iso_100_12bits_uncompressed_nef, "raw_modes/NIKON D2X_ISO_100_12bits_Uncompressed.NEF"); } mod camera_d40_raw_modes { super::camera_file_check!("Nikon", "D40", cam_nikon_d40_iso_200_12bits_lossy__type_1__nef, "raw_modes/NIKON D40_ISO_200_12bits_Lossy (type 1).NEF"); } mod camera_d4_raw_modes { super::camera_file_check!("Nikon", "D4", cam_nikon_d4_iso_400_12bits_lossy__type_2__nef, "raw_modes/NIKON D4_ISO_400_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D4", cam_nikon_d4_iso_400_12bits_uncompressed_nef, "raw_modes/NIKON D4_ISO_400_12bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D4", cam_nikon_d4_iso_400_14bits_lossless_nef, "raw_modes/NIKON D4_ISO_400_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D4", cam_nikon_d4_iso_400_14bits_uncompressed_nef, "raw_modes/NIKON D4_ISO_400_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D4", cam_nikon_d4_iso_400_12bits_lossless_nef, "raw_modes/NIKON D4_ISO_400_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D4", cam_nikon_d4_iso_400_14bits_lossy__type_2__nef, "raw_modes/NIKON D4_ISO_400_14bits_Lossy (type 2).NEF"); } mod camera_d300s_raw_modes { super::camera_file_check!("Nikon", "D300S", cam_nikon_d300s_iso_100_14bits_uncompressed_nef, "raw_modes/NIKON D300S_ISO_100_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D300S", cam_nikon_d300s_iso_100_12bits_lossless_nef, "raw_modes/NIKON D300S_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D300S", cam_nikon_d300s_iso_100_12bits_uncompressed_nef, "raw_modes/NIKON D300S_ISO_100_12bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D300S", cam_nikon_d300s_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON D300S_ISO_100_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D300S", cam_nikon_d300s_iso_100_14bits_lossless_nef, "raw_modes/NIKON D300S_ISO_100_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D300S", cam_nikon_d300s_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON D300S_ISO_100_12bits_Lossy (type 2).NEF"); } mod camera_d2xs_raw_modes { super::camera_file_check!("Nikon", "D2Xs", cam_nikon_d2xs_iso_100_12bits_uncompressed_nef, "raw_modes/NIKON D2Xs_ISO_100_12bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D2Xs", cam_nikon_d2xs_iso_100_12bits_lossy__type_1__nef, "raw_modes/NIKON D2Xs_ISO_100_12bits_Lossy (type 1).NEF"); } mod camera_d3_raw_modes { super::camera_file_check!("Nikon", "D3", cam_nikon_d3_iso_200_14bits_lossless_nef, "raw_modes/NIKON D3_ISO_200_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D3", cam_nikon_d3_iso_200_12bits_lossy__type_2__nef, "raw_modes/NIKON D3_ISO_200_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D3", cam_nikon_d3_iso_200_12bits_lossless_nef, "raw_modes/NIKON D3_ISO_200_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D3", cam_nikon_d3_iso_200_14bits_uncompressed_nef, "raw_modes/NIKON D3_ISO_200_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D3", cam_nikon_d3_iso_200_14bits_lossy__type_2__nef, "raw_modes/NIKON D3_ISO_200_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D3", cam_nikon_d3_iso_200_12bits_uncompressed_nef, "raw_modes/NIKON D3_ISO_200_12bits_Uncompressed.NEF"); } mod camera_d800e_raw_modes { super::camera_file_check!("Nikon", "D800E", cam_nikon_d800e_iso_560_14bits_uncompressed_nef, "raw_modes/NIKON D800E_ISO_560_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D800E", cam_nikon_d800e_iso_100_14bits_lossless_nef, "raw_modes/NIKON D800E_ISO_100_14bits_Lossless.NEF"); } mod camera_e5400_raw_modes { super::camera_file_check!("Nikon", "E5400", cam_e5400_iso_0_12bits_uncompressed_nef, "raw_modes/E5400_ISO_0_12bits_Uncompressed.NEF"); } mod camera_coolpix_p6000_raw_modes { super::camera_file_check!("Nikon", "Coolpix P6000", cam_coolpix_p6000_iso_64_12bits_uncompressed_nrw, "raw_modes/COOLPIX P6000_ISO_64_12bits_Uncompressed.NRW"); } mod camera_d700_raw_modes { super::camera_file_check!("Nikon", "D700", cam_nikon_d700_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON D700_ISO_100_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D700", cam_nikon_d700_iso_100_14bits_lossless_nef, "raw_modes/NIKON D700_ISO_100_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D700", cam_nikon_d700_iso_100_14bits_uncompressed_nef, "raw_modes/NIKON D700_ISO_100_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D700", cam_nikon_d700_iso_100_12bits_lossless_nef, "raw_modes/NIKON D700_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D700", cam_nikon_d700_iso_100_12bits_uncompressed_nef, "raw_modes/NIKON D700_ISO_100_12bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D700", cam_nikon_d700_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON D700_ISO_100_12bits_Lossy (type 2).NEF"); } mod camera_coolpix_p7000_raw_modes { super::camera_file_check!("Nikon", "Coolpix P7000", cam_coolpix_p7000_iso_800_12bits_uncompressed_nrw, "raw_modes/COOLPIX P7000_ISO_800_12bits_Uncompressed.NRW"); } mod camera_d3400_raw_modes { super::camera_file_check!("Nikon", "D3400", cam_nikon_d3400_iso_3200_12bits_lossy__type_2__nef, "raw_modes/NIKON D3400_ISO_3200_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D3400", cam_nikon_d3400_iso_400_12bits_lossy__type_2__nef, "raw_modes/NIKON D3400_ISO_400_12bits_Lossy (type 2).NEF"); } mod camera_d780_raw_modes { super::camera_file_check!("Nikon", "D780", cam_nikon_d780_iso_100_14bits_lossless_nef, "raw_modes/NIKON D780_ISO_100_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D780", cam_nikon_d780_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON D780_ISO_100_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D780", cam_nikon_d780_iso_100_12bits_lossless_nef, "raw_modes/NIKON D780_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D780", cam_nikon_d780_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON D780_ISO_100_12bits_Lossy (type 2).NEF"); } mod camera_d2hs_raw_modes { super::camera_file_check!("Nikon", "D2Hs", cam_nikon_d2hs_iso_200_12bits_uncompressed_nef, "raw_modes/NIKON D2Hs_ISO_200_12bits_Uncompressed.NEF"); } mod camera_1_v1_raw_modes { super::camera_file_check!("Nikon", "1 V1", cam_nikon_1_v1_iso_400_12bits_lossy__type_2__nef, "raw_modes/NIKON 1 V1_ISO_400_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "1 V1", cam_nikon_1_v1_iso_800_12bits_lossy__type_2__nef, "raw_modes/NIKON 1 V1_ISO_800_12bits_Lossy (type 2).NEF"); } mod camera_d610_raw_modes { super::camera_file_check!("Nikon", "D610", cam_nikon_d610_iso_400_14bits_lossy__type_2__nef, "raw_modes/NIKON D610_ISO_400_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D610", cam_nikon_d610_iso_400_12bits_lossy__type_2__nef, "raw_modes/NIKON D610_ISO_400_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D610", cam_nikon_d610_iso_400_14bits_lossless_nef, "raw_modes/NIKON D610_ISO_400_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D610", cam_nikon_d610_iso_400_12bits_lossless_nef, "raw_modes/NIKON D610_ISO_400_12bits_Lossless.NEF"); } mod camera_1_j3_raw_modes { super::camera_file_check!("Nikon", "1 J3", cam_nikon_1_j3_iso_160_12bits_lossy__type_2__nef, "raw_modes/NIKON 1 J3_ISO_160_12bits_Lossy (type 2).NEF"); } mod camera_d50_raw_modes { super::camera_file_check!("Nikon", "D50", cam_nikon_d50_iso_200_12bits_lossy__type_1__nef, "raw_modes/NIKON D50_ISO_200_12bits_Lossy (type 1).NEF"); } mod camera_d3x_raw_modes { super::camera_file_check!("Nikon", "D3X", cam_nikon_d3x_iso_125_14bits_uncompressed_nef, "raw_modes/NIKON D3X_ISO_125_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D3X", cam_nikon_d3x_iso_100_14bits_lossless_nef, "raw_modes/NIKON D3X_ISO_100_14bits_Lossless.NEF"); } mod camera_d5500_raw_modes { super::camera_file_check!("Nikon", "D5500", cam_nikon_d5500_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON D5500_ISO_100_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D5500", cam_nikon_d5500_iso_6400_14bits_lossy__type_2__nef, "raw_modes/NIKON D5500_ISO_6400_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D5500", cam_nikon_d5500_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON D5500_ISO_100_14bits_Lossy (type 2).NEF"); } mod camera_d500_raw_modes { super::camera_file_check!("Nikon", "D500", cam_nikon_d500_large_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON D500_Large_ISO_100_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D500", cam_nikon_d500_small_iso_100_12bits_lossless_nef, "raw_modes/NIKON D500_Small_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D500", cam_nikon_d500_large_iso_100_14bits_lossless_nef, "raw_modes/NIKON D500_Large_ISO_100_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D500", cam_nikon_d500_large_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON D500_Large_ISO_100_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D500", cam_nikon_d500_large_iso_100_14bits_uncompressed_nef, "raw_modes/NIKON D500_Large_ISO_100_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D500", cam_nikon_d500_large_iso_100_12bits_uncompressed__reduced_to_12_bit__nef, "raw_modes/NIKON D500_Large_ISO_100_12bits_Uncompressed (reduced to 12 bit).NEF"); super::camera_file_check!("Nikon", "D500", cam_nikon_d500_medium_iso_100_12bits_lossless_nef, "raw_modes/NIKON D500_Medium_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D500", cam_nikon_d500_large_iso_100_12bits_lossless_nef, "raw_modes/NIKON D500_Large_ISO_100_12bits_Lossless.NEF"); } mod camera_coolpix_b700_raw_modes { super::camera_file_check!("Nikon", "COOLPIX B700", cam_coolpix_b700_iso_100_12bits_uncompressed_nrw, "raw_modes/COOLPIX B700_ISO_100_12bits_Uncompressed.NRW"); } mod camera_coolpix_p7800_raw_modes { super::camera_file_check!("Nikon", "Coolpix P7800", cam_coolpix_p7800_iso_80_12bits_uncompressed_nrw, "raw_modes/COOLPIX P7800_ISO_80_12bits_Uncompressed.NRW"); } mod camera_coolpix_p1000_raw_modes { super::camera_file_check!("Nikon", "COOLPIX P1000", cam_coolpix_p1000_iso_100_12bits_uncompressed_nrw, "raw_modes/COOLPIX P1000_ISO_100_12bits_Uncompressed.NRW"); } mod camera_e5700_raw_modes { super::camera_file_check!("Nikon", "E5700", cam_e5700_iso_0_12bits_uncompressed_nef, "raw_modes/E5700_ISO_0_12bits_Uncompressed.NEF"); } mod camera_d850_raw_modes { super::camera_file_check!("Nikon", "D850", cam_nikon_d850_medium_iso_64_12bits_lossless_nef, "raw_modes/NIKON D850_Medium_ISO_64_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D850", cam_nikon_d850_large_iso_64_14bits_lossy__type_2__nef, "raw_modes/NIKON D850_Large_ISO_64_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D850", cam_nikon_d850_large_iso_64_12bits_uncompressed__reduced_to_12_bit__nef, "raw_modes/NIKON D850_Large_ISO_64_12bits_Uncompressed (reduced to 12 bit).NEF"); super::camera_file_check!("Nikon", "D850", cam_nikon_d850_large_iso_64_14bits_uncompressed_nef, "raw_modes/NIKON D850_Large_ISO_64_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D850", cam_nikon_d850_large_iso_64_14bits_lossless_nef, "raw_modes/NIKON D850_Large_ISO_64_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D850", cam_nikon_d850_large_iso_64_12bits_lossy__type_2__nef, "raw_modes/NIKON D850_Large_ISO_64_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D850", cam_nikon_d850_small_iso_64_12bits_lossless_nef, "raw_modes/NIKON D850_Small_ISO_64_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D850", cam_nikon_d850_large_iso_64_12bits_lossless_nef, "raw_modes/NIKON D850_Large_ISO_64_12bits_Lossless.NEF"); } mod camera_d2h_raw_modes { super::camera_file_check!("Nikon", "D2H", cam_nikon_d2h_iso_200_12bits_lossy__type_1__nef, "raw_modes/NIKON D2H_ISO_200_12bits_Lossy (type 1).NEF"); } mod camera_d7500_raw_modes { super::camera_file_check!("Nikon", "D7500", cam_nikon_d7500_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON D7500_ISO_100_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D7500", cam_nikon_d7500_iso_100_12bits_lossless_nef, "raw_modes/NIKON D7500_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D7500", cam_nikon_d7500_iso_100_14bits_lossless_nef, "raw_modes/NIKON D7500_ISO_100_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D7500", cam_nikon_d7500_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON D7500_ISO_100_12bits_Lossy (type 2).NEF"); } mod camera_coolpix_a_raw_modes { super::camera_file_check!("Nikon", "Coolpix A", cam_coolpix_a_iso_100_14bits_lossy__type_2__nef, "raw_modes/COOLPIX A_ISO_100_14bits_Lossy (type 2).NEF"); } mod camera_d3300_raw_modes { super::camera_file_check!("Nikon", "D3300", cam_nikon_d3300_iso_400_12bits_lossy__type_2__nef, "raw_modes/NIKON D3300_ISO_400_12bits_Lossy (type 2).NEF"); } mod camera_d5000_raw_modes { super::camera_file_check!("Nikon", "D5000", cam_nikon_d5000_iso_400_12bits_lossy__type_2__nef, "raw_modes/NIKON D5000_ISO_400_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D5000", cam_nikon_d5000_iso_200_12bits_lossy__type_2__nef, "raw_modes/NIKON D5000_ISO_200_12bits_Lossy (type 2).NEF"); } mod camera_d7100_raw_modes { super::camera_file_check!("Nikon", "D7100", cam_nikon_d7100_iso_200_14bits_lossy__type_2__nef, "raw_modes/NIKON D7100_ISO_200_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D7100", cam_nikon_d7100_iso_200_12bits_lossless_nef, "raw_modes/NIKON D7100_ISO_200_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D7100", cam_nikon_d7100_iso_200_14bits_lossless_nef, "raw_modes/NIKON D7100_ISO_200_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D7100", cam_nikon_d7100_iso_200_12bits_lossy__type_2__nef, "raw_modes/NIKON D7100_ISO_200_12bits_Lossy (type 2).NEF"); } mod camera_1_s2_raw_modes { super::camera_file_check!("Nikon", "1 S2", cam_nikon_1_s2_iso_720_12bits_lossy__type_2__nef, "raw_modes/NIKON 1 S2_ISO_720_12bits_Lossy (type 2).NEF"); } mod camera_d90_raw_modes { super::camera_file_check!("Nikon", "D90", cam_nikon_d90_iso_250_12bits_lossy__type_2__nef, "raw_modes/NIKON D90_ISO_250_12bits_Lossy (type 2).NEF"); } mod camera_1_aw1_raw_modes { super::camera_file_check!("Nikon", "1 AW1", cam_nikon_1_aw1_iso_160_12bits_lossy__type_2__nef, "raw_modes/NIKON 1 AW1_ISO_160_12bits_Lossy (type 2).NEF"); } mod camera_d5_raw_modes { super::camera_file_check!("Nikon", "D5", cam_nikon_d5_iso_400_14bits_lossy__type_2__nef, "raw_modes/NIKON D5_ISO_400_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D5", cam_nikon_d5_iso_100_14bits_uncompressed_nef, "raw_modes/NIKON D5_ISO_100_14bits_Uncompressed.NEF"); } mod camera_coolpix_a1000_raw_modes { super::camera_file_check!("Nikon", "COOLPIX A1000", cam_coolpix_a1000_iso_280_12bits_uncompressed_nrw, "raw_modes/COOLPIX A1000_ISO_280_12bits_Uncompressed.NRW"); } mod camera_e8400_raw_modes { super::camera_file_check!("Nikon", "E8400", cam_e8400_iso_100_12bits_uncompressed_nef, "raw_modes/E8400_ISO_100_12bits_Uncompressed.NEF"); } mod camera_d100_raw_modes { super::camera_file_check!("Nikon", "D100", cam_nikon_d100_iso_400_12bits_uncompressed_nef, "raw_modes/NIKON D100_ISO_400_12bits_Uncompressed.NEF"); } mod camera_d810_raw_modes { super::camera_file_check!("Nikon", "D810", cam_nikon_d810_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON D810_ISO_100_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D810", cam_nikon_d810_iso_100_12bits_lossless_nef, "raw_modes/NIKON D810_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D810", cam_nikon_d810_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON D810_ISO_100_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D810", cam_nikon_d810_iso_100_12bits_small_nef, "raw_modes/NIKON D810_ISO_100_12bits_Small.NEF"); super::camera_file_check!("Nikon", "D810", cam_nikon_d810_iso_100_14bits_uncompressed_nef, "raw_modes/NIKON D810_ISO_100_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D810", cam_nikon_d810_iso_100_14bits_lossless_nef, "raw_modes/NIKON D810_ISO_100_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D810", cam_nikon_d810_iso_100_12bits_uncompressed__reduced_to_12_bit__nef, "raw_modes/NIKON D810_ISO_100_12bits_Uncompressed (reduced to 12 bit).NEF"); } mod camera_1_j1_raw_modes { super::camera_file_check!("Nikon", "1 J1", cam_nikon_1_j1_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON 1 J1_ISO_100_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "1 J1", cam_nikon_1_j1_iso_200_12bits_lossy__type_2__nef, "raw_modes/NIKON 1 J1_ISO_200_12bits_Lossy (type 2).NEF"); } mod camera_d7000_raw_modes { super::camera_file_check!("Nikon", "D7000", cam_nikon_d7000_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON D7000_ISO_100_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D7000", cam_nikon_d7000_iso_hi_12800_14bits_lossy__type_2__nef, "raw_modes/NIKON D7000_ISO_Hi 12800_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D7000", cam_nikon_d7000_iso_100_14bits_lossless_nef, "raw_modes/NIKON D7000_ISO_100_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D7000", cam_nikon_d7000_iso_100_12bits_lossless_nef, "raw_modes/NIKON D7000_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D7000", cam_nikon_d7000_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON D7000_ISO_100_12bits_Lossy (type 2).NEF"); } mod camera_1_v3_raw_modes { super::camera_file_check!("Nikon", "1 V3", cam_nikon_1_v3_iso_160_12bits_lossy__type_2__nef, "raw_modes/NIKON 1 V3_ISO_160_12bits_Lossy (type 2).NEF"); } mod camera_d5100_raw_modes { super::camera_file_check!("Nikon", "D5100", cam_nikon_d5100_iso_500_14bits_lossless_nef, "raw_modes/NIKON D5100_ISO_500_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D5100", cam_nikon_d5100_iso_500_14bits_lossy__type_2__nef, "raw_modes/NIKON D5100_ISO_500_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D5100", cam_nikon_d5100_iso_500_14bits_uncompressed_nef, "raw_modes/NIKON D5100_ISO_500_14bits_Uncompressed.NEF"); } mod camera_d60_raw_modes { super::camera_file_check!("Nikon", "D60", cam_nikon_d60_iso_100_12bits_lossy__type_1__nef, "raw_modes/NIKON D60_ISO_100_12bits_Lossy (type 1).NEF"); } mod camera_d3200_raw_modes { super::camera_file_check!("Nikon", "D3200", cam_nikon_d3200_iso_800_12bits_lossy__type_2__nef, "raw_modes/NIKON D3200_ISO_800_12bits_Lossy (type 2).NEF"); } mod camera_d750_raw_modes { super::camera_file_check!("Nikon", "D750", cam_nikon_d750_iso_100_14bits_lossless_nef, "raw_modes/NIKON D750_ISO_100_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D750", cam_nikon_d750_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON D750_ISO_100_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D750", cam_nikon_d750_iso_100_12bits_lossless_nef, "raw_modes/NIKON D750_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D750", cam_nikon_d750_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON D750_ISO_100_14bits_Lossy (type 2).NEF"); } mod camera_d80_raw_modes { super::camera_file_check!("Nikon", "D80", cam_nikon_d80_iso_100_12bits_lossy__type_1__nef, "raw_modes/NIKON D80_ISO_100_12bits_Lossy (type 1).NEF"); } mod camera_d3000_raw_modes { super::camera_file_check!("Nikon", "D3000", cam_nikon_d3000_iso_100_12bits_lossy__type_1__nef, "raw_modes/NIKON D3000_ISO_100_12bits_Lossy (type 1).NEF"); } mod camera_d5300_raw_modes { super::camera_file_check!("Nikon", "D5300", cam_nikon_d5300_iso_160_14bits_lossy__type_2__nef, "raw_modes/NIKON D5300_ISO_160_14bits_Lossy (type 2).NEF"); } mod camera_coolpix_p340_raw_modes { super::camera_file_check!("Nikon", "Coolpix P340", cam_coolpix_p340_iso_80_12bits_uncompressed_nrw, "raw_modes/COOLPIX P340_ISO_80_12bits_Uncompressed.NRW"); } mod camera_1_j5_raw_modes { super::camera_file_check!("Nikon", "1 J5", cam_nikon_1_j5_iso_6400_12bits_lossy__type_2__nef, "raw_modes/NIKON 1 J5_ISO_6400_12bits_Lossy (type 2).NEF"); } mod camera_d4s_raw_modes { super::camera_file_check!("Nikon", "D4S", cam_nikon_d4s_iso_360_12bits_small_nef, "raw_modes/NIKON D4S_ISO_360_12bits_Small.NEF"); super::camera_file_check!("Nikon", "D4S", cam_nikon_d4s_iso_360_14bits_lossy__type_2__nef, "raw_modes/NIKON D4S_ISO_360_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D4S", cam_nikon_d4s_iso_280_14bits_uncompressed_nef, "raw_modes/NIKON D4S_ISO_280_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D4S", cam_nikon_d4s_iso_320_14bits_lossless_nef, "raw_modes/NIKON D4S_ISO_320_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D4S", cam_nikon_d4s_iso_280_12bits_lossy__type_2__nef, "raw_modes/NIKON D4S_ISO_280_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D4S", cam_nikon_d4s_iso_320_12bits_uncompressed__reduced_to_12_bit__nef, "raw_modes/NIKON D4S_ISO_320_12bits_Uncompressed (reduced to 12 bit).NEF"); super::camera_file_check!("Nikon", "D4S", cam_nikon_d4s_iso_280_12bits_lossless_nef, "raw_modes/NIKON D4S_ISO_280_12bits_Lossless.NEF"); } mod camera_d7200_raw_modes { super::camera_file_check!("Nikon", "D7200", cam_nikon_d7200_iso_1600_12bits_lossy__type_2__nef, "raw_modes/NIKON D7200_ISO_1600_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D7200", cam_nikon_d7200_iso_1600_14bits_lossless_nef, "raw_modes/NIKON D7200_ISO_1600_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D7200", cam_nikon_d7200_iso_1600_12bits_lossless_nef, "raw_modes/NIKON D7200_ISO_1600_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D7200", cam_nikon_d7200_iso_1600_14bits_lossy__type_2__nef, "raw_modes/NIKON D7200_ISO_1600_14bits_Lossy (type 2).NEF"); } mod camera_d300_raw_modes { super::camera_file_check!("Nikon", "D300", cam_nikon_d300_iso_200_12bits_lossy__type_2__nef, "raw_modes/NIKON D300_ISO_200_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D300", cam_nikon_d300_iso_200_12bits_uncompressed_nef, "raw_modes/NIKON D300_ISO_200_12bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D300", cam_nikon_d300_iso_200_12bits_lossless_nef, "raw_modes/NIKON D300_ISO_200_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D300", cam_nikon_d300_iso_200_14bits_uncompressed_nef, "raw_modes/NIKON D300_ISO_200_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D300", cam_nikon_d300_iso_200_14bits_lossy__type_2__nef, "raw_modes/NIKON D300_ISO_200_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D300", cam_nikon_d300_iso_200_14bits_lossless_nef, "raw_modes/NIKON D300_ISO_200_14bits_Lossless.NEF"); } mod camera_d1_raw_modes { super::camera_file_check!("Nikon", "D1", cam_nikon_d1_iso_200_12bits_uncompressed_nef, "raw_modes/NIKON D1_ISO_200_12bits_Uncompressed.NEF"); } mod camera_d200_raw_modes { super::camera_file_check!("Nikon", "D200", cam_nikon_d200_iso_200_12bits_uncompressed_nef, "raw_modes/NIKON D200_ISO_200_12bits_Uncompressed.NEF"); } mod camera_d1x_raw_modes { super::camera_file_check!("Nikon", "D1X", cam_nikon_d1x_iso_200_12bits_uncompressed_nef, "raw_modes/NIKON D1X_ISO_200_12bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D1X", cam_nikon_d1x_iso_125_12bits_lossy__type_1__nef, "raw_modes/NIKON D1X_ISO_125_12bits_Lossy (type 1).NEF"); } mod camera_d70_raw_modes { super::camera_file_check!("Nikon", "D70", cam_nikon_d70_iso_200_12bits_lossy__type_1__nef, "raw_modes/NIKON D70_ISO_200_12bits_Lossy (type 1).NEF"); } mod camera_coolpix_p330_raw_modes { super::camera_file_check!("Nikon", "Coolpix P330", cam_coolpix_p330_iso_80_12bits_uncompressed_nrw, "raw_modes/COOLPIX P330_ISO_80_12bits_Uncompressed.NRW"); } mod camera_1_j2_raw_modes { super::camera_file_check!("Nikon", "1 J2", cam_nikon_1_j2_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON 1 J2_ISO_100_12bits_Lossy (type 2).NEF"); } mod camera_d5200_raw_modes { super::camera_file_check!("Nikon", "D5200", cam_nikon_d5200_iso_280_14bits_lossy__type_2__nef, "raw_modes/NIKON D5200_ISO_280_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D5200", cam_nikon_d5200_iso_200_14bits_lossy__type_2__nef, "raw_modes/NIKON D5200_ISO_200_14bits_Lossy (type 2).NEF"); } mod camera_d3s_raw_modes { super::camera_file_check!("Nikon", "D3S", cam_nikon_d3s_iso_200_12bits_lossless_nef, "raw_modes/NIKON D3S_ISO_200_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D3S", cam_nikon_d3s_iso_200_12bits_uncompressed_nef, "raw_modes/NIKON D3S_ISO_200_12bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D3S", cam_nikon_d3s_iso_200_14bits_uncompressed_nef, "raw_modes/NIKON D3S_ISO_200_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D3S", cam_nikon_d3s_iso_200_14bits_lossless_nef, "raw_modes/NIKON D3S_ISO_200_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D3S", cam_nikon_d3s_iso_200_12bits_lossy__type_2__nef, "raw_modes/NIKON D3S_ISO_200_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D3S", cam_nikon_d3s_iso_200_14bits_lossy__type_2__nef, "raw_modes/NIKON D3S_ISO_200_14bits_Lossy (type 2).NEF"); } mod camera_df_raw_modes { super::camera_file_check!("Nikon", "Df", cam_nikon_df_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON Df_ISO_100_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "Df", cam_nikon_df_iso_100_12bits_uncompressed_nef, "raw_modes/NIKON Df_ISO_100_12bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "Df", cam_nikon_df_iso_100_14bits_uncompressed_nef, "raw_modes/NIKON Df_ISO_100_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "Df", cam_nikon_df_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON Df_ISO_100_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "Df", cam_nikon_df_iso_100_12bits_lossless_nef, "raw_modes/NIKON Df_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "Df", cam_nikon_df_iso_100_14bits_lossless_nef, "raw_modes/NIKON Df_ISO_100_14bits_Lossless.NEF"); } mod camera_d800_raw_modes { super::camera_file_check!("Nikon", "D800", cam_nikon_d800_iso_50_14bits_uncompressed_nef, "raw_modes/NIKON D800_ISO_50_14bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D800", cam_nikon_d800_iso_50_12bits_lossy__type_2__nef, "raw_modes/NIKON D800_ISO_50_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "D800", cam_nikon_d800_iso_50_12bits_uncompressed_nef, "raw_modes/NIKON D800_ISO_50_12bits_Uncompressed.NEF"); super::camera_file_check!("Nikon", "D800", cam_nikon_d800_iso_50_12bits_lossless_nef, "raw_modes/NIKON D800_ISO_50_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D800", cam_nikon_d800_iso_50_14bits_lossless_nef, "raw_modes/NIKON D800_ISO_50_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "D800", cam_nikon_d800_iso_50_14bits_lossy__type_2__nef, "raw_modes/NIKON D800_ISO_50_14bits_Lossy (type 2).NEF"); } mod camera_d3100_raw_modes { super::camera_file_check!("Nikon", "D3100", cam_nikon_d3100_iso_220_12bits_lossy__type_2__nef, "raw_modes/NIKON D3100_ISO_220_12bits_Lossy (type 2).NEF"); } mod camera_z_5_raw_modes { super::camera_file_check!("Nikon", "Z 5", cam_nikon_z_5_large_iso_400_12bits_lossless_nef, "raw_modes/NIKON Z 5_Large_ISO_400_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "Z 5", cam_nikon_z_5_large_iso_400_14bits_lossless_nef, "raw_modes/NIKON Z 5_Large_ISO_400_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "Z 5", cam_nikon_z_5_large_iso_360_12bits_lossy__type_2__nef, "raw_modes/NIKON Z 5_Large_ISO_360_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "Z 5", cam_nikon_z_5_large_iso_360_14bits_lossy__type_2__nef, "raw_modes/NIKON Z 5_Large_ISO_360_14bits_Lossy (type 2).NEF"); } mod camera_z_5_ii_raw_modes { super::camera_file_check!("Nikon", "Z 5 II", cam_z5_ii_lossless_compression_1_1_nef, "raw_modes/Z5_II_Lossless_compression_1-1.NEF"); super::camera_file_check!("Nikon", "Z 5 II", cam_z5_ii_lossless_compression_fx_1_nef, "raw_modes/Z5_II_Lossless_compression_FX_1.NEF"); super::camera_file_check!("Nikon", "Z 5 II", cam_z5_ii_lossless_compression_dx_nef, "raw_modes/Z5_II_Lossless_compression_DX.NEF"); } mod camera_nikon_z_6_2_raw_modes { super::camera_file_check!("Nikon", "NIKON Z 6_2", cam_nikon_z_6_2_large_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON Z 6_2_Large_ISO_100_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "NIKON Z 6_2", cam_nikon_z_6_2_large_iso_100_12bits_uncompressed__reduced_to_12_bit__nef, "raw_modes/NIKON Z 6_2_Large_ISO_100_12bits_Uncompressed (reduced to 12 bit).NEF"); super::camera_file_check!("Nikon", "NIKON Z 6_2", cam_nikon_z_6_2_large_iso_100_12bits_lossless_nef, "raw_modes/NIKON Z 6_2_Large_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "NIKON Z 6_2", cam_nikon_z_6_2_large_iso_100_14bits_lossless_nef, "raw_modes/NIKON Z 6_2_Large_ISO_100_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "NIKON Z 6_2", cam_nikon_z_6_2_large_iso_100_14bits_packed_14_bits_nef, "raw_modes/NIKON Z 6_2_Large_ISO_100_14bits_Packed 14 bits.NEF"); super::camera_file_check!("Nikon", "NIKON Z 6_2", cam_nikon_z_6_2_large_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON Z 6_2_Large_ISO_100_14bits_Lossy (type 2).NEF"); } mod camera_nikon_z_6_3_raw_modes { super::camera_file_check!("Nikon", "NIKON Z 6_3", cam_nikon_z6_3_lossless_compressed_dx_nef, "raw_modes/Nikon_Z6_3_Lossless_compressed_DX.NEF"); super::camera_file_check!("Nikon", "NIKON Z 6_3", cam_nikon_z6_3_lossless_compressed_16_9_nef, "raw_modes/Nikon_Z6_3_Lossless_compressed_16_9.NEF"); super::camera_file_check!("Nikon", "NIKON Z 6_3", cam_nikon_z6_3_lossless_compressed_1_1_nef, "raw_modes/Nikon_Z6_3_Lossless_compressed_1_1.NEF"); super::camera_file_check!("Nikon", "NIKON Z 6_3", cam_nikon_z6_3_lossless_compressed_fx_nef, "raw_modes/Nikon_Z6_3_Lossless_compressed_FX.NEF"); } mod camera_nikon_z_7_2_raw_modes { super::camera_file_check!("Nikon", "NIKON Z 7_2", cam_nikon_z_7_2_large_iso_100_12bits_uncompressed__reduced_to_12_bit__nef, "raw_modes/NIKON Z 7_2_Large_ISO_100_12bits_Uncompressed (reduced to 12 bit).NEF"); super::camera_file_check!("Nikon", "NIKON Z 7_2", cam_nikon_z_7_2_large_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON Z 7_2_Large_ISO_100_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "NIKON Z 7_2", cam_nikon_z_7_2_large_iso_100_14bits_packed_14_bits_nef, "raw_modes/NIKON Z 7_2_Large_ISO_100_14bits_Packed 14 bits.NEF"); super::camera_file_check!("Nikon", "NIKON Z 7_2", cam_nikon_z_7_2_large_iso_100_14bits_lossless_nef, "raw_modes/NIKON Z 7_2_Large_ISO_100_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "NIKON Z 7_2", cam_nikon_z_7_2_large_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON Z 7_2_Large_ISO_100_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "NIKON Z 7_2", cam_nikon_z_7_2_large_iso_100_12bits_lossless_nef, "raw_modes/NIKON Z 7_2_Large_ISO_100_12bits_Lossless.NEF"); } mod camera_z_30_raw_modes { super::camera_file_check!("Nikon", "Z 30", cam_nikon_z30_lossless_12bit_nef, "raw_modes/Nikon_Z30_Lossless_12bit.NEF"); super::camera_file_check!("Nikon", "Z 30", cam_nikon_z30_lossless_14bit_nef, "raw_modes/Nikon_Z30_Lossless_14bit.NEF"); } mod camera_z_50_raw_modes { super::camera_file_check!("Nikon", "Z 50", cam_nikon_z_50_large_iso_250_14bits_lossless_nef, "raw_modes/NIKON Z 50_Large_ISO_250_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "Z 50", cam_nikon_z_50_large_iso_250_12bits_lossless_nef, "raw_modes/NIKON Z 50_Large_ISO_250_12bits_Lossless.NEF"); } mod camera_z_50_ii_raw_modes { super::camera_file_check!("Nikon", "Z 50 II", cam_z50ii_dx_lossless_nef, "raw_modes/Z50II_DX_lossless.NEF"); super::camera_file_check!("Nikon", "Z 50 II", cam_z50ii_1x1_lossless_nef, "raw_modes/Z50II_1x1_lossless.NEF"); super::camera_file_check!("Nikon", "Z 50 II", cam_z50ii_16x9_lossless_nef, "raw_modes/Z50II_16x9_lossless.NEF"); } mod camera_z_6_raw_modes { super::camera_file_check!("Nikon", "Z 6", cam_nikon_z_6_large_iso_100_12bits_lossy__type_2__nef, "raw_modes/NIKON Z 6_Large_ISO_100_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "Z 6", cam_nikon_z_6_small_iso_100_12bits_lossless_nef, "raw_modes/NIKON Z 6_Small_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "Z 6", cam_nikon_z_6_large_iso_100_14bits_packed_14_bits_nef, "raw_modes/NIKON Z 6_Large_ISO_100_14bits_Packed 14 bits.NEF"); super::camera_file_check!("Nikon", "Z 6", cam_nikon_z_6_large_iso_100_14bits_lossless_nef, "raw_modes/NIKON Z 6_Large_ISO_100_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "Z 6", cam_nikon_z_6_large_iso_100_12bits_uncompressed__reduced_to_12_bit__nef, "raw_modes/NIKON Z 6_Large_ISO_100_12bits_Uncompressed (reduced to 12 bit).NEF"); super::camera_file_check!("Nikon", "Z 6", cam_nikon_z_6_large_iso_100_14bits_lossy__type_2__nef, "raw_modes/NIKON Z 6_Large_ISO_100_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "Z 6", cam_nikon_z_6_medium_iso_100_12bits_lossless_nef, "raw_modes/NIKON Z 6_Medium_ISO_100_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "Z 6", cam_nikon_z_6_large_iso_100_12bits_lossless_nef, "raw_modes/NIKON Z 6_Large_ISO_100_12bits_Lossless.NEF"); } mod camera_nikon_z_f_raw_modes { super::camera_file_check!("Nikon", "NIKON Z f", cam_nikon_z_f_iso_160_14bits_lossless_nrw, "raw_modes/NIKON Z f_ISO_160_14bits_Lossless.NRW"); } mod camera_nikon_z_fc_raw_modes { super::camera_file_check!("Nikon", "NIKON Z fc", cam_nikon_z_fc_large_iso_200_14bits_lossless_nef, "raw_modes/NIKON Z fc_Large_ISO_200_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "NIKON Z fc", cam_nikon_z_fc_large_iso_400_12bits_lossless_nef, "raw_modes/NIKON Z fc_Large_ISO_400_12bits_Lossless.NEF"); } mod camera_z_7_raw_modes { super::camera_file_check!("Nikon", "Z 7", cam_nikon_z_7_large_iso_64_12bits_lossy__type_2__nef, "raw_modes/NIKON Z 7_Large_ISO_64_12bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "Z 7", cam_nikon_z_7_large_iso_64_14bits_lossless_nef, "raw_modes/NIKON Z 7_Large_ISO_64_14bits_Lossless.NEF"); super::camera_file_check!("Nikon", "Z 7", cam_nikon_z_7_small_iso_64_12bits_lossless_nef, "raw_modes/NIKON Z 7_Small_ISO_64_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "Z 7", cam_nikon_z_7_large_iso_64_12bits_lossless_nef, "raw_modes/NIKON Z 7_Large_ISO_64_12bits_Lossless.NEF"); super::camera_file_check!("Nikon", "Z 7", cam_nikon_z_7_large_iso_64_14bits_packed_14_bits_nef, "raw_modes/NIKON Z 7_Large_ISO_64_14bits_Packed 14 bits.NEF"); super::camera_file_check!("Nikon", "Z 7", cam_nikon_z_7_large_iso_64_14bits_lossy__type_2__nef, "raw_modes/NIKON Z 7_Large_ISO_64_14bits_Lossy (type 2).NEF"); super::camera_file_check!("Nikon", "Z 7", cam_nikon_z_7_large_iso_64_12bits_uncompressed__reduced_to_12_bit__nef, "raw_modes/NIKON Z 7_Large_ISO_64_12bits_Uncompressed (reduced to 12 bit).NEF"); super::camera_file_check!("Nikon", "Z 7", cam_nikon_z_7_medium_iso_64_12bits_lossless_nef, "raw_modes/NIKON Z 7_Medium_ISO_64_12bits_Lossless.NEF"); } mod camera_nikon_z_9_raw_modes { super::camera_file_check!("Nikon", "NIKON Z 9", cam_nikon_z_9_large_iso_64_14bits_lossless_nef, "raw_modes/NIKON Z 9_Large_ISO_64_14bits_Lossless.NEF"); } mod camera_nikon_z_8_raw_modes { super::camera_file_check!("Nikon", "NIKON Z 8", cam_nikon_z8_raw_14_bit_lossless_compression_nef, "raw_modes/Nikon_Z8_raw_14_bit_lossless_compression.NEF"); } mod camera_dsc_f828_raw_modes { super::camera_file_check!("Sony", "DSC-F828", cam_dsc_f828_iso_64_14_14_14bits_uncompressed_srf, "raw_modes/DSC-F828_ISO_64_14 14 14bits_Uncompressed.SRF"); } mod camera_dsc_hx95_raw_modes { super::camera_file_check!("Sony", "DSC-HX95", cam_dsc_hx95_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/DSC-HX95_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_hx99_raw_modes { super::camera_file_check!("Sony", "DSC-HX99", cam_dsc_hx99_iso_80_12bits_sony_arw_compressed_arw, "raw_modes/DSC-HX99_ISO_80_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_r1_raw_modes { super::camera_file_check!("Sony", "DSC-R1", cam_dsc_r1_iso_160_14bits_uncompressed_sr2, "raw_modes/DSC-R1_ISO_160_14bits_Uncompressed.SR2"); } mod camera_dsc_rx0m2_raw_modes { super::camera_file_check!("Sony", "DSC-RX0M2", cam_dsc_rx0m2_iso_400_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX0M2_ISO_400_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx0_raw_modes { super::camera_file_check!("Sony", "DSC-RX0", cam_dsc_rx0_iso_125_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX0_ISO_125_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx100m2_raw_modes { super::camera_file_check!("Sony", "DSC-RX100M2", cam_dsc_rx100m2_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX100M2_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx100m3_raw_modes { super::camera_file_check!("Sony", "DSC-RX100M3", cam_dsc_rx100m3_iso_125_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX100M3_ISO_125_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx100m4_raw_modes { super::camera_file_check!("Sony", "DSC-RX100M4", cam_dsc_rx100m4_iso_125_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX100M4_ISO_125_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx100m5a_raw_modes { super::camera_file_check!("Sony", "DSC-RX100M5A", cam_dsc_rx100m5a_iso_125_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX100M5A_ISO_125_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx100m5_raw_modes { super::camera_file_check!("Sony", "DSC-RX100M5", cam_dsc_rx100m5_iso_125_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX100M5_ISO_125_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx100m6_raw_modes { super::camera_file_check!("Sony", "DSC-RX100M6", cam_dsc_rx100m6_iso_125_12bits_compressed_raw_arw, "raw_modes/DSC-RX100M6_ISO_125_12bits_Compressed RAW.ARW"); } mod camera_dsc_rx100m7_raw_modes { super::camera_file_check!("Sony", "DSC-RX100M7", cam_dsc_rx100m7_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX100M7_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx100_raw_modes { super::camera_file_check!("Sony", "DSC-RX100", cam_dsc_rx100_iso_640_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX100_ISO_640_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx10m2_raw_modes { super::camera_file_check!("Sony", "DSC-RX10M2", cam_dsc_rx10m2_iso_1250_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX10M2_ISO_1250_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx10m3_raw_modes { super::camera_file_check!("Sony", "DSC-RX10M3", cam_dsc_rx10m3_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX10M3_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx10m4_raw_modes { super::camera_file_check!("Sony", "DSC-RX10M4", cam_dsc_rx10m4_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX10M4_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx10_raw_modes { super::camera_file_check!("Sony", "DSC-RX10", cam_dsc_rx10_iso_320_12bits_sony_arw_compressed_arw, "raw_modes/DSC-RX10_ISO_320_12bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx1_raw_modes { super::camera_file_check!("Sony", "DSC-RX1", cam_dsc_rx1_iso_100_14bits_sony_arw_compressed_arw, "raw_modes/DSC-RX1_ISO_100_14bits_Sony ARW Compressed.ARW"); } mod camera_dsc_rx1rm2_raw_modes { super::camera_file_check!("Sony", "DSC-RX1RM2", cam_dsc_rx1rm2_iso_100_14bits_compressed_raw_arw, "raw_modes/DSC-RX1RM2_ISO_100_14bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "DSC-RX1RM2", cam_dsc_rx1rm2_iso_100_14bits_uncompressed_raw_arw, "raw_modes/DSC-RX1RM2_ISO_100_14bits_Uncompressed RAW.ARW"); } mod camera_dsc_rx1r_raw_modes { super::camera_file_check!("Sony", "DSC-RX1R", cam_dsc_rx1r_iso_6400_14bits_sony_arw_compressed_arw, "raw_modes/DSC-RX1R_ISO_6400_14bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a100_raw_modes { super::camera_file_check!("Sony", "DSLR-A100", cam_dslr_a100_iso_100_arw, "raw_modes/DSLR-A100_ISO_100.ARW"); } mod camera_dslr_a200_raw_modes { super::camera_file_check!("Sony", "DSLR-A200", cam_dslr_a200_iso_800_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A200_ISO_800_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a230_raw_modes { super::camera_file_check!("Sony", "DSLR-A230", cam_dslr_a230_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A230_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a290_raw_modes { super::camera_file_check!("Sony", "DSLR-A290", cam_dslr_a290_iso_400_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A290_ISO_400_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a300_raw_modes { super::camera_file_check!("Sony", "DSLR-A300", cam_dslr_a300_iso_400_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A300_ISO_400_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a330_raw_modes { super::camera_file_check!("Sony", "DSLR-A330", cam_dslr_a330_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A330_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a350_raw_modes { super::camera_file_check!("Sony", "DSLR-A350", cam_dslr_a350_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A350_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a380_raw_modes { super::camera_file_check!("Sony", "DSLR-A380", cam_dslr_a380_iso_400_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A380_ISO_400_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a390_raw_modes { super::camera_file_check!("Sony", "DSLR-A390", cam_dslr_a390_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A390_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a450_raw_modes { super::camera_file_check!("Sony", "DSLR-A450", cam_dslr_a450_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A450_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a500_raw_modes { super::camera_file_check!("Sony", "DSLR-A500", cam_dslr_a500_iso_500_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A500_ISO_500_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a550_raw_modes { super::camera_file_check!("Sony", "DSLR-A550", cam_dslr_a550_iso_3200_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A550_ISO_3200_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a560_raw_modes { super::camera_file_check!("Sony", "DSLR-A560", cam_dslr_a560_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A560_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a580_raw_modes { super::camera_file_check!("Sony", "DSLR-A580", cam_dslr_a580_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A580_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a700_raw_modes { super::camera_file_check!("Sony", "DSLR-A700", cam_dslr_a700_iso_200_8bits_sony_arw_compressed_arw, "raw_modes/DSLR-A700_ISO_200_8bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a850_raw_modes { super::camera_file_check!("Sony", "DSLR-A850", cam_dslr_a850_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A850_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_dslr_a900_raw_modes { super::camera_file_check!("Sony", "DSLR-A900", cam_dslr_a900_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/DSLR-A900_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_ilca_68_raw_modes { super::camera_file_check!("Sony", "ILCA-68", cam_ilca_68_iso_250_12bits_sony_arw_compressed_arw, "raw_modes/ILCA-68_ISO_250_12bits_Sony ARW Compressed.ARW"); } mod camera_ilca_77m2_raw_modes { super::camera_file_check!("Sony", "ILCA-77M2", cam_ilca_77m2_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/ILCA-77M2_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_ilca_99m2_raw_modes { super::camera_file_check!("Sony", "ILCA-99M2", cam_ilca_99m2_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/ILCA-99M2_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_ilme_fx30_raw_modes { super::camera_file_check!("Sony", "ILME-FX30", cam_ilme_fx30_iso_125_arw, "raw_modes/ILME-FX30_ISO_125.ARW"); } mod camera_ilme_fx3_raw_modes { super::camera_file_check!("Sony", "ILME-FX3", cam_ilme_fx3_iso_20000_14bits_arw, "raw_modes/ILME-FX3_ISO_20000_14bits.ARW"); } mod camera_ilce_1_raw_modes { super::camera_file_check!("Sony", "ILCE-1", cam_ilce_1_iso_500_14bits_uncompressed_raw_arw, "raw_modes/ILCE-1_ISO_500_14bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-1", cam_ilce_1_iso_500_14bits_lossless_compressed_raw_arw, "raw_modes/ILCE-1_ISO_500_14bits_Lossless Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-1", cam_ilce_1_iso_500_14bits_compressed_raw_arw, "raw_modes/ILCE-1_ISO_500_14bits_Compressed RAW.ARW"); } mod camera_ilce_3000_raw_modes { super::camera_file_check!("Sony", "ILCE-3000", cam_ilce_3000_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/ILCE-3000_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_ilce_3500_raw_modes { super::camera_file_check!("Sony", "ILCE-3500", cam_ilce_3500_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/ILCE-3500_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_ilce_5000_raw_modes { super::camera_file_check!("Sony", "ILCE-5000", cam_ilce_5000_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/ILCE-5000_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_ilce_5100_raw_modes { super::camera_file_check!("Sony", "ILCE-5100", cam_ilce_5100_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/ILCE-5100_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_ilce_6000_raw_modes { super::camera_file_check!("Sony", "ILCE-6000", cam_ilce_6000_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/ILCE-6000_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_ilce_6001_raw_modes { super::camera_file_check!("Sony", "ILCE-6001", cam_ilce_6001_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/ILCE-6001_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_ilce_6100_raw_modes { super::camera_file_check!("Sony", "ILCE-6100", cam_ilce_6100_iso_100_14bits_sony_arw_compressed_arw, "raw_modes/ILCE-6100_ISO_100_14bits_Sony ARW Compressed.ARW"); } mod camera_ilce_6300_raw_modes { super::camera_file_check!("Sony", "ILCE-6300", cam_ilce_6300_iso_100_14bits_sony_arw_compressed_arw, "raw_modes/ILCE-6300_ISO_100_14bits_Sony ARW Compressed.ARW"); super::camera_file_check!("Sony", "ILCE-6300", cam_ilce_6300_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/ILCE-6300_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_ilce_6400_raw_modes { super::camera_file_check!("Sony", "ILCE-6400", cam_ilce_6400_iso_250_12bits_compressed_raw_arw, "raw_modes/ILCE-6400_ISO_250_12bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-6400", cam_ilce_6400_iso_160_14bits_compressed_raw_arw, "raw_modes/ILCE-6400_ISO_160_14bits_Compressed RAW.ARW"); } mod camera_ilce_6500_raw_modes { super::camera_file_check!("Sony", "ILCE-6500", cam_ilce_6500_iso_100_14bits_compressed_raw_arw, "raw_modes/ILCE-6500_ISO_100_14bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-6500", cam_ilce_6500_iso_100_12bits_compressed_raw_arw, "raw_modes/ILCE-6500_ISO_100_12bits_Compressed RAW.ARW"); } mod camera_ilce_6600_raw_modes { super::camera_file_check!("Sony", "ILCE-6600", cam_ilce_6600_iso_100_14bits_sony_arw_compressed_arw, "raw_modes/ILCE-6600_ISO_100_14bits_Sony ARW Compressed.ARW"); } mod camera_ilce_6700_raw_modes { super::camera_file_check!("Sony", "ILCE-6700", cam_ilce_6700_iso_100_14bits_compressed_arw, "raw_modes/ILCE-6700_ISO_100_14bits_Compressed.ARW"); super::camera_file_check!("Sony", "ILCE-6700", cam_ilce_6700_iso_100_14bits_lossless_compressed_arw, "raw_modes/ILCE-6700_ISO_100_14bits_Lossless_Compressed.ARW"); super::camera_file_check!("Sony", "ILCE-6700", cam_ilce_6700_iso_100_12bits_compressed_arw, "raw_modes/ILCE-6700_ISO_100_12bits_Compressed.ARW"); } mod camera_ilce_7cr_raw_modes { super::camera_file_check!("Sony", "ILCE-7CR", cam_ilce_7cr_apsc_s_iso_125_15bits_jpeg_arw, "raw_modes/ILCE-7CR_APSC_S_ISO_125_15bits_JPEG.ARW"); super::camera_file_check!("Sony", "ILCE-7CR", cam_ilce_7cr_fullframe_m_iso_125_15bits_jpeg_arw, "raw_modes/ILCE-7CR_Fullframe_M_ISO_125_15bits_JPEG.ARW"); super::camera_file_check!("Sony", "ILCE-7CR", cam_ilce_7cr_fullframe_iso_125_14bits_uncompressed_arw, "raw_modes/ILCE-7CR_Fullframe_ISO_125_14bits_Uncompressed.ARW"); super::camera_file_check!("Sony", "ILCE-7CR", cam_ilce_7cr_apsc_iso_125_14bits_sony_arw_compressed_arw, "raw_modes/ILCE-7CR_APSC_ISO_125_14bits_Sony ARW Compressed.ARW"); super::camera_file_check!("Sony", "ILCE-7CR", cam_ilce_7cr_apsc_iso_125_14bits_uncompressed_arw, "raw_modes/ILCE-7CR_APSC_ISO_125_14bits_Uncompressed.ARW"); super::camera_file_check!("Sony", "ILCE-7CR", cam_ilce_7cr_fullframe_l_iso_125_14bits_jpeg_arw, "raw_modes/ILCE-7CR_Fullframe_L_ISO_125_14bits_JPEG.ARW"); super::camera_file_check!("Sony", "ILCE-7CR", cam_ilce_7cr_apsc_m_iso_125_14bits_jpeg_arw, "raw_modes/ILCE-7CR_APSC_M_ISO_125_14bits_JPEG.ARW"); super::camera_file_check!("Sony", "ILCE-7CR", cam_ilce_7cr_fullframe_iso_125_14bits_sony_arw_compressed_arw, "raw_modes/ILCE-7CR_Fullframe_ISO_125_14bits_Sony ARW Compressed.ARW"); super::camera_file_check!("Sony", "ILCE-7CR", cam_ilce_7cr_fullframe_s_iso_125_15bits_jpeg_arw, "raw_modes/ILCE-7CR_Fullframe_S_ISO_125_15bits_JPEG.ARW"); } mod camera_ilce_7c_raw_modes { super::camera_file_check!("Sony", "ILCE-7C", cam_ilce_7c_iso_12800_14bits_uncompressed_raw_arw, "raw_modes/ILCE-7C_ISO_12800_14bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7C", cam_ilce_7c_iso_2000_14bits_compressed_raw_arw, "raw_modes/ILCE-7C_ISO_2000_14bits_Compressed RAW.ARW"); } mod camera_ilce_7cm2_raw_modes { super::camera_file_check!("Sony", "ILCE-7CM2", cam_ilce_7cm2_iso_100_14bits_jpeg_arw, "raw_modes/ILCE-7CM2_ISO_100_14bits_JPEG.ARW"); super::camera_file_check!("Sony", "ILCE-7CM2", cam_ilce_7cm2_iso_100_14bits_uncompressed_arw, "raw_modes/ILCE-7CM2_ISO_100_14bits_Uncompressed.ARW"); super::camera_file_check!("Sony", "ILCE-7CM2", cam_ilce_7cm2_iso_100_14bits_sony_arw_compressed_arw, "raw_modes/ILCE-7CM2_ISO_100_14bits_Sony ARW Compressed.ARW"); super::camera_file_check!("Sony", "ILCE-7CM2", cam_ilce_7cm2_iso_100_14bits_uncompressed_raw_arw, "raw_modes/ILCE-7CM2_ISO_100_14bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7CM2", cam_ilce_7cm2_iso_100_14bits_compressed_raw_arw, "raw_modes/ILCE-7CM2_ISO_100_14bits_Compressed RAW.ARW"); } mod camera_ilce_7m2_raw_modes { super::camera_file_check!("Sony", "ILCE-7M2", cam_ilce_7m2_iso_100_14bits_uncompressed_arw, "raw_modes/ILCE-7M2_ISO_100_14bits_Uncompressed.ARW"); super::camera_file_check!("Sony", "ILCE-7M2", cam_ilce_7m2_iso_100_14bits_sony_arw_compressed_arw, "raw_modes/ILCE-7M2_ISO_100_14bits_Sony ARW Compressed.ARW"); super::camera_file_check!("Sony", "ILCE-7M2", cam_ilce_7m2_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/ILCE-7M2_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_ilce_7m3_raw_modes { super::camera_file_check!("Sony", "ILCE-7M3", cam_ilce_7m3_iso_400_12bits_compressed_raw_arw, "raw_modes/ILCE-7M3_ISO_400_12bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7M3", cam_ilce_7m3_iso_400_14bits_uncompressed_raw_arw, "raw_modes/ILCE-7M3_ISO_400_14bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7M3", cam_ilce_7m3_iso_400_14bits_compressed_raw_arw, "raw_modes/ILCE-7M3_ISO_400_14bits_Compressed RAW.ARW"); } mod camera_ilce_7m4_raw_modes { super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_iso_100_14bits_compressed_raw_arw, "raw_modes/ILCE-7M4_ISO_100_14bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_iso_100_12bits_compressed_raw_arw, "raw_modes/ILCE-7M4_ISO_100_12bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_iso_100_14bits_lossless_compressed_raw_arw, "raw_modes/ILCE-7M4_ISO_100_14bits_Lossless Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_iso_100_14bits_uncompressed_raw_arw, "raw_modes/ILCE-7M4_ISO_100_14bits_Uncompressed RAW.ARW"); } mod camera_ilce_7m4_resolutions { super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_dsc06680_aps_c_lossless_small_arw, "resolutions/ILCE-7M4_DSC06680_APS-C-LossLess-Small.ARW"); super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_dsc06674_fullframe_lossless_compressed_large_arw, "resolutions/ILCE-7M4_DSC06674_FullFrame-LossLess-Compressed-Large.ARW"); super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_dsc06681_aps_c_raw_compressed_arw, "resolutions/ILCE-7M4_DSC06681_APS-C-Raw-Compressed.ARW"); super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_dsc06678_aps_c_raw_uncompressed_arw, "resolutions/ILCE-7M4_DSC06678_APS-C-Raw-Uncompressed.ARW"); super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_dsc06677_fullframe_raw_compressed_arw, "resolutions/ILCE-7M4_DSC06677_FullFrame-Raw-Compressed.ARW"); super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_dsc06679_aps_c_lossless_medium_arw, "resolutions/ILCE-7M4_DSC06679_APS-C-LossLess-Medium.ARW"); super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_dsc06675_fullframe_lossless_compressed_medium_arw, "resolutions/ILCE-7M4_DSC06675_FullFrame-LossLess-Compressed-Medium.ARW"); super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_dsc06676_fullframe_lossless_compressed_small_arw, "resolutions/ILCE-7M4_DSC06676_FullFrame-LossLess-Compressed-Small.ARW"); super::camera_file_check!("Sony", "ILCE-7M4", cam_ilce_7m4_dsc06673_fullframe_raw_uncompressed_arw, "resolutions/ILCE-7M4_DSC06673_FullFrame-Raw-Uncompressed.ARW"); } mod camera_ilce_7_raw_modes { super::camera_file_check!("Sony", "ILCE-7", cam_ilce_7_iso_200_14bits_sony_arw_compressed_arw, "raw_modes/ILCE-7_ISO_200_14bits_Sony ARW Compressed.ARW"); } mod camera_ilce_7rm2_raw_modes { super::camera_file_check!("Sony", "ILCE-7RM2", cam_ilce_7rm2_iso_100_12bits_compressed_raw_arw, "raw_modes/ILCE-7RM2_ISO_100_12bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7RM2", cam_ilce_7rm2_iso_100_12bits_uncompressed_raw_arw, "raw_modes/ILCE-7RM2_ISO_100_12bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7RM2", cam_ilce_7rm2_iso_100_14bits_uncompressed_raw_arw, "raw_modes/ILCE-7RM2_ISO_100_14bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7RM2", cam_ilce_7rm2_iso_100_14bits_compressed_raw_arw, "raw_modes/ILCE-7RM2_ISO_100_14bits_Compressed RAW.ARW"); } mod camera_ilce_7rm3a_raw_modes { super::camera_file_check!("Sony", "ILCE-7RM3A", cam_ilce_7rm3a_iso_200_14bits_uncompressed_raw_arw, "raw_modes/ILCE-7RM3A_ISO_200_14bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7RM3A", cam_ilce_7rm3a_iso_500_14bits_compressed_raw_arw, "raw_modes/ILCE-7RM3A_ISO_500_14bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7RM3A", cam_ilce_7rm3a_iso_250_14bits_compressed_raw_arw, "raw_modes/ILCE-7RM3A_ISO_250_14bits_Compressed RAW.ARW"); } mod camera_ilce_7rm3_raw_modes {} mod camera_ilce_7rm4a_raw_modes { super::camera_file_check!("Sony", "ILCE-7RM4A", cam_ilce_7rm4a_iso_250_14bits_uncompressed_raw_arw, "raw_modes/ILCE-7RM4A_ISO_250_14bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7RM4A", cam_ilce_7rm4a_iso_125_14bits_compressed_raw_arw, "raw_modes/ILCE-7RM4A_ISO_125_14bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7RM4A", cam_ilce_7rm4a_iso_1250_12bits_uncompressed_raw_arw, "raw_modes/ILCE-7RM4A_ISO_1250_12bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7RM4A", cam_ilce_7rm4a_iso_160_12bits_compressed_raw_arw, "raw_modes/ILCE-7RM4A_ISO_160_12bits_Compressed RAW.ARW"); } mod camera_ilce_7rm4_raw_modes { super::camera_file_check!("Sony", "ILCE-7RM4", cam_ilce_7rm4_iso_50_14bits_uncompressed_raw_arw, "raw_modes/ILCE-7RM4_ISO_50_14bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7RM4", cam_ilce_7rm4_iso_50_12bits_uncompressed_raw_arw, "raw_modes/ILCE-7RM4_ISO_50_12bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7RM4", cam_ilce_7rm4_iso_50_14bits_compressed_raw_arw, "raw_modes/ILCE-7RM4_ISO_50_14bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7RM4", cam_ilce_7rm4_iso_50_12bits_compressed_raw_arw, "raw_modes/ILCE-7RM4_ISO_50_12bits_Compressed RAW.ARW"); } mod camera_ilce_7rm5_raw_modes { super::camera_file_check!("Sony", "ILCE-7RM5", cam_sony_7rm5_lossless_l_ljpeg_arw, "raw_modes/Sony_7RM5_Lossless_L_LJPEG.ARW"); super::camera_file_check!("Sony", "ILCE-7RM5", cam_sony_7rm5_uncompressed_arw, "raw_modes/Sony_7RM5_Uncompressed.ARW"); super::camera_file_check!("Sony", "ILCE-7RM5", cam_sony_7rm5_lossy_arw, "raw_modes/Sony_7RM5_Lossy.ARW"); super::camera_file_check!("Sony", "ILCE-7RM5", cam_sony_7rm5_s35_lossy_arw, "raw_modes/Sony_7RM5_S35_Lossy.ARW"); super::camera_file_check!("Sony", "ILCE-7RM5", cam_sony_7rm5_s35_uncompressed_arw, "raw_modes/Sony_7RM5_S35_Uncompressed.ARW"); } mod camera_ilce_7rm5_yuv { super::camera_file_check!("Sony", "ILCE-7RM5", cam_sony_7rm5_lossless_s_ljpeg_arw, "yuv/Sony_7RM5_Lossless_S_LJPEG.ARW"); super::camera_file_check!("Sony", "ILCE-7RM5", cam_sony_7rm5_s35_lossless_m_ljpeg_arw, "yuv/Sony_7RM5_S35_Lossless_M_LJPEG.ARW"); super::camera_file_check!("Sony", "ILCE-7RM5", cam_sony_7rm5_s35_lossless_s_ljpeg_arw, "yuv/Sony_7RM5_S35_Lossless_S_LJPEG.ARW"); super::camera_file_check!("Sony", "ILCE-7RM5", cam_sony_7rm5_lossless_m_ljpeg_arw, "yuv/Sony_7RM5_Lossless_M_LJPEG.ARW"); } mod camera_ilce_7r_raw_modes { super::camera_file_check!("Sony", "ILCE-7R", cam_ilce_7r_iso_50_14bits_sony_arw_compressed_arw, "raw_modes/ILCE-7R_ISO_50_14bits_Sony ARW Compressed.ARW"); } mod camera_ilce_7sm2_raw_modes { super::camera_file_check!("Sony", "ILCE-7SM2", cam_ilce_7sm2_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/ILCE-7SM2_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_ilce_7sm3_raw_modes { super::camera_file_check!("Sony", "ILCE-7SM3", cam_ilce_7sm3_iso_80_14bits_uncompressed_raw_arw, "raw_modes/ILCE-7SM3_ISO_80_14bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7SM3", cam_ilce_7sm3_iso_2500_14bits_compressed_raw_arw, "raw_modes/ILCE-7SM3_ISO_2500_14bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-7SM3", cam_ilce_7sm3_iso_80_14bits_compressed_raw_arw, "raw_modes/ILCE-7SM3_ISO_80_14bits_Compressed RAW.ARW"); } mod camera_ilce_7s_raw_modes { super::camera_file_check!("Sony", "ILCE-7S", cam_ilce_7s_iso_400_14bits_sony_arw_compressed_arw, "raw_modes/ILCE-7S_ISO_400_14bits_Sony ARW Compressed.ARW"); } mod camera_ilce_9m2_raw_modes { super::camera_file_check!("Sony", "ILCE-9M2", cam_ilce_9m2_iso_640_14bits_compressed_raw_arw, "raw_modes/ILCE-9M2_ISO_640_14bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-9M2", cam_ilce_9m2_iso_800_14bits_uncompressed_raw_arw, "raw_modes/ILCE-9M2_ISO_800_14bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-9M2", cam_ilce_9m2_iso_640_12bits_compressed_raw_arw, "raw_modes/ILCE-9M2_ISO_640_12bits_Compressed RAW.ARW"); } mod camera_ilce_9m3_raw_modes { super::camera_file_check!("Sony", "ILCE-9M3", cam_sony_ilce_9m3_14bits_lossless_m_arw, "raw_modes/Sony_ILCE_9M3_14bits_lossless_M.ARW"); super::camera_file_check!("Sony", "ILCE-9M3", cam_sony_ilce_9m3_14bits_apsc_14bits_lossy_arw, "raw_modes/Sony_ILCE_9M3_14bits_APSC_14bits_lossy.ARW"); super::camera_file_check!("Sony", "ILCE-9M3", cam_sony_ilce_9m3_14bits_uncompressed_arw, "raw_modes/Sony_ILCE_9M3_14bits_uncompressed.ARW"); super::camera_file_check!("Sony", "ILCE-9M3", cam_sony_ilce_9m3_14bits_lossless_l_arw, "raw_modes/Sony_ILCE_9M3_14bits_lossless_L.ARW"); super::camera_file_check!("Sony", "ILCE-9M3", cam_sony_ilce_9m3_14bits_apsc_14bits_lossless_m_arw, "raw_modes/Sony_ILCE_9M3_14bits_APSC_14bits_lossless_M.ARW"); super::camera_file_check!("Sony", "ILCE-9M3", cam_sony_ilce_9m3_14bits_lossless_s_arw, "raw_modes/Sony_ILCE_9M3_14bits_lossless_S.ARW"); super::camera_file_check!("Sony", "ILCE-9M3", cam_sony_ilce_9m3_14bits_lossy_arw, "raw_modes/Sony_ILCE_9M3_14bits_lossy.ARW"); super::camera_file_check!("Sony", "ILCE-9M3", cam_sony_ilce_9m3_14bits_apsc_14bits_lossless_s_arw, "raw_modes/Sony_ILCE_9M3_14bits_APSC_14bits_lossless_S.ARW"); super::camera_file_check!("Sony", "ILCE-9M3", cam_sony_ilce_9m3_14bits_apsc_14bits_uncompressed_arw, "raw_modes/Sony_ILCE_9M3_14bits_APSC_14bits_uncompressed.ARW"); } mod camera_ilce_9_raw_modes { super::camera_file_check!("Sony", "ILCE-9", cam_ilce_9_iso_100_14bits_uncompressed_raw_arw, "raw_modes/ILCE-9_ISO_100_14bits_Uncompressed RAW.ARW"); super::camera_file_check!("Sony", "ILCE-9", cam_ilce_9_iso_100_14bits_compressed_raw_arw, "raw_modes/ILCE-9_ISO_100_14bits_Compressed RAW.ARW"); } mod camera_ilce_qx1_raw_modes { super::camera_file_check!("Sony", "ILCE-QX1", cam_ilce_qx1_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/ILCE-QX1_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_nex_3n_raw_modes { super::camera_file_check!("Sony", "NEX-3N", cam_nex_3n_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/NEX-3N_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_nex_3_raw_modes { super::camera_file_check!("Sony", "NEX-3", cam_nex_3_iso_1600_12bits_sony_arw_compressed_arw, "raw_modes/NEX-3_ISO_1600_12bits_Sony ARW Compressed.ARW"); } mod camera_nex_5n_raw_modes { super::camera_file_check!("Sony", "NEX-5N", cam_nex_5n_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/NEX-5N_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_nex_5_raw_modes { super::camera_file_check!("Sony", "NEX-5", cam_nex_5_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/NEX-5_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_nex_5r_raw_modes { super::camera_file_check!("Sony", "NEX-5R", cam_nex_5r_iso_1600_12bits_sony_arw_compressed_arw, "raw_modes/NEX-5R_ISO_1600_12bits_Sony ARW Compressed.ARW"); } mod camera_nex_5t_raw_modes { super::camera_file_check!("Sony", "NEX-5T", cam_nex_5t_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/NEX-5T_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_nex_6_raw_modes { super::camera_file_check!("Sony", "NEX-6", cam_nex_6_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/NEX-6_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_nex_7_raw_modes { super::camera_file_check!("Sony", "NEX-7", cam_nex_7_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/NEX-7_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_nex_c3_raw_modes { super::camera_file_check!("Sony", "NEX-C3", cam_nex_c3_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/NEX-C3_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_nex_f3_raw_modes { super::camera_file_check!("Sony", "NEX-F3", cam_nex_f3_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/NEX-F3_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_slt_a33_raw_modes { super::camera_file_check!("Sony", "SLT-A33", cam_slt_a33_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/SLT-A33_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_slt_a35_raw_modes { super::camera_file_check!("Sony", "SLT-A35", cam_slt_a35_iso_400_12bits_sony_arw_compressed_arw, "raw_modes/SLT-A35_ISO_400_12bits_Sony ARW Compressed.ARW"); } mod camera_slt_a37_raw_modes { super::camera_file_check!("Sony", "SLT-A37", cam_slt_a37_iso_800_12bits_sony_arw_compressed_arw, "raw_modes/SLT-A37_ISO_800_12bits_Sony ARW Compressed.ARW"); } mod camera_slt_a55_raw_modes { super::camera_file_check!("Sony", "SLT-A55", cam_slt_a55v_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/SLT-A55V_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_slt_a57_raw_modes { super::camera_file_check!("Sony", "SLT-A57", cam_slt_a57_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/SLT-A57_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_slt_a58_raw_modes { super::camera_file_check!("Sony", "SLT-A58", cam_slt_a58_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/SLT-A58_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_slt_a65_raw_modes { super::camera_file_check!("Sony", "SLT-A65", cam_slt_a65v_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/SLT-A65V_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_slt_a77_raw_modes { super::camera_file_check!("Sony", "SLT-A77", cam_slt_a77v_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/SLT-A77V_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_slt_a99_raw_modes { super::camera_file_check!("Sony", "SLT-A99", cam_slt_a99v_iso_100_12bits_sony_arw_compressed_arw, "raw_modes/SLT-A99V_ISO_100_12bits_Sony ARW Compressed.ARW"); } mod camera_zv_1_raw_modes { super::camera_file_check!("Sony", "ZV-1", cam_zv_1_iso_125_12bits_sony_arw_compressed_arw, "raw_modes/ZV-1_ISO_125_12bits_Sony ARW Compressed.ARW"); } mod camera_zv_e1_raw_modes { super::camera_file_check!("Sony", "ZV-E1", cam_zv_e1_iso_200_14bits_arw, "raw_modes/ZV-E1_ISO_200_14bits.ARW"); } mod camera_zv_e10_raw_modes { super::camera_file_check!("Sony", "ZV-E10", cam_zv_e10_iso_400_14bits_sony_arw_compressed_arw, "raw_modes/ZV-E10_ISO_400_14bits_Sony ARW Compressed.ARW"); } mod camera_zv_e10m2_raw_modes { super::camera_file_check!("Sony", "ZV-E10M2", cam_zv_e10m2_iso_400_12bits_compressed_raw_arw, "raw_modes/ZV-E10M2_ISO_400_12bits_Compressed RAW.ARW"); super::camera_file_check!("Sony", "ZV-E10M2", cam_zv_e10m2_iso_400_12bits_lossless_compressed_raw_arw, "raw_modes/ZV-E10M2_ISO_400_12bits_Lossless Compressed RAW.ARW"); } mod camera_umc_r10c_raw_modes { super::camera_file_check!("Sony", "UMC-R10C", cam_umc_r10c_iso_200_12bits_sony_arw_compressed_arw, "raw_modes/UMC-R10C_ISO_200_12bits_Sony ARW Compressed.ARW"); } mod camera_r_d1_raw_modes { super::camera_file_check!("Epson", "R-D1", cam_r_d1_iso_400_12bits_erf, "raw_modes/R-D1_ISO_400_12bits.ERF"); } mod camera_r_d1s_raw_modes { super::camera_file_check!("Epson", "R-D1s", cam_r_d1s_iso_200_12bits_erf, "raw_modes/R-D1s_ISO_200_12bits.ERF"); } mod camera_r_d1x_raw_modes { super::camera_file_check!("Epson", "R-D1x", cam_r_d1x_iso_200_12bits_erf, "raw_modes/R-D1x_ISO_200_12bits.ERF"); } mod camera_aptus_22_raw_modes { super::camera_file_check!("Leaf", "Aptus 22", cam_aptus_22_iso_25_16bits_mos, "raw_modes/Aptus 22_ISO_25_16bits.MOS"); } mod camera_aptus_75_raw_modes { super::camera_file_check!("Leaf", "Aptus 75", cam_aptus_75_iso_50_16bits_mos, "raw_modes/Aptus 75_ISO_50_16bits.MOS"); } mod camera_credo_40_raw_modes { super::camera_file_check!("Leaf", "Credo 40", cam_credo_40_iso_100_iiq_sv2_iiq, "raw_modes/Credo 40_ISO_100_IIQ Sv2.IIQ"); super::camera_file_check!("Leaf", "Credo 40", cam_credo_40_iso_100_iiq_l_iiq, "raw_modes/Credo 40_ISO_100_IIQ L.IIQ"); } mod camera_alexa_65_raw_modes { super::camera_file_check!("Arri", "Alexa 65", cam_alexa_65_ari, "raw_modes/Alexa_65.ari"); } mod camera_alexa_lf_raw_modes { super::camera_file_check!("Arri", "Alexa LF", cam_alexa_lf_ari, "raw_modes/Alexa_LF.ari"); } mod camera_alexa_mini_raw_modes { super::camera_file_check!("Arri", "Alexa Mini", cam_alexa_mini_ari, "raw_modes/Alexa_Mini.ari"); } mod camera_alexa_sxt_raw_modes { super::camera_file_check!("Arri", "Alexa SXT", cam_alexa_sxt_ari, "raw_modes/Alexa_SXT.ari"); } mod camera_alexa_xt_raw_modes { super::camera_file_check!("Arri", "Alexa XT", cam_alexa_xt_ari, "raw_modes/Alexa_XT.ari"); } mod camera_alpha_7_digital_raw_modes { super::camera_file_check!("Minolta", "ALPHA-7 DIGITAL", cam_alpha_7_digital_iso_200_uncompressed_mrw, "raw_modes/ALPHA-7 DIGITAL_ISO_200_Uncompressed.MRW"); } mod camera_dimage_7hi_raw_modes { super::camera_file_check!("Minolta", "DiMAGE 7Hi", cam_dimage_7hi_iso_100_uncompressed_mrw, "raw_modes/DiMAGE 7Hi_ISO_100_Uncompressed.MRW"); } mod camera_dimage_7i_raw_modes { super::camera_file_check!("Minolta", "DiMAGE 7i", cam_dimage_7i_iso_100_uncompressed_mrw, "raw_modes/DiMAGE 7i_ISO_100_Uncompressed.MRW"); } mod camera_dimage_7_raw_modes { super::camera_file_check!("Minolta", "DiMAGE 7", cam_dimage_7_iso_100_uncompressed_mrw, "raw_modes/DiMAGE 7_ISO_100_Uncompressed.MRW"); } mod camera_dimage_a1_raw_modes { super::camera_file_check!("Minolta", "DiMAGE A1", cam_dimage_a1_iso_100_uncompressed_mrw, "raw_modes/DiMAGE A1_ISO_100_Uncompressed.MRW"); } mod camera_dimage_a200_raw_modes { super::camera_file_check!("Minolta", "DiMAGE A200", cam_dimage_a200_iso_200_uncompressed_mrw, "raw_modes/DiMAGE A200_ISO_200_Uncompressed.MRW"); } mod camera_dimage_a2_raw_modes { super::camera_file_check!("Minolta", "DiMAGE A2", cam_dimage_a2_iso_64_uncompressed_mrw, "raw_modes/DiMAGE A2_ISO_64_Uncompressed.MRW"); } mod camera_dimage_g600_raw_modes { super::camera_file_check!("Minolta", "DiMAGE G600", cam_minolta_dimage_g600_1_mrw, "raw_modes/Minolta_DiMAGE_G600_1.MRW"); super::camera_file_check!("Minolta", "DiMAGE G600", cam_minolta_dimage_g600_2_mrw, "raw_modes/Minolta_DiMAGE_G600_2.MRW"); } mod camera_dynax_7d_raw_modes { super::camera_file_check!("Minolta", "Dynax 7D", cam_dynax_7d_iso_100_uncompressed_mrw, "raw_modes/DYNAX 7D_ISO_100_Uncompressed.MRW"); } mod camera_maxxum_7d_raw_modes { super::camera_file_check!("Minolta", "Maxxum 7D", cam_maxxum_7d_iso_200_uncompressed_mrw, "raw_modes/MAXXUM 7D_ISO_200_Uncompressed.MRW"); } mod camera_zd_raw_modes { super::camera_file_check!("Mamiya", "ZD", cam_mamiya_zd_mef, "raw_modes/MAMIYA_ZD.MEF"); } mod camera_cfv_50_raw_modes { super::camera_file_check!("Hasselblad", "CFV-50", cam_hasselblad_cfv_50_iso_50_jpeg_fff, "raw_modes/Hasselblad CFV-50_ISO_50_JPEG.FFF"); } mod camera_cfv_raw_modes { super::camera_file_check!("Hasselblad", "CFV", cam_hasselblad_500_mech__iso_100_jpeg_3fr, "raw_modes/Hasselblad 500 mech._ISO_100_JPEG.3FR"); } mod camera_h3d_raw_modes { super::camera_file_check!("Hasselblad", "H3D", cam_hasselblad_h3d_iso_50_jpeg_3fr, "raw_modes/Hasselblad H3D_ISO_50_JPEG.3FR"); } mod camera_h4d_50_raw_modes { super::camera_file_check!("Hasselblad", "H4D-50", cam_hasselblad_h4d_50_iso_100_jpeg_fff, "raw_modes/Hasselblad H4D-50_ISO_100_JPEG.FFF"); } mod camera_h5d_40_raw_modes { super::camera_file_check!("Hasselblad", "H5D-40", cam_hasselblad_h5d_40_iso_100_jpeg_fff, "raw_modes/Hasselblad H5D-40_ISO_100_JPEG.FFF"); } mod camera_h5d_50c_raw_modes { super::camera_file_check!("Hasselblad", "H5D-50c", cam_hasselblad_h5d_50c_iso_100_jpeg_fff, "raw_modes/Hasselblad H5D-50c_ISO_100_JPEG.FFF"); } mod camera_hasselblad_h4d_40_raw_modes { super::camera_file_check!("Hasselblad", "Hasselblad H4D-40", cam_hasselblad_h4d_40_iso_100_jpeg_fff, "raw_modes/Hasselblad H4D-40_ISO_100_JPEG.FFF"); } mod camera_hasselblad_h4d_raw_modes { super::camera_file_check!("Hasselblad", "Hasselblad H4D", cam_hasselblad_h4d_iso_50_jpeg_3fr, "raw_modes/Hasselblad H4D_ISO_50_JPEG.3FR"); } mod camera_hasselblad_h6d_100cms_raw_modes { super::camera_file_check!("Hasselblad", "Hasselblad H6D-100cMS", cam_hasselblad_h6d_100cms_iso_64_jpeg_fff, "raw_modes/Hasselblad H6D-100cMS_ISO_64_JPEG.FFF"); } mod camera_hasselblad_x1d_raw_modes { super::camera_file_check!("Hasselblad", "Hasselblad X1D", cam_hasselblad_x1d_iso_1600_uncompressed_3fr, "raw_modes/Hasselblad X1D_ISO_1600_Uncompressed.3FR"); } mod camera_hasselblad_x2d_100c_raw_modes { super::camera_file_check!("Hasselblad", "Hasselblad X2D 100C", cam_x2d_100c_iso_64_3fr, "raw_modes/X2D 100C_ISO_64.3FR"); } mod camera_x1d_ii_50c_raw_modes { super::camera_file_check!("Hasselblad", "X1D II 50C", cam_x1d_ii_50c_iso_100_uncompressed_3fr, "raw_modes/X1D II 50C_ISO_100_Uncompressed.3FR"); } mod camera_ex1_raw_modes { super::camera_file_check!("Samsung", "EX1", cam_ex1_iso_80_packed_raw_srw, "raw_modes/EX1_ISO_80_Packed RAW.SRW"); } mod camera_ex2f_raw_modes { super::camera_file_check!("Samsung", "EX2F", cam_ex2f_iso_480_packed_raw_srw, "raw_modes/EX2F_ISO_480_Packed RAW.SRW"); } mod camera_nx1000_raw_modes { super::camera_file_check!("Samsung", "NX1000", cam_nx1000_iso_400_samsung_srw_compressed_srw, "raw_modes/NX1000_ISO_400_Samsung SRW Compressed.SRW"); } mod camera_nx100_raw_modes { super::camera_file_check!("Samsung", "NX100", cam_nx100_iso_100_samsung_srw_compressed_srw, "raw_modes/NX100_ISO_100_Samsung SRW Compressed.SRW"); } mod camera_nx1100_raw_modes { super::camera_file_check!("Samsung", "NX1100", cam_nx1100_iso_200_samsung_srw_compressed_srw, "raw_modes/NX1100_ISO_200_Samsung SRW Compressed.SRW"); } mod camera_nx1_raw_modes { super::camera_file_check!("Samsung", "NX1", cam_nx1_iso_400_packbits_srw, "raw_modes/NX1_ISO_400_PackBits.SRW"); } mod camera_nx2000_raw_modes { super::camera_file_check!("Samsung", "NX2000", cam_nx2000_iso_320_samsung_srw_compressed_srw, "raw_modes/NX2000_ISO_320_Samsung SRW Compressed.SRW"); } mod camera_nx200_raw_modes { super::camera_file_check!("Samsung", "NX200", cam_nx200_iso_200_samsung_srw_compressed_srw, "raw_modes/NX200_ISO_200_Samsung SRW Compressed.SRW"); } mod camera_nx20_raw_modes { super::camera_file_check!("Samsung", "NX20", cam_nx20_iso_200_samsung_srw_compressed_srw, "raw_modes/NX20_ISO_200_Samsung SRW Compressed.SRW"); } mod camera_nx210_raw_modes { super::camera_file_check!("Samsung", "NX210", cam_nx210_iso_100_samsung_srw_compressed_srw, "raw_modes/NX210_ISO_100_Samsung SRW Compressed.SRW"); } mod camera_nx3000_raw_modes { super::camera_file_check!("Samsung", "NX3000", cam_nx3000_iso_100_samsung_srw_compressed_2_srw, "raw_modes/NX3000_ISO_100_Samsung SRW Compressed 2.SRW"); } mod camera_nx3300_raw_modes { super::camera_file_check!("Samsung", "NX3300", cam_nx3300_12bits_srw, "raw_modes/NX3300_12bits.SRW"); } mod camera_nx300m_raw_modes { super::camera_file_check!("Samsung", "NX300M", cam_nx300m_iso_800_samsung_srw_compressed_srw, "raw_modes/NX300M_ISO_800_Samsung SRW Compressed.SRW"); } mod camera_nx300_raw_modes { super::camera_file_check!("Samsung", "NX300", cam_nx300_iso_100_samsung_srw_compressed_srw, "raw_modes/NX300_ISO_100_Samsung SRW Compressed.SRW"); } mod camera_nx30_raw_modes { super::camera_file_check!("Samsung", "NX30", cam_nx30_iso_800_samsung_srw_compressed_srw, "raw_modes/NX30_ISO_800_Samsung SRW Compressed.SRW"); } mod camera_nx500_raw_modes { super::camera_file_check!("Samsung", "NX500", cam_nx500_iso_100_14bits_normal_compression_srw, "raw_modes/NX500_ISO_100_14bits_normal_compression.SRW"); super::camera_file_check!("Samsung", "NX500", cam_nx500_iso_100_12bits_lossless_compression_srw, "raw_modes/NX500_ISO_100_12bits_lossless_compression.SRW"); super::camera_file_check!("Samsung", "NX500", cam_nx500_iso_100_12bits_normal_compression_srw, "raw_modes/NX500_ISO_100_12bits_normal_compression.SRW"); super::camera_file_check!("Samsung", "NX500", cam_nx500_iso_100_14bits_lossless_compression_srw, "raw_modes/NX500_ISO_100_14bits_lossless_compression.SRW"); } mod camera_nx_mini_raw_modes { super::camera_file_check!("Samsung", "NX mini", cam_nx_mini_iso_1000_samsung_srw_compressed_2_srw, "raw_modes/NX mini_ISO_1000_Samsung SRW Compressed 2.SRW"); } mod camera_wb2000_raw_modes { super::camera_file_check!("Samsung", "WB2000", cam_wb2000_iso_80_packed_raw_srw, "raw_modes/WB2000_ISO_80_Packed RAW.SRW"); } mod camera_dc120_raw_modes { super::camera_file_check!("Kodak", "DC120", cam_kodak_dc120_zoom_digital_camera_jpeg_kdc, "raw_modes/Kodak DC120 ZOOM Digital Camera_JPEG.KDC"); super::camera_file_check!("Kodak", "DC120", cam_kodak_dc120_zoom_digital_camera_uncompressed_kdc, "raw_modes/Kodak DC120 ZOOM Digital Camera_Uncompressed.KDC"); } mod camera_dc50_raw_modes { super::camera_file_check!("Kodak", "DC50", cam_kodak_dc50_compressed_kdc, "raw_modes/Kodak_DC50_compressed.KDC"); } mod camera_dcs460d_raw_modes { super::camera_file_check!("Kodak", "DCS460D", cam_dcs460d_tiff, "raw_modes/DCS460D.TIFF"); } mod camera_dcs560c_raw_modes { super::camera_file_check!("Kodak", "DCS560C", cam_raw_kodak_dcs560c_tif, "raw_modes/RAW_KODAK_DCS560C.TIF"); } mod camera_dcs760c_raw_modes { super::camera_file_check!("Kodak", "DCS760C", cam_dcs760c_dcr, "raw_modes/DCS760C.DCR"); } mod camera_dcs_pro_14n_raw_modes { super::camera_file_check!("Kodak", "DCS Pro 14N", cam_dcs_pro_14n_iso_160_kodak_dcr_compressed_dcr, "raw_modes/DCS Pro 14N_ISO_160_Kodak DCR Compressed.DCR"); } mod camera_dcs_pro_14nx_raw_modes { super::camera_file_check!("Kodak", "DCS Pro 14nx", cam_dcs_pro_14nx_iso_160_kodak_dcr_compressed_dcr, "raw_modes/DCS Pro 14nx_ISO_160_Kodak DCR Compressed.DCR"); } mod camera_dcs_pro_slrc_raw_modes { super::camera_file_check!("Kodak", "DCS Pro SLRc", cam_dcs_pro_slrc_iso_160_kodak_dcr_compressed_dcr, "raw_modes/DCS Pro SLRc_ISO_160_Kodak DCR Compressed.DCR"); } mod camera_dcs_pro_slrn_raw_modes { super::camera_file_check!("Kodak", "DCS Pro SLRn", cam_dcs_pro_slrn_iso_160_kodak_dcr_compressed_dcr, "raw_modes/DCS Pro SLRn_ISO_160_Kodak DCR Compressed.DCR"); } mod camera_easyshare_z981_raw_modes { super::camera_file_check!("Kodak", "EasyShare Z981", cam_kodak_easyshare_z981_digital_camera_iso_100_jpeg_kdc, "raw_modes/KODAK EasyShare Z981 Digital Camera_ISO_100_JPEG.KDC"); } mod camera_easyshare_z990_raw_modes { super::camera_file_check!("Kodak", "EasyShare Z990", cam_kodak_easyshare_z990_digital_camera_iso_125_kdc, "raw_modes/KODAK EasyShare Z990 Digital Camera_ISO_125.KDC"); } mod camera_eos_dcs_1_raw_modes { super::camera_file_check!("Kodak", "EOS DCS 1", cam_raw_canon_dcs1_tif, "raw_modes/RAW_CANON_DCS1.TIF"); } mod camera_eos_dcs_3_raw_modes { super::camera_file_check!("Kodak", "EOS DCS 3", cam_eos_dcs_3_tif, "raw_modes/EOS DCS 3.TIF"); } mod camera_kodak_p712_zoom_digital_camera_raw_modes { super::camera_file_check!("Kodak", "KODAK P712 ZOOM DIGITAL CAMERA", cam_kodak_p712_zoom_digital_camera_iso_64_jpeg_kdc, "raw_modes/KODAK P712 ZOOM DIGITAL CAMERA_ISO_64_JPEG.KDC"); } mod camera_p880_raw_modes { super::camera_file_check!("Kodak", "P880", cam_kodak_p880_zoom_digital_camera_iso_50_jpeg_kdc, "raw_modes/KODAK P880 ZOOM DIGITAL CAMERA_ISO_50_JPEG.KDC"); } mod camera_z1015_is_raw_modes { super::camera_file_check!("Kodak", "Z1015 IS", cam_raw_kodak_easyshare_z1015_is_kdc, "raw_modes/RAW_KODAK_EASYSHARE_Z1015-IS.KDC"); } mod camera_c5050z_raw_modes { super::camera_file_check!("Olympus", "C5050Z", cam_c5050z_iso_100_orf, "raw_modes/C5050Z_ISO_100.ORF"); } mod camera_c5060wz_raw_modes { super::camera_file_check!("Olympus", "C5060WZ", cam_c5060wz_iso_80_orf, "raw_modes/C5060WZ_ISO_80.ORF"); } mod camera_c7070wz_raw_modes { super::camera_file_check!("Olympus", "C7070WZ", cam_c7070wz_iso_80_orf, "raw_modes/C7070WZ_ISO_80.ORF"); } mod camera_c8080wz_raw_modes { super::camera_file_check!("Olympus", "C8080WZ", cam_c8080wz_iso_50_orf, "raw_modes/C8080WZ_ISO_50.ORF"); } mod camera_e_10_raw_modes { super::camera_file_check!("Olympus", "E-10", cam_e_10_iso_80_orf, "raw_modes/E-10_ISO_80.ORF"); } mod camera_e_1_raw_modes { super::camera_file_check!("Olympus", "E-1", cam_e_1_iso_100_orf, "raw_modes/E-1_ISO_100.ORF"); } mod camera_e_20_raw_modes { super::camera_file_check!("Olympus", "E-20", cam_e_20_iso_80_orf, "raw_modes/E-20_ISO_80.ORF"); } mod camera_e_300_raw_modes { super::camera_file_check!("Olympus", "E-300", cam_e_300_iso_400_orf, "raw_modes/E-300_ISO_400.ORF"); } mod camera_e_30_raw_modes { super::camera_file_check!("Olympus", "E-30", cam_e_30_iso_200_orf, "raw_modes/E-30_ISO_200.ORF"); } mod camera_e_330_raw_modes { super::camera_file_check!("Olympus", "E-330", cam_e_330_iso_100_orf, "raw_modes/E-330_ISO_100.ORF"); } mod camera_e_3_raw_modes { super::camera_file_check!("Olympus", "E-3", cam_e_3_iso_100_orf, "raw_modes/E-3_ISO_100.ORF"); } mod camera_e_400_raw_modes { super::camera_file_check!("Olympus", "E-400", cam_e_400_iso_200_orf, "raw_modes/E-400_ISO_200.ORF"); } mod camera_e_410_raw_modes { super::camera_file_check!("Olympus", "E-410", cam_e_410_iso_400_orf, "raw_modes/E-410_ISO_400.ORF"); } mod camera_e_420_raw_modes { super::camera_file_check!("Olympus", "E-420", cam_e_420_iso_100_orf, "raw_modes/E-420_ISO_100.ORF"); } mod camera_e_450_raw_modes { super::camera_file_check!("Olympus", "E-450", cam_e_450_iso_200_orf, "raw_modes/E-450_ISO_200.ORF"); } mod camera_e_500_raw_modes { super::camera_file_check!("Olympus", "E-500", cam_e_500_iso_400_orf, "raw_modes/E-500_ISO_400.ORF"); } mod camera_e_510_raw_modes { super::camera_file_check!("Olympus", "E-510", cam_e_510_iso_100_orf, "raw_modes/E-510_ISO_100.ORF"); } mod camera_e_520_raw_modes { super::camera_file_check!("Olympus", "E-520", cam_e_520_iso_400_orf, "raw_modes/E-520_ISO_400.ORF"); } mod camera_e_5_raw_modes { super::camera_file_check!("Olympus", "E-5", cam_e_5_iso_200_orf, "raw_modes/E-5_ISO_200.ORF"); } mod camera_e_600_raw_modes { super::camera_file_check!("Olympus", "E-600", cam_e_600_iso_100_orf, "raw_modes/E-600_ISO_100.ORF"); } mod camera_e_620_raw_modes { super::camera_file_check!("Olympus", "E-620", cam_e_620_iso_200_orf, "raw_modes/E-620_ISO_200.ORF"); } mod camera_e_m10_mark_iii_raw_modes { super::camera_file_check!("Olympus", "E-M10 Mark III", cam_e_m10_mark_iii_iso_100_orf, "raw_modes/E-M10 Mark III_ISO_100.ORF"); } mod camera_e_m10markiiis_raw_modes { super::camera_file_check!("Olympus", "E-M10MarkIIIS", cam_e_m10markiiis_iso_200_orf, "raw_modes/E-M10MarkIIIS_ISO_200.ORF"); } mod camera_e_m10_mark_ii_raw_modes { super::camera_file_check!("Olympus", "E-M10 Mark II", cam_e_m10markii_iso_3200_orf, "raw_modes/E-M10MarkII_ISO_3200.ORF"); } mod camera_e_m10_mark_iv_raw_modes { super::camera_file_check!("Olympus", "E-M10 Mark IV", cam_e_m10markiv_iso_100_stackedmode_no_orf, "raw_modes/E-M10MarkIV_ISO_100_StackedMode_No.ORF"); } mod camera_e_m10_raw_modes { super::camera_file_check!("Olympus", "E-M10", cam_e_m10_iso_200_orf, "raw_modes/E-M10_ISO_200.ORF"); } mod camera_e_m1markiii_raw_modes { super::camera_file_check!("Olympus", "E-M1MarkIII", cam_e_m1markiii_iso_200_stackedmode_no_orf, "raw_modes/E-M1MarkIII_ISO_200_StackedMode_No.ORF"); super::camera_file_check!("Olympus", "E-M1MarkIII", cam_e_m1markiii_iso_200_stackedmode_hand_held_high_resolution_orf, "raw_modes/E-M1MarkIII_ISO_200_StackedMode_Hand-held high resolution.ORF"); super::camera_file_check!("Olympus", "E-M1MarkIII", cam_e_m1markiii_iso_200_stackedmode_tripod_high_resolution_orf, "raw_modes/E-M1MarkIII_ISO_200_StackedMode_Tripod high resolution.ORF"); } mod camera_e_m1markii_raw_modes { super::camera_file_check!("Olympus", "E-M1MarkII", cam_olympus_em1mk2__hires_25mp_ori, "raw_modes/Olympus_EM1mk2__HIRES_25MP.ORI"); super::camera_file_check!("Olympus", "E-M1MarkII", cam_olympus_em1mk2__hires_50mp_ori, "raw_modes/Olympus_EM1mk2__HIRES_50MP.ORI"); super::camera_file_check!("Olympus", "E-M1MarkII", cam_olympus_em1mk2_standard_20mp_colorchecker_orf, "raw_modes/Olympus_EM1mk2_Standard_20MP_ColorChecker.ORF"); super::camera_file_check!("Olympus", "E-M1MarkII", cam_olympus_em1mk2_standard_20mp_orf, "raw_modes/Olympus_EM1mk2_Standard_20MP.ORF"); super::camera_file_check!("Olympus", "E-M1MarkII", cam_olympus_em1mk2__hires_25mp_orf, "raw_modes/Olympus_EM1mk2__HIRES_25MP.ORF"); super::camera_file_check!("Olympus", "E-M1MarkII", cam_olympus_em1mk2__hires_50mp_orf, "raw_modes/Olympus_EM1mk2__HIRES_50MP.ORF"); } mod camera_e_m1_raw_modes { super::camera_file_check!("Olympus", "E-M1", cam_e_m1_iso_200_orf, "raw_modes/E-M1_ISO_200.ORF"); } mod camera_e_m1x_raw_modes { super::camera_file_check!("Olympus", "E-M1X", cam_e_m1x_iso_1600_orf, "raw_modes/E-M1X_ISO_1600.ORF"); } mod camera_e_m5_mark_iii_raw_modes { super::camera_file_check!("Olympus", "E-M5 Mark III", cam_e_m5markiii_iso_200_orf, "raw_modes/E-M5MarkIII_ISO_200.ORF"); } mod camera_e_m5_mark_ii_raw_modes { super::camera_file_check!("Olympus", "E-M5 Mark II", cam_e_m5markii_iso_200_stackedmode_tripod_high_resolution_orf, "raw_modes/E-M5MarkII_ISO_200_StackedMode_Tripod high resolution.ORF"); super::camera_file_check!("Olympus", "E-M5 Mark II", cam_e_m5markii_iso_200_stackedmode_no_orf, "raw_modes/E-M5MarkII_ISO_200_StackedMode_No.ORF"); } mod camera_e_m5_raw_modes { super::camera_file_check!("Olympus", "E-M5", cam_e_m5_iso_200_orf, "raw_modes/E-M5_ISO_200.ORF"); } mod camera_e_p1_raw_modes { super::camera_file_check!("Olympus", "E-P1", cam_e_p1_iso_100_orf, "raw_modes/E-P1_ISO_100.ORF"); super::camera_file_check!("Olympus", "E-P1", cam_e_p1_iso_200_orf, "raw_modes/E-P1_ISO_200.ORF"); } mod camera_e_p2_raw_modes { super::camera_file_check!("Olympus", "E-P2", cam_e_p2_iso_800_orf, "raw_modes/E-P2_ISO_800.ORF"); } mod camera_e_p3_raw_modes { super::camera_file_check!("Olympus", "E-P3", cam_e_p3_iso_200_orf, "raw_modes/E-P3_ISO_200.ORF"); } mod camera_e_p5_raw_modes { super::camera_file_check!("Olympus", "E-P5", cam_e_p5_iso_200_orf, "raw_modes/E-P5_ISO_200.ORF"); } mod camera_e_pl10_raw_modes { super::camera_file_check!("Olympus", "E-PL10", cam_e_pl10_iso_1000_orf, "raw_modes/E-PL10_ISO_1000.ORF"); } mod camera_e_pl1_raw_modes { super::camera_file_check!("Olympus", "E-PL1", cam_e_pl1_iso_1600_orf, "raw_modes/E-PL1_ISO_1600.ORF"); } mod camera_e_pl2_raw_modes { super::camera_file_check!("Olympus", "E-PL2", cam_e_pl2_iso_200_orf, "raw_modes/E-PL2_ISO_200.ORF"); } mod camera_e_pl3_raw_modes { super::camera_file_check!("Olympus", "E-PL3", cam_e_pl3_iso_200_orf, "raw_modes/E-PL3_ISO_200.ORF"); } mod camera_e_pl5_raw_modes { super::camera_file_check!("Olympus", "E-PL5", cam_e_pl5_iso_320_orf, "raw_modes/E-PL5_ISO_320.ORF"); } mod camera_e_pl6_raw_modes { super::camera_file_check!("Olympus", "E-PL6", cam_e_pl6_iso_200_orf, "raw_modes/E-PL6_ISO_200.ORF"); } mod camera_e_pl7_raw_modes { super::camera_file_check!("Olympus", "E-PL7", cam_e_pl7_iso_200_orf, "raw_modes/E-PL7_ISO_200.ORF"); } mod camera_e_pl8_raw_modes { super::camera_file_check!("Olympus", "E-PL8", cam_e_pl8_iso_200_orf, "raw_modes/E-PL8_ISO_200.ORF"); } mod camera_e_pl9_raw_modes { super::camera_file_check!("Olympus", "E-PL9", cam_e_pl9_iso_200_orf, "raw_modes/E-PL9_ISO_200.ORF"); } mod camera_e_pm1_raw_modes { super::camera_file_check!("Olympus", "E-PM1", cam_e_pm1_iso_200_orf, "raw_modes/E-PM1_ISO_200.ORF"); } mod camera_e_pm2_raw_modes { super::camera_file_check!("Olympus", "E-PM2", cam_e_pm2_iso_200_orf, "raw_modes/E-PM2_ISO_200.ORF"); } mod camera_pen_f_raw_modes { super::camera_file_check!("Olympus", "PEN-F", cam_pen_f_iso_200_stackedmode_no_orf, "raw_modes/PEN-F_ISO_200_StackedMode_No.ORF"); super::camera_file_check!("Olympus", "PEN-F", cam_pen_f_iso_200_stackedmode_tripod_high_resolution_orf, "raw_modes/PEN-F_ISO_200_StackedMode_Tripod high resolution.ORF"); } mod camera_sh_2_raw_modes { super::camera_file_check!("Olympus", "SH-2", cam_sh_2_iso_125_orf, "raw_modes/SH-2_ISO_125.ORF"); } mod camera_sp350_raw_modes { super::camera_file_check!("Olympus", "SP350", cam_sp350_iso_100_orf, "raw_modes/SP350_ISO_100.ORF"); } mod camera_sp500uz_raw_modes { super::camera_file_check!("Olympus", "SP500UZ", cam_sp500uz_iso_100_orf, "raw_modes/SP500UZ_ISO_100.ORF"); } mod camera_sp510uz_raw_modes { super::camera_file_check!("Olympus", "SP510UZ", cam_sp510uz_iso_50_orf, "raw_modes/SP510UZ_ISO_50.ORF"); } mod camera_sp565uz_raw_modes { super::camera_file_check!("Olympus", "SP565UZ", cam_sp565uz_iso_64_orf, "raw_modes/SP565UZ_ISO_64.ORF"); } mod camera_sp570uz_raw_modes { super::camera_file_check!("Olympus", "SP570UZ", cam_olympus_sp570uz_12bit_orf, "raw_modes/Olympus_SP570UZ_12bit.ORF"); } mod camera_stylus1_raw_modes { super::camera_file_check!("Olympus", "Stylus1", cam_stylus1_iso_100_orf, "raw_modes/STYLUS1_ISO_100.ORF"); } mod camera_tg_4_raw_modes { super::camera_file_check!("Olympus", "TG-4", cam_tg_4_iso_100_orf, "raw_modes/TG-4_ISO_100.ORF"); } mod camera_tg_5_raw_modes { super::camera_file_check!("Olympus", "TG-5", cam_tg_5_iso_100_orf, "raw_modes/TG-5_ISO_100.ORF"); } mod camera_tg_6_raw_modes { super::camera_file_check!("Olympus", "TG-6", cam_tg_6_iso_100_orf, "raw_modes/TG-6_ISO_100.ORF"); } mod camera_xz_10_raw_modes { super::camera_file_check!("Olympus", "XZ-10", cam_xz_10_iso_100_orf, "raw_modes/XZ-10_ISO_100.ORF"); } mod camera_xz_1_raw_modes { super::camera_file_check!("Olympus", "XZ-1", cam_xz_1_iso_100_orf, "raw_modes/XZ-1_ISO_100.ORF"); } mod camera_xz_2_raw_modes { super::camera_file_check!("Olympus", "XZ-2", cam_xz_2_iso_100_orf, "raw_modes/XZ-2_ISO_100.ORF"); } mod camera_dc_fz10002_raw_modes { super::camera_file_check!("Panasonic", "DC-FZ10002", cam_dc_fz10002_iso_320_4fmt_3x2_rw2, "raw_modes/DC-FZ10002_ISO_320_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DC-FZ10002", cam_dc_fz10002_iso_250_4fmt_1x1_rw2, "raw_modes/DC-FZ10002_ISO_250_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-FZ10002", cam_dc_fz10002_iso_250_4fmt_4x3_rw2, "raw_modes/DC-FZ10002_ISO_250_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-FZ10002", cam_dc_fz10002_iso_250_4fmt_16x9_rw2, "raw_modes/DC-FZ10002_ISO_250_4fmt_16x9.RW2"); } mod camera_dc_fz45_raw_modes { super::camera_file_check!("Panasonic", "DC-FZ45", cam_dmc_fz45_iso_500_4fmt_4320x2880_rw2, "raw_modes/DMC-FZ45_ISO_500_4fmt_4320x2880.RW2"); super::camera_file_check!("Panasonic", "DC-FZ45", cam_dmc_fz45_iso_400_4fmt_4320x3240_rw2, "raw_modes/DMC-FZ45_ISO_400_4fmt_4320x3240.RW2"); super::camera_file_check!("Panasonic", "DC-FZ45", cam_dmc_fz45_iso_500_4fmt_3232x3234_rw2, "raw_modes/DMC-FZ45_ISO_500_4fmt_3232x3234.RW2"); super::camera_file_check!("Panasonic", "DC-FZ45", cam_dmc_fz45_iso_500_4fmt_4320x2436_rw2, "raw_modes/DMC-FZ45_ISO_500_4fmt_4320x2436.RW2"); } mod camera_dc_fz80_raw_modes { super::camera_file_check!("Panasonic", "DC-FZ80", cam_dc_fz80_iso_80_4fmt_1x1_rw2, "raw_modes/DC-FZ80_ISO_80_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-FZ80", cam_dc_fz80_iso_80_4fmt_4x3_rw2, "raw_modes/DC-FZ80_ISO_80_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-FZ80", cam_dc_fz80_iso_80_4fmt_3x2_rw2, "raw_modes/DC-FZ80_ISO_80_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DC-FZ80", cam_dc_fz80_iso_80_4fmt_16x9_rw2, "raw_modes/DC-FZ80_ISO_80_4fmt_16x9.RW2"); } mod camera_dc_fz82_raw_modes { super::camera_file_check!("Panasonic", "DC-FZ82", cam_dc_fz82_iso_80_4fmt_4x3_rw2, "raw_modes/DC-FZ82_ISO_80_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-FZ82", cam_dc_fz82_iso_80_4fmt_1x1_rw2, "raw_modes/DC-FZ82_ISO_80_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-FZ82", cam_dc_fz82_iso_80_4fmt_3x2_rw2, "raw_modes/DC-FZ82_ISO_80_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DC-FZ82", cam_dc_fz82_iso_80_4fmt_16x9_rw2, "raw_modes/DC-FZ82_ISO_80_4fmt_16x9.RW2"); } mod camera_dc_g100_raw_modes { super::camera_file_check!("Panasonic", "DC-G100", cam_dc_g100_iso_200_4fmt_16x9_rw2, "raw_modes/DC-G100_ISO_200_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DC-G100", cam_dc_g100_iso_200_4fmt_3x2_rw2, "raw_modes/DC-G100_ISO_200_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DC-G100", cam_dc_g100_iso_200_4fmt_1x1_rw2, "raw_modes/DC-G100_ISO_200_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-G100", cam_dc_g100_iso_200_4fmt_4x3_rw2, "raw_modes/DC-G100_ISO_200_4fmt_4x3.RW2"); } mod camera_dc_g110_raw_modes { super::camera_file_check!("Panasonic", "DC-G110", cam_dc_g110_iso_400_4fmt_1x1_rw2, "raw_modes/DC-G110_ISO_400_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-G110", cam_dc_g110_iso_400_4fmt_4x3_rw2, "raw_modes/DC-G110_ISO_400_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-G110", cam_dc_g110_iso_400_4fmt_16x9_rw2, "raw_modes/DC-G110_ISO_400_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DC-G110", cam_dc_g110_iso_400_4fmt_3x2_rw2, "raw_modes/DC-G110_ISO_400_4fmt_3x2.RW2"); } mod camera_dc_g90_raw_modes { super::camera_file_check!("Panasonic", "DC-G90", cam_dc_g90_iso_200_4fmt_4x3_rw2, "raw_modes/DC-G90_ISO_200_4fmt_4x3.RW2"); } mod camera_dc_g91_raw_modes { super::camera_file_check!("Panasonic", "DC-G91", cam_dc_g91_iso_200_4fmt_4x3_rw2, "raw_modes/DC-G91_ISO_200_4fmt_4x3.RW2"); } mod camera_dc_g95_raw_modes { super::camera_file_check!("Panasonic", "DC-G95", cam_dc_g95_iso_400_4fmt_16x9_rw2, "raw_modes/DC-G95_ISO_400_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DC-G95", cam_dc_g95_iso_400_4fmt_3x2_rw2, "raw_modes/DC-G95_ISO_400_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DC-G95", cam_dc_g95_iso_400_4fmt_4x3_rw2, "raw_modes/DC-G95_ISO_400_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-G95", cam_dc_g95_iso_400_4fmt_1x1_rw2, "raw_modes/DC-G95_ISO_400_4fmt_1x1.RW2"); } mod camera_dc_g9_raw_modes { super::camera_file_check!("Panasonic", "DC-G9", cam_dc_g9_iso_3200_4fmt_4x3_sh2_burst_rw2, "raw_modes/DC-G9_ISO_3200_4fmt_4x3_SH2-Burst.RW2"); super::camera_file_check!("Panasonic", "DC-G9", cam_dc_g9_iso_200_4fmt_1x1_rw2, "raw_modes/DC-G9_ISO_200_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-G9", cam_dc_g9_iso_200_4fmt_4x3_rw2, "raw_modes/DC-G9_ISO_200_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-G9", cam_dc_g9_iso_200_4fmt_16x9_rw2, "raw_modes/DC-G9_ISO_200_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DC-G9", cam_dc_g9_iso_200_5fmt_4x3_hires_secondary_rw2, "raw_modes/DC-G9_ISO_200_5fmt_4x3_hires_secondary.RW2"); super::camera_file_check!("Panasonic", "DC-G9", cam_dc_g9_iso_200_5fmt_80mp_hires_rw2, "raw_modes/DC-G9_ISO_200_5fmt_80mp_hires.RW2"); super::camera_file_check!("Panasonic", "DC-G9", cam_dc_g9_iso_200_4fmt_3x2_rw2, "raw_modes/DC-G9_ISO_200_4fmt_3x2.RW2"); } mod camera_dc_g9m2_raw_modes { super::camera_file_check!("Panasonic", "DC-G9M2", cam_dc_g9m2_iso_100_8fmt_5776x4336_rw2, "raw_modes/DC-G9M2_ISO_100_8fmt_5776x4336.RW2"); super::camera_file_check!("Panasonic", "DC-G9M2", cam_dc_g9m2_iso_100_8fmt_11552x8672_rw2, "raw_modes/DC-G9M2_ISO_100_8fmt_11552x8672.RW2"); } mod camera_dc_gf10_raw_modes { super::camera_file_check!("Panasonic", "DC-GF10", cam_dc_gf10_iso_200_panasonic_raw_1_4592x3448_rw2, "raw_modes/DC-GF10_ISO_200_Panasonic RAW 1_4592x3448.RW2"); super::camera_file_check!("Panasonic", "DC-GF10", cam_p1010137_rw2, "raw_modes/P1010137.RW2"); super::camera_file_check!("Panasonic", "DC-GF10", cam_p1010141_rw2, "raw_modes/P1010141.RW2"); super::camera_file_check!("Panasonic", "DC-GF10", cam_p1010140_rw2, "raw_modes/P1010140.RW2"); } mod camera_dc_gh5m2_raw_modes { super::camera_file_check!("Panasonic", "DC-GH5M2", cam_dc_gh5m2_iso_250_6fmt_3x2_rw2, "raw_modes/DC-GH5M2_ISO_250_6fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DC-GH5M2", cam_dc_gh5m2_iso_250_6fmt_16x9_rw2, "raw_modes/DC-GH5M2_ISO_250_6fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DC-GH5M2", cam_dc_gh5m2_iso_250_6fmt_4x3_rw2, "raw_modes/DC-GH5M2_ISO_250_6fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-GH5M2", cam_dc_gh5m2_iso_250_6fmt_1x1_rw2, "raw_modes/DC-GH5M2_ISO_250_6fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-GH5M2", cam_dc_gh5m2_colortarget_rw2, "raw_modes/DC-GH5M2_colortarget.RW2"); } mod camera_dc_gh5_raw_modes { super::camera_file_check!("Panasonic", "DC-GH5", cam_dc_gh5_iso_400_4fmt_16x9_rw2, "raw_modes/DC-GH5_ISO_400_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DC-GH5", cam_dc_gh5_iso_400_4fmt_1x1_rw2, "raw_modes/DC-GH5_ISO_400_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-GH5", cam_dc_gh5_iso_400_4fmt_4x3_rw2, "raw_modes/DC-GH5_ISO_400_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-GH5", cam_dc_gh5_iso_400_4fmt_3x2_rw2, "raw_modes/DC-GH5_ISO_400_4fmt_3x2.RW2"); } mod camera_dc_gh5s_raw_modes { super::camera_file_check!("Panasonic", "DC-GH5S", cam_p1022091_rw2, "raw_modes/P1022091.RW2"); super::camera_file_check!("Panasonic", "DC-GH5S", cam_dc_gh5s_iso_800_panasonic_raw_1_3840x2560_rw2, "raw_modes/DC-GH5S_ISO_800_Panasonic RAW 1_3840x2560.RW2"); super::camera_file_check!("Panasonic", "DC-GH5S", cam_dc_gh5s_iso_800_panasonic_raw_1_4016x2256_rw2, "raw_modes/DC-GH5S_ISO_800_Panasonic RAW 1_4016x2256.RW2"); super::camera_file_check!("Panasonic", "DC-GH5S", cam_dc_gh5s_iso_800_panasonic_raw_1_3680x2760_rw2, "raw_modes/DC-GH5S_ISO_800_Panasonic RAW 1_3680x2760.RW2"); super::camera_file_check!("Panasonic", "DC-GH5S", cam_p1022090_rw2, "raw_modes/P1022090.RW2"); super::camera_file_check!("Panasonic", "DC-GH5S", cam_p1022085_rw2, "raw_modes/P1022085.RW2"); super::camera_file_check!("Panasonic", "DC-GH5S", cam_dc_gh5s_iso_800_panasonic_raw_1_2752x2752_rw2, "raw_modes/DC-GH5S_ISO_800_Panasonic RAW 1_2752x2752.RW2"); super::camera_file_check!("Panasonic", "DC-GH5S", cam_p1022092_rw2, "raw_modes/P1022092.RW2"); } mod camera_dc_gh6_raw_modes { super::camera_file_check!("Panasonic", "DC-GH6", cam_dc_gh6_iso_800_8fmt_1x1_hires_rw2, "raw_modes/DC-GH6_ISO_800_8fmt_1x1_hires.RW2"); super::camera_file_check!("Panasonic", "DC-GH6", cam_dc_gh6_iso_800_8fmt_4x3_rw2, "raw_modes/DC-GH6_ISO_800_8fmt_4x3.RW2"); } mod camera_dc_gh7_raw_modes { super::camera_file_check!("Panasonic", "DC-GH7", cam_dc_gh7_iso_100_8fmt_3x2_rw2, "raw_modes/DC-GH7_ISO_100_8fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DC-GH7", cam_dc_gh7_iso_100_8fmt_4x3_rw2, "raw_modes/DC-GH7_ISO_100_8fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-GH7", cam_dc_gh7_iso_100_8fmt_1x1_rw2, "raw_modes/DC-GH7_ISO_100_8fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-GH7", cam_dc_gh7_iso_100_8fmt_16x9_rw2, "raw_modes/DC-GH7_ISO_100_8fmt_16x9.RW2"); } mod camera_dc_gx7mk3_raw_modes { super::camera_file_check!("Panasonic", "DC-GX7MK3", cam_dc_gx7mk3_iso_1600_panasonic_raw_1_5184x3888_rw2, "raw_modes/DC-GX7MK3_ISO_1600_Panasonic RAW 1_5184x3888.RW2"); } mod camera_dc_gx800_raw_modes { super::camera_file_check!("Panasonic", "DC-GX800", cam_dc_gx800_iso_200_4fmt_3x2_rw2, "raw_modes/DC-GX800_ISO_200_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DC-GX800", cam_dc_gx800_iso_200_4fmt_1x1_rw2, "raw_modes/DC-GX800_ISO_200_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-GX800", cam_dc_gx800_iso_200_4fmt_4x3_rw2, "raw_modes/DC-GX800_ISO_200_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-GX800", cam_dc_gx800_iso_200_4fmt_16x9_rw2, "raw_modes/DC-GX800_ISO_200_4fmt_16x9.RW2"); } mod camera_dc_gx850_raw_modes { super::camera_file_check!("Panasonic", "DC-GX850", cam_dc_gx850_iso_2000_4fmt_1x1_rw2, "raw_modes/DC-GX850_ISO_2000_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-GX850", cam_dc_gx850_iso_2000_4fmt_4x3_rw2, "raw_modes/DC-GX850_ISO_2000_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-GX850", cam_dc_gx850_iso_2000_4fmt_16x9_rw2, "raw_modes/DC-GX850_ISO_2000_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DC-GX850", cam_dc_gx850_iso_2000_4fmt_3x2_rw2, "raw_modes/DC-GX850_ISO_2000_4fmt_3x2.RW2"); } mod camera_dc_gx880_raw_modes { super::camera_file_check!("Panasonic", "DC-GX880", cam_dc_gx880_iso_1250_4fmt_16x9_rw2, "raw_modes/DC-GX880_ISO_1250_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DC-GX880", cam_dc_gx880_iso_1250_4fmt_3x2_rw2, "raw_modes/DC-GX880_ISO_1250_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DC-GX880", cam_dc_gx880_iso_1250_4fmt_1x1_rw2, "raw_modes/DC-GX880_ISO_1250_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-GX880", cam_dc_gx880_iso_1250_4fmt_4x3_rw2, "raw_modes/DC-GX880_ISO_1250_4fmt_4x3.RW2"); } mod camera_dc_gx9_raw_modes { super::camera_file_check!("Panasonic", "DC-GX9", cam_dc_gx9_iso_200_4fmt_16x9_rw2, "raw_modes/DC-GX9_ISO_200_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DC-GX9", cam_dc_gx9_iso_200_4fmt_3x2_rw2, "raw_modes/DC-GX9_ISO_200_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DC-GX9", cam_dc_gx9_iso_200_4fmt_4x3_rw2, "raw_modes/DC-GX9_ISO_200_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-GX9", cam_dc_gx9_iso_200_4fmt_1x1_rw2, "raw_modes/DC-GX9_ISO_200_4fmt_1x1.RW2"); } mod camera_dc_lx100m2_raw_modes { super::camera_file_check!("Panasonic", "DC-LX100M2", cam_dc_lx100m2_iso_200_panasonic_raw_1_4928x3288_rw2, "raw_modes/DC-LX100M2_ISO_200_Panasonic RAW 1_4928x3288.RW2"); super::camera_file_check!("Panasonic", "DC-LX100M2", cam_dc_lx100m2_iso_200_panasonic_raw_1_3552x3552_rw2, "raw_modes/DC-LX100M2_ISO_200_Panasonic RAW 1_3552x3552.RW2"); super::camera_file_check!("Panasonic", "DC-LX100M2", cam_dc_lx100m2_iso_200_panasonic_raw_1_4736x3552_rw2, "raw_modes/DC-LX100M2_ISO_200_Panasonic RAW 1_4736x3552.RW2"); super::camera_file_check!("Panasonic", "DC-LX100M2", cam_dc_lx100m2_iso_200_panasonic_raw_1_5152x2904_rw2, "raw_modes/DC-LX100M2_ISO_200_Panasonic RAW 1_5152x2904.RW2"); } mod camera_dc_s1h_raw_modes { super::camera_file_check!("Panasonic", "DC-S1H", cam_dc_s1h_iso_100_6fmt_6000x4000_rw2, "raw_modes/DC-S1H_ISO_100_6fmt_6000x4000.RW2"); } mod camera_dc_s1_raw_modes { super::camera_file_check!("Panasonic", "DC-S1", cam_dc_s1_iso_800_6fmt_6000x4000_rw2, "raw_modes/DC-S1_ISO_800_6fmt_6000x4000.RW2"); } mod camera_dc_s1r_raw_modes { super::camera_file_check!("Panasonic", "DC-S1R", cam_dc_s1r_iso_100_6fmt_8368x5584_rw2, "raw_modes/DC-S1R_ISO_100_6fmt_8368x5584.RW2"); } mod camera_dc_s1rm2_raw_modes { super::camera_file_check!("Panasonic", "DC-S1RM2", cam_dc_s1rm2_2x1_rw2, "raw_modes/DC-S1RM2_2x1.RW2"); super::camera_file_check!("Panasonic", "DC-S1RM2", cam_dc_s1rm2_65x24_rw2, "raw_modes/DC-S1RM2_65x24.RW2"); super::camera_file_check!("Panasonic", "DC-S1RM2", cam_dc_s1rm2_12bit_burst_electronic_rw2, "raw_modes/DC-S1RM2_12bit_burst_electronic.RW2"); super::camera_file_check!("Panasonic", "DC-S1RM2", cam_dc_s1rm2_1x1_rw2, "raw_modes/DC-S1RM2_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-S1RM2", cam_dc_s1rm2_4x3_rw2, "raw_modes/DC-S1RM2_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-S1RM2", cam_dc_s1rm2_3x2_multi_exposure_rw2, "raw_modes/DC-S1RM2_3x2_multi_exposure.RW2"); super::camera_file_check!("Panasonic", "DC-S1RM2", cam_dc_s1rm2_3x2_eshutter_rw2, "raw_modes/DC-S1RM2_3x2_eshutter.RW2"); super::camera_file_check!("Panasonic", "DC-S1RM2", cam_dc_s1rm2_hires_standard_rw2, "raw_modes/DC-S1RM2_hires_standard.RW2"); super::camera_file_check!("Panasonic", "DC-S1RM2", cam_dc_s1rm2_live_composite_mode_rw2, "raw_modes/DC-S1RM2_live_composite_mode.RW2"); super::camera_file_check!("Panasonic", "DC-S1RM2", cam_dc_s1rm2_16x9_rw2, "raw_modes/DC-S1RM2_16x9.RW2"); } mod camera_dc_s5_raw_modes { super::camera_file_check!("Panasonic", "DC-S5", cam_dc_s5_iso_640_6fmt_6000x4000_rw2, "raw_modes/DC-S5_ISO_640_6fmt_6000x4000.RW2"); super::camera_file_check!("Panasonic", "DC-S5", cam_dc_s5_iso_640_7fmt_12000x8000_rw2, "raw_modes/DC-S5_ISO_640_7fmt_12000x8000.RW2"); } mod camera_dc_s5m2_raw_modes { super::camera_file_check!("Panasonic", "DC-S5M2", cam_dc_s5m2_3x2_rw2, "raw_modes/DC-S5M2_3x2.RW2"); } mod camera_dc_s5m2x_raw_modes { super::camera_file_check!("Panasonic", "DC-S5M2X", cam_dc_s5m2x_3x2_14bits_rw2, "raw_modes/DC-S5M2X_3x2_14bits.RW2"); super::camera_file_check!("Panasonic", "DC-S5M2X", cam_dc_s5m2x_3x2_sensorshift_96mp_rw2, "raw_modes/DC-S5M2X_3x2_sensorshift_96MP.RW2"); super::camera_file_check!("Panasonic", "DC-S5M2X", cam_dc_s5m2x_3x2_12bits_burst_rw2, "raw_modes/DC-S5M2X_3x2_12bits_burst.RW2"); } mod camera_dc_s9_raw_modes { super::camera_file_check!("Panasonic", "DC-S9", cam_dc_s9_iso6400_medium_rw2, "raw_modes/DC-S9_ISO6400_Medium.RW2"); super::camera_file_check!("Panasonic", "DC-S9", cam_dc_s9_iso400_hires_ll_rw2, "raw_modes/DC-S9_ISO400_HiRes-LL.RW2"); super::camera_file_check!("Panasonic", "DC-S9", cam_dc_s9_iso400_hires_xl_rw2, "raw_modes/DC-S9_ISO400_HiRes-XL.RW2"); super::camera_file_check!("Panasonic", "DC-S9", cam_dc_s9_iso800_rw2, "raw_modes/DC-S9_ISO800.RW2"); super::camera_file_check!("Panasonic", "DC-S9", cam_dc_s9_iso6400_rw2, "raw_modes/DC-S9_ISO6400.RW2"); super::camera_file_check!("Panasonic", "DC-S9", cam_dc_s9_iso800_medium_rw2, "raw_modes/DC-S9_ISO800_Medium.RW2"); super::camera_file_check!("Panasonic", "DC-S9", cam_dc_s9_iso400_medium_rw2, "raw_modes/DC-S9_ISO400_Medium.RW2"); super::camera_file_check!("Panasonic", "DC-S9", cam_dc_s9_iso100_rw2, "raw_modes/DC-S9_ISO100.RW2"); super::camera_file_check!("Panasonic", "DC-S9", cam_dc_s9_iso51200_medium_rw2, "raw_modes/DC-S9_ISO51200_Medium.RW2"); super::camera_file_check!("Panasonic", "DC-S9", cam_dc_s9_iso51200_rw2, "raw_modes/DC-S9_ISO51200.RW2"); super::camera_file_check!("Panasonic", "DC-S9", cam_dc_s9_iso100_medium_rw2, "raw_modes/DC-S9_ISO100_Medium.RW2"); } mod camera_dc_tz200_raw_modes { super::camera_file_check!("Panasonic", "DC-TZ200", cam_dc_tz202_iso_125_4fmt_1x1_rw2, "raw_modes/DC-TZ202_ISO_125_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-TZ200", cam_dc_tz202_iso_125_4fmt_4x3_rw2, "raw_modes/DC-TZ202_ISO_125_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-TZ200", cam_dc_tz202_iso_125_4fmt_16x9_rw2, "raw_modes/DC-TZ202_ISO_125_4fmt_16x9.RW2"); } mod camera_dc_tz202_raw_modes { super::camera_file_check!("Panasonic", "DC-TZ202", cam_dc_tz202_iso_200_4fmt_1x1_rw2, "raw_modes/DC-TZ202_ISO_200_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-TZ202", cam_dc_tz202_iso_200_4fmt_4x3_rw2, "raw_modes/DC-TZ202_ISO_200_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-TZ202", cam_dc_tz202_iso_200_4fmt_16x9_rw2, "raw_modes/DC-TZ202_ISO_200_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DC-TZ202", cam_dc_tz202_iso_200_4fmt_3x2_rw2, "raw_modes/DC-TZ202_ISO_200_4fmt_3x2.RW2"); } mod camera_dc_tz90_raw_modes { super::camera_file_check!("Panasonic", "DC-TZ90", cam_dc_tz90_iso_125_4fmt_5184x3888_rw2, "raw_modes/DC-TZ90_ISO_125_4fmt_5184x3888.RW2"); super::camera_file_check!("Panasonic", "DC-TZ90", cam_dc_tz90_iso_160_4fmt_5184x3888_rw2, "raw_modes/DC-TZ90_ISO_160_4fmt_5184x3888.RW2"); super::camera_file_check!("Panasonic", "DC-TZ90", cam_dc_tz90_iso_200_4fmt_5184x3888_rw2, "raw_modes/DC-TZ90_ISO_200_4fmt_5184x3888.RW2"); super::camera_file_check!("Panasonic", "DC-TZ90", cam_dc_tz90_iso_100_4fmt_5184x3888_rw2, "raw_modes/DC-TZ90_ISO_100_4fmt_5184x3888.RW2"); } mod camera_dc_tz91_raw_modes { super::camera_file_check!("Panasonic", "DC-TZ91", cam_dc_tz91_iso_80_4fmt_5184x3888_rw2, "raw_modes/DC-TZ91_ISO_80_4fmt_5184x3888.RW2"); } mod camera_dc_tz95_raw_modes { super::camera_file_check!("Panasonic", "DC-TZ95", cam_dc_tz95_iso_80_panasonic_raw_1_5184x3888_rw2, "raw_modes/DC-TZ95_ISO_80_Panasonic RAW 1_5184x3888.RW2"); } mod camera_dc_tz96_raw_modes { super::camera_file_check!("Panasonic", "DC-TZ96", cam_dc_tz96_iso_80_4fmt_1x1_rw2, "raw_modes/DC-TZ96_ISO_80_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DC-TZ96", cam_dc_tz96_iso_80_4fmt_4x3_rw2, "raw_modes/DC-TZ96_ISO_80_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DC-TZ96", cam_dc_tz96_iso_80_4fmt_16x9_rw2, "raw_modes/DC-TZ96_ISO_80_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DC-TZ96", cam_dc_tz96_iso_80_4fmt_3x2_rw2, "raw_modes/DC-TZ96_ISO_80_4fmt_3x2.RW2"); } mod camera_dc_tz220d_raw_modes { super::camera_file_check!("Panasonic", "DC-TZ220D", cam_panasonic_dc_tz220d_iso100_3x2_1_rw2, "raw_modes/panasonic_dc-tz220d_iso100_3x2_1.RW2"); super::camera_file_check!("Panasonic", "DC-TZ220D", cam_panasonic_dc_tz220d_iso100_16x9_2_rw2, "raw_modes/panasonic_dc-tz220d_iso100_16x9_2.RW2"); super::camera_file_check!("Panasonic", "DC-TZ220D", cam_panasonic_dc_tz220d_iso100_4x3_2_rw2, "raw_modes/panasonic_dc-tz220d_iso100_4x3_2.RW2"); super::camera_file_check!("Panasonic", "DC-TZ220D", cam_panasonic_dc_tz220d_iso100_1x1_2_rw2, "raw_modes/panasonic_dc-tz220d_iso100_1x1_2.RW2"); super::camera_file_check!("Panasonic", "DC-TZ220D", cam_panasonic_dc_tz220d_iso100_1x1_1_rw2, "raw_modes/panasonic_dc-tz220d_iso100_1x1_1.RW2"); super::camera_file_check!("Panasonic", "DC-TZ220D", cam_panasonic_dc_tz220d_iso100_16x9_1_rw2, "raw_modes/panasonic_dc-tz220d_iso100_16x9_1.RW2"); super::camera_file_check!("Panasonic", "DC-TZ220D", cam_panasonic_dc_tz220d_iso100_4x3_1_rw2, "raw_modes/panasonic_dc-tz220d_iso100_4x3_1.RW2"); super::camera_file_check!("Panasonic", "DC-TZ220D", cam_panasonic_dc_tz220d_iso100_3x2_2_rw2, "raw_modes/panasonic_dc-tz220d_iso100_3x2_2.RW2"); } mod camera_dmc_cm1_raw_modes { super::camera_file_check!("Panasonic", "DMC-CM1", cam_dmc_cm1_iso_125_panasonic_raw_1_5472x3648_rw2, "raw_modes/DMC-CM1_ISO_125_Panasonic RAW 1_5472x3648.RW2"); super::camera_file_check!("Panasonic", "DMC-CM1", cam_dmc_cm1_iso_125_panasonic_raw_1_3648x3648_rw2, "raw_modes/DMC-CM1_ISO_125_Panasonic RAW 1_3648x3648.RW2"); super::camera_file_check!("Panasonic", "DMC-CM1", cam_dmc_cm1_iso_125_panasonic_raw_1_5472x3080_rw2, "raw_modes/DMC-CM1_ISO_125_Panasonic RAW 1_5472x3080.RW2"); super::camera_file_check!("Panasonic", "DMC-CM1", cam_dmc_cm1_iso_125_panasonic_raw_1_4864x3648_rw2, "raw_modes/DMC-CM1_ISO_125_Panasonic RAW 1_4864x3648.RW2"); } mod camera_dmc_fx150_raw_modes { super::camera_file_check!("Panasonic", "DMC-FX150", cam_dmc_fx150_3x2_rw2, "raw_modes/DMC-FX150_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-FX150", cam_dmc_fx150_4x3_rw2, "raw_modes/DMC-FX150_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-FX150", cam_dmc_fx150_16x9_rw2, "raw_modes/DMC-FX150_16x9.RW2"); } mod camera_dmc_fz1000_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ1000", cam_dmc_fz1000_iso_640_4fmt_5472x3648_rw2, "raw_modes/DMC-FZ1000_ISO_640_4fmt_5472x3648.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ1000", cam_dmc_fz1000_iso_800_4fmt_3648x3648_rw2, "raw_modes/DMC-FZ1000_ISO_800_4fmt_3648x3648.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ1000", cam_dmc_fz1000_iso_640_4fmt_4864x3648_rw2, "raw_modes/DMC-FZ1000_ISO_640_4fmt_4864x3648.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ1000", cam_dmc_fz1000_iso_640_4fmt_5472x3080_rw2, "raw_modes/DMC-FZ1000_ISO_640_4fmt_5472x3080.RW2"); } mod camera_dmc_fz100_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ100", cam_dmc_fz100_iso_320_panasonic_raw_1_4320x2880_rw2, "raw_modes/DMC-FZ100_ISO_320_Panasonic RAW 1_4320x2880.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ100", cam_dmc_fz100_iso_800_panasonic_raw_1_4320x2432_rw2, "raw_modes/DMC-FZ100_ISO_800_Panasonic RAW 1_4320x2432.RW2"); } mod camera_dmc_fz150_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ150", cam_dmc_fz150_iso_100_panasonic_raw_1_4000x2248_rw2, "raw_modes/DMC-FZ150_ISO_100_Panasonic RAW 1_4000x2248.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ150", cam_dmc_fz150_iso_100_panasonic_raw_1_4000x3000_rw2, "raw_modes/DMC-FZ150_ISO_100_Panasonic RAW 1_4000x3000.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ150", cam_dmc_fz150_iso_100_panasonic_raw_1_4000x2672_rw2, "raw_modes/DMC-FZ150_ISO_100_Panasonic RAW 1_4000x2672.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ150", cam_dmc_fz150_iso_100_panasonic_raw_1_2992x2992_rw2, "raw_modes/DMC-FZ150_ISO_100_Panasonic RAW 1_2992x2992.RW2"); } mod camera_dmc_fz18_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ18", cam_dmc_fz18_iso_100_2fmt_3264x2448_raw, "raw_modes/DMC-FZ18_ISO_100_2fmt_3264x2448.RAW"); } mod camera_dmc_fz2000_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ2000", cam_dmc_fz2000_iso_80_4fmt_3x2_rw2, "raw_modes/DMC-FZ2000_ISO_80_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ2000", cam_dmc_fz2000_iso_80_4fmt_16x9_rw2, "raw_modes/DMC-FZ2000_ISO_80_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ2000", cam_dmc_fz2000_iso_80_4fmt_4x3_rw2, "raw_modes/DMC-FZ2000_ISO_80_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ2000", cam_dmc_fz2000_iso_80_4fmt_1x1_rw2, "raw_modes/DMC-FZ2000_ISO_80_4fmt_1x1.RW2"); } mod camera_dmc_fz200_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ200", cam_dmc_fz200_iso_100_4fmt_2992x2992_rw2, "raw_modes/DMC-FZ200_ISO_100_4fmt_2992x2992.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ200", cam_dmc_fz200_iso_100_4fmt_4000x3000_rw2, "raw_modes/DMC-FZ200_ISO_100_4fmt_4000x3000.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ200", cam_dmc_fz200_iso_100_4fmt_4000x2672_rw2, "raw_modes/DMC-FZ200_ISO_100_4fmt_4000x2672.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ200", cam_dmc_fz200_iso_100_4fmt_4000x2248_rw2, "raw_modes/DMC-FZ200_ISO_100_4fmt_4000x2248.RW2"); } mod camera_dmc_fz2500_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ2500", cam_dmc_fz2500_iso_125_4fmt_1x1_rw2, "raw_modes/DMC-FZ2500_ISO_125_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ2500", cam_dmc_fz2500_iso_125_4fmt_16x9_rw2, "raw_modes/DMC-FZ2500_ISO_125_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ2500", cam_dmc_fz2500_iso_125_4fmt_4x3_rw2, "raw_modes/DMC-FZ2500_ISO_125_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ2500", cam_dmc_fz2500_iso_125_4fmt_3x2_rw2, "raw_modes/DMC-FZ2500_ISO_125_4fmt_3x2.RW2"); } mod camera_dmc_fz28_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ28", cam_dmc_fz28_iso_400_4fmt_3648x2056_rw2, "raw_modes/DMC-FZ28_ISO_400_4fmt_3648x2056.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ28", cam_dmc_fz28_iso_100_4fmt_3648x2736_rw2, "raw_modes/DMC-FZ28_ISO_100_4fmt_3648x2736.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ28", cam_dmc_fz28_iso_400_4fmt_3648x2432_rw2, "raw_modes/DMC-FZ28_ISO_400_4fmt_3648x2432.RW2"); } mod camera_dmc_fz300_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ300", cam_dmc_fz300_iso_100_4fmt_3x2_rw2, "raw_modes/DMC-FZ300_ISO_100_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ300", cam_dmc_fz300_iso_100_4fmt_4x2_rw2, "raw_modes/DMC-FZ300_ISO_100_4fmt_4x2.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ300", cam_dmc_fz300_iso_100_4fmt_16x9_rw2, "raw_modes/DMC-FZ300_ISO_100_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ300", cam_dmc_fz300_iso_100_4fmt_1x1_rw2, "raw_modes/DMC-FZ300_ISO_100_4fmt_1x1.RW2"); } mod camera_dmc_fz30_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ30", cam_dmc_fz30_iso_80_panasonic_raw_3_3264x2448_raw, "raw_modes/DMC-FZ30_ISO_80_Panasonic RAW 3_3264x2448.RAW"); } mod camera_dmc_fz330_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ330", cam_dmc_fz330_iso_100_4fmt_16x9_rw2, "raw_modes/DMC-FZ330_ISO_100_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ330", cam_dmc_fz330_iso_100_4fmt_3x2_rw2, "raw_modes/DMC-FZ330_ISO_100_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ330", cam_dmc_fz330_iso_100_4fmt_4x3_rw2, "raw_modes/DMC-FZ330_ISO_100_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ330", cam_dmc_fz330_iso_100_4fmt_1x1_rw2, "raw_modes/DMC-FZ330_ISO_100_4fmt_1x1.RW2"); } mod camera_dmc_fz35_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ35", cam_dmc_fz35_iso_80_panasonic_raw_1_4000x2672_rw2, "raw_modes/DMC-FZ35_ISO_80_Panasonic RAW 1_4000x2672.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ35", cam_dmc_fz35_iso_80_panasonic_raw_1_4000x3000_rw2, "raw_modes/DMC-FZ35_ISO_80_Panasonic RAW 1_4000x3000.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ35", cam_dmc_fz35_iso_80_panasonic_raw_1_4000x2248_rw2, "raw_modes/DMC-FZ35_ISO_80_Panasonic RAW 1_4000x2248.RW2"); } mod camera_dmc_fz38_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ38", cam_dmc_fz38_iso_80_panasonic_raw_1_4000x3000_rw2, "raw_modes/DMC-FZ38_ISO_80_Panasonic RAW 1_4000x3000.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ38", cam_dmc_fz38_iso_80_panasonic_raw_1_4000x2672_rw2, "raw_modes/DMC-FZ38_ISO_80_Panasonic RAW 1_4000x2672.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ38", cam_dmc_fz38_iso_80_panasonic_raw_1_4000x2248_rw2, "raw_modes/DMC-FZ38_ISO_80_Panasonic RAW 1_4000x2248.RW2"); } mod camera_dmc_fz45_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ45", cam_dmc_fz45_iso_500_panasonic_raw_1_4320x2436_rw2, "raw_modes/DMC-FZ45_ISO_500_Panasonic RAW 1_4320x2436.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ45", cam_dmc_fz45_iso_500_panasonic_raw_1_3232x3234_rw2, "raw_modes/DMC-FZ45_ISO_500_Panasonic RAW 1_3232x3234.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ45", cam_dmc_fz45_iso_400_panasonic_raw_1_4320x3240_rw2, "raw_modes/DMC-FZ45_ISO_400_Panasonic RAW 1_4320x3240.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ45", cam_dmc_fz45_iso_500_panasonic_raw_1_4320x2880_rw2, "raw_modes/DMC-FZ45_ISO_500_Panasonic RAW 1_4320x2880.RW2"); } mod camera_dmc_fz50_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ50", cam_dmc_fz50_iso_100_panasonic_raw_3_3648x2424_raw, "raw_modes/DMC-FZ50_ISO_100_Panasonic RAW 3_3648x2424.RAW"); super::camera_file_check!("Panasonic", "DMC-FZ50", cam_dmc_fz50_iso_100_panasonic_raw_3_3648x2052_raw, "raw_modes/DMC-FZ50_ISO_100_Panasonic RAW 3_3648x2052.RAW"); super::camera_file_check!("Panasonic", "DMC-FZ50", cam_dmc_fz50_iso_100_panasonic_raw_3_3648x2736_raw, "raw_modes/DMC-FZ50_ISO_100_Panasonic RAW 3_3648x2736.RAW"); } mod camera_dmc_fz70_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ70", cam_dmc_fz70_iso_100_panasonic_raw_1_4608x3456_rw2, "raw_modes/DMC-FZ70_ISO_100_Panasonic RAW 1_4608x3456.RW2"); } mod camera_dmc_fz72_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ72", cam_dmc_fz72_iso_200_4fmt_4608x3456_rw2, "raw_modes/DMC-FZ72_ISO_200_4fmt_4608x3456.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ72", cam_dmc_fz72_iso_100_4fmt_4608x3072_rw2, "raw_modes/DMC-FZ72_ISO_100_4fmt_4608x3072.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ72", cam_dmc_fz72_iso_100_4fmt_3456x3456_rw2, "raw_modes/DMC-FZ72_ISO_100_4fmt_3456x3456.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ72", cam_dmc_fz72_iso_100_4fmt_4608x2592_rw2, "raw_modes/DMC-FZ72_ISO_100_4fmt_4608x2592.RW2"); super::camera_file_check!("Panasonic", "DMC-FZ72", cam_dmc_fz72_iso_100_4fmt_4608x3456_rw2, "raw_modes/DMC-FZ72_ISO_100_4fmt_4608x3456.RW2"); } mod camera_dmc_fz8_raw_modes { super::camera_file_check!("Panasonic", "DMC-FZ8", cam_dmc_fz8_iso_100_panasonic_raw_1_3072x2304_raw, "raw_modes/DMC-FZ8_ISO_100_Panasonic RAW 1_3072x2304.RAW"); } mod camera_dmc_g10_raw_modes { super::camera_file_check!("Panasonic", "DMC-G10", cam_dmc_g10_iso_200_panasonic_raw_1_4000x2672_rw2, "raw_modes/DMC-G10_ISO_200_Panasonic RAW 1_4000x2672.RW2"); super::camera_file_check!("Panasonic", "DMC-G10", cam_dmc_g10_iso_200_panasonic_raw_1_4000x3000_rw2, "raw_modes/DMC-G10_ISO_200_Panasonic RAW 1_4000x3000.RW2"); super::camera_file_check!("Panasonic", "DMC-G10", cam_dmc_g10_iso_200_panasonic_raw_1_2992x2992_rw2, "raw_modes/DMC-G10_ISO_200_Panasonic RAW 1_2992x2992.RW2"); super::camera_file_check!("Panasonic", "DMC-G10", cam_dmc_g10_iso_200_panasonic_raw_1_4000x2248_rw2, "raw_modes/DMC-G10_ISO_200_Panasonic RAW 1_4000x2248.RW2"); } mod camera_dmc_g1_raw_modes { super::camera_file_check!("Panasonic", "DMC-G1", cam_dmc_g1_iso_100_panasonic_raw_1_4000x3000_rw2, "raw_modes/DMC-G1_ISO_100_Panasonic RAW 1_4000x3000.RW2"); } mod camera_dmc_g2_raw_modes { super::camera_file_check!("Panasonic", "DMC-G2", cam_dmc_g2_iso_400_4fmt_19x9_rw2, "raw_modes/DMC-G2_ISO_400_4fmt_19x9.RW2"); } mod camera_dmc_g3_raw_modes { super::camera_file_check!("Panasonic", "DMC-G3", cam_dmc_g3_iso_640_panasonic_raw_1_4576x2576_rw2, "raw_modes/DMC-G3_ISO_640_Panasonic RAW 1_4576x2576.RW2"); super::camera_file_check!("Panasonic", "DMC-G3", cam_dmc_g3_iso_640_panasonic_raw_1_4576x3056_rw2, "raw_modes/DMC-G3_ISO_640_Panasonic RAW 1_4576x3056.RW2"); super::camera_file_check!("Panasonic", "DMC-G3", cam_dmc_g3_iso_640_panasonic_raw_1_3424x3424_rw2, "raw_modes/DMC-G3_ISO_640_Panasonic RAW 1_3424x3424.RW2"); super::camera_file_check!("Panasonic", "DMC-G3", cam_dmc_g3_iso_640_panasonic_raw_1_4592x3448_rw2, "raw_modes/DMC-G3_ISO_640_Panasonic RAW 1_4592x3448.RW2"); } mod camera_dmc_g5_raw_modes { super::camera_file_check!("Panasonic", "DMC-G5", cam_dmc_g5_iso_160_panasonic_raw_1_4608x3456_rw2, "raw_modes/DMC-G5_ISO_160_Panasonic RAW 1_4608x3456.RW2"); } mod camera_dmc_g6_raw_modes { super::camera_file_check!("Panasonic", "DMC-G6", cam_dmc_g6_iso_160_panasonic_raw_1_3456x3456_rw2, "raw_modes/DMC-G6_ISO_160_Panasonic RAW 1_3456x3456.RW2"); super::camera_file_check!("Panasonic", "DMC-G6", cam_dmc_g6_iso_160_panasonic_raw_1_4608x3072_rw2, "raw_modes/DMC-G6_ISO_160_Panasonic RAW 1_4608x3072.RW2"); super::camera_file_check!("Panasonic", "DMC-G6", cam_dmc_g6_iso_160_panasonic_raw_1_4608x3456_rw2, "raw_modes/DMC-G6_ISO_160_Panasonic RAW 1_4608x3456.RW2"); super::camera_file_check!("Panasonic", "DMC-G6", cam_dmc_g6_iso_160_panasonic_raw_1_4608x2592_rw2, "raw_modes/DMC-G6_ISO_160_Panasonic RAW 1_4608x2592.RW2"); } mod camera_dmc_g70_raw_modes { super::camera_file_check!("Panasonic", "DMC-G70", cam_dmc_g70_iso_100_4fmt_4592x3448_rw2, "raw_modes/DMC-G70_ISO_100_4fmt_4592x3448.RW2"); } mod camera_dmc_g7_raw_modes { super::camera_file_check!("Panasonic", "DMC-G7", cam_dmc_g7_iso_200_4fmt_4x3_gbrg_rw2, "raw_modes/DMC-G7_ISO_200_4fmt_4x3_GBRG.RW2"); super::camera_file_check!("Panasonic", "DMC-G7", cam_dmc_g7_iso_200_4fmt_4x3_bggr_rw2, "raw_modes/DMC-G7_ISO_200_4fmt_4x3_BGGR.RW2"); super::camera_file_check!("Panasonic", "DMC-G7", cam_dmc_g7_iso_200_4fmt_16x9_rw2, "raw_modes/DMC-G7_ISO_200_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-G7", cam_dmc_g7_iso_200_4fmt_1x1_rw2, "raw_modes/DMC-G7_ISO_200_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-G7", cam_dmc_g7_iso_200_4fmt_4x3_rw2, "raw_modes/DMC-G7_ISO_200_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-G7", cam_dmc_g7_iso_200_4fmt_3x2_rw2, "raw_modes/DMC-G7_ISO_200_4fmt_3x2.RW2"); } mod camera_dmc_g80_raw_modes { super::camera_file_check!("Panasonic", "DMC-G80", cam_dmc_g80_iso_200_4fmt_1x1_rw2, "raw_modes/DMC-G80_ISO_200_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-G80", cam_dmc_g80_iso_200_4fmt_16x9_rw2, "raw_modes/DMC-G80_ISO_200_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-G80", cam_dmc_g80_iso_200_4fmt_3x2_rw2, "raw_modes/DMC-G80_ISO_200_4fmt_3x2.RW2"); } mod camera_dmc_g81_raw_modes { super::camera_file_check!("Panasonic", "DMC-G81", cam_dmc_g81_iso_400_4fmt_3x2_rw2, "raw_modes/DMC-G81_ISO_400_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-G81", cam_dmc_g81_iso_500_4fmt_16x9_rw2, "raw_modes/DMC-G81_ISO_500_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-G81", cam_dmc_g81_iso_400_4fmt_4x3_rw2, "raw_modes/DMC-G81_ISO_400_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-G81", cam_dmc_g81_iso_400_4fmt_1x1_rw2, "raw_modes/DMC-G81_ISO_400_4fmt_1x1.RW2"); } mod camera_dmc_g85_raw_modes { super::camera_file_check!("Panasonic", "DMC-G85", cam_dmc_g85_iso_320_4fmt_1x1_rw2, "raw_modes/DMC-G85_ISO_320_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-G85", cam_dmc_g85_iso_320_4fmt_16x9_rw2, "raw_modes/DMC-G85_ISO_320_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-G85", cam_dmc_g85_iso_320_4fmt_3x2_rw2, "raw_modes/DMC-G85_ISO_320_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-G85", cam_dmc_g85_iso_250_4fmt_4x3_rw2, "raw_modes/DMC-G85_ISO_250_4fmt_4x3.RW2"); } mod camera_dmc_gf1_raw_modes { super::camera_file_check!("Panasonic", "DMC-GF1", cam_dmc_gf1_iso_100_panasonic_raw_1_4000x2248_rw2, "raw_modes/DMC-GF1_ISO_100_Panasonic RAW 1_4000x2248.RW2"); super::camera_file_check!("Panasonic", "DMC-GF1", cam_dmc_gf1_iso_100_panasonic_raw_1_2992x2992_rw2, "raw_modes/DMC-GF1_ISO_100_Panasonic RAW 1_2992x2992.RW2"); super::camera_file_check!("Panasonic", "DMC-GF1", cam_dmc_gf1_iso_100_panasonic_raw_1_4000x2672_rw2, "raw_modes/DMC-GF1_ISO_100_Panasonic RAW 1_4000x2672.RW2"); super::camera_file_check!("Panasonic", "DMC-GF1", cam_dmc_gf1_iso_100_panasonic_raw_1_4000x3000_rw2, "raw_modes/DMC-GF1_ISO_100_Panasonic RAW 1_4000x3000.RW2"); } mod camera_dmc_gf2_raw_modes { super::camera_file_check!("Panasonic", "DMC-GF2", cam_dmc_gf2_iso_100_panasonic_raw_1_4000x2248_rw2, "raw_modes/DMC-GF2_ISO_100_Panasonic RAW 1_4000x2248.RW2"); super::camera_file_check!("Panasonic", "DMC-GF2", cam_dmc_gf2_iso_100_panasonic_raw_1_2992x2992_rw2, "raw_modes/DMC-GF2_ISO_100_Panasonic RAW 1_2992x2992.RW2"); super::camera_file_check!("Panasonic", "DMC-GF2", cam_dmc_gf2_iso_100_panasonic_raw_1_4000x3000_rw2, "raw_modes/DMC-GF2_ISO_100_Panasonic RAW 1_4000x3000.RW2"); super::camera_file_check!("Panasonic", "DMC-GF2", cam_dmc_gf2_iso_100_panasonic_raw_1_4000x2672_rw2, "raw_modes/DMC-GF2_ISO_100_Panasonic RAW 1_4000x2672.RW2"); } mod camera_dmc_gf3_raw_modes { super::camera_file_check!("Panasonic", "DMC-GF3", cam_dmc_gf3_iso_160_panasonic_raw_1_4000x2248_rw2, "raw_modes/DMC-GF3_ISO_160_Panasonic RAW 1_4000x2248.RW2"); super::camera_file_check!("Panasonic", "DMC-GF3", cam_dmc_gf3_iso_160_panasonic_raw_1_4000x3000_rw2, "raw_modes/DMC-GF3_ISO_160_Panasonic RAW 1_4000x3000.RW2"); super::camera_file_check!("Panasonic", "DMC-GF3", cam_dmc_gf3_iso_160_panasonic_raw_1_4000x2672_rw2, "raw_modes/DMC-GF3_ISO_160_Panasonic RAW 1_4000x2672.RW2"); super::camera_file_check!("Panasonic", "DMC-GF3", cam_dmc_gf3_iso_160_panasonic_raw_1_2992x2992_rw2, "raw_modes/DMC-GF3_ISO_160_Panasonic RAW 1_2992x2992.RW2"); } mod camera_dmc_gf5_raw_modes { super::camera_file_check!("Panasonic", "DMC-GF5", cam_dmc_gf5_iso_160_panasonic_raw_1_4000x3000_rw2, "raw_modes/DMC-GF5_ISO_160_Panasonic RAW 1_4000x3000.RW2"); super::camera_file_check!("Panasonic", "DMC-GF5", cam_dmc_gf5_iso_160_panasonic_raw_1_4000x2672_rw2, "raw_modes/DMC-GF5_ISO_160_Panasonic RAW 1_4000x2672.RW2"); super::camera_file_check!("Panasonic", "DMC-GF5", cam_dmc_gf5_iso_160_panasonic_raw_1_2992x2992_rw2, "raw_modes/DMC-GF5_ISO_160_Panasonic RAW 1_2992x2992.RW2"); super::camera_file_check!("Panasonic", "DMC-GF5", cam_dmc_gf5_iso_160_panasonic_raw_1_4000x2248_rw2, "raw_modes/DMC-GF5_ISO_160_Panasonic RAW 1_4000x2248.RW2"); } mod camera_dmc_gf6_raw_modes { super::camera_file_check!("Panasonic", "DMC-GF6", cam_dmc_gf6_iso_160_panasonic_raw_1_4592x2584_rw2, "raw_modes/DMC-GF6_ISO_160_Panasonic RAW 1_4592x2584.RW2"); super::camera_file_check!("Panasonic", "DMC-GF6", cam_dmc_gf6_iso_160_panasonic_raw_1_3424x3424_rw2, "raw_modes/DMC-GF6_ISO_160_Panasonic RAW 1_3424x3424.RW2"); super::camera_file_check!("Panasonic", "DMC-GF6", cam_dmc_gf6_iso_160_panasonic_raw_1_4592x3448_rw2, "raw_modes/DMC-GF6_ISO_160_Panasonic RAW 1_4592x3448.RW2"); super::camera_file_check!("Panasonic", "DMC-GF6", cam_dmc_gf6_iso_160_panasonic_raw_1_4592x3064_rw2, "raw_modes/DMC-GF6_ISO_160_Panasonic RAW 1_4592x3064.RW2"); } mod camera_dmc_gf7_raw_modes { super::camera_file_check!("Panasonic", "DMC-GF7", cam_dmc_gf7_iso_200_panasonic_raw_1_4592x3064_rw2, "raw_modes/DMC-GF7_ISO_200_Panasonic RAW 1_4592x3064.RW2"); super::camera_file_check!("Panasonic", "DMC-GF7", cam_dmc_gf7_iso_200_panasonic_raw_1_3424x3424_rw2, "raw_modes/DMC-GF7_ISO_200_Panasonic RAW 1_3424x3424.RW2"); super::camera_file_check!("Panasonic", "DMC-GF7", cam_dmc_gf7_iso_200_panasonic_raw_1_4592x3448_rw2, "raw_modes/DMC-GF7_ISO_200_Panasonic RAW 1_4592x3448.RW2"); super::camera_file_check!("Panasonic", "DMC-GF7", cam_dmc_gf7_iso_200_panasonic_raw_1_4592x2584_rw2, "raw_modes/DMC-GF7_ISO_200_Panasonic RAW 1_4592x2584.RW2"); } mod camera_dmc_gf8_raw_modes { super::camera_file_check!("Panasonic", "DMC-GF8", cam_dmc_gf8_iso_200_4fmt_4592x3064_rw2, "raw_modes/DMC-GF8_ISO_200_4fmt_4592x3064.RW2"); super::camera_file_check!("Panasonic", "DMC-GF8", cam_dmc_gf8_iso_200_4fmt_4592x2584_rw2, "raw_modes/DMC-GF8_ISO_200_4fmt_4592x2584.RW2"); super::camera_file_check!("Panasonic", "DMC-GF8", cam_dmc_gf8_iso_200_4fmt_4592x3448_rw2, "raw_modes/DMC-GF8_ISO_200_4fmt_4592x3448.RW2"); super::camera_file_check!("Panasonic", "DMC-GF8", cam_dmc_gf8_iso_200_4fmt_3424x3424_rw2, "raw_modes/DMC-GF8_ISO_200_4fmt_3424x3424.RW2"); } mod camera_dmc_gh1_raw_modes { super::camera_file_check!("Panasonic", "DMC-GH1", cam_dmc_gh1_iso_100_panasonic_raw_1_4352x2448_rw2, "raw_modes/DMC-GH1_ISO_100_Panasonic RAW 1_4352x2448.RW2"); super::camera_file_check!("Panasonic", "DMC-GH1", cam_dmc_gh1_iso_100_panasonic_raw_1_4128x2752_rw2, "raw_modes/DMC-GH1_ISO_100_Panasonic RAW 1_4128x2752.RW2"); super::camera_file_check!("Panasonic", "DMC-GH1", cam_dmc_gh1_iso_100_panasonic_raw_1_4000x3000_rw2, "raw_modes/DMC-GH1_ISO_100_Panasonic RAW 1_4000x3000.RW2"); super::camera_file_check!("Panasonic", "DMC-GH1", cam_dmc_gh1_iso_100_panasonic_raw_1_2992x2992_rw2, "raw_modes/DMC-GH1_ISO_100_Panasonic RAW 1_2992x2992.RW2"); } mod camera_dmc_gh2_raw_modes { super::camera_file_check!("Panasonic", "DMC-GH2", cam_dmc_gh2_iso_160_panasonic_raw_1_4608x3456_rw2, "raw_modes/DMC-GH2_ISO_160_Panasonic RAW 1_4608x3456.RW2"); } mod camera_dmc_gh3_raw_modes { super::camera_file_check!("Panasonic", "DMC-GH3", cam_dmc_gh3_iso_400_panasonic_raw_1_4608x2592_rw2, "raw_modes/DMC-GH3_ISO_400_Panasonic RAW 1_4608x2592.RW2"); super::camera_file_check!("Panasonic", "DMC-GH3", cam_dmc_gh3_iso_400_panasonic_raw_1_4608x3456_rw2, "raw_modes/DMC-GH3_ISO_400_Panasonic RAW 1_4608x3456.RW2"); super::camera_file_check!("Panasonic", "DMC-GH3", cam_dmc_gh3_iso_400_panasonic_raw_1_4608x3072_rw2, "raw_modes/DMC-GH3_ISO_400_Panasonic RAW 1_4608x3072.RW2"); super::camera_file_check!("Panasonic", "DMC-GH3", cam_dmc_gh3_iso_400_panasonic_raw_1_3456x3456_rw2, "raw_modes/DMC-GH3_ISO_400_Panasonic RAW 1_3456x3456.RW2"); } mod camera_dmc_gh4_raw_modes { super::camera_file_check!("Panasonic", "DMC-GH4", cam_dmc_gh4_iso_400_panasonic_raw_1_3456x3456_rw2, "raw_modes/DMC-GH4_ISO_400_Panasonic RAW 1_3456x3456.RW2"); super::camera_file_check!("Panasonic", "DMC-GH4", cam_dmc_gh4_iso_400_panasonic_raw_1_4608x3072_rw2, "raw_modes/DMC-GH4_ISO_400_Panasonic RAW 1_4608x3072.RW2"); super::camera_file_check!("Panasonic", "DMC-GH4", cam_dmc_gh4_iso_400_panasonic_raw_1_4608x3456_rw2, "raw_modes/DMC-GH4_ISO_400_Panasonic RAW 1_4608x3456.RW2"); super::camera_file_check!("Panasonic", "DMC-GH4", cam_dmc_gh4_iso_400_panasonic_raw_1_4608x2592_rw2, "raw_modes/DMC-GH4_ISO_400_Panasonic RAW 1_4608x2592.RW2"); } mod camera_dmc_gm1_raw_modes { super::camera_file_check!("Panasonic", "DMC-GM1", cam_dmc_gm1_iso_200_4fmt_4592x3064_rw2, "raw_modes/DMC-GM1_ISO_200_4fmt_4592x3064.RW2"); super::camera_file_check!("Panasonic", "DMC-GM1", cam_dmc_gm1_iso_200_4fmt_3424x3424_rw2, "raw_modes/DMC-GM1_ISO_200_4fmt_3424x3424.RW2"); super::camera_file_check!("Panasonic", "DMC-GM1", cam_dmc_gm1_iso_200_4fmt_4592x3448_rw2, "raw_modes/DMC-GM1_ISO_200_4fmt_4592x3448.RW2"); super::camera_file_check!("Panasonic", "DMC-GM1", cam_dmc_gm1_iso_200_4fmt_4592x2584_rw2, "raw_modes/DMC-GM1_ISO_200_4fmt_4592x2584.RW2"); } mod camera_dmc_gm1s_raw_modes { super::camera_file_check!("Panasonic", "DMC-GM1S", cam_dmc_gm1s_iso_200_panasonic_raw_1_4592x3448_rw2, "raw_modes/DMC-GM1S_ISO_200_Panasonic RAW 1_4592x3448.RW2"); } mod camera_dmc_gm5_raw_modes { super::camera_file_check!("Panasonic", "DMC-GM5", cam_dmc_gm5_iso_400_panasonic_raw_1_4592x3064_rw2, "raw_modes/DMC-GM5_ISO_400_Panasonic RAW 1_4592x3064.RW2"); super::camera_file_check!("Panasonic", "DMC-GM5", cam_dmc_gm5_iso_400_panasonic_raw_1_3424x3424_rw2, "raw_modes/DMC-GM5_ISO_400_Panasonic RAW 1_3424x3424.RW2"); super::camera_file_check!("Panasonic", "DMC-GM5", cam_dmc_gm5_iso_400_panasonic_raw_1_4592x3448_rw2, "raw_modes/DMC-GM5_ISO_400_Panasonic RAW 1_4592x3448.RW2"); super::camera_file_check!("Panasonic", "DMC-GM5", cam_dmc_gm5_iso_400_panasonic_raw_1_4592x2584_rw2, "raw_modes/DMC-GM5_ISO_400_Panasonic RAW 1_4592x2584.RW2"); } mod camera_dmc_gx1_raw_modes { super::camera_file_check!("Panasonic", "DMC-GX1", cam_dmc_gx1_iso_320_panasonic_raw_1_4576x3056_rw2, "raw_modes/DMC-GX1_ISO_320_Panasonic RAW 1_4576x3056.RW2"); } mod camera_dmc_gx7mk2_raw_modes { super::camera_file_check!("Panasonic", "DMC-GX7MK2", cam_dmc_gx7mk2_iso_2500_4fmt_16x9_rw2, "raw_modes/DMC-GX7MK2_ISO_2500_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-GX7MK2", cam_dmc_gx7mk2_iso_2500_4fmt_3x2_rw2, "raw_modes/DMC-GX7MK2_ISO_2500_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-GX7MK2", cam_dmc_gx7mk2_iso_2500_4fmt_1x1_rw2, "raw_modes/DMC-GX7MK2_ISO_2500_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-GX7MK2", cam_dmc_gx7mk2_iso_2500_4fmt_4x3_rw2, "raw_modes/DMC-GX7MK2_ISO_2500_4fmt_4x3.RW2"); } mod camera_dmc_gx7_raw_modes { super::camera_file_check!("Panasonic", "DMC-GX7", cam_dmc_gx7_iso_125_panasonic_raw_1_4592x2584_rw2, "raw_modes/DMC-GX7_ISO_125_Panasonic RAW 1_4592x2584.RW2"); super::camera_file_check!("Panasonic", "DMC-GX7", cam_dmc_gx7_iso_125_panasonic_raw_1_4592x3448_rw2, "raw_modes/DMC-GX7_ISO_125_Panasonic RAW 1_4592x3448.RW2"); super::camera_file_check!("Panasonic", "DMC-GX7", cam_dmc_gx7_iso_125_panasonic_raw_1_3424x3424_rw2, "raw_modes/DMC-GX7_ISO_125_Panasonic RAW 1_3424x3424.RW2"); super::camera_file_check!("Panasonic", "DMC-GX7", cam_dmc_gx7_iso_125_panasonic_raw_1_4592x3064_rw2, "raw_modes/DMC-GX7_ISO_125_Panasonic RAW 1_4592x3064.RW2"); } mod camera_dmc_gx80_raw_modes { super::camera_file_check!("Panasonic", "DMC-GX80", cam_dmc_gx80_iso_200_4fmt_16x9_rw2, "raw_modes/DMC-GX80_ISO_200_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-GX80", cam_dmc_gx80_iso_200_4fmt_4x3_rw2, "raw_modes/DMC-GX80_ISO_200_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-GX80", cam_dmc_gx80_iso_200_4fmt_1x1_rw2, "raw_modes/DMC-GX80_ISO_200_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-GX80", cam_dmc_gx80_iso_200_4fmt_3x2_rw2, "raw_modes/DMC-GX80_ISO_200_4fmt_3x2.RW2"); } mod camera_dmc_gx85_raw_modes { super::camera_file_check!("Panasonic", "DMC-GX85", cam_dmc_gx85_iso_200_4fmt_16x9_rw2, "raw_modes/DMC-GX85_ISO_200_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-GX85", cam_dmc_gx85_iso_200_4fmt_4x3_rw2, "raw_modes/DMC-GX85_ISO_200_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-GX85", cam_dmc_gx85_iso_200_4fmt_1x1_rw2, "raw_modes/DMC-GX85_ISO_200_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-GX85", cam_dmc_gx85_iso_200_4fmt_3x2_rw2, "raw_modes/DMC-GX85_ISO_200_4fmt_3x2.RW2"); } mod camera_dmc_gx8_raw_modes { super::camera_file_check!("Panasonic", "DMC-GX8", cam_dmc_gx8_iso_200_4fmt_16x9_rw2, "raw_modes/DMC-GX8_ISO_200_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-GX8", cam_dmc_gx8_iso_200_4fmt_3x2_rw2, "raw_modes/DMC-GX8_ISO_200_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-GX8", cam_dmc_gx8_iso_200_4fmt_1x1_rw2, "raw_modes/DMC-GX8_ISO_200_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-GX8", cam_dmc_gx8_iso_200_4fmt_4x3_rw2, "raw_modes/DMC-GX8_ISO_200_4fmt_4x3.RW2"); } mod camera_dmc_l10_raw_modes { super::camera_file_check!("Panasonic", "DMC-L10", cam_dmc_l10_iso_100_3fmt_3648x2736_raw, "raw_modes/DMC-L10_ISO_100_3fmt_3648x2736.RAW"); } mod camera_dmc_l1_raw_modes { super::camera_file_check!("Panasonic", "DMC-L1", cam_dmc_l1_iso_100_panasonic_raw_4_3136x2352_raw, "raw_modes/DMC-L1_ISO_100_Panasonic RAW 4_3136x2352.RAW"); } mod camera_dmc_lf1_raw_modes { super::camera_file_check!("Panasonic", "DMC-LF1", cam_dmc_lf1_iso_80_4fmt_4000x2672_rw2, "raw_modes/DMC-LF1_ISO_80_4fmt_4000x2672.RW2"); super::camera_file_check!("Panasonic", "DMC-LF1", cam_dmc_lf1_iso_80_4fmt_4000x3000_rw2, "raw_modes/DMC-LF1_ISO_80_4fmt_4000x3000.RW2"); } mod camera_dmc_lx100_raw_modes { super::camera_file_check!("Panasonic", "DMC-LX100", cam_dmc_lx100_iso_500_panasonic_raw_1_4272x2856_rw2, "raw_modes/DMC-LX100_ISO_500_Panasonic RAW 1_4272x2856.RW2"); super::camera_file_check!("Panasonic", "DMC-LX100", cam_dmc_lx100_iso_500_panasonic_raw_1_3088x3088_rw2, "raw_modes/DMC-LX100_ISO_500_Panasonic RAW 1_3088x3088.RW2"); super::camera_file_check!("Panasonic", "DMC-LX100", cam_dmc_lx100_iso_500_panasonic_raw_1_4112x3088_rw2, "raw_modes/DMC-LX100_ISO_500_Panasonic RAW 1_4112x3088.RW2"); super::camera_file_check!("Panasonic", "DMC-LX100", cam_dmc_lx100_iso_500_panasonic_raw_1_4480x2520_rw2, "raw_modes/DMC-LX100_ISO_500_Panasonic RAW 1_4480x2520.RW2"); } mod camera_dmc_lx10_raw_modes { super::camera_file_check!("Panasonic", "DMC-LX10", cam_dmc_lx10_iso_160_3x2_rw2, "raw_modes/DMC-LX10_ISO_160_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-LX10", cam_dmc_lx10_iso_160_1x1_rw2, "raw_modes/DMC-LX10_ISO_160_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-LX10", cam_dmc_lx10_iso_160_4x3_rw2, "raw_modes/DMC-LX10_ISO_160_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-LX10", cam_dmc_lx10_iso_160_16x9_rw2, "raw_modes/DMC-LX10_ISO_160_16x9.RW2"); } mod camera_dmc_lx15_raw_modes { super::camera_file_check!("Panasonic", "DMC-LX15", cam_dmc_lx15_iso_125_4fmt_16x9_rw2, "raw_modes/DMC-LX15_ISO_125_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-LX15", cam_dmc_lx15_iso_125_4fmt_3x2_rw2, "raw_modes/DMC-LX15_ISO_125_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-LX15", cam_dmc_lx15_iso_125_4fmt_1x1_rw2, "raw_modes/DMC-LX15_ISO_125_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-LX15", cam_dmc_lx15_iso_125_4fmt_4x3_rw2, "raw_modes/DMC-LX15_ISO_125_4fmt_4x3.RW2"); } mod camera_dmc_lx1_raw_modes { super::camera_file_check!("Panasonic", "DMC-LX1", cam_dmc_lx1_iso_100_panasonic_raw_3_3840x2160_raw, "raw_modes/DMC-LX1_ISO_100_Panasonic RAW 3_3840x2160.RAW"); } mod camera_dmc_lx2_raw_modes { super::camera_file_check!("Panasonic", "DMC-LX2", cam_dmc_lx2_iso_100_panasonic_raw_3_4224x2376_raw, "raw_modes/DMC-LX2_ISO_100_Panasonic RAW 3_4224x2376.RAW"); } mod camera_dmc_lx3_raw_modes { super::camera_file_check!("Panasonic", "DMC-LX3", cam_dmc_lx3_iso_400_4fmt_3968x2232_rw2, "raw_modes/DMC-LX3_ISO_400_4fmt_3968x2232.RW2"); super::camera_file_check!("Panasonic", "DMC-LX3", cam_dmc_lx3_iso_80_4fmt_2736x2736_rw2, "raw_modes/DMC-LX3_ISO_80_4fmt_2736x2736.RW2"); super::camera_file_check!("Panasonic", "DMC-LX3", cam_dmc_lx3_iso_400_4fmt_3648x2736_rw2, "raw_modes/DMC-LX3_ISO_400_4fmt_3648x2736.RW2"); super::camera_file_check!("Panasonic", "DMC-LX3", cam_dmc_lx3_iso_100_4fmt_3968x2232_rw2, "raw_modes/DMC-LX3_ISO_100_4fmt_3968x2232.RW2"); } mod camera_dmc_lx5_raw_modes { super::camera_file_check!("Panasonic", "DMC-LX5", cam_dmc_lx5_iso_80_panasonic_raw_1_3648x2736_rw2, "raw_modes/DMC-LX5_ISO_80_Panasonic RAW 1_3648x2736.RW2"); super::camera_file_check!("Panasonic", "DMC-LX5", cam_dmc_lx5_iso_80_panasonic_raw_1_2736x2736_rw2, "raw_modes/DMC-LX5_ISO_80_Panasonic RAW 1_2736x2736.RW2"); super::camera_file_check!("Panasonic", "DMC-LX5", cam_dmc_lx5_iso_80_panasonic_raw_1_3776x2520_rw2, "raw_modes/DMC-LX5_ISO_80_Panasonic RAW 1_3776x2520.RW2"); super::camera_file_check!("Panasonic", "DMC-LX5", cam_dmc_lx5_iso_80_panasonic_raw_1_3968x2232_rw2, "raw_modes/DMC-LX5_ISO_80_Panasonic RAW 1_3968x2232.RW2"); } mod camera_dmc_lx7_raw_modes { super::camera_file_check!("Panasonic", "DMC-LX7", cam_dmc_lx7_iso_100_panasonic_raw_1_3968x2232_rw2, "raw_modes/DMC-LX7_ISO_100_Panasonic RAW 1_3968x2232.RW2"); super::camera_file_check!("Panasonic", "DMC-LX7", cam_dmc_lx7_iso_100_panasonic_raw_1_3776x2520_rw2, "raw_modes/DMC-LX7_ISO_100_Panasonic RAW 1_3776x2520.RW2"); super::camera_file_check!("Panasonic", "DMC-LX7", cam_dmc_lx7_iso_100_panasonic_raw_1_3648x2736_rw2, "raw_modes/DMC-LX7_ISO_100_Panasonic RAW 1_3648x2736.RW2"); super::camera_file_check!("Panasonic", "DMC-LX7", cam_dmc_lx7_iso_100_panasonic_raw_1_2736x2736_rw2, "raw_modes/DMC-LX7_ISO_100_Panasonic RAW 1_2736x2736.RW2"); } mod camera_dmc_tx1_raw_modes { super::camera_file_check!("Panasonic", "DMC-TX1", cam_dmc_tx1_iso_125_4fmt_3x2_rw2, "raw_modes/DMC-TX1_ISO_125_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-TX1", cam_dmc_tx1_iso_125_4fmt_4x3_rw2, "raw_modes/DMC-TX1_ISO_125_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-TX1", cam_dmc_tx1_iso_125_4fmt_1x1_rw2, "raw_modes/DMC-TX1_ISO_125_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-TX1", cam_dmc_tx1_iso_125_4fmt_16x9_rw2, "raw_modes/DMC-TX1_ISO_125_4fmt_16x9.RW2"); } mod camera_dmc_tz100_raw_modes { super::camera_file_check!("Panasonic", "DMC-TZ100", cam_dmc_tz100_iso_640_4fmt_1x1_rw2, "raw_modes/DMC-TZ100_ISO_640_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ100", cam_dmc_tz100_iso_640_4fmt_4x2_rw2, "raw_modes/DMC-TZ100_ISO_640_4fmt_4x2.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ100", cam_dmc_tz100_iso_640_4fmt_16x9_rw2, "raw_modes/DMC-TZ100_ISO_640_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ100", cam_dmc_tz100_iso_640_4fmt_3x2_rw2, "raw_modes/DMC-TZ100_ISO_640_4fmt_3x2.RW2"); } mod camera_dmc_tz101_raw_modes { super::camera_file_check!("Panasonic", "DMC-TZ101", cam_dmc_tz101_iso_125_4fmt_5472x3648_rw2, "raw_modes/DMC-TZ101_ISO_125_4fmt_5472x3648.RW2"); } mod camera_dmc_tz110_raw_modes { super::camera_file_check!("Panasonic", "DMC-TZ110", cam_dmc_tz110_iso_200_4fmt_3x2_rw2, "raw_modes/DMC-TZ110_ISO_200_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ110", cam_dmc_tz110_iso_200_4fmt_1x1_rw2, "raw_modes/DMC-TZ110_ISO_200_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ110", cam_dmc_tz110_iso_200_4fmt_4x3_rw2, "raw_modes/DMC-TZ110_ISO_200_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ110", cam_dmc_tz110_iso_200_4fmt_16x9_rw2, "raw_modes/DMC-TZ110_ISO_200_4fmt_16x9.RW2"); } mod camera_dmc_tz60_raw_modes { super::camera_file_check!("Panasonic", "DMC-TZ60", cam_dmc_tz60_iso_200_panasonic_raw_1_4896x3672_rw2, "raw_modes/DMC-TZ60_ISO_200_Panasonic RAW 1_4896x3672.RW2"); } mod camera_dmc_tz61_raw_modes { super::camera_file_check!("Panasonic", "DMC-TZ61", cam_dmc_tz61_iso_400_panasonic_raw_1_3672x3672_rw2, "raw_modes/DMC-TZ61_ISO_400_Panasonic RAW 1_3672x3672.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ61", cam_dmc_tz61_iso_400_panasonic_raw_1_4896x2754_rw2, "raw_modes/DMC-TZ61_ISO_400_Panasonic RAW 1_4896x2754.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ61", cam_dmc_tz61_iso_400_panasonic_raw_1_4896x3672_rw2, "raw_modes/DMC-TZ61_ISO_400_Panasonic RAW 1_4896x3672.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ61", cam_dmc_tz61_iso_400_panasonic_raw_1_4896x3264_rw2, "raw_modes/DMC-TZ61_ISO_400_Panasonic RAW 1_4896x3264.RW2"); } mod camera_dmc_tz70_raw_modes { super::camera_file_check!("Panasonic", "DMC-TZ70", cam_dmc_tz70_iso_80_panasonic_raw_1_4000x2248_rw2, "raw_modes/DMC-TZ70_ISO_80_Panasonic RAW 1_4000x2248.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ70", cam_dmc_tz70_iso_80_panasonic_raw_1_2992x2992_rw2, "raw_modes/DMC-TZ70_ISO_80_Panasonic RAW 1_2992x2992.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ70", cam_dmc_tz70_iso_80_panasonic_raw_1_4000x3000_rw2, "raw_modes/DMC-TZ70_ISO_80_Panasonic RAW 1_4000x3000.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ70", cam_dmc_tz70_iso_80_panasonic_raw_1_4000x2672_rw2, "raw_modes/DMC-TZ70_ISO_80_Panasonic RAW 1_4000x2672.RW2"); } mod camera_dmc_tz71_raw_modes { super::camera_file_check!("Panasonic", "DMC-TZ71", cam_dmc_tz71_iso_80_panasonic_raw_1_4000x3000_rw2, "raw_modes/DMC-TZ71_ISO_80_Panasonic RAW 1_4000x3000.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ71", cam_dmc_tz71_iso_80_panasonic_raw_1_4000x2672_rw2, "raw_modes/DMC-TZ71_ISO_80_Panasonic RAW 1_4000x2672.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ71", cam_dmc_tz71_iso_80_panasonic_raw_1_2992x2992_rw2, "raw_modes/DMC-TZ71_ISO_80_Panasonic RAW 1_2992x2992.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ71", cam_dmc_tz71_iso_80_panasonic_raw_1_4000x2248_rw2, "raw_modes/DMC-TZ71_ISO_80_Panasonic RAW 1_4000x2248.RW2"); } mod camera_dmc_tz80_raw_modes { super::camera_file_check!("Panasonic", "DMC-TZ80", cam_dmc_tz80_iso_1600_4fmt_3x2_rw2, "raw_modes/DMC-TZ80_ISO_1600_4fmt_3x2.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ80", cam_dmc_tz80_iso_1600_4fmt_16x9_rw2, "raw_modes/DMC-TZ80_ISO_1600_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ80", cam_dmc_tz80_iso_1600_4fmt_4x3_rw2, "raw_modes/DMC-TZ80_ISO_1600_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ80", cam_dmc_tz80_iso_1600_4fmt_1x1_rw2, "raw_modes/DMC-TZ80_ISO_1600_4fmt_1x1.RW2"); } mod camera_dmc_tz81_raw_modes { super::camera_file_check!("Panasonic", "DMC-TZ81", cam_dmc_tz81_iso_80_4fmt_4x3_rw2, "raw_modes/DMC-TZ81_ISO_80_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ81", cam_dmc_tz81_iso_80_4fmt_1x1_rw2, "raw_modes/DMC-TZ81_ISO_80_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ81", cam_dmc_tz81_iso_80_4fmt_16x9_rw2, "raw_modes/DMC-TZ81_ISO_80_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-TZ81", cam_dmc_tz81_iso_80_4fmt_3x2_rw2, "raw_modes/DMC-TZ81_ISO_80_4fmt_3x2.RW2"); } mod camera_dmc_zs100_raw_modes { super::camera_file_check!("Panasonic", "DMC-ZS100", cam_dmc_zs100_iso_125_4fmt_4x3_rw2, "raw_modes/DMC-ZS100_ISO_125_4fmt_4x3.RW2"); super::camera_file_check!("Panasonic", "DMC-ZS100", cam_dmc_zs100_iso_125_4fmt_1x1_rw2, "raw_modes/DMC-ZS100_ISO_125_4fmt_1x1.RW2"); super::camera_file_check!("Panasonic", "DMC-ZS100", cam_dmc_zs100_iso_125_4fmt_16x9_rw2, "raw_modes/DMC-ZS100_ISO_125_4fmt_16x9.RW2"); super::camera_file_check!("Panasonic", "DMC-ZS100", cam_dmc_zs100_iso_125_4fmt_3x2_rw2, "raw_modes/DMC-ZS100_ISO_125_4fmt_3x2.RW2"); } mod camera_dmc_zs40_raw_modes { super::camera_file_check!("Panasonic", "DMC-ZS40", cam_dmc_zs40_iso_100_panasonic_raw_1_4896x3672_rw2, "raw_modes/DMC-ZS40_ISO_100_Panasonic RAW 1_4896x3672.RW2"); } mod camera_dmc_zs60_raw_modes { super::camera_file_check!("Panasonic", "DMC-ZS60", cam_dmc_zs60_iso_400_panasonic_raw_1_4896x3672_rw2, "raw_modes/DMC-ZS60_ISO_400_Panasonic RAW 1_4896x3672.RW2"); } mod camera_sigma_fp_cinemadng { super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_6k_14bit_dng, "cinemadng/SIGMA_FP_6k_14bit.DNG"); super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_653_20240229_000001_2k_8bit_dng, "cinemadng/SIGMA_FP_653_20240229_000001_2k_8bit.DNG"); super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_648_20240229_000001_4k_10bit_dng, "cinemadng/SIGMA_FP_648_20240229_000001_4k_10bit.DNG"); super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_647_20240229_000001_4k_12bit_dng, "cinemadng/SIGMA_FP_647_20240229_000001_4k_12bit.DNG"); super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_652_20240229_000001_2k_10bit_dng, "cinemadng/SIGMA_FP_652_20240229_000001_2k_10bit.DNG"); super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_650_20240229_000001_4k_8bit_dng, "cinemadng/SIGMA_FP_650_20240229_000001_4k_8bit.DNG"); super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_651_20240229_000001_2k_12bit_dng, "cinemadng/SIGMA_FP_651_20240229_000001_2k_12bit.DNG"); } mod camera_c_lux_raw_modes { super::camera_file_check!("Leica", "C-Lux", cam_c_lux_iso_125_4fmt_5472x3648_rwl, "raw_modes/C-Lux_ISO_125_4fmt_5472x3648.RWL"); } mod camera_c_typ_112_raw_modes { super::camera_file_check!("Leica", "C Typ 112", cam_c_typ_112_iso_80_4fmt_3x2_rwl, "raw_modes/C Typ 112_ISO_80_4fmt_3x2.RWL"); super::camera_file_check!("Leica", "C Typ 112", cam_c_typ_112_iso_640_4fmt_4x3_rwl, "raw_modes/C Typ 112_ISO_640_4fmt_4x3.RWL"); } mod camera_digilux_2_raw_modes { super::camera_file_check!("Leica", "Digilux 2", cam_digilux_2_iso_100_raw, "raw_modes/DIGILUX 2_ISO_100.RAW"); } mod camera_digilux_3_raw_modes { super::camera_file_check!("Leica", "Digilux 3", cam_digilux_3_iso_100_raw, "raw_modes/DIGILUX 3_ISO_100.RAW"); } mod camera_d_lux_3_raw_modes { super::camera_file_check!("Leica", "D-LUX 3", cam_raw_leica_dlux3_raw, "raw_modes/RAW_LEICA_DLUX3.RAW"); } mod camera_d_lux_4_raw_modes { super::camera_file_check!("Leica", "D-LUX 4", cam_d_lux_4_iso_80_4fmt_3x2_rwl, "raw_modes/D-LUX 4_ISO_80_4fmt_3x2.RWL"); } mod camera_d_lux_5_raw_modes { super::camera_file_check!("Leica", "D-LUX 5", cam_d_lux_5_iso_80_4fmt_3x2_rwl, "raw_modes/D-LUX 5_ISO_80_4fmt_3x2.RWL"); super::camera_file_check!("Leica", "D-LUX 5", cam_d_lux_5_iso_80_4fmt_16x9_rwl, "raw_modes/D-LUX 5_ISO_80_4fmt_16x9.RWL"); super::camera_file_check!("Leica", "D-LUX 5", cam_d_lux_5_iso_80_4fmt_1x1_rwl, "raw_modes/D-LUX 5_ISO_80_4fmt_1x1.RWL"); super::camera_file_check!("Leica", "D-LUX 5", cam_d_lux_5_iso_80_4fmt_4x3_rwl, "raw_modes/D-LUX 5_ISO_80_4fmt_4x3.RWL"); } mod camera_d_lux_7_raw_modes { super::camera_file_check!("Leica", "D-LUX 7", cam_d_lux_7_iso_200_4fmt_4x3_rwl, "raw_modes/D-Lux 7_ISO_200_4fmt_4x3.RWL"); } mod camera_d_lux_typ_109_raw_modes { super::camera_file_check!("Leica", "D-LUX Typ 109", cam_d_lux_typ_109_iso_500_4fmt_16x9_rwl, "raw_modes/D-LUX Typ 109_ISO_500_4fmt_16x9.RWL"); super::camera_file_check!("Leica", "D-LUX Typ 109", cam_d_lux_typ_109_iso_500_4fmt_3x2_rwl, "raw_modes/D-LUX Typ 109_ISO_500_4fmt_3x2.RWL"); super::camera_file_check!("Leica", "D-LUX Typ 109", cam_d_lux_typ_109_iso_640_4fmt_1x1_rwl, "raw_modes/D-LUX Typ 109_ISO_640_4fmt_1x1.RWL"); super::camera_file_check!("Leica", "D-LUX Typ 109", cam_d_lux_typ_109_iso_640_4fmt_4x3_rwl, "raw_modes/D-LUX Typ 109_ISO_640_4fmt_4x3.RWL"); } mod camera_v_lux_1_raw_modes { super::camera_file_check!("Leica", "V-LUX 1", cam_v_lux_1_iso_100_raw, "raw_modes/V-LUX 1_ISO_100.RAW"); } mod camera_v_lux_4_raw_modes { super::camera_file_check!("Leica", "V-LUX 4", cam_v_lux_4_iso_100_4fmt_4000x3000_rwl, "raw_modes/V-LUX 4_ISO_100_4fmt_4000x3000.RWL"); } mod camera_v_lux_5_raw_modes { super::camera_file_check!("Leica", "V-LUX 5", cam_v_lux_5_iso_125_4fmt_5472x3648_rwl, "raw_modes/V-Lux 5_ISO_125_4fmt_5472x3648.RWL"); } mod camera_v_lux_typ_114_raw_modes { super::camera_file_check!("Leica", "V-LUX Typ 114", cam_v_lux_typ_114_iso_125_4fmt_3x2_rwl, "raw_modes/V-LUX Typ 114_ISO_125_4fmt_3x2.RWL"); super::camera_file_check!("Leica", "V-LUX Typ 114", cam_v_lux_typ_114_iso_125_4fmt_16x9_rwl, "raw_modes/V-LUX Typ 114_ISO_125_4fmt_16x9.RWL"); super::camera_file_check!("Leica", "V-LUX Typ 114", cam_v_lux_typ_114_iso_125_4fmt_1x1_rwl, "raw_modes/V-LUX Typ 114_ISO_125_4fmt_1x1.RWL"); super::camera_file_check!("Leica", "V-LUX Typ 114", cam_v_lux_typ_114_iso_125_4fmt_4x3_rwl, "raw_modes/V-LUX Typ 114_ISO_125_4fmt_4x3.RWL"); } mod camera_dbp_for_gx680_raw_modes { super::camera_file_check!("Fujifilm", "DBP for GX680", cam_dbp_for_gx680_iso_100_raf, "raw_modes/DBP for GX680_ISO_100.RAF"); } mod camera_finepix_e550_raw_modes { super::camera_file_check!("Fujifilm", "FinePix E550", cam_finepix_e550_iso_200_raf, "raw_modes/FinePix E550_ISO_200.RAF"); } mod camera_finepix_e900_raw_modes { super::camera_file_check!("Fujifilm", "FinePix E900", cam_finepix_e900_iso_80_raf, "raw_modes/FinePix E900_ISO_80.RAF"); } mod camera_finepix_f550exr_raw_modes { super::camera_file_check!("Fujifilm", "FinePix F550EXR", cam_finepix_f550exr_iso_400_raf, "raw_modes/FinePix F550EXR_ISO_400.RAF"); } mod camera_finepix_f600exr_raw_modes { super::camera_file_check!("Fujifilm", "FinePix F600EXR", cam_finepix_f600exr_iso_100_raf, "raw_modes/FinePix F600EXR_ISO_100.RAF"); } mod camera_finepix_f700_raw_modes { super::camera_file_check!("Fujifilm", "FinePix F700", cam_finepix_f700_iso_200_raf, "raw_modes/FinePix F700_ISO_200.RAF"); } mod camera_finepix_f770exr_raw_modes { super::camera_file_check!("Fujifilm", "FinePix F770EXR", cam_finepix_f770exr_iso_100_raf, "raw_modes/FinePix F770EXR_ISO_100.RAF"); } mod camera_finepix_f900exr_raw_modes { super::camera_file_check!("Fujifilm", "FinePix F900EXR", cam_finepix_f900exr_iso_400_raf, "raw_modes/FinePix F900EXR_ISO_400.RAF"); } mod camera_finepix_hs10_hs11_raw_modes { super::camera_file_check!("Fujifilm", "FinePix HS10 HS11", cam_finepix_hs10_hs11_iso_200_raf, "raw_modes/FinePix HS10 HS11_ISO_200.RAF"); } mod camera_finepix_hs20exr_raw_modes { super::camera_file_check!("Fujifilm", "FinePix HS20EXR", cam_finepix_hs20exr_iso_100_raf, "raw_modes/FinePix HS20EXR_ISO_100.RAF"); } mod camera_finepix_hs30exr_raw_modes { super::camera_file_check!("Fujifilm", "FinePix HS30EXR", cam_finepix_hs30exr_iso_400_raf, "raw_modes/FinePix HS30EXR_ISO_400.RAF"); } mod camera_finepix_hs33exr_raw_modes { super::camera_file_check!("Fujifilm", "FinePix HS33EXR", cam_finepix_hs33exr_iso_100_raf, "raw_modes/FinePix HS33EXR_ISO_100.RAF"); } mod camera_finepix_hs50exr_raw_modes { super::camera_file_check!("Fujifilm", "FinePix HS50EXR", cam_finepix_hs50exr_iso_100_raf, "raw_modes/FinePix HS50EXR_ISO_100.RAF"); } mod camera_finepix_s100fs_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S100FS", cam_finepix_s100fs_iso_100_raf, "raw_modes/FinePix S100FS_ISO_100.RAF"); } mod camera_finepix_sl1000_raw_modes { super::camera_file_check!("Fujifilm", "FinePix SL1000", cam_finepix_sl1000_iso_100_12bits_raf, "raw_modes/FinePix SL1000_ISO_100_12bits.RAF"); } mod camera_finepix_s1_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S1", cam_finepix_s1_iso_200_raf, "raw_modes/FinePix S1_ISO_200.RAF"); } mod camera_finepix_s200exr_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S200EXR", cam_finepix_s200exr_iso_100_raf, "raw_modes/FinePix S200EXR_ISO_100.RAF"); } mod camera_finepix_s2pro_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S2Pro", cam_finepixs2pro_iso_100_raf, "raw_modes/FinePixS2Pro_ISO_100.RAF"); } mod camera_finepix_s3pro_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S3Pro", cam_finepix_s3pro_iso_100_raf, "raw_modes/FinePix S3Pro_ISO_100.RAF"); } mod camera_finepix_s5000_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S5000", cam_finepix_s5000_iso_200_raf, "raw_modes/FinePix S5000_ISO_200.RAF"); } mod camera_finepix_s5200_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S5200", cam_finepix_s5200_iso_64_raf, "raw_modes/FinePix S5200_ISO_64.RAF"); } mod camera_finepix_s5500_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S5500", cam_finepix_s5500_iso_100_raf, "raw_modes/FinePix S5500_ISO_100.RAF"); } mod camera_finepix_s5600_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S5600", cam_finepix_s5600_iso_64_raf, "raw_modes/FinePix S5600_ISO_64.RAF"); } mod camera_finepix_s5pro_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S5Pro", cam_finepix_s5pro_iso_100_raf, "raw_modes/FinePix S5Pro_ISO_100.RAF"); } mod camera_finepix_s6500fd_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S6500fd", cam_finepix_s6500fd_iso_100_raf, "raw_modes/FinePix S6500fd_ISO_100.RAF"); } mod camera_finepix_s7000_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S7000", cam_finepix_s7000_iso_200_raf, "raw_modes/FinePix S7000_ISO_200.RAF"); } mod camera_finepix_s9500_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S9500", cam_finepix_s9500_iso_80_raf, "raw_modes/FinePix S9500_ISO_80.RAF"); } mod camera_finepix_s9600_raw_modes { super::camera_file_check!("Fujifilm", "FinePix S9600", cam_finepix_s9600_iso_200_raf, "raw_modes/FinePix S9600_ISO_200.RAF"); } mod camera_finepix_x100_raw_modes { super::camera_file_check!("Fujifilm", "FinePix X100", cam_finepix_x100_iso_400_raf, "raw_modes/FinePix X100_ISO_400.RAF"); } mod camera_finepix_x10_raw_modes { super::camera_file_check!("Fujifilm", "FinePix X10", cam_x10_iso_200_raf, "raw_modes/X10_ISO_200.RAF"); } mod camera_gfx_100_compressed { super::camera_file_check!("Fujifilm", "GFX 100", cam_gfx_100_iso_100_bitdepth_16_124_mib_raf, "compressed/GFX 100_ISO_100_Bitdepth_16_124 MiB.RAF"); super::camera_file_check!("Fujifilm", "GFX 100", cam_gfx_100_iso_100_bitdepth_14_101_mib_raf, "compressed/GFX 100_ISO_100_Bitdepth_14_101 MiB.RAF"); } mod camera_gfx_100_raw_modes { super::camera_file_check!("Fujifilm", "GFX 100", cam_gfx_100_iso_100_bitdepth_14_200_mib_raf, "raw_modes/GFX 100_ISO_100_Bitdepth_14_200 MiB.RAF"); super::camera_file_check!("Fujifilm", "GFX 100", cam_gfx_100_iso_100_bitdepth_16_200_mib_raf, "raw_modes/GFX 100_ISO_100_Bitdepth_16_200 MiB.RAF"); } mod camera_gfx_100rf_raw_modes { super::camera_file_check!("Fujifilm", "GFX 100RF", cam_gfx100rf_14bit_uncompressed_raf, "raw_modes/GFX100RF_14bit_uncompressed.RAF"); super::camera_file_check!("Fujifilm", "GFX 100RF", cam_gfx100rf_16bit_lossy_raf, "raw_modes/GFX100RF_16bit_lossy.RAF"); super::camera_file_check!("Fujifilm", "GFX 100RF", cam_gfx100rf_14bit_lossy_raf, "raw_modes/GFX100RF_14bit_lossy.RAF"); super::camera_file_check!("Fujifilm", "GFX 100RF", cam_gfx100rf_16bit_lossless_raf, "raw_modes/GFX100RF_16bit_lossless.RAF"); super::camera_file_check!("Fujifilm", "GFX 100RF", cam_gfx100rf_14bit_lossless_raf, "raw_modes/GFX100RF_14bit_lossless.RAF"); super::camera_file_check!("Fujifilm", "GFX 100RF", cam_gfx100rf_16bit_uncompressed_raf, "raw_modes/GFX100RF_16bit_uncompressed.RAF"); } mod camera_gfx_100_ii_raw_modes { super::camera_file_check!("Fujifilm", "GFX 100 II", cam_gfx100_ii_14bits_lossy_4x3_raf, "raw_modes/GFX100_II_14bits_lossy_4x3.RAF"); super::camera_file_check!("Fujifilm", "GFX 100 II", cam_gfx100_ii_14bits_lossless_4x3_raf, "raw_modes/GFX100_II_14bits_lossless_4x3.RAF"); super::camera_file_check!("Fujifilm", "GFX 100 II", cam_gfx100_ii_14bits_uncompressed_4x3_raf, "raw_modes/GFX100_II_14bits_uncompressed_4x3.RAF"); super::camera_file_check!("Fujifilm", "GFX 100 II", cam_gfx100_ii_16bits_lossy_4x3_raf, "raw_modes/GFX100_II_16bits_lossy_4x3.RAF"); super::camera_file_check!("Fujifilm", "GFX 100 II", cam_gfx100_ii_16bits_lossless_4x3_raf, "raw_modes/GFX100_II_16bits_lossless_4x3.RAF"); } mod camera_gfx100s_compressed { super::camera_file_check!("Fujifilm", "GFX100S", cam_fujifilm_gfx100s_16bits_compress_4_3_raf, "compressed/Fujifilm-GFX100S-16bits-compress-4_3.RAF"); super::camera_file_check!("Fujifilm", "GFX100S", cam_fujifilm_gfx100s_16bits_losslesscompressed_4_3_raf, "compressed/Fujifilm-GFX100S-16bits-losslesscompressed-4_3.RAF"); super::camera_file_check!("Fujifilm", "GFX100S", cam_fujifilm_gfx100s_14bits_losslescompressed_4_3_raf, "compressed/Fujifilm-GFX100S-14bits-losslescompressed-4_3.RAF"); super::camera_file_check!("Fujifilm", "GFX100S", cam_fujifilm_gfx100s_14bits_compress_4_3_raf, "compressed/Fujifilm-GFX100S-14bits-compress-4_3.RAF"); } mod camera_gfx100s_raw_modes { super::camera_file_check!("Fujifilm", "GFX100S", cam_fujifilm_gfx100s_16bits_uncompress_4_3_raf, "raw_modes/Fujifilm-GFX100S-16bits-uncompress-4_3.RAF"); super::camera_file_check!("Fujifilm", "GFX100S", cam_fujifilm_gfx100s_14bits_uncompress_4_3_raf, "raw_modes/Fujifilm-GFX100S-14bits-uncompress-4_3.RAF"); } mod camera_gfx_100s_ii_raw_modes { super::camera_file_check!("Fujifilm", "GFX 100S II", cam_gfx100sii_14bit_lossless_raf, "raw_modes/GFX100SII_14bit_lossless.RAF"); super::camera_file_check!("Fujifilm", "GFX 100S II", cam_gfx100sii_14bit_uncompressed_raf, "raw_modes/GFX100SII_14bit_uncompressed.RAF"); super::camera_file_check!("Fujifilm", "GFX 100S II", cam_gfx100sii_16bit_lossless_raf, "raw_modes/GFX100SII_16bit_lossless.RAF"); super::camera_file_check!("Fujifilm", "GFX 100S II", cam_gfx100sii_14bit_lossy_raf, "raw_modes/GFX100SII_14bit_lossy.RAF"); super::camera_file_check!("Fujifilm", "GFX 100S II", cam_gfx100sii_16bit_lossy_raf, "raw_modes/GFX100SII_16bit_lossy.RAF"); super::camera_file_check!("Fujifilm", "GFX 100S II", cam_gfx100sii_16bit_uncompressed_raf, "raw_modes/GFX100SII_16bit_uncompressed.RAF"); } mod camera_gfx_50r_compressed { super::camera_file_check!("Fujifilm", "GFX 50R", cam_gfx_50r_iso_100_bitdepth_14_50_mib_raf, "compressed/GFX 50R_ISO_100_Bitdepth_14_50 MiB.RAF"); } mod camera_gfx_50r_raw_modes { super::camera_file_check!("Fujifilm", "GFX 50R", cam_gfx_50r_iso_100_bitdepth_14_112_mib_raf, "raw_modes/GFX 50R_ISO_100_Bitdepth_14_112 MiB.RAF"); } mod camera_gfx_50s_compressed { super::camera_file_check!("Fujifilm", "GFX 50S", cam_gfx_50s_iso_100_bitdepth_14_48_mib_raf, "compressed/GFX 50S_ISO_100_Bitdepth_14_48 MiB.RAF"); } mod camera_gfx50s_ii_compressed { super::camera_file_check!("Fujifilm", "GFX50S II", cam_fuji_gfx50s_ii___compressed_raf, "compressed/Fuji_GFX50S_II_-_Compressed.RAF"); super::camera_file_check!("Fujifilm", "GFX50S II", cam_fuji_gfx50s_ii___lossless_compressed_raf, "compressed/Fuji_GFX50S_II_-_Lossless_Compressed.RAF"); } mod camera_gfx50s_ii_raw_modes { super::camera_file_check!("Fujifilm", "GFX50S II", cam_fuji_gfx50s_ii___uncompressed_raf, "raw_modes/Fuji_GFX50S_II_-_Uncompressed.RAF"); } mod camera_gfx_50s_raw_modes { super::camera_file_check!("Fujifilm", "GFX 50S", cam_gfx_50s_iso_100_bitdepth_14_111_mib_raf, "raw_modes/GFX 50S_ISO_100_Bitdepth_14_111 MiB.RAF"); } mod camera_x100f_compressed { super::camera_file_check!("Fujifilm", "X100F", cam_x100f_lossless_compressed_raw_temple_raf, "compressed/X100F_lossless_compressed_raw_Temple.RAF"); } mod camera_x100f_raw_modes { super::camera_file_check!("Fujifilm", "X100F", cam_x100f_uncompressed_raw_temple_raf, "raw_modes/X100F_uncompressed_raw_Temple.RAF"); } mod camera_x100s_raw_modes { super::camera_file_check!("Fujifilm", "X100S", cam_x100s_iso_200_bitdepth_14_raf, "raw_modes/X100S_ISO_200_Bitdepth_14.RAF"); } mod camera_x100t_raw_modes { super::camera_file_check!("Fujifilm", "X100T", cam_x100t_iso_400_bitdepth_14_raf, "raw_modes/X100T_ISO_400_Bitdepth_14.RAF"); } mod camera_x100v_compressed { super::camera_file_check!("Fujifilm", "X100V", cam_x100v_iso_160_bitdepth_14_31_mib_raf, "compressed/X100V_ISO_160_Bitdepth_14_31 MiB.RAF"); } mod camera_x100v_raw_modes { super::camera_file_check!("Fujifilm", "X100V", cam_x100v_iso_160_bitdepth_14_56_mib_raf, "raw_modes/X100V_ISO_160_Bitdepth_14_56 MiB.RAF"); } mod camera_x100vi_raw_modes { super::camera_file_check!("Fujifilm", "X100VI", cam_x100vi_14bits_3x2_uncompressed_raf, "raw_modes/X100VI_14bits_3x2_uncompressed.RAF"); super::camera_file_check!("Fujifilm", "X100VI", cam_x100vi_14bits_3x2_lossless_raf, "raw_modes/X100VI_14bits_3x2_lossless.RAF"); super::camera_file_check!("Fujifilm", "X100VI", cam_x100vi_14bits_3x2_lossy_raf, "raw_modes/X100VI_14bits_3x2_lossy.RAF"); } mod camera_x20_raw_modes { super::camera_file_check!("Fujifilm", "X20", cam_x20_iso_200_raf, "raw_modes/X20_ISO_200.RAF"); } mod camera_x30_raw_modes { super::camera_file_check!("Fujifilm", "X30", cam_x30_iso_100_raf, "raw_modes/X30_ISO_100.RAF"); } mod camera_x70_raw_modes { super::camera_file_check!("Fujifilm", "X70", cam_x70_iso_6400_raf, "raw_modes/X70_ISO_6400.RAF"); } mod camera_x_a10_raw_modes { super::camera_file_check!("Fujifilm", "X-A10", cam_x_a10_iso_200_raf, "raw_modes/X-A10_ISO_200.RAF"); } mod camera_x_a1_raw_modes { super::camera_file_check!("Fujifilm", "X-A1", cam_x_a1_iso_1000_raf, "raw_modes/X-A1_ISO_1000.RAF"); } mod camera_x_a2_raw_modes { super::camera_file_check!("Fujifilm", "X-A2", cam_x_a2_iso_200_raf, "raw_modes/X-A2_ISO_200.RAF"); } mod camera_x_a3_raw_modes { super::camera_file_check!("Fujifilm", "X-A3", cam_x_a3_iso_400_raf, "raw_modes/X-A3_ISO_400.RAF"); } mod camera_x_a5_raw_modes { super::camera_file_check!("Fujifilm", "X-A5", cam_x_a5_iso_200_raf, "raw_modes/X-A5_ISO_200.RAF"); } mod camera_x_a7_raw_modes { super::camera_file_check!("Fujifilm", "X-A7", cam_x_a7_iso_200_raf, "raw_modes/X-A7_ISO_200.RAF"); } mod camera_x_e1_raw_modes { super::camera_file_check!("Fujifilm", "X-E1", cam_x_e1_iso_500_raf, "raw_modes/X-E1_ISO_500.RAF"); } mod camera_x_e2_raw_modes { super::camera_file_check!("Fujifilm", "X-E2", cam_x_e2_iso_200_raf, "raw_modes/X-E2_ISO_200.RAF"); } mod camera_x_e2s_raw_modes { super::camera_file_check!("Fujifilm", "X-E2S", cam_x_e2s_iso_400_raf, "raw_modes/X-E2S_ISO_400.RAF"); } mod camera_x_e3_compressed { super::camera_file_check!("Fujifilm", "X-E3", cam_x_e3_iso_250_bitdepth_14_27_mib_raf, "compressed/X-E3_ISO_250_Bitdepth_14_27 MiB.RAF"); } mod camera_x_e3_raw_modes { super::camera_file_check!("Fujifilm", "X-E3", cam_x_e3_iso_250_bitdepth_14_48_mib_raf, "raw_modes/X-E3_ISO_250_Bitdepth_14_48 MiB.RAF"); } mod camera_x_e4_compressed { super::camera_file_check!("Fujifilm", "X-E4", cam_fuji_xe4_32_lossy_raf, "compressed/fuji_xe4_32_lossy.RAF"); super::camera_file_check!("Fujifilm", "X-E4", cam_fuji_xe4_32_lossless_raf, "compressed/fuji_xe4_32_lossless.RAF"); } mod camera_x_e4_raw_modes { super::camera_file_check!("Fujifilm", "X-E4", cam_fuji_xe4_32_uncompressed_raf, "raw_modes/fuji_xe4_32_uncompressed.RAF"); } mod camera_x_e5_raw_modes { super::camera_file_check!("Fujifilm", "X-E5", cam_x_e5_uncompressed_14bit_raf, "raw_modes/X-E5_uncompressed_14bit.RAF"); super::camera_file_check!("Fujifilm", "X-E5", cam_x_e5_lossy_14bit_raf, "raw_modes/X-E5_lossy_14bit.RAF"); super::camera_file_check!("Fujifilm", "X-E5", cam_x_e5_lossless_14bit_raf, "raw_modes/X-E5_lossless_14bit.RAF"); } mod camera_xf10_raw_modes { super::camera_file_check!("Fujifilm", "XF10", cam_xf10_iso_200_raf, "raw_modes/XF10_ISO_200.RAF"); } mod camera_xf1_raw_modes { super::camera_file_check!("Fujifilm", "XF1", cam_xf1_iso_1250_raf, "raw_modes/XF1_ISO_1250.RAF"); } mod camera_x_h1_compressed { super::camera_file_check!("Fujifilm", "X-H1", cam_fuji_xh1_compressed_raf, "compressed/fuji_xh1_compressed.RAF"); } mod camera_x_h1_raw_modes { super::camera_file_check!("Fujifilm", "X-H1", cam_fuji_xh1_uncompressed_raf, "raw_modes/fuji_xh1_uncompressed.RAF"); } mod camera_x_h2s_raw_modes { super::camera_file_check!("Fujifilm", "X-H2S", cam_fujifilm_x_h2s_14bit_lossy_raf, "raw_modes/Fujifilm_X-H2S_14bit_lossy.raf"); super::camera_file_check!("Fujifilm", "X-H2S", cam_fujifilm_x_h2s_14bit_uncompressed_raf, "raw_modes/Fujifilm_X-H2S_14bit_uncompressed.raf"); super::camera_file_check!("Fujifilm", "X-H2S", cam_fujifilm_x_h2s_14bit_lossless_raf, "raw_modes/Fujifilm_X-H2S_14bit_lossless.raf"); } mod camera_x_h2_raw_modes { super::camera_file_check!("Fujifilm", "X-H2", cam_fujifilm_x_h2_14bit_lossy_raf, "raw_modes/Fujifilm_X-H2_14bit_lossy.raf"); super::camera_file_check!("Fujifilm", "X-H2", cam_fujifilm_x_h2_14bit_uncompressed_raf, "raw_modes/Fujifilm_X-H2_14bit_uncompressed.raf"); super::camera_file_check!("Fujifilm", "X-H2", cam_fujifilm_x_h2_14bit_lossless_raf, "raw_modes/Fujifilm_X-H2_14bit_lossless.raf"); } mod camera_x_m1_raw_modes { super::camera_file_check!("Fujifilm", "X-M1", cam_x_m1_iso_200_raf, "raw_modes/X-M1_ISO_200.RAF"); } mod camera_x_m5_raw_modes { super::camera_file_check!("Fujifilm", "X-M5", cam_fujifilm_x_m5_iso100_lossy_compressed2_raf, "raw_modes/fujifilm_X-M5_ISO100_lossy_compressed2.RAF"); super::camera_file_check!("Fujifilm", "X-M5", cam_fujifilm_x_m5_iso100_lossless_compressed_raf, "raw_modes/fujifilm_X-M5_ISO100_lossless_compressed.RAF"); super::camera_file_check!("Fujifilm", "X-M5", cam_fujifilm_x_m5_iso100_uncompressed2_raf, "raw_modes/fujifilm_X-M5_ISO100_uncompressed2.RAF"); super::camera_file_check!("Fujifilm", "X-M5", cam_fujifilm_x_m5_iso100_lossy_compressed_raf, "raw_modes/fujifilm_X-M5_ISO100_lossy_compressed.RAF"); super::camera_file_check!("Fujifilm", "X-M5", cam_fujifilm_x_m5_iso100_lossless_compressed2_raf, "raw_modes/fujifilm_X-M5_ISO100_lossless_compressed2.RAF"); super::camera_file_check!("Fujifilm", "X-M5", cam_fujifilm_x_m5_iso100_uncompressed_raf, "raw_modes/fujifilm_X-M5_ISO100_uncompressed.RAF"); } mod camera_x_pro1_raw_modes { super::camera_file_check!("Fujifilm", "X-Pro1", cam_x_pro1_iso_200_raf, "raw_modes/X-Pro1_ISO_200.RAF"); } mod camera_x_pro2_compressed { super::camera_file_check!("Fujifilm", "X-Pro2", cam_x_pro2_iso_500_bitdepth_14_26_mib_raf, "compressed/X-Pro2_ISO_500_Bitdepth_14_26 MiB.RAF"); } mod camera_x_pro2_raw_modes { super::camera_file_check!("Fujifilm", "X-Pro2", cam_x_pro2_iso_500_bitdepth_14_48_mib_raf, "raw_modes/X-Pro2_ISO_500_Bitdepth_14_48 MiB.RAF"); } mod camera_x_pro3_compressed { super::camera_file_check!("Fujifilm", "X-Pro3", cam_x_pro3_iso_640_bitdepth_14_29_mib_raf, "compressed/X-Pro3_ISO_640_Bitdepth_14_29 MiB.RAF"); } mod camera_x_pro3_raw_modes { super::camera_file_check!("Fujifilm", "X-Pro3", cam_x_pro3_iso_640_bitdepth_14_54_mib_raf, "raw_modes/X-Pro3_ISO_640_Bitdepth_14_54 MiB.RAF"); } mod camera_xq1_raw_modes { super::camera_file_check!("Fujifilm", "XQ1", cam_xq1_iso_400_raf, "raw_modes/XQ1_ISO_400.RAF"); } mod camera_xq2_raw_modes { super::camera_file_check!("Fujifilm", "XQ2", cam_xq2_iso_100_raf, "raw_modes/XQ2_ISO_100.RAF"); } mod camera_x_s10_compressed { super::camera_file_check!("Fujifilm", "X-S10", cam_fujifilm_x_s10_lossless_compressed_raf, "compressed/Fujifilm-X-S10-lossless-compressed.RAF"); super::camera_file_check!("Fujifilm", "X-S10", cam_fujifilm_x_s10_compressed_raf, "compressed/Fujifilm-X-S10-compressed.RAF"); } mod camera_x_s10_raw_modes { super::camera_file_check!("Fujifilm", "X-S10", cam_fujifilm_x_s10_uncompressed_raf, "raw_modes/Fujifilm-X-S10-uncompressed.RAF"); } mod camera_x_s20_raw_modes { super::camera_file_check!("Fujifilm", "X-S20", cam_x_s20_iso_160_14bits_lossy_raf, "raw_modes/X-S20_ISO_160_14bits_Lossy.RAF"); super::camera_file_check!("Fujifilm", "X-S20", cam_x_s20_iso_160_14bits_lossless_raf, "raw_modes/X-S20_ISO_160_14bits_Lossless.RAF"); super::camera_file_check!("Fujifilm", "X-S20", cam_x_s20_iso_160_14bits_uncompressed_raf, "raw_modes/X-S20_ISO_160_14bits_uncompressed.RAF"); } mod camera_x_s1_raw_modes { super::camera_file_check!("Fujifilm", "X-S1", cam_x_s1_iso_400_raf, "raw_modes/X-S1_ISO_400.RAF"); } mod camera_x_t100_raw_modes { super::camera_file_check!("Fujifilm", "X-T100", cam_x_t100_iso_200_raf, "raw_modes/X-T100_ISO_200.RAF"); } mod camera_x_t10_raw_modes { super::camera_file_check!("Fujifilm", "X-T10", cam_x_t10_iso_4000_raf, "raw_modes/X-T10_ISO_4000.RAF"); } mod camera_x_t1_raw_modes { super::camera_file_check!("Fujifilm", "X-T1", cam_x_t1_iso_200_raf, "raw_modes/X-T1_ISO_200.RAF"); } mod camera_x_t200_raw_modes { super::camera_file_check!("Fujifilm", "X-T200", cam_x_t200_iso_200_raf, "raw_modes/X-T200_ISO_200.RAF"); } mod camera_x_t20_compressed { super::camera_file_check!("Fujifilm", "X-T20", cam_x_t20_iso_200_bitdepth_14_24_mib_raf, "compressed/X-T20_ISO_200_Bitdepth_14_24 MiB.RAF"); } mod camera_x_t20_raw_modes { super::camera_file_check!("Fujifilm", "X-T20", cam_x_t20_iso_200_bitdepth_14_48_mib_raf, "raw_modes/X-T20_ISO_200_Bitdepth_14_48 MiB.RAF"); } mod camera_x_t2_compressed { super::camera_file_check!("Fujifilm", "X-T2", cam_x_t2_iso_400_bitdepth_14_22_mib_raf, "compressed/X-T2_ISO_400_Bitdepth_14_22 MiB.RAF"); } mod camera_x_t2_raw_modes { super::camera_file_check!("Fujifilm", "X-T2", cam_x_t2_iso_200_bitdepth_14_48_mib_raf, "raw_modes/X-T2_ISO_200_Bitdepth_14_48 MiB.RAF"); } mod camera_x_t30_compressed { super::camera_file_check!("Fujifilm", "X-T30", cam_x_t30_iso_100_bitdepth_14_30_mib_raf, "compressed/X-T30_ISO_100_Bitdepth_14_30 MiB.RAF"); } mod camera_x_t30_ii_compressed { super::camera_file_check!("Fujifilm", "X-T30 II", cam_x_t30_ii_14_bits_lossy_raf, "compressed/X-T30-II-14-bits-lossy.RAF"); super::camera_file_check!("Fujifilm", "X-T30 II", cam_x_t30_ii_14_bits_lossless_raf, "compressed/X-T30-II-14-bits-lossless.RAF"); } mod camera_x_t30_ii_raw_modes { super::camera_file_check!("Fujifilm", "X-T30 II", cam_x_t30_ii_14_bits_uncompressed_raf, "raw_modes/X-T30-II-14-bits-uncompressed.RAF"); } mod camera_x_t30_raw_modes { super::camera_file_check!("Fujifilm", "X-T30", cam_x_t30_iso_100_bitdepth_14_54_mib_raf, "raw_modes/X-T30_ISO_100_Bitdepth_14_54 MiB.RAF"); } mod camera_x_t3_compressed { super::camera_file_check!("Fujifilm", "X-T3", cam_x_t3_iso_160_bitdepth_14_26_mib_raf, "compressed/X-T3_ISO_160_Bitdepth_14_26 MiB.RAF"); } mod camera_x_t3_raw_modes { super::camera_file_check!("Fujifilm", "X-T3", cam_x_t3_iso_160_bitdepth_14_53_mib_raf, "raw_modes/X-T3_ISO_160_Bitdepth_14_53 MiB.RAF"); } mod camera_x_t4_raw_modes { super::camera_file_check!("Fujifilm", "X-T4", cam_x_t4_iso_160_bitdepth_14_55_mib_raf, "raw_modes/X-T4_ISO_160_Bitdepth_14_55 MiB.RAF"); } mod camera_x_t4_compressed { super::camera_file_check!("Fujifilm", "X-T4", cam_x_t4_iso_160_bitdepth_14_26_mib_raf, "compressed/X-T4_ISO_160_Bitdepth_14_26 MiB.RAF"); super::camera_file_check!("Fujifilm", "X-T4", cam_x_t4_iso_160_bitdepth_14_27_mib_raf, "compressed/X-T4_ISO_160_Bitdepth_14_27 MiB.RAF"); } mod camera_x_t5_raw_modes { super::camera_file_check!("Fujifilm", "X-T5", cam_x_t5_iso_125_bitdepth_14_lossy_raf, "raw_modes/X-T5_ISO_125_Bitdepth_14_lossy.RAF"); super::camera_file_check!("Fujifilm", "X-T5", cam_x_t5_iso_125_bitdepth_14_lossless_raf, "raw_modes/X-T5_ISO_125_Bitdepth_14_lossless.RAF"); super::camera_file_check!("Fujifilm", "X-T5", cam_x_t5_iso_125_bitdepth_14_uncompressed_raf, "raw_modes/X-T5_ISO_125_Bitdepth_14_uncompressed.RAF"); } mod camera_x_t50_raw_modes { super::camera_file_check!("Fujifilm", "X-T50", cam_xt50_14bit_uncompressed_raf, "raw_modes/XT50_14bit_uncompressed.RAF"); super::camera_file_check!("Fujifilm", "X-T50", cam_xt50_14bit_lossless_raf, "raw_modes/XT50_14bit_lossless.RAF"); super::camera_file_check!("Fujifilm", "X-T50", cam_xt50_14bit_lossy_raf, "raw_modes/XT50_14bit_lossy.RAF"); } mod camera_om_1_raw_modes { super::camera_file_check!("OM", "OM-1", cam_om_1_iso_200_16bits_normal_orf, "raw_modes/OM-1_ISO_200_16bits_normal.ORF"); super::camera_file_check!("OM", "OM-1", cam_om_1_iso_200_16bits_handheld_hires_orf, "raw_modes/OM-1_ISO_200_16bits_handheld_hires.ORF"); super::camera_file_check!("OM", "OM-1", cam_om_1_iso_200_16bits_tripod_hires_orf, "raw_modes/OM-1_ISO_200_16bits_tripod_hires.ORF"); } mod camera_om_1_mark_ii_raw_modes { super::camera_file_check!("OM", "OM-1 Mark II", cam_om_1_mark_ii_16bits_normal_orf, "raw_modes/OM-1-Mark-II_16bits_normal.ORF"); super::camera_file_check!("OM", "OM-1 Mark II", cam_om_1_mark_ii_16bits_handheld_hires_orf, "raw_modes/OM-1-Mark-II_16bits_handheld_hires.ORF"); super::camera_file_check!("OM", "OM-1 Mark II", cam_om_1_mark_ii_16bits_tripod_hires_orf, "raw_modes/OM-1-Mark-II_16bits_tripod_hires.ORF"); } mod camera_om_3_raw_modes { super::camera_file_check!("OM", "OM-3", cam_om_3_tripod_80mp_12bit_orf, "raw_modes/OM-3_Tripod_80mp_12bit.ORF"); super::camera_file_check!("OM", "OM-3", cam_om_3_handheld_20mp_12bit_ori, "raw_modes/OM-3_Handheld_20mp_12bit.ORI"); super::camera_file_check!("OM", "OM-3", cam_om_3_tripod_80mp_14bit_orf, "raw_modes/OM-3_Tripod_80mp_14bit.ORF"); super::camera_file_check!("OM", "OM-3", cam_om_3_handheld_20mp_14bit_ori, "raw_modes/OM-3_Handheld_20mp_14bit.ORI"); super::camera_file_check!("OM", "OM-3", cam_om_3_handheld_50mp_14bit_orf, "raw_modes/OM-3_Handheld_50mp_14bit.ORF"); super::camera_file_check!("OM", "OM-3", cam_om_3_tripod_20mp_12bit_ori, "raw_modes/OM-3_Tripod_20mp_12bit.ORI"); super::camera_file_check!("OM", "OM-3", cam_om_3_tripod_20mp_14bit_ori, "raw_modes/OM-3_Tripod_20mp_14bit.ORI"); super::camera_file_check!("OM", "OM-3", cam_om_3_20mp_12bit_orf, "raw_modes/OM-3_20mp_12bit.ORF"); super::camera_file_check!("OM", "OM-3", cam_om_3_handheld_50mp_12bit_orf, "raw_modes/OM-3_Handheld_50mp_12bit.ORF"); } mod camera_om_5_raw_modes { super::camera_file_check!("OM", "OM-5", cam_om_5_iso_100_16bits_tripod_hires_orf, "raw_modes/OM-5_ISO_100_16bits_tripod_hires.ORF"); super::camera_file_check!("OM", "OM-5", cam_om_5_iso_100_16bits_normal_orf, "raw_modes/OM-5_ISO_100_16bits_normal.ORF"); super::camera_file_check!("OM", "OM-5", cam_om_5_iso_100_16bits_handheld_hires_orf, "raw_modes/OM-5_ISO_100_16bits_handheld_hires.ORF"); } mod camera_tg_7_raw_modes { super::camera_file_check!("OM", "TG-7", cam_tg_7_iso_100_16bits_orf, "raw_modes/TG-7_ISO_100_16bits.ORF"); } rawler-0.7.1/tests/common/mod.rs000064400000000000000000000147321046102023000147130ustar 00000000000000// SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher //#[cfg(feature = "samplecheck")] use md5::Digest; use rawler::dng::convert::ConvertParams; use rawler::dng::convert::convert_raw_file; use rawler::{ analyze::{AnalyzerResult, analyze_metadata, extract_raw_pixels}, decoders::RawDecodeParams, }; use std::{ convert::TryInto, path::{Path, PathBuf}, }; use zerocopy::IntoBytes; macro_rules! camera_file_check { ($make:expr, $model:expr, $test:ident, $file:expr) => { #[allow(non_snake_case)] #[test] fn $test() -> std::result::Result<(), Box> { //crate::init_test_logger(); crate::common::check_camera_raw_file_conversion("cameras", $make, $model, $file) } }; } pub(crate) use camera_file_check; macro_rules! sample_file_check { ($sampleset:expr, $test:ident, $file:expr) => { #[allow(non_snake_case)] #[test] fn $test() -> std::result::Result<(), Box> { //crate::init_test_logger(); crate::common::check_sample_raw_file_conversion($sampleset, $file) } }; } pub(crate) use sample_file_check; pub(crate) fn rawdb_path() -> PathBuf { PathBuf::from(std::env::var("RAWLER_RAWDB").expect("RAWLER_RAWDB variable must be set in order to run RAW test!")) } pub(crate) fn rawdb_file(path: impl AsRef) -> PathBuf { let rawdb = rawdb_path(); rawdb.join(path) } pub(crate) fn check_md5_equal(digest: [u8; 16], expected: &str) { assert_eq!(hex::encode(digest), expected); } /// Generic function to check camera raw files against /// pre-generated stats and pixel files. pub(crate) fn check_camera_raw_file_conversion(category: &str, make: &str, model: &str, sample: &str) -> std::result::Result<(), Box> { let rawdb = PathBuf::from(std::env::var("RAWLER_RAWDB").expect("RAWLER_RAWDB variable must be set in order to run RAW test!")); let mut camera_rawdb = rawdb.clone(); camera_rawdb.push(category); let mut testfiles = PathBuf::from(env!("CARGO_MANIFEST_DIR")); testfiles.push("data/testdata"); let base_path = testfiles.join(category).join(make).join(model); let raw_file = camera_rawdb.join(make).join(model).join(sample); let filename = raw_file.file_name().map(|name| name.to_os_string()).expect("Filename must by OS string compatible"); let mut orig_analyze_file = filename.clone(); let mut orig_digest_file = filename.clone(); orig_analyze_file.push(".analyze.yaml"); orig_digest_file.push(".digest.txt"); let stats_file = base_path.join(sample).with_file_name(orig_analyze_file); let digest_file = base_path.join(sample).with_file_name(orig_digest_file); //let pixel_file = base_path.join(&sample).with_extension("pixel"); //eprintln!("{:?}", stats_file); assert!(raw_file.exists(), "Raw file {:?} not found", raw_file); assert!(stats_file.exists(), "Stats file {:?} not found", stats_file); // Validate stats file let new_stats = analyze_metadata(PathBuf::from(&raw_file)).unwrap(); let old_stats = std::fs::read_to_string(&stats_file)?; let old_stats: AnalyzerResult = serde_yaml::from_str(&old_stats)?; assert_eq!(old_stats, new_stats); // Validate pixel data let old_digest_str = std::fs::read_to_string(digest_file)?; let old_digest = Digest(TryInto::<[u8; 16]>::try_into(hex::decode(old_digest_str.trim()).expect("Malformed MD5 digest")).expect("Must be [u8; 16]")); let image = extract_raw_pixels(&raw_file, &RawDecodeParams::default()).unwrap(); let byte_buf = match &image.data { rawler::RawImageData::Integer(samples) => samples.as_slice().as_bytes(), rawler::RawImageData::Float(samples) => samples.as_slice().as_bytes(), }; let new_digest = md5::compute(byte_buf); assert_eq!(old_digest, new_digest, "Old and new raw pixel digest not match!"); // Convert to DNG with default params let params = ConvertParams { embedded: false, apply_scaling: false, ..Default::default() }; let mut dng = std::io::Cursor::new(Vec::new()); convert_raw_file(&raw_file, &mut dng, ¶ms)?; Ok(()) } /// Generic function to check camera raw files against /// pre-generated stats and pixel files. pub(crate) fn check_sample_raw_file_conversion(sampleset: &str, sample: &str) -> std::result::Result<(), Box> { let rawdb = PathBuf::from(std::env::var("RAWLER_RAWDB").expect("RAWLER_RAWDB variable must be set in order to run RAW test!")); let mut camera_rawdb = rawdb.clone(); camera_rawdb.push("samples"); let mut testfiles = PathBuf::from(env!("CARGO_MANIFEST_DIR")); testfiles.push("data/testdata/samples"); let base_path = testfiles.join(sampleset); let raw_file = camera_rawdb.join(sampleset).join(sample); let filename = raw_file.file_name().map(|name| name.to_os_string()).expect("Filename must by OS string compatible"); let mut orig_analyze_file = filename.clone(); let mut orig_digest_file = filename.clone(); orig_analyze_file.push(".analyze.yaml"); orig_digest_file.push(".digest.txt"); let stats_file = base_path.join(sample).with_file_name(orig_analyze_file); let digest_file = base_path.join(sample).with_file_name(orig_digest_file); //let pixel_file = base_path.join(&sample).with_extension("pixel"); //eprintln!("{:?}", stats_file); assert!(raw_file.exists(), "Raw file {:?} not found", raw_file); assert!(stats_file.exists(), "Stats file {:?} not found", stats_file); // Validate stats file let new_stats = analyze_metadata(PathBuf::from(&raw_file)).unwrap(); let old_stats = std::fs::read_to_string(&stats_file)?; let old_stats: AnalyzerResult = serde_yaml::from_str(&old_stats)?; assert_eq!(old_stats, new_stats); // Validate pixel data let old_digest_str = std::fs::read_to_string(digest_file)?; let old_digest = Digest(TryInto::<[u8; 16]>::try_into(hex::decode(old_digest_str.trim()).expect("Malformed MD5 digest")).expect("Must be [u8; 16]")); let image = extract_raw_pixels(&raw_file, &RawDecodeParams::default()).unwrap(); let byte_buf = match &image.data { rawler::RawImageData::Integer(samples) => samples.as_slice().as_bytes(), rawler::RawImageData::Float(samples) => samples.as_slice().as_bytes(), }; let new_digest = md5::compute(byte_buf); assert_eq!(old_digest, new_digest, "Old and new raw pixel digest not match!"); // Convert to DNG with default params let params = ConvertParams { embedded: false, apply_scaling: false, ..Default::default() }; let mut dng = std::io::Cursor::new(Vec::new()); convert_raw_file(&raw_file, &mut dng, ¶ms)?; Ok(()) } rawler-0.7.1/tests/dng/mod.rs000064400000000000000000000000011046102023000141530ustar 00000000000000 rawler-0.7.1/tests/issues/mod.rs000064400000000000000000000045001046102023000147260ustar 00000000000000use std::io::Cursor; use crate::common::check_md5_equal; use crate::common::rawdb_file; use rawler::dng::convert::ConvertParams; use rawler::dng::convert::convert_raw_file; use rawler::formats::jfif::Jfif; use rawler::rawsource::RawSource; use rawler::{analyze::raw_pixels_digest, decoders::RawDecodeParams}; #[test] fn dnglab_354_dng_mismatch_tile_dim_vs_ljpeg_sof_dim() -> std::result::Result<(), Box> { let path = rawdb_file("issues/dnglab_354/dnglab_354.dng"); let digest = raw_pixels_digest(path, &RawDecodeParams::default())?; check_md5_equal(digest, "e5fcd3fd81a3f8e2d9709b92f3b8f546"); Ok(()) } #[test] fn dnglab_366_monochrome_dng_support() -> std::result::Result<(), Box> { let path = rawdb_file("issues/dnglab_366/dnglab_366.dng"); let digest = raw_pixels_digest(&path, &RawDecodeParams::default())?; check_md5_equal(digest, "f3549fafda97fca90b9993c1278bcd90"); let mut dng = Cursor::new(Vec::new()); convert_raw_file(&path, &mut dng, &ConvertParams::default())?; Ok(()) } #[test] fn dnglab_376_canon_crx_craw_qstep_shl_bug() -> std::result::Result<(), Box> { { let path = rawdb_file("issues/dnglab_376/Canon_EOS_R6M2_CRAW_ISO_25600.CR3"); let digest = raw_pixels_digest(&path, &RawDecodeParams::default())?; check_md5_equal(digest, "66c9fcb6541c90bdfb06d876be5984ec"); let mut dng = Cursor::new(Vec::new()); convert_raw_file(&path, &mut dng, &ConvertParams::default())?; } { let path = rawdb_file("issues/dnglab_376/_MGC9382.CR3"); let digest = raw_pixels_digest(&path, &RawDecodeParams::default())?; check_md5_equal(digest, "aef96546a58e5265fb2f7b9e7498cbd0"); let mut dng = Cursor::new(Vec::new()); convert_raw_file(&path, &mut dng, &ConvertParams::default())?; } Ok(()) } #[test] fn dnglab_386_catch_jpeg_exif_tiff_ifd_error() -> std::result::Result<(), Box> { let path = rawdb_file("issues/dnglab_386/jpeg_ifd_error.jpg"); let rawfile = RawSource::new(&path)?; let jfif = Jfif::new(&rawfile)?; assert!(jfif.exif_ifd().is_none()); Ok(()) } #[test] fn dnglab_477_jpeg_quantization_table_with_zero_value() -> std::result::Result<(), Box> { let image = image::open(rawdb_file("issues/dnglab_477/dnglab_477.jpg"))?; let _ = image.to_rgb8(); Ok(()) } rawler-0.7.1/tests/mod.rs000064400000000000000000000003331046102023000134130ustar 00000000000000#[cfg(feature = "samplecheck")] mod cameras; #[cfg(feature = "samplecheck")] mod common; #[cfg(feature = "samplecheck")] mod dng; #[cfg(feature = "samplecheck")] mod issues; #[cfg(feature = "samplecheck")] mod samples; rawler-0.7.1/tests/rustfmt.toml000064400000000000000000000005611046102023000146720ustar 00000000000000#brace_style = "SameLineWhere" #comment_width = 160 #wrap_comments = true edition = "2021" #enum_discrim_align_threshold = 30 force_explicit_abi = true #format_strings = true max_width = 300 #imports_layout = "HorizontalVertical" merge_derives = true #imports_granularity = "Crate" reorder_imports = true #report_fixme = "Always" #report_todo = "Always" tab_spaces = 2 rawler-0.7.1/tests/samples/mod.rs000064400000000000000000000046351046102023000150700ustar 00000000000000use crate::common::sample_file_check; mod dng_compression_variants { super::sample_file_check!("dng-compression-variants", sample_10bit_dng, "10bit.dng"); super::sample_file_check!("dng-compression-variants", sample_dng_jpegxl_lossless_16bit_mosaic_tiles_dng, "dng_jpegxl_lossless_16bit_mosaic_tiles.dng"); super::sample_file_check!("dng-compression-variants", sample_lossy_tiles_dng, "lossy_tiles.dng"); super::sample_file_check!("dng-compression-variants", sample_ljpeg_tiles_dng, "ljpeg_tiles.dng"); super::sample_file_check!("dng-compression-variants", sample_12bit_dng, "12bit.dng"); super::sample_file_check!("dng-compression-variants", sample_dng_fp24_w_pred_deflate_dng, "dng-fp24-w-pred-deflate.dng"); super::sample_file_check!("dng-compression-variants", sample_uncompressed_multistrip_16row_dng, "uncompressed_multistrip_16row.dng"); super::sample_file_check!("dng-compression-variants", sample_8bit_lintable_dng, "8bit_lintable.dng"); super::sample_file_check!("dng-compression-variants", sample_dng_fp16_w_pred_deflate_dng, "dng-fp16-w-pred-deflate.dng"); super::sample_file_check!("dng-compression-variants", sample_dng_fp16_uncompressed_dng, "dng-fp16-uncompressed.dng"); super::sample_file_check!("dng-compression-variants", sample_ljpeg_singlestrip_dng, "ljpeg_singlestrip.dng"); super::sample_file_check!("dng-compression-variants", sample_dng_fp32_w_pred_deflate_dng, "dng-fp32-w-pred-deflate.dng"); super::sample_file_check!("dng-compression-variants", sample_dng_jpegxl_lossy_16bit_mosaic_tiles_dng, "dng_jpegxl_lossy_16bit_mosaic_tiles.dng"); super::sample_file_check!("dng-compression-variants", sample_origin_cr3, "origin.CR3"); super::sample_file_check!("dng-compression-variants", sample_dng_jpegxl_lossless_16bit_linear_tiles_dng, "dng_jpegxl_lossless_16bit_linear_tiles.dng"); super::sample_file_check!("dng-compression-variants", sample_uncompressed_multistrip_1row_dng, "uncompressed_multistrip_1row.dng"); super::sample_file_check!("dng-compression-variants", sample_dng_fp24_uncompressed_dng, "dng-fp24-uncompressed.dng"); super::sample_file_check!("dng-compression-variants", sample_16bit_bigend_dng, "16bit_bigend.dng"); super::sample_file_check!("dng-compression-variants", sample_dng_fp32_uncompressed_dng, "dng-fp32-uncompressed.dng"); super::sample_file_check!("dng-compression-variants", sample_dng_jpegxl_lossy_16bit_linear_tiles_dng, "dng_jpegxl_lossy_16bit_linear_tiles.dng"); } rawler-0.7.1/tests/supported_rawdb_sets.txt000064400000000000000000000641271046102023000173040ustar 00000000000000cameras/Apple/QuickTake 100/raw_modes cameras/Apple/QuickTake 150/raw_modes cameras/Canon/EOS 1000D/raw_modes cameras/Canon/EOS 100D/raw_modes cameras/Canon/EOS 10D/raw_modes cameras/Canon/EOS 1100D/raw_modes cameras/Canon/EOS 1200D/raw_modes cameras/Canon/EOS 1300D/raw_modes cameras/Canon/EOS-1D Mark III/raw_modes cameras/Canon/EOS-1D Mark II N/raw_modes cameras/Canon/EOS-1D Mark II/raw_modes cameras/Canon/EOS-1D Mark IV/raw_modes cameras/Canon/EOS-1D/raw_modes cameras/Canon/EOS-1Ds Mark III/raw_modes cameras/Canon/EOS-1Ds Mark II/raw_modes cameras/Canon/EOS-1Ds/raw_modes cameras/Canon/EOS-1D X Mark III/raw_modes cameras/Canon/EOS-1D X Mark III/crm cameras/Canon/EOS-1D X Mark II/raw_modes cameras/Canon/EOS-1D X/raw_modes cameras/Canon/EOS 2000D/raw_modes cameras/Canon/EOS 200D/raw_modes cameras/Canon/EOS 20D/raw_modes cameras/Canon/EOS 250D/raw_modes cameras/Canon/EOS 300D/raw_modes cameras/Canon/EOS 30D/raw_modes cameras/Canon/EOS 350D/raw_modes cameras/Canon/EOS 4000D/raw_modes cameras/Canon/EOS 400D/raw_modes cameras/Canon/EOS 40D/raw_modes cameras/Canon/EOS 450D/raw_modes cameras/Canon/EOS 500D/raw_modes cameras/Canon/EOS 50D/raw_modes cameras/Canon/EOS 550D/raw_modes cameras/Canon/EOS 5D Mark III/raw_modes cameras/Canon/EOS 5D Mark II/raw_modes cameras/Canon/EOS 5D Mark IV/raw_modes cameras/Canon/EOS 5D/raw_modes cameras/Canon/EOS 5DS/raw_modes cameras/Canon/EOS 5DS R/raw_modes cameras/Canon/EOS 600D/raw_modes cameras/Canon/EOS 60D/raw_modes cameras/Canon/EOS 650D/raw_modes cameras/Canon/EOS 6D Mark II/raw_modes cameras/Canon/EOS 6D/raw_modes cameras/Canon/EOS 700D/raw_modes cameras/Canon/EOS 70D/raw_modes cameras/Canon/EOS 750D/raw_modes cameras/Canon/EOS 760D/raw_modes cameras/Canon/EOS 77D/raw_modes cameras/Canon/EOS 7D Mark II/raw_modes cameras/Canon/EOS 7D/raw_modes cameras/Canon/EOS 800D/raw_modes cameras/Canon/EOS 80D/raw_modes cameras/Canon/EOS 850D/raw_modes cameras/Canon/EOS 90D/raw_modes cameras/Canon/EOS D2000C/raw_modes cameras/Canon/EOS D30/raw_modes cameras/Canon/EOS D60/raw_modes cameras/Canon/EOS Digital Rebel/raw_modes cameras/Canon/EOS Digital Rebel XSi/raw_modes cameras/Canon/EOS Digital Rebel XS/raw_modes cameras/Canon/EOS Digital Rebel XTi/raw_modes cameras/Canon/EOS Digital Rebel XT/raw_modes cameras/Canon/EOS Kiss Digital N/raw_modes cameras/Canon/EOS Kiss X3/raw_modes cameras/Canon/EOS Kiss X4/raw_modes cameras/Canon/EOS Kiss X80/raw_modes cameras/Canon/EOS Kiss X9/raw_modes cameras/Canon/EOS M100/raw_modes cameras/Canon/EOS M10/raw_modes cameras/Canon/EOS M200/raw_modes cameras/Canon/EOS M2/raw_modes cameras/Canon/EOS M3/raw_modes cameras/Canon/EOS M50m2/raw_modes cameras/Canon/EOS M50/raw_modes cameras/Canon/EOS M5/raw_modes cameras/Canon/EOS M6 Mark II/raw_modes cameras/Canon/EOS M6/raw_modes cameras/Canon/EOS M/raw_modes cameras/Canon/EOS R5/raw_modes cameras/Canon/EOS R5 Mark II/raw_modes cameras/Canon/EOS R5 Mark II/crm_movie_modes cameras/Canon/EOS R5 C/raw_modes cameras/Canon/EOS R5 C/crm cameras/Canon/EOS R6/raw_modes cameras/Canon/EOS R6 Mark II/raw_modes cameras/Canon/EOS R7/raw_modes cameras/Canon/EOS R8/raw_modes cameras/Canon/EOS R10/raw_modes cameras/Canon/EOS R50/raw_modes cameras/Canon/EOS R100/raw_modes cameras/Canon/EOS Rebel SL1/raw_modes cameras/Canon/EOS Rebel SL2/raw_modes cameras/Canon/EOS Rebel SL3/raw_modes cameras/Canon/EOS Rebel T100/raw_modes cameras/Canon/EOS Rebel T1i/raw_modes cameras/Canon/EOS Rebel T2i/raw_modes cameras/Canon/EOS Rebel T3i/raw_modes cameras/Canon/EOS Rebel T3/raw_modes cameras/Canon/EOS Rebel T4i/raw_modes cameras/Canon/EOS Rebel T5i/raw_modes cameras/Canon/EOS Rebel T5/raw_modes cameras/Canon/EOS Rebel T6i/raw_modes cameras/Canon/EOS Rebel T6/raw_modes cameras/Canon/EOS Rebel T6s/raw_modes cameras/Canon/EOS REBEL T7i/raw_modes cameras/Canon/EOS Rebel T7/raw_modes cameras/Canon/EOS RP/raw_modes cameras/Canon/EOS R/raw_modes cameras/Canon/IXUS900Ti/raw_modes cameras/Canon/IXY 220F/raw_modes cameras/Canon/PowerShot A480/raw_modes cameras/Canon/PowerShot A540/raw_modes cameras/Canon/PowerShot A550/raw_modes cameras/Canon/PowerShot A570 IS/raw_modes cameras/Canon/PowerShot A610/raw_modes cameras/Canon/PowerShot A620/raw_modes cameras/Canon/PowerShot A630/raw_modes cameras/Canon/PowerShot A640/raw_modes cameras/Canon/PowerShot A650/raw_modes cameras/Canon/PowerShot A710 IS/raw_modes cameras/Canon/PowerShot A720 IS/raw_modes cameras/Canon/PowerShot D10/raw_modes cameras/Canon/PowerShot ELPH 130 IS/raw_modes cameras/Canon/PowerShot G10/raw_modes cameras/Canon/PowerShot G11/raw_modes cameras/Canon/PowerShot G12/raw_modes cameras/Canon/PowerShot G15/raw_modes cameras/Canon/PowerShot G16/raw_modes cameras/Canon/PowerShot G1/raw_modes cameras/Canon/PowerShot G1 X Mark III/raw_modes cameras/Canon/PowerShot G1 X Mark II/raw_modes cameras/Canon/PowerShot G1 X/raw_modes cameras/Canon/PowerShot G2/raw_modes cameras/Canon/PowerShot G3/raw_modes cameras/Canon/PowerShot G3 X/raw_modes cameras/Canon/PowerShot G5/raw_modes cameras/Canon/PowerShot G5 X Mark II/raw_modes cameras/Canon/PowerShot G5 X/raw_modes cameras/Canon/PowerShot G6/raw_modes cameras/Canon/PowerShot G7 X Mark III/raw_modes cameras/Canon/PowerShot G7 X Mark II/raw_modes cameras/Canon/PowerShot G7 X/raw_modes cameras/Canon/PowerShot G9/raw_modes cameras/Canon/PowerShot G9 X Mark II/raw_modes cameras/Canon/PowerShot G9 X/raw_modes cameras/Canon/PowerShot Pro1/raw_modes cameras/Canon/PowerShot S100/raw_modes cameras/Canon/PowerShot S100V/raw_modes cameras/Canon/PowerShot S110/raw_modes cameras/Canon/PowerShot S120/raw_modes cameras/Canon/PowerShot S2 IS/raw_modes cameras/Canon/PowerShot S30/raw_modes cameras/Canon/PowerShot S3IS/raw_modes cameras/Canon/PowerShot S40/raw_modes cameras/Canon/PowerShot S45/raw_modes cameras/Canon/PowerShot S50/raw_modes cameras/Canon/PowerShot S5 IS/raw_modes cameras/Canon/PowerShot S60/raw_modes cameras/Canon/PowerShot S70/raw_modes cameras/Canon/PowerShot S90/raw_modes cameras/Canon/PowerShot S95/raw_modes cameras/Canon/PowerShot SD750/raw_modes cameras/Canon/PowerShot SX110 IS/raw_modes cameras/Canon/PowerShot SX160 IS/raw_modes cameras/Canon/PowerShot SX1 IS/raw_modes cameras/Canon/PowerShot SX260 HS/raw_modes cameras/Canon/PowerShot SX40 HS/raw_modes cameras/Canon/PowerShot SX50 HS/raw_modes cameras/Canon/PowerShot SX60 HS/raw_modes cameras/Canon/PowerShot SX70 HS/raw_modes cameras/Canon/SX150IS/raw_modes cameras/Pentax/ist DL2/raw_modes cameras/Pentax/K-5 II/raw_modes cameras/Pentax/645D/raw_modes cameras/Pentax/645Z/raw_modes cameras/Pentax/ist DL/raw_modes cameras/Pentax/K-3/raw_modes cameras/Pentax/K-3 III Monochrome/raw_modes cameras/Pentax/K-7/raw_modes cameras/Pentax/K-3 II/raw_modes cameras/Pentax/K-3 III/raw_modes cameras/Pentax/K-70/raw_modes cameras/Pentax/K-m/raw_modes cameras/Pentax/K-r/raw_modes cameras/Pentax/Kf/raw_modes cameras/Pentax/K-5 II s/raw_modes cameras/Pentax/ist DS/raw_modes cameras/Pentax/K-1 Mark II/raw_modes cameras/Pentax/ist D/raw_modes cameras/Pentax/K100D Super/raw_modes cameras/Pentax/K-S2/raw_modes cameras/Pentax/K-5/raw_modes cameras/Pentax/K10D/raw_modes cameras/Pentax/K100D/raw_modes cameras/Pentax/K-1/raw_modes cameras/Pentax/KP/raw_modes cameras/Pentax/K200D/raw_modes cameras/Pentax/K-S1/raw_modes cameras/Pentax/K-x/raw_modes cameras/Pentax/K20D/raw_modes cameras/Pentax/K110D/raw_modes cameras/Phase One/IQ3 100MP/raw_modes cameras/Phase One/H 25/raw_modes cameras/Phase One/iXM-100/raw_modes cameras/Phase One/IQ180/raw_modes cameras/Phase One/IQ4 150MP/raw_modes cameras/Phase One/IQ140/raw_modes cameras/Phase One/P30/raw_modes cameras/Phase One/IQ3 100MP Trichr/raw_modes cameras/Phase One/IQ150/raw_modes cameras/Phase One/iXM-RS150F/raw_modes cameras/Phase One/iXU-RS1000 NIR/raw_modes cameras/Phase One/P65/raw_modes cameras/Phase One/P20/raw_modes cameras/Phase One/P25/raw_modes cameras/Phase One/P25+/raw_modes cameras/Phase One/P45+/raw_modes cameras/Nikon/D3500/raw_modes cameras/Nikon/1 V2/raw_modes cameras/Nikon/D40X/raw_modes cameras/Nikon/D5600/raw_modes cameras/Nikon/D70s/raw_modes cameras/Nikon/Coolpix P7100/raw_modes cameras/Nikon/D600/raw_modes cameras/Nikon/D2X/raw_modes cameras/Nikon/D40/raw_modes cameras/Nikon/D4/raw_modes cameras/Nikon/D300S/raw_modes cameras/Nikon/D2Xs/raw_modes cameras/Nikon/D3/raw_modes cameras/Nikon/D800E/raw_modes cameras/Nikon/E5400/raw_modes cameras/Nikon/Coolpix P6000/raw_modes cameras/Nikon/D700/raw_modes cameras/Nikon/Coolpix P7000/raw_modes cameras/Nikon/D3400/raw_modes cameras/Nikon/D780/raw_modes cameras/Nikon/D2Hs/raw_modes cameras/Nikon/1 V1/raw_modes cameras/Nikon/D610/raw_modes cameras/Nikon/1 J3/raw_modes cameras/Nikon/D50/raw_modes cameras/Nikon/D3X/raw_modes cameras/Nikon/D5500/raw_modes cameras/Nikon/D500/raw_modes cameras/Nikon/COOLPIX B700/raw_modes cameras/Nikon/Coolpix P7800/raw_modes cameras/Nikon/COOLPIX P1000/raw_modes cameras/Nikon/E5700/raw_modes cameras/Nikon/D850/raw_modes cameras/Nikon/D2H/raw_modes cameras/Nikon/D7500/raw_modes cameras/Nikon/Coolpix A/raw_modes cameras/Nikon/D3300/raw_modes cameras/Nikon/D5000/raw_modes cameras/Nikon/D7100/raw_modes cameras/Nikon/1 S2/raw_modes cameras/Nikon/D90/raw_modes cameras/Nikon/1 AW1/raw_modes cameras/Nikon/D5/raw_modes cameras/Nikon/COOLPIX A1000/raw_modes cameras/Nikon/E8400/raw_modes cameras/Nikon/D100/raw_modes cameras/Nikon/D810/raw_modes cameras/Nikon/1 J1/raw_modes cameras/Nikon/D7000/raw_modes cameras/Nikon/1 V3/raw_modes cameras/Nikon/D5100/raw_modes cameras/Nikon/D60/raw_modes cameras/Nikon/D3200/raw_modes cameras/Nikon/D750/raw_modes cameras/Nikon/D80/raw_modes cameras/Nikon/D3000/raw_modes cameras/Nikon/D5300/raw_modes cameras/Nikon/Coolpix P340/raw_modes cameras/Nikon/1 J5/raw_modes cameras/Nikon/D4S/raw_modes cameras/Nikon/D7200/raw_modes cameras/Nikon/D300/raw_modes cameras/Nikon/D1/raw_modes cameras/Nikon/D200/raw_modes cameras/Nikon/D1X/raw_modes cameras/Nikon/D70/raw_modes cameras/Nikon/Coolpix P330/raw_modes cameras/Nikon/1 J2/raw_modes cameras/Nikon/D5200/raw_modes cameras/Nikon/D3S/raw_modes cameras/Nikon/Df/raw_modes cameras/Nikon/D800/raw_modes cameras/Nikon/D3100/raw_modes cameras/Nikon/Z 5/raw_modes cameras/Nikon/Z 5 II/raw_modes cameras/Nikon/NIKON Z 6_2/raw_modes cameras/Nikon/NIKON Z 6_3/raw_modes cameras/Nikon/NIKON Z 7_2/raw_modes cameras/Nikon/Z 30/raw_modes cameras/Nikon/Z 50/raw_modes cameras/Nikon/Z 50 II/raw_modes cameras/Nikon/Z 6/raw_modes cameras/Nikon/NIKON Z f/raw_modes cameras/Nikon/NIKON Z fc/raw_modes cameras/Nikon/Z 7/raw_modes cameras/Nikon/NIKON Z 9/raw_modes cameras/Nikon/NIKON Z 8/raw_modes cameras/Sony/DSC-F828/raw_modes cameras/Sony/DSC-HX95/raw_modes cameras/Sony/DSC-HX99/raw_modes cameras/Sony/DSC-R1/raw_modes cameras/Sony/DSC-RX0M2/raw_modes cameras/Sony/DSC-RX0/raw_modes cameras/Sony/DSC-RX100M2/raw_modes cameras/Sony/DSC-RX100M3/raw_modes cameras/Sony/DSC-RX100M4/raw_modes cameras/Sony/DSC-RX100M5A/raw_modes cameras/Sony/DSC-RX100M5/raw_modes cameras/Sony/DSC-RX100M6/raw_modes cameras/Sony/DSC-RX100M7/raw_modes cameras/Sony/DSC-RX100/raw_modes cameras/Sony/DSC-RX10M2/raw_modes cameras/Sony/DSC-RX10M3/raw_modes cameras/Sony/DSC-RX10M4/raw_modes cameras/Sony/DSC-RX10/raw_modes cameras/Sony/DSC-RX1/raw_modes cameras/Sony/DSC-RX1RM2/raw_modes cameras/Sony/DSC-RX1R/raw_modes cameras/Sony/DSLR-A100/raw_modes cameras/Sony/DSLR-A200/raw_modes cameras/Sony/DSLR-A230/raw_modes cameras/Sony/DSLR-A290/raw_modes cameras/Sony/DSLR-A300/raw_modes cameras/Sony/DSLR-A330/raw_modes cameras/Sony/DSLR-A350/raw_modes cameras/Sony/DSLR-A380/raw_modes cameras/Sony/DSLR-A390/raw_modes cameras/Sony/DSLR-A450/raw_modes cameras/Sony/DSLR-A500/raw_modes cameras/Sony/DSLR-A550/raw_modes cameras/Sony/DSLR-A560/raw_modes cameras/Sony/DSLR-A580/raw_modes cameras/Sony/DSLR-A700/raw_modes cameras/Sony/DSLR-A850/raw_modes cameras/Sony/DSLR-A900/raw_modes cameras/Sony/ILCA-68/raw_modes cameras/Sony/ILCA-77M2/raw_modes cameras/Sony/ILCA-99M2/raw_modes cameras/Sony/ILME-FX30/raw_modes cameras/Sony/ILME-FX3/raw_modes cameras/Sony/ILCE-1/raw_modes cameras/Sony/ILCE-3000/raw_modes cameras/Sony/ILCE-3500/raw_modes cameras/Sony/ILCE-5000/raw_modes cameras/Sony/ILCE-5100/raw_modes cameras/Sony/ILCE-6000/raw_modes cameras/Sony/ILCE-6001/raw_modes cameras/Sony/ILCE-6100/raw_modes cameras/Sony/ILCE-6300/raw_modes cameras/Sony/ILCE-6400/raw_modes cameras/Sony/ILCE-6500/raw_modes cameras/Sony/ILCE-6600/raw_modes cameras/Sony/ILCE-6700/raw_modes cameras/Sony/ILCE-7CR/raw_modes cameras/Sony/ILCE-7C/raw_modes cameras/Sony/ILCE-7CM2/raw_modes cameras/Sony/ILCE-7M2/raw_modes cameras/Sony/ILCE-7M3/raw_modes cameras/Sony/ILCE-7M4/raw_modes cameras/Sony/ILCE-7M4/resolutions cameras/Sony/ILCE-7/raw_modes cameras/Sony/ILCE-7RM2/raw_modes cameras/Sony/ILCE-7RM3A/raw_modes cameras/Sony/ILCE-7RM3/raw_modes cameras/Sony/ILCE-7RM4A/raw_modes cameras/Sony/ILCE-7RM4/raw_modes cameras/Sony/ILCE-7RM5/raw_modes cameras/Sony/ILCE-7RM5/yuv cameras/Sony/ILCE-7R/raw_modes cameras/Sony/ILCE-7SM2/raw_modes cameras/Sony/ILCE-7SM3/raw_modes cameras/Sony/ILCE-7S/raw_modes cameras/Sony/ILCE-9M2/raw_modes cameras/Sony/ILCE-9M3/raw_modes cameras/Sony/ILCE-9/raw_modes cameras/Sony/ILCE-QX1/raw_modes cameras/Sony/NEX-3N/raw_modes cameras/Sony/NEX-3/raw_modes cameras/Sony/NEX-5N/raw_modes cameras/Sony/NEX-5/raw_modes cameras/Sony/NEX-5R/raw_modes cameras/Sony/NEX-5T/raw_modes cameras/Sony/NEX-6/raw_modes cameras/Sony/NEX-7/raw_modes cameras/Sony/NEX-C3/raw_modes cameras/Sony/NEX-F3/raw_modes cameras/Sony/SLT-A33/raw_modes cameras/Sony/SLT-A35/raw_modes cameras/Sony/SLT-A37/raw_modes cameras/Sony/SLT-A55/raw_modes cameras/Sony/SLT-A57/raw_modes cameras/Sony/SLT-A58/raw_modes cameras/Sony/SLT-A65/raw_modes cameras/Sony/SLT-A77/raw_modes cameras/Sony/SLT-A99/raw_modes cameras/Sony/ZV-1/raw_modes cameras/Sony/ZV-E1/raw_modes cameras/Sony/ZV-E10/raw_modes cameras/Sony/ZV-E10M2/raw_modes cameras/Sony/UMC-R10C/raw_modes cameras/Epson/R-D1/raw_modes cameras/Epson/R-D1s/raw_modes cameras/Epson/R-D1x/raw_modes cameras/Leaf/Aptus 22/raw_modes cameras/Leaf/Aptus 75/raw_modes cameras/Leaf/Credo 40/raw_modes cameras/Arri/Alexa 65/raw_modes cameras/Arri/Alexa LF/raw_modes cameras/Arri/Alexa Mini/raw_modes cameras/Arri/Alexa SXT/raw_modes cameras/Arri/Alexa XT/raw_modes cameras/Minolta/ALPHA-7 DIGITAL/raw_modes cameras/Minolta/DiMAGE 7Hi/raw_modes cameras/Minolta/DiMAGE 7i/raw_modes cameras/Minolta/DiMAGE 7/raw_modes cameras/Minolta/DiMAGE A1/raw_modes cameras/Minolta/DiMAGE A200/raw_modes cameras/Minolta/DiMAGE A2/raw_modes cameras/Minolta/DiMAGE G600/raw_modes cameras/Minolta/Dynax 7D/raw_modes cameras/Minolta/Maxxum 7D/raw_modes cameras/Mamiya/ZD/raw_modes cameras/Hasselblad/CFV-50/raw_modes cameras/Hasselblad/CFV/raw_modes cameras/Hasselblad/H3D/raw_modes cameras/Hasselblad/H4D-50/raw_modes cameras/Hasselblad/H5D-40/raw_modes cameras/Hasselblad/H5D-50c/raw_modes cameras/Hasselblad/Hasselblad H4D-40/raw_modes cameras/Hasselblad/Hasselblad H4D/raw_modes cameras/Hasselblad/Hasselblad H6D-100cMS/raw_modes cameras/Hasselblad/Hasselblad X1D/raw_modes cameras/Hasselblad/Hasselblad X2D 100C/raw_modes cameras/Hasselblad/X1D II 50C/raw_modes cameras/Samsung/EX1/raw_modes cameras/Samsung/EX2F/raw_modes cameras/Samsung/NX1000/raw_modes cameras/Samsung/NX100/raw_modes cameras/Samsung/NX1100/raw_modes cameras/Samsung/NX1/raw_modes cameras/Samsung/NX2000/raw_modes cameras/Samsung/NX200/raw_modes cameras/Samsung/NX20/raw_modes cameras/Samsung/NX210/raw_modes cameras/Samsung/NX3000/raw_modes cameras/Samsung/NX3300/raw_modes cameras/Samsung/NX300M/raw_modes cameras/Samsung/NX300/raw_modes cameras/Samsung/NX30/raw_modes cameras/Samsung/NX500/raw_modes cameras/Samsung/NX mini/raw_modes cameras/Samsung/WB2000/raw_modes cameras/Kodak/DC120/raw_modes cameras/Kodak/DC50/raw_modes cameras/Kodak/DCS460D/raw_modes cameras/Kodak/DCS560C/raw_modes cameras/Kodak/DCS760C/raw_modes cameras/Kodak/DCS Pro 14N/raw_modes cameras/Kodak/DCS Pro 14nx/raw_modes cameras/Kodak/DCS Pro SLRc/raw_modes cameras/Kodak/DCS Pro SLRn/raw_modes cameras/Kodak/EasyShare Z981/raw_modes cameras/Kodak/EasyShare Z990/raw_modes cameras/Kodak/EOS DCS 1/raw_modes cameras/Kodak/EOS DCS 3/raw_modes cameras/Kodak/KODAK P712 ZOOM DIGITAL CAMERA/raw_modes cameras/Kodak/P880/raw_modes cameras/Kodak/Z1015 IS/raw_modes cameras/Olympus/C5050Z/raw_modes cameras/Olympus/C5060WZ/raw_modes cameras/Olympus/C7070WZ/raw_modes cameras/Olympus/C8080WZ/raw_modes cameras/Olympus/E-10/raw_modes cameras/Olympus/E-1/raw_modes cameras/Olympus/E-20/raw_modes cameras/Olympus/E-300/raw_modes cameras/Olympus/E-30/raw_modes cameras/Olympus/E-330/raw_modes cameras/Olympus/E-3/raw_modes cameras/Olympus/E-400/raw_modes cameras/Olympus/E-410/raw_modes cameras/Olympus/E-420/raw_modes cameras/Olympus/E-450/raw_modes cameras/Olympus/E-500/raw_modes cameras/Olympus/E-510/raw_modes cameras/Olympus/E-520/raw_modes cameras/Olympus/E-5/raw_modes cameras/Olympus/E-600/raw_modes cameras/Olympus/E-620/raw_modes cameras/Olympus/E-M10 Mark III/raw_modes cameras/Olympus/E-M10MarkIIIS/raw_modes cameras/Olympus/E-M10 Mark II/raw_modes cameras/Olympus/E-M10 Mark IV/raw_modes cameras/Olympus/E-M10/raw_modes cameras/Olympus/E-M1MarkIII/raw_modes cameras/Olympus/E-M1MarkII/raw_modes cameras/Olympus/E-M1/raw_modes cameras/Olympus/E-M1X/raw_modes cameras/Olympus/E-M5 Mark III/raw_modes cameras/Olympus/E-M5 Mark II/raw_modes cameras/Olympus/E-M5/raw_modes cameras/Olympus/E-P1/raw_modes cameras/Olympus/E-P2/raw_modes cameras/Olympus/E-P3/raw_modes cameras/Olympus/E-P5/raw_modes cameras/Olympus/E-PL10/raw_modes cameras/Olympus/E-PL1/raw_modes cameras/Olympus/E-PL2/raw_modes cameras/Olympus/E-PL3/raw_modes cameras/Olympus/E-PL5/raw_modes cameras/Olympus/E-PL6/raw_modes cameras/Olympus/E-PL7/raw_modes cameras/Olympus/E-PL8/raw_modes cameras/Olympus/E-PL9/raw_modes cameras/Olympus/E-PM1/raw_modes cameras/Olympus/E-PM2/raw_modes cameras/Olympus/PEN-F/raw_modes cameras/Olympus/SH-2/raw_modes cameras/Olympus/SP350/raw_modes cameras/Olympus/SP500UZ/raw_modes cameras/Olympus/SP510UZ/raw_modes cameras/Olympus/SP565UZ/raw_modes cameras/Olympus/SP570UZ/raw_modes cameras/Olympus/Stylus1/raw_modes cameras/Olympus/TG-4/raw_modes cameras/Olympus/TG-5/raw_modes cameras/Olympus/TG-6/raw_modes cameras/Olympus/XZ-10/raw_modes cameras/Olympus/XZ-1/raw_modes cameras/Olympus/XZ-2/raw_modes cameras/Panasonic/DC-FZ10002/raw_modes cameras/Panasonic/DC-FZ45/raw_modes cameras/Panasonic/DC-FZ80/raw_modes cameras/Panasonic/DC-FZ82/raw_modes cameras/Panasonic/DC-G100/raw_modes cameras/Panasonic/DC-G110/raw_modes cameras/Panasonic/DC-G90/raw_modes cameras/Panasonic/DC-G91/raw_modes cameras/Panasonic/DC-G95/raw_modes cameras/Panasonic/DC-G9/raw_modes cameras/Panasonic/DC-G9M2/raw_modes cameras/Panasonic/DC-GF10/raw_modes cameras/Panasonic/DC-GH5M2/raw_modes cameras/Panasonic/DC-GH5/raw_modes cameras/Panasonic/DC-GH5S/raw_modes cameras/Panasonic/DC-GH6/raw_modes cameras/Panasonic/DC-GH7/raw_modes cameras/Panasonic/DC-GX7MK3/raw_modes cameras/Panasonic/DC-GX800/raw_modes cameras/Panasonic/DC-GX850/raw_modes cameras/Panasonic/DC-GX880/raw_modes cameras/Panasonic/DC-GX9/raw_modes cameras/Panasonic/DC-LX100M2/raw_modes cameras/Panasonic/DC-S1H/raw_modes cameras/Panasonic/DC-S1/raw_modes cameras/Panasonic/DC-S1R/raw_modes cameras/Panasonic/DC-S1RM2/raw_modes cameras/Panasonic/DC-S5/raw_modes cameras/Panasonic/DC-S5M2/raw_modes cameras/Panasonic/DC-S5M2X/raw_modes cameras/Panasonic/DC-S9/raw_modes cameras/Panasonic/DC-TZ200/raw_modes cameras/Panasonic/DC-TZ202/raw_modes cameras/Panasonic/DC-TZ90/raw_modes cameras/Panasonic/DC-TZ91/raw_modes cameras/Panasonic/DC-TZ95/raw_modes cameras/Panasonic/DC-TZ96/raw_modes cameras/Panasonic/DC-TZ220D/raw_modes cameras/Panasonic/DMC-CM1/raw_modes cameras/Panasonic/DMC-FX150/raw_modes cameras/Panasonic/DMC-FZ1000/raw_modes cameras/Panasonic/DMC-FZ100/raw_modes cameras/Panasonic/DMC-FZ150/raw_modes cameras/Panasonic/DMC-FZ18/raw_modes cameras/Panasonic/DMC-FZ2000/raw_modes cameras/Panasonic/DMC-FZ200/raw_modes cameras/Panasonic/DMC-FZ2500/raw_modes cameras/Panasonic/DMC-FZ28/raw_modes cameras/Panasonic/DMC-FZ300/raw_modes cameras/Panasonic/DMC-FZ30/raw_modes cameras/Panasonic/DMC-FZ330/raw_modes cameras/Panasonic/DMC-FZ35/raw_modes cameras/Panasonic/DMC-FZ38/raw_modes cameras/Panasonic/DMC-FZ45/raw_modes cameras/Panasonic/DMC-FZ50/raw_modes cameras/Panasonic/DMC-FZ70/raw_modes cameras/Panasonic/DMC-FZ72/raw_modes cameras/Panasonic/DMC-FZ8/raw_modes cameras/Panasonic/DMC-G10/raw_modes cameras/Panasonic/DMC-G1/raw_modes cameras/Panasonic/DMC-G2/raw_modes cameras/Panasonic/DMC-G3/raw_modes cameras/Panasonic/DMC-G5/raw_modes cameras/Panasonic/DMC-G6/raw_modes cameras/Panasonic/DMC-G70/raw_modes cameras/Panasonic/DMC-G7/raw_modes cameras/Panasonic/DMC-G80/raw_modes cameras/Panasonic/DMC-G81/raw_modes cameras/Panasonic/DMC-G85/raw_modes cameras/Panasonic/DMC-GF1/raw_modes cameras/Panasonic/DMC-GF2/raw_modes cameras/Panasonic/DMC-GF3/raw_modes cameras/Panasonic/DMC-GF5/raw_modes cameras/Panasonic/DMC-GF6/raw_modes cameras/Panasonic/DMC-GF7/raw_modes cameras/Panasonic/DMC-GF8/raw_modes cameras/Panasonic/DMC-GH1/raw_modes cameras/Panasonic/DMC-GH2/raw_modes cameras/Panasonic/DMC-GH3/raw_modes cameras/Panasonic/DMC-GH4/raw_modes cameras/Panasonic/DMC-GM1/raw_modes cameras/Panasonic/DMC-GM1S/raw_modes cameras/Panasonic/DMC-GM5/raw_modes cameras/Panasonic/DMC-GX1/raw_modes cameras/Panasonic/DMC-GX7MK2/raw_modes cameras/Panasonic/DMC-GX7/raw_modes cameras/Panasonic/DMC-GX80/raw_modes cameras/Panasonic/DMC-GX85/raw_modes cameras/Panasonic/DMC-GX8/raw_modes cameras/Panasonic/DMC-L10/raw_modes cameras/Panasonic/DMC-L1/raw_modes cameras/Panasonic/DMC-LF1/raw_modes cameras/Panasonic/DMC-LX100/raw_modes cameras/Panasonic/DMC-LX10/raw_modes cameras/Panasonic/DMC-LX15/raw_modes cameras/Panasonic/DMC-LX1/raw_modes cameras/Panasonic/DMC-LX2/raw_modes cameras/Panasonic/DMC-LX3/raw_modes cameras/Panasonic/DMC-LX5/raw_modes cameras/Panasonic/DMC-LX7/raw_modes cameras/Panasonic/DMC-TX1/raw_modes cameras/Panasonic/DMC-TZ100/raw_modes cameras/Panasonic/DMC-TZ101/raw_modes cameras/Panasonic/DMC-TZ110/raw_modes cameras/Panasonic/DMC-TZ60/raw_modes cameras/Panasonic/DMC-TZ61/raw_modes cameras/Panasonic/DMC-TZ70/raw_modes cameras/Panasonic/DMC-TZ71/raw_modes cameras/Panasonic/DMC-TZ80/raw_modes cameras/Panasonic/DMC-TZ81/raw_modes cameras/Panasonic/DMC-ZS100/raw_modes cameras/Panasonic/DMC-ZS40/raw_modes cameras/Panasonic/DMC-ZS60/raw_modes cameras/Sigma/SIGMA fp/cinemadng cameras/Leica/C-Lux/raw_modes cameras/Leica/C Typ 112/raw_modes cameras/Leica/Digilux 2/raw_modes cameras/Leica/Digilux 3/raw_modes cameras/Leica/D-LUX 3/raw_modes cameras/Leica/D-LUX 4/raw_modes cameras/Leica/D-LUX 5/raw_modes cameras/Leica/D-LUX 7/raw_modes cameras/Leica/D-LUX Typ 109/raw_modes cameras/Leica/V-LUX 1/raw_modes cameras/Leica/V-LUX 4/raw_modes cameras/Leica/V-LUX 5/raw_modes cameras/Leica/V-LUX Typ 114/raw_modes cameras/Fujifilm/DBP for GX680/raw_modes cameras/Fujifilm/FinePix E550/raw_modes cameras/Fujifilm/FinePix E900/raw_modes cameras/Fujifilm/FinePix F550EXR/raw_modes cameras/Fujifilm/FinePix F600EXR/raw_modes cameras/Fujifilm/FinePix F700/raw_modes cameras/Fujifilm/FinePix F770EXR/raw_modes cameras/Fujifilm/FinePix F900EXR/raw_modes cameras/Fujifilm/FinePix HS10 HS11/raw_modes cameras/Fujifilm/FinePix HS20EXR/raw_modes cameras/Fujifilm/FinePix HS30EXR/raw_modes cameras/Fujifilm/FinePix HS33EXR/raw_modes cameras/Fujifilm/FinePix HS50EXR/raw_modes cameras/Fujifilm/FinePix S100FS/raw_modes cameras/Fujifilm/FinePix SL1000/raw_modes cameras/Fujifilm/FinePix S1/raw_modes cameras/Fujifilm/FinePix S200EXR/raw_modes cameras/Fujifilm/FinePix S2Pro/raw_modes cameras/Fujifilm/FinePix S3Pro/raw_modes cameras/Fujifilm/FinePix S5000/raw_modes cameras/Fujifilm/FinePix S5200/raw_modes cameras/Fujifilm/FinePix S5500/raw_modes cameras/Fujifilm/FinePix S5600/raw_modes cameras/Fujifilm/FinePix S5Pro/raw_modes cameras/Fujifilm/FinePix S6500fd/raw_modes cameras/Fujifilm/FinePix S7000/raw_modes cameras/Fujifilm/FinePix S9500/raw_modes cameras/Fujifilm/FinePix S9600/raw_modes cameras/Fujifilm/FinePix X100/raw_modes cameras/Fujifilm/FinePix X10/raw_modes cameras/Fujifilm/GFX 100/compressed cameras/Fujifilm/GFX 100/raw_modes cameras/Fujifilm/GFX 100RF/raw_modes cameras/Fujifilm/GFX 100 II/raw_modes cameras/Fujifilm/GFX100S/compressed cameras/Fujifilm/GFX100S/raw_modes cameras/Fujifilm/GFX 100S II/raw_modes cameras/Fujifilm/GFX 50R/compressed cameras/Fujifilm/GFX 50R/raw_modes cameras/Fujifilm/GFX 50S/compressed cameras/Fujifilm/GFX50S II/compressed cameras/Fujifilm/GFX50S II/raw_modes cameras/Fujifilm/GFX 50S/raw_modes cameras/Fujifilm/X100F/compressed cameras/Fujifilm/X100F/raw_modes cameras/Fujifilm/X100S/raw_modes cameras/Fujifilm/X100T/raw_modes cameras/Fujifilm/X100V/compressed cameras/Fujifilm/X100V/raw_modes cameras/Fujifilm/X100VI/raw_modes cameras/Fujifilm/X20/raw_modes cameras/Fujifilm/X30/raw_modes cameras/Fujifilm/X70/raw_modes cameras/Fujifilm/X-A10/raw_modes cameras/Fujifilm/X-A1/raw_modes cameras/Fujifilm/X-A2/raw_modes cameras/Fujifilm/X-A3/raw_modes cameras/Fujifilm/X-A5/raw_modes cameras/Fujifilm/X-A7/raw_modes cameras/Fujifilm/X-E1/raw_modes cameras/Fujifilm/X-E2/raw_modes cameras/Fujifilm/X-E2S/raw_modes cameras/Fujifilm/X-E3/compressed cameras/Fujifilm/X-E3/raw_modes cameras/Fujifilm/X-E4/compressed cameras/Fujifilm/X-E4/raw_modes cameras/Fujifilm/X-E5/raw_modes cameras/Fujifilm/XF10/raw_modes cameras/Fujifilm/XF1/raw_modes cameras/Fujifilm/X-H1/compressed cameras/Fujifilm/X-H1/raw_modes cameras/Fujifilm/X-H2S/raw_modes cameras/Fujifilm/X-H2/raw_modes cameras/Fujifilm/X-M1/raw_modes cameras/Fujifilm/X-M5/raw_modes cameras/Fujifilm/X-Pro1/raw_modes cameras/Fujifilm/X-Pro2/compressed cameras/Fujifilm/X-Pro2/raw_modes cameras/Fujifilm/X-Pro3/compressed cameras/Fujifilm/X-Pro3/raw_modes cameras/Fujifilm/XQ1/raw_modes cameras/Fujifilm/XQ2/raw_modes cameras/Fujifilm/X-S10/compressed cameras/Fujifilm/X-S10/raw_modes cameras/Fujifilm/X-S20/raw_modes cameras/Fujifilm/X-S1/raw_modes cameras/Fujifilm/X-T100/raw_modes cameras/Fujifilm/X-T10/raw_modes cameras/Fujifilm/X-T1/raw_modes cameras/Fujifilm/X-T200/raw_modes cameras/Fujifilm/X-T20/compressed cameras/Fujifilm/X-T20/raw_modes cameras/Fujifilm/X-T2/compressed cameras/Fujifilm/X-T2/raw_modes cameras/Fujifilm/X-T30/compressed cameras/Fujifilm/X-T30 II/compressed cameras/Fujifilm/X-T30 II/raw_modes cameras/Fujifilm/X-T30/raw_modes cameras/Fujifilm/X-T3/compressed cameras/Fujifilm/X-T3/raw_modes cameras/Fujifilm/X-T4/raw_modes cameras/Fujifilm/X-T4/compressed cameras/Fujifilm/X-T5/raw_modes cameras/Fujifilm/X-T50/raw_modes cameras/OM/OM-1/raw_modes cameras/OM/OM-1 Mark II/raw_modes cameras/OM/OM-3/raw_modes cameras/OM/OM-5/raw_modes cameras/OM/TG-7/raw_modes rawler-0.7.1/tests/supported_sample_sets.txt000064400000000000000000000000411046102023000174470ustar 00000000000000samples/dng-compression-variants