diff --git a/third_party/rawler-0.7.2/.cargo_vcs_info.json b/third_party/rawler-0.7.2/.cargo_vcs_info.json new file mode 100644 index 0000000..3c5c70e --- /dev/null +++ b/third_party/rawler-0.7.2/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ff7a4524cc7187554544269482e5fd5e68a6b4ab" + }, + "path_in_vcs": "rawler" +} \ No newline at end of file diff --git a/third_party/rawler-0.7.2/.gitignore b/third_party/rawler-0.7.2/.gitignore new file mode 100644 index 0000000..a9d37c5 --- /dev/null +++ b/third_party/rawler-0.7.2/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/third_party/rawler-0.7.2/Cargo.toml b/third_party/rawler-0.7.2/Cargo.toml new file mode 100644 index 0000000..918a0ab --- /dev/null +++ b/third_party/rawler-0.7.2/Cargo.toml @@ -0,0 +1,177 @@ +# 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.88" +name = "rawler" +version = "0.7.2" +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" diff --git a/third_party/rawler-0.7.2/Cargo.toml.orig b/third_party/rawler-0.7.2/Cargo.toml.orig new file mode 100644 index 0000000..6ac493a --- /dev/null +++ b/third_party/rawler-0.7.2/Cargo.toml.orig @@ -0,0 +1,74 @@ +[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.88" +version = "0.7.2" + +# 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" diff --git a/third_party/rawler-0.7.2/LICENSE b/third_party/rawler-0.7.2/LICENSE new file mode 100644 index 0000000..86cd459 --- /dev/null +++ b/third_party/rawler-0.7.2/LICENSE @@ -0,0 +1,504 @@ +GNU 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! \ No newline at end of file diff --git a/third_party/rawler-0.7.2/README.md b/third_party/rawler-0.7.2/README.md new file mode 100644 index 0000000..bbce0db --- /dev/null +++ b/third_party/rawler-0.7.2/README.md @@ -0,0 +1,18 @@ +# 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. + diff --git a/third_party/rawler-0.7.2/benches/perf.rs b/third_party/rawler-0.7.2/benches/perf.rs new file mode 100644 index 0000000..88331c7 --- /dev/null +++ b/third_party/rawler-0.7.2/benches/perf.rs @@ -0,0 +1,49 @@ +use 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); diff --git a/third_party/rawler-0.7.2/benches/raw_decoder.rs b/third_party/rawler-0.7.2/benches/raw_decoder.rs new file mode 100644 index 0000000..8e2da0a --- /dev/null +++ b/third_party/rawler-0.7.2/benches/raw_decoder.rs @@ -0,0 +1,100 @@ +use 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); diff --git a/third_party/rawler-0.7.2/data/cameras/apple/quicktake100.toml b/third_party/rawler-0.7.2/data/cameras/apple/quicktake100.toml new file mode 100644 index 0000000..be7eda7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/apple/quicktake100.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/apple/quicktake150.toml b/third_party/rawler-0.7.2/data/cameras/apple/quicktake150.toml new file mode 100644 index 0000000..04599b6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/apple/quicktake150.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/arri/alexa.toml b/third_party/rawler-0.7.2/data/cameras/arri/alexa.toml new file mode 100644 index 0000000..e100db6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/arri/alexa.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/arri/alexa_65.toml b/third_party/rawler-0.7.2/data/cameras/arri/alexa_65.toml new file mode 100644 index 0000000..eca95dc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/arri/alexa_65.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/arri/alexa_lf.toml b/third_party/rawler-0.7.2/data/cameras/arri/alexa_lf.toml new file mode 100644 index 0000000..20800eb --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/arri/alexa_lf.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/arri/alexa_mini.toml b/third_party/rawler-0.7.2/data/cameras/arri/alexa_mini.toml new file mode 100644 index 0000000..cfacff7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/arri/alexa_mini.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1000d.toml b/third_party/rawler-0.7.2/data/cameras/canon/1000d.toml new file mode 100644 index 0000000..56b2c11 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1000d.toml @@ -0,0 +1,20 @@ +make = "Canon" +model = "Canon EOS 1000D" +clean_make = "Canon" +clean_model = "EOS 1000D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL XS", "EOS Digital Rebel XS"], + ["Canon EOS REBEL XS", "EOS Rebel XS"], + ["Canon EOS Kiss Digital F", "EOS Kiss F"], + ["Canon EOS Kiss F", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/100d.toml b/third_party/rawler-0.7.2/data/cameras/canon/100d.toml new file mode 100644 index 0000000..6791143 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/100d.toml @@ -0,0 +1,20 @@ +make = "Canon" +model = "Canon EOS 100D" +clean_make = "Canon" +clean_model = "EOS 100D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL SL1", "EOS Rebel SL1"], + ["Canon EOS REBEL SL1", "EOS Rebel SL1"], + ["Canon EOS Kiss Digital X7", "EOS Kiss X7"], + ["Canon EOS Kiss X7", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/10d.toml b/third_party/rawler-0.7.2/data/cameras/canon/10d.toml new file mode 100644 index 0000000..b0cc431 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/10d.toml @@ -0,0 +1,16 @@ +# 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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1100d.toml b/third_party/rawler-0.7.2/data/cameras/canon/1100d.toml new file mode 100644 index 0000000..35c153c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1100d.toml @@ -0,0 +1,19 @@ +make = "Canon" +model = "Canon EOS 1100D" +clean_make = "Canon" +clean_model = "EOS 1100D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL T3", "EOS Rebel T3"], + ["Canon EOS REBEL T3", "EOS Rebel T3"], + ["Canon EOS Kiss Digital X50", "EOS Kiss X50"], + ["Canon EOS Kiss X50", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1200d.toml b/third_party/rawler-0.7.2/data/cameras/canon/1200d.toml new file mode 100644 index 0000000..f69d02b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1200d.toml @@ -0,0 +1,21 @@ +make = "Canon" +model = "Canon EOS 1200D" +clean_make = "Canon" +clean_model = "EOS 1200D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL T5", "EOS Rebel T5"], + ["Canon EOS REBEL T5", "EOS Rebel T5"], + ["Canon EOS Kiss Digital X70", "EOS Kiss X70"], + ["Canon EOS Kiss X70", "EOS Kiss X70"], + ["Canon EOS Hi", "EOS Hi"], +] + +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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1300d.toml b/third_party/rawler-0.7.2/data/cameras/canon/1300d.toml new file mode 100644 index 0000000..602f0d2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1300d.toml @@ -0,0 +1,20 @@ +make = "Canon" +model = "Canon EOS 1300D" +clean_make = "Canon" +clean_model = "EOS 1300D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL T6", "EOS Rebel T6"], + ["Canon EOS REBEL T6", "EOS Rebel T6"], + ["Canon EOS Rebel T6", "EOS Rebel T6"], + ["Canon EOS Kiss Digital X80", "EOS Kiss X80"], + ["Canon EOS Kiss X80", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1d.toml b/third_party/rawler-0.7.2/data/cameras/canon/1d.toml new file mode 100644 index 0000000..e992a56 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1d.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1dm2.toml b/third_party/rawler-0.7.2/data/cameras/canon/1dm2.toml new file mode 100644 index 0000000..2c252e5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1dm2.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1dm2n.toml b/third_party/rawler-0.7.2/data/cameras/canon/1dm2n.toml new file mode 100644 index 0000000..d99541a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1dm2n.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1dm3.toml b/third_party/rawler-0.7.2/data/cameras/canon/1dm3.toml new file mode 100644 index 0000000..08bec8e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1dm3.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1dm4.toml b/third_party/rawler-0.7.2/data/cameras/canon/1dm4.toml new file mode 100644 index 0000000..782502c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1dm4.toml @@ -0,0 +1,19 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1ds.toml b/third_party/rawler-0.7.2/data/cameras/canon/1ds.toml new file mode 100644 index 0000000..5ae8f28 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1ds.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1dsm2.toml b/third_party/rawler-0.7.2/data/cameras/canon/1dsm2.toml new file mode 100644 index 0000000..c06f2b2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1dsm2.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1dsm3.toml b/third_party/rawler-0.7.2/data/cameras/canon/1dsm3.toml new file mode 100644 index 0000000..52e7f27 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1dsm3.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1dx.toml b/third_party/rawler-0.7.2/data/cameras/canon/1dx.toml new file mode 100644 index 0000000..680a01b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1dx.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1dxm2.toml b/third_party/rawler-0.7.2/data/cameras/canon/1dxm2.toml new file mode 100644 index 0000000..e2a85ad --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1dxm2.toml @@ -0,0 +1,22 @@ +make = "Canon" +model = "Canon EOS-1D X Mark II" +clean_make = "Canon" +clean_model = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/1dxm3.toml b/third_party/rawler-0.7.2/data/cameras/canon/1dxm3.toml new file mode 100644 index 0000000..72a3421 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/1dxm3.toml @@ -0,0 +1,18 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/2000d.toml b/third_party/rawler-0.7.2/data/cameras/canon/2000d.toml new file mode 100644 index 0000000..c993008 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/2000d.toml @@ -0,0 +1,17 @@ +make = "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 1500D", "EOS 1500D"], + ["Canon EOS REBEL T7", "EOS Rebel T7"], + ["Canon EOS Rebel T7", "EOS Rebel T7"], + ["Canon EOS Kiss X90", "EOS Kiss X90"], +] + +[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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/200d.toml b/third_party/rawler-0.7.2/data/cameras/canon/200d.toml new file mode 100644 index 0000000..4bde380 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/200d.toml @@ -0,0 +1,18 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/20d.toml b/third_party/rawler-0.7.2/data/cameras/canon/20d.toml new file mode 100644 index 0000000..74f4f9a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/20d.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/250d.toml b/third_party/rawler-0.7.2/data/cameras/canon/250d.toml new file mode 100644 index 0000000..e967bba --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/250d.toml @@ -0,0 +1,21 @@ +make = "Canon" +model = "Canon EOS 250D" +clean_make = "Canon" +clean_model = "EOS 250D" +color_pattern = "RGGB" + +model_aliases = [ + ["Canon EOS Rebel SL3", "EOS Rebel SL3"], + ["Canon EOS Kiss X10", "EOS Kiss X10"], + ["Canon EOS 200D II", "EOS 200D Mark II"] +] + +[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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/300d.toml b/third_party/rawler-0.7.2/data/cameras/canon/300d.toml new file mode 100644 index 0000000..82af523 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/300d.toml @@ -0,0 +1,25 @@ +# CRW +make = "Canon" +model = "Canon EOS 300D DIGITAL" +clean_make = "Canon" +clean_model = "EOS 300D" + +model_aliases = [ + ["Canon EOS 300D Digital", "EOS 300D"], + ["Canon EOS DIGITAL REBEL", "EOS Digital Rebel"], + ["Canon EOS REBEL", "EOS Rebel"], + ["Canon EOS Kiss Digital", "EOS Kiss Digital"], + ["Canon EOS Kiss", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/30d.toml b/third_party/rawler-0.7.2/data/cameras/canon/30d.toml new file mode 100644 index 0000000..017c596 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/30d.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/350d.toml b/third_party/rawler-0.7.2/data/cameras/canon/350d.toml new file mode 100644 index 0000000..d6bee2b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/350d.toml @@ -0,0 +1,24 @@ +make = "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", "EOS Digital Rebel XT"], + ["Canon EOS REBEL XT", "EOS Rebel XT"], + ["Canon EOS Kiss Digital N", "EOS Kiss Digital N"], + ["Canon EOS Kiss N", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/4000d.toml b/third_party/rawler-0.7.2/data/cameras/canon/4000d.toml new file mode 100644 index 0000000..ad82b36 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/4000d.toml @@ -0,0 +1,15 @@ +make = "Canon" +model = "Canon EOS 4000D" +clean_make = "Canon" +clean_model = "EOS 4000D" +color_pattern = "GBRG" +active_area = [142, 51, 0, 0] + +model_aliases = [ + ["Canon EOS Rebel T100", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/400d.toml b/third_party/rawler-0.7.2/data/cameras/canon/400d.toml new file mode 100644 index 0000000..b64b7c9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/400d.toml @@ -0,0 +1,20 @@ +make = "Canon" +model = "Canon EOS 400D DIGITAL" +clean_make = "Canon" +clean_model = "EOS 400D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL XTi", "EOS Digital Rebel XTi"], + ["Canon EOS REBEL XTi", "EOS Rebel XTi"], + ["Canon EOS Kiss Digital X", "EOS Kiss Digital X"], + ["Canon EOS Kiss X", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/40d.toml b/third_party/rawler-0.7.2/data/cameras/canon/40d.toml new file mode 100644 index 0000000..23422b1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/40d.toml @@ -0,0 +1,20 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/450d.toml b/third_party/rawler-0.7.2/data/cameras/canon/450d.toml new file mode 100644 index 0000000..b5f8809 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/450d.toml @@ -0,0 +1,18 @@ +make = "Canon" +model = "Canon EOS 450D" +clean_make = "Canon" +clean_model = "EOS 450D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL XSi", "EOS Digital Rebel XSi"], + ["Canon EOS REBEL XSi", "EOS Rebel XSi"], + ["Canon EOS Kiss Digital X2", "EOS Kiss X2"], + ["Canon EOS Kiss X2", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/500d.toml b/third_party/rawler-0.7.2/data/cameras/canon/500d.toml new file mode 100644 index 0000000..328c6aa --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/500d.toml @@ -0,0 +1,19 @@ +make = "Canon" +model = "Canon EOS 500D" +clean_make = "Canon" +clean_model = "EOS 500D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL T1i", "EOS Rebel T1i"], + ["Canon EOS REBEL T1i", "EOS Rebel T1i"], + ["Canon EOS Kiss Digital X3", "EOS Kiss X3"], + ["Canon EOS Kiss X3", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/50d.toml b/third_party/rawler-0.7.2/data/cameras/canon/50d.toml new file mode 100644 index 0000000..618465b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/50d.toml @@ -0,0 +1,23 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/550d.toml b/third_party/rawler-0.7.2/data/cameras/canon/550d.toml new file mode 100644 index 0000000..467de22 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/550d.toml @@ -0,0 +1,20 @@ +make = "Canon" +model = "Canon EOS 550D" +clean_make = "Canon" +clean_model = "EOS 550D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL T2i", "EOS Rebel T2i"], + ["Canon EOS REBEL T2i", "EOS Rebel T2i"], + ["Canon EOS Kiss Digital X4", "EOS Kiss X4"], + ["Canon EOS Kiss X4", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/5d.toml b/third_party/rawler-0.7.2/data/cameras/canon/5d.toml new file mode 100644 index 0000000..3af8ba4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/5d.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/5dmk2.toml b/third_party/rawler-0.7.2/data/cameras/canon/5dmk2.toml new file mode 100644 index 0000000..3a10cf0 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/5dmk2.toml @@ -0,0 +1,20 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/5dmk3.toml b/third_party/rawler-0.7.2/data/cameras/canon/5dmk3.toml new file mode 100644 index 0000000..36eb884 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/5dmk3.toml @@ -0,0 +1,22 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/5dmk4.toml b/third_party/rawler-0.7.2/data/cameras/canon/5dmk4.toml new file mode 100644 index 0000000..d269c64 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/5dmk4.toml @@ -0,0 +1,23 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/5ds.toml b/third_party/rawler-0.7.2/data/cameras/canon/5ds.toml new file mode 100644 index 0000000..1d3b689 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/5ds.toml @@ -0,0 +1,23 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/5dsr.toml b/third_party/rawler-0.7.2/data/cameras/canon/5dsr.toml new file mode 100644 index 0000000..d864344 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/5dsr.toml @@ -0,0 +1,23 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/600d.toml b/third_party/rawler-0.7.2/data/cameras/canon/600d.toml new file mode 100644 index 0000000..306352b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/600d.toml @@ -0,0 +1,20 @@ +make = "Canon" +model = "Canon EOS 600D" +clean_make = "Canon" +clean_model = "EOS 600D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL T3i", "EOS Rebel T3i"], + ["Canon EOS REBEL T3i", "EOS Rebel T3i"], + ["Canon EOS Kiss Digital X5", "EOS Kiss X5"], + ["Canon EOS Kiss X5", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/60d.toml b/third_party/rawler-0.7.2/data/cameras/canon/60d.toml new file mode 100644 index 0000000..27d5c91 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/60d.toml @@ -0,0 +1,23 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/650d.toml b/third_party/rawler-0.7.2/data/cameras/canon/650d.toml new file mode 100644 index 0000000..387b34e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/650d.toml @@ -0,0 +1,20 @@ +make = "Canon" +model = "Canon EOS 650D" +clean_make = "Canon" +clean_model = "EOS 650D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL T4i", "EOS Rebel T4i"], + ["Canon EOS REBEL T4i", "EOS Rebel T4i"], + ["Canon EOS Kiss Digital X6i", "EOS Kiss X6i"], + ["Canon EOS Kiss X6i", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/6d.toml b/third_party/rawler-0.7.2/data/cameras/canon/6d.toml new file mode 100644 index 0000000..b60fc7a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/6d.toml @@ -0,0 +1,22 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/6dmk2.toml b/third_party/rawler-0.7.2/data/cameras/canon/6dmk2.toml new file mode 100644 index 0000000..2d6435e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/6dmk2.toml @@ -0,0 +1,24 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/700d.toml b/third_party/rawler-0.7.2/data/cameras/canon/700d.toml new file mode 100644 index 0000000..6462d6a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/700d.toml @@ -0,0 +1,20 @@ +make = "Canon" +model = "Canon EOS 700D" +clean_make = "Canon" +clean_model = "EOS 700D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL T5i", "EOS Rebel T5i"], + ["Canon EOS REBEL T5i", "EOS Rebel T5i"], + ["Canon EOS Kiss Digital X7i", "EOS Kiss X7i"], + ["Canon EOS Kiss X7i", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/70d.toml b/third_party/rawler-0.7.2/data/cameras/canon/70d.toml new file mode 100644 index 0000000..047053f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/70d.toml @@ -0,0 +1,25 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/750d.toml b/third_party/rawler-0.7.2/data/cameras/canon/750d.toml new file mode 100644 index 0000000..4186eb2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/750d.toml @@ -0,0 +1,20 @@ +make = "Canon" +model = "Canon EOS 750D" +clean_make = "Canon" +clean_model = "EOS 750D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL T6i", "EOS Rebel T6i"], + ["Canon EOS REBEL T6i", "EOS Rebel T6i"], + ["Canon EOS Rebel T6i", "EOS Rebel T6i"], + ["Canon EOS Kiss Digital X8i", "EOS Kiss X8i"], + ["Canon EOS Kiss X8i", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/760d.toml b/third_party/rawler-0.7.2/data/cameras/canon/760d.toml new file mode 100644 index 0000000..4e040e6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/760d.toml @@ -0,0 +1,18 @@ +make = "Canon" +model = "Canon EOS 760D" +clean_make = "Canon" +clean_model = "EOS 760D" + +model_aliases = [ + ["Canon EOS DIGITAL REBEL T6s", "EOS Rebel T6s"], + ["Canon EOS Rebel T6s", "EOS 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/77d.toml b/third_party/rawler-0.7.2/data/cameras/canon/77d.toml new file mode 100644 index 0000000..f8856d4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/77d.toml @@ -0,0 +1,17 @@ +make = "Canon" +model = "Canon EOS 77D" +clean_make = "Canon" +clean_model = "EOS 77D" + +model_aliases = [ + ["Canon EOS 9000D", "EOS 9000D"], +] + +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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/7d.toml b/third_party/rawler-0.7.2/data/cameras/canon/7d.toml new file mode 100644 index 0000000..7876dc2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/7d.toml @@ -0,0 +1,19 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/7dmk2.toml b/third_party/rawler-0.7.2/data/cameras/canon/7dmk2.toml new file mode 100644 index 0000000..cba24fd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/7dmk2.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/800d.toml b/third_party/rawler-0.7.2/data/cameras/canon/800d.toml new file mode 100644 index 0000000..3bf3e37 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/800d.toml @@ -0,0 +1,19 @@ +make = "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"], + ["Canon EOS Kiss X9i", "EOS Kiss X9i"], +] + +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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/80d.toml b/third_party/rawler-0.7.2/data/cameras/canon/80d.toml new file mode 100644 index 0000000..46c4a1f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/80d.toml @@ -0,0 +1,25 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/canon/850d.toml b/third_party/rawler-0.7.2/data/cameras/canon/850d.toml new file mode 100644 index 0000000..9ab1c1e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/850d.toml @@ -0,0 +1,19 @@ +make = "Canon" +model = "Canon EOS 850D" +model_aliases = [ + ["Canon EOS Rebel T8i", "EOS Rebel T8i"], + ["Canon EOS Kiss X10i", "EOS Kiss X10i"], +] +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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/90d.toml b/third_party/rawler-0.7.2/data/cameras/canon/90d.toml new file mode 100644 index 0000000..616a409 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/90d.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/a3300is.toml b/third_party/rawler-0.7.2/data/cameras/canon/a3300is.toml new file mode 100644 index 0000000..7f343bc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/a3300is.toml @@ -0,0 +1,15 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/a610.toml b/third_party/rawler-0.7.2/data/cameras/canon/a610.toml new file mode 100644 index 0000000..62f2aae --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/a610.toml @@ -0,0 +1,15 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/a620.toml b/third_party/rawler-0.7.2/data/cameras/canon/a620.toml new file mode 100644 index 0000000..1a5d711 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/a620.toml @@ -0,0 +1,15 @@ +# 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] \ No newline at end of file diff --git a/third_party/rawler-0.7.2/data/cameras/canon/a630.toml b/third_party/rawler-0.7.2/data/cameras/canon/a630.toml new file mode 100644 index 0000000..9dfd456 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/a630.toml @@ -0,0 +1,15 @@ +# 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] \ No newline at end of file diff --git a/third_party/rawler-0.7.2/data/cameras/canon/a640.toml b/third_party/rawler-0.7.2/data/cameras/canon/a640.toml new file mode 100644 index 0000000..634575c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/a640.toml @@ -0,0 +1,15 @@ +# 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] \ No newline at end of file diff --git a/third_party/rawler-0.7.2/data/cameras/canon/a650.toml b/third_party/rawler-0.7.2/data/cameras/canon/a650.toml new file mode 100644 index 0000000..98f6763 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/a650.toml @@ -0,0 +1,15 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/a720is.toml b/third_party/rawler-0.7.2/data/cameras/canon/a720is.toml new file mode 100644 index 0000000..0f124b2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/a720is.toml @@ -0,0 +1,15 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/d10.toml b/third_party/rawler-0.7.2/data/cameras/canon/d10.toml new file mode 100644 index 0000000..7d0cfa2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/d10.toml @@ -0,0 +1,15 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/d2000c.toml b/third_party/rawler-0.7.2/data/cameras/canon/d2000c.toml new file mode 100644 index 0000000..1ce2740 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/d2000c.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/d30.toml b/third_party/rawler-0.7.2/data/cameras/canon/d30.toml new file mode 100644 index 0000000..7aed6cc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/d30.toml @@ -0,0 +1,14 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/d60.toml b/third_party/rawler-0.7.2/data/cameras/canon/d60.toml new file mode 100644 index 0000000..4fa212a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/d60.toml @@ -0,0 +1,16 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g1.toml b/third_party/rawler-0.7.2/data/cameras/canon/g1.toml new file mode 100644 index 0000000..1d62be9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g1.toml @@ -0,0 +1,15 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g10.toml b/third_party/rawler-0.7.2/data/cameras/canon/g10.toml new file mode 100644 index 0000000..f21c03f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g10.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g11.toml b/third_party/rawler-0.7.2/data/cameras/canon/g11.toml new file mode 100644 index 0000000..bf30cfb --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g11.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g12.toml b/third_party/rawler-0.7.2/data/cameras/canon/g12.toml new file mode 100644 index 0000000..68a5b9a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g12.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g15.toml b/third_party/rawler-0.7.2/data/cameras/canon/g15.toml new file mode 100644 index 0000000..834350e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g15.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g16.toml b/third_party/rawler-0.7.2/data/cameras/canon/g16.toml new file mode 100644 index 0000000..f322579 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g16.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g1x.toml b/third_party/rawler-0.7.2/data/cameras/canon/g1x.toml new file mode 100644 index 0000000..93ec43c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g1x.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g1xm2.toml b/third_party/rawler-0.7.2/data/cameras/canon/g1xm2.toml new file mode 100644 index 0000000..2d2aa36 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g1xm2.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g1xm3.toml b/third_party/rawler-0.7.2/data/cameras/canon/g1xm3.toml new file mode 100644 index 0000000..aed7050 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g1xm3.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g2.toml b/third_party/rawler-0.7.2/data/cameras/canon/g2.toml new file mode 100644 index 0000000..c840d4e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g2.toml @@ -0,0 +1,14 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g3.toml b/third_party/rawler-0.7.2/data/cameras/canon/g3.toml new file mode 100644 index 0000000..e232503 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g3.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g3x.toml b/third_party/rawler-0.7.2/data/cameras/canon/g3x.toml new file mode 100644 index 0000000..6246288 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g3x.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g5.toml b/third_party/rawler-0.7.2/data/cameras/canon/g5.toml new file mode 100644 index 0000000..daa8141 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g5.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g5x.toml b/third_party/rawler-0.7.2/data/cameras/canon/g5x.toml new file mode 100644 index 0000000..9f21313 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g5x.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g5xmk2.toml b/third_party/rawler-0.7.2/data/cameras/canon/g5xmk2.toml new file mode 100644 index 0000000..3322117 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g5xmk2.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g6.toml b/third_party/rawler-0.7.2/data/cameras/canon/g6.toml new file mode 100644 index 0000000..3601fc1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g6.toml @@ -0,0 +1,16 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g7x.toml b/third_party/rawler-0.7.2/data/cameras/canon/g7x.toml new file mode 100644 index 0000000..ce8d12f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g7x.toml @@ -0,0 +1,13 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g7x_crw.toml b/third_party/rawler-0.7.2/data/cameras/canon/g7x_crw.toml new file mode 100644 index 0000000..e6ea07b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g7x_crw.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g7xm2.toml b/third_party/rawler-0.7.2/data/cameras/canon/g7xm2.toml new file mode 100644 index 0000000..e422d41 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g7xm2.toml @@ -0,0 +1,11 @@ +make = "Canon" +model = "Canon PowerShot G7 X Mark II" +clean_make = "Canon" +clean_model = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g7xmk3.toml b/third_party/rawler-0.7.2/data/cameras/canon/g7xmk3.toml new file mode 100644 index 0000000..08e866a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g7xmk3.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g9.toml b/third_party/rawler-0.7.2/data/cameras/canon/g9.toml new file mode 100644 index 0000000..65ff040 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g9.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g9x.toml b/third_party/rawler-0.7.2/data/cameras/canon/g9x.toml new file mode 100644 index 0000000..f6cc21e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g9x.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/g9xm2.toml b/third_party/rawler-0.7.2/data/cameras/canon/g9xm2.toml new file mode 100644 index 0000000..3014d4a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/g9xm2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/ixy220f.toml b/third_party/rawler-0.7.2/data/cameras/canon/ixy220f.toml new file mode 100644 index 0000000..894029a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/ixy220f.toml @@ -0,0 +1,16 @@ +make = "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] + diff --git a/third_party/rawler-0.7.2/data/cameras/canon/m.toml b/third_party/rawler-0.7.2/data/cameras/canon/m.toml new file mode 100644 index 0000000..c65396d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/m.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/m10.toml b/third_party/rawler-0.7.2/data/cameras/canon/m10.toml new file mode 100644 index 0000000..11c2cee --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/m10.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/m100.toml b/third_party/rawler-0.7.2/data/cameras/canon/m100.toml new file mode 100644 index 0000000..e2a2152 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/m100.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/m2.toml b/third_party/rawler-0.7.2/data/cameras/canon/m2.toml new file mode 100644 index 0000000..50f367f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/m2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/m200.toml b/third_party/rawler-0.7.2/data/cameras/canon/m200.toml new file mode 100644 index 0000000..90fd9e7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/m200.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/m3.toml b/third_party/rawler-0.7.2/data/cameras/canon/m3.toml new file mode 100644 index 0000000..a9a5afa --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/m3.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/m5.toml b/third_party/rawler-0.7.2/data/cameras/canon/m5.toml new file mode 100644 index 0000000..44b07fb --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/m5.toml @@ -0,0 +1,12 @@ +make = "Canon" +model = "Canon EOS M5" +clean_make = "Canon" +clean_model = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/m50.toml b/third_party/rawler-0.7.2/data/cameras/canon/m50.toml new file mode 100644 index 0000000..0b49750 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/m50.toml @@ -0,0 +1,19 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/m50mk2.toml b/third_party/rawler-0.7.2/data/cameras/canon/m50mk2.toml new file mode 100644 index 0000000..d41a2c6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/m50mk2.toml @@ -0,0 +1,18 @@ +make = "Canon" +model = "Canon EOS M50m2" +model_aliases = [ + ["Canon EOS KISS M2", "EOS Kiss M2"], +] +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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/m6.toml b/third_party/rawler-0.7.2/data/cameras/canon/m6.toml new file mode 100644 index 0000000..2eb129d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/m6.toml @@ -0,0 +1,12 @@ +make = "Canon" +model = "Canon EOS M6" +clean_make = "Canon" +clean_model = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/m6mk2.toml b/third_party/rawler-0.7.2/data/cameras/canon/m6mk2.toml new file mode 100644 index 0000000..42c842d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/m6mk2.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/pro1.toml b/third_party/rawler-0.7.2/data/cameras/canon/pro1.toml new file mode 100644 index 0000000..68b9813 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/pro1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/pro70.toml.unsupp b/third_party/rawler-0.7.2/data/cameras/canon/pro70.toml.unsupp new file mode 100644 index 0000000..79f6005 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/pro70.toml.unsupp @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r.toml b/third_party/rawler-0.7.2/data/cameras/canon/r.toml new file mode 100644 index 0000000..9391848 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r10.toml b/third_party/rawler-0.7.2/data/cameras/canon/r10.toml new file mode 100644 index 0000000..899fabd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r10.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r100.toml b/third_party/rawler-0.7.2/data/cameras/canon/r100.toml new file mode 100644 index 0000000..4c5d4a6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r100.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r3.toml b/third_party/rawler-0.7.2/data/cameras/canon/r3.toml new file mode 100644 index 0000000..a9d1110 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r3.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r5.toml b/third_party/rawler-0.7.2/data/cameras/canon/r5.toml new file mode 100644 index 0000000..16f3b25 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r5.toml @@ -0,0 +1,19 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r50.toml b/third_party/rawler-0.7.2/data/cameras/canon/r50.toml new file mode 100644 index 0000000..a24c1c2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r50.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r5c.toml b/third_party/rawler-0.7.2/data/cameras/canon/r5c.toml new file mode 100644 index 0000000..3828d47 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r5c.toml @@ -0,0 +1,19 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r5m2.toml b/third_party/rawler-0.7.2/data/cameras/canon/r5m2.toml new file mode 100644 index 0000000..f02611c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r5m2.toml @@ -0,0 +1,19 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r6.toml b/third_party/rawler-0.7.2/data/cameras/canon/r6.toml new file mode 100644 index 0000000..7457094 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r6.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r6m2.toml b/third_party/rawler-0.7.2/data/cameras/canon/r6m2.toml new file mode 100644 index 0000000..d9db358 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r6m2.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r6m3.toml b/third_party/rawler-0.7.2/data/cameras/canon/r6m3.toml new file mode 100644 index 0000000..2ad4267 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r6m3.toml @@ -0,0 +1,15 @@ +make = "Canon" +model = "Canon EOS R6 Mark III" +clean_make = "Canon" +clean_model = "EOS R6 Mark III" +color_pattern = "RGGB" + +[cameras.color_matrix] +A = [1.0273, -0.4611, 0.0139, -0.3922, 1.1425, 0.2856, -0.0231, 0.0839, 0.6645] +D65 = [0.8309, -0.1786, -0.1095, -0.4851, 1.2736, 0.2353, -0.0956, 0.1911, 0.5534] + +[[cameras.modes]] +mode = "raw" + +[[cameras.modes]] +mode = "craw" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r7.toml b/third_party/rawler-0.7.2/data/cameras/canon/r7.toml new file mode 100644 index 0000000..c9e60f6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r7.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/r8.toml b/third_party/rawler-0.7.2/data/cameras/canon/r8.toml new file mode 100644 index 0000000..2e7a47a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/r8.toml @@ -0,0 +1,15 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/rp.toml b/third_party/rawler-0.7.2/data/cameras/canon/rp.toml new file mode 100644 index 0000000..e118f69 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/rp.toml @@ -0,0 +1,16 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s100.toml b/third_party/rawler-0.7.2/data/cameras/canon/s100.toml new file mode 100644 index 0000000..cdb760c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s100.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s100_crw.toml b/third_party/rawler-0.7.2/data/cameras/canon/s100_crw.toml new file mode 100644 index 0000000..af83314 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s100_crw.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s100v.toml b/third_party/rawler-0.7.2/data/cameras/canon/s100v.toml new file mode 100644 index 0000000..a92ec46 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s100v.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s110.toml b/third_party/rawler-0.7.2/data/cameras/canon/s110.toml new file mode 100644 index 0000000..487a6fd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s110.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s120.toml b/third_party/rawler-0.7.2/data/cameras/canon/s120.toml new file mode 100644 index 0000000..8339fff --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s120.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s2is.toml b/third_party/rawler-0.7.2/data/cameras/canon/s2is.toml new file mode 100644 index 0000000..56ec3fe --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s2is.toml @@ -0,0 +1,9 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s30.toml b/third_party/rawler-0.7.2/data/cameras/canon/s30.toml new file mode 100644 index 0000000..a4caaa8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s30.toml @@ -0,0 +1,14 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s3is.toml b/third_party/rawler-0.7.2/data/cameras/canon/s3is.toml new file mode 100644 index 0000000..b77e127 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s3is.toml @@ -0,0 +1,15 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s40.toml b/third_party/rawler-0.7.2/data/cameras/canon/s40.toml new file mode 100644 index 0000000..9b96578 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s40.toml @@ -0,0 +1,17 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s45.toml b/third_party/rawler-0.7.2/data/cameras/canon/s45.toml new file mode 100644 index 0000000..e11d703 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s45.toml @@ -0,0 +1,16 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s50.toml b/third_party/rawler-0.7.2/data/cameras/canon/s50.toml new file mode 100644 index 0000000..ddefd47 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s50.toml @@ -0,0 +1,17 @@ +# 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] + diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s60.toml b/third_party/rawler-0.7.2/data/cameras/canon/s60.toml new file mode 100644 index 0000000..4847d7d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s60.toml @@ -0,0 +1,17 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s70.toml b/third_party/rawler-0.7.2/data/cameras/canon/s70.toml new file mode 100644 index 0000000..57cf6d2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s70.toml @@ -0,0 +1,17 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s90.toml b/third_party/rawler-0.7.2/data/cameras/canon/s90.toml new file mode 100644 index 0000000..14d78e3 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s90.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/s95.toml b/third_party/rawler-0.7.2/data/cameras/canon/s95.toml new file mode 100644 index 0000000..ba3dbcf --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/s95.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/sx110is.toml b/third_party/rawler-0.7.2/data/cameras/canon/sx110is.toml new file mode 100644 index 0000000..74cca80 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/sx110is.toml @@ -0,0 +1,15 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/sx150is.toml b/third_party/rawler-0.7.2/data/cameras/canon/sx150is.toml new file mode 100644 index 0000000..90facca --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/sx150is.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/sx1is.toml b/third_party/rawler-0.7.2/data/cameras/canon/sx1is.toml new file mode 100644 index 0000000..bf0a410 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/sx1is.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/sx220hs.toml b/third_party/rawler-0.7.2/data/cameras/canon/sx220hs.toml new file mode 100644 index 0000000..01c0e46 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/sx220hs.toml @@ -0,0 +1,15 @@ +# 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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/sx260hs.toml b/third_party/rawler-0.7.2/data/cameras/canon/sx260hs.toml new file mode 100644 index 0000000..6ce33a2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/sx260hs.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/sx40hs.toml b/third_party/rawler-0.7.2/data/cameras/canon/sx40hs.toml new file mode 100644 index 0000000..f550795 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/sx40hs.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/sx50.toml b/third_party/rawler-0.7.2/data/cameras/canon/sx50.toml new file mode 100644 index 0000000..5a60901 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/sx50.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/sx60hs.toml b/third_party/rawler-0.7.2/data/cameras/canon/sx60hs.toml new file mode 100644 index 0000000..e6327a7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/sx60hs.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/canon/sx70_hs.toml b/third_party/rawler-0.7.2/data/cameras/canon/sx70_hs.toml new file mode 100644 index 0000000..bc65eca --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/sx70_hs.toml @@ -0,0 +1,18 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/canon/sx710hs.toml b/third_party/rawler-0.7.2/data/cameras/canon/sx710hs.toml new file mode 100644 index 0000000..fc3c707 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/canon/sx710hs.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/epson/r-d1.toml b/third_party/rawler-0.7.2/data/cameras/epson/r-d1.toml new file mode 100644 index 0000000..0565253 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/epson/r-d1.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/epson/r-d1s.toml b/third_party/rawler-0.7.2/data/cameras/epson/r-d1s.toml new file mode 100644 index 0000000..a8dfa66 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/epson/r-d1s.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/epson/r-d1x.toml b/third_party/rawler-0.7.2/data/cameras/epson/r-d1x.toml new file mode 100644 index 0000000..449e5d6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/epson/r-d1x.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/dbp_gx680.toml b/third_party/rawler-0.7.2/data/cameras/fuji/dbp_gx680.toml new file mode 100644 index 0000000..582e345 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/dbp_gx680.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/e550.toml b/third_party/rawler-0.7.2/data/cameras/fuji/e550.toml new file mode 100644 index 0000000..0ca6cf7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/e550.toml @@ -0,0 +1,16 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/e900.toml b/third_party/rawler-0.7.2/data/cameras/fuji/e900.toml new file mode 100644 index 0000000..bf53f90 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/e900.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/f550exr.toml b/third_party/rawler-0.7.2/data/cameras/fuji/f550exr.toml new file mode 100644 index 0000000..e0087a1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/f550exr.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/f600exr.toml b/third_party/rawler-0.7.2/data/cameras/fuji/f600exr.toml new file mode 100644 index 0000000..1473231 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/f600exr.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/f700.toml b/third_party/rawler-0.7.2/data/cameras/fuji/f700.toml new file mode 100644 index 0000000..ebfffc4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/f700.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/f770exr.toml b/third_party/rawler-0.7.2/data/cameras/fuji/f770exr.toml new file mode 100644 index 0000000..843d83e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/f770exr.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/f900exr.toml b/third_party/rawler-0.7.2/data/cameras/fuji/f900exr.toml new file mode 100644 index 0000000..eb63cb6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/f900exr.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/gfx100.toml b/third_party/rawler-0.7.2/data/cameras/fuji/gfx100.toml new file mode 100644 index 0000000..cd34859 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/gfx100.toml @@ -0,0 +1,11 @@ +make = "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] + diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/gfx100mk2.toml b/third_party/rawler-0.7.2/data/cameras/fuji/gfx100mk2.toml new file mode 100644 index 0000000..ce7e082 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/gfx100mk2.toml @@ -0,0 +1,10 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/gfx100rf.toml b/third_party/rawler-0.7.2/data/cameras/fuji/gfx100rf.toml new file mode 100644 index 0000000..b1a74c8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/gfx100rf.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/gfx100s.toml b/third_party/rawler-0.7.2/data/cameras/fuji/gfx100s.toml new file mode 100644 index 0000000..900bb1f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/gfx100s.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/gfx100smk2.toml b/third_party/rawler-0.7.2/data/cameras/fuji/gfx100smk2.toml new file mode 100644 index 0000000..5baa52d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/gfx100smk2.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/gfx50r.toml b/third_party/rawler-0.7.2/data/cameras/fuji/gfx50r.toml new file mode 100644 index 0000000..32464e8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/gfx50r.toml @@ -0,0 +1,11 @@ +make = "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] + diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/gfx50s.toml b/third_party/rawler-0.7.2/data/cameras/fuji/gfx50s.toml new file mode 100644 index 0000000..32e4600 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/gfx50s.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/gfx50smk2.toml b/third_party/rawler-0.7.2/data/cameras/fuji/gfx50smk2.toml new file mode 100644 index 0000000..5bc4ddc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/gfx50smk2.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/hs10.toml b/third_party/rawler-0.7.2/data/cameras/fuji/hs10.toml new file mode 100644 index 0000000..661e30b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/hs10.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/hs20exr.toml b/third_party/rawler-0.7.2/data/cameras/fuji/hs20exr.toml new file mode 100644 index 0000000..d0016f0 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/hs20exr.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/hs30exr.toml b/third_party/rawler-0.7.2/data/cameras/fuji/hs30exr.toml new file mode 100644 index 0000000..b0a6a35 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/hs30exr.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/hs33exr.toml b/third_party/rawler-0.7.2/data/cameras/fuji/hs33exr.toml new file mode 100644 index 0000000..bdf691e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/hs33exr.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/hs50exr.toml b/third_party/rawler-0.7.2/data/cameras/fuji/hs50exr.toml new file mode 100644 index 0000000..3bc9b84 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/hs50exr.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s1.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s1.toml new file mode 100644 index 0000000..97ea873 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s1.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s100fs.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s100fs.toml new file mode 100644 index 0000000..3d1cb7d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s100fs.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s200exr.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s200exr.toml new file mode 100644 index 0000000..3c4084e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s200exr.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s2pro.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s2pro.toml new file mode 100644 index 0000000..e05389d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s2pro.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s3pro.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s3pro.toml new file mode 100644 index 0000000..56ba5b9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s3pro.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s5000.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s5000.toml new file mode 100644 index 0000000..7be2b72 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s5000.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s5200.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s5200.toml new file mode 100644 index 0000000..bcbb350 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s5200.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s5500.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s5500.toml new file mode 100644 index 0000000..07087ec --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s5500.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s5600.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s5600.toml new file mode 100644 index 0000000..47c6ff7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s5600.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s5pro.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s5pro.toml new file mode 100644 index 0000000..17c9e59 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s5pro.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s6500fd.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s6500fd.toml new file mode 100644 index 0000000..e49c78a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s6500fd.toml @@ -0,0 +1,18 @@ +make = "FUJIFILM" +model = "FinePix S6500fd" +clean_make = "Fujifilm" +clean_model = "FinePix S6500fd" + +model_aliases = [ + ["FinePix S6000fd", "FinePix S6000fd"], +] + +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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s7000.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s7000.toml new file mode 100644 index 0000000..6508072 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s7000.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s9500.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s9500.toml new file mode 100644 index 0000000..6aa412f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s9500.toml @@ -0,0 +1,20 @@ +make = "FUJIFILM" +model = "FinePix S9500" +clean_make = "Fujifilm" +clean_model = "FinePix S9500" + +model_aliases = [ + ["FinePix S9000", "FinePix S9000"], +] + +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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/s9600.toml b/third_party/rawler-0.7.2/data/cameras/fuji/s9600.toml new file mode 100644 index 0000000..b2d9030 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/s9600.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/sl1000.toml b/third_party/rawler-0.7.2/data/cameras/fuji/sl1000.toml new file mode 100644 index 0000000..2e9e0c3 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/sl1000.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-a1.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-a1.toml new file mode 100644 index 0000000..3f81167 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-a1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-a10.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-a10.toml new file mode 100644 index 0000000..652062d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-a10.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-a2.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-a2.toml new file mode 100644 index 0000000..d23f70b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-a2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-a3.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-a3.toml new file mode 100644 index 0000000..37945d9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-a3.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-a5.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-a5.toml new file mode 100644 index 0000000..b024417 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-a5.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-a7.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-a7.toml new file mode 100644 index 0000000..d2e7338 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-a7.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-e1.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-e1.toml new file mode 100644 index 0000000..06ef4a7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-e1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-e2.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-e2.toml new file mode 100644 index 0000000..a1027d2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-e2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-e2s.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-e2s.toml new file mode 100644 index 0000000..3a87482 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-e2s.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-e3.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-e3.toml new file mode 100644 index 0000000..cbc57d0 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-e3.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-e4.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-e4.toml new file mode 100644 index 0000000..0c2b720 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-e4.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-e5.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-e5.toml new file mode 100644 index 0000000..6ff04ba --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-e5.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-h1.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-h1.toml new file mode 100644 index 0000000..494db4c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-h1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-h2.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-h2.toml new file mode 100644 index 0000000..6c738cf --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-h2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-h2s.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-h2s.toml new file mode 100644 index 0000000..05512da --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-h2s.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-m1.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-m1.toml new file mode 100644 index 0000000..54655c5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-m1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-m5.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-m5.toml new file mode 100644 index 0000000..61c9807 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-m5.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-pro1.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-pro1.toml new file mode 100644 index 0000000..4062eae --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-pro1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-pro2.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-pro2.toml new file mode 100644 index 0000000..45f1131 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-pro2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-pro3.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-pro3.toml new file mode 100644 index 0000000..5a22a0c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-pro3.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-s1.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-s1.toml new file mode 100644 index 0000000..da882d8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-s1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-s10.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-s10.toml new file mode 100644 index 0000000..14a8696 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-s10.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-s20.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-s20.toml new file mode 100644 index 0000000..1370d62 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-s20.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-t1.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-t1.toml new file mode 100644 index 0000000..4630baf --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-t1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-t10.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-t10.toml new file mode 100644 index 0000000..7a97f17 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-t10.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-t100.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-t100.toml new file mode 100644 index 0000000..47473e3 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-t100.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-t2.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-t2.toml new file mode 100644 index 0000000..08af39c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-t2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-t20.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-t20.toml new file mode 100644 index 0000000..84fd4b6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-t20.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-t200.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-t200.toml new file mode 100644 index 0000000..5dd7e5c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-t200.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-t3.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-t3.toml new file mode 100644 index 0000000..ff1a006 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-t3.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-t30.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-t30.toml new file mode 100644 index 0000000..46c63f8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-t30.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-t30mk2.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-t30mk2.toml new file mode 100644 index 0000000..443475f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-t30mk2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-t4.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-t4.toml new file mode 100644 index 0000000..4c6e2e6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-t4.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-t5.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-t5.toml new file mode 100644 index 0000000..d9e147d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-t5.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x-t50.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x-t50.toml new file mode 100644 index 0000000..13abdb4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x-t50.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x10.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x10.toml new file mode 100644 index 0000000..ae8929a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x10.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x100.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x100.toml new file mode 100644 index 0000000..3f122a9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x100.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x100f.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x100f.toml new file mode 100644 index 0000000..ce4cc75 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x100f.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x100s.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x100s.toml new file mode 100644 index 0000000..2776b59 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x100s.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x100t.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x100t.toml new file mode 100644 index 0000000..ca10f56 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x100t.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x100v.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x100v.toml new file mode 100644 index 0000000..7e27d8c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x100v.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x100vi.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x100vi.toml new file mode 100644 index 0000000..43ad808 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x100vi.toml @@ -0,0 +1,10 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x20.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x20.toml new file mode 100644 index 0000000..44652f8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x20.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x30.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x30.toml new file mode 100644 index 0000000..37542af --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x30.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/x70.toml b/third_party/rawler-0.7.2/data/cameras/fuji/x70.toml new file mode 100644 index 0000000..a929738 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/x70.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/xf1.toml b/third_party/rawler-0.7.2/data/cameras/fuji/xf1.toml new file mode 100644 index 0000000..3873d87 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/xf1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/xf10.toml b/third_party/rawler-0.7.2/data/cameras/fuji/xf10.toml new file mode 100644 index 0000000..28334bd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/xf10.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/xq1.toml b/third_party/rawler-0.7.2/data/cameras/fuji/xq1.toml new file mode 100644 index 0000000..dcdaeac --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/xq1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/fuji/xq2.toml b/third_party/rawler-0.7.2/data/cameras/fuji/xq2.toml new file mode 100644 index 0000000..d1bcefd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/fuji/xq2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/hasselblad/cfv.toml b/third_party/rawler-0.7.2/data/cameras/hasselblad/cfv.toml new file mode 100644 index 0000000..81fd55f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/hasselblad/cfv.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/hasselblad/cfv_50.toml b/third_party/rawler-0.7.2/data/cameras/hasselblad/cfv_50.toml new file mode 100644 index 0000000..7fe89b7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/hasselblad/cfv_50.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/hasselblad/h3d.toml b/third_party/rawler-0.7.2/data/cameras/hasselblad/h3d.toml new file mode 100644 index 0000000..20769e0 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/hasselblad/h3d.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/hasselblad/h4d_40.toml b/third_party/rawler-0.7.2/data/cameras/hasselblad/h4d_40.toml new file mode 100644 index 0000000..e876fdc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/hasselblad/h4d_40.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/hasselblad/h4d_50.toml b/third_party/rawler-0.7.2/data/cameras/hasselblad/h4d_50.toml new file mode 100644 index 0000000..631fe35 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/hasselblad/h4d_50.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/hasselblad/h5d_40.toml b/third_party/rawler-0.7.2/data/cameras/hasselblad/h5d_40.toml new file mode 100644 index 0000000..d4ab466 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/hasselblad/h5d_40.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/hasselblad/h5d_50c.toml b/third_party/rawler-0.7.2/data/cameras/hasselblad/h5d_50c.toml new file mode 100644 index 0000000..c8b32f6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/hasselblad/h5d_50c.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/hasselblad/h6d_100cms.toml b/third_party/rawler-0.7.2/data/cameras/hasselblad/h6d_100cms.toml new file mode 100644 index 0000000..c72a117 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/hasselblad/h6d_100cms.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/hasselblad/x1d.toml b/third_party/rawler-0.7.2/data/cameras/hasselblad/x1d.toml new file mode 100644 index 0000000..4c0ee7f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/hasselblad/x1d.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/hasselblad/x1d2.toml b/third_party/rawler-0.7.2/data/cameras/hasselblad/x1d2.toml new file mode 100644 index 0000000..eeb5bfc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/hasselblad/x1d2.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/hasselblad/x2d_100c.toml b/third_party/rawler-0.7.2/data/cameras/hasselblad/x2d_100c.toml new file mode 100644 index 0000000..51fb65c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/hasselblad/x2d_100c.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/dc120.toml b/third_party/rawler-0.7.2/data/cameras/kodak/dc120.toml new file mode 100644 index 0000000..2b9411a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/dc120.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/dc50.toml b/third_party/rawler-0.7.2/data/cameras/kodak/dc50.toml new file mode 100644 index 0000000..83c7461 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/dc50.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/dcs1.toml b/third_party/rawler-0.7.2/data/cameras/kodak/dcs1.toml new file mode 100644 index 0000000..f29dc22 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/dcs1.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/dcs3.toml b/third_party/rawler-0.7.2/data/cameras/kodak/dcs3.toml new file mode 100644 index 0000000..4807c4f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/dcs3.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/dcs460d.toml b/third_party/rawler-0.7.2/data/cameras/kodak/dcs460d.toml new file mode 100644 index 0000000..bc2a8d0 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/dcs460d.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/dcs560c.toml b/third_party/rawler-0.7.2/data/cameras/kodak/dcs560c.toml new file mode 100644 index 0000000..12367d8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/dcs560c.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/dcs760c.toml b/third_party/rawler-0.7.2/data/cameras/kodak/dcs760c.toml new file mode 100644 index 0000000..df75c89 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/dcs760c.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/dcs_pro14n.toml b/third_party/rawler-0.7.2/data/cameras/kodak/dcs_pro14n.toml new file mode 100644 index 0000000..0e9a019 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/dcs_pro14n.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/dcs_pro14nx.toml b/third_party/rawler-0.7.2/data/cameras/kodak/dcs_pro14nx.toml new file mode 100644 index 0000000..e39457b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/dcs_pro14nx.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/dcs_pro_slrc.toml b/third_party/rawler-0.7.2/data/cameras/kodak/dcs_pro_slrc.toml new file mode 100644 index 0000000..a04c504 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/dcs_pro_slrc.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/dcs_pro_slrn.toml b/third_party/rawler-0.7.2/data/cameras/kodak/dcs_pro_slrn.toml new file mode 100644 index 0000000..ca5a142 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/dcs_pro_slrn.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/p712.toml b/third_party/rawler-0.7.2/data/cameras/kodak/p712.toml new file mode 100644 index 0000000..cd5f1f4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/p712.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/p880.toml b/third_party/rawler-0.7.2/data/cameras/kodak/p880.toml new file mode 100644 index 0000000..a0cd02c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/p880.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/z1015.toml b/third_party/rawler-0.7.2/data/cameras/kodak/z1015.toml new file mode 100644 index 0000000..4595279 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/z1015.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/z981.toml b/third_party/rawler-0.7.2/data/cameras/kodak/z981.toml new file mode 100644 index 0000000..8c1e457 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/z981.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/kodak/z990.toml b/third_party/rawler-0.7.2/data/cameras/kodak/z990.toml new file mode 100644 index 0000000..43780a8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/kodak/z990.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leaf/aptus22.toml b/third_party/rawler-0.7.2/data/cameras/leaf/aptus22.toml new file mode 100644 index 0000000..8d0fbc2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leaf/aptus22.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leaf/aptus75.toml b/third_party/rawler-0.7.2/data/cameras/leaf/aptus75.toml new file mode 100644 index 0000000..554b0cd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leaf/aptus75.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leaf/credo40.toml b/third_party/rawler-0.7.2/data/cameras/leaf/credo40.toml new file mode 100644 index 0000000..7787927 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leaf/credo40.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leaf/credo50.toml b/third_party/rawler-0.7.2/data/cameras/leaf/credo50.toml new file mode 100644 index 0000000..0449445 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leaf/credo50.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leaf/credo60.toml b/third_party/rawler-0.7.2/data/cameras/leaf/credo60.toml new file mode 100644 index 0000000..1663cb8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leaf/credo60.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leaf/credo80.toml b/third_party/rawler-0.7.2/data/cameras/leaf/credo80.toml new file mode 100644 index 0000000..c730be4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leaf/credo80.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leica/c112.toml b/third_party/rawler-0.7.2/data/cameras/leica/c112.toml new file mode 100644 index 0000000..005f8e4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/c112.toml @@ -0,0 +1,19 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leica/cl.toml b/third_party/rawler-0.7.2/data/cameras/leica/cl.toml new file mode 100644 index 0000000..68aa64c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/cl.toml @@ -0,0 +1,7 @@ +make = "LEICA CAMERA AG" +model = "LEICA CL" +clean_make = "Leica" +clean_model = "CL" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/leica/clux.toml b/third_party/rawler-0.7.2/data/cameras/leica/clux.toml new file mode 100644 index 0000000..4f046b0 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/clux.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leica/digilux2.toml b/third_party/rawler-0.7.2/data/cameras/leica/digilux2.toml new file mode 100644 index 0000000..6f86269 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/digilux2.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leica/digilux3.toml b/third_party/rawler-0.7.2/data/cameras/leica/digilux3.toml new file mode 100644 index 0000000..682a3c8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/digilux3.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leica/dlux109.toml b/third_party/rawler-0.7.2/data/cameras/leica/dlux109.toml new file mode 100644 index 0000000..0a5fc1b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/dlux109.toml @@ -0,0 +1,28 @@ +make = "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] + diff --git a/third_party/rawler-0.7.2/data/cameras/leica/dlux3.toml b/third_party/rawler-0.7.2/data/cameras/leica/dlux3.toml new file mode 100644 index 0000000..c87a136 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/dlux3.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leica/dlux4.toml b/third_party/rawler-0.7.2/data/cameras/leica/dlux4.toml new file mode 100644 index 0000000..9c170f6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/dlux4.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leica/dlux5.toml b/third_party/rawler-0.7.2/data/cameras/leica/dlux5.toml new file mode 100644 index 0000000..607cc2f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/dlux5.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leica/dlux7.toml b/third_party/rawler-0.7.2/data/cameras/leica/dlux7.toml new file mode 100644 index 0000000..5d415f4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/dlux7.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leica/m10.toml b/third_party/rawler-0.7.2/data/cameras/leica/m10.toml new file mode 100644 index 0000000..50e0350 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/m10.toml @@ -0,0 +1,7 @@ +make = "Leica Camera AG" +model = "LEICA M10" +clean_make = "Leica" +clean_model = "M10" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/leica/m10r.toml b/third_party/rawler-0.7.2/data/cameras/leica/m10r.toml new file mode 100644 index 0000000..3eb3e7f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/m10r.toml @@ -0,0 +1,7 @@ +make = "Leica Camera AG" +model = "LEICA M10-R" +clean_make = "Leica" +clean_model = "M10-R" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/leica/m8.toml b/third_party/rawler-0.7.2/data/cameras/leica/m8.toml new file mode 100644 index 0000000..58909da --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/m8.toml @@ -0,0 +1,7 @@ +make = "Leica Camera AG" +model = "M8 Digital Camera" +clean_make = "Leica" +clean_model = "M8" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/leica/m9.toml b/third_party/rawler-0.7.2/data/cameras/leica/m9.toml new file mode 100644 index 0000000..f0b80cb --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/m9.toml @@ -0,0 +1,7 @@ +make = "Leica Camera AG" +model = "M9 Digital Camera" +clean_make = "Leica" +clean_model = "M9" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/leica/m_monochrom.toml b/third_party/rawler-0.7.2/data/cameras/leica/m_monochrom.toml new file mode 100644 index 0000000..e1a1066 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/m_monochrom.toml @@ -0,0 +1,7 @@ +make = "Leica Camera AG" +model = "M Monochrom" +clean_make = "Leica" +clean_model = "M Monochrom" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/leica/m_monochrom_typ246.toml b/third_party/rawler-0.7.2/data/cameras/leica/m_monochrom_typ246.toml new file mode 100644 index 0000000..6942584 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/m_monochrom_typ246.toml @@ -0,0 +1,7 @@ +make = "Leica Camera AG" +model = "LEICA M MONOCHROM (Typ 246)" +clean_make = "Leica" +clean_model = "M Monochrom (Typ 246)" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/leica/m_typ240.toml b/third_party/rawler-0.7.2/data/cameras/leica/m_typ240.toml new file mode 100644 index 0000000..75e8e23 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/m_typ240.toml @@ -0,0 +1,7 @@ +make = "Leica Camera AG" +model = "LEICA M (Typ 240)" +clean_make = "Leica" +clean_model = "M (Typ 240)" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/leica/q2.toml b/third_party/rawler-0.7.2/data/cameras/leica/q2.toml new file mode 100644 index 0000000..22b5186 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/q2.toml @@ -0,0 +1,7 @@ +make = "LEICA CAMERA AG" +model = "LEICA Q2" +clean_make = "Leica" +clean_model = "Q2" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/leica/q_typ116.toml b/third_party/rawler-0.7.2/data/cameras/leica/q_typ116.toml new file mode 100644 index 0000000..9c70949 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/q_typ116.toml @@ -0,0 +1,7 @@ +make = "LEICA CAMERA AG" +model = "LEICA Q (Typ 116)" +clean_make = "Leica" +clean_model = "Q (Typ 116)" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/leica/sl2.toml b/third_party/rawler-0.7.2/data/cameras/leica/sl2.toml new file mode 100644 index 0000000..a5e03e8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/sl2.toml @@ -0,0 +1,7 @@ +make = "LEICA CAMERA AG" +model = "LEICA SL2" +clean_make = "Leica" +clean_model = "SL2" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/leica/sl_typ601.toml b/third_party/rawler-0.7.2/data/cameras/leica/sl_typ601.toml new file mode 100644 index 0000000..b56903c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/sl_typ601.toml @@ -0,0 +1,7 @@ +make = "LEICA CAMERA AG" +model = "LEICA SL (Typ 601)" +clean_make = "Leica" +clean_model = "SL (Typ 601)" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/leica/vlux1.toml b/third_party/rawler-0.7.2/data/cameras/leica/vlux1.toml new file mode 100644 index 0000000..709c41d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/vlux1.toml @@ -0,0 +1,19 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leica/vlux114.toml b/third_party/rawler-0.7.2/data/cameras/leica/vlux114.toml new file mode 100644 index 0000000..0259052 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/vlux114.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/leica/vlux4.toml b/third_party/rawler-0.7.2/data/cameras/leica/vlux4.toml new file mode 100644 index 0000000..36f70fa --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/vlux4.toml @@ -0,0 +1,16 @@ +make = "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] + diff --git a/third_party/rawler-0.7.2/data/cameras/leica/vlux5.toml b/third_party/rawler-0.7.2/data/cameras/leica/vlux5.toml new file mode 100644 index 0000000..d8bed2a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/vlux5.toml @@ -0,0 +1,16 @@ +make = "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] + diff --git a/third_party/rawler-0.7.2/data/cameras/leica/x2.toml b/third_party/rawler-0.7.2/data/cameras/leica/x2.toml new file mode 100644 index 0000000..d6e22f7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/leica/x2.toml @@ -0,0 +1,7 @@ +make = "LEICA CAMERA AG" +model = "LEICA X2" +clean_make = "Leica" +clean_model = "X2" + +[[cameras.modes]] +mode = "dng" diff --git a/third_party/rawler-0.7.2/data/cameras/mamiya/zd.toml b/third_party/rawler-0.7.2/data/cameras/mamiya/zd.toml new file mode 100644 index 0000000..28e8aa8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/mamiya/zd.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/minolta/7.toml b/third_party/rawler-0.7.2/data/cameras/minolta/7.toml new file mode 100644 index 0000000..d5c96e5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/minolta/7.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/minolta/7hi.toml b/third_party/rawler-0.7.2/data/cameras/minolta/7hi.toml new file mode 100644 index 0000000..697994a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/minolta/7hi.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/minolta/7i.toml b/third_party/rawler-0.7.2/data/cameras/minolta/7i.toml new file mode 100644 index 0000000..889f91f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/minolta/7i.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/minolta/a1.toml b/third_party/rawler-0.7.2/data/cameras/minolta/a1.toml new file mode 100644 index 0000000..06d7b75 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/minolta/a1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/minolta/a2.toml b/third_party/rawler-0.7.2/data/cameras/minolta/a2.toml new file mode 100644 index 0000000..2ddd1c7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/minolta/a2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/minolta/a200.toml b/third_party/rawler-0.7.2/data/cameras/minolta/a200.toml new file mode 100644 index 0000000..366c8b5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/minolta/a200.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/minolta/alpha7.toml b/third_party/rawler-0.7.2/data/cameras/minolta/alpha7.toml new file mode 100644 index 0000000..b26702c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/minolta/alpha7.toml @@ -0,0 +1,14 @@ +make = "KONICA MINOLTA" +model = "ALPHA-7 DIGITAL" +model_aliases = [ + ["ALPHA 7D", "ALPHA 7D"] +] +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] diff --git a/third_party/rawler-0.7.2/data/cameras/minolta/dynax_7d.toml b/third_party/rawler-0.7.2/data/cameras/minolta/dynax_7d.toml new file mode 100644 index 0000000..7948800 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/minolta/dynax_7d.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/minolta/g600.toml b/third_party/rawler-0.7.2/data/cameras/minolta/g600.toml new file mode 100644 index 0000000..a47e758 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/minolta/g600.toml @@ -0,0 +1,17 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/minolta/maxxum_7d.toml b/third_party/rawler-0.7.2/data/cameras/minolta/maxxum_7d.toml new file mode 100644 index 0000000..113fea9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/minolta/maxxum_7d.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/1aw1.toml b/third_party/rawler-0.7.2/data/cameras/nikon/1aw1.toml new file mode 100644 index 0000000..0ad68f7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/1aw1.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/1j1.toml b/third_party/rawler-0.7.2/data/cameras/nikon/1j1.toml new file mode 100644 index 0000000..3e86e45 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/1j1.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/1j2.toml b/third_party/rawler-0.7.2/data/cameras/nikon/1j2.toml new file mode 100644 index 0000000..d69c0c9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/1j2.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/1j3.toml b/third_party/rawler-0.7.2/data/cameras/nikon/1j3.toml new file mode 100644 index 0000000..13a93dd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/1j3.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/1j5.toml b/third_party/rawler-0.7.2/data/cameras/nikon/1j5.toml new file mode 100644 index 0000000..921a57f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/1j5.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/1s2.toml b/third_party/rawler-0.7.2/data/cameras/nikon/1s2.toml new file mode 100644 index 0000000..7517d11 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/1s2.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/1v1.toml b/third_party/rawler-0.7.2/data/cameras/nikon/1v1.toml new file mode 100644 index 0000000..66d748d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/1v1.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/1v2.toml b/third_party/rawler-0.7.2/data/cameras/nikon/1v2.toml new file mode 100644 index 0000000..9fd146c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/1v2.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/1v3.toml b/third_party/rawler-0.7.2/data/cameras/nikon/1v3.toml new file mode 100644 index 0000000..bdf744d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/1v3.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_a.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_a.toml new file mode 100644 index 0000000..84a748d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_a.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_a1000.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_a1000.toml new file mode 100644 index 0000000..920229b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_a1000.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_b700.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_b700.toml new file mode 100644 index 0000000..747ef8b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_b700.toml @@ -0,0 +1,17 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_e8800.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_e8800.toml new file mode 100644 index 0000000..1586338 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_e8800.toml @@ -0,0 +1,17 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p1000.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p1000.toml new file mode 100644 index 0000000..456a66a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p1000.toml @@ -0,0 +1,22 @@ +make = "NIKON CORPORATION" +model = "COOLPIX P1000" +clean_make = "Nikon" +clean_model = "Coolpix P1000" + +model_aliases = [ + ["COOLPIX P1100", "Coolpix P1100"], +] + +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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p330.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p330.toml new file mode 100644 index 0000000..8650e9b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p330.toml @@ -0,0 +1,17 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p340.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p340.toml new file mode 100644 index 0000000..8a84939 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p340.toml @@ -0,0 +1,17 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p6000.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p6000.toml new file mode 100644 index 0000000..da26872 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p6000.toml @@ -0,0 +1,17 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p7000.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p7000.toml new file mode 100644 index 0000000..72eb006 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p7000.toml @@ -0,0 +1,17 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p7100.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p7100.toml new file mode 100644 index 0000000..6f51c95 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p7100.toml @@ -0,0 +1,18 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p7800.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p7800.toml new file mode 100644 index 0000000..ca703a8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p7800.toml @@ -0,0 +1,18 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p950.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p950.toml new file mode 100644 index 0000000..dde4be6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolpix_p950.toml @@ -0,0 +1,17 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/coolscan_5000_ed.toml b/third_party/rawler-0.7.2/data/cameras/nikon/coolscan_5000_ed.toml new file mode 100644 index 0000000..a30f704 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/coolscan_5000_ed.toml @@ -0,0 +1,13 @@ +make = "Nikon" +model = "Nikon SUPER COOLSCAN 5000 ED" +clean_make = "Nikon" +clean_model = "Super Coolscan 5000 ED" + +#color_pattern = "RGGB" + +[cameras.color_matrix] +Unknown = [3.1336, -1.6168, -0.4907, -0.9787, 1.9161, 0.0335, 0.0721, -0.2291, 1.4054] + +[[cameras.modes]] +mode = "16bit" +whitepoint = 65535 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d1.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d1.toml new file mode 100644 index 0000000..a52c803 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d1.toml @@ -0,0 +1,17 @@ +make = "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 + diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d100.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d100.toml new file mode 100644 index 0000000..917dba9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d100.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d1x.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d1x.toml new file mode 100644 index 0000000..d4ac07c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d1x.toml @@ -0,0 +1,18 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d200.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d200.toml new file mode 100644 index 0000000..7608c94 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d200.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d2h.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d2h.toml new file mode 100644 index 0000000..efff260 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d2h.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d2hs.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d2hs.toml new file mode 100644 index 0000000..bc19c9d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d2hs.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d2x.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d2x.toml new file mode 100644 index 0000000..e72c6e9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d2x.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d2xs.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d2xs.toml new file mode 100644 index 0000000..8b09fee --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d2xs.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d3.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d3.toml new file mode 100644 index 0000000..56f2dc6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d3.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d300.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d300.toml new file mode 100644 index 0000000..d759632 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d300.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d3000.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d3000.toml new file mode 100644 index 0000000..8d12626 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d3000.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d300s.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d300s.toml new file mode 100644 index 0000000..140b21f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d300s.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d3100.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d3100.toml new file mode 100644 index 0000000..f8fc9c8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d3100.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d3200.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d3200.toml new file mode 100644 index 0000000..e6aa0e2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d3200.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d3300.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d3300.toml new file mode 100644 index 0000000..f791dbc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d3300.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d3400.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d3400.toml new file mode 100644 index 0000000..45ee935 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d3400.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d3500.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d3500.toml new file mode 100644 index 0000000..84c16ce --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d3500.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d3s.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d3s.toml new file mode 100644 index 0000000..eb5ccf3 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d3s.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d3x.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d3x.toml new file mode 100644 index 0000000..001703b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d3x.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d4.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d4.toml new file mode 100644 index 0000000..073e32e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d4.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d40.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d40.toml new file mode 100644 index 0000000..5fa714b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d40.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d40x.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d40x.toml new file mode 100644 index 0000000..b00df3a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d40x.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d4s.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d4s.toml new file mode 100644 index 0000000..4f68865 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d4s.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d5.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d5.toml new file mode 100644 index 0000000..ebbc2fd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d5.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d50.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d50.toml new file mode 100644 index 0000000..b60de5d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d50.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d500.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d500.toml new file mode 100644 index 0000000..94cc2ba --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d500.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d5000.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d5000.toml new file mode 100644 index 0000000..85c6ba7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d5000.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d5100.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d5100.toml new file mode 100644 index 0000000..b36ba9d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d5100.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d5200.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d5200.toml new file mode 100644 index 0000000..d9940d7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d5200.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d5300.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d5300.toml new file mode 100644 index 0000000..c7dce5e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d5300.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d5500.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d5500.toml new file mode 100644 index 0000000..4f08082 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d5500.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d5600.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d5600.toml new file mode 100644 index 0000000..a2ef6ef --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d5600.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d6.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d6.toml new file mode 100644 index 0000000..6cf51d5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d6.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d60.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d60.toml new file mode 100644 index 0000000..57f1b48 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d60.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d600.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d600.toml new file mode 100644 index 0000000..90679fa --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d600.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d610.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d610.toml new file mode 100644 index 0000000..fa098d7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d610.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d70.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d70.toml new file mode 100644 index 0000000..f752a6d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d70.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d700.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d700.toml new file mode 100644 index 0000000..94a9c5f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d700.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d7000.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d7000.toml new file mode 100644 index 0000000..3342a6a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d7000.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d70s.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d70s.toml new file mode 100644 index 0000000..e80ed39 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d70s.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d7100.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d7100.toml new file mode 100644 index 0000000..2055046 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d7100.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d7200.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d7200.toml new file mode 100644 index 0000000..4788657 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d7200.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d750.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d750.toml new file mode 100644 index 0000000..bdad816 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d750.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d7500.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d7500.toml new file mode 100644 index 0000000..e040805 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d7500.toml @@ -0,0 +1,21 @@ +make = "NIKON CORPORATION" +model = "NIKON D7500" +clean_make = "Nikon" +clean_model = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d780.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d780.toml new file mode 100644 index 0000000..9749af3 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d780.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d80.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d80.toml new file mode 100644 index 0000000..554856f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d80.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d800.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d800.toml new file mode 100644 index 0000000..4038597 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d800.toml @@ -0,0 +1,26 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d810.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d810.toml new file mode 100644 index 0000000..4113623 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d810.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d850.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d850.toml new file mode 100644 index 0000000..f63e7cf --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d850.toml @@ -0,0 +1,21 @@ +make = "NIKON CORPORATION" +model = "NIKON D850" +clean_make = "Nikon" +clean_model = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/d90.toml b/third_party/rawler-0.7.2/data/cameras/nikon/d90.toml new file mode 100644 index 0000000..7baf8f7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/d90.toml @@ -0,0 +1,16 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/df.toml b/third_party/rawler-0.7.2/data/cameras/nikon/df.toml new file mode 100644 index 0000000..9a42e56 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/df.toml @@ -0,0 +1,21 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/e5400.toml b/third_party/rawler-0.7.2/data/cameras/nikon/e5400.toml new file mode 100644 index 0000000..c8e93e5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/e5400.toml @@ -0,0 +1,17 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/e5700.toml b/third_party/rawler-0.7.2/data/cameras/nikon/e5700.toml new file mode 100644 index 0000000..2bd38f6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/e5700.toml @@ -0,0 +1,17 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/e8400.toml b/third_party/rawler-0.7.2/data/cameras/nikon/e8400.toml new file mode 100644 index 0000000..714e593 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/e8400.toml @@ -0,0 +1,17 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z30.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z30.toml new file mode 100644 index 0000000..d8de45b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z30.toml @@ -0,0 +1,19 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z5.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z5.toml new file mode 100644 index 0000000..38b4b4d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z5.toml @@ -0,0 +1,19 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z50.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z50.toml new file mode 100644 index 0000000..aa6cf70 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z50.toml @@ -0,0 +1,19 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z50_mk2.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z50_mk2.toml new file mode 100644 index 0000000..8c43a29 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z50_mk2.toml @@ -0,0 +1,14 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z5_mk2.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z5_mk2.toml new file mode 100644 index 0000000..278a7fd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z5_mk2.toml @@ -0,0 +1,14 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z6.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z6.toml new file mode 100644 index 0000000..b277b31 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z6.toml @@ -0,0 +1,19 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z6_mk2.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z6_mk2.toml new file mode 100644 index 0000000..e18e333 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z6_mk2.toml @@ -0,0 +1,18 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z6_mk3.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z6_mk3.toml new file mode 100644 index 0000000..572499c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z6_mk3.toml @@ -0,0 +1,14 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z7.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z7.toml new file mode 100644 index 0000000..9ad7557 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z7.toml @@ -0,0 +1,19 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z7_mk2.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z7_mk2.toml new file mode 100644 index 0000000..efebc64 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z7_mk2.toml @@ -0,0 +1,19 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z8.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z8.toml new file mode 100644 index 0000000..d9e9152 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z8.toml @@ -0,0 +1,15 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z9.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z9.toml new file mode 100644 index 0000000..ce4c921 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z9.toml @@ -0,0 +1,19 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z_f.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z_f.toml new file mode 100644 index 0000000..31c3820 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z_f.toml @@ -0,0 +1,19 @@ +make = "NIKON CORPORATION" +model = "NIKON Z f" +clean_make = "Nikon" +clean_model = "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 = 15892 \ No newline at end of file diff --git a/third_party/rawler-0.7.2/data/cameras/nikon/z_fc.toml b/third_party/rawler-0.7.2/data/cameras/nikon/z_fc.toml new file mode 100644 index 0000000..e3ec680 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/nikon/z_fc.toml @@ -0,0 +1,19 @@ +make = "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 diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/c5050z.toml b/third_party/rawler-0.7.2/data/cameras/olympus/c5050z.toml new file mode 100644 index 0000000..e3c5a49 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/c5050z.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/c5060wz.toml b/third_party/rawler-0.7.2/data/cameras/olympus/c5060wz.toml new file mode 100644 index 0000000..0b5b985 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/c5060wz.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/c7070wz.toml b/third_party/rawler-0.7.2/data/cameras/olympus/c7070wz.toml new file mode 100644 index 0000000..f8f823e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/c7070wz.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/c8080.toml b/third_party/rawler-0.7.2/data/cameras/olympus/c8080.toml new file mode 100644 index 0000000..25bfedd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/c8080.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-1.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-1.toml new file mode 100644 index 0000000..9a523a3 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-1.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-10.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-10.toml new file mode 100644 index 0000000..d6ccb52 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-10.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-20.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-20.toml new file mode 100644 index 0000000..8285f65 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-20.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-3.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-3.toml new file mode 100644 index 0000000..028d879 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-3.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-30.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-30.toml new file mode 100644 index 0000000..cc59d96 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-30.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-300.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-300.toml new file mode 100644 index 0000000..4d61832 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-300.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-330.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-330.toml new file mode 100644 index 0000000..585ece1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-330.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-400.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-400.toml new file mode 100644 index 0000000..db6fbd8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-400.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-410.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-410.toml new file mode 100644 index 0000000..7cd9598 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-410.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-420.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-420.toml new file mode 100644 index 0000000..7258fdc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-420.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-450.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-450.toml new file mode 100644 index 0000000..287da16 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-450.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-5.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-5.toml new file mode 100644 index 0000000..297266e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-5.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-500.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-500.toml new file mode 100644 index 0000000..9afbb78 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-500.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-510.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-510.toml new file mode 100644 index 0000000..ad148a3 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-510.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-520.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-520.toml new file mode 100644 index 0000000..8b00e8d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-520.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-600.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-600.toml new file mode 100644 index 0000000..edb5eb2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-600.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-620.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-620.toml new file mode 100644 index 0000000..6aaa226 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-620.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-m1.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-m1.toml new file mode 100644 index 0000000..8f4cb99 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-m1.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-m10.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-m10.toml new file mode 100644 index 0000000..d6fa95b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-m10.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-m10mk2.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-m10mk2.toml new file mode 100644 index 0000000..b0bff8a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-m10mk2.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-m10mk3.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-m10mk3.toml new file mode 100644 index 0000000..fbc1ba1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-m10mk3.toml @@ -0,0 +1,13 @@ +make = "OLYMPUS CORPORATION" +model = "E-M10 Mark III" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-m10mk3s.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-m10mk3s.toml new file mode 100644 index 0000000..4715125 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-m10mk3s.toml @@ -0,0 +1,13 @@ +make = "OLYMPUS CORPORATION" +model = "E-M10MarkIIIS" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-m10mk4.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-m10mk4.toml new file mode 100644 index 0000000..e7d9d09 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-m10mk4.toml @@ -0,0 +1,13 @@ +make = "OLYMPUS CORPORATION" +model = "E-M10MarkIV" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-m1mk2.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-m1mk2.toml new file mode 100644 index 0000000..a3f483c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-m1mk2.toml @@ -0,0 +1,18 @@ +make = "OLYMPUS CORPORATION" +model = "E-M1MarkII" +clean_make = "Olympus" +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] + diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-m1mk3.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-m1mk3.toml new file mode 100644 index 0000000..d5e88cc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-m1mk3.toml @@ -0,0 +1,17 @@ +make = "OLYMPUS CORPORATION" +model = "E-M1MarkIII" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-m1x.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-m1x.toml new file mode 100644 index 0000000..f976610 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-m1x.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-m5.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-m5.toml new file mode 100644 index 0000000..8b5266f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-m5.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-m5mk2.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-m5mk2.toml new file mode 100644 index 0000000..f21b67b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-m5mk2.toml @@ -0,0 +1,18 @@ +make = "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" + diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-m5mk3.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-m5mk3.toml new file mode 100644 index 0000000..e7e5f37 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-m5mk3.toml @@ -0,0 +1,18 @@ +make = "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" + diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-p1.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-p1.toml new file mode 100644 index 0000000..088d2ba --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-p1.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-p2.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-p2.toml new file mode 100644 index 0000000..f65c5d6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-p2.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-p3.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-p3.toml new file mode 100644 index 0000000..fb58154 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-p3.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-p5.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-p5.toml new file mode 100644 index 0000000..e2d98c3 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-p5.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-pl1.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl1.toml new file mode 100644 index 0000000..6523f2d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl1.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-pl10.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl10.toml new file mode 100644 index 0000000..d26c5f5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl10.toml @@ -0,0 +1,13 @@ +make = "OLYMPUS CORPORATION" +model = "E-PL10" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-pl2.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl2.toml new file mode 100644 index 0000000..0eb3d21 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl2.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-pl3.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl3.toml new file mode 100644 index 0000000..6e67db8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl3.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-pl5.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl5.toml new file mode 100644 index 0000000..26fe496 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl5.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-pl6.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl6.toml new file mode 100644 index 0000000..823d605 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl6.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-pl7.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl7.toml new file mode 100644 index 0000000..0e7a140 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl7.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-pl8.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl8.toml new file mode 100644 index 0000000..72368aa --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl8.toml @@ -0,0 +1,13 @@ +make = "OLYMPUS CORPORATION" +model = "E-PL8" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-pl9.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl9.toml new file mode 100644 index 0000000..4a9326c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-pl9.toml @@ -0,0 +1,13 @@ +make = "OLYMPUS CORPORATION" +model = "E-PL9" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-pm1.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-pm1.toml new file mode 100644 index 0000000..45e2781 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-pm1.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/e-pm2.toml b/third_party/rawler-0.7.2/data/cameras/olympus/e-pm2.toml new file mode 100644 index 0000000..f8db26e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/e-pm2.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/penf.toml b/third_party/rawler-0.7.2/data/cameras/olympus/penf.toml new file mode 100644 index 0000000..40aceba --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/penf.toml @@ -0,0 +1,17 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/sh-2.toml b/third_party/rawler-0.7.2/data/cameras/olympus/sh-2.toml new file mode 100644 index 0000000..301b882 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/sh-2.toml @@ -0,0 +1,13 @@ +make = "OLYMPUS IMAGING CORP." +model = "SH-2" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/sp320.toml b/third_party/rawler-0.7.2/data/cameras/olympus/sp320.toml new file mode 100644 index 0000000..07aa7c9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/sp320.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/sp350.toml b/third_party/rawler-0.7.2/data/cameras/olympus/sp350.toml new file mode 100644 index 0000000..7ab0556 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/sp350.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/sp500uz.toml b/third_party/rawler-0.7.2/data/cameras/olympus/sp500uz.toml new file mode 100644 index 0000000..4de3155 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/sp500uz.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/sp510uz.toml b/third_party/rawler-0.7.2/data/cameras/olympus/sp510uz.toml new file mode 100644 index 0000000..d02e2ac --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/sp510uz.toml @@ -0,0 +1,14 @@ +make = "OLYMPUS IMAGING CORP." +model = "SP510UZ" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/sp550uz.toml b/third_party/rawler-0.7.2/data/cameras/olympus/sp550uz.toml new file mode 100644 index 0000000..470c793 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/sp550uz.toml @@ -0,0 +1,13 @@ +make = "OLYMPUS IMAGING CORP." +model = "SP550UZ" +clean_make = "Olympus" +clean_model = "SP550UZ" +whitepoint = 4095 +color_pattern = "BGGR" +hints = ["interlaced"] +active_area = [0, 0, 0, 0] +crop_area = [8, 2, 8, 3] + +[cameras.color_matrix] +A = [1.4117, -0.6746, 0.0307, -0.386, 1.0859, 0.347, -0.0207, 0.1013, 0.654] +D65 = [1.1596, -0.4007, -0.1048, -0.5432, 1.2798, 0.2957, -0.1029, 0.1750, 0.6516] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/sp565uz.toml b/third_party/rawler-0.7.2/data/cameras/olympus/sp565uz.toml new file mode 100644 index 0000000..8ff4808 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/sp565uz.toml @@ -0,0 +1,13 @@ +make = "OLYMPUS IMAGING CORP." +model = "SP565UZ" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/sp570uz.toml b/third_party/rawler-0.7.2/data/cameras/olympus/sp570uz.toml new file mode 100644 index 0000000..9cab872 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/sp570uz.toml @@ -0,0 +1,13 @@ +make = "OLYMPUS IMAGING CORP." +model = "SP570UZ" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/stylus1-1.toml b/third_party/rawler-0.7.2/data/cameras/olympus/stylus1-1.toml new file mode 100644 index 0000000..481d5d1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/stylus1-1.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/stylus1.toml b/third_party/rawler-0.7.2/data/cameras/olympus/stylus1.toml new file mode 100644 index 0000000..6b234fd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/stylus1.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/tg-4.toml b/third_party/rawler-0.7.2/data/cameras/olympus/tg-4.toml new file mode 100644 index 0000000..a4a8006 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/tg-4.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/tg-5.toml b/third_party/rawler-0.7.2/data/cameras/olympus/tg-5.toml new file mode 100644 index 0000000..286095b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/tg-5.toml @@ -0,0 +1,13 @@ +make = "OLYMPUS CORPORATION" +model = "TG-5" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/tg-6.toml b/third_party/rawler-0.7.2/data/cameras/olympus/tg-6.toml new file mode 100644 index 0000000..3506bc4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/tg-6.toml @@ -0,0 +1,13 @@ +make = "OLYMPUS CORPORATION" +model = "TG-6" +clean_make = "Olympus" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/xz-1.toml b/third_party/rawler-0.7.2/data/cameras/olympus/xz-1.toml new file mode 100644 index 0000000..8744d4c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/xz-1.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/xz-10.toml b/third_party/rawler-0.7.2/data/cameras/olympus/xz-10.toml new file mode 100644 index 0000000..a997eab --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/xz-10.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/olympus/xz-2.toml b/third_party/rawler-0.7.2/data/cameras/olympus/xz-2.toml new file mode 100644 index 0000000..348ec36 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/olympus/xz-2.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/omdigital/om_1.toml b/third_party/rawler-0.7.2/data/cameras/omdigital/om_1.toml new file mode 100644 index 0000000..6a03024 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/omdigital/om_1.toml @@ -0,0 +1,18 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/omdigital/om_1mk2.toml b/third_party/rawler-0.7.2/data/cameras/omdigital/om_1mk2.toml new file mode 100644 index 0000000..568a2d4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/omdigital/om_1mk2.toml @@ -0,0 +1,18 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/omdigital/om_3.toml b/third_party/rawler-0.7.2/data/cameras/omdigital/om_3.toml new file mode 100644 index 0000000..0078e56 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/omdigital/om_3.toml @@ -0,0 +1,18 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/omdigital/om_5.toml b/third_party/rawler-0.7.2/data/cameras/omdigital/om_5.toml new file mode 100644 index 0000000..dbd6fe1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/omdigital/om_5.toml @@ -0,0 +1,16 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/omdigital/tg-7.toml b/third_party/rawler-0.7.2/data/cameras/omdigital/tg-7.toml new file mode 100644 index 0000000..37126ba --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/omdigital/tg-7.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/cm1.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/cm1.toml new file mode 100644 index 0000000..eacf8d4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/cm1.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fx150.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fx150.toml new file mode 100644 index 0000000..3779ccd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fx150.toml @@ -0,0 +1,19 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz100.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz100.toml new file mode 100644 index 0000000..4e518e4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz100.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz1000.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz1000.toml new file mode 100644 index 0000000..744871c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz1000.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz10002.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz10002.toml new file mode 100644 index 0000000..32ad975 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz10002.toml @@ -0,0 +1,33 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz150.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz150.toml new file mode 100644 index 0000000..dd62114 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz150.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz18.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz18.toml new file mode 100644 index 0000000..4dac3a9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz18.toml @@ -0,0 +1,23 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz200.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz200.toml new file mode 100644 index 0000000..f11e2c0 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz200.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz2000.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz2000.toml new file mode 100644 index 0000000..870125b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz2000.toml @@ -0,0 +1,12 @@ +make = "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] + diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz2500.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz2500.toml new file mode 100644 index 0000000..fb01739 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz2500.toml @@ -0,0 +1,20 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz28.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz28.toml new file mode 100644 index 0000000..b2f1486 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz28.toml @@ -0,0 +1,23 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz30.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz30.toml new file mode 100644 index 0000000..8ca5c5a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz30.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz300.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz300.toml new file mode 100644 index 0000000..8d60eac --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz300.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz330.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz330.toml new file mode 100644 index 0000000..a2c7648 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz330.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz38.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz38.toml new file mode 100644 index 0000000..bf9e0c9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz38.toml @@ -0,0 +1,28 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz45.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz45.toml new file mode 100644 index 0000000..52ee59f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz45.toml @@ -0,0 +1,31 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz50.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz50.toml new file mode 100644 index 0000000..c5d98d3 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz50.toml @@ -0,0 +1,23 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz70.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz70.toml new file mode 100644 index 0000000..84a8307 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz70.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz72.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz72.toml new file mode 100644 index 0000000..b33a594 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz72.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz8.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz8.toml new file mode 100644 index 0000000..81d7644 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz8.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/fz80.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/fz80.toml new file mode 100644 index 0000000..dc9d5ee --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/fz80.toml @@ -0,0 +1,25 @@ +make = "Panasonic" +model = "DC-FZ80" +clean_make = "Panasonic" +clean_model = "DC-FZ80" + +model_aliases = [ + ["DC-FZ80D", "DC-FZ80D"], + ["DC-FZ82", "DC-FZ82"], + ["DC-FZ82D", "DC-FZ82D"], + ["DC-FZ85", "DC-FZ85"], + ["DC-FZ85D", "DC-FZ85D"], +] + +#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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g1.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g1.toml new file mode 100644 index 0000000..d1f23a1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g1.toml @@ -0,0 +1,23 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g10.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g10.toml new file mode 100644 index 0000000..068ba78 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g10.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g100.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g100.toml new file mode 100644 index 0000000..85c820b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g100.toml @@ -0,0 +1,21 @@ +make = "Panasonic" +model = "DC-G100" +clean_make = "Panasonic" +clean_model = "DC-G100" + +model_aliases = [ + ["DC-G100D", "DC-G100D"], + ["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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g2.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g2.toml new file mode 100644 index 0000000..9782672 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g2.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g3.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g3.toml new file mode 100644 index 0000000..e5c30fb --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g3.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g5.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g5.toml new file mode 100644 index 0000000..fbc4827 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g5.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g6.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g6.toml new file mode 100644 index 0000000..1a1973c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g6.toml @@ -0,0 +1,28 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g7.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g7.toml new file mode 100644 index 0000000..fda4948 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g7.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g70.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g70.toml new file mode 100644 index 0000000..1ad0fdb --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g70.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g80.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g80.toml new file mode 100644 index 0000000..ae6abc5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g80.toml @@ -0,0 +1,21 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g9.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g9.toml new file mode 100644 index 0000000..502d213 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g9.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g90.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g90.toml new file mode 100644 index 0000000..b60a063 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g90.toml @@ -0,0 +1,22 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/g9mk2.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/g9mk2.toml new file mode 100644 index 0000000..2b1b041 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/g9mk2.toml @@ -0,0 +1,13 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gf1.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gf1.toml new file mode 100644 index 0000000..9ae8806 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gf1.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gf10.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gf10.toml new file mode 100644 index 0000000..6967433 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gf10.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gf2.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gf2.toml new file mode 100644 index 0000000..c29f01a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gf2.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gf3.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gf3.toml new file mode 100644 index 0000000..4e85d42 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gf3.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gf5.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gf5.toml new file mode 100644 index 0000000..5481fbd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gf5.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gf6.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gf6.toml new file mode 100644 index 0000000..566dfed --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gf6.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gf7.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gf7.toml new file mode 100644 index 0000000..be7b962 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gf7.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gf8.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gf8.toml new file mode 100644 index 0000000..0f00df4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gf8.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gh1.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gh1.toml new file mode 100644 index 0000000..c0d87b0 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gh1.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gh2.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gh2.toml new file mode 100644 index 0000000..d71a752 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gh2.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gh3.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gh3.toml new file mode 100644 index 0000000..686d9f0 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gh3.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gh4.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gh4.toml new file mode 100644 index 0000000..c2b0011 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gh4.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gh5.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gh5.toml new file mode 100644 index 0000000..20f2cbd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gh5.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gh5m2.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gh5m2.toml new file mode 100644 index 0000000..0754a2b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gh5m2.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gh5s.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gh5s.toml new file mode 100644 index 0000000..f320443 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gh5s.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gh6.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gh6.toml new file mode 100644 index 0000000..869b2dd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gh6.toml @@ -0,0 +1,22 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gh7.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gh7.toml new file mode 100644 index 0000000..a8f2c22 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gh7.toml @@ -0,0 +1,22 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gm1.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gm1.toml new file mode 100644 index 0000000..8a3813a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gm1.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gm1s.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gm1s.toml new file mode 100644 index 0000000..4b44804 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gm1s.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gm5.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gm5.toml new file mode 100644 index 0000000..35868ba --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gm5.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gx1.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gx1.toml new file mode 100644 index 0000000..b6d3694 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gx1.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gx7.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gx7.toml new file mode 100644 index 0000000..6a62c51 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gx7.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gx7mk2.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gx7mk2.toml new file mode 100644 index 0000000..fe80eaa --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gx7mk2.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gx7mk3.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gx7mk3.toml new file mode 100644 index 0000000..b1f5965 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gx7mk3.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gx8.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gx8.toml new file mode 100644 index 0000000..ba1dc31 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gx8.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gx80.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gx80.toml new file mode 100644 index 0000000..0461525 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gx80.toml @@ -0,0 +1,20 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gx800.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gx800.toml new file mode 100644 index 0000000..9581a6f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gx800.toml @@ -0,0 +1,20 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gx880.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gx880.toml new file mode 100644 index 0000000..4a982a7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gx880.toml @@ -0,0 +1,18 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/gx9.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/gx9.toml new file mode 100644 index 0000000..1f0ad7d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/gx9.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/l1.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/l1.toml new file mode 100644 index 0000000..b36ec94 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/l1.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/l10.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/l10.toml new file mode 100644 index 0000000..17ebbf9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/l10.toml @@ -0,0 +1,16 @@ +make = "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] + diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/lf1.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/lf1.toml new file mode 100644 index 0000000..f3409b9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/lf1.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/lx1.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/lx1.toml new file mode 100644 index 0000000..f55f633 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/lx1.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/lx10.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/lx10.toml new file mode 100644 index 0000000..239530f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/lx10.toml @@ -0,0 +1,20 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/lx100.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/lx100.toml new file mode 100644 index 0000000..b142fb4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/lx100.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/lx100m2.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/lx100m2.toml new file mode 100644 index 0000000..c33d5bc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/lx100m2.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/lx2.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/lx2.toml new file mode 100644 index 0000000..a556162 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/lx2.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/lx3.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/lx3.toml new file mode 100644 index 0000000..27adffc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/lx3.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/lx5.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/lx5.toml new file mode 100644 index 0000000..7e14f0a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/lx5.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/lx7.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/lx7.toml new file mode 100644 index 0000000..8859dac --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/lx7.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/s1.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/s1.toml new file mode 100644 index 0000000..f3ba3d7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/s1.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/s1h.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/s1h.toml new file mode 100644 index 0000000..a6da592 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/s1h.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/s1m2es.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/s1m2es.toml new file mode 100644 index 0000000..e2e559a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/s1m2es.toml @@ -0,0 +1,14 @@ +make = "Panasonic" +model = "DC-S1M2ES" +clean_make = "Panasonic" +clean_model = "DC-S1M2ES" +whitepoint = 16383 +color_pattern = "RGGB" + +[cameras.color_matrix] +A = [1.6824, -1.1875, 0.0536, -0.4077, 1.2021, 0.2316, 0.0046, 0.0356, 0.7564] +D65 = [1.1333, -0.4794, -0.1062, -0.3912, 1.2027, 0.2115, 0.0042, 0.0784, 0.5904] + +[[cameras.modes]] +mode = "3:2" +active_area = [0, 2, 0, 0] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/s1r.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/s1r.toml new file mode 100644 index 0000000..c92ab5b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/s1r.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/s1rm2.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/s1rm2.toml new file mode 100644 index 0000000..769dfcd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/s1rm2.toml @@ -0,0 +1,14 @@ +make = "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" diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/s5.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/s5.toml new file mode 100644 index 0000000..f33f5e0 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/s5.toml @@ -0,0 +1,19 @@ +make = "Panasonic" +model = "DC-S5" +clean_make = "Panasonic" +clean_model = "DC-S5" +#blackpoint = 142 +whitepoint = 16380 +color_pattern = "RGGB" + +model_aliases = [ + ["DC-S5D", "DC-S5D"], +] + +[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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/s5m2.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/s5m2.toml new file mode 100644 index 0000000..2279aea --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/s5m2.toml @@ -0,0 +1,18 @@ +make = "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" + diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/s9.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/s9.toml new file mode 100644 index 0000000..148b5a7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/s9.toml @@ -0,0 +1,14 @@ +make = "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" + diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/tz100.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/tz100.toml new file mode 100644 index 0000000..e6ff903 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/tz100.toml @@ -0,0 +1,24 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/tz202.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/tz202.toml new file mode 100644 index 0000000..16a1733 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/tz202.toml @@ -0,0 +1,28 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/tz60.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/tz60.toml new file mode 100644 index 0000000..e5bdb58 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/tz60.toml @@ -0,0 +1,33 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/tz61.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/tz61.toml new file mode 100644 index 0000000..273f853 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/tz61.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/tz70.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/tz70.toml new file mode 100644 index 0000000..284b845 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/tz70.toml @@ -0,0 +1,32 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/tz71.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/tz71.toml new file mode 100644 index 0000000..3ba7798 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/tz71.toml @@ -0,0 +1,27 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/tz80.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/tz80.toml new file mode 100644 index 0000000..5a32887 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/tz80.toml @@ -0,0 +1,20 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/tz90.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/tz90.toml new file mode 100644 index 0000000..e9dd7fa --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/tz90.toml @@ -0,0 +1,23 @@ +make = "Panasonic" +model = "DC-TZ90" +clean_make = "Panasonic" +clean_model = "DC-TZ90" + +model_aliases = [ + ["DC-TZ91", "DC-TZ91"], + ["DC-TZ92", "DC-TZ92"], + ["DC-TZ93", "DC-TZ93"], + ["DC-ZS70", "DC-ZS70"], +] + +#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] diff --git a/third_party/rawler-0.7.2/data/cameras/panasonic/tz95.toml b/third_party/rawler-0.7.2/data/cameras/panasonic/tz95.toml new file mode 100644 index 0000000..0acd4ce --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/panasonic/tz95.toml @@ -0,0 +1,24 @@ +make = "Panasonic" +model = "DC-TZ95" +clean_make = "Panasonic" +clean_model = "DC-TZ95" + +model_aliases = [ + ["DC-TZ95D", "DC-TZ95D"], + ["DC-TZ96", "DC-TZ96"], + ["DC-TZ99", "DC-TZ99"], + ["DC-ZS80", "DC-ZS80"], + ["DC-ZS99", "DC-ZS99"], +] + +#blackpoint = 139 +whitepoint = 4095 +color_pattern = "GBRG" + +[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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/645d.toml b/third_party/rawler-0.7.2/data/cameras/pentax/645d.toml new file mode 100644 index 0000000..d8e923e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/645d.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/645z.toml b/third_party/rawler-0.7.2/data/cameras/pentax/645z.toml new file mode 100644 index 0000000..9750b63 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/645z.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/istD.toml b/third_party/rawler-0.7.2/data/cameras/pentax/istD.toml new file mode 100644 index 0000000..40b7460 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/istD.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/istDL.toml b/third_party/rawler-0.7.2/data/cameras/pentax/istDL.toml new file mode 100644 index 0000000..5d97b2c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/istDL.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/istDL2.toml b/third_party/rawler-0.7.2/data/cameras/pentax/istDL2.toml new file mode 100644 index 0000000..6032964 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/istDL2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/istDS.toml b/third_party/rawler-0.7.2/data/cameras/pentax/istDS.toml new file mode 100644 index 0000000..fc4a311 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/istDS.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-1.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-1.toml new file mode 100644 index 0000000..c29914e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-1.toml @@ -0,0 +1,12 @@ +make = "RICOH IMAGING COMPANY, LTD." +model = "PENTAX K-1" +clean_make = "Pentax" +clean_model = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-1II.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-1II.toml new file mode 100644 index 0000000..f5bef71 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-1II.toml @@ -0,0 +1,12 @@ +make = "RICOH IMAGING COMPANY, LTD." +model = "PENTAX K-1 Mark II" +clean_make = "Pentax" +clean_model = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-3.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-3.toml new file mode 100644 index 0000000..fd3178f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-3.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-3II.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-3II.toml new file mode 100644 index 0000000..3f7c9d4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-3II.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-3III.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-3III.toml new file mode 100644 index 0000000..d23d384 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-3III.toml @@ -0,0 +1,12 @@ +make = "RICOH IMAGING COMPANY, LTD." +model = "PENTAX K-3 Mark III" +clean_make = "Pentax" +clean_model = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-3III_monochrome.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-3III_monochrome.toml new file mode 100644 index 0000000..c6263e7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-3III_monochrome.toml @@ -0,0 +1,7 @@ +make = "RICOH IMAGING COMPANY, LTD." +model = "PENTAX K-3 Mark III Monochrome" +clean_make = "Pentax" +clean_model = "K-3 Mark III Monochrome" +whitepoint = 16378 +active_area = [26, 34, 54, 30] +crop_area = [54, 58, 58, 38] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-5.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-5.toml new file mode 100644 index 0000000..a404371 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-5.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-5II.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-5II.toml new file mode 100644 index 0000000..8e6239b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-5II.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-5IIs.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-5IIs.toml new file mode 100644 index 0000000..0003c27 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-5IIs.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-7.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-7.toml new file mode 100644 index 0000000..855025a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-7.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-70.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-70.toml new file mode 100644 index 0000000..a630c4f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-70.toml @@ -0,0 +1,12 @@ +make = "RICOH IMAGING COMPANY, LTD." +model = "PENTAX K-70" +clean_make = "Pentax" +clean_model = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-m.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-m.toml new file mode 100644 index 0000000..de6ab80 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-m.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-r.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-r.toml new file mode 100644 index 0000000..8193e49 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-r.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-s1.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-s1.toml new file mode 100644 index 0000000..c12d8f9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-s1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-s2.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-s2.toml new file mode 100644 index 0000000..ed90b9d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-s2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k-x.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k-x.toml new file mode 100644 index 0000000..0716f51 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k-x.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k100d.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k100d.toml new file mode 100644 index 0000000..09a3b05 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k100d.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k100dsuper.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k100dsuper.toml new file mode 100644 index 0000000..434d47c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k100dsuper.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k10d.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k10d.toml new file mode 100644 index 0000000..f7b93d6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k10d.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k110d.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k110d.toml new file mode 100644 index 0000000..b2de2d4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k110d.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k200d.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k200d.toml new file mode 100644 index 0000000..54c020f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k200d.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/k20d.toml b/third_party/rawler-0.7.2/data/cameras/pentax/k20d.toml new file mode 100644 index 0000000..2471ec9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/k20d.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/kf.toml b/third_party/rawler-0.7.2/data/cameras/pentax/kf.toml new file mode 100644 index 0000000..c916cac --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/kf.toml @@ -0,0 +1,12 @@ +make = "RICOH IMAGING COMPANY, LTD." +model = "PENTAX KF" +clean_make = "Pentax" +clean_model = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/pentax/kp.toml b/third_party/rawler-0.7.2/data/cameras/pentax/kp.toml new file mode 100644 index 0000000..fb6cf1d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/pentax/kp.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/h25.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/h25.toml new file mode 100644 index 0000000..ab3f33e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/h25.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/iq140.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/iq140.toml new file mode 100644 index 0000000..2ddb2c5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/iq140.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/iq150.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/iq150.toml new file mode 100644 index 0000000..a66e24a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/iq150.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/iq180.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/iq180.toml new file mode 100644 index 0000000..8018308 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/iq180.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/iq3_100mp.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/iq3_100mp.toml new file mode 100644 index 0000000..63f21aa --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/iq3_100mp.toml @@ -0,0 +1,13 @@ +make = "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] + diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/iq3_100mp_trichr.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/iq3_100mp_trichr.toml new file mode 100644 index 0000000..f8fde83 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/iq3_100mp_trichr.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/iq4_150mp.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/iq4_150mp.toml new file mode 100644 index 0000000..3e8ca9f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/iq4_150mp.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/ixm_100.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/ixm_100.toml new file mode 100644 index 0000000..5bca79a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/ixm_100.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/ixm_rs150f.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/ixm_rs150f.toml new file mode 100644 index 0000000..002bc12 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/ixm_rs150f.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/ixu180.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/ixu180.toml new file mode 100644 index 0000000..1762498 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/ixu180.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/ixu_rs1000_nir.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/ixu_rs1000_nir.toml new file mode 100644 index 0000000..3d53b1d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/ixu_rs1000_nir.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/p20.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/p20.toml new file mode 100644 index 0000000..519e931 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/p20.toml @@ -0,0 +1,13 @@ +make = "Phase One A/S" +model = "P20+" +clean_make = "Phase One" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/p25.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/p25.toml new file mode 100644 index 0000000..fbf97c1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/p25.toml @@ -0,0 +1,15 @@ +make = "Phase One A/S" +model = "P25" +clean_make = "Phase One" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/p30.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/p30.toml new file mode 100644 index 0000000..34cfcdb --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/p30.toml @@ -0,0 +1,13 @@ +make = "Phase One A/S" +model = "P30" +clean_make = "Phase One" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/p45.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/p45.toml new file mode 100644 index 0000000..ded7982 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/p45.toml @@ -0,0 +1,15 @@ +make = "Phase One A/S" +model = "P45" +clean_make = "Phase One" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/phase_one/p65.toml b/third_party/rawler-0.7.2/data/cameras/phase_one/p65.toml new file mode 100644 index 0000000..b6a88b8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/phase_one/p65.toml @@ -0,0 +1,13 @@ +make = "Phase One A/S" +model = "P65+" +clean_make = "Phase One" +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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/ex1.toml b/third_party/rawler-0.7.2/data/cameras/samsung/ex1.toml new file mode 100644 index 0000000..34b98fc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/ex1.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/ex2f.toml b/third_party/rawler-0.7.2/data/cameras/samsung/ex2f.toml new file mode 100644 index 0000000..957f7da --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/ex2f.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx1.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx1.toml new file mode 100644 index 0000000..615828a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx1.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx10.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx10.toml new file mode 100644 index 0000000..7d49821 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx10.toml @@ -0,0 +1,13 @@ +make = "SAMSUNG" +model = "NX10" +clean_make = "Samsung" +clean_model = "NX10" +whitepoint = 3750 +color_pattern = "BGGR" +active_area = [8, 8, 8, 0] +crop_area = [20, 12, 92, 56] +blackareav = [0, 8] + +[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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx100.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx100.toml new file mode 100644 index 0000000..fd930f9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx100.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx1000.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx1000.toml new file mode 100644 index 0000000..a929b1b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx1000.toml @@ -0,0 +1,15 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx11.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx11.toml new file mode 100644 index 0000000..7a93a1a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx11.toml @@ -0,0 +1,13 @@ +make = "SAMSUNG" +model = "NX11" +clean_make = "Samsung" +clean_model = "NX11" +whitepoint = 3750 +color_pattern = "BGGR" +active_area = [8, 8, 8, 0] +crop_area = [20, 12, 92, 56] +blackareav = [0, 8] + +[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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx1100.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx1100.toml new file mode 100644 index 0000000..00c67cd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx1100.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx20.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx20.toml new file mode 100644 index 0000000..2849828 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx20.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx200.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx200.toml new file mode 100644 index 0000000..5970154 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx200.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx2000.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx2000.toml new file mode 100644 index 0000000..6b677d6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx2000.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx210.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx210.toml new file mode 100644 index 0000000..158a249 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx210.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx30.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx30.toml new file mode 100644 index 0000000..d90a904 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx30.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx300.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx300.toml new file mode 100644 index 0000000..a6b4413 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx300.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx3000.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx3000.toml new file mode 100644 index 0000000..8a43290 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx3000.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx300m.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx300m.toml new file mode 100644 index 0000000..434197d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx300m.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx3300.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx3300.toml new file mode 100644 index 0000000..2915488 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx3300.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx5.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx5.toml new file mode 100644 index 0000000..f7804c4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx5.toml @@ -0,0 +1,13 @@ +make = "SAMSUNG" +model = "NX5" +clean_make = "Samsung" +clean_model = "NX5" +whitepoint = 3750 +color_pattern = "BGGR" +active_area = [8, 8, 8, 0] +crop_area = [20, 12, 92, 56] +blackareav = [0, 8] + +[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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx500.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx500.toml new file mode 100644 index 0000000..9b9d3f8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx500.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/nx_mini.toml b/third_party/rawler-0.7.2/data/cameras/samsung/nx_mini.toml new file mode 100644 index 0000000..b6faaf2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/nx_mini.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/samsung/wb2000.toml b/third_party/rawler-0.7.2/data/cameras/samsung/wb2000.toml new file mode 100644 index 0000000..faf95ad --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/samsung/wb2000.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a1.toml b/third_party/rawler-0.7.2/data/cameras/sony/a1.toml new file mode 100644 index 0000000..1995b33 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a1.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a100.toml b/third_party/rawler-0.7.2/data/cameras/sony/a100.toml new file mode 100644 index 0000000..9a3d253 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a100.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a1m2.toml b/third_party/rawler-0.7.2/data/cameras/sony/a1m2.toml new file mode 100644 index 0000000..3ad1e79 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a1m2.toml @@ -0,0 +1,10 @@ +make = "SONY" +model = "ILCE-1M2" +clean_make = "Sony" +clean_model = "ILCE-1M2" +color_pattern = "RGGB" +bps = 8 + +[cameras.color_matrix] +A = [1.201, -0.6965, 0.0665, -0.4276, 1.2077, 0.248, -0.0167, 0.0625, 0.7188] +D65 = [1.0058, -0.4074, -0.0932, -0.4777, 1.2731, 0.2274, -0.0544, 0.1282, 0.6102] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a200.toml b/third_party/rawler-0.7.2/data/cameras/sony/a200.toml new file mode 100644 index 0000000..1c84dff --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a200.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a230.toml b/third_party/rawler-0.7.2/data/cameras/sony/a230.toml new file mode 100644 index 0000000..73aa28a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a230.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a290.toml b/third_party/rawler-0.7.2/data/cameras/sony/a290.toml new file mode 100644 index 0000000..c021067 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a290.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a300.toml b/third_party/rawler-0.7.2/data/cameras/sony/a300.toml new file mode 100644 index 0000000..49c33e1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a300.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a3000.toml b/third_party/rawler-0.7.2/data/cameras/sony/a3000.toml new file mode 100644 index 0000000..e2a908f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a3000.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a33.toml b/third_party/rawler-0.7.2/data/cameras/sony/a33.toml new file mode 100644 index 0000000..f7a0177 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a33.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a330.toml b/third_party/rawler-0.7.2/data/cameras/sony/a330.toml new file mode 100644 index 0000000..f95ad94 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a330.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a35.toml b/third_party/rawler-0.7.2/data/cameras/sony/a35.toml new file mode 100644 index 0000000..9028210 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a35.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a350.toml b/third_party/rawler-0.7.2/data/cameras/sony/a350.toml new file mode 100644 index 0000000..6db4219 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a350.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a3500.toml b/third_party/rawler-0.7.2/data/cameras/sony/a3500.toml new file mode 100644 index 0000000..50b73bd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a3500.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a37.toml b/third_party/rawler-0.7.2/data/cameras/sony/a37.toml new file mode 100644 index 0000000..6c9ae45 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a37.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a380.toml b/third_party/rawler-0.7.2/data/cameras/sony/a380.toml new file mode 100644 index 0000000..6af4c5b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a380.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a390.toml b/third_party/rawler-0.7.2/data/cameras/sony/a390.toml new file mode 100644 index 0000000..24950c9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a390.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a450.toml b/third_party/rawler-0.7.2/data/cameras/sony/a450.toml new file mode 100644 index 0000000..2aa4773 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a450.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a500.toml b/third_party/rawler-0.7.2/data/cameras/sony/a500.toml new file mode 100644 index 0000000..f52d9d2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a500.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a5000.toml b/third_party/rawler-0.7.2/data/cameras/sony/a5000.toml new file mode 100644 index 0000000..76608a6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a5000.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a5100.toml b/third_party/rawler-0.7.2/data/cameras/sony/a5100.toml new file mode 100644 index 0000000..7514bd6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a5100.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a55.toml b/third_party/rawler-0.7.2/data/cameras/sony/a55.toml new file mode 100644 index 0000000..6d7c540 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a55.toml @@ -0,0 +1,19 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a550.toml b/third_party/rawler-0.7.2/data/cameras/sony/a550.toml new file mode 100644 index 0000000..734eb13 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a550.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a560.toml b/third_party/rawler-0.7.2/data/cameras/sony/a560.toml new file mode 100644 index 0000000..9e8cf17 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a560.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a57.toml b/third_party/rawler-0.7.2/data/cameras/sony/a57.toml new file mode 100644 index 0000000..03028ba --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a57.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a58.toml b/third_party/rawler-0.7.2/data/cameras/sony/a58.toml new file mode 100644 index 0000000..a0789cf --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a58.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a580.toml b/third_party/rawler-0.7.2/data/cameras/sony/a580.toml new file mode 100644 index 0000000..674637e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a580.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a6000.toml b/third_party/rawler-0.7.2/data/cameras/sony/a6000.toml new file mode 100644 index 0000000..226386c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a6000.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a6001.toml b/third_party/rawler-0.7.2/data/cameras/sony/a6001.toml new file mode 100644 index 0000000..e8f3f82 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a6001.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a6100.toml b/third_party/rawler-0.7.2/data/cameras/sony/a6100.toml new file mode 100644 index 0000000..6907f6c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a6100.toml @@ -0,0 +1,19 @@ +make = "SONY" +model = "ILCE-6100" +clean_make = "Sony" +clean_model = "ILCE-6100" + +model_aliases = [ + ["ILCE-6100A", "ILCE-6100A"], +] + +##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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a6300.toml b/third_party/rawler-0.7.2/data/cameras/sony/a6300.toml new file mode 100644 index 0000000..db1a47d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a6300.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a6400.toml b/third_party/rawler-0.7.2/data/cameras/sony/a6400.toml new file mode 100644 index 0000000..3714099 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a6400.toml @@ -0,0 +1,19 @@ +make = "SONY" +model = "ILCE-6400" +clean_make = "Sony" +clean_model = "ILCE-6400" + +model_aliases = [ + ["ILCE-6400A", "ILCE-6400A"], +] + +##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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a65.toml b/third_party/rawler-0.7.2/data/cameras/sony/a65.toml new file mode 100644 index 0000000..42b559b --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a65.toml @@ -0,0 +1,19 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a6500.toml b/third_party/rawler-0.7.2/data/cameras/sony/a6500.toml new file mode 100644 index 0000000..d9aea2f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a6500.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a6600.toml b/third_party/rawler-0.7.2/data/cameras/sony/a6600.toml new file mode 100644 index 0000000..c88d6c8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a6600.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a6700.toml b/third_party/rawler-0.7.2/data/cameras/sony/a6700.toml new file mode 100644 index 0000000..837251f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a6700.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a68.toml b/third_party/rawler-0.7.2/data/cameras/sony/a68.toml new file mode 100644 index 0000000..20a44f3 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a68.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7.toml new file mode 100644 index 0000000..c2928b1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a700.toml b/third_party/rawler-0.7.2/data/cameras/sony/a700.toml new file mode 100644 index 0000000..86b516c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a700.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a77.toml b/third_party/rawler-0.7.2/data/cameras/sony/a77.toml new file mode 100644 index 0000000..948164e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a77.toml @@ -0,0 +1,19 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a77m2.toml b/third_party/rawler-0.7.2/data/cameras/sony/a77m2.toml new file mode 100644 index 0000000..b981cec --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a77m2.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7c.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7c.toml new file mode 100644 index 0000000..6e8ac2a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7c.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7cm2.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7cm2.toml new file mode 100644 index 0000000..ec6d1be --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7cm2.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7cr.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7cr.toml new file mode 100644 index 0000000..f186eb1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7cr.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7m2.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7m2.toml new file mode 100644 index 0000000..b88d01a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7m2.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7m3.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7m3.toml new file mode 100644 index 0000000..3c6daef --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7m3.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7m4.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7m4.toml new file mode 100644 index 0000000..38ae1b6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7m4.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7r.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7r.toml new file mode 100644 index 0000000..9c5e6a0 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7r.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7rm2.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7rm2.toml new file mode 100644 index 0000000..f37c50d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7rm2.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7rm3.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7rm3.toml new file mode 100644 index 0000000..8f46a07 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7rm3.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7rm3a.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7rm3a.toml new file mode 100644 index 0000000..be76ddf --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7rm3a.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7rm4.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7rm4.toml new file mode 100644 index 0000000..12471e7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7rm4.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7rm4a.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7rm4a.toml new file mode 100644 index 0000000..7371a12 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7rm4a.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7rm5.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7rm5.toml new file mode 100644 index 0000000..ddbd850 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7rm5.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7s.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7s.toml new file mode 100644 index 0000000..93be419 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7s.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7sm2.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7sm2.toml new file mode 100644 index 0000000..d93aa8f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7sm2.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a7sm3.toml b/third_party/rawler-0.7.2/data/cameras/sony/a7sm3.toml new file mode 100644 index 0000000..56ba182 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a7sm3.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a850.toml b/third_party/rawler-0.7.2/data/cameras/sony/a850.toml new file mode 100644 index 0000000..b516de6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a850.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a9.toml b/third_party/rawler-0.7.2/data/cameras/sony/a9.toml new file mode 100644 index 0000000..ebb76c5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a9.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a900.toml b/third_party/rawler-0.7.2/data/cameras/sony/a900.toml new file mode 100644 index 0000000..3b1aaa7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a900.toml @@ -0,0 +1,13 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a99.toml b/third_party/rawler-0.7.2/data/cameras/sony/a99.toml new file mode 100644 index 0000000..19a3b94 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a99.toml @@ -0,0 +1,19 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a99m2.toml b/third_party/rawler-0.7.2/data/cameras/sony/a99m2.toml new file mode 100644 index 0000000..081d106 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a99m2.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a9m2.toml b/third_party/rawler-0.7.2/data/cameras/sony/a9m2.toml new file mode 100644 index 0000000..de56a3c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a9m2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/a9m3.toml b/third_party/rawler-0.7.2/data/cameras/sony/a9m3.toml new file mode 100644 index 0000000..cd4120a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/a9m3.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/f828.toml b/third_party/rawler-0.7.2/data/cameras/sony/f828.toml new file mode 100644 index 0000000..bee6d28 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/f828.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/fx3.toml b/third_party/rawler-0.7.2/data/cameras/sony/fx3.toml new file mode 100644 index 0000000..9d6b161 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/fx3.toml @@ -0,0 +1,17 @@ +make = "SONY" +model = "ILME-FX3" +clean_make = "Sony" +clean_model = "ILME-FX3" + +model_aliases = [ + ["ILME-FX3A", "ILME-FX3A"], +] + +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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/fx30.toml b/third_party/rawler-0.7.2/data/cameras/sony/fx30.toml new file mode 100644 index 0000000..28db53d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/fx30.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/hx95.toml b/third_party/rawler-0.7.2/data/cameras/sony/hx95.toml new file mode 100644 index 0000000..9b90ad8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/hx95.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/hx99.toml b/third_party/rawler-0.7.2/data/cameras/sony/hx99.toml new file mode 100644 index 0000000..c293c9d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/hx99.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/nex3.toml b/third_party/rawler-0.7.2/data/cameras/sony/nex3.toml new file mode 100644 index 0000000..2b61b20 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/nex3.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/nex3n.toml b/third_party/rawler-0.7.2/data/cameras/sony/nex3n.toml new file mode 100644 index 0000000..1447610 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/nex3n.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/nex5.toml b/third_party/rawler-0.7.2/data/cameras/sony/nex5.toml new file mode 100644 index 0000000..e9e67a6 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/nex5.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/nex5n.toml b/third_party/rawler-0.7.2/data/cameras/sony/nex5n.toml new file mode 100644 index 0000000..5dc3b0a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/nex5n.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/nex5r.toml b/third_party/rawler-0.7.2/data/cameras/sony/nex5r.toml new file mode 100644 index 0000000..8f5236e --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/nex5r.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/nex5t.toml b/third_party/rawler-0.7.2/data/cameras/sony/nex5t.toml new file mode 100644 index 0000000..cdea812 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/nex5t.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/nex6.toml b/third_party/rawler-0.7.2/data/cameras/sony/nex6.toml new file mode 100644 index 0000000..1d722fc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/nex6.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/nex7.toml b/third_party/rawler-0.7.2/data/cameras/sony/nex7.toml new file mode 100644 index 0000000..6924aaf --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/nex7.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/nexc3.toml b/third_party/rawler-0.7.2/data/cameras/sony/nexc3.toml new file mode 100644 index 0000000..7582bd7 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/nexc3.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/nexf3.toml b/third_party/rawler-0.7.2/data/cameras/sony/nexf3.toml new file mode 100644 index 0000000..6981fa4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/nexf3.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/qx1.toml b/third_party/rawler-0.7.2/data/cameras/sony/qx1.toml new file mode 100644 index 0000000..9e0006f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/qx1.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/r1.toml b/third_party/rawler-0.7.2/data/cameras/sony/r1.toml new file mode 100644 index 0000000..f840c51 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/r1.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx0.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx0.toml new file mode 100644 index 0000000..af21ce4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx0.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx0m2.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx0m2.toml new file mode 100644 index 0000000..324c9c5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx0m2.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx1.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx1.toml new file mode 100644 index 0000000..e5c7be1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx1.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx10.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx10.toml new file mode 100644 index 0000000..112e4cd --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx10.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx100.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx100.toml new file mode 100644 index 0000000..7a8c1f8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx100.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx100m2.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx100m2.toml new file mode 100644 index 0000000..1197c71 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx100m2.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx100m3.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx100m3.toml new file mode 100644 index 0000000..516d50d --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx100m3.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx100m4.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx100m4.toml new file mode 100644 index 0000000..aaf81a4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx100m4.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx100m5.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx100m5.toml new file mode 100644 index 0000000..487ffdb --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx100m5.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx100m5a.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx100m5a.toml new file mode 100644 index 0000000..1b7d8ec --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx100m5a.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx100m6.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx100m6.toml new file mode 100644 index 0000000..10d91d4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx100m6.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx100m7.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx100m7.toml new file mode 100644 index 0000000..095efbc --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx100m7.toml @@ -0,0 +1,16 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx10m2.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx10m2.toml new file mode 100644 index 0000000..7be3962 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx10m2.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx10m3.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx10m3.toml new file mode 100644 index 0000000..31ade55 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx10m3.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx10m4.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx10m4.toml new file mode 100644 index 0000000..0f753bb --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx10m4.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx1r.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx1r.toml new file mode 100644 index 0000000..884cd4a --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx1r.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/rx1rm2.toml b/third_party/rawler-0.7.2/data/cameras/sony/rx1rm2.toml new file mode 100644 index 0000000..e5740d4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/rx1rm2.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/umc-r10c.toml b/third_party/rawler-0.7.2/data/cameras/sony/umc-r10c.toml new file mode 100644 index 0000000..bad056f --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/umc-r10c.toml @@ -0,0 +1,10 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/zv1.toml b/third_party/rawler-0.7.2/data/cameras/sony/zv1.toml new file mode 100644 index 0000000..06379ab --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/zv1.toml @@ -0,0 +1,19 @@ +make = "SONY" +model = "ZV-1" +clean_make = "Sony" +clean_model = "ZV-1" + +model_aliases = [ + ["ZV-1A", "ZV-1A"], +] + +##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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/zv1m2.toml b/third_party/rawler-0.7.2/data/cameras/sony/zv1m2.toml new file mode 100644 index 0000000..4657100 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/zv1m2.toml @@ -0,0 +1,13 @@ +make = "SONY" +model = "ZV-1M2" +clean_make = "Sony" +clean_model = "ZV-1M2" + +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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/zve1.toml b/third_party/rawler-0.7.2/data/cameras/sony/zve1.toml new file mode 100644 index 0000000..5142cd8 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/zve1.toml @@ -0,0 +1,11 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/zve10.toml b/third_party/rawler-0.7.2/data/cameras/sony/zve10.toml new file mode 100644 index 0000000..a28794c --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/zve10.toml @@ -0,0 +1,14 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/cameras/sony/zve10m2.toml b/third_party/rawler-0.7.2/data/cameras/sony/zve10m2.toml new file mode 100644 index 0000000..8c36449 --- /dev/null +++ b/third_party/rawler-0.7.2/data/cameras/sony/zve10m2.toml @@ -0,0 +1,12 @@ +make = "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] diff --git a/third_party/rawler-0.7.2/data/join.rs b/third_party/rawler-0.7.2/data/join.rs new file mode 100644 index 0000000..ecb80f9 --- /dev/null +++ b/third_party/rawler-0.7.2/data/join.rs @@ -0,0 +1,73 @@ +use 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"); + } +} diff --git a/third_party/rawler-0.7.2/data/lenses/README.md b/third_party/rawler-0.7.2/data/lenses/README.md new file mode 100644 index 0000000..4c5600c --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/README.md @@ -0,0 +1,5 @@ +# 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. + diff --git a/third_party/rawler-0.7.2/data/lenses/e_mount/laowa.toml b/third_party/rawler-0.7.2/data/lenses/e_mount/laowa.toml new file mode 100644 index 0000000..d1abadc --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/e_mount/laowa.toml @@ -0,0 +1,7 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/e_mount/samyang.toml b/third_party/rawler-0.7.2/data/lenses/e_mount/samyang.toml new file mode 100644 index 0000000..037a794 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/e_mount/samyang.toml @@ -0,0 +1,151 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/e_mount/sigma.toml b/third_party/rawler-0.7.2/data/lenses/e_mount/sigma.toml new file mode 100644 index 0000000..69163da --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/e_mount/sigma.toml @@ -0,0 +1,447 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/e_mount/sony.toml b/third_party/rawler-0.7.2/data/lenses/e_mount/sony.toml new file mode 100644 index 0000000..1145514 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/e_mount/sony.toml @@ -0,0 +1,811 @@ +[[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 = 32875 +make = "Sony" +model = "FE 24-70mm F2.8 GM II" +focal_range = [[24, 1], [70, 1]] +aperture_range = [[28, 10], [28, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 32876 +make = "Sony" +model = "E 11mm F1.8" +focal_range = [[11, 1], [11, 1]] +aperture_range = [[18, 10], [18, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 32877 +make = "Sony" +model = "E 15mm F1.4 G" +focal_range = [[15, 1], [15, 1]] +aperture_range = [[14, 10], [14, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 32878 +make = "Sony" +model = "FE 20-70mm F4 G" +focal_range = [[20, 1], [70, 1]] +aperture_range = [[4, 1], [4, 1]] + +[[lenses]] +mount = "e-mount" +lens_id = 32879 +make = "Sony" +model = "FE 50mm F1.4 GM" +focal_range = [[50, 1], [50, 1]] +aperture_range = [[14, 10], [14, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 32880 +make = "Sony" +model = "FE 16mm F1.8 G" +focal_range = [[16, 1], [16, 1]] +aperture_range = [[18, 10], [18, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 32881 +make = "Sony" +model = "FE 24-50mm F2.8 G" +focal_range = [[24, 1], [50, 1]] +aperture_range = [[28, 10], [28, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 32882 +make = "Sony" +model = "FE 16-25mm F2.8 G" +focal_range = [[16, 1], [25, 1]] +aperture_range = [[28, 10], [28, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 32884 +make = "Sony" +model = "FE 70-200mm F4 Macro G OSS II" +focal_range = [[70, 1], [200, 1]] +aperture_range = [[4, 1], [4, 1]] + +[[lenses]] +mount = "e-mount" +lens_id = 32885 +make = "Sony" +model = "FE 16-35mm F2.8 GM II" +focal_range = [[16, 1], [35, 1]] +aperture_range = [[28, 10], [28, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 32886 +make = "Sony" +model = "FE 300mm F2.8 GM OSS" +focal_range = [[300, 1], [300, 1]] +aperture_range = [[28, 10], [28, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 32887 +make = "Sony" +model = "E PZ 16-50mm F3.5-5.6 OSS II" +focal_range = [[16, 1], [50, 1]] +aperture_range = [[35, 10], [56, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 32888 +make = "Sony" +model = "FE 85mm F1.4 GM II" +focal_range = [[85, 1], [85, 1]] +aperture_range = [[4, 1], [4, 1]] + +[[lenses]] +mount = "e-mount" +lens_id = 32889 +make = "Sony" +model = "FE 28-70mm F2 GM" +focal_range = [[28, 1], [70, 1]] +aperture_range = [[2, 1], [2, 1]] + +[[lenses]] +mount = "e-mount" +lens_id = 32890 +make = "Sony" +model = "FE 400-800mm F6.3-8 G OSS" +focal_range = [[400, 1], [800, 1]] +aperture_range = [[63, 10], [8, 1]] + + +[[lenses]] +mount = "e-mount" +lens_id = 32891 +make = "Sony" +model = "FE 50-150mm F2 GM" +focal_range = [[50, 1], [150, 1]] +aperture_range = [[2, 1], [2, 1]] + +[[lenses]] +mount = "e-mount" +lens_id = 32893 +make = "Sony" +model = "FE 100mm F2.8 Macro GM OSS" +focal_range = [[100, 1], [100, 1]] +aperture_range = [[28, 10], [28, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 33093 +make = "Sony" +model = "FE 100mm F2.8 Macro GM OSS + 1.4X Teleconverter" +focal_range = [[100, 1], [100, 1]] +aperture_range = [[28, 10], [28, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 33094 +make = "Sony" +model = "FE 100mm F2.8 Macro GM OSS + 2X Teleconverter" +focal_range = [[100, 1], [100, 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]] diff --git a/third_party/rawler-0.7.2/data/lenses/e_mount/tamron.toml b/third_party/rawler-0.7.2/data/lenses/e_mount/tamron.toml new file mode 100644 index 0000000..dfc23ea --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/e_mount/tamron.toml @@ -0,0 +1,135 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/e_mount/tokina.toml b/third_party/rawler-0.7.2/data/lenses/e_mount/tokina.toml new file mode 100644 index 0000000..82a4396 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/e_mount/tokina.toml @@ -0,0 +1,31 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/e_mount/viltrox.toml b/third_party/rawler-0.7.2/data/lenses/e_mount/viltrox.toml new file mode 100644 index 0000000..2895852 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/e_mount/viltrox.toml @@ -0,0 +1,119 @@ +[[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 = 49474 +make = "Viltrox" +model = "13mm F1.4 E" +focal_range = [[13, 1], [13, 1]] +aperture_range = [[14, 10], [14, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 49474 +make = "Viltrox" +model = "16mm F1.8 FE" +focal_range = [[16, 1], [16, 1]] +aperture_range = [[18, 10], [18, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 49474 +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 = 49474 +make = "Viltrox" +model = "24mm F1.8 FE" +focal_range = [[24, 1], [24, 1]] +aperture_range = [[18, 10], [18, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 49474 +make = "Viltrox" +model = "28mm F1.8 FE" +focal_range = [[28, 1], [28, 1]] +aperture_range = [[18, 10], [18, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 49474 +make = "Viltrox" +model = "33mm F1.4 E" +focal_range = [[33, 1], [33, 1]] +aperture_range = [[14, 10], [14, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 49474 +make = "Viltrox" +model = "35mm F1.8 FE" +focal_range = [[35, 1], [35, 1]] +aperture_range = [[18, 10], [18, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 49474 +make = "Viltrox" +model = "50mm F1.8 FE" +focal_range = [[50, 1], [50, 1]] +aperture_range = [[18, 10], [18, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 49474 +make = "Viltrox" +model = "75mm F1.2 E" +focal_range = [[75, 1], [75, 1]] +aperture_range = [[12, 10], [12, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 49474 +make = "Viltrox" +model = "20mm F2.8 FE" +focal_range = [[20, 1], [20, 1]] +aperture_range = [[28, 10], [28, 10]] + +[[lenses]] +mount = "e-mount" +lens_id = 49474 +make = "Viltrox" +model = "AF 135/1.8 LAB FE" +focal_range = [[135, 1], [135, 1]] +aperture_range = [[18, 10], [18, 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]] diff --git a/third_party/rawler-0.7.2/data/lenses/e_mount/voigtlander.toml b/third_party/rawler-0.7.2/data/lenses/e_mount/voigtlander.toml new file mode 100644 index 0000000..b563e6e --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/e_mount/voigtlander.toml @@ -0,0 +1,127 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/e_mount/zeiss.toml b/third_party/rawler-0.7.2/data/lenses/e_mount/zeiss.toml new file mode 100644 index 0000000..905c692 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/e_mount/zeiss.toml @@ -0,0 +1,119 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/ef_mount/canon.toml b/third_party/rawler-0.7.2/data/lenses/ef_mount/canon.toml new file mode 100644 index 0000000..feef36c --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/ef_mount/canon.toml @@ -0,0 +1,1792 @@ +[[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]] +keyname = "EF70-200mm f/2.8L IS II USM +2x III" + +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/ef_mount/cosina.toml b/third_party/rawler-0.7.2/data/lenses/ef_mount/cosina.toml new file mode 100644 index 0000000..5f12bd1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/ef_mount/cosina.toml @@ -0,0 +1,7 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/ef_mount/irix.toml b/third_party/rawler-0.7.2/data/lenses/ef_mount/irix.toml new file mode 100644 index 0000000..c8f08bb --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/ef_mount/irix.toml @@ -0,0 +1,7 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/ef_mount/rokinon.toml b/third_party/rawler-0.7.2/data/lenses/ef_mount/rokinon.toml new file mode 100644 index 0000000..3868e6a --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/ef_mount/rokinon.toml @@ -0,0 +1,31 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/ef_mount/samyang.toml b/third_party/rawler-0.7.2/data/lenses/ef_mount/samyang.toml new file mode 100644 index 0000000..3eabb78 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/ef_mount/samyang.toml @@ -0,0 +1,7 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/ef_mount/sigma.toml b/third_party/rawler-0.7.2/data/lenses/ef_mount/sigma.toml new file mode 100644 index 0000000..b8fc13c --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/ef_mount/sigma.toml @@ -0,0 +1,1013 @@ +[[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 +key = "20mm F1.4 DG HSM | Art 015" +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]] diff --git a/third_party/rawler-0.7.2/data/lenses/ef_mount/tamron.toml b/third_party/rawler-0.7.2/data/lenses/ef_mount/tamron.toml new file mode 100644 index 0000000..97b4b78 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/ef_mount/tamron.toml @@ -0,0 +1,420 @@ +[[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]] +keyname = "TAMRON 100-400mm F/4.5-6.3 Di VC USD A035" + +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/ef_mount/tokina.toml b/third_party/rawler-0.7.2/data/lenses/ef_mount/tokina.toml new file mode 100644 index 0000000..5c3ffbc --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/ef_mount/tokina.toml @@ -0,0 +1,119 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/ef_mount/venus.toml b/third_party/rawler-0.7.2/data/lenses/ef_mount/venus.toml new file mode 100644 index 0000000..1d9725b --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/ef_mount/venus.toml @@ -0,0 +1,8 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/ef_mount/voigtlander.toml b/third_party/rawler-0.7.2/data/lenses/ef_mount/voigtlander.toml new file mode 100644 index 0000000..970ef60 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/ef_mount/voigtlander.toml @@ -0,0 +1,31 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/ef_mount/yongnuo.toml b/third_party/rawler-0.7.2/data/lenses/ef_mount/yongnuo.toml new file mode 100644 index 0000000..ac30dbb --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/ef_mount/yongnuo.toml @@ -0,0 +1,17 @@ + +[[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]] + diff --git a/third_party/rawler-0.7.2/data/lenses/ef_mount/zeiss.toml b/third_party/rawler-0.7.2/data/lenses/ef_mount/zeiss.toml new file mode 100644 index 0000000..80dd507 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/ef_mount/zeiss.toml @@ -0,0 +1,243 @@ + +[[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]] + diff --git a/third_party/rawler-0.7.2/data/lenses/f_mount/cosina.toml b/third_party/rawler-0.7.2/data/lenses/f_mount/cosina.toml new file mode 100644 index 0000000..8d995df --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/f_mount/cosina.toml @@ -0,0 +1,47 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/f_mount/misc.toml b/third_party/rawler-0.7.2/data/lenses/f_mount/misc.toml new file mode 100644 index 0000000..27a0fb3 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/f_mount/misc.toml @@ -0,0 +1,143 @@ + +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/f_mount/nikon.toml b/third_party/rawler-0.7.2/data/lenses/f_mount/nikon.toml new file mode 100644 index 0000000..88b056b --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/f_mount/nikon.toml @@ -0,0 +1,2015 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/f_mount/samyang.toml b/third_party/rawler-0.7.2/data/lenses/f_mount/samyang.toml new file mode 100644 index 0000000..2255ea5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/f_mount/samyang.toml @@ -0,0 +1,79 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/f_mount/sigma.toml b/third_party/rawler-0.7.2/data/lenses/f_mount/sigma.toml new file mode 100644 index 0000000..10d53e4 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/f_mount/sigma.toml @@ -0,0 +1,1303 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/f_mount/sony.toml b/third_party/rawler-0.7.2/data/lenses/f_mount/sony.toml new file mode 100644 index 0000000..0e68cc2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/f_mount/sony.toml @@ -0,0 +1,15 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/f_mount/tamron.toml b/third_party/rawler-0.7.2/data/lenses/f_mount/tamron.toml new file mode 100644 index 0000000..b56d431 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/f_mount/tamron.toml @@ -0,0 +1,647 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/f_mount/tokina.toml b/third_party/rawler-0.7.2/data/lenses/f_mount/tokina.toml new file mode 100644 index 0000000..9df7d55 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/f_mount/tokina.toml @@ -0,0 +1,327 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/f_mount/voigtlander.toml b/third_party/rawler-0.7.2/data/lenses/f_mount/voigtlander.toml new file mode 100644 index 0000000..107d020 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/f_mount/voigtlander.toml @@ -0,0 +1,47 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/f_mount/zeiss.toml b/third_party/rawler-0.7.2/data/lenses/f_mount/zeiss.toml new file mode 100644 index 0000000..a2cc19d --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/f_mount/zeiss.toml @@ -0,0 +1,159 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/fixed/canon_fixed_lenses.toml b/third_party/rawler-0.7.2/data/lenses/fixed/canon_fixed_lenses.toml new file mode 100644 index 0000000..0bdfe93 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/fixed/canon_fixed_lenses.toml @@ -0,0 +1,15 @@ +[[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" diff --git a/third_party/rawler-0.7.2/data/lenses/k_mount/pentax.toml b/third_party/rawler-0.7.2/data/lenses/k_mount/pentax.toml new file mode 100644 index 0000000..8cde59f --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/k_mount/pentax.toml @@ -0,0 +1,2510 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/mft_mount/leica.toml b/third_party/rawler-0.7.2/data/lenses/mft_mount/leica.toml new file mode 100644 index 0000000..db6dea1 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/mft_mount/leica.toml @@ -0,0 +1,151 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/mft_mount/lumix.toml b/third_party/rawler-0.7.2/data/lenses/mft_mount/lumix.toml new file mode 100644 index 0000000..47b63bf --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/mft_mount/lumix.toml @@ -0,0 +1,215 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/mft_mount/misc.toml b/third_party/rawler-0.7.2/data/lenses/mft_mount/misc.toml new file mode 100644 index 0000000..b755d63 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/mft_mount/misc.toml @@ -0,0 +1,15 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/mft_mount/olympus.toml b/third_party/rawler-0.7.2/data/lenses/mft_mount/olympus.toml new file mode 100644 index 0000000..9c148dd --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/mft_mount/olympus.toml @@ -0,0 +1,479 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/mft_mount/sigma.toml b/third_party/rawler-0.7.2/data/lenses/mft_mount/sigma.toml new file mode 100644 index 0000000..1129cfd --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/mft_mount/sigma.toml @@ -0,0 +1,191 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/nx_mount/samsung.toml b/third_party/rawler-0.7.2/data/lenses/nx_mount/samsung.toml new file mode 100644 index 0000000..daf42a0 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/nx_mount/samsung.toml @@ -0,0 +1,135 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/phaseone/phaseone.toml b/third_party/rawler-0.7.2/data/lenses/phaseone/phaseone.toml new file mode 100644 index 0000000..9ec1795 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/phaseone/phaseone.toml @@ -0,0 +1,15 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/rf_mount/canon.toml b/third_party/rawler-0.7.2/data/lenses/rf_mount/canon.toml new file mode 100644 index 0000000..fdfa18f --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/rf_mount/canon.toml @@ -0,0 +1,360 @@ +[[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]] + +[[lenses]] +mount = "rf-mount" +key = "RF70-200mm F2.8 L IS USM Z" +lens_id = 61182 +lens_subid = 319 +make = "Canon" +model = "RF 70-200mm F2.8L IS USM Z" +focal_range = [[70, 1], [200, 1]] +aperture_range = [[28, 10], [28, 10]] + +[[lenses]] +mount = "rf-mount" +key = "RF50mm F1.4 L VCM" +lens_id = 61182 +lens_subid = 325 +make = "Canon" +model = "RF 50mm F1.4L VCM" +focal_range = [[50, 1], [50, 1]] +aperture_range = [[14, 10], [14, 10]] diff --git a/third_party/rawler-0.7.2/data/lenses/rf_mount/samyang.toml b/third_party/rawler-0.7.2/data/lenses/rf_mount/samyang.toml new file mode 100644 index 0000000..7c36d39 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/rf_mount/samyang.toml @@ -0,0 +1,7 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/rf_mount/tamron.toml b/third_party/rawler-0.7.2/data/lenses/rf_mount/tamron.toml new file mode 100644 index 0000000..8f8b0d2 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/rf_mount/tamron.toml @@ -0,0 +1,9 @@ +[[lenses]] +mount = "rf-mount" +key = "TAMRON 18-300mm F3.5-6.3 B061 RF" +lens_id = 373 +lens_subid = 0 +make = "Tamron" +model = "18-300mm F/3.5-6.3 Di III-A VC VXD" +focal_range = [[18, 1], [300, 1]] +aperture_range = [[35, 10], [63, 10]] diff --git a/third_party/rawler-0.7.2/data/lenses/x_mount/hasselblad.toml b/third_party/rawler-0.7.2/data/lenses/x_mount/hasselblad.toml new file mode 100644 index 0000000..6f4801e --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/x_mount/hasselblad.toml @@ -0,0 +1,7 @@ +[[lenses]] +key = "xcd_80" +mount = "x-mount" +make = "Hasselblad" +model = "XCD 80" +focal_range = [[80, 1], [80, 1]] +aperture_range = [[19, 10], [19, 10]] diff --git a/third_party/rawler-0.7.2/data/lenses/z_mount/nikon.toml b/third_party/rawler-0.7.2/data/lenses/z_mount/nikon.toml new file mode 100644 index 0000000..8b317e3 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/z_mount/nikon.toml @@ -0,0 +1,159 @@ +[[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]] diff --git a/third_party/rawler-0.7.2/data/lenses/z_mount/tamron.toml b/third_party/rawler-0.7.2/data/lenses/z_mount/tamron.toml new file mode 100644 index 0000000..d3d2ed5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/z_mount/tamron.toml @@ -0,0 +1,7 @@ +[[lenses]] +mount = "Z-mount" +lens_id = 57346 +make = "Tamron" +model = "35-150mm F/2-2.8 Di III VXD" +focal_range = [[35, 1], [150, 1]] +aperture_range = [[20, 10], [28, 10]] diff --git a/third_party/rawler-0.7.2/data/lenses/z_mount/viltrox.toml b/third_party/rawler-0.7.2/data/lenses/z_mount/viltrox.toml new file mode 100644 index 0000000..5c480e5 --- /dev/null +++ b/third_party/rawler-0.7.2/data/lenses/z_mount/viltrox.toml @@ -0,0 +1,7 @@ +[[lenses]] +mount = "Z-mount" +lens_id = 2826 +make = "Viltrox" +model = "AF 35/1.7 Z" +focal_range = [[35, 1], [35, 1]] +aperture_range = [[17, 10], [17, 10]] diff --git a/third_party/rawler-0.7.2/src/analyze.rs b/third_party/rawler-0.7.2/src/analyze.rs new file mode 100644 index 0000000..5edd407 --- /dev/null +++ b/third_party/rawler-0.7.2/src/analyze.rs @@ -0,0 +1,277 @@ +use 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(()) +} diff --git a/third_party/rawler-0.7.2/src/bin/benchmark.rs b/third_party/rawler-0.7.2/src/bin/benchmark.rs new file mode 100644 index 0000000..96798de --- /dev/null +++ b/third_party/rawler-0.7.2/src/bin/benchmark.rs @@ -0,0 +1,51 @@ +use 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); +} diff --git a/third_party/rawler-0.7.2/src/bin/identify.rs b/third_party/rawler-0.7.2/src/bin/identify.rs new file mode 100644 index 0000000..baaea53 --- /dev/null +++ b/third_party/rawler-0.7.2/src/bin/identify.rs @@ -0,0 +1,14 @@ +use 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"), + } +} diff --git a/third_party/rawler-0.7.2/src/bitarray.rs b/third_party/rawler-0.7.2/src/bitarray.rs new file mode 100644 index 0000000..742e904 --- /dev/null +++ b/third_party/rawler-0.7.2/src/bitarray.rs @@ -0,0 +1,242 @@ +// 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/bits.rs b/third_party/rawler-0.7.2/src/bits.rs new file mode 100644 index 0000000..ea8b336 --- /dev/null +++ b/third_party/rawler-0.7.2/src/bits.rs @@ -0,0 +1,378 @@ +// 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); + + #[allow(dead_code)] + const SIGN_BITS: usize = 1; + #[allow(dead_code)] + 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; + #[allow(dead_code)] + 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); + } +} diff --git a/third_party/rawler-0.7.2/src/buffer.rs b/third_party/rawler-0.7.2/src/buffer.rs new file mode 100644 index 0000000..9d59645 --- /dev/null +++ b/third_party/rawler-0.7.2/src/buffer.rs @@ -0,0 +1,51 @@ +use 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, + } + } +} diff --git a/third_party/rawler-0.7.2/src/cfa.rs b/third_party/rawler-0.7.2/src/cfa.rs new file mode 100644 index 0000000..49f8167 --- /dev/null +++ b/third_party/rawler-0.7.2/src/cfa.rs @@ -0,0 +1,371 @@ +use 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) + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/ari.rs b/third_party/rawler-0.7.2/src/decoders/ari.rs new file mode 100644 index 0000000..9bf1e58 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/ari.rs @@ -0,0 +1,103 @@ +use 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()) +} diff --git a/third_party/rawler-0.7.2/src/decoders/arw.rs b/third_party/rawler-0.7.2/src/decoders/arw.rs new file mode 100644 index 0000000..0191d22 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/arw.rs @@ -0,0 +1,797 @@ +use 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, +} diff --git a/third_party/rawler-0.7.2/src/decoders/camera.rs b/third_party/rawler-0.7.2/src/decoders/camera.rs new file mode 100644 index 0000000..f40fc38 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/camera.rs @@ -0,0 +1,276 @@ +use 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, + } + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/cr2.rs b/third_party/rawler-0.7.2/src/decoders/cr2.rs new file mode 100644 index 0000000..6853184 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/cr2.rs @@ -0,0 +1,903 @@ +// 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; diff --git a/third_party/rawler-0.7.2/src/decoders/cr2/colordata.rs b/third_party/rawler-0.7.2/src/decoders/cr2/colordata.rs new file mode 100644 index 0000000..58c6214 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/cr2/colordata.rs @@ -0,0 +1,145 @@ +use 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), 66 (R6MK3) + 64 | 66 => 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() + ))), + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/cr3.rs b/third_party/rawler-0.7.2/src/decoders/cr3.rs new file mode 100644 index 0000000..ffb76bd --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/cr3.rs @@ -0,0 +1,796 @@ +// 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, +} diff --git a/third_party/rawler-0.7.2/src/decoders/crw.rs b/third_party/rawler-0.7.2/src/decoders/crw.rs new file mode 100644 index 0000000..28f1951 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/crw.rs @@ -0,0 +1,285 @@ +use 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] +} diff --git a/third_party/rawler-0.7.2/src/decoders/dcr.rs b/third_party/rawler-0.7.2/src/decoders/dcr.rs new file mode 100644 index 0000000..0a33af1 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/dcr.rs @@ -0,0 +1,167 @@ +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::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 + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/dcs.rs b/third_party/rawler-0.7.2/src/decoders/dcs.rs new file mode 100644 index 0000000..566a56f --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/dcs.rs @@ -0,0 +1,75 @@ +use 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 + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/dng.rs b/third_party/rawler-0.7.2/src/decoders/dng.rs new file mode 100644 index 0000000..c7bd51d --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/dng.rs @@ -0,0 +1,436 @@ +use 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::matrix::*; +use crate::imgop::xyz::*; +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_with_mode(self.tiff.root_ifd(), "dng") + .or_else(|_| self.rawloader.check_supported(self.tiff.root_ifd())) + { + cam.clean_make = known_cam.clean_make; + cam.clean_model = known_cam.clean_model; + cam.hints.extend_from_slice(&known_cam.hints); + cam.params.extend(known_cam.params.iter().map(|(k, v)| (k.clone(), v.clone()))); + } else { + log::debug!("DNG: camera {} / {} is not in the camera catalog", cam.make, cam.model); + // panic!("Camera {} / {} is not in the camera catalog", cam.make, cam.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 wb_coeffs = self.get_wb(&cam)?; + let mut image = RawImage::new_with_data(cam, raw_data, width * cpp, height, cpp, wb_coeffs, 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, cam: &Camera) -> Result<[f32; 4]> { + if let Some(levels) = self.tiff.get_entry(DngTag::AsShotNeutral) { + Ok([1.0 / levels.force_f32(0), 1.0 / levels.force_f32(1), 1.0 / levels.force_f32(2), f32::NAN]) + } else if let Some(levels) = self.tiff.get_entry(DngTag::AsShotWhiteXY) { + // TODO: improve once AnalogBalance and CC is properly implemented + if let Some(flat_colormatrix) = cam.color_matrix.get(&Illuminant::D65) + && let Some(colormatrix) = transform_1d::<3, 3>(flat_colormatrix) + { + let wb_coeff = xy_whitepoint_to_wb_coeff(levels.force_f32(0), levels.force_f32(1), &colormatrix); + Ok([wb_coeff[0], wb_coeff[1], wb_coeff[2], f32::NAN]) + } else { + Ok([f32::NAN, f32::NAN, f32::NAN, 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_val = self.tiff.get_entry(cal).map(|e| e.force_u16(0)).unwrap_or(21); + let illuminant: Illuminant = illuminant_val.try_into().unwrap_or(Illuminant::D65); + + let mut matrix = FlatColorMatrix::new(); + for i in 0..c.count() as usize { + matrix.push(c.force_f32(i)); + } + + if !matrix.is_empty() && matrix.len() <= 12 { + result.insert(illuminant, matrix); + } else { + log::warn!("Invalid ColorMatrix dimensions for illuminant {:?}: length {}", illuminant, matrix.len()); + } + } + Ok(()) + }; + + read_matrix(DngTag::CalibrationIlluminant1, DngTag::ColorMatrix1)?; + read_matrix(DngTag::CalibrationIlluminant2, DngTag::ColorMatrix2)?; + // TODO: add 3 + + Ok(result) + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/erf.rs b/third_party/rawler-0.7.2/src/decoders/erf.rs new file mode 100644 index 0000000..099889c --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/erf.rs @@ -0,0 +1,113 @@ +use 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 + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/iiq.rs b/third_party/rawler-0.7.2/src/decoders/iiq.rs new file mode 100644 index 0000000..2a00277 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/iiq.rs @@ -0,0 +1,1196 @@ +// 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.clone(); // 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 + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/kdc.rs b/third_party/rawler-0.7.2/src/decoders/kdc.rs new file mode 100644 index 0000000..c2da106 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/kdc.rs @@ -0,0 +1,219 @@ +use 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) + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/mef.rs b/third_party/rawler-0.7.2/src/decoders/mef.rs new file mode 100644 index 0000000..9ec72f7 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/mef.rs @@ -0,0 +1,64 @@ +use 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 + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/mod.rs b/third_party/rawler-0.7.2/src/decoders/mod.rs new file mode 100644 index 0000000..972549c --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/mod.rs @@ -0,0 +1,1144 @@ +use chrono::FixedOffset; +use chrono::NaiveDateTime; +use chrono::TimeZone; +use image::DynamicImage; +use image::ImageBuffer; +use image::ImageFormat; +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) + } + + 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_jpeg_interchange_format(ifd: &IFD, rawsource: &RawSource) -> Result { + let offset = fetch_tiff_tag!(ifd, ExifTag::JPEGInterchangeFormat).force_usize(0) as u64; + let size = fetch_tiff_tag!(ifd, ExifTag::JPEGInterchangeFormatLength).force_usize(0) as u64; + let buf = rawsource.subview(offset, size)?; + image::load_from_memory_with_format(buf, ImageFormat::Jpeg).map_err(|err| RawlerError::DecoderFailed(format!("Failed to read JPEG image: {:?}", err))) +} + +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" => return use_decoder!(nef::NefDecoder, 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 +} diff --git a/third_party/rawler-0.7.2/src/decoders/mos.rs b/third_party/rawler-0.7.2/src/decoders/mos.rs new file mode 100644 index 0000000..ce48952 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/mos.rs @@ -0,0 +1,142 @@ +use 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) + } + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/mrw.rs b/third_party/rawler-0.7.2/src/decoders/mrw.rs new file mode 100644 index 0000000..f0176fb --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/mrw.rs @@ -0,0 +1,271 @@ +use 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] +} diff --git a/third_party/rawler-0.7.2/src/decoders/nef.rs b/third_party/rawler-0.7.2/src/decoders/nef.rs new file mode 100644 index 0000000..47bb499 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/nef.rs @@ -0,0 +1,817 @@ +use image::DynamicImage; +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::dynamic_image_from_ifd; +use crate::decoders::dynamic_image_from_jpeg_interchange_format; +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) + .or_else(|| tiff.find_ifd_with_new_subfile_type(0)) + .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a suitable IFD in NEF decoder")))?; + 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) + .or_else(|| self.tiff.find_ifd_with_new_subfile_type(0)) + .ok_or_else(|| RawlerError::DecoderFailed(format!("Failed to find a suitable IFD in NEF decoder")))?; + 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 mut cpp = fetch_tiff_tag!(raw, TiffCommonTag::BitsPerSample).count(); // Linear files don't have SamplesPerPixel + 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 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 { + 16 => { + // Used by Coolscan scanners + if self.tiff.little_endian() { + decode_16le(&src, width * cpp, height, dummy) + } else { + decode_16be(&src, width * cpp, height, dummy) + } + } + 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())?; + Ok(match self.get_lens_description() { + Ok(lens_data) => RawMetadata::new_with_lens(&self.camera, exif, lens_data.cloned()), + Err(err) => { + log::warn!("Failed to read lens information: {:?}", err); + RawMetadata::new(&self.camera, exif) + } + }) + } + + fn full_image(&self, file: &RawSource, params: &RawDecodeParams) -> Result> { + if params.image_index != 0 { + return Ok(None); + } + // High resolution preview image is stored in JPEGInterchangeFormat tag. + // Search for all IFDs and use the best match. + let mut ifds = self.tiff.find_ifds_with_filter(|ifd| { + if ifd.get_new_sub_file_type() == Some(1) { + ifd.get_entry(ExifTag::JPEGInterchangeFormatLength).is_some() + } else { + false + } + }); + + ifds.sort_by(|a, b| { + a.get_entry(ExifTag::JPEGInterchangeFormatLength) + .map(|x| x.force_u32(0)) + .cmp(&b.get_entry(ExifTag::JPEGInterchangeFormatLength).map(|x| x.force_u32(0))) + }); + + // Take the IFD with the largest JPEG stream size + if let Some(jpeg_ifd) = ifds.last() { + return Ok(Some(dynamic_image_from_jpeg_interchange_format(jpeg_ifd, file)?)); + } else { + // No matching IFDs found, use root IFD (possibly bad resolution) + Ok(Some(dynamic_image_from_ifd(self.tiff.root_ifd(), file)?)) + } + } + + 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 { + log::debug!("NEF: Don't know how to fetch WB, fallback to [1.0, 1.0, 1.0]"); + Ok([1.0, 1.0, 1.0, 1.0]) + } + } + + 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)), + }) + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/nef/decrypt.rs b/third_party/rawler-0.7.2/src/decoders/nef/decrypt.rs new file mode 100644 index 0000000..a1e0cd5 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/nef/decrypt.rs @@ -0,0 +1,65 @@ +use 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, +]; diff --git a/third_party/rawler-0.7.2/src/decoders/nef/lensdata.rs b/third_party/rawler-0.7.2/src/decoders/nef/lensdata.rs new file mode 100644 index 0000000..bd1121e --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/nef/lensdata.rs @@ -0,0 +1,283 @@ +use 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, Debug)] +#[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, Debug)] +#[allow(dead_code)] +pub struct NefLensDataZ { + version: u32, + pub lens_id: u16, +} + +#[derive(Clone, Debug)] +#[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}, lensdata: {:?}", version, lensdata); + + 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[48..].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, +} diff --git a/third_party/rawler-0.7.2/src/decoders/nkd.rs b/third_party/rawler-0.7.2/src/decoders/nkd.rs new file mode 100644 index 0000000..5c3a9fa --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/nkd.rs @@ -0,0 +1,57 @@ +use 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 + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/nrw.rs b/third_party/rawler-0.7.2/src/decoders/nrw.rs new file mode 100644 index 0000000..e1167ff --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/nrw.rs @@ -0,0 +1,3 @@ +/// 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>; diff --git a/third_party/rawler-0.7.2/src/decoders/orf.rs b/third_party/rawler-0.7.2/src/decoders/orf.rs new file mode 100644 index 0000000..6fb4b4b --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/orf.rs @@ -0,0 +1,491 @@ +use 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, +} diff --git a/third_party/rawler-0.7.2/src/decoders/pef.rs b/third_party/rawler-0.7.2/src/decoders/pef.rs new file mode 100644 index 0000000..d4929f1 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/pef.rs @@ -0,0 +1,518 @@ +use 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, +} diff --git a/third_party/rawler-0.7.2/src/decoders/qtk.rs b/third_party/rawler-0.7.2/src/decoders/qtk.rs new file mode 100644 index 0000000..ff7bab9 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/qtk.rs @@ -0,0 +1,240 @@ +// 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) + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/raf.rs b/third_party/rawler-0.7.2/src/decoders/raf.rs new file mode 100644 index 0000000..6be8610 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/raf.rs @@ -0,0 +1,749 @@ +use 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 +} diff --git a/third_party/rawler-0.7.2/src/decoders/raf/dbp.rs b/third_party/rawler-0.7.2/src/decoders/raf/dbp.rs new file mode 100644 index 0000000..067a18e --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/raf/dbp.rs @@ -0,0 +1,30 @@ +/// +/// 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) +} diff --git a/third_party/rawler-0.7.2/src/decoders/raf/fuji_decompressor.rs b/third_party/rawler-0.7.2/src/decoders/raf/fuji_decompressor.rs new file mode 100644 index 0000000..15b58cf --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/raf/fuji_decompressor.rs @@ -0,0 +1,1104 @@ +/// +/// 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; diff --git a/third_party/rawler-0.7.2/src/decoders/rw2.rs b/third_party/rawler-0.7.2/src/decoders/rw2.rs new file mode 100644 index 0000000..4966edb --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/rw2.rs @@ -0,0 +1,447 @@ +use 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, +} diff --git a/third_party/rawler-0.7.2/src/decoders/rw2/v4decompressor.rs b/third_party/rawler-0.7.2/src/decoders/rw2/v4decompressor.rs new file mode 100644 index 0000000..64b8553 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/rw2/v4decompressor.rs @@ -0,0 +1,86 @@ +use 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; + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/rw2/v5decompressor.rs b/third_party/rawler-0.7.2/src/decoders/rw2/v5decompressor.rs new file mode 100644 index 0000000..6207ad8 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/rw2/v5decompressor.rs @@ -0,0 +1,50 @@ +/// 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); + } + }), + ) +} diff --git a/third_party/rawler-0.7.2/src/decoders/rw2/v6decompressor.rs b/third_party/rawler-0.7.2/src/decoders/rw2/v6decompressor.rs new file mode 100644 index 0000000..e6dcf07 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/rw2/v6decompressor.rs @@ -0,0 +1,189 @@ +/// 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; + } + } + */ + } + }), + ) +} diff --git a/third_party/rawler-0.7.2/src/decoders/rw2/v7decompressor.rs b/third_party/rawler-0.7.2/src/decoders/rw2/v7decompressor.rs new file mode 100644 index 0000000..0218bc7 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/rw2/v7decompressor.rs @@ -0,0 +1,36 @@ +/// 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); + } + }), + ) +} diff --git a/third_party/rawler-0.7.2/src/decoders/rw2/v8decompressor.rs b/third_party/rawler-0.7.2/src/decoders/rw2/v8decompressor.rs new file mode 100644 index 0000000..8c2df1b --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/rw2/v8decompressor.rs @@ -0,0 +1,495 @@ +// 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]; + } + } + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/srw.rs b/third_party/rawler-0.7.2/src/decoders/srw.rs new file mode 100644 index 0000000..d7bd9f4 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/srw.rs @@ -0,0 +1,523 @@ +use 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, +} diff --git a/third_party/rawler-0.7.2/src/decoders/tfr.rs b/third_party/rawler-0.7.2/src/decoders/tfr.rs new file mode 100644 index 0000000..661b851 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/tfr.rs @@ -0,0 +1,177 @@ +use 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) + } +} diff --git a/third_party/rawler-0.7.2/src/decoders/unwrapped.rs b/third_party/rawler-0.7.2/src/decoders/unwrapped.rs new file mode 100644 index 0000000..df35b2e --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/unwrapped.rs @@ -0,0 +1,191 @@ +use 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(), + )) +} diff --git a/third_party/rawler-0.7.2/src/decoders/x3f.rs b/third_party/rawler-0.7.2/src/decoders/x3f.rs new file mode 100644 index 0000000..b2c68a2 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decoders/x3f.rs @@ -0,0 +1,158 @@ +use 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()) + } +} diff --git a/third_party/rawler-0.7.2/src/decompressors/crx/decoder.rs b/third_party/rawler-0.7.2/src/decompressors/crx/decoder.rs new file mode 100644 index 0000000..b67d98d --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/crx/decoder.rs @@ -0,0 +1,757 @@ +// 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(()) +} diff --git a/third_party/rawler-0.7.2/src/decompressors/crx/idwt.rs b/third_party/rawler-0.7.2/src/decompressors/crx/idwt.rs new file mode 100644 index 0000000..a2ac6fb --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/crx/idwt.rs @@ -0,0 +1,570 @@ +// 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/decompressors/crx/iquant.rs b/third_party/rawler-0.7.2/src/decompressors/crx/iquant.rs new file mode 100644 index 0000000..8087051 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/crx/iquant.rs @@ -0,0 +1,308 @@ +// 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(()), + } + } +} diff --git a/third_party/rawler-0.7.2/src/decompressors/crx/mdat.rs b/third_party/rawler-0.7.2/src/decompressors/crx/mdat.rs new file mode 100644 index 0000000..67ae8b1 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/crx/mdat.rs @@ -0,0 +1,429 @@ +// 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) +} diff --git a/third_party/rawler-0.7.2/src/decompressors/crx/mod.rs b/third_party/rawler-0.7.2/src/decompressors/crx/mod.rs new file mode 100644 index 0000000..37419cd --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/crx/mod.rs @@ -0,0 +1,422 @@ +// 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) +} diff --git a/third_party/rawler-0.7.2/src/decompressors/crx/rice.rs b/third_party/rawler-0.7.2/src/decompressors/crx/rice.rs new file mode 100644 index 0000000..b346790 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/crx/rice.rs @@ -0,0 +1,108 @@ +// 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 } + } +} diff --git a/third_party/rawler-0.7.2/src/decompressors/crx/runlength.rs b/third_party/rawler-0.7.2/src/decompressors/crx/runlength.rs new file mode 100644 index 0000000..ddd9b03 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/crx/runlength.rs @@ -0,0 +1,59 @@ +// 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) + } +} diff --git a/third_party/rawler-0.7.2/src/decompressors/deflate.rs b/third_party/rawler-0.7.2/src/decompressors/deflate.rs new file mode 100644 index 0000000..45b1973 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/deflate.rs @@ -0,0 +1,78 @@ +use 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) + } +} diff --git a/third_party/rawler-0.7.2/src/decompressors/jpeg.rs b/third_party/rawler-0.7.2/src/decompressors/jpeg.rs new file mode 100644 index 0000000..e44b326 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/jpeg.rs @@ -0,0 +1,59 @@ +use 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 + } +} diff --git a/third_party/rawler-0.7.2/src/decompressors/jpegxl.rs b/third_party/rawler-0.7.2/src/decompressors/jpegxl.rs new file mode 100644 index 0000000..0326d98 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/jpegxl.rs @@ -0,0 +1,81 @@ +// 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/decompressors/ljpeg/decompressors.rs b/third_party/rawler-0.7.2/src/decompressors/ljpeg/decompressors.rs new file mode 100644 index 0000000..5f9ea4c --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/ljpeg/decompressors.rs @@ -0,0 +1,360 @@ +use 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(()) +} diff --git a/third_party/rawler-0.7.2/src/decompressors/ljpeg/huffman.rs b/third_party/rawler-0.7.2/src/decompressors/ljpeg/huffman.rs new file mode 100644 index 0000000..17b35fc --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/ljpeg/huffman.rs @@ -0,0 +1,244 @@ +use 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 }}") + } + } +} diff --git a/third_party/rawler-0.7.2/src/decompressors/ljpeg/mod.rs b/third_party/rawler-0.7.2/src/decompressors/ljpeg/mod.rs new file mode 100644 index 0000000..1c93b55 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/ljpeg/mod.rs @@ -0,0 +1,367 @@ +use 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 < 10 { + 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() + } +} diff --git a/third_party/rawler-0.7.2/src/decompressors/mod.rs b/third_party/rawler-0.7.2/src/decompressors/mod.rs new file mode 100644 index 0000000..0a4b4ac --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/mod.rs @@ -0,0 +1,83 @@ +// 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 + } +} diff --git a/third_party/rawler-0.7.2/src/decompressors/packed.rs b/third_party/rawler-0.7.2/src/decompressors/packed.rs new file mode 100644 index 0000000..a094d8b --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/packed.rs @@ -0,0 +1,219 @@ +use 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, line_width, 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, width: usize, bits: u32) { + assert!(bits <= 16); + let skip_bits = skip_rows * width * bits as usize; + let offset = skip_bits / 8; + let bias = skip_bits % 8; + let mut pump = BitPumpMSB::new(&src[offset..]); + pump.consume_bits(bias as u32); + 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); + } + } +} diff --git a/third_party/rawler-0.7.2/src/decompressors/radc.rs b/third_party/rawler-0.7.2/src/decompressors/radc.rs new file mode 100644 index 0000000..666fe34 --- /dev/null +++ b/third_party/rawler-0.7.2/src/decompressors/radc.rs @@ -0,0 +1,225 @@ +// 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) +} diff --git a/third_party/rawler-0.7.2/src/devtools/inspector.rs b/third_party/rawler-0.7.2/src/devtools/inspector.rs new file mode 100644 index 0000000..64adaff --- /dev/null +++ b/third_party/rawler-0.7.2/src/devtools/inspector.rs @@ -0,0 +1,13 @@ +// 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 ),*) => {}; +} diff --git a/third_party/rawler-0.7.2/src/devtools/mod.rs b/third_party/rawler-0.7.2/src/devtools/mod.rs new file mode 100644 index 0000000..d0ec430 --- /dev/null +++ b/third_party/rawler-0.7.2/src/devtools/mod.rs @@ -0,0 +1,41 @@ +// 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"); +} diff --git a/third_party/rawler-0.7.2/src/dng/convert.rs b/third_party/rawler-0.7.2/src/dng/convert.rs new file mode 100644 index 0000000..d090bbd --- /dev/null +++ b/third_party/rawler-0.7.2/src/dng/convert.rs @@ -0,0 +1,231 @@ +use std::{ + ffi::OsStr, + io::{Cursor, Seek, Write}, + path::Path, + sync::Arc, + thread::JoinHandle, +}; + +use image::DynamicImage; + +use crate::{ + RawImage, RawlerError, + 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 { + let image = 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)?; + image + .to_dynamic_image() + .ok_or_else(|| RawlerError::DecoderFailed("Failed to generate preview image".to_string())) + } + }?; + log::debug!("Using preview image with source dimension {}x{}", image.width(), image.height()); + Ok(image) +} diff --git a/third_party/rawler-0.7.2/src/dng/mod.rs b/third_party/rawler-0.7.2/src/dng/mod.rs new file mode 100644 index 0000000..1a39c83 --- /dev/null +++ b/third_party/rawler-0.7.2/src/dng/mod.rs @@ -0,0 +1,114 @@ +// 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 +} diff --git a/third_party/rawler-0.7.2/src/dng/original.rs b/third_party/rawler-0.7.2/src/dng/original.rs new file mode 100644 index 0000000..4e40ee5 --- /dev/null +++ b/third_party/rawler-0.7.2/src/dng/original.rs @@ -0,0 +1,246 @@ +// 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/dng/writer.rs b/third_party/rawler-0.7.2/src/dng/writer.rs new file mode 100644 index 0000000..b7ecceb --- /dev/null +++ b/third_party/rawler-0.7.2/src/dng/writer.rs @@ -0,0 +1,784 @@ +use 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, + envparams::{rawler_dng_multistrip_threshold, rawler_dng_rows_per_strip}, + 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 = if img.width() > 1024 { + DynamicImage::ImageRgb8(img.resize(1024, 768, FilterType::Nearest).to_rgb8()) + } else { + DynamicImage::ImageRgb8(img.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 > rawler_dng_multistrip_threshold().unwrap_or(100) { + rawler_dng_rows_per_strip().unwrap_or(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()?; + #[cfg(target_endian = "little")] + 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, + ]; + #[cfg(not(target_endian = "little"))] + let expected_output = [ + 77, 77, 0, 42, 0, 0, 0, 36, 0, 1, 144, 0, 0, 7, 0, 0, 0, 4, 48, 50, 50, 48, 0, 0, 0, 0, 0, 0, 84, 101, 115, 116, 0, 0, 0, 0, 0, 4, 1, 59, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 28, 135, 105, 0, 4, 0, 0, 0, 1, 0, 0, 0, 8, 198, 18, 0, 1, 0, 0, 0, 4, 0, 0, 6, 1, 198, 19, 0, 1, 0, 0, 0, 4, 0, 0, 4, 1, 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/envparams.rs b/third_party/rawler-0.7.2/src/envparams.rs new file mode 100644 index 0000000..8416b67 --- /dev/null +++ b/third_party/rawler-0.7.2/src/envparams.rs @@ -0,0 +1,48 @@ +// 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, + } +} + +pub(crate) fn rawler_dng_rows_per_strip() -> Option { + match std::env::var("RAWLER_DNG_ROWS_PER_STRIP").map(|val| val.parse::()) { + Ok(Ok(value)) => Some(value), + Ok(Err(_)) => { + warn!("Invalid value for RAWLER_DNG_ROWS_PER_STRIP"); + None + } + Err(_) => None, + } +} + +pub(crate) fn rawler_dng_multistrip_threshold() -> Option { + match std::env::var("RAWLER_DNG_MULTISTRIP_THRESHOLD").map(|val| val.parse::()) { + Ok(Ok(value)) => Some(value), + Ok(Err(_)) => { + warn!("Invalid value for RAWLER_DNG_MULTISTRIP_THRESHOLD"); + None + } + Err(_) => None, + } +} diff --git a/third_party/rawler-0.7.2/src/exif.rs b/third_party/rawler-0.7.2/src/exif.rs new file mode 100644 index 0000000..6e0e2ce --- /dev/null +++ b/third_party/rawler-0.7.2/src/exif.rs @@ -0,0 +1,234 @@ +use 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()); + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/co64.rs b/third_party/rawler-0.7.2/src/formats/bmff/co64.rs new file mode 100644 index 0000000..60a33c4 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/co64.rs @@ -0,0 +1,43 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/dinf.rs b/third_party/rawler-0.7.2/src/formats/bmff/dinf.rs new file mode 100644 index 0000000..0b4e5e5 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/dinf.rs @@ -0,0 +1,24 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/ccdt.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/ccdt.rs new file mode 100644 index 0000000..1c0871e --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/ccdt.rs @@ -0,0 +1,36 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cctp.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cctp.rs new file mode 100644 index 0000000..b734ebe --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cctp.rs @@ -0,0 +1,69 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cdi1.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cdi1.rs new file mode 100644 index 0000000..2080e16 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cdi1.rs @@ -0,0 +1,60 @@ +// 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()))?, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmp1.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmp1.rs new file mode 100644 index 0000000..8e3f216 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmp1.rs @@ -0,0 +1,114 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmt1.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmt1.rs new file mode 100644 index 0000000..4aa7c55 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmt1.rs @@ -0,0 +1,34 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmt2.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmt2.rs new file mode 100644 index 0000000..398b535 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmt2.rs @@ -0,0 +1,34 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmt3.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmt3.rs new file mode 100644 index 0000000..66e7ff9 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmt3.rs @@ -0,0 +1,34 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmt4.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmt4.rs new file mode 100644 index 0000000..1afbf1a --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cmt4.rs @@ -0,0 +1,34 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cncv.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cncv.rs new file mode 100644 index 0000000..d918889 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cncv.rs @@ -0,0 +1,33 @@ +// 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(), + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cnop.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cnop.rs new file mode 100644 index 0000000..efe0470 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cnop.rs @@ -0,0 +1,29 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cr3desc.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cr3desc.rs new file mode 100644 index 0000000..746863f --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cr3desc.rs @@ -0,0 +1,111 @@ +// 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()))?, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cr3xpacket.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cr3xpacket.rs new file mode 100644 index 0000000..59741e1 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/cr3xpacket.rs @@ -0,0 +1,24 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/craw.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/craw.rs new file mode 100644 index 0000000..6c8d58c --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/craw.rs @@ -0,0 +1,135 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/ctbo.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/ctbo.rs new file mode 100644 index 0000000..a5c281e --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/ctbo.rs @@ -0,0 +1,25 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/ctmd.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/ctmd.rs new file mode 100644 index 0000000..7c87781 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/ctmd.rs @@ -0,0 +1,76 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/hevc.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/hevc.rs new file mode 100644 index 0000000..a8a4c60 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/hevc.rs @@ -0,0 +1,23 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/iad1.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/iad1.rs new file mode 100644 index 0000000..9fb6dfe --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/iad1.rs @@ -0,0 +1,125 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/jpeg.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/jpeg.rs new file mode 100644 index 0000000..6791e8a --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/jpeg.rs @@ -0,0 +1,27 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/mod.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/mod.rs new file mode 100644 index 0000000..ab26fa0 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/mod.rs @@ -0,0 +1,22 @@ +// 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; diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/thmb.rs b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/thmb.rs new file mode 100644 index 0000000..7af39bc --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ext_cr3/thmb.rs @@ -0,0 +1,25 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/free.rs b/third_party/rawler-0.7.2/src/formats/bmff/free.rs new file mode 100644 index 0000000..e0387c0 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/free.rs @@ -0,0 +1,24 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/ftyp.rs b/third_party/rawler-0.7.2/src/formats/bmff/ftyp.rs new file mode 100644 index 0000000..c0d6543 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/ftyp.rs @@ -0,0 +1,46 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/hdlr.rs b/third_party/rawler-0.7.2/src/formats/bmff/hdlr.rs new file mode 100644 index 0000000..bf781c8 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/hdlr.rs @@ -0,0 +1,30 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/mdat.rs b/third_party/rawler-0.7.2/src/formats/bmff/mdat.rs new file mode 100644 index 0000000..7727302 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/mdat.rs @@ -0,0 +1,24 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/mdhd.rs b/third_party/rawler-0.7.2/src/formats/bmff/mdhd.rs new file mode 100644 index 0000000..33e1468 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/mdhd.rs @@ -0,0 +1,63 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/mdia.rs b/third_party/rawler-0.7.2/src/formats/bmff/mdia.rs new file mode 100644 index 0000000..4005027 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/mdia.rs @@ -0,0 +1,71 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/minf.rs b/third_party/rawler-0.7.2/src/formats/bmff/minf.rs new file mode 100644 index 0000000..3beacaf --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/minf.rs @@ -0,0 +1,72 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/mod.rs b/third_party/rawler-0.7.2/src/formats/bmff/mod.rs new file mode 100644 index 0000000..dd1b2ce --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/mod.rs @@ -0,0 +1,327 @@ +// 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 + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/moov.rs b/third_party/rawler-0.7.2/src/formats/bmff/moov.rs new file mode 100644 index 0000000..91a0d93 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/moov.rs @@ -0,0 +1,82 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/mvhd.rs b/third_party/rawler-0.7.2/src/formats/bmff/mvhd.rs new file mode 100644 index 0000000..1de61d5 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/mvhd.rs @@ -0,0 +1,62 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/skip.rs b/third_party/rawler-0.7.2/src/formats/bmff/skip.rs new file mode 100644 index 0000000..92edf64 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/skip.rs @@ -0,0 +1,24 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/stbl.rs b/third_party/rawler-0.7.2/src/formats/bmff/stbl.rs new file mode 100644 index 0000000..7fe44c3 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/stbl.rs @@ -0,0 +1,111 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/stsc.rs b/third_party/rawler-0.7.2/src/formats/bmff/stsc.rs new file mode 100644 index 0000000..47a66fc --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/stsc.rs @@ -0,0 +1,82 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/stsd.rs b/third_party/rawler-0.7.2/src/formats/bmff/stsd.rs new file mode 100644 index 0000000..209296a --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/stsd.rs @@ -0,0 +1,80 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/stsz.rs b/third_party/rawler-0.7.2/src/formats/bmff/stsz.rs new file mode 100644 index 0000000..82e191f --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/stsz.rs @@ -0,0 +1,60 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/stts.rs b/third_party/rawler-0.7.2/src/formats/bmff/stts.rs new file mode 100644 index 0000000..c3bcbb8 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/stts.rs @@ -0,0 +1,51 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/tkhd.rs b/third_party/rawler-0.7.2/src/formats/bmff/tkhd.rs new file mode 100644 index 0000000..1126783 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/tkhd.rs @@ -0,0 +1,30 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/trak.rs b/third_party/rawler-0.7.2/src/formats/bmff/trak.rs new file mode 100644 index 0000000..a33e2c3 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/trak.rs @@ -0,0 +1,68 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/vendor.rs b/third_party/rawler-0.7.2/src/formats/bmff/vendor.rs new file mode 100644 index 0000000..7b143f6 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/vendor.rs @@ -0,0 +1,19 @@ +// 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 }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/bmff/vmhd.rs b/third_party/rawler-0.7.2/src/formats/bmff/vmhd.rs new file mode 100644 index 0000000..dee7940 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/bmff/vmhd.rs @@ -0,0 +1,51 @@ +// 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, + }) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/ciff/mod.rs b/third_party/rawler-0.7.2/src/formats/ciff/mod.rs new file mode 100644 index 0000000..cb61299 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/ciff/mod.rs @@ -0,0 +1,163 @@ +use 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) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/jfif.rs b/third_party/rawler-0.7.2/src/formats/jfif.rs new file mode 100644 index 0000000..05f8964 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/jfif.rs @@ -0,0 +1,322 @@ +use 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 + } + } +} diff --git a/third_party/rawler-0.7.2/src/formats/mod.rs b/third_party/rawler-0.7.2/src/formats/mod.rs new file mode 100644 index 0000000..3b373a4 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/mod.rs @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: LGPL-2.1 +// Copyright 2021 Daniel Vogelbacher + +pub mod bmff; +pub mod ciff; +pub mod jfif; +pub mod tiff; diff --git a/third_party/rawler-0.7.2/src/formats/tiff/entry.rs b/third_party/rawler-0.7.2/src/formats/tiff/entry.rs new file mode 100644 index 0000000..6d32e95 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/tiff/entry.rs @@ -0,0 +1,245 @@ +// 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() + } +} diff --git a/third_party/rawler-0.7.2/src/formats/tiff/file.rs b/third_party/rawler-0.7.2/src/formats/tiff/file.rs new file mode 100644 index 0000000..157ae97 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/tiff/file.rs @@ -0,0 +1,26 @@ +// 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); + } +} diff --git a/third_party/rawler-0.7.2/src/formats/tiff/ifd.rs b/third_party/rawler-0.7.2/src/formats/tiff/ifd.rs new file mode 100644 index 0000000..8f9343b --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/tiff/ifd.rs @@ -0,0 +1,679 @@ +// 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}, +}; + +const MAX_IFD_ENTRIES: usize = 4096; + +#[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()?; + + if entry_count as usize > MAX_IFD_ENTRIES { + log::warn!( + "TIFF: IFD entry count {} is suspicious (limit {}). The file might be corrupt.", + entry_count, + MAX_IFD_ENTRIES + ); + } + + let mut entries = BTreeMap::new(); + let mut sub = HashMap::new(); + let mut next_pos = reader.position()?; + debug!("Parse entries"); + let mut consecutive_errors = 0; + + for i in 0..entry_count { + if i as usize >= MAX_IFD_ENTRIES { + log::warn!( + "TIFF: Reached maximum IFD entry limit ({}). Stopping parse to prevent infinite loops.", + MAX_IFD_ENTRIES + ); + break; + } + + if let Err(e) = reader.goto(next_pos) { + log::warn!("Truncated IFD: Could not seek to next entry position. Stopping parse. Error: {}", e); + break; + } + + next_pos += 12; + + let tag = match reader.read_u16() { + Ok(t) => t, + Err(e) => { + log::warn!("Truncated IFD: Could not read tag ID (Index {}). Stopping parse. Error: {}", i, e); + break; + } + }; + + match Entry::parse(&mut reader, base, corr, tag) { + Ok(entry) => { + consecutive_errors = 0; + + if sub_tags.contains(&tag) { + match &entry.value { + Value::Long(offsets) => { + sub_ifd_offsets.insert(tag, offsets.clone()); + } + Value::Unknown(tag, offsets) => { + sub_ifd_offsets.insert(*tag, vec![offsets[0] as u32]); + } + 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) => { + consecutive_errors += 1; + log::warn!("Failed to parse TIFF tag 0x{:X} (Index {}). Error: {:?}", tag, i, err); + + // If we fail 5 times in a row, the IFD is likely garbage or physically truncated. + if consecutive_errors >= 5 { + log::warn!("Too many consecutive parsing errors ({}). Stopping parse to prevent flood.", consecutive_errors); + break; + } + } + } + } + + // 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 get_new_sub_file_type(&self) -> Option { + if let Some(entry) = self.get_entry(TiffCommonTag::NewSubFileType) { + Some(entry.force_u16(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 + } +} diff --git a/third_party/rawler-0.7.2/src/formats/tiff/mod.rs b/third_party/rawler-0.7.2/src/formats/tiff/mod.rs new file mode 100644 index 0000000..4b5a3c5 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/tiff/mod.rs @@ -0,0 +1,375 @@ +// 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/formats/tiff/reader.rs b/third_party/rawler-0.7.2/src/formats/tiff/reader.rs new file mode 100644 index 0000000..9b77505 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/tiff/reader.rs @@ -0,0 +1,429 @@ +// 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_ifds_with_filter bool>(&self, filter: F) -> Vec<&IFD> { + let mut ifds = Vec::new(); + for ifd in &self.file().chain { + if filter(ifd) { + ifds.push(ifd); + } + // Now search in all sub IFDs + for subs in ifd.sub_ifds() { + for ifd in subs.1 { + if filter(ifd) { + 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), + } + } +} diff --git a/third_party/rawler-0.7.2/src/formats/tiff/value.rs b/third_party/rawler-0.7.2/src/formats/tiff/value.rs new file mode 100644 index 0000000..fcf723c --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/tiff/value.rs @@ -0,0 +1,1357 @@ +// 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); + } +} diff --git a/third_party/rawler-0.7.2/src/formats/tiff/writer.rs b/third_party/rawler-0.7.2/src/formats/tiff/writer.rs new file mode 100644 index 0000000..2d738a7 --- /dev/null +++ b/third_party/rawler-0.7.2/src/formats/tiff/writer.rs @@ -0,0 +1,412 @@ +// 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(()) +} diff --git a/third_party/rawler-0.7.2/src/imgop/chromatic_adaption.rs b/third_party/rawler-0.7.2/src/imgop/chromatic_adaption.rs new file mode 100644 index 0000000..79b71b5 --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/chromatic_adaption.rs @@ -0,0 +1,105 @@ +// 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/imgop/develop.rs b/third_party/rawler-0.7.2/src/imgop/develop.rs new file mode 100644 index 0000000..a6a7677 --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/develop.rs @@ -0,0 +1,317 @@ +use 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 found_matrix = rawimage + .color_matrix + .iter() + .find(|(illuminant, _m)| **illuminant == Illuminant::D65) + .or_else(|| rawimage.color_matrix.iter().next()); + + if let Some((_illuminant, color_matrix)) = found_matrix { + // Safety check: ensure matrix is valid length + if color_matrix.len() % 3 == 0 { + let mut xyz2cam: [[f32; 3]; 4] = [[0.0; 3]; 4]; + 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 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)), + }; + } else { + log::warn!("Color matrix found but has invalid length. Skipping calibration."); + } + } else { + log::warn!("Illuminant matrix D65 not found and no fallback available. Skipping calibration."); + } + } + + 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/imgop/gamma.rs b/third_party/rawler-0.7.2/src/imgop/gamma.rs new file mode 100644 index 0000000..82bd2e9 --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/gamma.rs @@ -0,0 +1,10 @@ +// 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) +} diff --git a/third_party/rawler-0.7.2/src/imgop/matrix.rs b/third_party/rawler-0.7.2/src/imgop/matrix.rs new file mode 100644 index 0000000..273f806 --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/matrix.rs @@ -0,0 +1,129 @@ +// 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/imgop/mod.rs b/third_party/rawler-0.7.2/src/imgop/mod.rs new file mode 100644 index 0000000..30348fb --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/mod.rs @@ -0,0 +1,328 @@ +// 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/imgop/raw.rs b/third_party/rawler-0.7.2/src/imgop/raw.rs new file mode 100644 index 0000000..f5f2234 --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/raw.rs @@ -0,0 +1,275 @@ +// 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; + } + } +} diff --git a/third_party/rawler-0.7.2/src/imgop/sensor/bayer/bilinear.rs b/third_party/rawler-0.7.2/src/imgop/sensor/bayer/bilinear.rs new file mode 100644 index 0000000..7dc601a --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/sensor/bayer/bilinear.rs @@ -0,0 +1,113 @@ +use 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 + } +} diff --git a/third_party/rawler-0.7.2/src/imgop/sensor/bayer/mod.rs b/third_party/rawler-0.7.2/src/imgop/sensor/bayer/mod.rs new file mode 100644 index 0000000..58b582e --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/sensor/bayer/mod.rs @@ -0,0 +1,49 @@ +// 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)| { + 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, +} diff --git a/third_party/rawler-0.7.2/src/imgop/sensor/bayer/ppg.rs b/third_party/rawler-0.7.2/src/imgop/sensor/bayer/ppg.rs new file mode 100644 index 0000000..4428ffb --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/sensor/bayer/ppg.rs @@ -0,0 +1,263 @@ +// 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 + } +} diff --git a/third_party/rawler-0.7.2/src/imgop/sensor/bayer/superpixel.rs b/third_party/rawler-0.7.2/src/imgop/sensor/bayer/superpixel.rs new file mode 100644 index 0000000..3ab8756 --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/sensor/bayer/superpixel.rs @@ -0,0 +1,131 @@ +// 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) + } +} diff --git a/third_party/rawler-0.7.2/src/imgop/sensor/mod.rs b/third_party/rawler-0.7.2/src/imgop/sensor/mod.rs new file mode 100644 index 0000000..a45e6b8 --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/sensor/mod.rs @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: LGPL-2.1 +// Copyright 2021 Daniel Vogelbacher + +pub mod bayer; +pub mod xtrans; diff --git a/third_party/rawler-0.7.2/src/imgop/sensor/xtrans/mod.rs b/third_party/rawler-0.7.2/src/imgop/sensor/xtrans/mod.rs new file mode 100644 index 0000000..7548a84 --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/sensor/xtrans/mod.rs @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: LGPL-2.1 +// Copyright 2021 Daniel Vogelbacher + +// This file is reserved for X-Trans specific sensor code. diff --git a/third_party/rawler-0.7.2/src/imgop/sensor/xtrans/xtrans_fast.rs b/third_party/rawler-0.7.2/src/imgop/sensor/xtrans/xtrans_fast.rs new file mode 100644 index 0000000..cc9e705 --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/sensor/xtrans/xtrans_fast.rs @@ -0,0 +1,85 @@ +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, sensor::Demosaic}, + pixarray::{Color2D, PixF32, RgbF32}, +}; + +#[derive(Default)] +pub struct XtransFastDemosaic {} + +impl XtransFastDemosaic { + 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 XtransFastDemosaic { + /// 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 xtrans", 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_xtrans_rgb(pixels.pixels(), pixels.dim(), cfa, roi); + + // Now interpolate the missing channels + interpolate_missing(&mut rgb, &cfa_roi); + + log::debug!("xtrans total debayer time: {:.5}s", now.elapsed().as_secs_f32()); + rgb + } +} + +#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))] +fn interpolate_missing(input: &mut RgbF32, shifted: &CFA) { + let w = input.width; + let h = input.height; + // Iterate over all rows + for row in 0..h { + for col in 0..w { + let mut tmp = *input.at(row, col); + for (i, p) in tmp.iter_mut().enumerate() { + if p.is_nan() { + if shifted.color_at(row.saturating_sub(1), col) == i { + *p = input.at(row.saturating_sub(1), col)[i]; + } + if shifted.color_at(row, col.saturating_sub(1)) == i { + *p = input.at(row, col.saturating_sub(1))[i]; + } + if shifted.color_at((h - 1).min(row + 1), col) == i { + *p = input.at((h - 1).min(row + 1), col)[i]; + } + if shifted.color_at(row, (w - 1).min(col + 1)) == i { + *p = input.at(row, (w - 1).min(col + 1))[i]; + } + } + } + *input.at_mut(row, col) = tmp; + } + } +} diff --git a/third_party/rawler-0.7.2/src/imgop/sensor/xtrans/xtrans_markenstein.rs b/third_party/rawler-0.7.2/src/imgop/sensor/xtrans/xtrans_markenstein.rs new file mode 100644 index 0000000..e69de29 diff --git a/third_party/rawler-0.7.2/src/imgop/spline.rs b/third_party/rawler-0.7.2/src/imgop/spline.rs new file mode 100644 index 0000000..6832bd0 --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/spline.rs @@ -0,0 +1,135 @@ +use 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/imgop/srgb.rs b/third_party/rawler-0.7.2/src/imgop/srgb.rs new file mode 100644 index 0000000..88a93ee --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/srgb.rs @@ -0,0 +1,61 @@ +// 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)); +} diff --git a/third_party/rawler-0.7.2/src/imgop/xyz.rs b/third_party/rawler-0.7.2/src/imgop/xyz.rs new file mode 100644 index 0000000..29ffbe1 --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/xyz.rs @@ -0,0 +1,213 @@ +// 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 +} diff --git a/third_party/rawler-0.7.2/src/imgop/yuv.rs b/third_party/rawler-0.7.2/src/imgop/yuv.rs new file mode 100644 index 0000000..58ce671 --- /dev/null +++ b/third_party/rawler-0.7.2/src/imgop/yuv.rs @@ -0,0 +1,71 @@ +// 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; + } + } + }); +} diff --git a/third_party/rawler-0.7.2/src/lens.rs b/third_party/rawler-0.7.2/src/lens.rs new file mode 100644 index 0000000..0912424 --- /dev/null +++ b/third_party/rawler-0.7.2/src/lens.rs @@ -0,0 +1,411 @@ +// 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::debug!("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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/lib.rs b/third_party/rawler-0.7.2/src/lib.rs new file mode 100644 index 0000000..d1b5b63 --- /dev/null +++ b/third_party/rawler-0.7.2/src/lib.rs @@ -0,0 +1,257 @@ +//! 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(); +} diff --git a/third_party/rawler-0.7.2/src/ljpeg92.rs b/third_party/rawler-0.7.2/src/ljpeg92.rs new file mode 100644 index 0000000..0a58e5c --- /dev/null +++ b/third_party/rawler-0.7.2/src/ljpeg92.rs @@ -0,0 +1,1475 @@ +// 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/packed.rs b/third_party/rawler-0.7.2/src/packed.rs new file mode 100644 index 0000000..fe556eb --- /dev/null +++ b/third_party/rawler-0.7.2/src/packed.rs @@ -0,0 +1,591 @@ +use 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 +} diff --git a/third_party/rawler-0.7.2/src/pixarray.rs b/third_party/rawler-0.7.2/src/pixarray.rs new file mode 100644 index 0000000..be9e18e --- /dev/null +++ b/third_party/rawler-0.7.2/src/pixarray.rs @@ -0,0 +1,579 @@ +use 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) + } + }}; +} diff --git a/third_party/rawler-0.7.2/src/pumps.rs b/third_party/rawler-0.7.2/src/pumps.rs new file mode 100644 index 0000000..07bb02f --- /dev/null +++ b/third_party/rawler-0.7.2/src/pumps.rs @@ -0,0 +1,484 @@ +use std::slice::Chunks; + +use crate::bits::*; + +#[derive(Debug, Clone)] +pub struct BitPumpLSB<'a> { + buffer: Chunks<'a, u8>, + bits: u64, + nbits: u32, +} + +impl<'a> BitPumpLSB<'a> { + pub fn new(src: &'a [u8]) -> Self { + Self { + buffer: src.chunks(size_of::()), + bits: 0, + nbits: 0, + } + } + + /// Refill internal bit buffer - Little-Endian + /// + /// For fast refill, we can simply take a whole u32 value out. + /// For slow refill, there may be 1, 2 or 3 bytes left in buffer. We need + /// to collect them manually. + fn refill(&mut self) -> (u32, u32) { + if let Some(chunk) = self.buffer.next() { + if chunk.len() == 4 { + // Fast refill + let bits: u32 = u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]); + (bits, u32::BITS) + } else { + // Slow refill + chunk + .into_iter() + .rev() + .fold((0, 0), |(bits, bit_cnt), x| ((bits << 8) | *x as u32, bit_cnt + 8)) + } + } else { + panic!("Can't refill bitpump, buffer exhausted"); + } + } +} + +#[derive(Debug, Clone)] +pub struct BitPumpMSB<'a> { + buffer: Chunks<'a, u8>, + bits: u64, + nbits: u32, +} + +impl<'a> BitPumpMSB<'a> { + pub fn new(src: &'a [u8]) -> Self { + Self { + buffer: src.chunks(size_of::()), + bits: 0, + nbits: 0, + } + } + + /// Refill internal bit buffer - Big-Endian + /// + /// For fast refill, we can simply take a whole u32 value out. + /// For slow refill, there may be 1, 2 or 3 bytes left in buffer. We need + /// to collect them manually. + fn refill(&mut self) -> (u32, u32) { + if let Some(chunk) = self.buffer.next() { + if chunk.len() == 4 { + // Fast refill + let bits: u32 = u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]); + (bits, u32::BITS) + } else { + // Slow refill + chunk.into_iter().fold((0, 0), |(bits, bit_cnt), x| ((bits << 8) | *x as u32, bit_cnt + 8)) + } + } else { + panic!("Can't refill bitpump, buffer exhausted"); + } + } +} + +#[derive(Debug, Clone)] +pub struct BitPumpMSB32<'a> { + buffer: Chunks<'a, u8>, + pos: usize, + bits: u64, + nbits: u32, +} + +impl<'a> BitPumpMSB32<'a> { + pub fn new(src: &'a [u8]) -> Self { + Self { + buffer: src.chunks(size_of::()), + pos: 0, + bits: 0, + nbits: 0, + } + } + + /// Refill internal bit buffer - Little-Endian + /// + /// For fast refill, we can simply take a whole u32 value out. + /// For slow refill, there may be 1, 2 or 3 bytes left in buffer. We need + /// to collect them manually. + fn refill(&mut self) -> (u32, u32) { + if let Some(chunk) = self.buffer.next() { + if chunk.len() == 4 { + // Fast refill + let bits: u32 = u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]); + (bits, u32::BITS) + } else { + // Slow refill + chunk + .into_iter() + .rev() + .fold((0, 0), |(bits, bit_cnt), x| ((bits << 8) | *x as u32, bit_cnt + 8)) + } + } else { + panic!("Can't refill bitpump, buffer exhausted"); + } + } + + #[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, bit_cnt) = self.refill(); + self.bits = (((inbits as u64) << 32) | (self.bits << (32 - self.nbits))) >> (32 - self.nbits); + self.nbits += bit_cnt; + } + (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, bit_cnt) = self.refill(); + self.bits = (self.bits << bit_cnt) | inbits as u64; + self.nbits += bit_cnt; + } + (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, bit_cnt) = self.refill(); + self.bits = (self.bits << 32) | inbits as u64; + self.nbits += bit_cnt; + self.pos += bit_cnt as usize / 8; + } + (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; + } +} diff --git a/third_party/rawler-0.7.2/src/rawimage.rs b/third_party/rawler-0.7.2/src/rawimage.rs new file mode 100644 index 0000000..343759c --- /dev/null +++ b/third_party/rawler-0.7.2/src/rawimage.rs @@ -0,0 +1,729 @@ +use 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(()) + } +} diff --git a/third_party/rawler-0.7.2/src/rawsource.rs b/third_party/rawler-0.7.2/src/rawsource.rs new file mode 100644 index 0000000..8e0d2ff --- /dev/null +++ b/third_party/rawler-0.7.2/src/rawsource.rs @@ -0,0 +1,146 @@ +use 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() + } +} diff --git a/third_party/rawler-0.7.2/src/tags.rs b/third_party/rawler-0.7.2/src/tags.rs new file mode 100644 index 0000000..889b8cb --- /dev/null +++ b/third_party/rawler-0.7.2/src/tags.rs @@ -0,0 +1,649 @@ +// 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, +} diff --git a/third_party/rawler-0.7.2/src/tiles.rs b/third_party/rawler-0.7.2/src/tiles.rs new file mode 100644 index 0000000..059cb5b --- /dev/null +++ b/third_party/rawler-0.7.2/src/tiles.rs @@ -0,0 +1,394 @@ +// 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); + } +} diff --git a/third_party/rawler-0.7.2/tests/cameras/mod.rs b/third_party/rawler-0.7.2/tests/cameras/mod.rs new file mode 100644 index 0000000..469a070 --- /dev/null +++ b/third_party/rawler-0.7.2/tests/cameras/mod.rs @@ -0,0 +1,3127 @@ +use 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_r6_mark_iii_raw_modes { + super::camera_file_check!("Canon", "EOS R6 Mark III", cam_r6m3_raw_iso_100_nodual_crop_cr3, "raw_modes/R6m3_RAW_ISO_100_nodual_crop.CR3"); + super::camera_file_check!("Canon", "EOS R6 Mark III", cam_r6m3_craw_iso_100_nodual_nocrop_cr3, "raw_modes/R6m3_CRAW_ISO_100_nodual_nocrop.CR3"); + super::camera_file_check!("Canon", "EOS R6 Mark III", cam_r6m3_raw_iso_100_nodual_nocrop_cr3, "raw_modes/R6m3_RAW_ISO_100_nodual_nocrop.CR3"); + super::camera_file_check!("Canon", "EOS R6 Mark III", cam_r6m3_craw_iso_100_nodual_crop_cr3, "raw_modes/R6m3_CRAW_ISO_100_nodual_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_nikon_coolscan_5000_ed_raw_modes { + super::camera_file_check!("Nikon", "Nikon COOLSCAN 5000 ED", cam_nikon_super_coolscan_5000_ed_nef, "raw_modes/nikon-super-coolscan-5000-ed.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_1m2_raw_modes { + super::camera_file_check!("Sony", "ILCE-1M2", cam_ilce_1m2_iso_100_14bits_lossless_arw, "raw_modes/ILCE-1M2_ISO_100_14bits_Lossless.ARW"); + super::camera_file_check!("Sony", "ILCE-1M2", cam_ilce_1m2_iso_100_14bits_small_lossless_arw, "raw_modes/ILCE-1M2_ISO_100_14bits_small_Lossless.ARW"); + super::camera_file_check!("Sony", "ILCE-1M2", cam_ilce_1m2_iso_100_14bits_medium_lossless_arw, "raw_modes/ILCE-1M2_ISO_100_14bits_medium_Lossless.ARW"); + super::camera_file_check!("Sony", "ILCE-1M2", cam_ilce_1m2_iso_100_14bits_lossy_arw, "raw_modes/ILCE-1M2_ISO_100_14bits_Lossy.ARW"); + super::camera_file_check!("Sony", "ILCE-1M2", cam_ilce_1m2_iso_100_14bits_crop_lossy_arw, "raw_modes/ILCE-1M2_ISO_100_14bits_Crop_Lossy.ARW"); + super::camera_file_check!("Sony", "ILCE-1M2", cam_ilce_1m2_iso_100_14bits_uncompressed_raw_arw, "raw_modes/ILCE-1M2_ISO_100_14bits_Uncompressed RAW.ARW"); + super::camera_file_check!("Sony", "ILCE-1M2", cam_ilce_1m2_iso_100_14bits_crop_medium_lossless_arw, "raw_modes/ILCE-1M2_ISO_100_14bits_Crop_medium_Lossless.ARW"); + super::camera_file_check!("Sony", "ILCE-1M2", cam_ilce_1m2_iso_100_14bits_crop_small_lossless_arw, "raw_modes/ILCE-1M2_ISO_100_14bits_Crop_small_Lossless.ARW"); + super::camera_file_check!("Sony", "ILCE-1M2", cam_ilce_1m2_iso_100_14bits_crop_uncompressed_raw_arw, "raw_modes/ILCE-1M2_ISO_100_14bits_Crop_Uncompressed 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_1m2_raw_modes { + super::camera_file_check!("Sony", "ZV-1M2", cam_sony_zv_1m2_12bit_3x2_arw, "raw_modes/Sony_ZV-1M2_12bit_3x2.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_nx5_raw_modes { + super::camera_file_check!("Samsung", "NX5", cam_samsung_nx5_srw, "raw_modes/Samsung_NX5.SRW"); +} +mod camera_nx10_raw_modes { + super::camera_file_check!("Samsung", "NX10", cam_samsung_nx10_srw, "raw_modes/Samsung_NX10.SRW"); +} +mod camera_nx11_raw_modes { + super::camera_file_check!("Samsung", "NX11", cam_samsung_nx11_srw, "raw_modes/Samsung_NX11.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_sp550uz_raw_modes { + super::camera_file_check!("Olympus", "SP550UZ", cam_olympus_sp550uz_12bit_4x3_orf, "raw_modes/Olympus_SP550UZ_12bit_4x3.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_s1m2es_raw_modes { + super::camera_file_check!("Panasonic", "DC-S1M2ES", cam_dc_s1m2es_3x2_rw2, "raw_modes/DC-S1M2ES_3x2.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_cl_raw_modes { + super::camera_file_check!("Leica", "CL", cam_leica_cl_14bit_uncompressed_3x2_dng, "raw_modes/Leica_CL_14bit_uncompressed_3x2.dng"); +} +mod camera_m10_raw_modes { + super::camera_file_check!("Leica", "M10", cam_leica_m10_16bi6_uncompressed_3x2_dng, "raw_modes/Leica_M10_16bi6_uncompressed_3x2.dng"); +} +mod camera_m10_r_raw_modes { + super::camera_file_check!("Leica", "M10-R", cam_leica_m10_r_16bit_compressed_3x2_dng, "raw_modes/Leica_M10-R_16bit_compressed_3x2.dng"); +} +mod camera_m8_raw_modes { + super::camera_file_check!("Leica", "M8", cam_leica_m8_8bit_uncompressed_3x2_dng, "raw_modes/Leica_M8_8bit_uncompressed_3x2.dng"); +} +mod camera_m9_raw_modes { + super::camera_file_check!("Leica", "M9", cam_leica_m9_16bit_uncompressed_dng, "raw_modes/Leica_M9_16bit_uncompressed.dng"); + super::camera_file_check!("Leica", "M9", cam_leica_m9_8bit_compressed_dng, "raw_modes/Leica_M9_8bit_compressed.dng"); +} +mod camera_m_monochrom_raw_modes { + super::camera_file_check!("Leica", "M Monochrom", cam_leica_m_monochrom_16bit_3x2_dng, "raw_modes/Leica_M_Monochrom_16bit_3x2.dng"); +} +mod camera_m_monochrom_typ_246_raw_modes { + super::camera_file_check!("Leica", "M Monochrom Typ 246", cam_leica_m_typ_246_monochrom_12bit_3x2_dng, "raw_modes/Leica_M_Typ_246_Monochrom_12bit_3x2.dng"); +} +mod camera_m_typ_240_raw_modes { + super::camera_file_check!("Leica", "M Typ 240", cam_leica_m_typ_240_16bit_uncompressed_3x2_dng, "raw_modes/Leica_M_Typ_240_16bit_uncompressed_3x2.dng"); + super::camera_file_check!("Leica", "M Typ 240", cam_leica_m_typ_240_16bit_compressed_3x2_dng, "raw_modes/Leica_M_Typ_240_16bit_compressed_3x2.dng"); +} +mod camera_q2_raw_modes { + super::camera_file_check!("Leica", "Q2", cam_leica_q2_14bit_uncompressed_3x2_dng, "raw_modes/Leica_Q2_14bit_uncompressed_3x2.dng"); +} +mod camera_q_typ_116_raw_modes { + super::camera_file_check!("Leica", "Q Typ 116", cam_leica_q_typ_116_14bit_3x2_dng, "raw_modes/Leica_Q_Typ_116_14bit_3x2.dng"); +} +mod camera_sl2_raw_modes { + super::camera_file_check!("Leica", "SL2", cam_leica_sl2_14bit_uncompressed_3x2_dng, "raw_modes/Leica_SL2_14bit_uncompressed_3x2.dng"); +} +mod camera_sl_typ_601_raw_modes { + super::camera_file_check!("Leica", "SL Typ 601", cam_leica_sl_typ_601_14bit_3x2_dng, "raw_modes/Leica_SL_Typ_601_14bit_3x2.dng"); +} +mod camera_x2_raw_modes { + super::camera_file_check!("Leica", "X2", cam_leica_x2_12bit_3x2_dng, "raw_modes/Leica_X2_12bit_3x2.dng"); +} +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"); +} diff --git a/third_party/rawler-0.7.2/tests/common/mod.rs b/third_party/rawler-0.7.2/tests/common/mod.rs new file mode 100644 index 0000000..7c639ab --- /dev/null +++ b/third_party/rawler-0.7.2/tests/common/mod.rs @@ -0,0 +1,175 @@ +// 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(()) +} diff --git a/third_party/rawler-0.7.2/tests/dng/mod.rs b/third_party/rawler-0.7.2/tests/dng/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/third_party/rawler-0.7.2/tests/dng/mod.rs @@ -0,0 +1 @@ + diff --git a/third_party/rawler-0.7.2/tests/issues/mod.rs b/third_party/rawler-0.7.2/tests/issues/mod.rs new file mode 100644 index 0000000..1258f90 --- /dev/null +++ b/third_party/rawler-0.7.2/tests/issues/mod.rs @@ -0,0 +1,70 @@ +use 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(()) +} + +#[test] +fn dnglab_619_silverfast_scan_missing_illuminant() -> std::result::Result<(), Box> { + let path = rawdb_file("issues/dnglab_619/silverfast_scan.dng"); + let mut dng = Cursor::new(Vec::new()); + convert_raw_file(&path, &mut dng, &ConvertParams::default())?; + Ok(()) +} diff --git a/third_party/rawler-0.7.2/tests/mod.rs b/third_party/rawler-0.7.2/tests/mod.rs new file mode 100644 index 0000000..d9d0be8 --- /dev/null +++ b/third_party/rawler-0.7.2/tests/mod.rs @@ -0,0 +1,10 @@ +#[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; diff --git a/third_party/rawler-0.7.2/tests/rustfmt.toml b/third_party/rawler-0.7.2/tests/rustfmt.toml new file mode 100644 index 0000000..0f1b482 --- /dev/null +++ b/third_party/rawler-0.7.2/tests/rustfmt.toml @@ -0,0 +1,15 @@ +#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 diff --git a/third_party/rawler-0.7.2/tests/samples/mod.rs b/third_party/rawler-0.7.2/tests/samples/mod.rs new file mode 100644 index 0000000..e3561f3 --- /dev/null +++ b/third_party/rawler-0.7.2/tests/samples/mod.rs @@ -0,0 +1,23 @@ +use 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"); +} diff --git a/third_party/rawler-0.7.2/tests/supported_rawdb_sets.txt b/third_party/rawler-0.7.2/tests/supported_rawdb_sets.txt new file mode 100644 index 0000000..b903011 --- /dev/null +++ b/third_party/rawler-0.7.2/tests/supported_rawdb_sets.txt @@ -0,0 +1,797 @@ +cameras/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 R6 Mark III/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/Nikon/Nikon COOLSCAN 5000 ED/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-1M2/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-1M2/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/NX5/raw_modes +cameras/Samsung/NX10/raw_modes +cameras/Samsung/NX11/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/SP550UZ/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-S1M2ES/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/Leica/CL/raw_modes +cameras/Leica/M10/raw_modes +cameras/Leica/M10-R/raw_modes +cameras/Leica/M8/raw_modes +cameras/Leica/M9/raw_modes +cameras/Leica/M Monochrom/raw_modes +cameras/Leica/M Monochrom Typ 246/raw_modes +cameras/Leica/M Typ 240/raw_modes +cameras/Leica/Q2/raw_modes +cameras/Leica/Q Typ 116/raw_modes +cameras/Leica/SL2/raw_modes +cameras/Leica/SL Typ 601/raw_modes +cameras/Leica/X2/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 diff --git a/third_party/rawler-0.7.2/tests/supported_sample_sets.txt b/third_party/rawler-0.7.2/tests/supported_sample_sets.txt new file mode 100644 index 0000000..d405f67 --- /dev/null +++ b/third_party/rawler-0.7.2/tests/supported_sample_sets.txt @@ -0,0 +1 @@ +samples/dng-compression-variants