[f-spot] Add libfspotraw, a simple GObject LibRaw wrapper.



commit 9a042510b4d111ed61446008de10c31b5d44985e
Author: Ruben Vermeersch <ruben savanne be>
Date:   Wed Jul 15 13:34:08 2009 +0200

    Add libfspotraw, a simple GObject LibRaw wrapper.

 Makefile.am                                        |    2 +
 configure.ac                                       |    2 +
 libfspotraw/.gitignore                             |    8 +
 libfspotraw/LibRaw/COPYRIGHT                       |  358 +
 libfspotraw/LibRaw/Changelog.rus                   |  538 ++
 libfspotraw/LibRaw/Changelog.txt                   |  431 +
 libfspotraw/LibRaw/Makefile                        |  106 +
 libfspotraw/LibRaw/Makefile.mingw                  |   83 +
 libfspotraw/LibRaw/Makefile.msvc                   |   93 +
 libfspotraw/LibRaw/bin/.keep_me                    |    2 +
 libfspotraw/LibRaw/dcraw/dcraw.c                   | 8713 ++++++++++++++++++++
 libfspotraw/LibRaw/doc/API-C-eng.html              |  200 +
 libfspotraw/LibRaw/doc/API-C-rus.html              |  197 +
 libfspotraw/LibRaw/doc/API-CXX-eng.html            |  811 ++
 libfspotraw/LibRaw/doc/API-CXX-rus.html            |  810 ++
 libfspotraw/LibRaw/doc/API-datastruct-eng.html     | 1067 +++
 libfspotraw/LibRaw/doc/API-datastruct-rus.html     | 1099 +++
 libfspotraw/LibRaw/doc/API-notes-eng.html          |  443 +
 libfspotraw/LibRaw/doc/API-notes-rus.html          |  469 ++
 libfspotraw/LibRaw/doc/API-overview-eng.html       |   70 +
 libfspotraw/LibRaw/doc/API-overview-rus.html       |   70 +
 libfspotraw/LibRaw/doc/Install-LibRaw-eng.html     |  133 +
 libfspotraw/LibRaw/doc/Install-LibRaw-rus.html     |  139 +
 libfspotraw/LibRaw/doc/Samples-LibRaw-eng.html     |  190 +
 libfspotraw/LibRaw/doc/Samples-LibRaw-rus.html     |  186 +
 libfspotraw/LibRaw/doc/Why-LibRaw-eng.html         |  230 +
 libfspotraw/LibRaw/doc/Why-LibRaw-rus.html         |  223 +
 libfspotraw/LibRaw/doc/corner-scheme.png           |  Bin 0 -> 6351 bytes
 libfspotraw/LibRaw/doc/index-eng.html              |   54 +
 libfspotraw/LibRaw/doc/index-rus.html              |   56 +
 libfspotraw/LibRaw/doc/index.html                  |   20 +
 libfspotraw/LibRaw/internal/dcraw_common.cpp       | 8383 +++++++++++++++++++
 libfspotraw/LibRaw/internal/dcraw_fileio.cpp       |  211 +
 libfspotraw/LibRaw/internal/defines.h              |  131 +
 libfspotraw/LibRaw/internal/foveon.cpp             |  812 ++
 .../LibRaw/internal/libraw_internal_funcs.h        |  197 +
 libfspotraw/LibRaw/internal/var_defines.h          |  182 +
 libfspotraw/LibRaw/lib/Makefile                    |    3 +
 libfspotraw/LibRaw/libraw/libraw.h                 |  219 +
 libfspotraw/LibRaw/libraw/libraw_alloc.h           |   97 +
 libfspotraw/LibRaw/libraw/libraw_const.h           |  160 +
 libfspotraw/LibRaw/libraw/libraw_datastream.h      |  301 +
 libfspotraw/LibRaw/libraw/libraw_internal.h        |  237 +
 libfspotraw/LibRaw/libraw/libraw_types.h           |  277 +
 libfspotraw/LibRaw/libraw/libraw_version.h         |   47 +
 libfspotraw/LibRaw/samples/4channels.cpp           |  190 +
 libfspotraw/LibRaw/samples/Makefile                |    2 +
 libfspotraw/LibRaw/samples/README-samples.rus      |    3 +
 libfspotraw/LibRaw/samples/dcraw_emu.cpp           |  282 +
 libfspotraw/LibRaw/samples/dcraw_half.c            |   83 +
 libfspotraw/LibRaw/samples/half_mt.c               |  173 +
 libfspotraw/LibRaw/samples/half_mt_win32.c         |  212 +
 libfspotraw/LibRaw/samples/mem_image.cpp           |  199 +
 libfspotraw/LibRaw/samples/raw-identify.cpp        |  147 +
 libfspotraw/LibRaw/samples/simple_dcraw.cpp        |  213 +
 libfspotraw/LibRaw/samples/unprocessed_raw.cpp     |  158 +
 libfspotraw/LibRaw/src/Makefile                    |    2 +
 libfspotraw/LibRaw/src/libraw_c_api.cpp            |  143 +
 libfspotraw/LibRaw/src/libraw_cxx.cpp              | 1970 +++++
 libfspotraw/Makefile.am                            |   38 +
 libfspotraw/fspot-librawloader.cpp                 |  211 +
 libfspotraw/fspot-librawloader.h                   |   56 +
 62 files changed, 32142 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index de468f3..e3a2399 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,6 +11,7 @@ SUBDIRS = 		\
 	icons		\
 	libjpegtran	\
 	libfspot	\
+	libfspotraw	\
 	libgphoto2-sharp \
 	Tao		\
 	mono-addins	\
@@ -34,6 +35,7 @@ DIST_SUBDIRS = 		\
 	icons		\
 	libjpegtran	\
 	libfspot	\
+	libfspotraw	\
 	libgphoto2-sharp \
 	Tao		\
 	mono-addins	\
diff --git a/configure.ac b/configure.ac
index d924ef8..7a46419 100644
--- a/configure.ac
+++ b/configure.ac
@@ -10,6 +10,7 @@ AM_MAINTAINER_MODE
 IT_PROG_INTLTOOL([0.35.0])
 
 AC_PROG_CC
+AC_PROG_CXX
 AC_ISC_POSIX
 AC_HEADER_STDC
 AM_PROG_LIBTOOL
@@ -294,6 +295,7 @@ gnome-keyring-sharp/Makefile
 icons/Makefile
 libjpegtran/Makefile
 libfspot/Makefile
+libfspotraw/Makefile
 libgphoto2-sharp/Makefile
 mono-addins/Makefile
 mono-addins/Mono.Addins/Makefile
diff --git a/libfspotraw/.gitignore b/libfspotraw/.gitignore
new file mode 100644
index 0000000..33b9466
--- /dev/null
+++ b/libfspotraw/.gitignore
@@ -0,0 +1,8 @@
+/Makefile
+/Makefile.in
+/.deps
+/.libs
+/*.o
+/*.lo
+/*.la
+/LibRaw-*.tar.gz
diff --git a/libfspotraw/LibRaw/COPYRIGHT b/libfspotraw/LibRaw/COPYRIGHT
new file mode 100644
index 0000000..934ee68
--- /dev/null
+++ b/libfspotraw/LibRaw/COPYRIGHT
@@ -0,0 +1,358 @@
+
+ ** LibRaw: Raw images processing library **
+
+ Copyright (C) 2008-2009 Alex Tutubalin <lexa lexa ru> and Illiah Borg <ib pochtar com>
+ 
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.  See below details.
+
+Contact author if you want to use and/or redistribute LibRaw under non
+GNU GPL license.
+
+
+LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder,
+dcraw.c is copyright 1997-2008 by Dave Coffin, dcoffin a cybercom o net.
+
+========================================================================
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 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.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, 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 or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+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 give any other recipients of the Program a copy of this License
+along with the Program.
+
+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 Program or any portion
+of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+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 Program, 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 Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) 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; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, 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 executable.  However, as a
+special exception, the source code 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.
+
+If distribution of executable or 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 counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program 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.
+
+  5. 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 Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program 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 to
+this License.
+
+  7. 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 Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program 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 Program.
+
+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.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program 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.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the 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 Program
+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 Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, 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
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), 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 Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  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.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; 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.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/libfspotraw/LibRaw/Changelog.rus b/libfspotraw/LibRaw/Changelog.rus
new file mode 100644
index 0000000..067f85f
--- /dev/null
+++ b/libfspotraw/LibRaw/Changelog.rus
@@ -0,0 +1,538 @@
+2009-06-08 Alex Tutubalin <lexa lexa ru>
+           * Èñïðàâëåíèå: ãàììà-êðèâàÿ íå íàêëàäûâàëàñü â ôóíêöèè
+              dcraw_write_mem_image()
+           * Èñïðàâëåíèå: ãàììà-êðèâàÿ íå íàêëàäûâàëàñü ïðè îáðàáîòêå
+             preview íåêîòîðûõ êàìåð Kodak
+           * LibRaw 0.8.0-Beta3
+
+2009-06-05 Alex Tutubalin <lexa lexa ru>
+           * Ïîïðàâêè â äîêóìåíòàöèè: params.gamm[] îïèñàí áîëåå òî÷íî
+           * Ïîïðàâêè â íîìåðå âåðñèè, 0.8-beta1 has version 0.0.0-beta2
+           * LibRaw 0.8.0-Beta2
+
+2009-06-04 Alex Tutubalin <lexa lexa ru>
+           * Èìïîðòèðîâàíà  dcraw 8.94 (1.423):
+             + Ïîääåðæêà íîâûõ êàìåð:
+                 Canon: SX1, 500D/Rebel T1i, A570, A590, SX110
+                 Kodak Z1015, Motorola PIXL, Olympus E30, Panasonic DMC-GH1
+             + Óëó÷øåíû öâåòîâûå äàííûå äëÿ êàìåðû Nikon D3X
+             + Íîâàÿ ñõåìà ðàáîòû ñ ãàììà-êðèâîé
+             + ìíîæåñòâî èçìåíåíèé â êîäå ðàñïàêîâêè
+             + Äëÿ êàìåð Canon: âû÷èòàíèå óðîâíÿ ÷åðíîãî íå ïðîèçâîäèòñÿ, åñëè
+               ÷åðåç ïàðàìåòðû óñòàíîâëåíà params.document_mode > 1
+
+           * Èçìåíåíèÿ API: ïàðàìåòðà params.gamma_16bit field áîëåå íå 
+             ñóùåñòâóåò.
+             Ïàðàìåòðû ãàììà-êðèâîé çàäàþòñÿ ÷åðåç ïîëÿ params.gamm[0]/gamm[1] 
+             (ñì. äîêóìåíòàöèþ è èñõîäíûå òåêñòû ïðèìåðîâ).
+           * Ôóíêöèÿ LibRaw::identify() ðàçäåëåíà íà äâå äëÿ îáõîäà îøèáêè â MS 
+             VS2008 bug 
+           * Èçìåíåíèÿ â ïðèìåðàõ: ïðèìåðû dcraw_emu è mem_image ïîääåðæèâàþò 
+             íîâûå êëþ÷è êîìàíäíîé ñòðîêè dcraw:
+              16bit/gamma semantics:
+                -6 16-áèòíûé âûâîä (ãàììà-êîððåêòèðîâàííûé)
+                -4 16-áèò, ëèíåéíàÿ ãàììà-êðèâàÿ è âûêëþ÷åíî àâòîìàòè÷åñêîå 
+                   ïîâûøåíèå ÿðêîñòè
+           *  LibRaw 0.8.0-Beta1
+
+2009-04-28 Alex Tutubalin <lexa lexa ru>
+           * Ïðèìåð identify ïåðåèìåíîâàí â raw-identify (êîíôëèêò ñ ImageMagic)
+           * Èñïðàâëåíû êîïèðàéòû
+           * Óäàëåíî ìíîæåñòâî ïðåäóïðåæäåíèé êîìïèëÿòîðà
+
+2009-04-07 Alex Tutubalin <lexa lexa ru>
+           * Áîëåå àêêóðàòíîå ïðåîáðàçîâàíèå òèïîâ â libraw_datastream.h
+             (ïîäàâëåíèå warnings ïðè êîìïèëÿöèè ñòîðîííèõ ïðèëîæåíèé ñ -Wall) 
+           * Íîâûé ïàðàìåòð ïîñò-îáðàáîòêè  imgdata.params.auto_bright_thr 
+             - çàäàåò äîëþ íàñûùåííûõ ïèêñåëîâ ïðè èñïîëüçîâàíèè 
+               àâòî-óñòàíîâêè ÿðêîñòè (âìåñòî çàáèòîãî ðàíåå â êîä 1%)
+           * Ïàðàìåòð -U ó ïðèìåðà dcraw_emu: óñòàíàâëèâàåò ïàðàìåòð 
+              auto_bright_thr
+           * Âñå êëèåíòñêèå ïðèëîæåíèÿ äîëæíû áûòü ïåðåêîìïèëèðîâàíû èç-çà 
+             ñìåíû ðàçìåðîâ ñòðóêòóð äàííûõ.
+           * LibRaw 0.7.2-Release
+
+2009-03-22 Alex Tutubalin <lexa lexa ru>
+           * Èñïðàâëåíà îïå÷àòêà â êîäå ïîääåðæêè OpenMP
+           * Ïîääåðæàí MinGW
+           *  ïîñòàâêó âêëþ÷åí èñõîäíûé òåêñò dcraw.c
+           * LibRaw 0.7.1-Release
+
+2009-03-15 Alex Tutubalin <lexa lexa ru>
+           * Öâåòîâûå êàíàëû äëÿ ôàéëîâ Fuji SuperCCD óïîðÿäî÷èâàþòñÿ íà ýòàïå
+             ðàñïàêîâêè RAW (à íå íà ýòàïå ïîñòïðîöåññèíãà, êàê ðàíåå)
+           * LibRaw 0.7.0-Release
+             
+2009-03-13 Alex Tutubalin <lexa lexa ru>
+           * Èìïîðòèðîâàíà dcraw 8.93/1.421
+             + áîëåå îáùàÿ ïîääåðæêà Pentax PEF
+             + ïðàâêè â èäåíòèôèêàöèè ôàéëîâ Kodak DSC620X/720X
+             + áîëåå áûñòðàÿ èäåíòèôèêàöèÿ äëÿ ðÿäà ôîðìàòîâ.
+           * LibRaw 0.7.0-Beta5
+
+2009-03-08 Alex Tutubalin <lexa lexa ru>
+           * Èìïîðòèðîâàíà dcraw 8.92/1.420
+             + âîçìîæíîñòü çàäàíèÿ ïîëüçîâàòåëüñêîé ãàììà-êðèâîé
+             + ïîääåðæêà Pentax K2000/Km
+             + èçìåíåíèÿ â îáðàáîòêå â Canon sRAW
+
+           * òðåáóåòñÿ ïåðåêîìïèëÿöèÿ âñåãî êëèåíòñêîãî êîäà
+
+           * LibRaw 0.7.0-Beta4
+
+2009-02-13 Alex Tutubalin <lexa lexa ru>
+           * bugfix: Ïðèìåð 4channels âû÷èòàåò óðîâåíü ÷åðíîãî ïî-óìîë÷àíèþ
+
+           * dcraw 8.91/1.419 imported:
+              + ïðàâêè â ðàçáîðå ôàéëîâ RIFF
+
+           * LibRaw 0.7.0-Beta3
+
+2009-02-12 Alex Tutubalin <lexa lexa ru>
+           * Äëÿ êàìåð êýíîí íå ðàññ÷èòûâàëñÿ óðîâåíü ÷åðíîãî äëÿ ðÿäà ðåæèìîâ
+             ôèëüòðàöèè RAW
+
+           * Ïðèìåð 4channels òåïåðü ïå÷àòàåò óðîâåíü ÷åðíîãî (ìàñøòàáèðîâàííûé
+             åñëè èñïîëüçóåòñÿ àâòîìàñøòàáèðîâàíèå), èìåíà ïîðîæäàåìûõ
+             ôàéëîâ òåïåðü ñîäåðæàò íàçâàíèå öâåòîâîãî êàíàëà.
+
+           * LibRaw 0.7.0-Beta2
+
+2009-02-09 Alex Tutubalin <lexa lexa ru>
+           * Íîâûé ïðèìåð 4channels: ñîõðàíÿåò êàíàëû ôàéëà â îòäåëüíûõ
+             tiff-ôàéëàõ
+
+           * LibRaw 0.7.0-Beta1
+
+2009-02-07 Alex Tutubalin <lexa lexa ru>
+           * Èñïðàâëåíà îøèáêà â îáðàáîòêå ÷òåíèÿ ìåòàäàííûõ èç
+             âíåøíèõ JPEG-ôàéëîâ
+           * Óñòðàíåíû íåêîòîðûå ïðåäóïðåæäåíèÿ êîìïèëÿòîðà Ñ++
+
+           * Èìïîðòèðîâàíà dcraw 8.91/1.418
+             + Ïîääåðæêà Hasselblad V96C
+
+           * Åñëè âàø êîä èñïîëüçóåò ïîòîêè ââîäà LibRaw, òî âàì
+             ñëåäóåò åãî ïåðåêîìïèëèðîâàòü
+
+           * LibRaw 0.7.0-Alpha6
+
+2009-01-30  Alex Tutubalin <lexa lexa ru>
+           * Ðåàëèçîâàí ïîëíîñòüþ íîâûé framework ââîäà, äîïóñêàþùèé
+             ëåãêîå ïåðåîïðåäåëåíèå ôóíêöèé ÷òåíèÿ RAW-ôàéëîâ ïîëüçîâàòåëåì
+             áèáëèîòåêè.
+             
+           * Âñå ïðîãðàììû, íàïèñàííûå äëÿ ñòàðûõ âåðñèé LibRaw ïîëíîñòüþ
+             ñîâìåñòèìû ñ äàííîé íà óðîâíå èñõîäíûõ òåêñòîâ 
+
+           * Íà áàçå íîâîé  input framework ðåàëèçîâàí èíòåðôåéñ ââîäà äàííûõ
+             èç áóôåðà â ïàìÿòè LibRaw::open_buffer(). Ïðèìåðû dcraw_emu
+             è simple_dcraw èñïîëüçóþò ýòîò èíòåðôåéñ åñëè çàäàí êëþ÷ -B
+
+           * Ôóíêöèÿì - óâåäîìèòåëÿì îá îøèáêàõ ìîæåò áûòü ïåðåäàíî
+             íóëåâîå (NULL) èìÿ îáðàáàòûâàåìîãî ôàéëà, åñëè ïîòîê ââîäà
+             íå àññîöèèðîâàí ñ ôàéëîì. Ýòà ñèòóàöèÿ äîëæíà êîððåêòíî 
+             îáðàáàòûâàòüñÿ êëèåíòñêèì êîäîì, åñëè îí ñòàâèò ñâîè óâåäîìèòåëè
+             îá îøèáêàõ.
+
+           * Òðåáóåòñÿ ïîëíàÿ ïåðåêîìïèëÿöèÿ êëèåíòñêîãî êîäà
+
+           * Èìïîðòèðîâàíà dcraw 8.90/1.417:
+              + Ïîääåðæêà çàãðóçêè áàëàíñà áåëîãî èç ôàéëîâ
+               Sony ARW, ðåäàêòèðîâàííûõ êîíâåðòîðîì Sony IDC.
+
+           * LibRaw 0.7.0-Alpha5
+
+2009-01-17 Alex Tutubalin <lexa lexa ru>
+           * LIBRAW_FILTERING_NOPOSTPROCESS ïåðåèìåíîâàíà 
+             LIBRAW_FILTERING_NORAWCURVE, ÷òî îçíà÷àåò "íå ïðîïóñêàòü
+             RAW-äàííûå ÷åðåç òîíîâóþ êðèâóþ" (äëÿ PhaseOne ýòî
+             îòêëþ÷àåò è âåñü ïðî÷èé ïîñòïðîöåññèíã RAW äàííûõ)
+
+           * Ðåæèì ôèëüòðàöèè NORAWCURVE ðåàëèçîâàí äëÿ âñåõ 
+             ðåëåâàíòíûõ êàìåð ñ áàéåðîâñêîé ìàòðèöåé:
+              + Adobe DNG (òîëüêî RAW-äàííûå ñ áàéåðîâñêîé ìàòðèöû)
+              + Nikon compressed NEF
+              + Ðÿä êàìåð Kodak
+              + Sony A700/A900 (òîëüêî 8-áèòíûå RAW-ôàéëû)
+
+           * Ðåàëèçîâàíà ðàñïàêîâêà áåç ïîâîðîòà äëÿ  DNG-ôàéëîâ 
+             ñêîíâåðòèðîâàííûõ  èç Fuji RAF (SuperCCD)
+           
+           * Ïðèìåð unprocessed_raw: äîáàâëåí êëþ÷ -N, âêëþ÷àþùèé
+             ðåæèì LIBRAW_FILTERING_NORAWCURVE
+
+           * Èìïîðòèðîâàíà dcraw 8.90/1.416:
+              + óëó÷øåíà ïîääåðæêà êàìåðû Samsung S85
+              + èñïðàâëåíî âîçìîæíîå ïåðåïîëíåíèå öåëîãî â
+                wavelet-øóìîïîíèæåíèè
+
+           * LibRaw 0.7.0-Alpha4
+
+
+2009-01-14 Alex Tutubalin <lexa lexa ru>
+           * Èçâëå÷åíèå ÷åðíîé ðàìêè òåïåðü ðàáîòàåò äëÿ âñåõ êàìåð ñ 
+             îäíîöâåòíûìè äàííûìè (äîáàâëåíà ïîääåðæêà äëÿ Fuji è PhaseOne).
+             Âñå åùå íå  ðàáîòàåò äëÿ ìíîãîöâåòíûõ äàííûõ: Foveon, Canon sRAW,
+             Sinar 4-shot, Kodak YRGB è YCbCr
+           * Ðåæèì íåâû÷èòàíèÿ ÷åðíîãî ðàáîòàåò äëÿ âñåõ êàìåð ñ îäíîöâåòíûìè
+             äàííûìè (äîáàâèëàñü ïîääåðæêà PhaseOne backs)
+
+           * Èçìåíåíèÿ â îáðàáîòêå äàííûõ êàìåð FujiFilm:
+              + èñõîäíîå RAW-èçîáðàæåíèå èçâëåêàåòñÿ áåç ïîâîðîòà íà 45 ãðàäóñîâ
+              + ïîâîðîò ïðîèñõîäèò íà ñòàäèè ïîñòîáðàáîòêè
+              + âûçûâàþùàÿ ïðîãðàììà ìîæåò ñäåëàòü ïîâîðîò (è äëÿ ðÿäà êàìåð -
+                äâîéíîå ñæàòèå ïî äëèííîé ñòîðîíå) ñàìîñòîÿòåëüíî, âûçîâîì 
+                rotate_fuji_raw()
+
+           * Íîâûé áèò â íàñòðîéêàõ filtering_mode: 
+              LIBRAW_FILTERING_NOPOSTPROCESS
+             Îòêëþ÷àåò ïîñòïðîöåññèíã, êîòîðûé äåëàåòñÿ íà îñíîâàíèè ñ÷èòàííûõ
+             èç RAW ìåòàäàííûõ. Â íàñòîÿùèé ìîìåíò ôóíêöèîíàëüíîñòü ïîääåðæàíà
+             òîëüêî äëÿ PhaseOne (ïëàíèðóåòñÿ ïîääåðæêà äëÿ âñåõ ðåëåâàíòíûõ 
+             êàìåð)
+
+           * Äëÿ êàìåð PhaseOne ïîìèìî ÷åðíîé ðàìêè õðàíÿòñÿ äàííûå î òî÷êå 
+             ÷åðíîãî, ñ÷èòàííûå èç äàííûõ ôàéëà.
+
+           * Èñïðàâëåíà èìåþùàÿñÿ â dcraw îøèáêà ñ ðàñ÷åòîì óðîâíÿ ÷åðíîãî
+             äëÿ êàìåð PhaseOne, ðåçóëüòàòû ðàáîòû äëÿ ýòèõ çàäíèêîâ áèíàðíî
+             íå ñîâïàäàþò ñî ñòàíäàðòíîé dcraw.
+
+           * Èñïðàâëåíà îøèáêà â îáðàáîòêå ïàðàìåòðà -s â ïðèìåðå dcraw_emu
+           
+           * Äîáàâëåí ïàðàìåòð -s N â ïðèìåð unprocessed_raw, ïîçâîëÿþùèé 
+             çàäàòü íîìåð èçîáðàæåíèÿ äëÿ èçâëå÷åíèÿ.           
+
+           * Èìïîðòèðîâàíà dcraw 8.90/1.414:
+              + èçìåíåíèÿ â îáðàáîòêå âíåøíèõ jpeg ñ ìåòàäàííûìè (Diag RAW)
+              + Ïîääåðæêà Samsung S85
+              + èçìåíåíèÿ â îáðàáîòêå ôàéëîâ QuickTake 100
+
+           * Òðåáóåòñÿ ïîëíàÿ ïåðåêîìïèëÿöèÿ âñåãî êëèåíòñêîãî êîäà
+
+           * LibRaw 0.7.0-Alpha3
+
+
+2009-01-10 Alex Tutubalin <lexa lexa ru>
+           * Èñïðàâëåíà îøèáêà â add_masked_borders(): âñå ïîðòèëîñü, åñëè
+             ðàçìåð âûõîäíîãî èçîáðàæåíèÿ áûë áîëüøå, ÷åì ðàçìåð RAW-äàííûõ
+            * Èñïðàâëåíà îøèáêà â samples/unprocessed_raw.cpp ïðîÿâëÿâøàÿñÿ íà
+             ôàéëîâ ñ êàìåð ñ íåêâàäðàòíûìè ïèêñåëàìè
+
+           * LibRaw 0.7.0-Alpha2 released
+
+2009-01-08 Alex Tutubalin <lexa lexa ru>
+           * èñïðàâëåíà îøèáêà 0.7.0-a0 - ðàçìåðû ðàìêè íå îáíóëÿëèñü, 
+             ïðîÿâëÿëîñü ïðè áàò÷-îáðàáîòêå, åñëè ó ñëåäóþùåãî ôàéëà áûëà ðàìêà
+             íóëåâîãî ðàçìåðà.
+
+           * ×òåíèå ÷åðíîé ðàìêè ñäåëàíî ïðàêòè÷åñêè äëÿ âñåõ êàìåð, ãäå ýòî èìååò
+             ñìûñë (èìååòñÿ ðàìêà). Èñêëþ÷åíèÿ:
+             + Canon sRAW, Leaf (MOS), Sinar 4-shot - ôîðìàòû â êîòîðûõ áîëüøå
+               îäíîãî êîìïîíåíòà â ðàìêå (â Leaf: ïîòåíöèàëüíî, â îñòàëüíûõ - âñåãäà),
+               òðåáóåòñÿ ñìåíà ôîðìàòà äàííûõ õðàíåíèÿ ðàìêè.
+             + Fuji SuperCCD: ïîêà íå ïðèíÿòî ðåøåíèå, êàê ñîâìåñòèòü õðàíåíèå ðàìêè
+                è ïîâîðîò èçîáðàæåíèå (ñî ñìåíîé ìàñøòàáà)
+            Òåñòèðîâàíèå èçâëå÷åíèå ðàìêè íåïîëíîå: äëÿ 9 ôîðìàòîâ ïàêîâêè (èç 21
+            äëÿ êîòîðûõ ïîääåðæàíî èçâëå÷åíèå ÷åðíîé ðàìêè) ïîêà íåò ïðèìåðîâ äàííûõ.
+            Ïðàâäà 7 èç ýòèõ 9 - ýòî ñòàðûå P&S êàìåðû.
+
+           * Íîâûå ïàðàìåòðû ó ïðèìåðà identify: 
+                  -u - ïå÷àòàòü èìÿ  ôóíêöèè-ðàñïàêîâùèêà,
+                  -f - ïå÷àòàòü ðàçìåðû ÷åðíîé ðàìêè ó èçîáðàæåíèÿ.
+             Ðàáîòàþò òîëüêî åñëè identify çàïóùåíà áåç -v
+
+           * íîâûé âûçîâ unpack_function_name(), âîçâðàùàåò èìÿ ôóíêöèè-ðàñïàêîâùèêà
+
+           * Èìïîðòèðîâàíà dcraw 8.89/1.411
+             + èñïðàâëåíèÿ â ðàçáîðå ôàéëîâ Panasonic FZ50
+
+           * LibRaw 0.7.0-Alpha1
+
+2009-01-05 Alex Tutubalin <lexa lexa ru>
+           * Âîçìîæíîñòü îòêëþ÷åíèÿ ôèëüòðàöèè RAW-äàííûõ (âû÷èòàíèå óðîâíÿ ÷åðíîãî,
+            çàìàçûâàíèå ïèêñåëîâ ñ íóëåâûìè çíà÷åíèÿìè):
+                + ïîääåðæàíî íà âñåõ êàìåðàõ êðîìå êàìåð Foveon è Phase One
+                + óïðàâëåíèå ôèëüòðàöèåé ïàðàìåòðîì filtering_mode
+                + âîçìîæíîñòü ðàñøèðåíèÿ API ïðîöåäóðàìè ôèëüòðàöèè, ñïåöèàëèçèðîâàííûìè 
+                  äëÿ êîíêðåòíîé ìîäåëè êàìåðû
+           * Èçâëå÷åíèå äàííûõ ÷åðíîé ðàìêè
+                + API äëÿ õðàíåíèÿ äàííûõ ÷åðíîé ðàìêè
+                + Ïðîöåäóðû èçâëå÷åíèÿ äàííûõ ðàìêè äëÿ ôîðìàòîâ .CRW, .CR2 (êðîìå sRAW),
+                  DNG, NEF, Canon A600 è Canon A5
+           * Âûçîâ add_masked_borders_to_bitmap äëÿ ïîñòðîåíèÿ îáùåãî áèòìýïà 
+             ìàñêèðîâàííàÿ ðàìêà + RAW-äàííûå.
+           * Ïðèìåð èñïîëüçîâàíèÿ âûøåîïèñàííîé ôóíêöèîíàëüíîñòè: samples/unprocessed_raw 
+           * Èìïîðòèðîâàíà íîâàÿ ðåäàêöèÿ dcraw 8.89 (âåðñèÿ 1.410)
+              + èñïðàâëåíèÿ â ðàçáîðå ôàéëîâ Hasselblad
+              + èñïðàâëåíèÿ â ðàçáîðå ôàéëîâ Imacon
+           * Èçìåíåíèÿ â äîêóìåíòàöèè
+           * Òðåáóåòñÿ ïîëíàÿ ïåðåêîìïèëÿöèÿ âñåãî êëèåíòñêîãî êîäà
+           * LibRaw 0.7.0-Alpha0
+
+2009-01-01 Alex Tutubalin <lexa lexa ru>
+           * Èñïðàâëåíà îøèáêà (filedescriptor and buffer memory leak) â êîäå èçâëå÷åíèÿ
+             preview, åñëè èçâëå÷åíèå preview âûçûâàëîñü äî îòêðûòèÿ RAW-ôàéëà.
+             Thanks to Albert Astalis Cid.
+           * LibRaw 0.6.4 Release
+
+2008-12-11 Alex Tutubalin <lexa lexa ru>
+           * Èìïîðòèðîâàíà íîâàÿ ðåäàêöèÿ dcraw 8.89 (âåðñèÿ 1.409)
+           * Èçìåíåíî ðàñêîäèðîâàíèå NEF-ôàéëîâ (ëó÷øå îáðàáàòûâàåòñÿ ïåðåïîëíåíèå)
+           * LibRaw 0.6.3 Release
+
+2008-12-04 Alex Tutubalin <lexa lexa ru>
+           *  Èñïðàâëåíà îøèáêà â îáðàáîòêå ôàéëîâ .RW2 (Panasonic). Îøèáêà ïðîÿâëÿëàñü
+           òîëüêî â thread-safe ðåæèìå, single-threaded âàðèàíò íå áûë çàòðîíóò.
+           * Òðåáóåòñÿ ïîëíàÿ ïåðåêîìïèëÿöèÿ âñåãî êëèåíòñêîãî êîäà
+           * LibRaw 0.6.2 Release
+
+2008-12-03 Alex Tutubalin <lexa lexa ru>
+           * Èìïîðòèðîâàíà dcraw 8.89
+           * Ïîääåðæêà íîâûõ êàìåð
+               Canon G10 è 5D Mk2, Leaf AFi 7, Leica D-LUX4, Panasonic FX150 è G1, Fujifilm IS Pro
+           * Èçìåíåíà ïîääåðæêà êàìåð (öâåòîâûå òàáëèöû), ïîääåðæàíûõ â ïðåäûäóùåé âåðñèè
+               Canon 50D, Nikon D90 & P6000, Panasonic LX3 & FZ28, Sony A900
+           * LibRaw 0.6.2 beta
+
+Äîáàâëåíî ïîëå float LibRaw::imgdata.color.cam_xyz[4][3] - òàáëèöà 
+             ïðåîáðàçîâàíèÿ èç êàìåðíîãî     RGB â XYZ. Ýòà òàáëèöà - êîíñòàíòíà
+             äëÿ êàæäîé êàìåðû (è êîíñòàíòíà â êîäå)
+           * Òðåáóåòñÿ ïîëíàÿ ïåðåêîìïèëÿöèÿ âñåãî êëèåíòñêîãî êîäà
+           * LibRaw 0.6.1 Release
+
+2008-09-25 Alex Tutubalin <lexa lexa ru>
+           * Äîáàâëåíî ïîëå float LibRaw::imgdata.color.cam_xyz[4][3] - òàáëèöà 
+             ïðåîáðàçîâàíèÿ èç êàìåðíîãî     RGB â XYZ. Ýòà òàáëèöà - êîíñòàíòíà
+             äëÿ êàæäîé êàìåðû (è êîíñòàíòíà â êîäå)
+           * Òðåáóåòñÿ ïîëíàÿ ïåðåêîìïèëÿöèÿ âñåãî êëèåíòñêîãî êîäà
+           * LibRaw 0.6.1 Release
+
+2008-09-18 Alex Tutubalin <lexa lexa ru>
+           * èìïîðò  dcraw 8.88:
+              - ïîääåðæêà íîâûõ êàìåð (Canon 50D, Sony A900, Nikon D90 & P6000,
+                Panasonic LX3 FZ28)
+              - íîâàÿ îáðàáîòêà òî÷êè ÷åðíîãî íà êàìåðàõ Canon: áîðüáà ñ áýíäèíãîì
+                (î÷åíü ïðèáëèçèòåëüíàÿ)
+            * Óìåíüøåíèå òðåáîâàíèé ïî ïàìÿòè íà ñòåêå äëÿ îáúåêòà LibRaw
+            (ëîêàëüíûå äàííûå thread ïåðåíåñåíû â äèíàìè÷åñêóþ ïàìÿòü)
+            * ïàò÷è äëÿ ñîâìåñòèìîñòè ñ MS Visual C++
+            * LibRaw 0.6.0 Release
+
+2008-09-16 Alex Tutubalin <lexa lexa ru>
+           * Èçìåíåíèÿ â îïðåäåëåíèè êîíñòàíò, ÷òîáû ñäåëàòü gcc -pedantic ñ÷àñòëèâûì
+           * Ôëàãè êîìïèëÿöèè íå âëèÿþò íà ñîäåðæèìîå ïîëåé êëàññà LibRaw 
+           * Ïðè êîìïèëÿöèè ïî-óìîë÷àíèþ êîìïèëèðóåòñÿ thread-safe âåðñèÿ, õðàíÿùàÿ
+           ñòàòè÷åñêèå äàííûå ðàñïàêîâùèêîâ â îáúåêòå LibRaw
+
+2008-09-14 Alex Tutubalin <lexa lexa ru>
+           * ïàðàëëåëèçàöèÿ ÷åðåç OpenMP íàèáîëåå ðåñóðñîåìêèõ ýòàïîâ îáðàáîòêè
+             ahd_interpolation. wavelet_denoise
+             Ïîääåðæêà OpenMP ðàáîòàåò òîëüêî íà Unix (Linux/FreeBSD) è Mac OS X
+
+           * LibRaw 0.6.0-Beta-1
+ 
+2008-09-10 Alex Tutubalin <lexa lexa ru>
+           *  Ïðè óñòàíîâêå callbacks ñîõðàíÿåòñÿ äîïîëíèòåëüíûé void* - óêàçàòåëü,
+            óêàçûâàþùèé íà ïðèâàòíûå äàííûå callback (äëÿ èñïîëüçîâàíèÿ íåñêîëüêèõ
+            LibRaw instances)
+
+           * LibRaw 0.6.0-alpha5
+
+           * Òðåáóåòñÿ ïîëíàÿ ïåðåêîìïèëÿöèÿ âñåãî êëèåíòñêîãî êîäà
+
+2008-09-10 Alex Tutubalin <lexa lexa ru>
+           * Äîáàâëåíû ñòàäèè îáðàáîòêè LIBRAW_PROGRESS_BAD_PIXELS è 
+             LIBRAW_PROGRESS_DARK_FRAME
+            (óäàëåíû LIBRAW_PROGRESS_RESERVED_PRE1-LIBRAW_PROGRESS_RESERVED_PRE2)
+
+           * Äîáàâëåíà ïîääåðæêà user callbacks íà ïðîìåæóòî÷íûõ ñòàäèÿõ îáðàáîòêè
+
+           * libraw_strprogress call
+
+           * íîâàÿ ôàòàëüíàÿ îøèáêà 'CANCELLED_BY_CALLBACK'
+
+           * ïðèìåð èñïîëüçîâàíèÿ callback â ïðèìåðå dcraw_emu (çàïóñòèòü ñ 
+           êëþ÷àìè -v -v -v)
+
+           * LibRaw 0.6.0-alpha4
+
+           * Òðåáóåòñÿ ïîëíàÿ ïåðåêîìïèëÿöèÿ âñåãî êëèåíòñêîãî êîäà
+
+
+2008-09-08 Alex Tutubalin <lexa lexa ru>
+           * Ïîääåðæêà ICC-ïðîôèëåé, àíàëîãè÷íàÿ ïîääåðæêå â dcraw
+             + âîçìîæíîñòü çàäàòü ïðîôèëü êàìåðû (âêëþ÷àÿ embedded) è âûõîäíîé 
+             ïðîôèëü ïîñëå êîíâåðñèè
+             + äîïîëíèòåëüíûå ïðåäóïðåæäåíèÿ, åñëè çàäàíû íåâåðíûå ïðîôèëè
+             + èñïîëüçóåòñÿ áèáëèîòåêà LCMS
+
+           * ïîääåðæêà êàðòû ïëîõèõ ïèêñåëåé (çàäàåòñÿ ïóòü ê ôàéëó, ôîðìàò 
+            àíàëîãè÷åí dcraw)
+
+           * ïîääåðæêà âû÷èòàíèÿ dark frame ([çàäàåòñÿ ïóòü ê 16-áèò PGM) 
+             samples/simple_dcraw.cpp - äîáàâëåí êëþ÷ -4 äëÿ ãåíåðàöèè dark frame file
+
+           * ïîääåðæêà êàðòû ïëîõèõ ïèêñåëîâ (â ôîðìàòå dcraw)
+
+           * ïðèìåð dcraw_emu ïîääåðæèâàåò âñþ íîâóþ ôóíêöèîíàëüíîñòü 
+           (ICC, dark frame, bad pixels)
+
+           * libraw/libraw_version.h, âûçîâû è ìàêðîñû äëÿ  ïðîâåðêè âåðñèè
+              + LibRaw::version(), LibRaw::versionNumber(), LIBRAW_CHECK_VERSION()
+
+           * âûäàåòñÿ ñïèñîê ïîääåðæèâàåìûõ êàìåð:
+              + LibRaw::cameraCount()
+              + LibRaw::cameraList()
+
+           * èñïðàâëåíà îøèáêà â âûçîâå adjust_sizes_info_only
+
+           * èçìåíåíèÿ â äîêóìåíòàöèè
+
+           * LibRaw 0.6.0-alpha3
+
+2008-09-07 Alex Tutubalin <lexa lexa ru>
+           * samples/mem_image.c - âûâîä 16-áèòíûõ äàííûõ òåïåðü îäèíàêîâ ñ dcraw -4
+             (âûâîä PPM ïðîèçâîäèòñÿ â network byte order)
+
+           * LibRaw 0.6.0-alpha2
+           
+2008-09-06 Alex Tutubalin <lexa lexa ru>
+           * Äîáàâëåíû ôóíêöèè dcraw_make_mem_image è dcraw_make_mem_image:
+             + ðåàëèçàöèÿ ôóíêöèé
+             + èçìåíåíèÿ â äîêóìåíòàöèè
+             + íîâûé ïðèìåð samples/mem_image.cpp
+           * Äîáàâëåí ïàðàìåòð LibRaw::imgdata.params.gamma_16bit 
+              (åñëè îí óñòàíîâëåí â 1, òî âûâîä â  TIFF/ïàìÿòü 16-áèòíûõ äàííûõ  
+              áóäåò ñ ãàììà-êîððåêöèåé)
+           * LibRaw 0.6.0-alpha1
+
+2008-08-28 Alex Tutubalin <lexa lexa ru>
+           * Èìïîðò dcraw 1.404 (8.87):
+             - íîâûå êàìåðû (Canon 1000D, A720, SD300; 
+                Nikon D700, Oly E-520,Kodak C603)
+           * Ëèöåíçèðîâàíèå èçìåíåíî íà GPL v2
+
+2008-05-02 Alex Tutubalin <lexa lexa ru>
+           * Óäàëåí io layer, êàê íå äàþùèé ñóùåñòâåííîãî âûèãðûøà 
+           â ïðîèçâîäèòåëüíîñòè,  âîçâðàùåí FILE I/O
+           
+2008-05-02 Alex Tutubalin <lexa lexa ru>
+           * Èìïîðò dcraw 1.403
+             - èçìåíåíèÿ â ðàñïàêîâêå ljpeg: èíäåêñ â êðèâîé
+             îáðåçàåòñÿ äî 12 áèò (ðàíåå íå áûëî)
+             - èçìåíåíèÿ â îáðàáîòêå êàðòèíîê ñ foveon ñ 
+             jpeg thumbnail: îáðàáàòûâàåòñÿ ñëó÷àé, êîãäà
+             çàÿâëåííàÿ äëèíà thumbnail áîëüøå, ÷åì åñòü ìåñòà
+           * LibRaw 0.5.3 released
+
+2008-04-24 Alex Tutubalin <lexa lexa ru>
+           * Ðåäàêòèðîâàíèå àíãëèéñêîé äîêóìåíòàöèè
+           * ïîïðàâëåíà ñáîðêà ïðèìåðà identify ïîä Linux
+           * LibRaw 0.5.2 released
+
+2008-04-21 Alex Tutubalin <lexa lexa ru>
+           * Îêîí÷àòåëüíûé ïåðåâîä äîêóìåíòàöèè íà àíãëèéñêèé
+           * Ìèêðî-èñïðàâëåíè (ïóòü äî include) â samples/half-mt
+           * LibRaw 0.5.1 released
+
+2008-04-20 Alex Tutubalin <lexa lexa ru>
+           * Äîáàâëåíà è çàäîêóìåíòèðîâàíà óñòàíîâêà ïîä Unix
+           * äîáàâëåíà âòîðàÿ ïîðöèÿ àíãëèéñêîé äîêóìåíòàöèè
+           * èìïîðòèðîâàíà dcraw 1.402 (8.86)
+           * LibRaw 0.5.0 released
+
+2008-04-18 Alex Tutubalin <lexa lexa ru>
+           * ïðàâêà îïå÷àòîê â ðóññêîé äîêóìåíòàöèè
+           * äîáàâëåíà ïåðâàÿ ïîðöèÿ àíãëèéñêîé äîêóìåíòàöèè
+
+2008-04-11 Alex Tutubalin <lexa lexa ru>
+           * Èìïîðòèðîâàíà  dcraw 1.401 (8.85)
+
+2008-04-06 Alex Tutubalin <lexa lexa ru>
+           * Èìïîðòèðîâàíà  dcraw 1.400 (8.84)
+
+2008-04-03 Alex Tutubalin <lexa lexa ru>
+           * Äîáàâëåíà ñáîðêà DLL äëÿ Win32
+           * LibRaw 0.4.9 released
+
+2008-04-03 Alex Tutubalin <lexa lexa ru>
+           * Äîáàâëåíà (è çàäîêóìåíòèðîâàíà) ñáîðêà ïîä Win32
+           * Äîáàâëåí êëþ÷ -T ê half_mt (âûâîä â Tiff)
+           * ïðèìåð half_mt ïåðåïèñàí ïîä Win32 (òàìîøíèé threads interface)
+           * LibRaw 0.4.8 released
+
+2008-03-24 Alex Tutubalin <lexa lexa ru>
+           * Èñïðàâëåíà îøèáêà â ïðîâåðêå íà OUT_OF_ORDER calls
+           * Èñïðàâëåíû ïðîáëåìû c thread safety (Coffin static variables)
+           * äîáàâëåí ïðèìåð half_mt
+           * Äîáàâëåíû warnings è âñå ÷òî ñ ýòèì ñâÿçàíî.
+
+2008-03-23 Alex Tutubalin <lexa lexa ru>
+           * øëèôîâêà Why-LibRaw-rus
+           * open_file() òåïåðü èçâëåêàåò ICC-ïðîôèëü (åñëè îí åñòü â ôàéëå)
+           * óäàëåíà ïîääåðæêà bad_pixels è dark_frame
+           * èñïðàâëåíà îøèáêà â open_file(): params.use_camera_wb íå êîïèðîâàëñÿ â 
+             params.use_camera_matrix åñëè ó ïîñëåäíåãî áûëî çíà÷åíèå ïî óìîë÷àíèþ.
+           * Ïðèìåð samples/dcraw_emu.cpp - ïîëíàÿ ýìóëÿöèÿ ðåæèìîâ dcraw (êðîìå 
+           êëþ÷åé    -i -e -D -d -P -K).
+           * Ïîâåäåíèå "-h implies -f" hardcoded â dcraw_process() 
+           * C API (ñäåëàíî, äîêóìåíòèðîâàíî)
+           * ïðèìåð  dcraw_half (èñïîëüçîâàíèå C API)
+
+2008-03-22 Alex Tutubalin <lexa lexa ru>
+           * äîáàâëåíà char *libraw_strerror(int errcode);
+           * äîáàâëåí ìàêðîñ LIBRAW_FATAL_ERROR
+           * îáðàáîòêà îøèáîê â ïðèìåðàõ ïðèâåäåíà ê ñîâðåìåííûì âåÿíèÿì
+           * Ïðèìåðû ïåðåèìåíîâàíû è èçìåíåíû
+             - dcraw_main -  óäàëåí, çàïóòûâàåò êàðòèíó
+             - identify_cxx => identify 
+             - docmode_cxx => simple_dcraw, äîáàâëåí "ýìóëÿòîð" dcraw áåç
+               ïàðàìåòðîâ (âñå - defaults)
+           * ïåðåóïîðÿäî÷åíî ðàñïîëîæåíèå èñõîäíûõ òåêñòîâ
+           * io.h => libraw_io.h
+           * çàïðîãðàììèðîâàíà dcraw_process()
+           * øëèôîâêà äîêóìåíòàöèè
+           * LibRaw 0.3.0 released
+           
+2008-03-20 Alex Tutubalin <lexa lexa ru>
+           * âñå ïåðåìåííûå _offset ñïðÿòàíû èç çîíû âèäèìîñòè
+           * óäàëåíà îáðàáîòêà îøèáêè íåõâàòêè ïàìÿòè íà longjmp (âñå ðàâíî
+             íå ðàáîòàëà), çàìåíåíà íà C++ exceptions. 
+
+           * ïàìÿòü ïîä ãèñòîãðàììó òåïåðü àëëîöèðóåòñÿ äèíàìè÷åñêè
+           * Èçìåíåíèÿ â îáðàáîòêå preview äëÿ êàìåð Kodak (ïîâëåêøèå
+             çà ñîáîé ìàññèðîâàííûå èçìåíåíèÿ â èíòåðôåéñå):
+                - kodak thumbnails ñðàçó ãàììà-êîððåêòèðóþòñÿ è ïðèìåíÿåòñÿ 
+                  âíóòðèêàìåðíûé áàëàíñ áåëîãî  (àíàëîãè÷íî dcraw -e)
+                - Óäàëåíà ôóíêöèÿ int LibRaw::dcraw_ppm_tiff_writer (ò.ê. 
+                  âñå bitmap-ïðåâüþ òåïåðü â îäèíàêîâîì ôîðìàòå, òî îíà 
+                  íå íóæíà) 
+                - óäàëåíû êîíñòàíòû ôîðìàòà thumbnail:
+                          LIBRAW_THUMBNAIL_FOVEON
+                          LIBRAW_THUMBNAIL_KODAK
+                          LIBRAW_THUMBNAIL_PPM
+                  âìåñòî íèõ òåïåðü
+                          LIBRAW_THUMBNAIL_BITMAP
+	
+            * èìïëåìåíòèðîâàíû ïîëüçîâàòåëüñêèå callbacks íà îøèáî÷íûå
+              ñîñòîÿíèÿ "íåõâàòêà ïàìÿòè" è "îøèáêà ïðè ÷òåíèè äàííûõ"
+	
+            * èìïëåìåíòèðîâàí ìåíåäæåð ïàìÿòè è àâòîìàòè÷åñêîå îñâîáîæäåíèå
+              âñåãî àëëîöèðîâàííîãî ïî recycle()
+        
+            * Ïðè âîçíèêíîâåíèè èñêëþ÷èòåëüíîé ñèòóàöèè ïðè çàïèñè âî
+              âíåøíèé ôàéë - ôàéë çàêðûâàåòñÿ.  
+
+            * Äîáàâëåíû íîâûå êîäû îøèáîê
+                        LIBRAW_UNSUFFICIENT_MEMORY
+                        LIBRAW_DATA_ERROR
+                        LIBRAW_IO_ERROR
+              Ïðè âîçíèêíîâåíèè ýòèõ îøèáîê äåëàåòñÿ recycle() è îáúåêò
+              LibRaw ïåðåõîäèò â èñõîäíîå (ñòàðòîâîå) ñîñòîÿíèå
+	
+            * Äîáàâëåíî íîâîå ñîñòîÿíèå èñòî÷íèêà öâåòîâûõ äàííûõ:
+              LIBRAW_COLORSTATE_INIT 
+
+            * LibRaw 0.3.0 released
\ No newline at end of file
diff --git a/libfspotraw/LibRaw/Changelog.txt b/libfspotraw/LibRaw/Changelog.txt
new file mode 100644
index 0000000..b5d47e0
--- /dev/null
+++ b/libfspotraw/LibRaw/Changelog.txt
@@ -0,0 +1,431 @@
+2009-06-08 Alex Tutubalin <lexa lexa ru>
+           * Fixes: gamma  curve processing was not performed in 
+              dcraw_write_mem_image()
+           * Fixes: gamma curve processing was not performed for 
+              Kodak thumbnails
+           * LibRaw 0.8.0-Beta3
+
+2009-06-05 Alex Tutubalin <lexa lexa ru>
+           * Fixes in documentation: params.gamm[] described more precisely
+           * Fixes in version number, 0.8-beta1 was mistakenly 0.0.0-beta1
+           * LibRaw 0.8.0-Beta2
+
+2009-06-04 Alex Tutubalin <lexa lexa ru>
+           * Imported dcraw 8.94 (1.423):
+             + New camera support:
+                 Canon: SX1, 500D/Rebel T1i, A570, A590, SX110
+                 Kodak Z1015, Motorola PIXL, Olympus E30, Panasonic DMC-GH1
+             + Improved color data for Nikon D3X
+             + New gamma curve model
+             + Many changes in RAW unpacking code
+             + Canon cameras: black level is not subtracted if set 
+               params.document_mode > 1
+
+           * API changed: params.gamma_16bit field removed. Gamma curve is
+             set via params.gamm[0]/gamm[1] values (see documentation and 
+             samples for details)
+           * LibRaw::identify() splitted to avoid MS VS2008 bug (too many 
+             nested blocks)
+
+           * Samples: dcraw_emu and mem_image samples supports new dcraw 
+              16bit/gamma semantics:
+                -6: set 16 bit output
+                -4: set 16 bit output and linear gamma curve and no auto 
+                   brighness
+           *  LibRaw 0.8.0-Beta1
+
+2009-04-28 Alex Tutubalin <lexa lexa ru>
+           * Identify sample renamed to raw-identify (name conflict 
+             with ImageMagic)
+           * Copyright notice changes
+           * Many compiler warnings removed
+
+2009-04-07 Alex Tutubalin <lexa lexa ru>
+           * More accurate types conversion in libraw_datastream.h 
+           * New postprocessing parameter auto_bright_thr: set portion of 
+             clipped pixels for auto brightening code (instead of 
+             dcraw-derived hardcoded 1%)
+           * -U  option for dcraw_emu sample sets auto_bright_thr parameter
+           * all client code should be recompiled due to structures size 
+             change
+           * LibRaw 0.7.2-Release
+
+2009-03-22 Alex Tutubalin <lexa lexa ru>
+           * Fixed typo in OpenMP support code
+           * MinGW support 
+           * dcraw source is included in distribution
+           * LibRaw 0.7.1-Release
+
+2009-03-15 Alex Tutubalin <lexa lexa ru>
+           * Fuji SuperCCD RAWs: color channels unshuffled on RAW
+             read stage (moved from postprocessing stage)
+
+           * LibRaw 0.7.0-Release
+
+2009-03-13 Alex Tutubalin <lexa lexa ru>
+           * dcraw 8.93/1.421 imported:
+             + more accurate pentax dSLR support
+             + fixes in Kodak 620x/720x identification
+             + faster identification procedure for some formats.
+           * LibRaw 0.7.0-Beta5
+
+
+2009-03-08 Alex Tutubalin <lexa lexa ru>
+           * dcraw 8.92/1.420 imported:
+             + user-specified gamma curve
+             + Pentax K2000/Km support
+             + Changes in Canon sRAW processing (support for 5D2 fw 1.07)
+
+           * all client code should be recompiled
+
+           * LibRaw 0.7.0-Beta4
+
+2009-02-13 Alex Tutubalin <lexa lexa ru>
+           * bugfix: 4channels sample finally subtracts black by default
+           * dcraw 8.91/1.419 imported:
+              + fixes in RIFF files parsing
+
+           * LibRaw 0.7.0-Beta3
+
+2009-02-12 Alex Tutubalin <lexa lexa ru>
+           * Black level was not calculated for Canon RAWs in
+             some filtering modes
+
+           * 4channels sample prints calculated black level
+             (scaled if autoscaling used). 
+             Also output file names for this sample now includes 
+             color channel name (R/G/B/G2 or C/M/Y/G)
+
+           * LibRaw 0.7.0-Beta2
+
+2009-02-09 Alex Tutubalin <lexa lexa ru>
+           * New sample 4channels: splits RAW color channels into four 
+             separate TIFFs
+
+           * LibRaw 0.7.0-Beta1
+
+2009-02-07 Alex Tutubalin <lexa lexa ru>
+           * Fixed bug in external jpeg metadata reading code.
+
+           * Cleaned some C++ warnings
+
+           * dcraw 8.91/1.418 imported
+             + Hasselblad V96C support
+
+           * You need to clean and recompile client code which
+             uses LibRaw_*_datastream classes.
+
+           * LibRaw 0.7.0-Alpha6
+
+2009-01-30  Alex Tutubalin <lexa lexa ru>
+
+           * New data input framework is created. It is possible now to
+             easyly implement your own data input interface for LibRaw
+             (e.g. for reading RAW data from network data stream)
+             
+           * All older programs using previous LibRaw versions are
+	     compatible at source code level.
+
+           * LibRaw can read RAW data from memory buffer via
+             new LibRaw::open_buffer() API call (implemented on top of
+             new input framework). 
+             This call used in sample application dcraw_emu and simple_dcraw
+             (with -B command-line switch) to test new API.
+
+           * Error handling callback functions now can be called with
+             NULL filename passed (if underlying data stream object
+             does not know file name).
+             So, client error handling callbacks should work with NULL
+             filename.
+
+           * All client code should be recompiled
+
+           * Imported dcraw 8.90/1.417:
+              + Support for loading White Balance data from
+                Sony ARW files edited with Sony IDC software.
+
+           * LibRaw 0.7.0-Alpha5
+
+2009-01-17 Alex Tutubalin <lexa lexa ru>
+           * Raw filtering mode LIBRAW_FILTERING_NOPOSTPROCESS has renamed
+            to LIBRAW_FILTERING_NORAWCURVE for better reflect its purpose.
+            This filtering_mode bit turns off tone curve applying on
+            RAW data on bayer-pattern cameras with raw tone curve:
+              + Adobe DNG (only RAW with bayer pattern)
+              + Nikon compressed NEF
+              + Some Kodak cameras
+              + Sony A700/A900 (tone curve applied to 8-bit raws)
+
+           * unprocessed_raw sample: added command-line key -N, this key
+             turns on LIBRAW_FILTERING_NORAWCURVE filtering mode.
+
+           * New scheme of Fuji RAW processing (introduced in 0.7-Alpha3)
+             supports DNG files generated from Fuji RAF.
+           
+           * Imported dcraw 8.90/1.416:
+              + better support for Samsung S85
+              + fixed possible integer overflow in wavelet denoising code
+
+           * LibRaw 0.7.0-Alpha4
+
+
+2009-01-14 Alex Tutubalin <lexa lexa ru>
+           * Black mask extraction supported for all files with bayer data
+            (one component per pixel). Black mask data not avaliable
+            for multi-component data (Foveon, Canon sRAW, Sinar 4-shot,
+            Kodak YCC/YRGB).
+
+           * Black level subtraction can be turned off for all bayer
+            cameras (added support for PhaseOne backs).
+
+           * Fujifilm camera processing model changed:
+              + RAW data is extracted without 45-degree rotation
+              + dcraw-compatible rotation is performed on postptocessing stage
+              + it is possible to rotate RAW data without postprocessing
+                by LibRaw::rotate_fuji_raw() call.
+
+           * New filtering mode setting: LIBRAW_FILTERING_NOPOSTPROCESS
+             This bits turns off RAW tone curve processing based on tone curve
+             readed from RAW metadata.
+             This mode supported only for PhaseOne backs now (to be supported
+             on all relevant cameras in nearest future releases)
+
+           * Black level data (got from RAW data) are stored for PhaseOne backs.
+
+           * Black level subtraction bug (derived from dcraw) fixed
+             for PhaseOne files.
+
+           * Fixed processing of -s parameter for dcraw_emu sample
+           
+           * Parameter  -s N (select shot number) added to 
+             unprocessed_raw sample.
+
+           * Imported dcraw 8.90/1.414:
+              + changes in QuickTake 100 metadata processing
+              + changes in external jpeg processing code
+              + Samsung S85 support
+
+           * All client code should be recompiled
+
+           * LibRaw 0.7.0-Alpha3 released
+
+2009-01-10 Alex Tutubalin <lexa lexa ru>
+           * Fixed bug in add_masked_borders: crash if output dimensions
+            is already larger than raw dimensions
+            * Fixed out of bounds in samples/unprocessed_raw.cpp for files
+            with non-square pixels
+
+           * LibRaw 0.7.0-Alpha2 released
+           
+2009-01-08 Alex Tutubalin <lexa lexa ru>
+           * Fixed bug in  0.7.0-a0: black frame size has not reset, 
+             so in batch processing there is an error in black frame
+             size for files without black frame.
+
+           * Implemented reading of black/masked pixels data for 
+             near all cameras with masked pixels, exclding:
+              + Canon sRAW, Leaf (MOS), Sinar 4-shot - more than one 
+                color component in black frame (redesign of black frame
+                data structures required).
+              + Fuji SuperCCD: need to design right methods of extraction 
+                (should we rotate and resize black pixels as active ones??)
+
+            * Tested for most dSLR data formats with masked pixels: 7 of 9
+              untested formats are from old P&S cameras.
+
+           * New call LibRaw::unpack_function_name() returns unpack function name
+             (useful for testers only)
+
+           * New identify sample parameters (useful for test-suite builders
+             to check test coverage):
+                  -u - print unpack function name
+                  -f - print masked frame size
+             These parameters works only for identify run without -v parameter
+
+           * Imported dcraw 8.89/1.411
+             + changes in Panasonic FZ50 files parsing
+
+           * LibRaw 0.7.0-Alpha1 released
+
+
+2009-01-05 Alex Tutubalin <lexa lexa ru>
+           * It is possible to turn off RAW data filtration (black level 
+             subtraction,              zero pixels averaging):
+                + supported on all cameras except Foveon and Phase One
+                + filtraction controlled by new parameter "filtering_mode"
+                + it is possible to expand API by filtering procedures 
+                  built for specific camera model.
+
+           * Black border (masked pixels) extraction:
+                + API (data structures) for storing black mask.
+                + Black mask extraction supported only for limited list of
+                  data formats: 
+                       - Canon .CRW, .CR2 (with exception of sRAW),A600, A5
+                       - Adobe DNG (both converted RAW and native DNG)
+                       - Nikon NEF (compressed only)
+                  this list to be expanded in future LibRaw versions
+           * New call add_masked_borders_to_bitmap makes full bitmap
+             'masked border' + image
+           * Usage sample for functionality listed above: 
+              samples/unprocessed_raw 
+           * Imported dcraw 8.89/1.410:
+              + fixed bugs in Hasselblad .fff decoding
+              + fixes in Imacon metadata decoding
+           * Documentation changes
+           * All client code should be recompiled
+           * LibRaw 0.7.0-Alpha0
+
+
+2009-01-01 Alex Tutubalin <lexa lexa ru>
+           * Fixed a bug (filedescriptor and buffer memory leak)  in thumbnail 
+             extraction when called before metadata analysis. 
+             Thanks to Albert Astalis Cid.
+           * LibRaw 0.6.4 Release
+
+2008-12-11 Alex Tutubalin <lexa lexa ru>
+           * Imported new edition of dcraw 8.89 (version 1.409)
+           * Nikon NEF decoding changed
+           * LibRaw 0.6.3 Release
+           
+2008-12-03 Alex Tutubalin <lexa lexa ru>
+           * fixed bug in Panasonic .RW2 processing (only for thread-safe version,
+             single-threaded version was not affected)
+           * All client code should be recompiled
+           * LibRaw 0.6.2 Release
+
+2008-12-03 Alex Tutubalin <lexa lexa ru>
+           * Imported  dcraw 8.89 (version 1.407)
+           * New cameras:
+               Canon G10 & 5D Mk2, Leaf AFi 7, Leica D-LUX4, Panasonic FX150 & G1, 
+               Fujifilm IS Pro,
+           * Changed camera support (color conversion tables):
+               Canon 50D, Nikon D90 & P6000, Panasonic LX3 & FZ28, Sony A900
+           * LibRaw 0.6.2 beta
+
+2008-09-25 Alex Tutubalin <lexa lexa ru>
+           * Added new data field  float LibRaw::imgdata.color.cam_xyz[4][3]. 
+           This field contains constant table (different for each camera) for
+           Camera RGB->XYZ conversion.
+           * All client code should be recompiled
+           * LibRaw 0.6.1 Release
+
+2008-09-18 Alex Tutubalin <lexa lexa ru>
+           * dcraw 8.88 imported:
+              - new cameras (Canon 50D, Sony A900, Nikon D90 & P6000,
+                Panasonic LX3 FZ28)
+              - new method of black point subtraction for Canon cameras, 
+                preliminary banding supression.
+            * Stack memory usage lowered (some thread data moved to dynamic
+            memory) 
+            * some patches for MSVC compatibility
+            * LibRaw 0.6.0 Release
+
+2008-09-16 Alex Tutubalin <lexa lexa ru>
+           * Enum definitions changed to make gcc -pedantic happy
+           * Compiler/preprocessor flags does not affects LibRaw class field set
+           (i.e. structure for thread local storage is always allocated)                   
+           * Default library compilation mode (i.e. sources imported in another
+             project) is thread-safe 
+
+2008-09-14 Alex Tutubalin <lexa lexa ru>
+           * OpenMP support for most CPU consuming steps of processing:
+             ahd_interpolation. wavelet_denoise
+             10-30% speed-up of full processing pipe on 2-core CPU 
+             OpenMP supported only on gcc (Linux/FreeBSD and Mac OS X)
+
+           * LibRaw 0.6.0-Beta-1
+
+2008-09-10 Alex Tutubalin <lexa lexa ru>
+           *  All set_**handler accepts additional void* pointer, which should point to
+            callback private data. This pointer passed to user callback when it called.
+
+           * LibRaw 0.6.0-alpha5
+
+           * All client code should be recompiled
+
+2008-09-10 Alex Tutubalin <lexa lexa ru>
+           * New processing stages in enum LibRaw_progress: 
+             LIBRAW_PROGRESS_BAD_PIXELS LIBRAW_PROGRESS_DARK_FRAME
+            (reserved stages LIBRAW_PROGRESS_RESERVED_PRE1-PRE2 has removed)
+           * libraw_strprogress() - convert progress code into string
+
+           * Added progress/cancellation user callbacks
+             + new fatal error code: CANCELLED_BY_CALLBACK
+             + sample usage in samples/dcraw_emu.cpp (try run it with -v -v -v opts)
+
+           * LibRaw 0.6.0-alpha4
+
+           * All client code should be recompiled
+
+2008-09-08 Alex Tutubalin <lexa lexa ru>
+           * ICC-profiles support (same as in dcraw)
+             + input/output profiles (specified as path to 'icc' file or 'embed' for 
+               embedded input profile)
+             + additional warnings
+             + LCMS library used
+
+           * support of bad pixel map (caller should specify path to bad pixel file 
+              in dcraw-compatible format)
+
+           * dark frame subtraction support (caller should supply path to 16-bit PGM 
+              map). samples/simple_dcraw.cpp - -4 option added for dark frame file 
+              generation
+
+           * support of bad pixeld map (dcraw-compatible format)
+
+           * the dcraw_emu sample supports all new features (ICC, dark frame, bad 
+              pixels)
+
+           * libraw/libraw_version.h, defines, calls and macros for version checks:
+              + LibRaw::version(), LibRaw::versionNumber(), LIBRAW_CHECK_VERSION()
+
+           * List of supported cameras:
+              + LibRaw::cameraCount()
+              + LibRaw::cameraList()
+
+           * fixed error in adjust_sizes_info_only
+
+           * documentation changes
+
+           * LibRaw 0.6.0-alpha3
+
+2008-09-07 Alex Tutubalin <lexa lexa ru>
+           * samples/mem_image.c - bitwise equal output with dcraw -4
+             (PPMs outputted with network byte order)
+           * LibRaw 0.6.0-alpha2
+           
+2008-09-06 Alex Tutubalin <lexa lexa ru>
+           * Added calls dcraw_make_mem_image and dcraw_make_mem_image:
+             + functions (and supporting code)
+             + documentation changed
+             + new sample code samples/mem_image.cpp
+           * Added processing parameter  LibRaw::imgdata.params.gamma_16bit 
+              (set to 1 to make gamma correction for 16-bit output)
+           * LibRaw 0.6.0-alpha1
+
+2008-08-28 Alex Tutubalin <lexa lexa ru>
+           * dcraw 1.404 (8.87) imported:
+             - 6 new cameras supported (Canon 1000D, A720, SD300; 
+                Nikon D700, Oly E-520,Kodak C603)
+           * Licensing changed to GPL v2
+
+2008-05-02  Alex Tutubalin <lexa lexa ru>
+            * mmap/malloc+read IO-layer removed due to no performance gain.
+              FILE I/O returned
+
+2008-05-02  Alex Tutubalin <lexa lexa ru>
+            * dcraw 1.403 imported
+              - changes in ljpeg decompression (index values cut to 12 bit)
+              - changes in parse_foveon() jpeg thumbnail extraction	
+            * LibRaw 0.5.3 released
+
+2008-04-24  Alex Tutubalin <lexa lexa ru>
+            * Linux build of samples/identify fixed
+            * documentation editorial
+            * LibRaw 0.5.2 released
+
+2008-04-21  Alex Tutubalin <lexa lexa ru>
+            * All documentation translated to English
+            * English changelog started :)
+            * minor bug (include path) fixed in samples/half_mt 
+            * LibRaw 0.5.1 released
diff --git a/libfspotraw/LibRaw/Makefile b/libfspotraw/LibRaw/Makefile
new file mode 100644
index 0000000..66f9183
--- /dev/null
+++ b/libfspotraw/LibRaw/Makefile
@@ -0,0 +1,106 @@
+all: library all_samples 
+
+CFLAGS=-O4  -I. -w
+
+# OpenMP support
+#CFLAGS=-O4  -I. -w -fopenmp
+
+# LCMS support
+#LCMS_DEF=-DUSE_LCMS -I/usr/local/include
+#LCMS_LIB=-L/usr/local/lib -llcms
+
+
+DCRAW_LIB_OBJECTS=object/dcraw_common.o object/foveon.o object/libraw_cxx.o object/libraw_c_api.o object/dcraw_fileio.o
+DCRAW_LIB_MT_OBJECTS=object/dcraw_common_mt.o object/foveon_mt.o object/libraw_cxx_mt.o object/libraw_c_api_mt.o object/dcraw_fileio_mt.o
+
+library: lib/libraw.a lib/libraw_r.a
+
+all_samples: bin/raw-identify bin/simple_dcraw  bin/dcraw_emu bin/dcraw_half bin/half_mt bin/mem_image bin/unprocessed_raw bin/4channels
+
+install: library
+	@if [ -d /usr/local/include ] ; then cp -R libraw /usr/local/include/ ; else echo 'no /usr/local/include' ; fi
+	@if [ -d /usr/local/lib ] ; then cp lib/libraw.a lib/libraw_r.a /usr/local/lib/ ; else echo 'no /usr/local/lib' ; fi
+
+install-binaries: all_samples
+	@if [ -d /usr/local/bin ] ; then cp bin/[a-z]* /usr/local/bin/ ; else echo 'no /usr/local/bin' ; fi
+
+
+#binaries
+
+bin/raw-identify: lib/libraw.a samples/raw-identify.cpp
+	g++ -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/raw-identify samples/raw-identify.cpp -L./lib -lraw  -lm ${LCMS_LIB}
+
+bin/unprocessed_raw: lib/libraw.a samples/unprocessed_raw.cpp
+	g++ -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/unprocessed_raw samples/unprocessed_raw.cpp -L./lib -lraw  -lm  ${LCMS_LIB}
+
+bin/4channels: lib/libraw.a samples/4channels.cpp
+	g++ -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/4channels samples/4channels.cpp -L./lib -lraw  -lm  ${LCMS_LIB}
+
+bin/simple_dcraw: lib/libraw.a samples/simple_dcraw.cpp
+	g++ -DLIBRAW_NOTHREADS ${LCMS_DEF}  ${CFLAGS} -o bin/simple_dcraw samples/simple_dcraw.cpp -L./lib -lraw  -lm  ${LCMS_LIB}
+
+bin/mem_image: lib/libraw.a samples/mem_image.cpp
+	g++ -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/mem_image samples/mem_image.cpp -L./lib -lraw  -lm  ${LCMS_LIB}
+
+bin/dcraw_half: lib/libraw.a object/dcraw_half.o
+	gcc -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/dcraw_half object/dcraw_half.o -L./lib -lraw  -lm -lstdc++  ${LCMS_LIB}
+
+bin/half_mt: lib/libraw_r.a object/half_mt.o
+	gcc ${LCMS_DEF}  -pthread ${CFLAGS} -o bin/half_mt object/half_mt.o -L./lib -lraw_r  -lm -lstdc++  ${LCMS_LIB}
+
+bin/dcraw_emu: lib/libraw.a samples/dcraw_emu.cpp
+	g++ -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/dcraw_emu samples/dcraw_emu.cpp -L./lib -lraw  -lm  ${LCMS_LIB}
+
+#objects
+
+object/dcraw_common.o: internal/dcraw_common.cpp
+	g++ -c -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o object/dcraw_common.o internal/dcraw_common.cpp
+
+object/dcraw_fileio.o: internal/dcraw_fileio.cpp
+	g++ -c -DLIBRAW_NOTHREADS ${CFLAGS} ${LCMS_DEF} -o object/dcraw_fileio.o internal/dcraw_fileio.cpp
+
+object/foveon.o: internal/foveon.cpp
+	g++ -c -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o object/foveon.o internal/foveon.cpp
+
+object/libraw_cxx.o: src/libraw_cxx.cpp
+	g++ -c -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o object/libraw_cxx.o src/libraw_cxx.cpp
+
+object/libraw_c_api.o: src/libraw_c_api.cpp
+	g++ -c -DLIBRAW_NOTHREADS  ${LCMS_DEF} ${CFLAGS} -o object/libraw_c_api.o src/libraw_c_api.cpp
+
+object/dcraw_half.o: samples/dcraw_half.c
+	gcc -c -DLIBRAW_NOTHREADS  ${LCMS_DEF} ${CFLAGS} -o object/dcraw_half.o samples/dcraw_half.c
+
+object/half_mt.o: samples/half_mt.c
+	gcc -c -pthread ${LCMS_DEF}  ${CFLAGS} -o object/half_mt.o samples/half_mt.c
+
+
+lib/libraw.a: ${DCRAW_LIB_OBJECTS}
+	rm -f lib/libraw.a
+	ar crv lib/libraw.a ${DCRAW_LIB_OBJECTS}
+	ranlib lib/libraw.a
+
+lib/libraw_r.a: ${DCRAW_LIB_MT_OBJECTS}
+	rm -f lib/libraw_r.a
+	ar crv lib/libraw_r.a ${DCRAW_LIB_MT_OBJECTS}
+	ranlib lib/libraw_r.a
+
+object/dcraw_common_mt.o: internal/dcraw_common.cpp
+	g++ -c -pthread ${LCMS_DEF}  ${CFLAGS} -o object/dcraw_common_mt.o internal/dcraw_common.cpp
+
+object/dcraw_fileio_mt.o: internal/dcraw_fileio.cpp
+	g++ -c -pthread ${LCMS_DEF} ${CFLAGS} -o object/dcraw_fileio_mt.o internal/dcraw_fileio.cpp
+
+object/foveon_mt.o: internal/foveon.cpp
+	g++ -c ${LCMS_DEF} -pthread ${CFLAGS} -o object/foveon_mt.o internal/foveon.cpp
+
+object/libraw_cxx_mt.o: src/libraw_cxx.cpp
+	g++ -c ${LCMS_DEF}  -pthread ${CFLAGS} -o object/libraw_cxx_mt.o src/libraw_cxx.cpp
+
+object/libraw_c_api_mt.o: src/libraw_c_api.cpp
+	g++ -c ${LCMS_DEF}  -pthread ${CFLAGS} -o object/libraw_c_api_mt.o src/libraw_c_api.cpp
+
+clean:
+	rm -fr bin/*.dSYM
+	rm -f *.o *~ src/*~ samples/*~ internal/*~ libraw/*~ lib/lib*.a bin/[4a-z]* object/*o dcraw/*~ doc/*~ bin/*~
+
diff --git a/libfspotraw/LibRaw/Makefile.mingw b/libfspotraw/LibRaw/Makefile.mingw
new file mode 100644
index 0000000..e14c9e9
--- /dev/null
+++ b/libfspotraw/LibRaw/Makefile.mingw
@@ -0,0 +1,83 @@
+all: library samples 
+
+# OpenMP support
+#OPENMP_CFLAGS=-fopenmp
+
+# LCMS support
+#LCMS_DEF=-DUSE_LCMS -I/usr/local/include
+#LCMS_LIB=-L/usr/local/lib -llcms
+
+# Common flags
+# WARNING: library order matters
+COMMON_LIBS=-lws2_32 -lm ${LCMS_LIB}
+CLIBS=-L./lib  -lraw ${COMMON_LIBS}
+CFLAGS=-O4 -I. -w -DLIBRAW_NODLL ${OPENMP_CFLAGS}
+
+DCRAW_LIB_OBJECTS=object/libraw_cxx.o object/libraw_c_api.o object/dcraw_common.o object/foveon.o object/dcraw_fileio.o
+
+library: lib/libraw.a
+
+samples: bin/raw-identify bin/simple_dcraw bin/dcraw_emu bin/dcraw_half bin/mem_image bin/mem_image bin/unprocessed_raw bin/4channels
+
+install: library
+	@if [ -d /usr/local/include ] ; then cp -R libraw /usr/local/include/ ; else echo 'no /usr/local/include' ; fi
+	@if [ -d /usr/local/lib ] ; then cp lib/libraw.a /usr/local/lib/ ; else echo 'no /usr/local/lib' ; fi
+
+install-samples: samples
+	@if [ -d /usr/local/bin ] ; then cp bin/[a-z]* /usr/local/bin/ ; else echo 'no /usr/local/bin' ; fi
+
+# Samples
+
+bin/raw-identify: lib/libraw.a samples/raw-identify.cpp
+	g++ -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/raw-identify samples/raw-identify.cpp ${CLIBS} 
+
+bin/unprocessed_raw: lib/libraw.a samples/unprocessed_raw.cpp
+	g++ -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/unprocessed_raw samples/unprocessed_raw.cpp ${CLIBS}
+
+bin/4channels: lib/libraw.a samples/4channels.cpp
+	g++ -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/4channels samples/4channels.cpp ${CLIBS}
+
+bin/simple_dcraw: lib/libraw.a samples/simple_dcraw.cpp
+	g++ -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/simple_dcraw samples/simple_dcraw.cpp ${CLIBS}
+
+bin/mem_image: lib/libraw.a samples/mem_image.cpp
+	g++ -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/mem_image samples/mem_image.cpp ${CLIBS}
+
+bin/dcraw_half: lib/libraw.a object/dcraw_half.o
+	gcc -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/dcraw_half object/dcraw_half.o ${CLIBS} -lstdc++
+
+bin/dcraw_emu: lib/libraw.a samples/dcraw_emu.cpp
+	g++ -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o bin/dcraw_emu samples/dcraw_emu.cpp ${CLIBS}
+
+#Libraries
+
+# Non-threaded library
+
+object/dcraw_common.o: internal/dcraw_common.cpp
+	g++ -c -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o object/dcraw_common.o internal/dcraw_common.cpp
+
+object/dcraw_fileio.o: internal/dcraw_fileio.cpp
+	g++ -c -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o object/dcraw_fileio.o internal/dcraw_fileio.cpp
+
+object/foveon.o: internal/foveon.cpp
+	g++ -c -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o object/foveon.o internal/foveon.cpp
+
+object/libraw_cxx.o: src/libraw_cxx.cpp
+	g++ -c -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o object/libraw_cxx.o src/libraw_cxx.cpp
+
+object/libraw_c_api.o: src/libraw_c_api.cpp
+	g++ -c -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o object/libraw_c_api.o src/libraw_c_api.cpp
+
+object/dcraw_half.o: samples/dcraw_half.c
+	gcc -c -DLIBRAW_NOTHREADS ${LCMS_DEF} ${CFLAGS} -o object/dcraw_half.o samples/dcraw_half.c
+
+lib/libraw.a: ${DCRAW_LIB_OBJECTS}
+	del lib\\libraw.a
+	ar crv lib/libraw.a ${DCRAW_LIB_OBJECTS}
+	ranlib lib/libraw.a	
+
+# Clean	
+
+clean:
+	del bin\\*.dSYM
+	del lib\\lib*.a bin\\*.exe object\\*o 
diff --git a/libfspotraw/LibRaw/Makefile.msvc b/libfspotraw/LibRaw/Makefile.msvc
new file mode 100644
index 0000000..84e37c1
--- /dev/null
+++ b/libfspotraw/LibRaw/Makefile.msvc
@@ -0,0 +1,93 @@
+
+SAMPLES=bin\raw-identify.exe bin\simple_dcraw.exe  bin\dcraw_emu.exe bin\dcraw_half.exe bin\half_mt.exe bin\mem_image.exe bin\unprocessed_raw.exe bin\4channels.exe
+
+LIBSTATIC=lib\libraw_static.lib
+DLL=bin\libraw.dll
+LIBDLL=lib\libraw.lib
+
+all: $(DLL) $(SAMPLES) $(LIBSTATIC) 
+
+# Guess LIBPATH from $INCLUDE
+
+LIB_OBJECTS=object\dcraw_common_st.obj object\dcraw_fileio_st.obj object\foveon_st.obj object\libraw_cxx_st.obj object\libraw_c_api_st.obj
+DLL_OBJECTS=object\dcraw_common.obj object\dcraw_fileio.obj object\foveon.obj object\libraw_cxx.obj object\libraw_c_api.obj
+
+CC=cl.exe
+COPT=/EHsc /MT /I. /DWIN32 /O2 /W0 /nologo
+
+LINKLIB=$(LIBDLL)
+
+# Samples - default to dynamic (DLL) link, uncomment next lines 
+#CFLAGS2=/DLIBRAW_NODLL
+#LINKLIB=$(LIBSTATIC)
+
+bin\raw-identify.exe: $(LINKLIB) samples\raw-identify.cpp
+	$(CC) $(COPT) $(CFLAGS2) /Fe"bin\\raw-identify.exe" /Fo"object\\" samples\raw-identify.cpp $(LINKLIB)
+
+bin\unprocessed_raw.exe: $(LINKLIB) samples\unprocessed_raw.cpp
+	$(CC) $(COPT) $(CFLAGS2) /Fe"bin\\unprocessed_raw.exe" /Fo"object\\" samples\unprocessed_raw.cpp $(LINKLIB)
+
+bin\4channels.exe: $(LINKLIB) samples\4channels.cpp
+	$(CC) $(COPT) $(CFLAGS2) /Fe"bin\\4channels.exe" /Fo"object\\" samples\4channels.cpp $(LINKLIB)
+
+bin\simple_dcraw.exe: $(LINKLIB) samples\simple_dcraw.cpp
+	$(CC) $(COPT) $(CFLAGS2) /Fe"bin\\simple_dcraw.exe" /Fo"object\\" samples\simple_dcraw.cpp $(LINKLIB)
+
+bin\mem_image.exe: $(LINKLIB) samples\mem_image.cpp
+	$(CC) $(COPT) $(CFLAGS2) /Fe"bin\\mem_image.exe" /Fo"object\\" samples\mem_image.cpp $(LINKLIB)
+
+bin\dcraw_emu.exe: $(LINKLIB) samples\dcraw_emu.cpp
+	$(CC) $(COPT) $(CFLAGS2) /Fe"bin\\dcraw_emu.exe" /Fo"object\\" samples\dcraw_emu.cpp $(LINKLIB)
+
+bin\dcraw_half.exe: $(LINKLIB) samples\dcraw_half.c
+	$(CC) $(COPT) $(CFLAGS2) /Fe"bin\\dcraw_half.exe" /Fo"object\\" samples\dcraw_half.c $(LINKLIB)
+
+bin\half_mt.exe: $(LINKLIB) samples\half_mt_win32.c
+	$(CC) $(COPT) $(CFLAGS2) /Fe"bin\\half_mt.exe" /Fo"object\\" samples\half_mt_win32.c $(LINKLIB)
+
+# DLL build
+
+$(DLL): $(DLL_OBJECTS)
+	-del /f $(DLL) $(LIBDLL)
+	cl $(COPT) /LD $(DLL_OBJECTS) /link /out:"$(DLL)" /implib:"$(LIBDLL)"
+
+object\dcraw_common.obj: internal\dcraw_common.cpp
+	$(CC) $(COPT) /DLIBRAW_BUILDLIB /Fo"object\\dcraw_common.obj" /c internal\dcraw_common.cpp
+
+object\dcraw_fileio.obj: internal\dcraw_fileio.cpp
+	$(CC) $(COPT) /DLIBRAW_BUILDLIB /Fo"object\\dcraw_fileio.obj" /c internal\dcraw_fileio.cpp
+
+object\foveon.obj: internal\foveon.cpp
+	$(CC) $(COPT) /DLIBRAW_BUILDLIB /Fo"object\\foveon.obj" /c internal\foveon.cpp
+
+object\libraw_cxx.obj: src\libraw_cxx.cpp
+	$(CC) $(COPT) /DLIBRAW_BUILDLIB /Fo"object\\libraw_cxx.obj" /c src\libraw_cxx.cpp
+
+object\libraw_c_api.obj: src\libraw_c_api.cpp
+	$(CC) $(COPT) /DLIBRAW_BUILDLIB /Fo"object\\libraw_c_api.obj" /c src\libraw_c_api.cpp
+
+
+# LIBRARY BUILD
+$(LIBSTATIC): $(LIB_OBJECTS)
+        -del /f $(LIBSTATIC)
+	lib /OUT:$(LIBSTATIC) /LTCG $(LIB_OBJECTS)
+
+object\dcraw_common_st.obj: internal\dcraw_common.cpp
+	$(CC) $(COPT) /DLIBRAW_NODLL /Fo"object\\dcraw_common_st.obj" /c internal\dcraw_common.cpp
+
+object\dcraw_fileio_st.obj: internal\dcraw_fileio.cpp
+	$(CC) $(COPT) /DLIBRAW_NODLL /Fo"object\\dcraw_fileio_st.obj" /c internal\dcraw_fileio.cpp
+
+object\foveon_st.obj: internal\foveon.cpp
+	$(CC) $(COPT) /DLIBRAW_NODLL /Fo"object\\foveon_st.obj" /c internal\foveon.cpp
+
+object\libraw_cxx_st.obj: src\libraw_cxx.cpp
+	$(CC) $(COPT) /DLIBRAW_NODLL /Fo"object\\libraw_cxx_st.obj" /c src\libraw_cxx.cpp
+
+object\libraw_c_api_st.obj: src\libraw_c_api.cpp
+	$(CC) $(COPT) /DLIBRAW_NODLL /Fo"object\\libraw_c_api_st.obj" /c src\libraw_c_api.cpp
+
+clean:
+	-del $(LIBSTATIC) $(LIBDLL) lib\*.exp
+	-del $(LIB_OBJECTS) $(LIB_OBJECTS)
+	-del $(DLL) $(SAMPLES)
\ No newline at end of file
diff --git a/libfspotraw/LibRaw/bin/.keep_me b/libfspotraw/LibRaw/bin/.keep_me
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/libfspotraw/LibRaw/bin/.keep_me
@@ -0,0 +1,2 @@
+
+
diff --git a/libfspotraw/LibRaw/dcraw/dcraw.c b/libfspotraw/LibRaw/dcraw/dcraw.c
new file mode 100644
index 0000000..ba40720
--- /dev/null
+++ b/libfspotraw/LibRaw/dcraw/dcraw.c
@@ -0,0 +1,8713 @@
+/*
+   dcraw.c -- Dave Coffin's raw photo decoder
+   Copyright 1997-2009 by Dave Coffin, dcoffin a cybercom o net
+
+   This is a command-line ANSI C program to convert raw photos from
+   any digital camera on any computer running any operating system.
+
+   No license is required to download and use dcraw.c.  However,
+   to lawfully redistribute dcraw, you must either (a) offer, at
+   no extra charge, full source code* for all executable files
+   containing RESTRICTED functions, (b) distribute this code under
+   the GPL Version 2 or later, (c) remove all RESTRICTED functions,
+   re-implement them, or copy them from an earlier, unrestricted
+   Revision of dcraw.c, or (d) purchase a license from the author.
+
+   The functions that process Foveon images have been RESTRICTED
+   since Revision 1.237.  All other code remains free for all uses.
+
+   *If you have not modified dcraw.c in any way, a link to my
+   homepage qualifies as "full source code".
+
+   $Revision: 1.423 $
+   $Date: 2009/05/15 03:35:39 $
+ */
+
+#define VERSION "8.94"
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#define _USE_MATH_DEFINES
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+/*
+   NO_JPEG disables decoding of compressed Kodak DC120 files.
+   NO_LCMS disables the "-p" option.
+ */
+#ifndef NO_JPEG
+#include <jpeglib.h>
+#endif
+#ifndef NO_LCMS
+#include <lcms.h>
+#endif
+#ifdef LOCALEDIR
+#include <libintl.h>
+#define _(String) gettext(String)
+#else
+#define _(String) (String)
+#endif
+#ifdef DJGPP
+#define fseeko fseek
+#define ftello ftell
+#else
+#define fgetc getc_unlocked
+#endif
+#ifdef __CYGWIN__
+#include <io.h>
+#endif
+#ifdef WIN32
+#include <sys/utime.h>
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+#define snprintf _snprintf
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+typedef __int64 INT64;
+typedef unsigned __int64 UINT64;
+#else
+#include <unistd.h>
+#include <utime.h>
+#include <netinet/in.h>
+typedef long long INT64;
+typedef unsigned long long UINT64;
+#endif
+
+#ifdef LJPEG_DECODE
+#error Please compile dcraw.c by itself.
+#error Do not link it with ljpeg_decode.
+#endif
+
+#ifndef LONG_BIT
+#define LONG_BIT (8 * sizeof (long))
+#endif
+
+#define ushort UshORt
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+
+/*
+   All global variables are defined here, and all functions that
+   access them are prefixed with "CLASS".  Note that a thread-safe
+   C++ class cannot have non-const static local variables.
+ */
+FILE *ifp, *ofp;
+short order;
+const char *ifname;
+char *meta_data;
+char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64];
+float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len;
+time_t timestamp;
+unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id;
+off_t    strip_offset, data_offset;
+off_t    thumb_offset, meta_offset, profile_offset;
+unsigned thumb_length, meta_length, profile_length;
+unsigned thumb_misc, *oprof, fuji_layout, shot_select=0, multi_out=0;
+unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress;
+unsigned black, maximum, mix_green, raw_color, zero_is_bad;
+unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error;
+unsigned tile_width, tile_length, gpsdata[32], load_flags;
+ushort raw_height, raw_width, height, width, top_margin, left_margin;
+ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height;
+int flip, tiff_flip, colors;
+double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 };
+ushort (*image)[4], white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4];
+float bright=1, user_mul[4]={0,0,0,0}, threshold=0;
+int half_size=0, four_color_rgb=0, document_mode=0, highlight=0;
+int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1;
+int output_color=1, output_bps=8, output_tiff=0, med_passes=0;
+int no_auto_bright=0;
+unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX };
+float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4];
+const double xyz_rgb[3][3] = {			/* XYZ from RGB */
+  { 0.412453, 0.357580, 0.180423 },
+  { 0.212671, 0.715160, 0.072169 },
+  { 0.019334, 0.119193, 0.950227 } };
+const float d65_white[3] = { 0.950456, 1, 1.088754 };
+int histogram[4][0x2000];
+void (*write_thumb)(), (*write_fun)();
+void (*load_raw)(), (*thumb_load_raw)();
+jmp_buf failure;
+
+struct decode {
+  struct decode *branch[2];
+  int leaf;
+} first_decode[2048], *second_decode, *free_decode;
+
+struct tiff_ifd {
+  int width, height, bps, comp, phint, offset, flip, samples, bytes;
+} tiff_ifd[10];
+
+struct ph1 {
+  int format, key_off, black, black_off, split_col, tag_21a;
+  float tag_210;
+} ph1;
+
+#define CLASS
+
+#define FORC(cnt) for (c=0; c < cnt; c++)
+#define FORC3 FORC(3)
+#define FORC4 FORC(4)
+#define FORCC FORC(colors)
+
+#define SQR(x) ((x)*(x))
+#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define LIM(x,min,max) MAX(min,MIN(x,max))
+#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
+#define CLIP(x) LIM(x,0,65535)
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+
+/*
+   In order to inline this calculation, I make the risky
+   assumption that all filter patterns can be described
+   by a repeating pattern of eight rows and two columns
+
+   Do not use the FC or BAYER macros with the Leaf CatchLight,
+   because its pattern is 16x16, not 2x8.
+
+   Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2
+
+	PowerShot 600	PowerShot A50	PowerShot Pro70	Pro90 & G1
+	0xe1e4e1e4:	0x1b4e4b1e:	0x1e4b4e1b:	0xb4b4b4b4:
+
+	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5
+	0 G M G M G M	0 C Y C Y C Y	0 Y C Y C Y C	0 G M G M G M
+	1 C Y C Y C Y	1 M G M G M G	1 M G M G M G	1 Y C Y C Y C
+	2 M G M G M G	2 Y C Y C Y C	2 C Y C Y C Y
+	3 C Y C Y C Y	3 G M G M G M	3 G M G M G M
+			4 C Y C Y C Y	4 Y C Y C Y C
+	PowerShot A5	5 G M G M G M	5 G M G M G M
+	0x1e4e1e4e:	6 Y C Y C Y C	6 C Y C Y C Y
+			7 M G M G M G	7 M G M G M G
+	  0 1 2 3 4 5
+	0 C Y C Y C Y
+	1 G M G M G M
+	2 C Y C Y C Y
+	3 M G M G M G
+
+   All RGB cameras use one of these Bayer grids:
+
+	0x16161616:	0x61616161:	0x49494949:	0x94949494:
+
+	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5
+	0 B G B G B G	0 G R G R G R	0 G B G B G B	0 R G R G R G
+	1 G R G R G R	1 B G B G B G	1 R G R G R G	1 G B G B G B
+	2 B G B G B G	2 G R G R G R	2 G B G B G B	2 R G R G R G
+	3 G R G R G R	3 B G B G B G	3 R G R G R G	3 G B G B G B
+ */
+
+#define FC(row,col) \
+	(filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
+
+#define BAYER(row,col) \
+	image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)]
+
+#define BAYER2(row,col) \
+	image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)]
+
+int CLASS fc (int row, int col)
+{
+  static const char filter[16][16] =
+  { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
+    { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
+    { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
+    { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
+    { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
+    { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
+    { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
+    { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
+    { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
+    { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
+    { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
+    { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
+    { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
+    { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
+    { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
+    { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
+
+  if (filters != 1) return FC(row,col);
+  return filter[(row+top_margin) & 15][(col+left_margin) & 15];
+}
+
+#ifndef __GLIBC__
+char *my_memmem (char *haystack, size_t haystacklen,
+	      char *needle, size_t needlelen)
+{
+  char *c;
+  for (c = haystack; c <= haystack + haystacklen - needlelen; c++)
+    if (!memcmp (c, needle, needlelen))
+      return c;
+  return 0;
+}
+#define memmem my_memmem
+#endif
+
+void CLASS merror (void *ptr, const char *where)
+{
+  if (ptr) return;
+  fprintf (stderr,_("%s: Out of memory in %s\n"), ifname, where);
+  longjmp (failure, 1);
+}
+
+void CLASS derror()
+{
+  if (!data_error) {
+    fprintf (stderr, "%s: ", ifname);
+    if (feof(ifp))
+      fprintf (stderr,_("Unexpected end of file\n"));
+    else
+      fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp));
+  }
+  data_error = 1;
+}
+
+ushort CLASS sget2 (uchar *s)
+{
+  if (order == 0x4949)		/* "II" means little-endian */
+    return s[0] | s[1] << 8;
+  else				/* "MM" means big-endian */
+    return s[0] << 8 | s[1];
+}
+
+ushort CLASS get2()
+{
+  uchar str[2] = { 0xff,0xff };
+  fread (str, 1, 2, ifp);
+  return sget2(str);
+}
+
+unsigned CLASS sget4 (uchar *s)
+{
+  if (order == 0x4949)
+    return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
+  else
+    return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
+}
+#define sget4(s) sget4((uchar *)s)
+
+unsigned CLASS get4()
+{
+  uchar str[4] = { 0xff,0xff,0xff,0xff };
+  fread (str, 1, 4, ifp);
+  return sget4(str);
+}
+
+unsigned CLASS getint (int type)
+{
+  return type == 3 ? get2() : get4();
+}
+
+float CLASS int_to_float (int i)
+{
+  union { int i; float f; } u;
+  u.i = i;
+  return u.f;
+}
+
+double CLASS getreal (int type)
+{
+  union { char c[8]; double d; } u;
+  int i, rev;
+
+  switch (type) {
+    case 3: return (unsigned short) get2();
+    case 4: return (unsigned int) get4();
+    case 5:  u.d = (unsigned int) get4();
+      return u.d / (unsigned int) get4();
+    case 8: return (signed short) get2();
+    case 9: return (signed int) get4();
+    case 10: u.d = (signed int) get4();
+      return u.d / (signed int) get4();
+    case 11: return int_to_float (get4());
+    case 12:
+      rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234));
+      for (i=0; i < 8; i++)
+	u.c[i ^ rev] = fgetc(ifp);
+      return u.d;
+    default: return fgetc(ifp);
+  }
+}
+
+void CLASS read_shorts (ushort *pixel, int count)
+{
+  if (fread (pixel, 2, count, ifp) < count) derror();
+  if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
+    swab (pixel, pixel, count*2);
+}
+
+void CLASS canon_black (double dark[2], int nblack)
+{
+  int c, diff, row, col;
+
+  if (!nblack) return;
+  FORC(2) dark[c] /= nblack >> 1;
+  if ((diff = dark[0] - dark[1]))
+    for (row=0; row < height; row++)
+      for (col=1; col < width; col+=2)
+	BAYER(row,col) += diff;
+  dark[1] += diff;
+  black = (dark[0] + dark[1] + 1) / 2;
+}
+
+void CLASS canon_600_fixed_wb (int temp)
+{
+  static const short mul[4][5] = {
+    {  667, 358,397,565,452 },
+    {  731, 390,367,499,517 },
+    { 1119, 396,348,448,537 },
+    { 1399, 485,431,508,688 } };
+  int lo, hi, i;
+  float frac=0;
+
+  for (lo=4; --lo; )
+    if (*mul[lo] <= temp) break;
+  for (hi=0; hi < 3; hi++)
+    if (*mul[hi] >= temp) break;
+  if (lo != hi)
+    frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]);
+  for (i=1; i < 5; i++)
+    pre_mul[i-1] = 1 / (frac * mul[hi][i] + (1-frac) * mul[lo][i]);
+}
+
+/* Return values:  0 = white  1 = near white  2 = not white */
+int CLASS canon_600_color (int ratio[2], int mar)
+{
+  int clipped=0, target, miss;
+
+  if (flash_used) {
+    if (ratio[1] < -104)
+      { ratio[1] = -104; clipped = 1; }
+    if (ratio[1] >   12)
+      { ratio[1] =   12; clipped = 1; }
+  } else {
+    if (ratio[1] < -264 || ratio[1] > 461) return 2;
+    if (ratio[1] < -50)
+      { ratio[1] = -50; clipped = 1; }
+    if (ratio[1] > 307)
+      { ratio[1] = 307; clipped = 1; }
+  }
+  target = flash_used || ratio[1] < 197
+	? -38 - (398 * ratio[1] >> 10)
+	: -123 + (48 * ratio[1] >> 10);
+  if (target - mar <= ratio[0] &&
+      target + 20  >= ratio[0] && !clipped) return 0;
+  miss = target - ratio[0];
+  if (abs(miss) >= mar*4) return 2;
+  if (miss < -20) miss = -20;
+  if (miss > mar) miss = mar;
+  ratio[0] = target - miss;
+  return 1;
+}
+
+void CLASS canon_600_auto_wb()
+{
+  int mar, row, col, i, j, st, count[] = { 0,0 };
+  int test[8], total[2][8], ratio[2][2], stat[2];
+
+  memset (&total, 0, sizeof total);
+  i = canon_ev + 0.5;
+  if      (i < 10) mar = 150;
+  else if (i > 12) mar = 20;
+  else mar = 280 - 20 * i;
+  if (flash_used) mar = 80;
+  for (row=14; row < height-14; row+=4)
+    for (col=10; col < width; col+=2) {
+      for (i=0; i < 8; i++)
+	test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] =
+		    BAYER(row+(i >> 1),col+(i & 1));
+      for (i=0; i < 8; i++)
+	if (test[i] < 150 || test[i] > 1500) goto next;
+      for (i=0; i < 4; i++)
+	if (abs(test[i] - test[i+4]) > 50) goto next;
+      for (i=0; i < 2; i++) {
+	for (j=0; j < 4; j+=2)
+	  ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j];
+	stat[i] = canon_600_color (ratio[i], mar);
+      }
+      if ((st = stat[0] | stat[1]) > 1) goto next;
+      for (i=0; i < 2; i++)
+	if (stat[i])
+	  for (j=0; j < 2; j++)
+	    test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10;
+      for (i=0; i < 8; i++)
+	total[st][i] += test[i];
+      count[st]++;
+next: ;
+    }
+  if (count[0] | count[1]) {
+    st = count[0]*200 < count[1];
+    for (i=0; i < 4; i++)
+      pre_mul[i] = 1.0 / (total[st][i] + total[st][i+4]);
+  }
+}
+
+void CLASS canon_600_coeff()
+{
+  static const short table[6][12] = {
+    { -190,702,-1878,2390,   1861,-1349,905,-393, -432,944,2617,-2105  },
+    { -1203,1715,-1136,1648, 1388,-876,267,245,  -1641,2153,3921,-3409 },
+    { -615,1127,-1563,2075,  1437,-925,509,3,     -756,1268,2519,-2007 },
+    { -190,702,-1886,2398,   2153,-1641,763,-251, -452,964,3040,-2528  },
+    { -190,702,-1878,2390,   1861,-1349,905,-393, -432,944,2617,-2105  },
+    { -807,1319,-1785,2297,  1388,-876,769,-257,  -230,742,2067,-1555  } };
+  int t=0, i, c;
+  float mc, yc;
+
+  mc = pre_mul[1] / pre_mul[2];
+  yc = pre_mul[3] / pre_mul[2];
+  if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1;
+  if (mc > 1.28 && mc <= 2) {
+    if  (yc < 0.8789) t=3;
+    else if (yc <= 2) t=4;
+  }
+  if (flash_used) t=5;
+  for (raw_color = i=0; i < 3; i++)
+    FORCC rgb_cam[i][c] = table[t][i*4 + c] / 1024.0;
+}
+
+void CLASS canon_600_load_raw()
+{
+  uchar  data[1120], *dp;
+  ushort pixel[896], *pix;
+  int irow, row, col, val;
+  static const short mul[4][2] =
+  { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
+
+  for (irow=row=0; irow < height; irow++) {
+    if (fread (data, 1, raw_width*5/4, ifp) < raw_width*5/4) derror();
+    for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) {
+      pix[0] = (dp[0] << 2) + (dp[1] >> 6    );
+      pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
+      pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
+      pix[3] = (dp[4] << 2) + (dp[1]      & 3);
+      pix[4] = (dp[5] << 2) + (dp[9]      & 3);
+      pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3);
+      pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
+      pix[7] = (dp[8] << 2) + (dp[9] >> 6    );
+    }
+    for (col=0; col < width; col++)
+      BAYER(row,col) = pixel[col];
+    for (col=width; col < raw_width; col++)
+      black += pixel[col];
+    if ((row+=2) > height) row = 1;
+  }
+  if (raw_width > width)
+    black = black / ((raw_width - width) * height) - 4;
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++) {
+      if ((val = BAYER(row,col) - black) < 0) val = 0;
+      val = val * mul[row & 3][col & 1] >> 9;
+      BAYER(row,col) = val;
+    }
+  canon_600_fixed_wb(1311);
+  canon_600_auto_wb();
+  canon_600_coeff();
+  maximum = (0x3ff - black) * 1109 >> 9;
+  black = 0;
+}
+
+void CLASS remove_zeroes()
+{
+  unsigned row, col, tot, n, r, c;
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      if (BAYER(row,col) == 0) {
+	tot = n = 0;
+	for (r = row-2; r <= row+2; r++)
+	  for (c = col-2; c <= col+2; c++)
+	    if (r < height && c < width &&
+		FC(r,c) == FC(row,col) && BAYER(r,c))
+	      tot += (n++,BAYER(r,c));
+	if (n) BAYER(row,col) = tot/n;
+      }
+}
+
+int CLASS canon_s2is()
+{
+  unsigned row;
+
+  for (row=0; row < 100; row++) {
+    fseek (ifp, row*3340 + 3284, SEEK_SET);
+    if (getc(ifp) > 15) return 1;
+  }
+  return 0;
+}
+
+void CLASS canon_a5_load_raw()
+{
+  ushort data[2565], *dp, pixel;
+  int vbits=0, buf=0, row, col, bc=0;
+
+  order = 0x4949;
+  for (row=-top_margin; row < raw_height-top_margin; row++) {
+    read_shorts (dp=data, raw_width * 10 / 16);
+    for (col=-left_margin; col < raw_width-left_margin; col++) {
+      if ((vbits -= 10) < 0)
+	buf = (vbits += 16, (buf << 16) + *dp++);
+      pixel = buf >> vbits & 0x3ff;
+      if ((unsigned) row < height && (unsigned) col < width)
+	BAYER(row,col) = pixel;
+      else if (col > 1-left_margin && col != width)
+	black += (bc++,pixel);
+    }
+  }
+  if (bc) black /= bc;
+  maximum = 0x3ff;
+  if (raw_width > 1600) remove_zeroes();
+}
+
+/*
+   getbits(-1) initializes the buffer
+   getbits(n) where 0 <= n <= 25 returns an n-bit integer
+ */
+unsigned CLASS getbits (int nbits)
+{
+  static unsigned bitbuf=0;
+  static int vbits=0, reset=0;
+  unsigned c;
+
+  if (nbits == -1)
+    return bitbuf = vbits = reset = 0;
+  if (nbits == 0 || reset) return 0;
+  while (vbits < nbits) {
+    if ((c = fgetc(ifp)) == EOF) derror();
+    if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) return 0;
+    bitbuf = (bitbuf << 8) + (uchar) c;
+    vbits += 8;
+  }
+  vbits -= nbits;
+  return bitbuf << (32-nbits-vbits) >> (32-nbits);
+}
+
+void CLASS init_decoder()
+{
+  memset (first_decode, 0, sizeof first_decode);
+  free_decode = first_decode;
+}
+
+/*
+   Construct a decode tree according the specification in *source.
+   The first 16 bytes specify how many codes should be 1-bit, 2-bit
+   3-bit, etc.  Bytes after that are the leaf values.
+
+   For example, if the source is
+
+    { 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  },
+
+   then the code is
+
+	00		0x04
+	010		0x03
+	011		0x05
+	100		0x06
+	101		0x02
+	1100		0x07
+	1101		0x01
+	11100		0x08
+	11101		0x09
+	11110		0x00
+	111110		0x0a
+	1111110		0x0b
+	1111111		0xff
+ */
+uchar * CLASS make_decoder (const uchar *source, int level)
+{
+  struct decode *cur;
+  static int leaf;
+  int i, next;
+
+  if (level==0) leaf=0;
+  cur = free_decode++;
+  if (free_decode > first_decode+2048) {
+    fprintf (stderr,_("%s: decoder table overflow\n"), ifname);
+    longjmp (failure, 2);
+  }
+  for (i=next=0; i <= leaf && next < 16; )
+    i += source[next++];
+  if (i > leaf) {
+    if (level < next) {
+      cur->branch[0] = free_decode;
+      make_decoder (source, level+1);
+      cur->branch[1] = free_decode;
+      make_decoder (source, level+1);
+    } else
+      cur->leaf = source[16 + leaf++];
+  }
+  return (uchar *) source + 16 + leaf;
+}
+
+void CLASS crw_init_tables (unsigned table)
+{
+  static const uchar first_tree[3][29] = {
+    { 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  },
+  };
+  static const uchar second_tree[3][180] = {
+    { 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  }
+  };
+  if (table > 2) table = 2;
+  init_decoder();
+  make_decoder ( first_tree[table], 0);
+  second_decode = free_decode;
+  make_decoder (second_tree[table], 0);
+}
+
+/*
+   Return 0 if the image starts with compressed data,
+   1 if it starts with uncompressed low-order bits.
+
+   In Canon compressed data, 0xff is always followed by 0x00.
+ */
+int CLASS canon_has_lowbits()
+{
+  uchar test[0x4000];
+  int ret=1, i;
+
+  fseek (ifp, 0, SEEK_SET);
+  fread (test, 1, sizeof test, ifp);
+  for (i=540; i < sizeof test - 1; i++)
+    if (test[i] == 0xff) {
+      if (test[i+1]) return 1;
+      ret=0;
+    }
+  return ret;
+}
+
+void CLASS canon_compressed_load_raw()
+{
+  ushort *pixel, *prow;
+  int nblocks, lowbits, i, row, r, col, save, val, nblack=0;
+  unsigned irow, icol;
+  struct decode *decode, *dindex;
+  int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
+  double dark[2] = { 0,0 };
+  uchar c;
+
+  crw_init_tables (tiff_compress);
+  pixel = (ushort *) calloc (raw_width*8, sizeof *pixel);
+  merror (pixel, "canon_compressed_load_raw()");
+  lowbits = canon_has_lowbits();
+  if (!lowbits) maximum = 0x3ff;
+  fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET);
+  zero_after_ff = 1;
+  getbits(-1);
+  for (row=0; row < raw_height; row+=8) {
+    nblocks = MIN (8, raw_height-row) * raw_width >> 6;
+    for (block=0; block < nblocks; block++) {
+      memset (diffbuf, 0, sizeof diffbuf);
+      decode = first_decode;
+      for (i=0; i < 64; i++ ) {
+	for (dindex=decode; dindex->branch[0]; )
+	  dindex = dindex->branch[getbits(1)];
+	leaf = dindex->leaf;
+	decode = second_decode;
+	if (leaf == 0 && i) break;
+	if (leaf == 0xff) continue;
+	i  += leaf >> 4;
+	len = leaf & 15;
+	if (len == 0) continue;
+	diff = getbits(len);
+	if ((diff & (1 << (len-1))) == 0)
+	  diff -= (1 << len) - 1;
+	if (i < 64) diffbuf[i] = diff;
+      }
+      diffbuf[0] += carry;
+      carry = diffbuf[0];
+      for (i=0; i < 64; i++ ) {
+	if (pnum++ % raw_width == 0)
+	  base[0] = base[1] = 512;
+	if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10)
+	  derror();
+      }
+    }
+    if (lowbits) {
+      save = ftell(ifp);
+      fseek (ifp, 26 + row*raw_width/4, SEEK_SET);
+      for (prow=pixel, i=0; i < raw_width*2; i++) {
+	c = fgetc(ifp);
+	for (r=0; r < 8; r+=2, prow++) {
+	  val = (*prow << 2) + ((c >> r) & 3);
+	  if (raw_width == 2672 && val < 512) val += 2;
+	  *prow = val;
+	}
+      }
+      fseek (ifp, save, SEEK_SET);
+    }
+    for (r=0; r < 8; r++) {
+      irow = row - top_margin + r;
+      if (irow >= height) continue;
+      for (col=0; col < raw_width; col++) {
+	icol = col - left_margin;
+	if (icol < width)
+	  BAYER(irow,icol) = pixel[r*raw_width+col];
+	else if (col > 1 && (unsigned) (col-left_margin+2) > width+3)
+	  dark[icol & 1] += (nblack++,pixel[r*raw_width+col]);
+      }
+    }
+  }
+  free (pixel);
+  canon_black (dark, nblack);
+}
+
+/*
+   Not a full implementation of Lossless JPEG, just
+   enough to decode Canon, Kodak and Adobe DNG images.
+ */
+struct jhead {
+  int bits, high, wide, clrs, sraw, psv, restart, vpred[6];
+  struct CLASS decode *huff[6];
+  ushort *row;
+};
+
+int CLASS ljpeg_start (struct jhead *jh, int info_only)
+{
+  int c, tag, len;
+  uchar data[0x10000], *dp;
+
+  if (!info_only) init_decoder();
+  memset (jh, 0, sizeof *jh);
+  FORC(6) jh->huff[c] = free_decode;
+  jh->restart = INT_MAX;
+  fread (data, 2, 1, ifp);
+  if (data[1] != 0xd8) return 0;
+  do {
+    fread (data, 2, 2, ifp);
+    tag =  data[0] << 8 | data[1];
+    len = (data[2] << 8 | data[3]) - 2;
+    if (tag <= 0xff00) return 0;
+    fread (data, 1, len, ifp);
+    switch (tag) {
+      case 0xffc3:
+	jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
+      case 0xffc0:
+	jh->bits = data[0];
+	jh->high = data[1] << 8 | data[2];
+	jh->wide = data[3] << 8 | data[4];
+	jh->clrs = data[5] + jh->sraw;
+	if (len == 9 && !dng_version) getc(ifp);
+	break;
+      case 0xffc4:
+	if (info_only) break;
+	for (dp = data; dp < data+len && *dp < 4; ) {
+	  jh->huff[*dp] = free_decode;
+	  dp = make_decoder (++dp, 0);
+	}
+	break;
+      case 0xffda:
+	jh->psv = data[1+data[0]*2];
+	jh->bits -= data[3+data[0]*2] & 15;
+	break;
+      case 0xffdd:
+	jh->restart = data[0] << 8 | data[1];
+    }
+  } while (tag != 0xffda);
+  if (info_only) return 1;
+  if (jh->sraw) {
+    FORC(4)        jh->huff[2+c] = jh->huff[1];
+    FORC(jh->sraw) jh->huff[1+c] = jh->huff[0];
+  }
+  jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4);
+  merror (jh->row, "ljpeg_start()");
+  return zero_after_ff = 1;
+}
+
+int CLASS ljpeg_diff (struct decode *dindex)
+{
+  int len, diff;
+
+  while (dindex->branch[0])
+    dindex = dindex->branch[getbits(1)];
+  len = dindex->leaf;
+  if (len == 16 && (!dng_version || dng_version >= 0x1010000))
+    return -32768;
+  diff = getbits(len);
+  if ((diff & (1 << (len-1))) == 0)
+    diff -= (1 << len) - 1;
+  return diff;
+}
+
+ushort * CLASS ljpeg_row (int jrow, struct jhead *jh)
+{
+  int col, c, diff, pred, spred=0;
+  ushort mark=0, *row[3];
+
+  if (jrow * jh->wide % jh->restart == 0) {
+    FORC(6) jh->vpred[c] = 1 << (jh->bits-1);
+    if (jrow)
+      do mark = (mark << 8) + (c = fgetc(ifp));
+      while (c != EOF && mark >> 4 != 0xffd);
+    getbits(-1);
+  }
+  FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
+  for (col=0; col < jh->wide; col++)
+    FORC(jh->clrs) {
+      diff = ljpeg_diff (jh->huff[c]);
+      if (jh->sraw && c <= jh->sraw && (col | c))
+		    pred = spred;
+      else if (col) pred = row[0][-jh->clrs];
+      else	    pred = (jh->vpred[c] += diff) - diff;
+      if (jrow && col) switch (jh->psv) {
+	case 1:	break;
+	case 2: pred = row[1][0];					break;
+	case 3: pred = row[1][-jh->clrs];				break;
+	case 4: pred = pred +   row[1][0] - row[1][-jh->clrs];		break;
+	case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1);	break;
+	case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1);	break;
+	case 7: pred = (pred + row[1][0]) >> 1;				break;
+	default: pred = 0;
+      }
+      if ((**row = pred + diff) >> jh->bits) derror();
+      if (c <= jh->sraw) spred = **row;
+      row[0]++; row[1]++;
+    }
+  return row[2];
+}
+
+void CLASS lossless_jpeg_load_raw()
+{
+  int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0, nblack=0;
+  double dark[2] = { 0,0 };
+  struct jhead jh;
+  int min=INT_MAX;
+  ushort *rp;
+
+  if (!ljpeg_start (&jh, 0)) return;
+  jwide = jh.wide * jh.clrs;
+
+  for (jrow=0; jrow < jh.high; jrow++) {
+    rp = ljpeg_row (jrow, &jh);
+    for (jcol=0; jcol < jwide; jcol++) {
+      val = *rp++;
+      if (jh.bits <= 12)
+	val = curve[val & 0xfff];
+      if (cr2_slice[0]) {
+	jidx = jrow*jwide + jcol;
+	i = jidx / (cr2_slice[1]*jh.high);
+	if ((j = i >= cr2_slice[0]))
+		 i  = cr2_slice[0];
+	jidx -= i * (cr2_slice[1]*jh.high);
+	row = jidx / cr2_slice[1+j];
+	col = jidx % cr2_slice[1+j] + i*cr2_slice[1];
+      }
+      if (raw_width == 3984 && (col -= 2) < 0)
+	col += (row--,raw_width);
+      if ((unsigned) (row-top_margin) < height) {
+	if ((unsigned) (col-left_margin) < width) {
+	  BAYER(row-top_margin,col-left_margin) = val;
+	  if (min > val) min = val;
+	} else if (col > 1 && (unsigned) (col-left_margin+2) > width+3)
+	  dark[(col-left_margin) & 1] += (nblack++,val);
+      }
+      if (++col >= raw_width)
+	col = (row++,0);
+    }
+  }
+  free (jh.row);
+  canon_black (dark, nblack);
+  if (!strcasecmp(make,"KODAK"))
+    black = min;
+}
+
+void CLASS canon_sraw_load_raw()
+{
+  struct jhead jh;
+  short *rp=0, (*ip)[4];
+  int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c;
+  int v[3]={0,0,0}, ver, hue;
+  char *cp;
+
+  if (!ljpeg_start (&jh, 0)) return;
+  jwide = (jh.wide >>= 1) * jh.clrs;
+
+  for (ecol=slice=0; slice <= cr2_slice[0]; slice++) {
+    scol = ecol;
+    ecol += cr2_slice[1] * 2 / jh.clrs;
+    if (!cr2_slice[0] || ecol > raw_width-1) ecol = raw_width & -2;
+    for (row=0; row < height; row += (jh.clrs >> 1) - 1) {
+      ip = (short (*)[4]) image + row*width;
+      for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) {
+	if ((jcol %= jwide) == 0)
+	  rp = (short *) ljpeg_row (jrow++, &jh);
+	if (col >= width) continue;
+	FORC (jh.clrs-2)
+	  ip[col + (c >> 1)*width + (c & 1)][0] = rp[jcol+c];
+	ip[col][1] = rp[jcol+jh.clrs-2] - 16384;
+	ip[col][2] = rp[jcol+jh.clrs-1] - 16384;
+      }
+    }
+  }
+  for (cp=model2; *cp && !isdigit(*cp); cp++);
+  sscanf (cp, "%d.%d.%d", v, v+1, v+2);
+  ver = (v[0]*1000 + v[1])*1000 + v[2];
+  hue = (jh.sraw+1) << 2;
+  if (unique_id == 0x80000218 && ver > 1000006 && ver < 3000000)
+    hue = jh.sraw << 1;
+  ip = (short (*)[4]) image;
+  rp = ip[0];
+  for (row=0; row < height; row++, ip+=width) {
+    if (row & (jh.sraw >> 1))
+      for (col=0; col < width; col+=2)
+	for (c=1; c < 3; c++)
+	  if (row == height-1)
+	       ip[col][c] =  ip[col-width][c];
+	  else ip[col][c] = (ip[col-width][c] + ip[col+width][c] + 1) >> 1;
+    for (col=1; col < width; col+=2)
+      for (c=1; c < 3; c++)
+	if (col == width-1)
+	     ip[col][c] =  ip[col-1][c];
+	else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
+  }
+  for ( ; rp < ip[0]; rp+=4) {
+    if (unique_id < 0x80000200) {
+      pix[0] = rp[0] + rp[2] - 512;
+      pix[2] = rp[0] + rp[1] - 512;
+      pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12) - 512;
+    } else {
+      rp[1] = (rp[1] << 2) + hue;
+      rp[2] = (rp[2] << 2) + hue;
+      pix[0] = rp[0] + ((  200*rp[1] + 22929*rp[2]) >> 14);
+      pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14);
+      pix[2] = rp[0] + ((29040*rp[1] -   101*rp[2]) >> 14);
+    }
+    FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
+  }
+  free (jh.row);
+  maximum = 0x3fff;
+}
+
+void CLASS adobe_copy_pixel (int row, int col, ushort **rp)
+{
+  unsigned r, c;
+
+  r = row -= top_margin;
+  c = col -= left_margin;
+  if (is_raw == 2 && shot_select) (*rp)++;
+  if (filters) {
+    if (fuji_width) {
+      r = row + fuji_width - 1 - (col >> 1);
+      c = row + ((col+1) >> 1);
+    }
+    if (r < height && c < width)
+      BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp;
+    *rp += is_raw;
+  } else {
+    if (r < height && c < width)
+      FORC(tiff_samples)
+	image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c];
+    *rp += tiff_samples;
+  }
+  if (is_raw == 2 && shot_select) (*rp)--;
+}
+
+void CLASS adobe_dng_load_raw_lj()
+{
+  unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col;
+  struct jhead jh;
+  ushort *rp;
+
+  while (trow < raw_height) {
+    save = ftell(ifp);
+    if (tile_length < INT_MAX)
+      fseek (ifp, get4(), SEEK_SET);
+    if (!ljpeg_start (&jh, 0)) break;
+    jwide = jh.wide;
+    if (filters) jwide *= jh.clrs;
+    jwide /= is_raw;
+    for (row=col=jrow=0; jrow < jh.high; jrow++) {
+      rp = ljpeg_row (jrow, &jh);
+      for (jcol=0; jcol < jwide; jcol++) {
+	adobe_copy_pixel (trow+row, tcol+col, &rp);
+	if (++col >= tile_width || col >= raw_width)
+	  row += 1 + (col = 0);
+      }
+    }
+    fseek (ifp, save+4, SEEK_SET);
+    if ((tcol += tile_width) >= raw_width)
+      trow += tile_length + (tcol = 0);
+    free (jh.row);
+  }
+}
+
+void CLASS adobe_dng_load_raw_nc()
+{
+  ushort *pixel, *rp;
+  int row, col;
+
+  pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel);
+  merror (pixel, "adobe_dng_load_raw_nc()");
+  for (row=0; row < raw_height; row++) {
+    if (tiff_bps == 16)
+      read_shorts (pixel, raw_width * tiff_samples);
+    else {
+      getbits(-1);
+      for (col=0; col < raw_width * tiff_samples; col++)
+	pixel[col] = getbits(tiff_bps);
+    }
+    for (rp=pixel, col=0; col < raw_width; col++)
+      adobe_copy_pixel (row, col, &rp);
+  }
+  free (pixel);
+}
+
+void CLASS pentax_tree()
+{
+  ushort bit[2][13];
+  struct decode *cur;
+  int c, i, j;
+
+  init_decoder();
+  FORC(13) bit[0][c] = get2();
+  FORC(13) bit[1][c] = fgetc(ifp) & 15;
+  FORC(13) {
+    cur = first_decode;
+    for (i=0; i < bit[1][c]; i++) {
+      j = bit[0][c] >> (11-i) & 1;
+      if (!cur->branch[j]) cur->branch[j] = ++free_decode;
+      cur = cur->branch[j];
+    }
+    cur->leaf = c;
+  }
+}
+
+void CLASS pentax_k10_load_raw()
+{
+  int row, col, diff;
+  ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2];
+
+  getbits(-1);
+  for (row=0; row < height; row++)
+    for (col=0; col < raw_width; col++) {
+      diff = ljpeg_diff (first_decode);
+      if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+      else	   hpred[col & 1] += diff;
+      if (col < width)
+	BAYER(row,col) = hpred[col & 1];
+      if (hpred[col & 1] >> 12) derror();
+    }
+}
+
+void CLASS nikon_compressed_load_raw()
+{
+  static const uchar nikon_tree[][32] = {
+    { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0,	/* 12-bit lossy */
+      5,4,3,6,2,7,1,0,8,9,11,10,12 },
+    { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0,	/* 12-bit lossy after split */
+      0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 },
+    { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,  /* 12-bit lossless */
+      5,4,6,3,7,2,8,1,9,0,10,11,12 },
+    { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0,	/* 14-bit lossy */
+      5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 },
+    { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0,	/* 14-bit lossy after split */
+      8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 },
+    { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0,	/* 14-bit lossless */
+      7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } };
+  struct decode *dindex;
+  ushort ver0, ver1, vpred[2][2], hpred[2], csize;
+  int i, min, max, step=0, huff=0, split=0, row, col, len, shl, diff;
+
+  fseek (ifp, meta_offset, SEEK_SET);
+  ver0 = fgetc(ifp);
+  ver1 = fgetc(ifp);
+  if (ver0 == 0x49 || ver1 == 0x58)
+    fseek (ifp, 2110, SEEK_CUR);
+  if (ver0 == 0x46) huff = 2;
+  if (tiff_bps == 14) huff += 3;
+  read_shorts (vpred[0], 4);
+  max = 1 << tiff_bps & 0x7fff;
+  if ((csize = get2()) > 1)
+    step = max / (csize-1);
+  if (ver0 == 0x44 && ver1 == 0x20 && step > 0) {
+    for (i=0; i < csize; i++)
+      curve[i*step] = get2();
+    for (i=0; i < max; i++)
+      curve[i] = ( curve[i-i%step]*(step-i%step) +
+		   curve[i-i%step+step]*(i%step) ) / step;
+    fseek (ifp, meta_offset+562, SEEK_SET);
+    split = get2();
+  } else if (ver0 != 0x46 && csize <= 0x4001)
+    read_shorts (curve, max=csize);
+  while (curve[max-2] == curve[max-1]) max--;
+  init_decoder();
+  make_decoder (nikon_tree[huff], 0);
+  fseek (ifp, data_offset, SEEK_SET);
+  getbits(-1);
+  for (min=row=0; row < height; row++) {
+    if (split && row == split) {
+      init_decoder();
+      make_decoder (nikon_tree[huff+1], 0);
+      max += (min = 16) << 1;
+    }
+    for (col=0; col < raw_width; col++) {
+      for (dindex=first_decode; dindex->branch[0]; )
+	dindex = dindex->branch[getbits(1)];
+      len = dindex->leaf & 15;
+      shl = dindex->leaf >> 4;
+      diff = ((getbits(len-shl) << 1) + 1) << shl >> 1;
+      if ((diff & (1 << (len-1))) == 0)
+	diff -= (1 << len) - !shl;
+      if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+      else	   hpred[col & 1] += diff;
+      if ((ushort)(hpred[col & 1] + min) >= max) derror();
+      if ((unsigned) (col-left_margin) < width)
+	BAYER(row,col-left_margin) = curve[LIM((short)hpred[col & 1],0,0x3fff)];
+    }
+  }
+}
+
+/*
+   Figure out if a NEF file is compressed.  These fancy heuristics
+   are only needed for the D100, thanks to a bug in some cameras
+   that tags all images as "compressed".
+ */
+int CLASS nikon_is_compressed()
+{
+  uchar test[256];
+  int i;
+
+  fseek (ifp, data_offset, SEEK_SET);
+  fread (test, 1, 256, ifp);
+  for (i=15; i < 256; i+=16)
+    if (test[i]) return 1;
+  return 0;
+}
+
+/*
+   Returns 1 for a Coolpix 995, 0 for anything else.
+ */
+int CLASS nikon_e995()
+{
+  int i, histo[256];
+  const uchar often[] = { 0x00, 0x55, 0xaa, 0xff };
+
+  memset (histo, 0, sizeof histo);
+  fseek (ifp, -2000, SEEK_END);
+  for (i=0; i < 2000; i++)
+    histo[fgetc(ifp)]++;
+  for (i=0; i < 4; i++)
+    if (histo[often[i]] < 200)
+      return 0;
+  return 1;
+}
+
+/*
+   Returns 1 for a Coolpix 2100, 0 for anything else.
+ */
+int CLASS nikon_e2100()
+{
+  uchar t[12];
+  int i;
+
+  fseek (ifp, 0, SEEK_SET);
+  for (i=0; i < 1024; i++) {
+    fread (t, 1, 12, ifp);
+    if (((t[2] & t[4] & t[7] & t[9]) >> 4
+	& t[1] & t[6] & t[8] & t[11] & 3) != 3)
+      return 0;
+  }
+  return 1;
+}
+
+void CLASS nikon_3700()
+{
+  int bits, i;
+  uchar dp[24];
+  static const struct {
+    int bits;
+    char make[12], model[15];
+  } table[] = {
+    { 0x00, "PENTAX",  "Optio 33WR" },
+    { 0x03, "NIKON",   "E3200" },
+    { 0x32, "NIKON",   "E3700" },
+    { 0x33, "OLYMPUS", "C740UZ" } };
+
+  fseek (ifp, 3072, SEEK_SET);
+  fread (dp, 1, 24, ifp);
+  bits = (dp[8] & 3) << 4 | (dp[20] & 3);
+  for (i=0; i < sizeof table / sizeof *table; i++)
+    if (bits == table[i].bits) {
+      strcpy (make,  table[i].make );
+      strcpy (model, table[i].model);
+    }
+}
+
+/*
+   Separates a Minolta DiMAGE Z2 from a Nikon E4300.
+ */
+int CLASS minolta_z2()
+{
+  int i, nz;
+  char tail[424];
+
+  fseek (ifp, -sizeof tail, SEEK_END);
+  fread (tail, 1, sizeof tail, ifp);
+  for (nz=i=0; i < sizeof tail; i++)
+    if (tail[i]) nz++;
+  return nz > 20;
+}
+
+/* Here raw_width is in bytes, not pixels. */
+void CLASS nikon_e900_load_raw()
+{
+  int offset=0, irow, row, col;
+
+  for (irow=0; irow < height; irow++) {
+    row = irow * 2 % height;
+    if (row == 1)
+      offset = - (-offset & -4096);
+    fseek (ifp, offset, SEEK_SET);
+    offset += raw_width;
+    getbits(-1);
+    for (col=0; col < width; col++)
+      BAYER(row,col) = getbits(10);
+  }
+}
+
+/*
+   The Fuji Super CCD is just a Bayer grid rotated 45 degrees.
+ */
+void CLASS fuji_load_raw()
+{
+  ushort *pixel;
+  int wide, row, col, r, c;
+
+  fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+  wide = fuji_width << !fuji_layout;
+  pixel = (ushort *) calloc (wide, sizeof *pixel);
+  merror (pixel, "fuji_load_raw()");
+  for (row=0; row < raw_height; row++) {
+    read_shorts (pixel, wide);
+    fseek (ifp, 2*(raw_width - wide), SEEK_CUR);
+    for (col=0; col < wide; col++) {
+      if (fuji_layout) {
+	r = fuji_width - 1 - col + (row >> 1);
+	c = col + ((row+1) >> 1);
+      } else {
+	r = fuji_width - 1 + row - (col >> 1);
+	c = row + ((col+1) >> 1);
+      }
+      BAYER(r,c) = pixel[col];
+    }
+  }
+  free (pixel);
+}
+
+void CLASS jpeg_thumb();
+
+void CLASS ppm_thumb()
+{
+  char *thumb;
+  thumb_length = thumb_width*thumb_height*3;
+  thumb = (char *) malloc (thumb_length);
+  merror (thumb, "ppm_thumb()");
+  fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+  fread  (thumb, 1, thumb_length, ifp);
+  fwrite (thumb, 1, thumb_length, ofp);
+  free (thumb);
+}
+
+void CLASS layer_thumb()
+{
+  int i, c;
+  char *thumb, map[][4] = { "012","102" };
+
+  colors = thumb_misc >> 5 & 7;
+  thumb_length = thumb_width*thumb_height;
+  thumb = (char *) calloc (colors, thumb_length);
+  merror (thumb, "layer_thumb()");
+  fprintf (ofp, "P%d\n%d %d\n255\n",
+	5 + (colors >> 1), thumb_width, thumb_height);
+  fread (thumb, thumb_length, colors, ifp);
+  for (i=0; i < thumb_length; i++)
+    FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], ofp);
+  free (thumb);
+}
+
+void CLASS rollei_thumb()
+{
+  unsigned i;
+  ushort *thumb;
+
+  thumb_length = thumb_width * thumb_height;
+  thumb = (ushort *) calloc (thumb_length, 2);
+  merror (thumb, "rollei_thumb()");
+  fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+  read_shorts (thumb, thumb_length);
+  for (i=0; i < thumb_length; i++) {
+    putc (thumb[i] << 3, ofp);
+    putc (thumb[i] >> 5  << 2, ofp);
+    putc (thumb[i] >> 11 << 3, ofp);
+  }
+  free (thumb);
+}
+
+void CLASS rollei_load_raw()
+{
+  uchar pixel[10];
+  unsigned iten=0, isix, i, buffer=0, row, col, todo[16];
+
+  isix = raw_width * raw_height * 5 / 8;
+  while (fread (pixel, 1, 10, ifp) == 10) {
+    for (i=0; i < 10; i+=2) {
+      todo[i]   = iten++;
+      todo[i+1] = pixel[i] << 8 | pixel[i+1];
+      buffer    = pixel[i] >> 2 | buffer << 6;
+    }
+    for (   ; i < 16; i+=2) {
+      todo[i]   = isix++;
+      todo[i+1] = buffer >> (14-i)*5;
+    }
+    for (i=0; i < 16; i+=2) {
+      row = todo[i] / raw_width - top_margin;
+      col = todo[i] % raw_width - left_margin;
+      if (row < height && col < width)
+	BAYER(row,col) = (todo[i+1] & 0x3ff);
+    }
+  }
+  maximum = 0x3ff;
+}
+
+int CLASS bayer (unsigned row, unsigned col)
+{
+  return (row < height && col < width) ? BAYER(row,col) : 0;
+}
+
+void CLASS phase_one_flat_field (int is_float, int nc)
+{
+  ushort head[8];
+  unsigned wide, y, x, c, rend, cend, row, col;
+  float *mrow, num, mult[4];
+
+  read_shorts (head, 8);
+  wide = head[2] / head[4];
+  mrow = (float *) calloc (nc*wide, sizeof *mrow);
+  merror (mrow, "phase_one_flat_field()");
+  for (y=0; y < head[3] / head[5]; y++) {
+    for (x=0; x < wide; x++)
+      for (c=0; c < nc; c+=2) {
+	num = is_float ? getreal(11) : get2()/32768.0;
+	if (y==0) mrow[c*wide+x] = num;
+	else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5];
+      }
+    if (y==0) continue;
+    rend = head[1]-top_margin + y*head[5];
+    for (row = rend-head[5]; row < height && row < rend; row++) {
+      for (x=1; x < wide; x++) {
+	for (c=0; c < nc; c+=2) {
+	  mult[c] = mrow[c*wide+x-1];
+	  mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4];
+	}
+	cend = head[0]-left_margin + x*head[4];
+	for (col = cend-head[4]; col < width && col < cend; col++) {
+	  c = nc > 2 ? FC(row,col) : 0;
+	  if (!(c & 1)) {
+	    c = BAYER(row,col) * mult[c];
+	    BAYER(row,col) = LIM(c,0,65535);
+	  }
+	  for (c=0; c < nc; c+=2)
+	    mult[c] += mult[c+1];
+	}
+      }
+      for (x=0; x < wide; x++)
+	for (c=0; c < nc; c+=2)
+	  mrow[c*wide+x] += mrow[(c+1)*wide+x];
+    }
+  }
+  free (mrow);
+}
+
+void CLASS phase_one_correct()
+{
+  unsigned entries, tag, data, save, col, row, type;
+  int len, i, j, k, cip, val[4], dev[4], sum, max;
+  int head[9], diff, mindiff=INT_MAX, off_412=0;
+  static const signed char dir[12][2] =
+    { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0},
+      {-2,-2}, {-2,2}, {2,-2}, {2,2} };
+  float poly[8], num, cfrac, frac, mult[2], *yval[2];
+  ushort *xval[2];
+
+  if (half_size || !meta_length) return;
+  if (verbose) fprintf (stderr,_("Phase One correction...\n"));
+  fseek (ifp, meta_offset, SEEK_SET);
+  order = get2();
+  fseek (ifp, 6, SEEK_CUR);
+  fseek (ifp, meta_offset+get4(), SEEK_SET);
+  entries = get4();  get4();
+  while (entries--) {
+    tag  = get4();
+    len  = get4();
+    data = get4();
+    save = ftell(ifp);
+    fseek (ifp, meta_offset+data, SEEK_SET);
+    if (tag == 0x419) {				/* Polynomial curve */
+      for (get4(), i=0; i < 8; i++)
+	poly[i] = getreal(11);
+      poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1;
+      for (i=0; i < 0x10000; i++) {
+	num = (poly[5]*i + poly[3])*i + poly[1];
+	curve[i] = LIM(num,0,65535);
+      } goto apply;				/* apply to right half */
+    } else if (tag == 0x41a) {			/* Polynomial curve */
+      for (i=0; i < 4; i++)
+	poly[i] = getreal(11);
+      for (i=0; i < 0x10000; i++) {
+	for (num=0, j=4; j--; )
+	  num = num * i + poly[j];
+	curve[i] = LIM(num+i,0,65535);
+      } apply:					/* apply to whole image */
+      for (row=0; row < height; row++)
+	for (col = (tag & 1)*ph1.split_col; col < width; col++)
+	  BAYER(row,col) = curve[BAYER(row,col)];
+    } else if (tag == 0x400) {			/* Sensor defects */
+      while ((len -= 8) >= 0) {
+	col  = get2() - left_margin;
+	row  = get2() - top_margin;
+	type = get2(); get2();
+	if (col >= width) continue;
+	if (type == 131)			/* Bad column */
+	  for (row=0; row < height; row++)
+	    if (FC(row,col) == 1) {
+	      for (sum=i=0; i < 4; i++)
+		sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]);
+	      for (max=i=0; i < 4; i++) {
+		dev[i] = abs((val[i] << 2) - sum);
+		if (dev[max] < dev[i]) max = i;
+	      }
+	      BAYER(row,col) = (sum - val[max])/3.0 + 0.5;
+	    } else {
+	      for (sum=0, i=8; i < 12; i++)
+		sum += bayer (row+dir[i][0], col+dir[i][1]);
+	      BAYER(row,col) = 0.5 + sum * 0.0732233 +
+		(bayer(row,col-2) + bayer(row,col+2)) * 0.3535534;
+	    }
+	else if (type == 129) {			/* Bad pixel */
+	  if (row >= height) continue;
+	  j = (FC(row,col) != 1) * 4;
+	  for (sum=0, i=j; i < j+8; i++)
+	    sum += bayer (row+dir[i][0], col+dir[i][1]);
+	  BAYER(row,col) = (sum + 4) >> 3;
+	}
+      }
+    } else if (tag == 0x401) {			/* All-color flat fields */
+      phase_one_flat_field (1, 2);
+    } else if (tag == 0x416 || tag == 0x410) {
+      phase_one_flat_field (0, 2);
+    } else if (tag == 0x40b) {			/* Red+blue flat field */
+      phase_one_flat_field (0, 4);
+    } else if (tag == 0x412) {
+      fseek (ifp, 36, SEEK_CUR);
+      diff = abs (get2() - ph1.tag_21a);
+      if (mindiff > diff) {
+	mindiff = diff;
+	off_412 = ftell(ifp) - 38;
+      }
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  if (off_412) {
+    fseek (ifp, off_412, SEEK_SET);
+    for (i=0; i < 9; i++) head[i] = get4() & 0x7fff;
+    yval[0] = (float *) calloc (head[1]*head[3] + head[2]*head[4], 6);
+    merror (yval[0], "phase_one_correct()");
+    yval[1] = (float  *) (yval[0] + head[1]*head[3]);
+    xval[0] = (ushort *) (yval[1] + head[2]*head[4]);
+    xval[1] = (ushort *) (xval[0] + head[1]*head[3]);
+    get2();
+    for (i=0; i < 2; i++)
+      for (j=0; j < head[i+1]*head[i+3]; j++)
+	yval[i][j] = getreal(11);
+    for (i=0; i < 2; i++)
+      for (j=0; j < head[i+1]*head[i+3]; j++)
+	xval[i][j] = get2();
+    for (row=0; row < height; row++)
+      for (col=0; col < width; col++) {
+	cfrac = (float) col * head[3] / raw_width;
+	cfrac -= cip = cfrac;
+	num = BAYER(row,col) * 0.5;
+	for (i=cip; i < cip+2; i++) {
+	  for (k=j=0; j < head[1]; j++)
+	    if (num < xval[0][k = head[1]*i+j]) break;
+	  frac = (j == 0 || j == head[1]) ? 0 :
+		(xval[0][k] - num) / (xval[0][k] - xval[0][k-1]);
+	  mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac);
+	}
+	i = ((mult[0] * (1-cfrac) + mult[1] * cfrac)
+		* (row + top_margin) + num) * 2;
+	BAYER(row,col) = LIM(i,0,65535);
+      }
+    free (yval[0]);
+  }
+}
+
+void CLASS phase_one_load_raw()
+{
+  int row, col, a, b;
+  ushort *pixel, akey, bkey, mask;
+
+  fseek (ifp, ph1.key_off, SEEK_SET);
+  akey = get2();
+  bkey = get2();
+  mask = ph1.format == 1 ? 0x5555:0x1354;
+  fseek (ifp, data_offset + top_margin*raw_width*2, SEEK_SET);
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "phase_one_load_raw()");
+  for (row=0; row < height; row++) {
+    read_shorts (pixel, raw_width);
+    for (col=0; col < raw_width; col+=2) {
+      a = pixel[col+0] ^ akey;
+      b = pixel[col+1] ^ bkey;
+      pixel[col+0] = (a & mask) | (b & ~mask);
+      pixel[col+1] = (b & mask) | (a & ~mask);
+    }
+    for (col=0; col < width; col++)
+      BAYER(row,col) = pixel[col+left_margin];
+  }
+  free (pixel);
+  phase_one_correct();
+}
+
+unsigned CLASS ph1_bits (int nbits)
+{
+  static UINT64 bitbuf=0;
+  static int vbits=0;
+
+  if (nbits == -1)
+    return bitbuf = vbits = 0;
+  if (nbits == 0) return 0;
+  if ((vbits -= nbits) < 0) {
+    bitbuf = bitbuf << 32 | get4();
+    vbits += 32;
+  }
+  return bitbuf << (64-nbits-vbits) >> (64-nbits);
+}
+
+void CLASS phase_one_load_raw_c()
+{
+  static const int length[] = { 8,7,6,9,11,10,5,12,14,13 };
+  int *offset, len[2], pred[2], row, col, i, j;
+  ushort *pixel;
+  short (*black)[2];
+
+  pixel = (ushort *) calloc (raw_width + raw_height*4, 2);
+  merror (pixel, "phase_one_load_raw_c()");
+  offset = (int *) (pixel + raw_width);
+  fseek (ifp, strip_offset, SEEK_SET);
+  for (row=0; row < raw_height; row++)
+    offset[row] = get4();
+  black = (short (*)[2]) offset + raw_height;
+  fseek (ifp, ph1.black_off, SEEK_SET);
+  if (ph1.black_off)
+    read_shorts ((ushort *) black[0], raw_height*2);
+  for (i=0; i < 256; i++)
+    curve[i] = i*i / 3.969 + 0.5;
+  for (row=0; row < raw_height; row++) {
+    fseek (ifp, data_offset + offset[row], SEEK_SET);
+    ph1_bits(-1);
+    pred[0] = pred[1] = 0;
+    for (col=0; col < raw_width; col++) {
+      if (col >= (raw_width & -8))
+	len[0] = len[1] = 14;
+      else if ((col & 7) == 0)
+	for (i=0; i < 2; i++) {
+	  for (j=0; j < 5 && !ph1_bits(1); j++);
+	  if (j--) len[i] = length[j*2 + ph1_bits(1)];
+	}
+      if ((i = len[col & 1]) == 14)
+	pixel[col] = pred[col & 1] = ph1_bits(16);
+      else
+	pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1));
+      if (pred[col & 1] >> 16) derror();
+      if (ph1.format == 5 && pixel[col] < 256)
+	pixel[col] = curve[pixel[col]];
+    }
+    if ((unsigned) (row-top_margin) < height)
+      for (col=0; col < width; col++) {
+	i = (pixel[col+left_margin] << 2)
+		- ph1.black + black[row][col >= ph1.split_col];
+	if (i > 0) BAYER(row-top_margin,col) = i;
+      }
+  }
+  free (pixel);
+  phase_one_correct();
+  maximum = 0xfffc - ph1.black;
+}
+
+void CLASS hasselblad_load_raw()
+{
+  struct jhead jh;
+  struct decode *dindex;
+  int row, col, pred[2], len[2], diff, i;
+
+  if (!ljpeg_start (&jh, 0)) return;
+  free (jh.row);
+  order = 0x4949;
+  ph1_bits(-1);
+  for (row=-top_margin; row < height; row++) {
+    pred[0] = pred[1] = 0x8000;
+    for (col=-left_margin; col < raw_width-left_margin; col+=2) {
+      for (i=0; i < 2; i++) {
+	for (dindex=jh.huff[0]; dindex->branch[0]; )
+	  dindex = dindex->branch[ph1_bits(1)];
+	len[i] = dindex->leaf;
+      }
+      for (i=0; i < 2; i++) {
+	diff = ph1_bits(len[i]);
+	if ((diff & (1 << (len[i]-1))) == 0)
+	  diff -= (1 << len[i]) - 1;
+	if (diff == 65535) diff = -32768;
+	pred[i] += diff;
+	if (row >= 0 && (unsigned)(col+i) < width)
+	  BAYER(row,col+i) = pred[i];
+      }
+    }
+  }
+  maximum = 0xffff;
+}
+
+void CLASS leaf_hdr_load_raw()
+{
+  ushort *pixel;
+  unsigned tile=0, r, c, row, col;
+
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "leaf_hdr_load_raw()");
+  FORC(tiff_samples)
+    for (r=0; r < raw_height; r++) {
+      if (r % tile_length == 0) {
+	fseek (ifp, data_offset + 4*tile++, SEEK_SET);
+	fseek (ifp, get4() + 2*left_margin, SEEK_SET);
+      }
+      if (filters && c != shot_select) continue;
+      read_shorts (pixel, raw_width);
+      if ((row = r - top_margin) >= height) continue;
+      for (col=0; col < width; col++)
+	if (filters)  BAYER(row,col) = pixel[col];
+	else image[row*width+col][c] = pixel[col];
+    }
+  free (pixel);
+  if (!filters) {
+    maximum = 0xffff;
+    raw_color = 1;
+  }
+}
+
+void CLASS unpacked_load_raw();
+
+void CLASS sinar_4shot_load_raw()
+{
+  ushort *pixel;
+  unsigned shot, row, col, r, c;
+
+  if ((shot = shot_select) || half_size) {
+    if (shot) shot--;
+    if (shot > 3) shot = 3;
+    fseek (ifp, data_offset + shot*4, SEEK_SET);
+    fseek (ifp, get4(), SEEK_SET);
+    unpacked_load_raw();
+    return;
+  }
+  free (image);
+  image = (ushort (*)[4])
+	calloc ((iheight=height)*(iwidth=width), sizeof *image);
+  merror (image, "sinar_4shot_load_raw()");
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "sinar_4shot_load_raw()");
+  for (shot=0; shot < 4; shot++) {
+    fseek (ifp, data_offset + shot*4, SEEK_SET);
+    fseek (ifp, get4(), SEEK_SET);
+    for (row=0; row < raw_height; row++) {
+      read_shorts (pixel, raw_width);
+      if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue;
+      for (col=0; col < raw_width; col++) {
+	if ((c = col-left_margin - (shot & 1)) >= width) continue;
+        image[r*width+c][FC(row,col)] = pixel[col];
+      }
+    }
+  }
+  free (pixel);
+  shrink = filters = 0;
+}
+
+void CLASS imacon_full_load_raw()
+{
+  int row, col;
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      read_shorts (image[row*width+col], 3);
+}
+
+void CLASS packed_12_load_raw()
+{
+  int vbits=0, rbits=0, bwide, bite, irow, row, col, val, i;
+  UINT64 bitbuf=0;
+
+  if (raw_width * 2 >= width * 3) {	/* If raw_width is in bytes, */
+    rbits = (bwide = raw_width) * 8;
+    raw_width = raw_width * 2 / 3;	/* convert it to pixels and  */
+    rbits -= raw_width * 12;		/* save the remainder.       */
+  } else bwide = raw_width * 3 / 2;
+  if (load_flags & 1) bwide = bwide * 16 / 15;
+  fseek (ifp, top_margin*bwide, SEEK_CUR);
+  bite = 8 + (load_flags & 24);
+  for (irow=0; irow < height; irow++) {
+    row = irow;
+    if (load_flags & 2 &&
+	(row = irow * 2 % height + irow / (height/2)) == 1 &&
+	load_flags & 4) {
+      if (vbits=0, tiff_compress)
+	fseek (ifp, data_offset - (-width*height*3/4 & -2048), SEEK_SET);
+      else {
+	fseek (ifp, 0, SEEK_END);
+	fseek (ifp, ftell(ifp)/2, SEEK_SET);
+      }
+    }
+    for (col=0; col < raw_width; col++) {
+      for (vbits -= 12; vbits < 0; vbits += bite) {
+	bitbuf <<= bite;
+	for (i=0; i < bite; i+=8)
+	  bitbuf |= (unsigned) (fgetc(ifp) << i);
+      }
+      val = bitbuf << (52-vbits) >> 52;
+      i = (col ^ (bite == 24)) - left_margin;
+      if ((unsigned) i < width)
+	BAYER(row,i) = val << (load_flags >> 6);
+      else if (load_flags & 32)
+	black += val;
+      if (load_flags & 1 && (col % 10) == 9 &&
+	fgetc(ifp) && col < width+left_margin) derror();
+    }
+    vbits -= rbits;
+  }
+  if (load_flags & 32 && raw_width > width)
+    black /= (raw_width - width) * height;
+}
+
+void CLASS unpacked_load_raw()
+{
+  ushort *pixel;
+  int row, col, bits=0;
+
+  while (1 << ++bits < maximum);
+  fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+  pixel = (ushort *) calloc (width, sizeof *pixel);
+  merror (pixel, "unpacked_load_raw()");
+  for (row=0; row < height; row++) {
+    read_shorts (pixel, width);
+    fseek (ifp, 2*(raw_width - width), SEEK_CUR);
+    for (col=0; col < width; col++)
+      if ((BAYER2(row,col) = pixel[col]) >> bits) derror();
+  }
+  free (pixel);
+}
+
+void CLASS nokia_load_raw()
+{
+  uchar  *data,  *dp;
+  ushort *pixel, *pix;
+  int dwide, row, c;
+
+  dwide = raw_width * 5 / 4;
+  data = (uchar *) malloc (dwide + raw_width*2);
+  merror (data, "nokia_load_raw()");
+  pixel = (ushort *) (data + dwide);
+  for (row=0; row < raw_height; row++) {
+    if (fread (data, 1, dwide, ifp) < dwide) derror();
+    for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=5, pix+=4)
+      FORC4 pix[c] = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
+    if (row < top_margin)
+      FORC(width) black += pixel[c];
+    else
+      FORC(width) BAYER(row-top_margin,c) = pixel[c];
+  }
+  free (data);
+  if (top_margin) black /= top_margin * width;
+  maximum = 0x3ff;
+}
+
+unsigned CLASS pana_bits (int nbits)
+{
+  static uchar buf[0x4000];
+  static int vbits;
+  int byte;
+
+  if (!nbits) return vbits=0;
+  if (!vbits) {
+    fread (buf+load_flags, 1, 0x4000-load_flags, ifp);
+    fread (buf, 1, load_flags, ifp);
+  }
+  vbits = (vbits - nbits) & 0x1ffff;
+  byte = vbits >> 3 ^ 0x3ff0;
+  return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits);
+}
+
+void CLASS panasonic_load_raw()
+{
+  int row, col, i, j, sh=0, pred[2], nonz[2];
+
+  pana_bits(0);
+  for (row=0; row < height; row++)
+    for (col=0; col < raw_width; col++) {
+      if ((i = col % 14) == 0)
+	pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
+      if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
+      if (nonz[i & 1]) {
+	if ((j = pana_bits(8))) {
+	  if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
+	       pred[i & 1] &= ~(-1 << sh);
+	  pred[i & 1] += j << sh;
+	}
+      } else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
+	pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
+      if (col < width)
+	if ((BAYER(row,col) = pred[col & 1]) > 4098) derror();
+    }
+}
+
+void CLASS olympus_e410_load_raw()
+{
+  int row, col, nbits, sign, low, high, i, w, n, nw;
+  int acarry[2][3], *carry, pred, diff;
+
+  fseek (ifp, 7, SEEK_CUR);
+  getbits(-1);
+  for (row=0; row < height; row++) {
+    memset (acarry, 0, sizeof acarry);
+    for (col=0; col < raw_width; col++) {
+      carry = acarry[col & 1];
+      i = 2 * (carry[2] < 3);
+      for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++);
+      sign = getbits(1) * -1;
+      low  = getbits(2);
+      for (high=0; high < 12; high++)
+	if (getbits(1)) break;
+      if (high == 12)
+	high = getbits(16-nbits) >> 1;
+      carry[0] = (high << nbits) | getbits(nbits);
+      diff = (carry[0] ^ sign) + carry[1];
+      carry[1] = (diff*3 + carry[1]) >> 5;
+      carry[2] = carry[0] > 16 ? 0 : carry[2]+1;
+      if (col >= width) continue;
+      if (row < 2 && col < 2) pred = 0;
+      else if (row < 2) pred = BAYER(row,col-2);
+      else if (col < 2) pred = BAYER(row-2,col);
+      else {
+	w  = BAYER(row,col-2);
+	n  = BAYER(row-2,col);
+	nw = BAYER(row-2,col-2);
+	if ((w < nw && nw < n) || (n < nw && nw < w)) {
+	  if (ABS(w-nw) > 32 || ABS(n-nw) > 32)
+	    pred = w + n - nw;
+	  else pred = (w + n) >> 1;
+	} else pred = ABS(w-nw) > ABS(n-nw) ? w : n;
+      }
+      if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror();
+    }
+  }
+}
+
+void CLASS minolta_rd175_load_raw()
+{
+  uchar pixel[768];
+  unsigned irow, box, row, col;
+
+  for (irow=0; irow < 1481; irow++) {
+    if (fread (pixel, 1, 768, ifp) < 768) derror();
+    box = irow / 82;
+    row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2);
+    switch (irow) {
+      case 1477: case 1479: continue;
+      case 1476: row = 984; break;
+      case 1480: row = 985; break;
+      case 1478: row = 985; box = 1;
+    }
+    if ((box < 12) && (box & 1)) {
+      for (col=0; col < 1533; col++, row ^= 1)
+	if (col != 1) BAYER(row,col) = (col+1) & 2 ?
+		   pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
+      BAYER(row,1)    = pixel[1]   << 1;
+      BAYER(row,1533) = pixel[765] << 1;
+    } else
+      for (col=row & 1; col < 1534; col+=2)
+	BAYER(row,col) = pixel[col/2] << 1;
+  }
+  maximum = 0xff << 1;
+}
+
+void CLASS casio_qv5700_load_raw()
+{
+  uchar  data[3232],  *dp;
+  ushort pixel[2576], *pix;
+  int row, col;
+
+  for (row=0; row < height; row++) {
+    fread (data, 1, 3232, ifp);
+    for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) {
+      pix[0] = (dp[0] << 2) + (dp[1] >> 6);
+      pix[1] = (dp[1] << 4) + (dp[2] >> 4);
+      pix[2] = (dp[2] << 6) + (dp[3] >> 2);
+      pix[3] = (dp[3] << 8) + (dp[4]     );
+    }
+    for (col=0; col < width; col++)
+      BAYER(row,col) = (pixel[col] & 0x3ff);
+  }
+  maximum = 0x3fc;
+}
+
+void CLASS quicktake_100_load_raw()
+{
+  uchar pixel[484][644];
+  static const short gstep[16] =
+  { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 };
+  static const short rstep[6][4] =
+  { {  -3,-1,1,3  }, {  -5,-1,1,5  }, {  -8,-2,2,8  },
+    { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } };
+  static const short curve[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 };
+  int rb, row, col, sharp, val=0;
+
+  getbits(-1);
+  memset (pixel, 0x80, sizeof pixel);
+  for (row=2; row < height+2; row++) {
+    for (col=2+(row & 1); col < width+2; col+=2) {
+      val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] +
+		pixel[row][col-2]) >> 2) + gstep[getbits(4)];
+      pixel[row][col] = val = LIM(val,0,255);
+      if (col < 4)
+	pixel[row][col-2] = pixel[row+1][~row & 1] = val;
+      if (row == 2)
+	pixel[row-1][col+1] = pixel[row-1][col+3] = val;
+    }
+    pixel[row][col] = val;
+  }
+  for (rb=0; rb < 2; rb++)
+    for (row=2+rb; row < height+2; row+=2)
+      for (col=3-(row & 1); col < width+2; col+=2) {
+	if (row < 4 || col < 4) sharp = 2;
+	else {
+	  val = ABS(pixel[row-2][col] - pixel[row][col-2])
+	      + ABS(pixel[row-2][col] - pixel[row-2][col-2])
+	      + ABS(pixel[row][col-2] - pixel[row-2][col-2]);
+	  sharp = val <  4 ? 0 : val <  8 ? 1 : val < 16 ? 2 :
+		  val < 32 ? 3 : val < 48 ? 4 : 5;
+	}
+	val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1)
+	      + rstep[sharp][getbits(2)];
+	pixel[row][col] = val = LIM(val,0,255);
+	if (row < 4) pixel[row-2][col+2] = val;
+	if (col < 4) pixel[row+2][col-2] = val;
+      }
+  for (row=2; row < height+2; row++)
+    for (col=3-(row & 1); col < width+2; col+=2) {
+      val = ((pixel[row][col-1] + (pixel[row][col] << 2) +
+	      pixel[row][col+1]) >> 1) - 0x100;
+      pixel[row][col] = LIM(val,0,255);
+    }
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      BAYER(row,col) = curve[pixel[row+2][col+2]];
+  maximum = 0x3ff;
+}
+
+const int * CLASS make_decoder_int (const int *source, int level)
+{
+  struct decode *cur;
+
+  cur = free_decode++;
+  if (level < source[0]) {
+    cur->branch[0] = free_decode;
+    source = make_decoder_int (source, level+1);
+    cur->branch[1] = free_decode;
+    source = make_decoder_int (source, level+1);
+  } else {
+    cur->leaf = source[1];
+    source += 2;
+  }
+  return source;
+}
+
+int CLASS radc_token (int tree)
+{
+  int t;
+  static struct decode *dstart[18], *dindex;
+  static const int *s, source[] = {
+    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
+  };
+
+  if (free_decode == first_decode)
+    for (s=source, t=0; t < 18; t++) {
+      dstart[t] = free_decode;
+      s = make_decoder_int (s, 0);
+    }
+  if (tree == 18) {
+    if (kodak_cbpp == 243)
+      return (getbits(6) << 2) + 2;	/* most DC50 photos */
+    else
+      return (getbits(5) << 3) + 4;	/* DC40, Fotoman Pixtura */
+  }
+  for (dindex = dstart[tree]; dindex->branch[0]; )
+    dindex = dindex->branch[getbits(1)];
+  return dindex->leaf;
+}
+
+#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
+
+#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
+: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
+
+void CLASS kodak_radc_load_raw()
+{
+  int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val;
+  short last[3] = { 16,16,16 }, mul[3], buf[3][3][386];
+  static const ushort pt[] =
+    { 0,0, 1280,1344, 2320,3616, 3328,8000, 4095,16383, 65535,16383 };
+
+  for (i=2; i < 12; i+=2)
+    for (c=pt[i-2]; c <= pt[i]; c++)
+      curve[c] = (float)
+	(c-pt[i-2]) / (pt[i]-pt[i-2]) * (pt[i+1]-pt[i-1]) + pt[i-1] + 0.5;
+  init_decoder();
+  getbits(-1);
+  for (i=0; i < sizeof(buf)/sizeof(short); i++)
+    buf[0][0][i] = 2048;
+  for (row=0; row < height; row+=4) {
+    FORC3 mul[c] = getbits(6);
+    FORC3 {
+      val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
+      s = val > 65564 ? 10:12;
+      x = ~(-1 << (s-1));
+      val <<= 12-s;
+      for (i=0; i < sizeof(buf[0])/sizeof(short); i++)
+	buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
+      last[c] = mul[c];
+      for (r=0; r <= !c; r++) {
+	buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7;
+	for (tree=1, col=width/2; col > 0; ) {
+	  if ((tree = radc_token(tree))) {
+	    col -= 2;
+	    if (tree == 8)
+	      FORYX buf[c][y][x] = radc_token(tree+10) * mul[c];
+	    else
+	      FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR;
+	  } else
+	    do {
+	      nreps = (col > 2) ? radc_token(9) + 1 : 1;
+	      for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) {
+		col -= 2;
+		FORYX buf[c][y][x] = PREDICTOR;
+		if (rep & 1) {
+		  step = radc_token(10) << 4;
+		  FORYX buf[c][y][x] += step;
+		}
+	      }
+	    } while (nreps == 9);
+	}
+	for (y=0; y < 2; y++)
+	  for (x=0; x < width/2; x++) {
+	    val = (buf[c][y+1][x] << 4) / mul[c];
+	    if (val < 0) val = 0;
+	    if (c) BAYER(row+y*2+c-1,x*2+2-c) = val;
+	    else   BAYER(row+r*2+y,x*2+y) = val;
+	  }
+	memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
+      }
+    }
+    for (y=row; y < row+4; y++)
+      for (x=0; x < width; x++)
+	if ((x+y) & 1) {
+	  r = x ? x-1 : x+1;
+	  s = x+1 < width ? x+1 : x-1;
+	  val = (BAYER(y,x)-2048)*2 + (BAYER(y,r)+BAYER(y,s))/2;
+	  if (val < 0) val = 0;
+	  BAYER(y,x) = val;
+	}
+  }
+  for (i=0; i < iheight*iwidth*4; i++)
+    image[0][i] = curve[image[0][i]];
+  maximum = 0x3fff;
+}
+
+#undef FORYX
+#undef PREDICTOR
+
+#ifdef NO_JPEG
+void CLASS kodak_jpeg_load_raw() {}
+#else
+
+METHODDEF(boolean)
+fill_input_buffer (j_decompress_ptr cinfo)
+{
+  static uchar jpeg_buffer[4096];
+  size_t nbytes;
+
+  nbytes = fread (jpeg_buffer, 1, 4096, ifp);
+  swab (jpeg_buffer, jpeg_buffer, nbytes);
+  cinfo->src->next_input_byte = jpeg_buffer;
+  cinfo->src->bytes_in_buffer = nbytes;
+  return TRUE;
+}
+
+void CLASS kodak_jpeg_load_raw()
+{
+  struct jpeg_decompress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  JSAMPARRAY buf;
+  JSAMPLE (*pixel)[3];
+  int row, col;
+
+  cinfo.err = jpeg_std_error (&jerr);
+  jpeg_create_decompress (&cinfo);
+  jpeg_stdio_src (&cinfo, ifp);
+  cinfo.src->fill_input_buffer = fill_input_buffer;
+  jpeg_read_header (&cinfo, TRUE);
+  jpeg_start_decompress (&cinfo);
+  if ((cinfo.output_width      != width  ) ||
+      (cinfo.output_height*2   != height ) ||
+      (cinfo.output_components != 3      )) {
+    fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), ifname);
+    jpeg_destroy_decompress (&cinfo);
+    longjmp (failure, 3);
+  }
+  buf = (*cinfo.mem->alloc_sarray)
+		((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1);
+
+  while (cinfo.output_scanline < cinfo.output_height) {
+    row = cinfo.output_scanline * 2;
+    jpeg_read_scanlines (&cinfo, buf, 1);
+    pixel = (JSAMPLE (*)[3]) buf[0];
+    for (col=0; col < width; col+=2) {
+      BAYER(row+0,col+0) = pixel[col+0][1] << 1;
+      BAYER(row+1,col+1) = pixel[col+1][1] << 1;
+      BAYER(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
+      BAYER(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
+    }
+  }
+  jpeg_finish_decompress (&cinfo);
+  jpeg_destroy_decompress (&cinfo);
+  maximum = 0xff << 1;
+}
+#endif
+
+void CLASS kodak_dc120_load_raw()
+{
+  static const int mul[4] = { 162, 192, 187,  92 };
+  static const int add[4] = {   0, 636, 424, 212 };
+  uchar pixel[848];
+  int row, shift, col;
+
+  for (row=0; row < height; row++) {
+    if (fread (pixel, 1, 848, ifp) < 848) derror();
+    shift = row * mul[row & 3] + add[row & 3];
+    for (col=0; col < width; col++)
+      BAYER(row,col) = (ushort) pixel[(col + shift) % 848];
+  }
+  maximum = 0xff;
+}
+
+void CLASS eight_bit_load_raw()
+{
+  uchar *pixel;
+  unsigned row, col, val, lblack=0;
+
+  pixel = (uchar *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "eight_bit_load_raw()");
+  fseek (ifp, top_margin*raw_width, SEEK_CUR);
+  for (row=0; row < height; row++) {
+    if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
+    for (col=0; col < raw_width; col++) {
+      val = curve[pixel[col]];
+      if ((unsigned) (col-left_margin) < width)
+        BAYER(row,col-left_margin) = val;
+      else lblack += val;
+    }
+  }
+  free (pixel);
+  if (raw_width > width+1)
+    black = lblack / ((raw_width - width) * height);
+  if (!strncmp(model,"DC2",3))
+    black = 0;
+  maximum = curve[0xff];
+}
+
+void CLASS kodak_yrgb_load_raw()
+{
+  uchar *pixel;
+  int row, col, y, cb, cr, rgb[3], c;
+
+  pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel);
+  merror (pixel, "kodak_yrgb_load_raw()");
+  for (row=0; row < height; row++) {
+    if (~row & 1)
+      if (fread (pixel, raw_width, 3, ifp) < 3) derror();
+    for (col=0; col < raw_width; col++) {
+      y  = pixel[width*2*(row & 1) + col];
+      cb = pixel[width + (col & -2)]   - 128;
+      cr = pixel[width + (col & -2)+1] - 128;
+      rgb[1] = y-((cb + cr + 2) >> 2);
+      rgb[2] = rgb[1] + cb;
+      rgb[0] = rgb[1] + cr;
+      FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,255)];
+    }
+  }
+  free (pixel);
+  maximum = curve[0xff];
+}
+
+void CLASS kodak_262_load_raw()
+{
+  static const uchar kodak_tree[2][26] =
+  { { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 },
+    { 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } };
+  struct decode *decode[2];
+  uchar *pixel;
+  int *strip, ns, i, row, col, chess, pi=0, pi1, pi2, pred, val;
+
+  init_decoder();
+  for (i=0; i < 2; i++) {
+    decode[i] = free_decode;
+    make_decoder (kodak_tree[i], 0);
+  }
+  ns = (raw_height+63) >> 5;
+  pixel = (uchar *) malloc (raw_width*32 + ns*4);
+  merror (pixel, "kodak_262_load_raw()");
+  strip = (int *) (pixel + raw_width*32);
+  order = 0x4d4d;
+  for (i=0; i < ns; i++)
+    strip[i] = get4();
+  for (row=0; row < raw_height; row++) {
+    if ((row & 31) == 0) {
+      fseek (ifp, strip[row >> 5], SEEK_SET);
+      getbits(-1);
+      pi = 0;
+    }
+    for (col=0; col < raw_width; col++) {
+      chess = (row + col) & 1;
+      pi1 = chess ? pi-2           : pi-raw_width-1;
+      pi2 = chess ? pi-2*raw_width : pi-raw_width+1;
+      if (col <= chess) pi1 = -1;
+      if (pi1 < 0) pi1 = pi2;
+      if (pi2 < 0) pi2 = pi1;
+      if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2;
+      pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1;
+      pixel[pi] = val = pred + ljpeg_diff (decode[chess]);
+      if (val >> 8) derror();
+      val = curve[pixel[pi++]];
+      if ((unsigned) (col-left_margin) < width)
+	BAYER(row,col-left_margin) = val;
+      else black += val;
+    }
+  }
+  free (pixel);
+  if (raw_width > width)
+    black /= (raw_width - width) * height;
+}
+
+int CLASS kodak_65000_decode (short *out, int bsize)
+{
+  uchar c, blen[768];
+  ushort raw[6];
+  INT64 bitbuf=0;
+  int save, bits=0, i, j, len, diff;
+
+  save = ftell(ifp);
+  bsize = (bsize + 3) & -4;
+  for (i=0; i < bsize; i+=2) {
+    c = fgetc(ifp);
+    if ((blen[i  ] = c & 15) > 12 ||
+	(blen[i+1] = c >> 4) > 12 ) {
+      fseek (ifp, save, SEEK_SET);
+      for (i=0; i < bsize; i+=8) {
+	read_shorts (raw, 6);
+	out[i  ] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
+	out[i+1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
+	for (j=0; j < 6; j++)
+	  out[i+2+j] = raw[j] & 0xfff;
+      }
+      return 1;
+    }
+  }
+  if ((bsize & 7) == 4) {
+    bitbuf  = fgetc(ifp) << 8;
+    bitbuf += fgetc(ifp);
+    bits = 16;
+  }
+  for (i=0; i < bsize; i++) {
+    len = blen[i];
+    if (bits < len) {
+      for (j=0; j < 32; j+=8)
+	bitbuf += (INT64) fgetc(ifp) << (bits+(j^8));
+      bits += 32;
+    }
+    diff = bitbuf & (0xffff >> (16-len));
+    bitbuf >>= len;
+    bits -= len;
+    if ((diff & (1 << (len-1))) == 0)
+      diff -= (1 << len) - 1;
+    out[i] = diff;
+  }
+  return 0;
+}
+
+void CLASS kodak_65000_load_raw()
+{
+  short buf[256];
+  int row, col, len, pred[2], ret, i;
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col+=256) {
+      pred[0] = pred[1] = 0;
+      len = MIN (256, width-col);
+      ret = kodak_65000_decode (buf, len);
+      for (i=0; i < len; i++)
+	if ((BAYER(row,col+i) =	curve[ret ? buf[i] :
+		(pred[i & 1] += buf[i])]) >> 12) derror();
+    }
+}
+
+void CLASS kodak_ycbcr_load_raw()
+{
+  short buf[384], *bp;
+  int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
+  ushort *ip;
+
+  for (row=0; row < height; row+=2)
+    for (col=0; col < width; col+=128) {
+      len = MIN (128, width-col);
+      kodak_65000_decode (buf, len*3);
+      y[0][1] = y[1][1] = cb = cr = 0;
+      for (bp=buf, i=0; i < len; i+=2, bp+=2) {
+	cb += bp[4];
+	cr += bp[5];
+	rgb[1] = -((cb + cr + 2) >> 2);
+	rgb[2] = rgb[1] + cb;
+	rgb[0] = rgb[1] + cr;
+	for (j=0; j < 2; j++)
+	  for (k=0; k < 2; k++) {
+	    if ((y[j][k] = y[j][k^1] + *bp++) >> 10) derror();
+	    ip = image[(row+j)*width + col+i+k];
+	    FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
+	  }
+      }
+    }
+}
+
+void CLASS kodak_rgb_load_raw()
+{
+  short buf[768], *bp;
+  int row, col, len, c, i, rgb[3];
+  ushort *ip=image[0];
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col+=256) {
+      len = MIN (256, width-col);
+      kodak_65000_decode (buf, len*3);
+      memset (rgb, 0, sizeof rgb);
+      for (bp=buf, i=0; i < len; i++, ip+=4)
+	FORC3 if ((ip[c] = rgb[c] += *bp++) >> 12) derror();
+    }
+}
+
+void CLASS kodak_thumb_load_raw()
+{
+  int row, col;
+  colors = thumb_misc >> 5;
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      read_shorts (image[row*width+col], colors);
+  maximum = (1 << (thumb_misc & 31)) - 1;
+}
+
+void CLASS sony_decrypt (unsigned *data, int len, int start, int key)
+{
+  static unsigned pad[128], p;
+
+  if (start) {
+    for (p=0; p < 4; p++)
+      pad[p] = key = key * 48828125 + 1;
+    pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
+    for (p=4; p < 127; p++)
+      pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
+    for (p=0; p < 127; p++)
+      pad[p] = htonl(pad[p]);
+  }
+  while (len--)
+    *data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
+}
+
+void CLASS sony_load_raw()
+{
+  uchar head[40];
+  ushort *pixel;
+  unsigned i, key, row, col;
+
+  fseek (ifp, 200896, SEEK_SET);
+  fseek (ifp, (unsigned) fgetc(ifp)*4 - 1, SEEK_CUR);
+  order = 0x4d4d;
+  key = get4();
+  fseek (ifp, 164600, SEEK_SET);
+  fread (head, 1, 40, ifp);
+  sony_decrypt ((unsigned int *) head, 10, 1, key);
+  for (i=26; i-- > 22; )
+    key = key << 8 | head[i];
+  fseek (ifp, data_offset, SEEK_SET);
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "sony_load_raw()");
+  for (row=0; row < height; row++) {
+    if (fread (pixel, 2, raw_width, ifp) < raw_width) derror();
+    sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key);
+    for (col=9; col < left_margin; col++)
+      black += ntohs(pixel[col]);
+    for (col=0; col < width; col++)
+      if ((BAYER(row,col) = ntohs(pixel[col+left_margin])) >> 14)
+	derror();
+  }
+  free (pixel);
+  if (left_margin > 9)
+    black /= (left_margin-9) * height;
+  maximum = 0x3ff0;
+}
+
+void CLASS sony_arw_load_raw()
+{
+  int col, row, len, diff, sum=0;
+
+  getbits(-1);
+  for (col = raw_width; col--; )
+    for (row=0; row < raw_height+1; row+=2) {
+      if (row == raw_height) row = 1;
+      len = 4 - getbits(2);
+      if (len == 3 && getbits(1)) len = 0;
+      if (len == 4)
+	while (len < 17 && !getbits(1)) len++;
+      diff = getbits(len);
+      if ((diff & (1 << (len-1))) == 0)
+	diff -= (1 << len) - 1;
+      if ((sum += diff) >> 12) derror();
+      if (row < height) BAYER(row,col) = sum;
+    }
+}
+
+void CLASS sony_arw2_load_raw()
+{
+  uchar *data, *dp;
+  ushort pix[16];
+  int row, col, val, max, min, imax, imin, sh, bit, i;
+
+  data = (uchar *) malloc (raw_width);
+  merror (data, "sony_arw2_load_raw()");
+  for (row=0; row < height; row++) {
+    fread (data, 1, raw_width, ifp);
+    for (dp=data, col=0; col < width-30; dp+=16) {
+      max = 0x7ff & (val = sget4(dp));
+      min = 0x7ff & val >> 11;
+      imax = 0x0f & val >> 22;
+      imin = 0x0f & val >> 26;
+      for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++);
+      for (bit=30, i=0; i < 16; i++)
+	if      (i == imax) pix[i] = max;
+	else if (i == imin) pix[i] = min;
+	else {
+	  pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
+	  if (pix[i] > 0x7ff) pix[i] = 0x7ff;
+	  bit += 7;
+	}
+      for (i=0; i < 16; i++, col+=2)
+	BAYER(row,col) = curve[pix[i] << 1] >> 1;
+      col -= col & 1 ? 1:31;
+    }
+  }
+  free (data);
+}
+
+#define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1)
+
+/* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */
+void CLASS smal_decode_segment (unsigned seg[2][2], int holes)
+{
+  uchar hist[3][13] = {
+    { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
+    { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
+    { 3, 3, 0, 0, 63,     47,     31,     15,    0 } };
+  int low, high=0xff, carry=0, nbits=8;
+  int s, count, bin, next, i, sym[3];
+  uchar diff, pred[]={0,0};
+  ushort data=0, range=0;
+  unsigned pix, row, col;
+
+  fseek (ifp, seg[0][1]+1, SEEK_SET);
+  getbits(-1);
+  for (pix=seg[0][0]; pix < seg[1][0]; pix++) {
+    for (s=0; s < 3; s++) {
+      data = data << nbits | getbits(nbits);
+      if (carry < 0)
+	carry = (nbits += carry+1) < 1 ? nbits-1 : 0;
+      while (--nbits >= 0)
+	if ((data >> nbits & 0xff) == 0xff) break;
+      if (nbits > 0)
+	  data = ((data & ((1 << (nbits-1)) - 1)) << 1) |
+	((data + (((data & (1 << (nbits-1)))) << 1)) & (-1 << nbits));
+      if (nbits >= 0) {
+	data += getbits(1);
+	carry = nbits - 8;
+      }
+      count = ((((data-range+1) & 0xffff) << 2) - 1) / (high >> 4);
+      for (bin=0; hist[s][bin+5] > count; bin++);
+		low = hist[s][bin+5] * (high >> 4) >> 2;
+      if (bin) high = hist[s][bin+4] * (high >> 4) >> 2;
+      high -= low;
+      for (nbits=0; high << nbits < 128; nbits++);
+      range = (range+low) << nbits;
+      high <<= nbits;
+      next = hist[s][1];
+      if (++hist[s][2] > hist[s][3]) {
+	next = (next+1) & hist[s][0];
+	hist[s][3] = (hist[s][next+4] - hist[s][next+5]) >> 2;
+	hist[s][2] = 1;
+      }
+      if (hist[s][hist[s][1]+4] - hist[s][hist[s][1]+5] > 1) {
+	if (bin < hist[s][1])
+	  for (i=bin; i < hist[s][1]; i++) hist[s][i+5]--;
+	else if (next <= bin)
+	  for (i=hist[s][1]; i < bin; i++) hist[s][i+5]++;
+      }
+      hist[s][1] = next;
+      sym[s] = bin;
+    }
+    diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
+    if (sym[0] & 4)
+      diff = diff ? -diff : 0x80;
+    if (ftell(ifp) + 12 >= seg[1][1])
+      diff = 0;
+    pred[pix & 1] += diff;
+    row = pix / raw_width - top_margin;
+    col = pix % raw_width - left_margin;
+    if (row < height && col < width)
+      BAYER(row,col) = pred[pix & 1];
+    if (!(pix & 1) && HOLE(row)) pix += 2;
+  }
+  maximum = 0xff;
+}
+
+void CLASS smal_v6_load_raw()
+{
+  unsigned seg[2][2];
+
+  fseek (ifp, 16, SEEK_SET);
+  seg[0][0] = 0;
+  seg[0][1] = get2();
+  seg[1][0] = raw_width * raw_height;
+  seg[1][1] = INT_MAX;
+  smal_decode_segment (seg, 0);
+}
+
+int CLASS median4 (int *p)
+{
+  int min, max, sum, i;
+
+  min = max = sum = p[0];
+  for (i=1; i < 4; i++) {
+    sum += p[i];
+    if (min > p[i]) min = p[i];
+    if (max < p[i]) max = p[i];
+  }
+  return (sum - min - max) >> 1;
+}
+
+void CLASS fill_holes (int holes)
+{
+  int row, col, val[4];
+
+  for (row=2; row < height-2; row++) {
+    if (!HOLE(row)) continue;
+    for (col=1; col < width-1; col+=4) {
+      val[0] = BAYER(row-1,col-1);
+      val[1] = BAYER(row-1,col+1);
+      val[2] = BAYER(row+1,col-1);
+      val[3] = BAYER(row+1,col+1);
+      BAYER(row,col) = median4(val);
+    }
+    for (col=2; col < width-2; col+=4)
+      if (HOLE(row-2) || HOLE(row+2))
+	BAYER(row,col) = (BAYER(row,col-2) + BAYER(row,col+2)) >> 1;
+      else {
+	val[0] = BAYER(row,col-2);
+	val[1] = BAYER(row,col+2);
+	val[2] = BAYER(row-2,col);
+	val[3] = BAYER(row+2,col);
+	BAYER(row,col) = median4(val);
+      }
+  }
+}
+
+void CLASS smal_v9_load_raw()
+{
+  unsigned seg[256][2], offset, nseg, holes, i;
+
+  fseek (ifp, 67, SEEK_SET);
+  offset = get4();
+  nseg = fgetc(ifp);
+  fseek (ifp, offset, SEEK_SET);
+  for (i=0; i < nseg*2; i++)
+    seg[0][i] = get4() + data_offset*(i & 1);
+  fseek (ifp, 78, SEEK_SET);
+  holes = fgetc(ifp);
+  fseek (ifp, 88, SEEK_SET);
+  seg[nseg][0] = raw_height * raw_width;
+  seg[nseg][1] = get4() + data_offset;
+  for (i=0; i < nseg; i++)
+    smal_decode_segment (seg+i, holes);
+  if (holes) fill_holes (holes);
+}
+
+/* RESTRICTED code starts here */
+
+void CLASS foveon_decoder (unsigned size, unsigned code)
+{
+  static unsigned huff[1024];
+  struct decode *cur;
+  int i, len;
+
+  if (!code) {
+    for (i=0; i < size; i++)
+      huff[i] = get4();
+    init_decoder();
+  }
+  cur = free_decode++;
+  if (free_decode > first_decode+2048) {
+    fprintf (stderr,_("%s: decoder table overflow\n"), ifname);
+    longjmp (failure, 2);
+  }
+  if (code)
+    for (i=0; i < size; i++)
+      if (huff[i] == code) {
+	cur->leaf = i;
+	return;
+      }
+  if ((len = code >> 27) > 26) return;
+  code = (len+1) << 27 | (code & 0x3ffffff) << 1;
+
+  cur->branch[0] = free_decode;
+  foveon_decoder (size, code);
+  cur->branch[1] = free_decode;
+  foveon_decoder (size, code+1);
+}
+
+void CLASS foveon_thumb()
+{
+  unsigned bwide, row, col, bitbuf=0, bit=1, c, i;
+  char *buf;
+  struct decode *dindex;
+  short pred[3];
+
+  bwide = get4();
+  fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+  if (bwide > 0) {
+    if (bwide < thumb_width*3) return;
+    buf = (char *) malloc (bwide);
+    merror (buf, "foveon_thumb()");
+    for (row=0; row < thumb_height; row++) {
+      fread  (buf, 1, bwide, ifp);
+      fwrite (buf, 3, thumb_width, ofp);
+    }
+    free (buf);
+    return;
+  }
+  foveon_decoder (256, 0);
+
+  for (row=0; row < thumb_height; row++) {
+    memset (pred, 0, sizeof pred);
+    if (!bit) get4();
+    for (bit=col=0; col < thumb_width; col++)
+      FORC3 {
+	for (dindex=first_decode; dindex->branch[0]; ) {
+	  if ((bit = (bit-1) & 31) == 31)
+	    for (i=0; i < 4; i++)
+	      bitbuf = (bitbuf << 8) + fgetc(ifp);
+	  dindex = dindex->branch[bitbuf >> bit & 1];
+	}
+	pred[c] += dindex->leaf;
+	fputc (pred[c], ofp);
+      }
+  }
+}
+
+void CLASS foveon_load_camf()
+{
+  unsigned key, i, val;
+
+  fseek (ifp, meta_offset, SEEK_SET);
+  key = get4();
+  fread (meta_data, 1, meta_length, ifp);
+  for (i=0; i < meta_length; i++) {
+    key = (key * 1597 + 51749) % 244944;
+    val = key * (INT64) 301593171 >> 24;
+    meta_data[i] ^= ((((key << 8) - val) >> 1) + val) >> 17;
+  }
+}
+
+void CLASS foveon_load_raw()
+{
+  struct decode *dindex;
+  short diff[1024];
+  unsigned bitbuf=0;
+  int pred[3], fixed, row, col, bit=-1, c, i;
+
+  fixed = get4();
+  read_shorts ((ushort *) diff, 1024);
+  if (!fixed) foveon_decoder (1024, 0);
+
+  for (row=0; row < height; row++) {
+    memset (pred, 0, sizeof pred);
+    if (!bit && !fixed && atoi(model+2) < 14) get4();
+    for (col=bit=0; col < width; col++) {
+      if (fixed) {
+	bitbuf = get4();
+	FORC3 pred[2-c] += diff[bitbuf >> c*10 & 0x3ff];
+      }
+      else FORC3 {
+	for (dindex=first_decode; dindex->branch[0]; ) {
+	  if ((bit = (bit-1) & 31) == 31)
+	    for (i=0; i < 4; i++)
+	      bitbuf = (bitbuf << 8) + fgetc(ifp);
+	  dindex = dindex->branch[bitbuf >> bit & 1];
+	}
+	pred[c] += diff[dindex->leaf];
+	if (pred[c] >> 16 && ~pred[c] >> 16) derror();
+      }
+      FORC3 image[row*width+col][c] = pred[c];
+    }
+  }
+  if (document_mode)
+    for (i=0; i < height*width*4; i++)
+      if ((short) image[0][i] < 0) image[0][i] = 0;
+  foveon_load_camf();
+}
+
+const char * CLASS foveon_camf_param (const char *block, const char *param)
+{
+  unsigned idx, num;
+  char *pos, *cp, *dp;
+
+  for (idx=0; idx < meta_length; idx += sget4(pos+8)) {
+    pos = meta_data + idx;
+    if (strncmp (pos, "CMb", 3)) break;
+    if (pos[3] != 'P') continue;
+    if (strcmp (block, pos+sget4(pos+12))) continue;
+    cp = pos + sget4(pos+16);
+    num = sget4(cp);
+    dp = pos + sget4(cp+4);
+    while (num--) {
+      cp += 8;
+      if (!strcmp (param, dp+sget4(cp)))
+	return dp+sget4(cp+4);
+    }
+  }
+  return 0;
+}
+
+void * CLASS foveon_camf_matrix (unsigned dim[3], const char *name)
+{
+  unsigned i, idx, type, ndim, size, *mat;
+  char *pos, *cp, *dp;
+  double dsize;
+
+  for (idx=0; idx < meta_length; idx += sget4(pos+8)) {
+    pos = meta_data + idx;
+    if (strncmp (pos, "CMb", 3)) break;
+    if (pos[3] != 'M') continue;
+    if (strcmp (name, pos+sget4(pos+12))) continue;
+    dim[0] = dim[1] = dim[2] = 1;
+    cp = pos + sget4(pos+16);
+    type = sget4(cp);
+    if ((ndim = sget4(cp+4)) > 3) break;
+    dp = pos + sget4(cp+8);
+    for (i=ndim; i--; ) {
+      cp += 12;
+      dim[i] = sget4(cp);
+    }
+    if ((dsize = (double) dim[0]*dim[1]*dim[2]) > meta_length/4) break;
+    mat = (unsigned *) malloc ((size = dsize) * 4);
+    merror (mat, "foveon_camf_matrix()");
+    for (i=0; i < size; i++)
+      if (type && type != 6)
+	mat[i] = sget4(dp + i*4);
+      else
+	mat[i] = sget4(dp + i*2) & 0xffff;
+    return mat;
+  }
+  fprintf (stderr,_("%s: \"%s\" matrix not found!\n"), ifname, name);
+  return 0;
+}
+
+int CLASS foveon_fixed (void *ptr, int size, const char *name)
+{
+  void *dp;
+  unsigned dim[3];
+
+  dp = foveon_camf_matrix (dim, name);
+  if (!dp) return 0;
+  memcpy (ptr, dp, size*4);
+  free (dp);
+  return 1;
+}
+
+float CLASS foveon_avg (short *pix, int range[2], float cfilt)
+{
+  int i;
+  float val, min=FLT_MAX, max=-FLT_MAX, sum=0;
+
+  for (i=range[0]; i <= range[1]; i++) {
+    sum += val = pix[i*4] + (pix[i*4]-pix[(i-1)*4]) * cfilt;
+    if (min > val) min = val;
+    if (max < val) max = val;
+  }
+  if (range[1] - range[0] == 1) return sum/2;
+  return (sum - min - max) / (range[1] - range[0] - 1);
+}
+
+short * CLASS foveon_make_curve (double max, double mul, double filt)
+{
+  short *curve;
+  unsigned i, size;
+  double x;
+
+  if (!filt) filt = 0.8;
+  size = 4*M_PI*max / filt;
+  if (size == UINT_MAX) size--;
+  curve = (short *) calloc (size+1, sizeof *curve);
+  merror (curve, "foveon_make_curve()");
+  curve[0] = size;
+  for (i=0; i < size; i++) {
+    x = i*filt/max/4;
+    curve[i+1] = (cos(x)+1)/2 * tanh(i*filt/mul) * mul + 0.5;
+  }
+  return curve;
+}
+
+void CLASS foveon_make_curves
+	(short **curvep, float dq[3], float div[3], float filt)
+{
+  double mul[3], max=0;
+  int c;
+
+  FORC3 mul[c] = dq[c]/div[c];
+  FORC3 if (max < mul[c]) max = mul[c];
+  FORC3 curvep[c] = foveon_make_curve (max, mul[c], filt);
+}
+
+int CLASS foveon_apply_curve (short *curve, int i)
+{
+  if (abs(i) >= curve[0]) return 0;
+  return i < 0 ? -curve[1-i] : curve[1+i];
+}
+
+#define image ((short (*)[4]) image)
+
+void CLASS foveon_interpolate()
+{
+  static const short hood[] = { -1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1 };
+  short *pix, prev[3], *curve[8], (*shrink)[3];
+  float cfilt=0, ddft[3][3][2], ppm[3][3][3];
+  float cam_xyz[3][3], correct[3][3], last[3][3], trans[3][3];
+  float chroma_dq[3], color_dq[3], diag[3][3], div[3];
+  float (*black)[3], (*sgain)[3], (*sgrow)[3];
+  float fsum[3], val, frow, num;
+  int row, col, c, i, j, diff, sgx, irow, sum, min, max, limit;
+  int dscr[2][2], dstb[4], (*smrow[7])[3], total[4], ipix[3];
+  int work[3][3], smlast, smred, smred_p=0, dev[3];
+  int satlev[3], keep[4], active[4];
+  unsigned dim[3], *badpix;
+  double dsum=0, trsum[3];
+  char str[128];
+  const char* cp;
+
+  if (verbose)
+    fprintf (stderr,_("Foveon interpolation...\n"));
+
+  foveon_fixed (dscr, 4, "DarkShieldColRange");
+  foveon_fixed (ppm[0][0], 27, "PostPolyMatrix");
+  foveon_fixed (satlev, 3, "SaturationLevel");
+  foveon_fixed (keep, 4, "KeepImageArea");
+  foveon_fixed (active, 4, "ActiveImageArea");
+  foveon_fixed (chroma_dq, 3, "ChromaDQ");
+  foveon_fixed (color_dq, 3,
+	foveon_camf_param ("IncludeBlocks", "ColorDQ") ?
+		"ColorDQ" : "ColorDQCamRGB");
+  if (foveon_camf_param ("IncludeBlocks", "ColumnFilter"))
+  		 foveon_fixed (&cfilt, 1, "ColumnFilter");
+
+  memset (ddft, 0, sizeof ddft);
+  if (!foveon_camf_param ("IncludeBlocks", "DarkDrift")
+	 || !foveon_fixed (ddft[1][0], 12, "DarkDrift"))
+    for (i=0; i < 2; i++) {
+      foveon_fixed (dstb, 4, i ? "DarkShieldBottom":"DarkShieldTop");
+      for (row = dstb[1]; row <= dstb[3]; row++)
+	for (col = dstb[0]; col <= dstb[2]; col++)
+	  FORC3 ddft[i+1][c][1] += (short) image[row*width+col][c];
+      FORC3 ddft[i+1][c][1] /= (dstb[3]-dstb[1]+1) * (dstb[2]-dstb[0]+1);
+    }
+
+  if (!(cp = foveon_camf_param ("WhiteBalanceIlluminants", model2)))
+  { fprintf (stderr,_("%s: Invalid white balance \"%s\"\n"), ifname, model2);
+    return; }
+  foveon_fixed (cam_xyz, 9, cp);
+  foveon_fixed (correct, 9,
+	foveon_camf_param ("WhiteBalanceCorrections", model2));
+  memset (last, 0, sizeof last);
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      FORC3 last[i][j] += correct[i][c] * cam_xyz[c][j];
+
+  #define LAST(x,y) last[(i+x)%3][(c+y)%3]
+  for (i=0; i < 3; i++)
+    FORC3 diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1);
+  #undef LAST
+  FORC3 div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583;
+  sprintf (str, "%sRGBNeutral", model2);
+  if (foveon_camf_param ("IncludeBlocks", str))
+    foveon_fixed (div, 3, str);
+  num = 0;
+  FORC3 if (num < div[c]) num = div[c];
+  FORC3 div[c] /= num;
+
+  memset (trans, 0, sizeof trans);
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      FORC3 trans[i][j] += rgb_cam[i][c] * last[c][j] * div[j];
+  FORC3 trsum[c] = trans[c][0] + trans[c][1] + trans[c][2];
+  dsum = (6*trsum[0] + 11*trsum[1] + 3*trsum[2]) / 20;
+  for (i=0; i < 3; i++)
+    FORC3 last[i][c] = trans[i][c] * dsum / trsum[i];
+  memset (trans, 0, sizeof trans);
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      FORC3 trans[i][j] += (i==c ? 32 : -1) * last[c][j] / 30;
+
+  foveon_make_curves (curve, color_dq, div, cfilt);
+  FORC3 chroma_dq[c] /= 3;
+  foveon_make_curves (curve+3, chroma_dq, div, cfilt);
+  FORC3 dsum += chroma_dq[c] / div[c];
+  curve[6] = foveon_make_curve (dsum, dsum, cfilt);
+  curve[7] = foveon_make_curve (dsum*2, dsum*2, cfilt);
+
+  sgain = (float (*)[3]) foveon_camf_matrix (dim, "SpatialGain");
+  if (!sgain) return;
+  sgrow = (float (*)[3]) calloc (dim[1], sizeof *sgrow);
+  sgx = (width + dim[1]-2) / (dim[1]-1);
+
+  black = (float (*)[3]) calloc (height, sizeof *black);
+  for (row=0; row < height; row++) {
+    for (i=0; i < 6; i++)
+      ddft[0][0][i] = ddft[1][0][i] +
+	row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
+    FORC3 black[row][c] =
+ 	( foveon_avg (image[row*width]+c, dscr[0], cfilt) +
+	  foveon_avg (image[row*width]+c, dscr[1], cfilt) * 3
+	  - ddft[0][c][0] ) / 4 - ddft[0][c][1];
+  }
+  memcpy (black, black+8, sizeof *black*8);
+  memcpy (black+height-11, black+height-22, 11*sizeof *black);
+  memcpy (last, black, sizeof last);
+
+  for (row=1; row < height-1; row++) {
+    FORC3 if (last[1][c] > last[0][c]) {
+	if (last[1][c] > last[2][c])
+	  black[row][c] = (last[0][c] > last[2][c]) ? last[0][c]:last[2][c];
+      } else
+	if (last[1][c] < last[2][c])
+	  black[row][c] = (last[0][c] < last[2][c]) ? last[0][c]:last[2][c];
+    memmove (last, last+1, 2*sizeof last[0]);
+    memcpy (last[2], black[row+1], sizeof last[2]);
+  }
+  FORC3 black[row][c] = (last[0][c] + last[1][c])/2;
+  FORC3 black[0][c] = (black[1][c] + black[3][c])/2;
+
+  val = 1 - exp(-1/24.0);
+  memcpy (fsum, black, sizeof fsum);
+  for (row=1; row < height; row++)
+    FORC3 fsum[c] += black[row][c] =
+	(black[row][c] - black[row-1][c])*val + black[row-1][c];
+  memcpy (last[0], black[height-1], sizeof last[0]);
+  FORC3 fsum[c] /= height;
+  for (row = height; row--; )
+    FORC3 last[0][c] = black[row][c] =
+	(black[row][c] - fsum[c] - last[0][c])*val + last[0][c];
+
+  memset (total, 0, sizeof total);
+  for (row=2; row < height; row+=4)
+    for (col=2; col < width; col+=4) {
+      FORC3 total[c] += (short) image[row*width+col][c];
+      total[3]++;
+    }
+  for (row=0; row < height; row++)
+    FORC3 black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0);
+
+  for (row=0; row < height; row++) {
+    for (i=0; i < 6; i++)
+      ddft[0][0][i] = ddft[1][0][i] +
+	row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
+    pix = image[row*width];
+    memcpy (prev, pix, sizeof prev);
+    frow = row / (height-1.0) * (dim[2]-1);
+    if ((irow = frow) == dim[2]-1) irow--;
+    frow -= irow;
+    for (i=0; i < dim[1]; i++)
+      FORC3 sgrow[i][c] = sgain[ irow   *dim[1]+i][c] * (1-frow) +
+			  sgain[(irow+1)*dim[1]+i][c] *    frow;
+    for (col=0; col < width; col++) {
+      FORC3 {
+	diff = pix[c] - prev[c];
+	prev[c] = pix[c];
+	ipix[c] = pix[c] + floor ((diff + (diff*diff >> 14)) * cfilt
+		- ddft[0][c][1] - ddft[0][c][0] * ((float) col/width - 0.5)
+		- black[row][c] );
+      }
+      FORC3 {
+	work[0][c] = ipix[c] * ipix[c] >> 14;
+	work[2][c] = ipix[c] * work[0][c] >> 14;
+	work[1][2-c] = ipix[(c+1) % 3] * ipix[(c+2) % 3] >> 14;
+      }
+      FORC3 {
+	for (val=i=0; i < 3; i++)
+	  for (  j=0; j < 3; j++)
+	    val += ppm[c][i][j] * work[i][j];
+	ipix[c] = floor ((ipix[c] + floor(val)) *
+		( sgrow[col/sgx  ][c] * (sgx - col%sgx) +
+		  sgrow[col/sgx+1][c] * (col%sgx) ) / sgx / div[c]);
+	if (ipix[c] > 32000) ipix[c] = 32000;
+	pix[c] = ipix[c];
+      }
+      pix += 4;
+    }
+  }
+  free (black);
+  free (sgrow);
+  free (sgain);
+
+  if ((badpix = (unsigned int *) foveon_camf_matrix (dim, "BadPixels"))) {
+    for (i=0; i < dim[0]; i++) {
+      col = (badpix[i] >> 8 & 0xfff) - keep[0];
+      row = (badpix[i] >> 20       ) - keep[1];
+      if ((unsigned)(row-1) > height-3 || (unsigned)(col-1) > width-3)
+	continue;
+      memset (fsum, 0, sizeof fsum);
+      for (sum=j=0; j < 8; j++)
+	if (badpix[i] & (1 << j)) {
+	  FORC3 fsum[c] += (short)
+		image[(row+hood[j*2])*width+col+hood[j*2+1]][c];
+	  sum++;
+	}
+      if (sum) FORC3 image[row*width+col][c] = fsum[c]/sum;
+    }
+    free (badpix);
+  }
+
+  /* Array for 5x5 Gaussian averaging of red values */
+  smrow[6] = (int (*)[3]) calloc (width*5, sizeof **smrow);
+  merror (smrow[6], "foveon_interpolate()");
+  for (i=0; i < 5; i++)
+    smrow[i] = smrow[6] + i*width;
+
+  /* Sharpen the reds against these Gaussian averages */
+  for (smlast=-1, row=2; row < height-2; row++) {
+    while (smlast < row+2) {
+      for (i=0; i < 6; i++)
+	smrow[(i+5) % 6] = smrow[i];
+      pix = image[++smlast*width+2];
+      for (col=2; col < width-2; col++) {
+	smrow[4][col][0] =
+	  (pix[0]*6 + (pix[-4]+pix[4])*4 + pix[-8]+pix[8] + 8) >> 4;
+	pix += 4;
+      }
+    }
+    pix = image[row*width+2];
+    for (col=2; col < width-2; col++) {
+      smred = ( 6 *  smrow[2][col][0]
+	      + 4 * (smrow[1][col][0] + smrow[3][col][0])
+	      +      smrow[0][col][0] + smrow[4][col][0] + 8 ) >> 4;
+      if (col == 2)
+	smred_p = smred;
+      i = pix[0] + ((pix[0] - ((smred*7 + smred_p) >> 3)) >> 3);
+      if (i > 32000) i = 32000;
+      pix[0] = i;
+      smred_p = smred;
+      pix += 4;
+    }
+  }
+
+  /* Adjust the brighter pixels for better linearity */
+  min = 0xffff;
+  FORC3 {
+    i = satlev[c] / div[c];
+    if (min > i) min = i;
+  }
+  limit = min * 9 >> 4;
+  for (pix=image[0]; pix < image[height*width]; pix+=4) {
+    if (pix[0] <= limit || pix[1] <= limit || pix[2] <= limit)
+      continue;
+    min = max = pix[0];
+    for (c=1; c < 3; c++) {
+      if (min > pix[c]) min = pix[c];
+      if (max < pix[c]) max = pix[c];
+    }
+    if (min >= limit*2) {
+      pix[0] = pix[1] = pix[2] = max;
+    } else {
+      i = 0x4000 - ((min - limit) << 14) / limit;
+      i = 0x4000 - (i*i >> 14);
+      i = i*i >> 14;
+      FORC3 pix[c] += (max - pix[c]) * i >> 14;
+    }
+  }
+/*
+   Because photons that miss one detector often hit another,
+   the sum R+G+B is much less noisy than the individual colors.
+   So smooth the hues without smoothing the total.
+ */
+  for (smlast=-1, row=2; row < height-2; row++) {
+    while (smlast < row+2) {
+      for (i=0; i < 6; i++)
+	smrow[(i+5) % 6] = smrow[i];
+      pix = image[++smlast*width+2];
+      for (col=2; col < width-2; col++) {
+	FORC3 smrow[4][col][c] = (pix[c-4]+2*pix[c]+pix[c+4]+2) >> 2;
+	pix += 4;
+      }
+    }
+    pix = image[row*width+2];
+    for (col=2; col < width-2; col++) {
+      FORC3 dev[c] = -foveon_apply_curve (curve[7], pix[c] -
+	((smrow[1][col][c] + 2*smrow[2][col][c] + smrow[3][col][c]) >> 2));
+      sum = (dev[0] + dev[1] + dev[2]) >> 3;
+      FORC3 pix[c] += dev[c] - sum;
+      pix += 4;
+    }
+  }
+  for (smlast=-1, row=2; row < height-2; row++) {
+    while (smlast < row+2) {
+      for (i=0; i < 6; i++)
+	smrow[(i+5) % 6] = smrow[i];
+      pix = image[++smlast*width+2];
+      for (col=2; col < width-2; col++) {
+	FORC3 smrow[4][col][c] =
+		(pix[c-8]+pix[c-4]+pix[c]+pix[c+4]+pix[c+8]+2) >> 2;
+	pix += 4;
+      }
+    }
+    pix = image[row*width+2];
+    for (col=2; col < width-2; col++) {
+      for (total[3]=375, sum=60, c=0; c < 3; c++) {
+	for (total[c]=i=0; i < 5; i++)
+	  total[c] += smrow[i][col][c];
+	total[3] += total[c];
+	sum += pix[c];
+      }
+      if (sum < 0) sum = 0;
+      j = total[3] > 375 ? (sum << 16) / total[3] : sum * 174;
+      FORC3 pix[c] += foveon_apply_curve (curve[6],
+		((j*total[c] + 0x8000) >> 16) - pix[c]);
+      pix += 4;
+    }
+  }
+
+  /* Transform the image to a different colorspace */
+  for (pix=image[0]; pix < image[height*width]; pix+=4) {
+    FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]);
+    sum = (pix[0]+pix[1]+pix[1]+pix[2]) >> 2;
+    FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]-sum);
+    FORC3 {
+      for (dsum=i=0; i < 3; i++)
+	dsum += trans[c][i] * pix[i];
+      if (dsum < 0)  dsum = 0;
+      if (dsum > 24000) dsum = 24000;
+      ipix[c] = dsum + 0.5;
+    }
+    FORC3 pix[c] = ipix[c];
+  }
+
+  /* Smooth the image bottom-to-top and save at 1/4 scale */
+  shrink = (short (*)[3]) calloc ((width/4) * (height/4), sizeof *shrink);
+  merror (shrink, "foveon_interpolate()");
+  for (row = height/4; row--; )
+    for (col=0; col < width/4; col++) {
+      ipix[0] = ipix[1] = ipix[2] = 0;
+      for (i=0; i < 4; i++)
+	for (j=0; j < 4; j++)
+	  FORC3 ipix[c] += image[(row*4+i)*width+col*4+j][c];
+      FORC3
+	if (row+2 > height/4)
+	  shrink[row*(width/4)+col][c] = ipix[c] >> 4;
+	else
+	  shrink[row*(width/4)+col][c] =
+	    (shrink[(row+1)*(width/4)+col][c]*1840 + ipix[c]*141 + 2048) >> 12;
+    }
+  /* From the 1/4-scale image, smooth right-to-left */
+  for (row=0; row < (height & ~3); row++) {
+    ipix[0] = ipix[1] = ipix[2] = 0;
+    if ((row & 3) == 0)
+      for (col = width & ~3 ; col--; )
+	FORC3 smrow[0][col][c] = ipix[c] =
+	  (shrink[(row/4)*(width/4)+col/4][c]*1485 + ipix[c]*6707 + 4096) >> 13;
+
+  /* Then smooth left-to-right */
+    ipix[0] = ipix[1] = ipix[2] = 0;
+    for (col=0; col < (width & ~3); col++)
+      FORC3 smrow[1][col][c] = ipix[c] =
+	(smrow[0][col][c]*1485 + ipix[c]*6707 + 4096) >> 13;
+
+  /* Smooth top-to-bottom */
+    if (row == 0)
+      memcpy (smrow[2], smrow[1], sizeof **smrow * width);
+    else
+      for (col=0; col < (width & ~3); col++)
+	FORC3 smrow[2][col][c] =
+	  (smrow[2][col][c]*6707 + smrow[1][col][c]*1485 + 4096) >> 13;
+
+  /* Adjust the chroma toward the smooth values */
+    for (col=0; col < (width & ~3); col++) {
+      for (i=j=30, c=0; c < 3; c++) {
+	i += smrow[2][col][c];
+	j += image[row*width+col][c];
+      }
+      j = (j << 16) / i;
+      for (sum=c=0; c < 3; c++) {
+	ipix[c] = foveon_apply_curve (curve[c+3],
+	  ((smrow[2][col][c] * j + 0x8000) >> 16) - image[row*width+col][c]);
+	sum += ipix[c];
+      }
+      sum >>= 3;
+      FORC3 {
+	i = image[row*width+col][c] + ipix[c] - sum;
+	if (i < 0) i = 0;
+	image[row*width+col][c] = i;
+      }
+    }
+  }
+  free (shrink);
+  free (smrow[6]);
+  for (i=0; i < 8; i++)
+    free (curve[i]);
+
+  /* Trim off the black border */
+  active[1] -= keep[1];
+  active[3] -= 2;
+  i = active[2] - active[0];
+  for (row=0; row < active[3]-active[1]; row++)
+    memcpy (image[row*i], image[(row+active[1])*width+active[0]],
+	 i * sizeof *image);
+  width = i;
+  height = row;
+}
+#undef image
+
+/* RESTRICTED code ends here */
+
+/*
+   Seach from the current directory up to the root looking for
+   a ".badpixels" file, and fix those pixels now.
+ */
+void CLASS bad_pixels (const char *cfname)
+{
+  FILE *fp=0;
+  char *fname, *cp, line[128];
+  int len, time, row, col, r, c, rad, tot, n, fixed=0;
+
+  if (!filters) return;
+  if (cfname)
+    fp = fopen (cfname, "r");
+  else {
+    for (len=32 ; ; len *= 2) {
+      fname = (char *) malloc (len);
+      if (!fname) return;
+      if (getcwd (fname, len-16)) break;
+      free (fname);
+      if (errno != ERANGE) return;
+    }
+#if defined(WIN32) || defined(DJGPP)
+    if (fname[1] == ':')
+      memmove (fname, fname+2, len-2);
+    for (cp=fname; *cp; cp++)
+      if (*cp == '\\') *cp = '/';
+#endif
+    cp = fname + strlen(fname);
+    if (cp[-1] == '/') cp--;
+    while (*fname == '/') {
+      strcpy (cp, "/.badpixels");
+      if ((fp = fopen (fname, "r"))) break;
+      if (cp == fname) break;
+      while (*--cp != '/');
+    }
+    free (fname);
+  }
+  if (!fp) return;
+  while (fgets (line, 128, fp)) {
+    cp = strchr (line, '#');
+    if (cp) *cp = 0;
+    if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue;
+    if ((unsigned) col >= width || (unsigned) row >= height) continue;
+    if (time > timestamp) continue;
+    for (tot=n=0, rad=1; rad < 3 && n==0; rad++)
+      for (r = row-rad; r <= row+rad; r++)
+	for (c = col-rad; c <= col+rad; c++)
+	  if ((unsigned) r < height && (unsigned) c < width &&
+		(r != row || c != col) && fc(r,c) == fc(row,col)) {
+	    tot += BAYER2(r,c);
+	    n++;
+	  }
+    BAYER2(row,col) = tot/n;
+    if (verbose) {
+      if (!fixed++)
+	fprintf (stderr,_("Fixed dead pixels at:"));
+      fprintf (stderr, " %d,%d", col, row);
+    }
+  }
+  if (fixed) fputc ('\n', stderr);
+  fclose (fp);
+}
+
+void CLASS subtract (const char *fname)
+{
+  FILE *fp;
+  int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col;
+  ushort *pixel;
+
+  if (!(fp = fopen (fname, "rb"))) {
+    perror (fname);  return;
+  }
+  if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1;
+  while (!error && nd < 3 && (c = fgetc(fp)) != EOF) {
+    if (c == '#')  comment = 1;
+    if (c == '\n') comment = 0;
+    if (comment) continue;
+    if (isdigit(c)) number = 1;
+    if (number) {
+      if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0';
+      else if (isspace(c)) {
+	number = 0;  nd++;
+      } else error = 1;
+    }
+  }
+  if (error || nd < 3) {
+    fprintf (stderr,_("%s is not a valid PGM file!\n"), fname);
+    fclose (fp);  return;
+  } else if (dim[0] != width || dim[1] != height || dim[2] != 65535) {
+    fprintf (stderr,_("%s has the wrong dimensions!\n"), fname);
+    fclose (fp);  return;
+  }
+  pixel = (ushort *) calloc (width, sizeof *pixel);
+  merror (pixel, "subtract()");
+  for (row=0; row < height; row++) {
+    fread (pixel, 2, width, fp);
+    for (col=0; col < width; col++)
+      BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0);
+  }
+  free (pixel);
+  black = 0;
+}
+
+void CLASS gamma_curve (double pwr, double ts, int mode, int imax)
+{
+  int i;
+  double g[6], bnd[2]={0,0}, r;
+
+  g[0] = pwr;
+  g[1] = ts;
+  g[2] = g[3] = g[4] = 0;
+  bnd[g[1] >= 1] = 1;
+  if (g[1] && (g[1]-1)*(g[0]-1) <= 0) {
+    for (i=0; i < 48; i++) {
+      g[2] = (bnd[0] + bnd[1])/2;
+      if (g[0]) bnd[(pow(g[2]/g[1],-g[0]) - 1)/g[0] - 1/g[2] > -1] = g[2];
+      else	bnd[g[2]/exp(1-1/g[2]) < g[1]] = g[2];
+    }
+    g[3] = g[2] / g[1];
+    if (g[0]) g[4] = g[2] * (1/g[0] - 1);
+  }
+  if (g[0]) g[5] = 1 / (g[1]*SQR(g[3])/2 - g[4]*(1 - g[3]) +
+		(1 - pow(g[3],1+g[0]))*(1 + g[4])/(1 + g[0])) - 1;
+  else      g[5] = 1 / (g[1]*SQR(g[3])/2 + 1
+		- g[2] - g[3] -	g[2]*g[3]*(log(g[3]) - 1)) - 1;
+  if (!mode--) {
+    memcpy (gamm, g, sizeof gamm);
+    return;
+  }
+  for (i=0; i < 0x10000; i++) {
+    curve[i] = 0xffff;
+    if ((r = (double) i / imax) < 1)
+      curve[i] = 0x10000 * ( mode
+	? (r < g[3] ? r*g[1] : (g[0] ? pow( r,g[0])*(1+g[4])-g[4]    : log(r)*g[2]+1))
+	: (r < g[2] ? r/g[1] : (g[0] ? pow((r+g[4])/(1+g[4]),1/g[0]) : exp((r-1)/g[2]))));
+  }
+}
+
+void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size)
+{
+  double work[3][6], num;
+  int i, j, k;
+
+  for (i=0; i < 3; i++) {
+    for (j=0; j < 6; j++)
+      work[i][j] = j == i+3;
+    for (j=0; j < 3; j++)
+      for (k=0; k < size; k++)
+	work[i][j] += in[k][i] * in[k][j];
+  }
+  for (i=0; i < 3; i++) {
+    num = work[i][i];
+    for (j=0; j < 6; j++)
+      work[i][j] /= num;
+    for (k=0; k < 3; k++) {
+      if (k==i) continue;
+      num = work[k][i];
+      for (j=0; j < 6; j++)
+	work[k][j] -= work[i][j] * num;
+    }
+  }
+  for (i=0; i < size; i++)
+    for (j=0; j < 3; j++)
+      for (out[i][j]=k=0; k < 3; k++)
+	out[i][j] += work[j][k+3] * in[i][k];
+}
+
+void CLASS cam_xyz_coeff (double cam_xyz[4][3])
+{
+  double cam_rgb[4][3], inverse[4][3], num;
+  int i, j, k;
+
+  for (i=0; i < colors; i++)		/* Multiply out XYZ colorspace */
+    for (j=0; j < 3; j++)
+      for (cam_rgb[i][j] = k=0; k < 3; k++)
+	cam_rgb[i][j] += cam_xyz[i][k] * xyz_rgb[k][j];
+
+  for (i=0; i < colors; i++) {		/* Normalize cam_rgb so that */
+    for (num=j=0; j < 3; j++)		/* cam_rgb * (1,1,1) is (1,1,1,1) */
+      num += cam_rgb[i][j];
+    for (j=0; j < 3; j++)
+      cam_rgb[i][j] /= num;
+    pre_mul[i] = 1 / num;
+  }
+  pseudoinverse (cam_rgb, inverse, colors);
+  for (raw_color = i=0; i < 3; i++)
+    for (j=0; j < colors; j++)
+      rgb_cam[i][j] = inverse[j][i];
+}
+
+#ifdef COLORCHECK
+void CLASS colorcheck()
+{
+#define NSQ 24
+// Coordinates of the GretagMacbeth ColorChecker squares
+// width, height, 1st_column, 1st_row
+  int cut[NSQ][4];			// you must set these
+// ColorChecker Chart under 6500-kelvin illumination
+  static const double gmb_xyY[NSQ][3] = {
+    { 0.400, 0.350, 10.1 },		// Dark Skin
+    { 0.377, 0.345, 35.8 },		// Light Skin
+    { 0.247, 0.251, 19.3 },		// Blue Sky
+    { 0.337, 0.422, 13.3 },		// Foliage
+    { 0.265, 0.240, 24.3 },		// Blue Flower
+    { 0.261, 0.343, 43.1 },		// Bluish Green
+    { 0.506, 0.407, 30.1 },		// Orange
+    { 0.211, 0.175, 12.0 },		// Purplish Blue
+    { 0.453, 0.306, 19.8 },		// Moderate Red
+    { 0.285, 0.202, 6.6 },		// Purple
+    { 0.380, 0.489, 44.3 },		// Yellow Green
+    { 0.473, 0.438, 43.1 },		// Orange Yellow
+    { 0.187, 0.129, 6.1 },		// Blue
+    { 0.305, 0.478, 23.4 },		// Green
+    { 0.539, 0.313, 12.0 },		// Red
+    { 0.448, 0.470, 59.1 },		// Yellow
+    { 0.364, 0.233, 19.8 },		// Magenta
+    { 0.196, 0.252, 19.8 },		// Cyan
+    { 0.310, 0.316, 90.0 },		// White
+    { 0.310, 0.316, 59.1 },		// Neutral 8
+    { 0.310, 0.316, 36.2 },		// Neutral 6.5
+    { 0.310, 0.316, 19.8 },		// Neutral 5
+    { 0.310, 0.316, 9.0 },		// Neutral 3.5
+    { 0.310, 0.316, 3.1 } };		// Black
+  double gmb_cam[NSQ][4], gmb_xyz[NSQ][3];
+  double inverse[NSQ][3], cam_xyz[4][3], num;
+  int c, i, j, k, sq, row, col, count[4];
+
+  memset (gmb_cam, 0, sizeof gmb_cam);
+  for (sq=0; sq < NSQ; sq++) {
+    FORCC count[c] = 0;
+    for   (row=cut[sq][3]; row < cut[sq][3]+cut[sq][1]; row++)
+      for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++) {
+	c = FC(row,col);
+	if (c >= colors) c -= 2;
+	gmb_cam[sq][c] += BAYER(row,col);
+	count[c]++;
+      }
+    FORCC gmb_cam[sq][c] = gmb_cam[sq][c]/count[c] - black;
+    gmb_xyz[sq][0] = gmb_xyY[sq][2] * gmb_xyY[sq][0] / gmb_xyY[sq][1];
+    gmb_xyz[sq][1] = gmb_xyY[sq][2];
+    gmb_xyz[sq][2] = gmb_xyY[sq][2] *
+		(1 - gmb_xyY[sq][0] - gmb_xyY[sq][1]) / gmb_xyY[sq][1];
+  }
+  pseudoinverse (gmb_xyz, inverse, NSQ);
+  for (i=0; i < colors; i++)
+    for (j=0; j < 3; j++)
+      for (cam_xyz[i][j] = k=0; k < NSQ; k++)
+	cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j];
+  cam_xyz_coeff (cam_xyz);
+  if (verbose) {
+    printf ("    { \"%s %s\", %d,\n\t{", make, model, black);
+    num = 10000 / (cam_xyz[1][0] + cam_xyz[1][1] + cam_xyz[1][2]);
+    FORCC for (j=0; j < 3; j++)
+      printf ("%c%d", (c | j) ? ',':' ', (int) (cam_xyz[c][j] * num + 0.5));
+    puts (" } },");
+  }
+#undef NSQ
+}
+#endif
+
+void CLASS hat_transform (float *temp, float *base, int st, int size, int sc)
+{
+  int i;
+  for (i=0; i < sc; i++)
+    temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)];
+  for (; i+sc < size; i++)
+    temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)];
+  for (; i < size; i++)
+    temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))];
+}
+
+void CLASS wavelet_denoise()
+{
+  float *fimg=0, *temp, thold, mul[2], avg, diff;
+  int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast;
+  ushort *window[4];
+  static const float noise[] =
+  { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
+
+  if (verbose) fprintf (stderr,_("Wavelet denoising...\n"));
+
+  while (maximum << scale < 0x10000) scale++;
+  maximum <<= --scale;
+  black <<= scale;
+  if ((size = iheight*iwidth) < 0x15550000)
+    fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg);
+  merror (fimg, "wavelet_denoise()");
+  temp = fimg + size*3;
+  if ((nc = colors) == 3 && filters) nc++;
+  FORC(nc) {			/* denoise R,G1,B,G3 individually */
+    for (i=0; i < size; i++)
+      fimg[i] = 256 * sqrt(image[i][c] << scale);
+    for (hpass=lev=0; lev < 5; lev++) {
+      lpass = size*((lev & 1)+1);
+      for (row=0; row < iheight; row++) {
+	hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev);
+        for (col=0; col < iwidth; col++)
+	  fimg[lpass + row*iwidth + col] = temp[col] * 0.25;
+      }
+      for (col=0; col < iwidth; col++) {
+	hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev);
+	for (row=0; row < iheight; row++)
+	  fimg[lpass + row*iwidth + col] = temp[row] * 0.25;
+      }
+      thold = threshold * noise[lev];
+      for (i=0; i < size; i++) {
+	fimg[hpass+i] -= fimg[lpass+i];
+	if	(fimg[hpass+i] < -thold) fimg[hpass+i] += thold;
+	else if (fimg[hpass+i] >  thold) fimg[hpass+i] -= thold;
+	else	 fimg[hpass+i] = 0;
+	if (hpass) fimg[i] += fimg[hpass+i];
+      }
+      hpass = lpass;
+    }
+    for (i=0; i < size; i++)
+      image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000);
+  }
+  if (filters && colors == 3) {  /* pull G1 and G3 closer together */
+    for (row=0; row < 2; row++)
+      mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1];
+    for (i=0; i < 4; i++)
+      window[i] = (ushort *) fimg + width*i;
+    for (wlast=-1, row=1; row < height-1; row++) {
+      while (wlast < row+1) {
+	for (wlast++, i=0; i < 4; i++)
+	  window[(i+3) & 3] = window[i];
+	for (col = FC(wlast,1) & 1; col < width; col+=2)
+	  window[2][col] = BAYER(wlast,col);
+      }
+      thold = threshold/512;
+      for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) {
+	avg = ( window[0][col-1] + window[0][col+1] +
+		window[2][col-1] + window[2][col+1] - black*4 )
+	      * mul[row & 1] + (window[1][col] - black) * 0.5 + black;
+	avg = avg < 0 ? 0 : sqrt(avg);
+	diff = sqrt(BAYER(row,col)) - avg;
+	if      (diff < -thold) diff += thold;
+	else if (diff >  thold) diff -= thold;
+	else diff = 0;
+	BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5);
+      }
+    }
+  }
+  free (fimg);
+}
+
+void CLASS scale_colors()
+{
+  unsigned bottom, right, size, row, col, ur, uc, i, x, y, c, sum[8];
+  int val, dark, sat;
+  double dsum[8], dmin, dmax;
+  float scale_mul[4], fr, fc;
+  ushort *img=0, *pix;
+
+  if (user_mul[0])
+    memcpy (pre_mul, user_mul, sizeof pre_mul);
+  if (use_auto_wb || (use_camera_wb && cam_mul[0] == -1)) {
+    memset (dsum, 0, sizeof dsum);
+    bottom = MIN (greybox[1]+greybox[3], height);
+    right  = MIN (greybox[0]+greybox[2], width);
+    for (row=greybox[1]; row < bottom; row += 8)
+      for (col=greybox[0]; col < right; col += 8) {
+	memset (sum, 0, sizeof sum);
+	for (y=row; y < row+8 && y < bottom; y++)
+	  for (x=col; x < col+8 && x < right; x++)
+	    FORC4 {
+	      if (filters) {
+		c = FC(y,x);
+		val = BAYER(y,x);
+	      } else
+		val = image[y*width+x][c];
+	      if (val > maximum-25) goto skip_block;
+	      if ((val -= black) < 0) val = 0;
+	      sum[c] += val;
+	      sum[c+4]++;
+	      if (filters) break;
+	    }
+	FORC(8) dsum[c] += sum[c];
+skip_block: ;
+      }
+    FORC4 if (dsum[c]) pre_mul[c] = dsum[c+4] / dsum[c];
+  }
+  if (use_camera_wb && cam_mul[0] != -1) {
+    memset (sum, 0, sizeof sum);
+    for (row=0; row < 8; row++)
+      for (col=0; col < 8; col++) {
+	c = FC(row,col);
+	if ((val = white[row][col] - black) > 0)
+	  sum[c] += val;
+	sum[c+4]++;
+      }
+    if (sum[0] && sum[1] && sum[2] && sum[3])
+      FORC4 pre_mul[c] = (float) sum[c+4] / sum[c];
+    else if (cam_mul[0] && cam_mul[2])
+      memcpy (pre_mul, cam_mul, sizeof pre_mul);
+    else
+      fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname);
+  }
+  if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1;
+  dark = black;
+  sat = maximum;
+  if (threshold) wavelet_denoise();
+  maximum -= black;
+  for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) {
+    if (dmin > pre_mul[c])
+	dmin = pre_mul[c];
+    if (dmax < pre_mul[c])
+	dmax = pre_mul[c];
+  }
+  if (!highlight) dmax = dmin;
+  FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum;
+  if (verbose) {
+    fprintf (stderr,
+      _("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat);
+    FORC4 fprintf (stderr, " %f", pre_mul[c]);
+    fputc ('\n', stderr);
+  }
+  size = iheight*iwidth;
+  for (i=0; i < size*4; i++) {
+    val = image[0][i];
+    if (!val) continue;
+    val -= black;
+    val *= scale_mul[i & 3];
+    image[0][i] = CLIP(val);
+  }
+  if ((aber[0] != 1 || aber[2] != 1) && colors == 3) {
+    if (verbose)
+      fprintf (stderr,_("Correcting chromatic aberration...\n"));
+    for (c=0; c < 4; c+=2) {
+      if (aber[c] == 1) continue;
+      img = (ushort *) malloc (size * sizeof *img);
+      merror (img, "scale_colors()");
+      for (i=0; i < size; i++)
+	img[i] = image[i][c];
+      for (row=0; row < iheight; row++) {
+	ur = fr = (row - iheight*0.5) * aber[c] + iheight*0.5;
+	if (ur > iheight-2) continue;
+	fr -= ur;
+	for (col=0; col < iwidth; col++) {
+	  uc = fc = (col - iwidth*0.5) * aber[c] + iwidth*0.5;
+	  if (uc > iwidth-2) continue;
+	  fc -= uc;
+	  pix = img + ur*iwidth + uc;
+	  image[row*iwidth+col][c] =
+	    (pix[     0]*(1-fc) + pix[       1]*fc) * (1-fr) +
+	    (pix[iwidth]*(1-fc) + pix[iwidth+1]*fc) * fr;
+	}
+      }
+      free(img);
+    }
+  }
+}
+
+void CLASS pre_interpolate()
+{
+  ushort (*img)[4];
+  int row, col, c;
+
+  if (shrink) {
+    if (half_size) {
+      height = iheight;
+      width  = iwidth;
+    } else {
+      img = (ushort (*)[4]) calloc (height*width, sizeof *img);
+      merror (img, "pre_interpolate()");
+      for (row=0; row < height; row++)
+	for (col=0; col < width; col++) {
+	  c = fc(row,col);
+	  img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c];
+	}
+      free (image);
+      image = img;
+      shrink = 0;
+    }
+  }
+  if (filters && colors == 3) {
+    if ((mix_green = four_color_rgb)) colors++;
+    else {
+      for (row = FC(1,0) >> 1; row < height; row+=2)
+	for (col = FC(row,1) & 1; col < width; col+=2)
+	  image[row*width+col][1] = image[row*width+col][3];
+      filters &= ~((filters & 0x55555555) << 1);
+    }
+  }
+  if (half_size) filters = 0;
+}
+
+void CLASS border_interpolate (int border)
+{
+  unsigned row, col, y, x, f, c, sum[8];
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++) {
+      if (col==border && row >= border && row < height-border)
+	col = width-border;
+      memset (sum, 0, sizeof sum);
+      for (y=row-1; y != row+2; y++)
+	for (x=col-1; x != col+2; x++)
+	  if (y < height && x < width) {
+	    f = fc(y,x);
+	    sum[f] += image[y*width+x][f];
+	    sum[f+4]++;
+	  }
+      f = fc(row,col);
+      FORCC if (c != f && sum[c+4])
+	image[row*width+col][c] = sum[c] / sum[c+4];
+    }
+}
+
+void CLASS lin_interpolate()
+{
+  int code[16][16][32], *ip, sum[4];
+  int c, i, x, y, row, col, shift, color;
+  ushort *pix;
+
+  if (verbose) fprintf (stderr,_("Bilinear interpolation...\n"));
+
+  border_interpolate(1);
+  for (row=0; row < 16; row++)
+    for (col=0; col < 16; col++) {
+      ip = code[row][col];
+      memset (sum, 0, sizeof sum);
+      for (y=-1; y <= 1; y++)
+	for (x=-1; x <= 1; x++) {
+	  shift = (y==0) + (x==0);
+	  if (shift == 2) continue;
+	  color = fc(row+y,col+x);
+	  *ip++ = (width*y + x)*4 + color;
+	  *ip++ = shift;
+	  *ip++ = color;
+	  sum[color] += 1 << shift;
+	}
+      FORCC
+	if (c != fc(row,col)) {
+	  *ip++ = c;
+	  *ip++ = 256 / sum[c];
+	}
+    }
+  for (row=1; row < height-1; row++)
+    for (col=1; col < width-1; col++) {
+      pix = image[row*width+col];
+      ip = code[row & 15][col & 15];
+      memset (sum, 0, sizeof sum);
+      for (i=8; i--; ip+=3)
+	sum[ip[2]] += pix[ip[0]] << ip[1];
+      for (i=colors; --i; ip+=2)
+	pix[ip[0]] = sum[ip[0]] * ip[1] >> 8;
+    }
+}
+
+/*
+   This algorithm is officially called:
+
+   "Interpolation using a Threshold-based variable number of gradients"
+
+   described in http://scien.stanford.edu/class/psych221/projects/99/tingchen/algodep/vargra.html
+
+   I've extended the basic idea to work with non-Bayer filter arrays.
+   Gradients are numbered clockwise from NW=0 to W=7.
+ */
+void CLASS vng_interpolate()
+{
+  static const signed char *cp, terms[] = {
+    -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01,
+    -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01,
+    -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03,
+    -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06,
+    -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04,
+    -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01,
+    -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
+    -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11,
+    -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11,
+    -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
+    -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44,
+    -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10,
+    -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04,
+    +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40,
+    +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20,
+    +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08,
+    +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20,
+    +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44,
+    +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60,
+    +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80,
+    +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40,
+    +1,+0,+2,+1,0,0x10
+  }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
+  ushort (*brow[5])[4], *pix;
+  int prow=7, pcol=1, *ip, *code[16][16], gval[8], gmin, gmax, sum[4];
+  int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
+  int g, diff, thold, num, c;
+
+  lin_interpolate();
+  if (verbose) fprintf (stderr,_("VNG interpolation...\n"));
+
+  if (filters == 1) prow = pcol = 15;
+  ip = (int *) calloc ((prow+1)*(pcol+1), 1280);
+  merror (ip, "vng_interpolate()");
+  for (row=0; row <= prow; row++)		/* Precalculate for VNG */
+    for (col=0; col <= pcol; col++) {
+      code[row][col] = ip;
+      for (cp=terms, t=0; t < 64; t++) {
+	y1 = *cp++;  x1 = *cp++;
+	y2 = *cp++;  x2 = *cp++;
+	weight = *cp++;
+	grads = *cp++;
+	color = fc(row+y1,col+x1);
+	if (fc(row+y2,col+x2) != color) continue;
+	diag = (fc(row,col+1) == color && fc(row+1,col) == color) ? 2:1;
+	if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
+	*ip++ = (y1*width + x1)*4 + color;
+	*ip++ = (y2*width + x2)*4 + color;
+	*ip++ = weight;
+	for (g=0; g < 8; g++)
+	  if (grads & 1<<g) *ip++ = g;
+	*ip++ = -1;
+      }
+      *ip++ = INT_MAX;
+      for (cp=chood, g=0; g < 8; g++) {
+	y = *cp++;  x = *cp++;
+	*ip++ = (y*width + x) * 4;
+	color = fc(row,col);
+	if (fc(row+y,col+x) != color && fc(row+y*2,col+x*2) == color)
+	  *ip++ = (y*width + x) * 8 + color;
+	else
+	  *ip++ = 0;
+      }
+    }
+  brow[4] = (ushort (*)[4]) calloc (width*3, sizeof **brow);
+  merror (brow[4], "vng_interpolate()");
+  for (row=0; row < 3; row++)
+    brow[row] = brow[4] + row*width;
+  for (row=2; row < height-2; row++) {		/* Do VNG interpolation */
+    for (col=2; col < width-2; col++) {
+      pix = image[row*width+col];
+      ip = code[row & prow][col & pcol];
+      memset (gval, 0, sizeof gval);
+      while ((g = ip[0]) != INT_MAX) {		/* Calculate gradients */
+	diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
+	gval[ip[3]] += diff;
+	ip += 5;
+	if ((g = ip[-1]) == -1) continue;
+	gval[g] += diff;
+	while ((g = *ip++) != -1)
+	  gval[g] += diff;
+      }
+      ip++;
+      gmin = gmax = gval[0];			/* Choose a threshold */
+      for (g=1; g < 8; g++) {
+	if (gmin > gval[g]) gmin = gval[g];
+	if (gmax < gval[g]) gmax = gval[g];
+      }
+      if (gmax == 0) {
+	memcpy (brow[2][col], pix, sizeof *image);
+	continue;
+      }
+      thold = gmin + (gmax >> 1);
+      memset (sum, 0, sizeof sum);
+      color = fc(row,col);
+      for (num=g=0; g < 8; g++,ip+=2) {		/* Average the neighbors */
+	if (gval[g] <= thold) {
+	  FORCC
+	    if (c == color && ip[1])
+	      sum[c] += (pix[c] + pix[ip[1]]) >> 1;
+	    else
+	      sum[c] += pix[ip[0] + c];
+	  num++;
+	}
+      }
+      FORCC {					/* Save to buffer */
+	t = pix[color];
+	if (c != color)
+	  t += (sum[c] - sum[color]) / num;
+	brow[2][col][c] = CLIP(t);
+      }
+    }
+    if (row > 3)				/* Write buffer to image */
+      memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
+    for (g=0; g < 4; g++)
+      brow[(g-1) & 3] = brow[g];
+  }
+  memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
+  memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image);
+  free (brow[4]);
+  free (code[0][0]);
+}
+
+/*
+   Patterned Pixel Grouping Interpolation by Alain Desbiolles
+*/
+void CLASS ppg_interpolate()
+{
+  int dir[5] = { 1, width, -1, -width, 1 };
+  int row, col, diff[2], guess[2], c, d, i;
+  ushort (*pix)[4];
+
+  border_interpolate(3);
+  if (verbose) fprintf (stderr,_("PPG interpolation...\n"));
+
+/*  Fill in the green layer with gradients and pattern recognition: */
+  for (row=3; row < height-3; row++)
+    for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) {
+      pix = image + row*width+col;
+      for (i=0; (d=dir[i]) > 0; i++) {
+	guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2
+		      - pix[-2*d][c] - pix[2*d][c];
+	diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) +
+		    ABS(pix[ 2*d][c] - pix[ 0][c]) +
+		    ABS(pix[  -d][1] - pix[ d][1]) ) * 3 +
+		  ( ABS(pix[ 3*d][1] - pix[ d][1]) +
+		    ABS(pix[-3*d][1] - pix[-d][1]) ) * 2;
+      }
+      d = dir[i = diff[0] > diff[1]];
+      pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]);
+    }
+/*  Calculate red and blue for each green pixel:		*/
+  for (row=1; row < height-1; row++)
+    for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) {
+      pix = image + row*width+col;
+      for (i=0; (d=dir[i]) > 0; c=2-c, i++)
+	pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1]
+			- pix[-d][1] - pix[d][1]) >> 1);
+    }
+/*  Calculate blue for red pixels and vice versa:		*/
+  for (row=1; row < height-1; row++)
+    for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) {
+      pix = image + row*width+col;
+      for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) {
+	diff[i] = ABS(pix[-d][c] - pix[d][c]) +
+		  ABS(pix[-d][1] - pix[0][1]) +
+		  ABS(pix[ d][1] - pix[0][1]);
+	guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1]
+		 - pix[-d][1] - pix[d][1];
+      }
+      if (diff[0] != diff[1])
+	pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1);
+      else
+	pix[0][c] = CLIP((guess[0]+guess[1]) >> 2);
+    }
+}
+
+/*
+   Adaptive Homogeneity-Directed interpolation is based on
+   the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
+ */
+#define TS 256		/* Tile Size */
+
+void CLASS ahd_interpolate()
+{
+  int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
+  ushort (*pix)[4], (*rix)[3];
+  static const int dir[4] = { -1, 1, -TS, TS };
+  unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
+  float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
+  ushort (*rgb)[TS][TS][3];
+   short (*lab)[TS][TS][3], (*lix)[3];
+   char (*homo)[TS][TS], *buffer;
+
+  if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
+
+  for (i=0; i < 0x10000; i++) {
+    r = i / 65535.0;
+    cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0;
+  }
+  for (i=0; i < 3; i++)
+    for (j=0; j < colors; j++)
+      for (xyz_cam[i][j] = k=0; k < 3; k++)
+	xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i];
+
+  border_interpolate(5);
+  buffer = (char *) malloc (26*TS*TS);		/* 1664 kB */
+  merror (buffer, "ahd_interpolate()");
+  rgb  = (ushort(*)[TS][TS][3]) buffer;
+  lab  = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
+  homo = (char  (*)[TS][TS])   (buffer + 24*TS*TS);
+
+  for (top=2; top < height-5; top += TS-6)
+    for (left=2; left < width-5; left += TS-6) {
+
+/*  Interpolate green horizontally and vertically:		*/
+      for (row = top; row < top+TS && row < height-2; row++) {
+	col = left + (FC(row,left) & 1);
+	for (c = FC(row,col); col < left+TS && col < width-2; col+=2) {
+	  pix = image + row*width+col;
+	  val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2
+		- pix[-2][c] - pix[2][c]) >> 2;
+	  rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]);
+	  val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2
+		- pix[-2*width][c] - pix[2*width][c]) >> 2;
+	  rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]);
+	}
+      }
+/*  Interpolate red and blue, and convert to CIELab:		*/
+      for (d=0; d < 2; d++)
+	for (row=top+1; row < top+TS-1 && row < height-3; row++)
+	  for (col=left+1; col < left+TS-1 && col < width-3; col++) {
+	    pix = image + row*width+col;
+	    rix = &rgb[d][row-top][col-left];
+	    lix = &lab[d][row-top][col-left];
+	    if ((c = 2 - FC(row,col)) == 1) {
+	      c = FC(row+1,col);
+	      val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
+				 - rix[-1][1] - rix[1][1] ) >> 1);
+	      rix[0][2-c] = CLIP(val);
+	      val = pix[0][1] + (( pix[-width][c] + pix[width][c]
+				 - rix[-TS][1] - rix[TS][1] ) >> 1);
+	    } else
+	      val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c]
+				 + pix[+width-1][c] + pix[+width+1][c]
+				 - rix[-TS-1][1] - rix[-TS+1][1]
+				 - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
+	    rix[0][c] = CLIP(val);
+	    c = FC(row,col);
+	    rix[0][c] = pix[0][c];
+	    xyz[0] = xyz[1] = xyz[2] = 0.5;
+	    FORCC {
+	      xyz[0] += xyz_cam[0][c] * rix[0][c];
+	      xyz[1] += xyz_cam[1][c] * rix[0][c];
+	      xyz[2] += xyz_cam[2][c] * rix[0][c];
+	    }
+	    xyz[0] = cbrt[CLIP((int) xyz[0])];
+	    xyz[1] = cbrt[CLIP((int) xyz[1])];
+	    xyz[2] = cbrt[CLIP((int) xyz[2])];
+	    lix[0][0] = 64 * (116 * xyz[1] - 16);
+	    lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]);
+	    lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]);
+	  }
+/*  Build homogeneity maps from the CIELab images:		*/
+      memset (homo, 0, 2*TS*TS);
+      for (row=top+2; row < top+TS-2 && row < height-4; row++) {
+	tr = row-top;
+	for (col=left+2; col < left+TS-2 && col < width-4; col++) {
+	  tc = col-left;
+	  for (d=0; d < 2; d++) {
+	    lix = &lab[d][tr][tc];
+	    for (i=0; i < 4; i++) {
+	       ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]);
+	      abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1])
+			   + SQR(lix[0][2]-lix[dir[i]][2]);
+	    }
+	  }
+	  leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
+		     MAX(ldiff[1][2],ldiff[1][3]));
+	  abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
+		      MAX(abdiff[1][2],abdiff[1][3]));
+	  for (d=0; d < 2; d++)
+	    for (i=0; i < 4; i++)
+	      if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
+		homo[d][tr][tc]++;
+	}
+      }
+/*  Combine the most homogenous pixels for the final result:	*/
+      for (row=top+3; row < top+TS-3 && row < height-5; row++) {
+	tr = row-top;
+	for (col=left+3; col < left+TS-3 && col < width-5; col++) {
+	  tc = col-left;
+	  for (d=0; d < 2; d++)
+	    for (hm[d]=0, i=tr-1; i <= tr+1; i++)
+	      for (j=tc-1; j <= tc+1; j++)
+		hm[d] += homo[d][i][j];
+	  if (hm[0] != hm[1])
+	    FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c];
+	  else
+	    FORC3 image[row*width+col][c] =
+		(rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
+	}
+      }
+    }
+  free (buffer);
+}
+#undef TS
+
+void CLASS median_filter()
+{
+  ushort (*pix)[4];
+  int pass, c, i, j, k, med[9];
+  static const uchar opt[] =	/* Optimal 9-element median search */
+  { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8,
+    0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 };
+
+  for (pass=1; pass <= med_passes; pass++) {
+    if (verbose)
+      fprintf (stderr,_("Median filter pass %d...\n"), pass);
+    for (c=0; c < 3; c+=2) {
+      for (pix = image; pix < image+width*height; pix++)
+	pix[0][3] = pix[0][c];
+      for (pix = image+width; pix < image+width*(height-1); pix++) {
+	if ((pix-image+1) % width < 2) continue;
+	for (k=0, i = -width; i <= width; i += width)
+	  for (j = i-1; j <= i+1; j++)
+	    med[k++] = pix[j][3] - pix[j][1];
+	for (i=0; i < sizeof opt; i+=2)
+	  if     (med[opt[i]] > med[opt[i+1]])
+	    SWAP (med[opt[i]] , med[opt[i+1]]);
+	pix[0][c] = CLIP(med[4] + pix[0][1]);
+      }
+    }
+  }
+}
+
+void CLASS blend_highlights()
+{
+  int clip=INT_MAX, row, col, c, i, j;
+  static const float trans[2][4][4] =
+  { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } },
+    { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
+  static const float itrans[2][4][4] =
+  { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } },
+    { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
+  float cam[2][4], lab[2][4], sum[2], chratio;
+
+  if ((unsigned) (colors-3) > 1) return;
+  if (verbose) fprintf (stderr,_("Blending highlights...\n"));
+  FORCC if (clip > (i = 65535*pre_mul[c])) clip = i;
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++) {
+      FORCC if (image[row*width+col][c] > clip) break;
+      if (c == colors) continue;
+      FORCC {
+	cam[0][c] = image[row*width+col][c];
+	cam[1][c] = MIN(cam[0][c],clip);
+      }
+      for (i=0; i < 2; i++) {
+	FORCC for (lab[i][c]=j=0; j < colors; j++)
+	  lab[i][c] += trans[colors-3][c][j] * cam[i][j];
+	for (sum[i]=0,c=1; c < colors; c++)
+	  sum[i] += SQR(lab[i][c]);
+      }
+      chratio = sqrt(sum[1]/sum[0]);
+      for (c=1; c < colors; c++)
+	lab[0][c] *= chratio;
+      FORCC for (cam[0][c]=j=0; j < colors; j++)
+	cam[0][c] += itrans[colors-3][c][j] * lab[0][j];
+      FORCC image[row*width+col][c] = cam[0][c] / colors;
+    }
+}
+
+#define SCALE (4 >> shrink)
+void CLASS recover_highlights()
+{
+  float *map, sum, wgt, grow;
+  int hsat[4], count, spread, change, val, i;
+  unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x;
+  ushort *pixel;
+  static const signed char dir[8][2] =
+    { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} };
+
+  if (verbose) fprintf (stderr,_("Rebuilding highlights...\n"));
+
+  grow = pow (2, 4-highlight);
+  FORCC hsat[c] = 32000 * pre_mul[c];
+  for (kc=0, c=1; c < colors; c++)
+    if (pre_mul[kc] < pre_mul[c]) kc = c;
+  high = height / SCALE;
+  wide =  width / SCALE;
+  map = (float *) calloc (high*wide, sizeof *map);
+  merror (map, "recover_highlights()");
+  FORCC if (c != kc) {
+    memset (map, 0, high*wide*sizeof *map);
+    for (mrow=0; mrow < high; mrow++)
+      for (mcol=0; mcol < wide; mcol++) {
+	sum = wgt = count = 0;
+	for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
+	  for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
+	    pixel = image[row*width+col];
+	    if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) {
+	      sum += pixel[c];
+	      wgt += pixel[kc];
+	      count++;
+	    }
+	  }
+	if (count == SCALE*SCALE)
+	  map[mrow*wide+mcol] = sum / wgt;
+      }
+    for (spread = 32/grow; spread--; ) {
+      for (mrow=0; mrow < high; mrow++)
+	for (mcol=0; mcol < wide; mcol++) {
+	  if (map[mrow*wide+mcol]) continue;
+	  sum = count = 0;
+	  for (d=0; d < 8; d++) {
+	    y = mrow + dir[d][0];
+	    x = mcol + dir[d][1];
+	    if (y < high && x < wide && map[y*wide+x] > 0) {
+	      sum  += (1 + (d & 1)) * map[y*wide+x];
+	      count += 1 + (d & 1);
+	    }
+	  }
+	  if (count > 3)
+	    map[mrow*wide+mcol] = - (sum+grow) / (count+grow);
+	}
+      for (change=i=0; i < high*wide; i++)
+	if (map[i] < 0) {
+	  map[i] = -map[i];
+	  change = 1;
+	}
+      if (!change) break;
+    }
+    for (i=0; i < high*wide; i++)
+      if (map[i] == 0) map[i] = 1;
+    for (mrow=0; mrow < high; mrow++)
+      for (mcol=0; mcol < wide; mcol++) {
+	for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
+	  for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
+	    pixel = image[row*width+col];
+	    if (pixel[c] / hsat[c] > 1) {
+	      val = pixel[kc] * map[mrow*wide+mcol];
+	      if (pixel[c] < val) pixel[c] = CLIP(val);
+	    }
+	  }
+      }
+  }
+  free (map);
+}
+#undef SCALE
+
+void CLASS tiff_get (unsigned base,
+	unsigned *tag, unsigned *type, unsigned *len, unsigned *save)
+{
+  *tag  = get2();
+  *type = get2();
+  *len  = get4();
+  *save = ftell(ifp) + 4;
+  if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4)
+    fseek (ifp, get4()+base, SEEK_SET);
+}
+
+void CLASS parse_thumb_note (int base, unsigned toff, unsigned tlen)
+{
+  unsigned entries, tag, type, len, save;
+
+  entries = get2();
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    if (tag == toff) thumb_offset = get4()+base;
+    if (tag == tlen) thumb_length = get4();
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+int CLASS parse_tiff_ifd (int base);
+
+void CLASS parse_makernote (int base, int uptag)
+{
+  static const uchar xlat[2][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 },
+  { 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 } };
+  unsigned offset=0, entries, tag, type, len, save, c;
+  unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0};
+  uchar buf97[324], ci, cj, ck;
+  short sorder=order;
+  char buf[10];
+/*
+   The MakerNote might have its own TIFF header (possibly with
+   its own byte-order!), or it might just be a table.
+ */
+  fread (buf, 1, 10, ifp);
+  if (!strncmp (buf,"KDK" ,3) ||	/* these aren't TIFF tables */
+      !strncmp (buf,"VER" ,3) ||
+      !strncmp (buf,"IIII",4) ||
+      !strncmp (buf,"MMMM",4)) return;
+  if (!strncmp (buf,"KC"  ,2) ||	/* Konica KD-400Z, KD-510Z */
+      !strncmp (buf,"MLY" ,3)) {	/* Minolta DiMAGE G series */
+    order = 0x4d4d;
+    while ((i=ftell(ifp)) < data_offset && i < 16384) {
+      wb[0] = wb[2];  wb[2] = wb[1];  wb[1] = wb[3];
+      wb[3] = get2();
+      if (wb[1] == 256 && wb[3] == 256 &&
+	  wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640)
+	FORC4 cam_mul[c] = wb[c];
+    }
+    goto quit;
+  }
+  if (!strcmp (buf,"Nikon")) {
+    base = ftell(ifp);
+    order = get2();
+    if (get2() != 42) goto quit;
+    offset = get4();
+    fseek (ifp, offset-8, SEEK_CUR);
+  } else if (!strcmp (buf,"OLYMPUS")) {
+    base = ftell(ifp)-10;
+    fseek (ifp, -2, SEEK_CUR);
+    order = get2();  get2();
+  } else if (!strncmp (buf,"FUJIFILM",8) ||
+	     !strncmp (buf,"SONY",4) ||
+	     !strcmp  (buf,"Panasonic")) {
+    order = 0x4949;
+    fseek (ifp,  2, SEEK_CUR);
+  } else if (!strcmp (buf,"OLYMP") ||
+	     !strcmp (buf,"LEICA") ||
+	     !strcmp (buf,"Ricoh") ||
+	     !strcmp (buf,"EPSON"))
+    fseek (ifp, -2, SEEK_CUR);
+  else if (!strcmp (buf,"AOC") ||
+	   !strcmp (buf,"QVC"))
+    fseek (ifp, -4, SEEK_CUR);
+  else fseek (ifp, -10, SEEK_CUR);
+
+  entries = get2();
+  if (entries > 1000) return;
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    tag |= uptag << 16;
+    if (tag == 2 && strstr(make,"NIKON"))
+      iso_speed = (get2(),get2());
+    if (tag == 4 && len > 26 && len < 35) {
+      if ((i=(get4(),get2())) != 0x7fff && !iso_speed)
+	iso_speed = 50 * pow (2, i/32.0 - 4);
+      if ((i=(get2(),get2())) != 0x7fff && !aperture)
+	aperture = pow (2, i/64.0);
+      if ((i=get2()) != 0xffff && !shutter)
+	shutter = pow (2, (short) i/-32.0);
+      wbi = (get2(),get2());
+      shot_order = (get2(),get2());
+    }
+    if (tag == 7 && type == 2 && len > 20)
+      fgets (model2, 64, ifp);
+    if (tag == 8 && type == 4)
+      shot_order = get4();
+    if (tag == 9 && !strcmp(make,"Canon"))
+      fread (artist, 64, 1, ifp);
+    if (tag == 0xc && len == 4) {
+      cam_mul[0] = getreal(type);
+      cam_mul[2] = getreal(type);
+    }
+    if (tag == 0x10 && type == 4)
+      unique_id = get4();
+    if (tag == 0x11 && is_raw && !strncmp(make,"NIKON",5)) {
+      fseek (ifp, get4()+base, SEEK_SET);
+      parse_tiff_ifd (base);
+    }
+    if (tag == 0x14 && len == 2560 && type == 7) {
+      fseek (ifp, 1248, SEEK_CUR);
+      goto get2_256;
+    }
+    if (tag == 0x15 && type == 2 && is_raw)
+      fread (model, 64, 1, ifp);
+    if (strstr(make,"PENTAX")) {
+      if (tag == 0x1b) tag = 0x1018;
+      if (tag == 0x1c) tag = 0x1017;
+    }
+    if (tag == 0x1d)
+      while ((c = fgetc(ifp)) && c != EOF)
+	serial = serial*10 + (isdigit(c) ? c - '0' : c % 10);
+    if (tag == 0x81 && type == 4) {
+      data_offset = get4();
+      fseek (ifp, data_offset + 41, SEEK_SET);
+      raw_height = get2() * 2;
+      raw_width  = get2();
+      filters = 0x61616161;
+    }
+    if (tag == 0x29 && type == 1) {
+      c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0;
+      fseek (ifp, 8 + c*32, SEEK_CUR);
+      FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4();
+    }
+    if ((tag == 0x81  && type == 7) ||
+	(tag == 0x100 && type == 7) ||
+	(tag == 0x280 && type == 1)) {
+      thumb_offset = ftell(ifp);
+      thumb_length = len;
+    }
+    if (tag == 0x88 && type == 4 && (thumb_offset = get4()))
+      thumb_offset += base;
+    if (tag == 0x89 && type == 4)
+      thumb_length = get4();
+    if (tag == 0x8c || tag == 0x96)
+      meta_offset = ftell(ifp);
+    if (tag == 0x97) {
+      for (i=0; i < 4; i++)
+	ver97 = ver97 * 10 + fgetc(ifp)-'0';
+      switch (ver97) {
+	case 100:
+	  fseek (ifp, 68, SEEK_CUR);
+	  FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2();
+	  break;
+	case 102:
+	  fseek (ifp, 6, SEEK_CUR);
+	  goto get2_rggb;
+	case 103:
+	  fseek (ifp, 16, SEEK_CUR);
+	  FORC4 cam_mul[c] = get2();
+      }
+      if (ver97 >= 200) {
+	if (ver97 != 205) fseek (ifp, 280, SEEK_CUR);
+	fread (buf97, 324, 1, ifp);
+      }
+    }
+    if (tag == 0xa4 && type == 3) {
+      fseek (ifp, wbi*48, SEEK_CUR);
+      FORC3 cam_mul[c] = get2();
+    }
+    if (tag == 0xa7 && (unsigned) (ver97-200) < 12 && !cam_mul[0]) {
+      ci = xlat[0][serial & 0xff];
+      cj = xlat[1][fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp)];
+      ck = 0x60;
+      for (i=0; i < 324; i++)
+	buf97[i] ^= (cj += ci * ck++);
+      i = "66666>666;6A"[ver97-200] - '0';
+      FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] =
+	sget2 (buf97 + (i & -2) + c*2);
+    }
+    if (tag == 0x200 && len == 3)
+      shot_order = (get4(),get4());
+    if (tag == 0x200 && len == 4)
+      black = (get2()+get2()+get2()+get2())/4;
+    if (tag == 0x201 && len == 4)
+      goto get2_rggb;
+    if (tag == 0x220 && len == 53) {
+      fseek (ifp, 14, SEEK_CUR);
+      pentax_tree();
+    }
+    if (tag == 0x401 && len == 4) {
+      black = (get4()+get4()+get4()+get4())/4;
+    }
+    if (tag == 0xe01) {		/* Nikon Capture Note */
+      type = order;
+      order = 0x4949;
+      fseek (ifp, 22, SEEK_CUR);
+      for (offset=22; offset+22 < len; offset += 22+i) {
+	tag = get4();
+	fseek (ifp, 14, SEEK_CUR);
+	i = get4()-4;
+	if (tag == 0x76a43207) flip = get2();
+	else fseek (ifp, i, SEEK_CUR);
+      }
+      order = type;
+    }
+    if (tag == 0xe80 && len == 256 && type == 7) {
+      fseek (ifp, 48, SEEK_CUR);
+      cam_mul[0] = get2() * 508 * 1.078 / 0x10000;
+      cam_mul[2] = get2() * 382 * 1.173 / 0x10000;
+    }
+    if (tag == 0xf00 && type == 7) {
+      if (len == 614)
+	fseek (ifp, 176, SEEK_CUR);
+      else if (len == 734 || len == 1502)
+	fseek (ifp, 148, SEEK_CUR);
+      else goto next;
+      goto get2_256;
+    }
+    if ((tag == 0x1011 && len == 9) || tag == 0x20400200)
+      for (i=0; i < 3; i++)
+	FORC3 cmatrix[i][c] = ((short) get2()) / 256.0;
+    if ((tag == 0x1012 || tag == 0x20400600) && len == 4)
+      for (black = i=0; i < 4; i++)
+	black += get2() << 2;
+    if (tag == 0x1017 || tag == 0x20400100)
+      cam_mul[0] = get2() / 256.0;
+    if (tag == 0x1018 || tag == 0x20400100)
+      cam_mul[2] = get2() / 256.0;
+    if (tag == 0x2011 && len == 2) {
+get2_256:
+      order = 0x4d4d;
+      cam_mul[0] = get2() / 256.0;
+      cam_mul[2] = get2() / 256.0;
+    }
+    if ((tag | 0x70) == 0x2070 && type == 4)
+      fseek (ifp, get4()+base, SEEK_SET);
+    if (tag == 0x2010 && type != 7)
+      load_raw = &CLASS olympus_e410_load_raw;
+    if (tag == 0x2020)
+      parse_thumb_note (base, 257, 258);
+    if (tag == 0x2040)
+      parse_makernote (base, 0x2040);
+    if (tag == 0xb028) {
+      fseek (ifp, get4(), SEEK_SET);
+      parse_thumb_note (base, 136, 137);
+    }
+    if (tag == 0x4001 && len > 500) {
+      i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126;
+      fseek (ifp, i, SEEK_CUR);
+get2_rggb:
+      FORC4 cam_mul[c ^ (c >> 1)] = get2();
+      fseek (ifp, 22, SEEK_CUR);
+      FORC4 sraw_mul[c ^ (c >> 1)] = get2();
+    }
+next:
+    fseek (ifp, save, SEEK_SET);
+  }
+quit:
+  order = sorder;
+}
+
+/*
+   Since the TIFF DateTime string has no timezone information,
+   assume that the camera's clock was set to Universal Time.
+ */
+void CLASS get_timestamp (int reversed)
+{
+  struct tm t;
+  char str[20];
+  int i;
+
+  str[19] = 0;
+  if (reversed)
+    for (i=19; i--; ) str[i] = fgetc(ifp);
+  else
+    fread (str, 19, 1, ifp);
+  memset (&t, 0, sizeof t);
+  if (sscanf (str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
+	&t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
+    return;
+  t.tm_year -= 1900;
+  t.tm_mon -= 1;
+  if (mktime(&t) > 0)
+    timestamp = mktime(&t);
+}
+
+void CLASS parse_exif (int base)
+{
+  unsigned kodak, entries, tag, type, len, save, c;
+  double expo;
+
+  kodak = !strncmp(make,"EASTMAN",7);
+  entries = get2();
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    switch (tag) {
+      case 33434:  shutter = getreal(type);		break;
+      case 33437:  aperture = getreal(type);		break;
+      case 34855:  iso_speed = get2();			break;
+      case 36867:
+      case 36868:  get_timestamp(0);			break;
+      case 37377:  if ((expo = -getreal(type)) < 128)
+		     shutter = pow (2, expo);		break;
+      case 37378:  aperture = pow (2, getreal(type)/2);	break;
+      case 37386:  focal_len = getreal(type);		break;
+      case 37500:  parse_makernote (base, 0);		break;
+      case 40962:  if (kodak) raw_width  = get4();	break;
+      case 40963:  if (kodak) raw_height = get4();	break;
+      case 41730:
+	if (get4() == 0x20002)
+	  for (exif_cfa=c=0; c < 8; c+=2)
+	    exif_cfa |= fgetc(ifp) * 0x01010101 << c;
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS parse_gps (int base)
+{
+  unsigned entries, tag, type, len, save, c;
+
+  entries = get2();
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    switch (tag) {
+      case 1: case 3: case 5:
+	gpsdata[29+tag/2] = getc(ifp);			break;
+      case 2: case 4: case 7:
+	FORC(6) gpsdata[tag/3*6+c] = get4();		break;
+      case 6:
+	FORC(2) gpsdata[18+c] = get4();			break;
+      case 18: case 29:
+	fgets ((char *) (gpsdata+14+tag/3), MIN(len,12), ifp);
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS romm_coeff (float romm_cam[3][3])
+{
+  static const float rgb_romm[3][3] =	/* ROMM == Kodak ProPhoto */
+  { {  2.034193, -0.727420, -0.306766 },
+    { -0.228811,  1.231729, -0.002922 },
+    { -0.008565, -0.153273,  1.161839 } };
+  int i, j, k;
+
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      for (cmatrix[i][j] = k=0; k < 3; k++)
+	cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j];
+}
+
+void CLASS parse_mos (int offset)
+{
+  char data[40];
+  int skip, from, i, c, neut[4], planes=0, frot=0;
+  static const char *mod[] =
+  { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22",
+    "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65",
+    "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7" };
+  float romm_cam[3][3];
+
+  fseek (ifp, offset, SEEK_SET);
+  while (1) {
+    if (get4() != 0x504b5453) break;
+    get4();
+    fread (data, 1, 40, ifp);
+    skip = get4();
+    from = ftell(ifp);
+    if (!strcmp(data,"JPEG_preview_data")) {
+      thumb_offset = from;
+      thumb_length = skip;
+    }
+    if (!strcmp(data,"icc_camera_profile")) {
+      profile_offset = from;
+      profile_length = skip;
+    }
+    if (!strcmp(data,"ShootObj_back_type")) {
+      fscanf (ifp, "%d", &i);
+      if ((unsigned) i < sizeof mod / sizeof (*mod))
+	strcpy (model, mod[i]);
+    }
+    if (!strcmp(data,"icc_camera_to_tone_matrix")) {
+      for (i=0; i < 9; i++)
+	romm_cam[0][i] = int_to_float(get4());
+      romm_coeff (romm_cam);
+    }
+    if (!strcmp(data,"CaptProf_color_matrix")) {
+      for (i=0; i < 9; i++)
+	fscanf (ifp, "%f", &romm_cam[0][i]);
+      romm_coeff (romm_cam);
+    }
+    if (!strcmp(data,"CaptProf_number_of_planes"))
+      fscanf (ifp, "%d", &planes);
+    if (!strcmp(data,"CaptProf_raw_data_rotation"))
+      fscanf (ifp, "%d", &flip);
+    if (!strcmp(data,"CaptProf_mosaic_pattern"))
+      FORC4 {
+	fscanf (ifp, "%d", &i);
+	if (i == 1) frot = c ^ (c >> 1);
+      }
+    if (!strcmp(data,"ImgProf_rotation_angle")) {
+      fscanf (ifp, "%d", &i);
+      flip = i - flip;
+    }
+    if (!strcmp(data,"NeutObj_neutrals") && !cam_mul[0]) {
+      FORC4 fscanf (ifp, "%d", neut+c);
+      FORC3 cam_mul[c] = (float) neut[0] / neut[c+1];
+    }
+    parse_mos (from);
+    fseek (ifp, skip+from, SEEK_SET);
+  }
+  if (planes)
+    filters = (planes == 1) * 0x01010101 *
+	(uchar) "\x94\x61\x16\x49"[(flip/90 + frot) & 3];
+}
+
+void CLASS linear_table (unsigned len)
+{
+  int i;
+  if (len > 0x1000) len = 0x1000;
+  read_shorts (curve, len);
+  for (i=len; i < 0x1000; i++)
+    curve[i] = curve[i-1];
+  maximum = curve[0xfff];
+}
+
+void CLASS parse_kodak_ifd (int base)
+{
+  unsigned entries, tag, type, len, save;
+  int i, c, wbi=-2, wbtemp=6500;
+  float mul[3], num;
+
+  entries = get2();
+  if (entries > 1024) return;
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    if (tag == 1020) wbi = getint(type);
+    if (tag == 1021 && len == 72) {		/* WB set in software */
+      fseek (ifp, 40, SEEK_CUR);
+      FORC3 cam_mul[c] = 2048.0 / get2();
+      wbi = -2;
+    }
+    if (tag == 2118) wbtemp = getint(type);
+    if (tag == 2130 + wbi)
+      FORC3 mul[c] = getreal(type);
+    if (tag == 2140 + wbi && wbi >= 0)
+      FORC3 {
+	for (num=i=0; i < 4; i++)
+	  num += getreal(type) * pow (wbtemp/100.0, i);
+	cam_mul[c] = 2048 / (num * mul[c]);
+      }
+    if (tag == 2317) linear_table (len);
+    if (tag == 6020) iso_speed = getint(type);
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS parse_minolta (int base);
+
+int CLASS parse_tiff_ifd (int base)
+{
+  unsigned entries, tag, type, len, plen=16, save;
+  int ifd, use_cm=0, cfa, i, j, c, ima_len=0;
+  char software[64], *cbuf, *cp;
+  uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256];
+  double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num;
+  double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 };
+  unsigned sony_curve[] = { 0,0,0,0,0,4095 };
+  unsigned *buf, sony_offset=0, sony_length=0, sony_key=0;
+  struct jhead jh;
+  FILE *sfp;
+
+  if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0])
+    return 1;
+  ifd = tiff_nifds++;
+  for (j=0; j < 4; j++)
+    for (i=0; i < 4; i++)
+      cc[j][i] = i == j;
+  entries = get2();
+  if (entries > 512) return 1;
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    switch (tag) {
+      case 17: case 18:
+	if (type == 3 && len == 1)
+	  cam_mul[(tag-17)*2] = get2() / 256.0;
+	break;
+      case 23:
+	if (type == 3) iso_speed = get2();
+	break;
+      case 36: case 37: case 38:
+	cam_mul[tag-0x24] = get2();
+	break;
+      case 39:
+	if (len < 50 || cam_mul[0]) break;
+	fseek (ifp, 12, SEEK_CUR);
+	FORC3 cam_mul[c] = get2();
+	break;
+      case 46:
+	if (type != 7 || fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) break;
+	thumb_offset = ftell(ifp) - 2;
+	thumb_length = len;
+	break;
+      case 2: case 256:			/* ImageWidth */
+	tiff_ifd[ifd].width = getint(type);
+	break;
+      case 3: case 257:			/* ImageHeight */
+	tiff_ifd[ifd].height = getint(type);
+	break;
+      case 258:				/* BitsPerSample */
+	tiff_ifd[ifd].samples = len & 7;
+	tiff_ifd[ifd].bps = get2();
+	break;
+      case 259:				/* Compression */
+	tiff_ifd[ifd].comp = get2();
+	break;
+      case 262:				/* PhotometricInterpretation */
+	tiff_ifd[ifd].phint = get2();
+	break;
+      case 270:				/* ImageDescription */
+	fread (desc, 512, 1, ifp);
+	break;
+      case 271:				/* Make */
+	fgets (make, 64, ifp);
+	break;
+      case 272:				/* Model */
+	fgets (model, 64, ifp);
+	break;
+      case 280:				/* Panasonic RW2 offset */
+	if (type != 4) break;
+	load_raw = &CLASS panasonic_load_raw;
+	load_flags = 0x2008;
+      case 273:				/* StripOffset */
+      case 513:
+	tiff_ifd[ifd].offset = get4()+base;
+	if (!tiff_ifd[ifd].bps) {
+	  fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET);
+	  if (ljpeg_start (&jh, 1)) {
+	    tiff_ifd[ifd].comp    = 6;
+	    tiff_ifd[ifd].width   = jh.wide << (jh.clrs == 2);
+	    tiff_ifd[ifd].height  = jh.high;
+	    tiff_ifd[ifd].bps     = jh.bits;
+	    tiff_ifd[ifd].samples = jh.clrs;
+	  }
+	}
+	break;
+      case 274:				/* Orientation */
+	tiff_ifd[ifd].flip = "50132467"[get2() & 7]-'0';
+	break;
+      case 277:				/* SamplesPerPixel */
+	tiff_ifd[ifd].samples = getint(type) & 7;
+	break;
+      case 279:				/* StripByteCounts */
+      case 514:
+	tiff_ifd[ifd].bytes = get4();
+	break;
+      case 305:  case 11:		/* Software */
+	fgets (software, 64, ifp);
+	if (!strncmp(software,"Adobe",5) ||
+	    !strncmp(software,"dcraw",5) ||
+	    !strncmp(software,"UFRaw",5) ||
+	    !strncmp(software,"Bibble",6) ||
+	    !strncmp(software,"Nikon Scan",10) ||
+	    !strcmp (software,"Digital Photo Professional"))
+	  is_raw = 0;
+	break;
+      case 306:				/* DateTime */
+	get_timestamp(0);
+	break;
+      case 315:				/* Artist */
+	fread (artist, 64, 1, ifp);
+	break;
+      case 322:				/* TileWidth */
+	tile_width = getint(type);
+	break;
+      case 323:				/* TileLength */
+	tile_length = getint(type);
+	break;
+      case 324:				/* TileOffsets */
+	tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4();
+	if (len == 4) {
+	  load_raw = &CLASS sinar_4shot_load_raw;
+	  is_raw = 5;
+	}
+	break;
+      case 330:				/* SubIFDs */
+	if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].width == 3872) {
+	  load_raw = &CLASS sony_arw_load_raw;
+	  data_offset = get4()+base;
+	  ifd++;  break;
+	}
+	while (len--) {
+	  i = ftell(ifp);
+	  fseek (ifp, get4()+base, SEEK_SET);
+	  if (parse_tiff_ifd (base)) break;
+	  fseek (ifp, i+4, SEEK_SET);
+	}
+	break;
+      case 400:
+	strcpy (make, "Sarnoff");
+	maximum = 0xfff;
+	break;
+      case 28688:
+	FORC4 sony_curve[c+1] = get2() >> 2 & 0xfff;
+	for (i=0; i < 5; i++)
+	  for (j = sony_curve[i]+1; j <= sony_curve[i+1]; j++)
+	    curve[j] = curve[j-1] + (1 << i);
+	break;
+      case 29184: sony_offset = get4();  break;
+      case 29185: sony_length = get4();  break;
+      case 29217: sony_key    = get4();  break;
+      case 29264:
+	parse_minolta (ftell(ifp));
+	raw_width = 0;
+	break;
+      case 29443:
+	FORC4 cam_mul[c ^ (c < 2)] = get2();
+	break;
+      case 29459:
+	FORC4 cam_mul[c ^ (c >> 1)] = get2();
+	break;
+      case 33405:			/* Model2 */
+	fgets (model2, 64, ifp);
+	break;
+      case 33422:			/* CFAPattern */
+      case 64777:			/* Kodak P-series */
+	if ((plen=len) > 16) plen = 16;
+	fread (cfa_pat, 1, plen, ifp);
+	for (colors=cfa=i=0; i < plen; i++) {
+	  colors += !(cfa & (1 << cfa_pat[i]));
+	  cfa |= 1 << cfa_pat[i];
+	}
+	if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3);	/* CMY */
+	if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4);	/* GMCY */
+	goto guess_cfa_pc;
+      case 33424:
+	fseek (ifp, get4()+base, SEEK_SET);
+	parse_kodak_ifd (base);
+	break;
+      case 33434:			/* ExposureTime */
+	shutter = getreal(type);
+	break;
+      case 33437:			/* FNumber */
+	aperture = getreal(type);
+	break;
+      case 34306:			/* Leaf white balance */
+	FORC4 cam_mul[c ^ 1] = 4096.0 / get2();
+	break;
+      case 34307:			/* Leaf CatchLight color matrix */
+	fread (software, 1, 7, ifp);
+	if (strncmp(software,"MATRIX",6)) break;
+	colors = 4;
+	for (raw_color = i=0; i < 3; i++) {
+	  FORC4 fscanf (ifp, "%f", &rgb_cam[i][c^1]);
+	  if (!use_camera_wb) continue;
+	  num = 0;
+	  FORC4 num += rgb_cam[i][c];
+	  FORC4 rgb_cam[i][c] /= num;
+	}
+	break;
+      case 34310:			/* Leaf metadata */
+	parse_mos (ftell(ifp));
+      case 34303:
+	strcpy (make, "Leaf");
+	break;
+      case 34665:			/* EXIF tag */
+	fseek (ifp, get4()+base, SEEK_SET);
+	parse_exif (base);
+	break;
+      case 34853:			/* GPSInfo tag */
+	fseek (ifp, get4()+base, SEEK_SET);
+	parse_gps (base);
+	break;
+      case 34675:			/* InterColorProfile */
+      case 50831:			/* AsShotICCProfile */
+	profile_offset = ftell(ifp);
+	profile_length = len;
+	break;
+      case 37122:			/* CompressedBitsPerPixel */
+	kodak_cbpp = get4();
+	break;
+      case 37386:			/* FocalLength */
+	focal_len = getreal(type);
+	break;
+      case 37393:			/* ImageNumber */
+	shot_order = getint(type);
+	break;
+      case 37400:			/* old Kodak KDC tag */
+	for (raw_color = i=0; i < 3; i++) {
+	  getreal(type);
+	  FORC3 rgb_cam[i][c] = getreal(type);
+	}
+	break;
+      case 46275:			/* Imacon tags */
+	strcpy (make, "Imacon");
+	data_offset = ftell(ifp);
+	ima_len = len;
+	break;
+      case 46279:
+	if (!ima_len) break;
+	fseek (ifp, 78, SEEK_CUR);
+	raw_width  = get4();
+	raw_height = get4();
+	left_margin = get4() & 7;
+	width = raw_width - left_margin - (get4() & 7);
+	top_margin = get4() & 7;
+	height = raw_height - top_margin - (get4() & 7);
+	if (raw_width == 7262) {
+	  height = 5444;
+	  width  = 7244;
+	  left_margin = 7;
+	}
+	fseek (ifp, 52, SEEK_CUR);
+	FORC3 cam_mul[c] = getreal(11);
+	fseek (ifp, 114, SEEK_CUR);
+	flip = (get2() >> 7) * 90;
+	if (width * height * 6 == ima_len) {
+	  if (flip % 180 == 90) SWAP(width,height);
+	  filters = flip = 0;
+	}
+	sprintf (model, "Ixpress %d-Mp", height*width/1000000);
+	load_raw = &CLASS imacon_full_load_raw;
+	if (filters) {
+	  if (left_margin & 1) filters = 0x61616161;
+	  load_raw = &CLASS unpacked_load_raw;
+	}
+	maximum = 0xffff;
+	break;
+      case 50454:			/* Sinar tag */
+      case 50455:
+	if (!(cbuf = (char *) malloc(len))) break;
+	fread (cbuf, 1, len, ifp);
+	for (cp = cbuf-1; cp && cp < cbuf+len; cp = strchr(cp,'\n'))
+	  if (!strncmp (++cp,"Neutral ",8))
+	    sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2);
+	free (cbuf);
+	break;
+      case 50458:
+	if (!make[0]) strcpy (make, "Hasselblad");
+	break;
+      case 50459:			/* Hasselblad tag */
+	i = order;
+	j = ftell(ifp);
+	c = tiff_nifds;
+	order = get2();
+	fseek (ifp, j+(get2(),get4()), SEEK_SET);
+	parse_tiff_ifd (j);
+	maximum = 0xffff;
+	tiff_nifds = c;
+	order = i;
+	break;
+      case 50706:			/* DNGVersion */
+	FORC4 dng_version = (dng_version << 8) + fgetc(ifp);
+	if (!make[0]) strcpy (make, "DNG");
+	is_raw = 1;
+	break;
+      case 50710:			/* CFAPlaneColor */
+	if (len > 4) len = 4;
+	colors = len;
+	fread (cfa_pc, 1, colors, ifp);
+guess_cfa_pc:
+	FORCC tab[cfa_pc[c]] = c;
+	cdesc[c] = 0;
+	for (i=16; i--; )
+	  filters = filters << 2 | tab[cfa_pat[i % plen]];
+	break;
+      case 50711:			/* CFALayout */
+	if (get2() == 2) {
+	  fuji_width = 1;
+	  filters = 0x49494949;
+	}
+	break;
+      case 291:
+      case 50712:			/* LinearizationTable */
+	linear_table (len);
+	break;
+      case 50714:			/* BlackLevel */
+      case 50715:			/* BlackLevelDeltaH */
+      case 50716:			/* BlackLevelDeltaV */
+	for (dblack=i=0; i < len; i++)
+	  dblack += getreal(type);
+	black += dblack/len + 0.5;
+	break;
+      case 50717:			/* WhiteLevel */
+	maximum = getint(type);
+	break;
+      case 50718:			/* DefaultScale */
+	pixel_aspect  = getreal(type);
+	pixel_aspect /= getreal(type);
+	break;
+      case 50721:			/* ColorMatrix1 */
+      case 50722:			/* ColorMatrix2 */
+	FORCC for (j=0; j < 3; j++)
+	  cm[c][j] = getreal(type);
+	use_cm = 1;
+	break;
+      case 50723:			/* CameraCalibration1 */
+      case 50724:			/* CameraCalibration2 */
+	for (i=0; i < colors; i++)
+	  FORCC cc[i][c] = getreal(type);
+      case 50727:			/* AnalogBalance */
+	FORCC ab[c] = getreal(type);
+	break;
+      case 50728:			/* AsShotNeutral */
+	FORCC asn[c] = getreal(type);
+	break;
+      case 50729:			/* AsShotWhiteXY */
+	xyz[0] = getreal(type);
+	xyz[1] = getreal(type);
+	xyz[2] = 1 - xyz[0] - xyz[1];
+	FORC3 xyz[c] /= d65_white[c];
+	break;
+      case 50740:			/* DNGPrivateData */
+	if (dng_version) break;
+	parse_minolta (j = get4()+base);
+	fseek (ifp, j, SEEK_SET);
+	parse_tiff_ifd (base);
+	break;
+      case 50752:
+	read_shorts (cr2_slice, 3);
+	break;
+      case 50829:			/* ActiveArea */
+	top_margin = getint(type);
+	left_margin = getint(type);
+	height = getint(type) - top_margin;
+	width = getint(type) - left_margin;
+	break;
+      case 64772:			/* Kodak P-series */
+	if (len < 13) break;
+	fseek (ifp, 16, SEEK_CUR);
+	data_offset = get4();
+	fseek (ifp, 28, SEEK_CUR);
+	data_offset += get4();
+	load_raw = &CLASS packed_12_load_raw;
+	break;
+      case 65026:
+	if (type == 2) fgets (model2, 64, ifp);
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  if (sony_length && (buf = (unsigned *) malloc(sony_length))) {
+    fseek (ifp, sony_offset, SEEK_SET);
+    fread (buf, sony_length, 1, ifp);
+    sony_decrypt (buf, sony_length/4, 1, sony_key);
+    sfp = ifp;
+    if ((ifp = tmpfile())) {
+      fwrite (buf, sony_length, 1, ifp);
+      fseek (ifp, 0, SEEK_SET);
+      parse_tiff_ifd (-sony_offset);
+      fclose (ifp);
+    }
+    ifp = sfp;
+    free (buf);
+  }
+  for (i=0; i < colors; i++)
+    FORCC cc[i][c] *= ab[i];
+  if (use_cm) {
+    FORCC for (i=0; i < 3; i++)
+      for (cam_xyz[c][i]=j=0; j < colors; j++)
+	cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i];
+    cam_xyz_coeff (cam_xyz);
+  }
+  if (asn[0]) {
+    cam_mul[3] = 0;
+    FORCC cam_mul[c] = 1 / asn[c];
+  }
+  if (!use_cm)
+    FORCC pre_mul[c] /= cc[c][c];
+  return 0;
+}
+
+void CLASS parse_tiff (int base)
+{
+  int doff, max_samp=0, raw=-1, thm=-1, i;
+  struct jhead jh;
+
+  fseek (ifp, base, SEEK_SET);
+  order = get2();
+  if (order != 0x4949 && order != 0x4d4d) return;
+  get2();
+  memset (tiff_ifd, 0, sizeof tiff_ifd);
+  tiff_nifds = 0;
+  while ((doff = get4())) {
+    fseek (ifp, doff+base, SEEK_SET);
+    if (parse_tiff_ifd (base)) break;
+  }
+  thumb_misc = 16;
+  if (thumb_offset) {
+    fseek (ifp, thumb_offset, SEEK_SET);
+    if (ljpeg_start (&jh, 1)) {
+      thumb_misc   = jh.bits;
+      thumb_width  = jh.wide;
+      thumb_height = jh.high;
+    }
+  }
+  for (i=0; i < tiff_nifds; i++) {
+    if (max_samp < tiff_ifd[i].samples)
+	max_samp = tiff_ifd[i].samples;
+    if (max_samp > 3) max_samp = 3;
+    if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) &&
+	tiff_ifd[i].width*tiff_ifd[i].height > raw_width*raw_height) {
+      raw_width     = tiff_ifd[i].width;
+      raw_height    = tiff_ifd[i].height;
+      tiff_bps      = tiff_ifd[i].bps;
+      tiff_compress = tiff_ifd[i].comp;
+      data_offset   = tiff_ifd[i].offset;
+      tiff_flip     = tiff_ifd[i].flip;
+      tiff_samples  = tiff_ifd[i].samples;
+      raw = i;
+    }
+  }
+  fuji_width *= (raw_width+1)/2;
+  if (tiff_ifd[0].flip) tiff_flip = tiff_ifd[0].flip;
+  if (raw >= 0 && !load_raw)
+    switch (tiff_compress) {
+      case 0:  case 1:
+	switch (tiff_bps) {
+	  case  8: load_raw = &CLASS eight_bit_load_raw;	break;
+	  case 12: load_raw = &CLASS packed_12_load_raw;
+		   if (tiff_ifd[raw].phint == 2)
+		     load_flags = 6;
+		   if (strncmp(make,"PENTAX",6)) break;
+	  case 14:
+	  case 16: load_raw = &CLASS unpacked_load_raw;		break;
+	}
+	if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) {
+	  load_raw = &CLASS packed_12_load_raw;
+	  load_flags = 273;
+	}
+	break;
+      case 6:  case 7:  case 99:
+	load_raw = &CLASS lossless_jpeg_load_raw;		break;
+      case 262:
+	load_raw = &CLASS kodak_262_load_raw;			break;
+      case 32767:
+	if (tiff_ifd[raw].bytes*8 != raw_width*raw_height*tiff_bps) {
+	  raw_height += 8;
+	  load_raw = &CLASS sony_arw_load_raw;			break;
+	}
+	if (tiff_bps == 8) {
+	  tiff_bps = 12;
+	  load_raw = &CLASS sony_arw2_load_raw;			break;
+	}
+	load_flags = 79;
+      case 32769:
+	load_flags++;
+      case 32773:
+	load_raw = &CLASS packed_12_load_raw;			break;
+      case 34713:
+	load_raw = &CLASS nikon_compressed_load_raw;		break;
+      case 65535:
+	load_raw = &CLASS pentax_k10_load_raw;			break;
+      case 65000:
+	switch (tiff_ifd[raw].phint) {
+	  case 2: load_raw = &CLASS kodak_rgb_load_raw;   filters = 0;  break;
+	  case 6: load_raw = &CLASS kodak_ycbcr_load_raw; filters = 0;  break;
+	  case 32803: load_raw = &CLASS kodak_65000_load_raw;
+	}
+      case 32867: break;
+      default: is_raw = 0;
+    }
+  if (!dng_version)
+    if ( (tiff_samples == 3 && tiff_ifd[raw].bytes &&
+	  tiff_bps != 14 && tiff_bps != 2048)
+      || (tiff_bps == 8 && !strstr(make,"KODAK") && !strstr(make,"Kodak") &&
+	  !strstr(model2,"DEBUG RAW")))
+      is_raw = 0;
+  for (i=0; i < tiff_nifds; i++)
+    if (i != raw && tiff_ifd[i].samples == max_samp &&
+	tiff_ifd[i].width * tiff_ifd[i].height / SQR(tiff_ifd[i].bps+1) >
+	      thumb_width *       thumb_height / SQR(thumb_misc+1)) {
+      thumb_width  = tiff_ifd[i].width;
+      thumb_height = tiff_ifd[i].height;
+      thumb_offset = tiff_ifd[i].offset;
+      thumb_length = tiff_ifd[i].bytes;
+      thumb_misc   = tiff_ifd[i].bps;
+      thm = i;
+    }
+  if (thm >= 0) {
+    thumb_misc |= tiff_ifd[thm].samples << 5;
+    switch (tiff_ifd[thm].comp) {
+      case 0:
+	write_thumb = &CLASS layer_thumb;
+	break;
+      case 1:
+	if (tiff_ifd[thm].bps > 8)
+	  thumb_load_raw = &CLASS kodak_thumb_load_raw;
+	else
+	  write_thumb = &CLASS ppm_thumb;
+	break;
+      case 65000:
+	thumb_load_raw = tiff_ifd[thm].phint == 6 ?
+		&CLASS kodak_ycbcr_load_raw : &CLASS kodak_rgb_load_raw;
+    }
+  }
+}
+
+void CLASS parse_minolta (int base)
+{
+  int save, tag, len, offset, high=0, wide=0, i, c;
+  short sorder=order;
+
+  fseek (ifp, base, SEEK_SET);
+  if (fgetc(ifp) || fgetc(ifp)-'M' || fgetc(ifp)-'R') return;
+  order = fgetc(ifp) * 0x101;
+  offset = base + get4() + 8;
+  while ((save=ftell(ifp)) < offset) {
+    for (tag=i=0; i < 4; i++)
+      tag = tag << 8 | fgetc(ifp);
+    len = get4();
+    switch (tag) {
+      case 0x505244:				/* PRD */
+	fseek (ifp, 8, SEEK_CUR);
+	high = get2();
+	wide = get2();
+	break;
+      case 0x574247:				/* WBG */
+	get4();
+	i = strcmp(model,"DiMAGE A200") ? 0:3;
+	FORC4 cam_mul[c ^ (c >> 1) ^ i] = get2();
+	break;
+      case 0x545457:				/* TTW */
+	parse_tiff (ftell(ifp));
+	data_offset = offset;
+    }
+    fseek (ifp, save+len+8, SEEK_SET);
+  }
+  raw_height = high;
+  raw_width  = wide;
+  order = sorder;
+}
+
+/*
+   Many cameras have a "debug mode" that writes JPEG and raw
+   at the same time.  The raw file has no header, so try to
+   to open the matching JPEG file and read its metadata.
+ */
+void CLASS parse_external_jpeg()
+{
+  const char *file, *ext;
+  char *jname, *jfile, *jext;
+  FILE *save=ifp;
+
+  ext  = strrchr (ifname, '.');
+  file = strrchr (ifname, '/');
+  if (!file) file = strrchr (ifname, '\\');
+  if (!file) file = ifname-1;
+  file++;
+  if (!ext || strlen(ext) != 4 || ext-file != 8) return;
+  jname = (char *) malloc (strlen(ifname) + 1);
+  merror (jname, "parse_external_jpeg()");
+  strcpy (jname, ifname);
+  jfile = file - ifname + jname;
+  jext  = ext  - ifname + jname;
+  if (strcasecmp (ext, ".jpg")) {
+    strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg");
+    if (isdigit(*file)) {
+      memcpy (jfile, file+4, 4);
+      memcpy (jfile+4, file, 4);
+    }
+  } else
+    while (isdigit(*--jext)) {
+      if (*jext != '9') {
+        (*jext)++;
+	break;
+      }
+      *jext = '0';
+    }
+  if (strcmp (jname, ifname)) {
+    if ((ifp = fopen (jname, "rb"))) {
+      if (verbose)
+	fprintf (stderr,_("Reading metadata from %s ...\n"), jname);
+      parse_tiff (12);
+      thumb_offset = 0;
+      is_raw = 1;
+      fclose (ifp);
+    }
+  }
+  if (!timestamp)
+    fprintf (stderr,_("Failed to read metadata from %s\n"), jname);
+  free (jname);
+  ifp = save;
+}
+
+/*
+   CIFF block 0x1030 contains an 8x8 white sample.
+   Load this into white[][] for use in scale_colors().
+ */
+void CLASS ciff_block_1030()
+{
+  static const ushort key[] = { 0x410, 0x45f3 };
+  int i, bpp, row, col, vbits=0;
+  unsigned long bitbuf=0;
+
+  if ((get2(),get4()) != 0x80008 || !get4()) return;
+  bpp = get2();
+  if (bpp != 10 && bpp != 12) return;
+  for (i=row=0; row < 8; row++)
+    for (col=0; col < 8; col++) {
+      if (vbits < bpp) {
+	bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
+	vbits += 16;
+      }
+      white[row][col] =
+	bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp);
+      vbits -= bpp;
+    }
+}
+
+/*
+   Parse a CIFF file, better known as Canon CRW format.
+ */
+void CLASS parse_ciff (int offset, int length)
+{
+  int tboff, nrecs, c, type, len, save, wbi=-1;
+  ushort key[] = { 0x410, 0x45f3 };
+
+  fseek (ifp, offset+length-4, SEEK_SET);
+  tboff = get4() + offset;
+  fseek (ifp, tboff, SEEK_SET);
+  nrecs = get2();
+  if (nrecs > 100) return;
+  while (nrecs--) {
+    type = get2();
+    len  = get4();
+    save = ftell(ifp) + 4;
+    fseek (ifp, offset+get4(), SEEK_SET);
+    if ((((type >> 8) + 8) | 8) == 0x38)
+      parse_ciff (ftell(ifp), len);	/* Parse a sub-table */
+
+    if (type == 0x0810)
+      fread (artist, 64, 1, ifp);
+    if (type == 0x080a) {
+      fread (make, 64, 1, ifp);
+      fseek (ifp, strlen(make) - 63, SEEK_CUR);
+      fread (model, 64, 1, ifp);
+    }
+    if (type == 0x1810) {
+      fseek (ifp, 12, SEEK_CUR);
+      flip = get4();
+    }
+    if (type == 0x1835)			/* Get the decoder table */
+      tiff_compress = get4();
+    if (type == 0x2007) {
+      thumb_offset = ftell(ifp);
+      thumb_length = len;
+    }
+    if (type == 0x1818) {
+      shutter = pow (2, -int_to_float((get4(),get4())));
+      aperture = pow (2, int_to_float(get4())/2);
+    }
+    if (type == 0x102a) {
+      iso_speed = pow (2, (get4(),get2())/32.0 - 4) * 50;
+      aperture  = pow (2, (get2(),(short)get2())/64.0);
+      shutter   = pow (2,-((short)get2())/32.0);
+      wbi = (get2(),get2());
+      if (wbi > 17) wbi = 0;
+      fseek (ifp, 32, SEEK_CUR);
+      if (shutter > 1e6) shutter = get2()/10.0;
+    }
+    if (type == 0x102c) {
+      if (get2() > 512) {		/* Pro90, G1 */
+	fseek (ifp, 118, SEEK_CUR);
+	FORC4 cam_mul[c ^ 2] = get2();
+      } else {				/* G2, S30, S40 */
+	fseek (ifp, 98, SEEK_CUR);
+	FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2();
+      }
+    }
+    if (type == 0x0032) {
+      if (len == 768) {			/* EOS D30 */
+	fseek (ifp, 72, SEEK_CUR);
+	FORC4 cam_mul[c ^ (c >> 1)] = 1024.0 / get2();
+	if (!wbi) cam_mul[0] = -1;	/* use my auto white balance */
+      } else if (!cam_mul[0]) {
+	if (get2() == key[0])		/* Pro1, G6, S60, S70 */
+	  c = (strstr(model,"Pro1") ?
+	      "012346000000000000":"01345:000000006008")[wbi]-'0'+ 2;
+	else {				/* G3, G5, S45, S50 */
+	  c = "023457000000006000"[wbi]-'0';
+	  key[0] = key[1] = 0;
+	}
+	fseek (ifp, 78 + c*8, SEEK_CUR);
+	FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2() ^ key[c & 1];
+	if (!wbi) cam_mul[0] = -1;
+      }
+    }
+    if (type == 0x10a9) {		/* D60, 10D, 300D, and clones */
+      if (len > 66) wbi = "0134567028"[wbi]-'0';
+      fseek (ifp, 2 + wbi*8, SEEK_CUR);
+      FORC4 cam_mul[c ^ (c >> 1)] = get2();
+    }
+    if (type == 0x1030 && (0x18040 >> wbi & 1))
+      ciff_block_1030();		/* all that don't have 0x10a9 */
+    if (type == 0x1031) {
+      raw_width = (get2(),get2());
+      raw_height = get2();
+    }
+    if (type == 0x5029) {
+      focal_len = len >> 16;
+      if ((len & 0xffff) == 2) focal_len /= 32;
+    }
+    if (type == 0x5813) flash_used = int_to_float(len);
+    if (type == 0x5814) canon_ev   = int_to_float(len);
+    if (type == 0x5817) shot_order = len;
+    if (type == 0x5834) unique_id  = len;
+    if (type == 0x580e) timestamp  = len;
+    if (type == 0x180e) timestamp  = get4();
+#ifdef LOCALTIME
+    if ((type | 0x4000) == 0x580e)
+      timestamp = mktime (gmtime (&timestamp));
+#endif
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS parse_rollei()
+{
+  char line[128], *val;
+  struct tm t;
+
+  fseek (ifp, 0, SEEK_SET);
+  memset (&t, 0, sizeof t);
+  do {
+    fgets (line, 128, ifp);
+    if ((val = strchr(line,'=')))
+      *val++ = 0;
+    else
+      val = line + strlen(line);
+    if (!strcmp(line,"DAT"))
+      sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
+    if (!strcmp(line,"TIM"))
+      sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
+    if (!strcmp(line,"HDR"))
+      thumb_offset = atoi(val);
+    if (!strcmp(line,"X  "))
+      raw_width = atoi(val);
+    if (!strcmp(line,"Y  "))
+      raw_height = atoi(val);
+    if (!strcmp(line,"TX "))
+      thumb_width = atoi(val);
+    if (!strcmp(line,"TY "))
+      thumb_height = atoi(val);
+  } while (strncmp(line,"EOHD",4));
+  data_offset = thumb_offset + thumb_width * thumb_height * 2;
+  t.tm_year -= 1900;
+  t.tm_mon -= 1;
+  if (mktime(&t) > 0)
+    timestamp = mktime(&t);
+  strcpy (make, "Rollei");
+  strcpy (model,"d530flex");
+  write_thumb = &CLASS rollei_thumb;
+}
+
+void CLASS parse_sinar_ia()
+{
+  int entries, off;
+  char str[8], *cp;
+
+  order = 0x4949;
+  fseek (ifp, 4, SEEK_SET);
+  entries = get4();
+  fseek (ifp, get4(), SEEK_SET);
+  while (entries--) {
+    off = get4(); get4();
+    fread (str, 8, 1, ifp);
+    if (!strcmp(str,"META"))   meta_offset = off;
+    if (!strcmp(str,"THUMB")) thumb_offset = off;
+    if (!strcmp(str,"RAW0"))   data_offset = off;
+  }
+  fseek (ifp, meta_offset+20, SEEK_SET);
+  fread (make, 64, 1, ifp);
+  make[63] = 0;
+  if ((cp = strchr(make,' '))) {
+    strcpy (model, cp+1);
+    *cp = 0;
+  }
+  raw_width  = get2();
+  raw_height = get2();
+  load_raw = &CLASS unpacked_load_raw;
+  thumb_width = (get4(),get2());
+  thumb_height = get2();
+  write_thumb = &CLASS ppm_thumb;
+  maximum = 0x3fff;
+}
+
+void CLASS parse_phase_one (int base)
+{
+  unsigned entries, tag, type, len, data, save, i, c;
+  float romm_cam[3][3];
+  char *cp;
+
+  memset (&ph1, 0, sizeof ph1);
+  fseek (ifp, base, SEEK_SET);
+  order = get4() & 0xffff;
+  if (get4() >> 8 != 0x526177) return;		/* "Raw" */
+  fseek (ifp, get4()+base, SEEK_SET);
+  entries = get4();
+  get4();
+  while (entries--) {
+    tag  = get4();
+    type = get4();
+    len  = get4();
+    data = get4();
+    save = ftell(ifp);
+    fseek (ifp, base+data, SEEK_SET);
+    switch (tag) {
+      case 0x100:  flip = "0653"[data & 3]-'0';  break;
+      case 0x106:
+	for (i=0; i < 9; i++)
+	  romm_cam[0][i] = getreal(11);
+	romm_coeff (romm_cam);
+	break;
+      case 0x107:
+	FORC3 cam_mul[c] = getreal(11);
+	break;
+      case 0x108:  raw_width     = data;	break;
+      case 0x109:  raw_height    = data;	break;
+      case 0x10a:  left_margin   = data;	break;
+      case 0x10b:  top_margin    = data;	break;
+      case 0x10c:  width         = data;	break;
+      case 0x10d:  height        = data;	break;
+      case 0x10e:  ph1.format    = data;	break;
+      case 0x10f:  data_offset   = data+base;	break;
+      case 0x110:  meta_offset   = data+base;
+		   meta_length   = len;			break;
+      case 0x112:  ph1.key_off   = save - 4;		break;
+      case 0x210:  ph1.tag_210   = int_to_float(data);	break;
+      case 0x21a:  ph1.tag_21a   = data;		break;
+      case 0x21c:  strip_offset  = data+base;		break;
+      case 0x21d:  ph1.black     = data;		break;
+      case 0x222:  ph1.split_col = data - left_margin;	break;
+      case 0x223:  ph1.black_off = data+base;		break;
+      case 0x301:
+	model[63] = 0;
+	fread (model, 1, 63, ifp);
+	if ((cp = strstr(model," camera"))) *cp = 0;
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  load_raw = ph1.format < 3 ?
+	&CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c;
+  maximum = 0xffff;
+  strcpy (make, "Phase One");
+  if (model[0]) return;
+  switch (raw_height) {
+    case 2060: strcpy (model,"LightPhase");	break;
+    case 2682: strcpy (model,"H 10");		break;
+    case 4128: strcpy (model,"H 20");		break;
+    case 5488: strcpy (model,"H 25");		break;
+  }
+}
+
+void CLASS parse_fuji (int offset)
+{
+  unsigned entries, tag, len, save, c;
+
+  fseek (ifp, offset, SEEK_SET);
+  entries = get4();
+  if (entries > 255) return;
+  while (entries--) {
+    tag = get2();
+    len = get2();
+    save = ftell(ifp);
+    if (tag == 0x100) {
+      raw_height = get2();
+      raw_width  = get2();
+    } else if (tag == 0x121) {
+      height = get2();
+      if ((width = get2()) == 4284) width += 3;
+    } else if (tag == 0x130)
+      fuji_layout = fgetc(ifp) >> 7;
+    if (tag == 0x2ff0)
+      FORC4 cam_mul[c ^ 1] = get2();
+    fseek (ifp, save+len, SEEK_SET);
+  }
+  height <<= fuji_layout;
+  width  >>= fuji_layout;
+}
+
+int CLASS parse_jpeg (int offset)
+{
+  int len, save, hlen, mark;
+
+  fseek (ifp, offset, SEEK_SET);
+  if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return 0;
+
+  while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda) {
+    order = 0x4d4d;
+    len   = get2() - 2;
+    save  = ftell(ifp);
+    if (mark == 0xc0 || mark == 0xc3) {
+      fgetc(ifp);
+      raw_height = get2();
+      raw_width  = get2();
+    }
+    order = get2();
+    hlen  = get4();
+    if (get4() == 0x48454150)		/* "HEAP" */
+      parse_ciff (save+hlen, len-hlen);
+    parse_tiff (save+6);
+    fseek (ifp, save+len, SEEK_SET);
+  }
+  return 1;
+}
+
+void CLASS parse_riff()
+{
+  unsigned i, size, end;
+  char tag[4], date[64], month[64];
+  static const char mon[12][4] =
+  { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
+  struct tm t;
+
+  order = 0x4949;
+  fread (tag, 4, 1, ifp);
+  size = get4();
+  end = ftell(ifp) + size;
+  if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) {
+    get4();
+    while (ftell(ifp)+7 < end)
+      parse_riff();
+  } else if (!memcmp(tag,"nctg",4)) {
+    while (ftell(ifp)+7 < end) {
+      i = get2();
+      size = get2();
+      if ((i+1) >> 1 == 10 && size == 20)
+	get_timestamp(0);
+      else fseek (ifp, size, SEEK_CUR);
+    }
+  } else if (!memcmp(tag,"IDIT",4) && size < 64) {
+    fread (date, 64, 1, ifp);
+    date[size] = 0;
+    memset (&t, 0, sizeof t);
+    if (sscanf (date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday,
+	&t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) == 6) {
+      for (i=0; i < 12 && strcasecmp(mon[i],month); i++);
+      t.tm_mon = i;
+      t.tm_year -= 1900;
+      if (mktime(&t) > 0)
+	timestamp = mktime(&t);
+    }
+  } else
+    fseek (ifp, size, SEEK_CUR);
+}
+
+void CLASS parse_smal (int offset, int fsize)
+{
+  int ver;
+
+  fseek (ifp, offset+2, SEEK_SET);
+  order = 0x4949;
+  ver = fgetc(ifp);
+  if (ver == 6)
+    fseek (ifp, 5, SEEK_CUR);
+  if (get4() != fsize) return;
+  if (ver > 6) data_offset = get4();
+  raw_height = height = get2();
+  raw_width  = width  = get2();
+  strcpy (make, "SMaL");
+  sprintf (model, "v%d %dx%d", ver, width, height);
+  if (ver == 6) load_raw = &CLASS smal_v6_load_raw;
+  if (ver == 9) load_raw = &CLASS smal_v9_load_raw;
+}
+
+void CLASS parse_cine()
+{
+  unsigned off_head, off_setup, off_image, i;
+
+  order = 0x4949;
+  fseek (ifp, 4, SEEK_SET);
+  is_raw = get2() == 2;
+  fseek (ifp, 14, SEEK_CUR);
+  is_raw *= get4();
+  off_head = get4();
+  off_setup = get4();
+  off_image = get4();
+  timestamp = get4();
+  if ((i = get4())) timestamp = i;
+  fseek (ifp, off_head+4, SEEK_SET);
+  raw_width = get4();
+  raw_height = get4();
+  switch (get2(),get2()) {
+    case  8:  load_raw = &CLASS eight_bit_load_raw;  break;
+    case 16:  load_raw = &CLASS  unpacked_load_raw;
+  }
+  fseek (ifp, off_setup+792, SEEK_SET);
+  strcpy (make, "CINE");
+  sprintf (model, "%d", get4());
+  fseek (ifp, 12, SEEK_CUR);
+  switch ((i=get4()) & 0xffffff) {
+    case  3:  filters = 0x94949494;  break;
+    case  4:  filters = 0x49494949;  break;
+    default:  is_raw = 0;
+  }
+  fseek (ifp, 72, SEEK_CUR);
+  switch ((get4()+3600) % 360) {
+    case 270:  flip = 4;  break;
+    case 180:  flip = 1;  break;
+    case  90:  flip = 7;  break;
+    case   0:  flip = 2;
+  }
+  cam_mul[0] = getreal(11);
+  cam_mul[2] = getreal(11);
+  maximum = ~(-1 << get4());
+  fseek (ifp, 668, SEEK_CUR);
+  shutter = get4()/1000000000.0;
+  fseek (ifp, off_image, SEEK_SET);
+  if (shot_select < is_raw)
+    fseek (ifp, shot_select*8, SEEK_CUR);
+  data_offset  = (INT64) get4() + 8;
+  data_offset += (INT64) get4() << 32;
+}
+
+char * CLASS foveon_gets (int offset, char *str, int len)
+{
+  int i;
+  fseek (ifp, offset, SEEK_SET);
+  for (i=0; i < len-1; i++)
+    if ((str[i] = get2()) == 0) break;
+  str[i] = 0;
+  return str;
+}
+
+void CLASS parse_foveon()
+{
+  int entries, img=0, off, len, tag, save, i, wide, high, pent, poff[256][2];
+  char name[64], value[64];
+
+  order = 0x4949;			/* Little-endian */
+  fseek (ifp, 36, SEEK_SET);
+  flip = get4();
+  fseek (ifp, -4, SEEK_END);
+  fseek (ifp, get4(), SEEK_SET);
+  if (get4() != 0x64434553) return;	/* SECd */
+  entries = (get4(),get4());
+  while (entries--) {
+    off = get4();
+    len = get4();
+    tag = get4();
+    save = ftell(ifp);
+    fseek (ifp, off, SEEK_SET);
+    if (get4() != (0x20434553 | (tag << 24))) return;
+    switch (tag) {
+      case 0x47414d49:			/* IMAG */
+      case 0x32414d49:			/* IMA2 */
+	fseek (ifp, 12, SEEK_CUR);
+	wide = get4();
+	high = get4();
+	if (wide > raw_width && high > raw_height) {
+	  raw_width  = wide;
+	  raw_height = high;
+	  data_offset = off+24;
+	}
+	fseek (ifp, off+28, SEEK_SET);
+	if (fgetc(ifp) == 0xff && fgetc(ifp) == 0xd8
+		&& thumb_length < len-28) {
+	  thumb_offset = off+28;
+	  thumb_length = len-28;
+	  write_thumb = &CLASS jpeg_thumb;
+	}
+	if (++img == 2 && !thumb_length) {
+	  thumb_offset = off+24;
+	  thumb_width = wide;
+	  thumb_height = high;
+	  write_thumb = &CLASS foveon_thumb;
+	}
+	break;
+      case 0x464d4143:			/* CAMF */
+	meta_offset = off+24;
+	meta_length = len-28;
+	if (meta_length > 0x20000)
+	    meta_length = 0x20000;
+	break;
+      case 0x504f5250:			/* PROP */
+	pent = (get4(),get4());
+	fseek (ifp, 12, SEEK_CUR);
+	off += pent*8 + 24;
+	if ((unsigned) pent > 256) pent=256;
+	for (i=0; i < pent*2; i++)
+	  poff[0][i] = off + get4()*2;
+	for (i=0; i < pent; i++) {
+	  foveon_gets (poff[i][0], name, 64);
+	  foveon_gets (poff[i][1], value, 64);
+	  if (!strcmp (name, "ISO"))
+	    iso_speed = atoi(value);
+	  if (!strcmp (name, "CAMMANUF"))
+	    strcpy (make, value);
+	  if (!strcmp (name, "CAMMODEL"))
+	    strcpy (model, value);
+	  if (!strcmp (name, "WB_DESC"))
+	    strcpy (model2, value);
+	  if (!strcmp (name, "TIME"))
+	    timestamp = atoi(value);
+	  if (!strcmp (name, "EXPTIME"))
+	    shutter = atoi(value) / 1000000.0;
+	  if (!strcmp (name, "APERTURE"))
+	    aperture = atof(value);
+	  if (!strcmp (name, "FLENGTH"))
+	    focal_len = atof(value);
+	}
+#ifdef LOCALTIME
+	timestamp = mktime (gmtime (&timestamp));
+#endif
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  is_foveon = 1;
+}
+
+/*
+   Thanks to Adobe for providing these excellent CAM -> XYZ matrices!
+ */
+void CLASS adobe_coeff (const char *make, const char *model)
+{
+  static const struct {
+    const char *prefix;
+    short black, maximum, trans[12];
+  } table[] = {
+    { "Apple QuickTake", 0, 0,		/* DJC */
+	{ 21392,-5653,-3353,2406,8010,-415,7166,1427,2078 } },
+    { "Canon EOS D2000", 0, 0,
+	{ 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+    { "Canon EOS D6000", 0, 0,
+	{ 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+    { "Canon EOS D30", 0, 0,
+	{ 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } },
+    { "Canon EOS D60", 0, 0xfa0,
+	{ 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } },
+    { "Canon EOS 5D Mark II", 0, 0x3cf0,
+	{ 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } },
+    { "Canon EOS 5D", 0, 0xe6c,
+	{ 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } },
+    { "Canon EOS 10D", 0, 0xfa0,
+	{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+    { "Canon EOS 20Da", 0, 0,
+	{ 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } },
+    { "Canon EOS 20D", 0, 0xfff,
+	{ 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } },
+    { "Canon EOS 30D", 0, 0,
+	{ 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } },
+    { "Canon EOS 40D", 0, 0x3f60,
+	{ 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } },
+    { "Canon EOS 50D", 0, 0x3d93,
+	{ 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } },
+    { "Canon EOS 300D", 0, 0xfa0,
+	{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+    { "Canon EOS 350D", 0, 0xfff,
+	{ 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } },
+    { "Canon EOS 400D", 0, 0xe8e,
+	{ 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } },
+    { "Canon EOS 450D", 0, 0x390d,
+	{ 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } },
+    { "Canon EOS 1000D", 0, 0xe43,
+	{ 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } },
+    { "Canon EOS-1Ds Mark III", 0, 0x3bb0,
+	{ 5859,-211,-930,-8255,16017,2353,-1732,1887,7448 } },
+    { "Canon EOS-1Ds Mark II", 0, 0xe80,
+	{ 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } },
+    { "Canon EOS-1D Mark II N", 0, 0xe80,
+	{ 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } },
+    { "Canon EOS-1D Mark III", 0, 0x3bb0,
+	{ 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } },
+    { "Canon EOS-1D Mark II", 0, 0xe80,
+	{ 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } },
+    { "Canon EOS-1DS", 0, 0xe20,
+	{ 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } },
+    { "Canon EOS-1D", 0, 0xe20,
+	{ 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } },
+    { "Canon EOS", 0, 0,
+	{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+    { "Canon PowerShot A50", 0, 0,
+	{ -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } },
+    { "Canon PowerShot A5", 0, 0,
+	{ -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } },
+    { "Canon PowerShot G10", 0, 0,
+	{ 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } },
+    { "Canon PowerShot G1", 0, 0,
+	{ -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } },
+    { "Canon PowerShot G2", 0, 0,
+	{ 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } },
+    { "Canon PowerShot G3", 0, 0,
+	{ 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } },
+    { "Canon PowerShot G5", 0, 0,
+	{ 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } },
+    { "Canon PowerShot G6", 0, 0,
+	{ 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } },
+    { "Canon PowerShot G9", 0, 0,
+	{ 7368,-2141,-598,-5621,13254,2625,-1418,1696,5743 } },
+    { "Canon PowerShot Pro1", 0, 0,
+	{ 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } },
+    { "Canon PowerShot Pro70", 34, 0,
+	{ -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } },
+    { "Canon PowerShot Pro90", 0, 0,
+	{ -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 } },
+    { "Canon PowerShot S30", 0, 0,
+	{ 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } },
+    { "Canon PowerShot S40", 0, 0,
+	{ 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } },
+    { "Canon PowerShot S45", 0, 0,
+	{ 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } },
+    { "Canon PowerShot S50", 0, 0,
+	{ 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } },
+    { "Canon PowerShot S60", 0, 0,
+	{ 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } },
+    { "Canon PowerShot S70", 0, 0,
+	{ 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } },
+    { "Canon PowerShot A610", 0, 0,	/* DJC */
+	{ 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } },
+    { "Canon PowerShot A620", 0, 0,	/* DJC */
+	{ 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } },
+    { "Canon PowerShot A630", 0, 0,	/* DJC */
+	{ 14201,-5308,-1757,-6087,14472,1617,-2191,3105,5348 } },
+    { "Canon PowerShot A640", 0, 0,	/* DJC */
+	{ 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } },
+    { "Canon PowerShot A650", 0, 0,	/* DJC */
+	{ 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } },
+    { "Canon PowerShot A720", 0, 0,	/* DJC */
+	{ 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } },
+    { "Canon PowerShot S3 IS", 0, 0,	/* DJC */
+	{ 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } },
+    { "Canon PowerShot SX1 IS", 0, 0,	/* DJC */
+	{ 10013,-2214,-1111,-3650,11589,2062,342,685,3617 } },
+    { "Canon PowerShot SX110 IS", 0, 0,	/* DJC */
+        { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } },
+    { "CINE 650", 0, 0,
+	{ 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+    { "CINE 660", 0, 0,
+	{ 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+    { "CINE", 0, 0,
+	{ 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } },
+    { "Contax N Digital", 0, 0xf1e,
+	{ 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } },
+    { "EPSON R-D1", 0, 0,
+	{ 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } },
+    { "FUJIFILM FinePix E550", 0, 0,
+	{ 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
+    { "FUJIFILM FinePix E900", 0, 0,
+	{ 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } },
+    { "FUJIFILM FinePix F8", 0, 0,
+	{ 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
+    { "FUJIFILM FinePix F7", 0, 0,
+	{ 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+    { "FUJIFILM FinePix S100FS", 514, 0,
+	{ 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } },
+    { "FUJIFILM FinePix S20Pro", 0, 0,
+	{ 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+    { "FUJIFILM FinePix S2Pro", 128, 0,
+	{ 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } },
+    { "FUJIFILM FinePix S3Pro", 0, 0,
+	{ 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } },
+    { "FUJIFILM FinePix S5Pro", 0, 0,
+	{ 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+    { "FUJIFILM FinePix S5000", 0, 0,
+	{ 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } },
+    { "FUJIFILM FinePix S5100", 0, 0x3e00,
+	{ 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+    { "FUJIFILM FinePix S5500", 0, 0x3e00,
+	{ 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+    { "FUJIFILM FinePix S5200", 0, 0,
+	{ 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+    { "FUJIFILM FinePix S5600", 0, 0,
+	{ 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+    { "FUJIFILM FinePix S6", 0, 0,
+	{ 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } },
+    { "FUJIFILM FinePix S7000", 0, 0,
+	{ 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } },
+    { "FUJIFILM FinePix S9000", 0, 0,
+	{ 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+    { "FUJIFILM FinePix S9500", 0, 0,
+	{ 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+    { "FUJIFILM FinePix S9100", 0, 0,
+	{ 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+    { "FUJIFILM FinePix S9600", 0, 0,
+	{ 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+    { "FUJIFILM IS-1", 0, 0,
+	{ 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } },
+    { "FUJIFILM IS Pro", 0, 0,
+	{ 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+    { "Imacon Ixpress", 0, 0,		/* DJC */
+	{ 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } },
+    { "KODAK NC2000", 0, 0,
+	{ 13891,-6055,-803,-465,9919,642,2121,82,1291 } },
+    { "Kodak DCS315C", 8, 0,
+	{ 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } },
+    { "Kodak DCS330C", 8, 0,
+	{ 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } },
+    { "KODAK DCS420", 0, 0,
+	{ 10868,-1852,-644,-1537,11083,484,2343,628,2216 } },
+    { "KODAK DCS460", 0, 0,
+	{ 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+    { "KODAK EOSDCS1", 0, 0,
+	{ 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+    { "KODAK EOSDCS3B", 0, 0,
+	{ 9898,-2700,-940,-2478,12219,206,1985,634,1031 } },
+    { "Kodak DCS520C", 180, 0,
+	{ 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+    { "Kodak DCS560C", 188, 0,
+	{ 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+    { "Kodak DCS620C", 180, 0,
+	{ 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } },
+    { "Kodak DCS620X", 185, 0,
+	{ 13095,-6231,154,12221,-21,-2137,895,4602,2258 } },
+    { "Kodak DCS660C", 214, 0,
+	{ 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } },
+    { "Kodak DCS720X", 0, 0,
+	{ 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } },
+    { "Kodak DCS760C", 0, 0,
+	{ 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } },
+    { "Kodak DCS Pro SLR", 0, 0,
+	{ 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+    { "Kodak DCS Pro 14nx", 0, 0,
+	{ 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+    { "Kodak DCS Pro 14", 0, 0,
+	{ 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } },
+    { "Kodak ProBack645", 0, 0,
+	{ 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } },
+    { "Kodak ProBack", 0, 0,
+	{ 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } },
+    { "KODAK P712", 0, 0,
+	{ 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } },
+    { "KODAK P850", 0, 0xf7c,
+	{ 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } },
+    { "KODAK P880", 0, 0xfff,
+	{ 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } },
+    { "Leaf CMost", 0, 0,
+	{ 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
+    { "Leaf Valeo 6", 0, 0,
+	{ 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
+    { "Leaf Aptus 54S", 0, 0,
+	{ 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
+    { "Leaf Aptus 65", 0, 0,
+	{ 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+    { "Leaf Aptus 75", 0, 0,
+	{ 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+    { "Leaf", 0, 0,
+	{ 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
+    { "Mamiya ZD", 0, 0,
+	{ 7645,2579,-1363,-8689,16717,2015,-3712,5941,5961 } },
+    { "Micron 2010", 110, 0,		/* DJC */
+	{ 16695,-3761,-2151,155,9682,163,3433,951,4904 } },
+    { "Minolta DiMAGE 5", 0, 0xf7d,
+	{ 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } },
+    { "Minolta DiMAGE 7Hi", 0, 0xf7d,
+	{ 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 } },
+    { "Minolta DiMAGE 7", 0, 0xf7d,
+	{ 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } },
+    { "Minolta DiMAGE A1", 0, 0xf8b,
+	{ 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } },
+    { "MINOLTA DiMAGE A200", 0, 0,
+	{ 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } },
+    { "Minolta DiMAGE A2", 0, 0xf8f,
+	{ 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } },
+    { "Minolta DiMAGE Z2", 0, 0,	/* DJC */
+	{ 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
+    { "MINOLTA DYNAX 5", 0, 0xffb,
+	{ 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } },
+    { "MINOLTA DYNAX 7", 0, 0xffb,
+	{ 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } },
+    { "MOTOROLA PIXL", 0, 0,		/* DJC */
+	{ 8898,-989,-1033,-3292,11619,1674,-661,3178,5216 } },
+    { "NIKON D100", 0, 0,
+	{ 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } },
+    { "NIKON D1H", 0, 0,
+	{ 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } },
+    { "NIKON D1X", 0, 0,
+	{ 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } },
+    { "NIKON D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */
+	{ 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } },
+    { "NIKON D2H", 0, 0,
+	{ 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } },
+    { "NIKON D2X", 0, 0,
+	{ 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } },
+    { "NIKON D40X", 0, 0,
+	{ 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } },
+    { "NIKON D40", 0, 0,
+	{ 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } },
+    { "NIKON D50", 0, 0,
+	{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+    { "NIKON D60", 0, 0,
+	{ 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
+    { "NIKON D700", 0, 0,
+	{ 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+    { "NIKON D70", 0, 0,
+	{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+    { "NIKON D80", 0, 0,
+	{ 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } },
+    { "NIKON D90", 0, 0xf00,
+	{ 7309,-1403,-519,-8474,16008,2622,-2434,2826,8064 } },
+    { "NIKON D200", 0, 0xfbc,
+	{ 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } },
+    { "NIKON D300", 0, 0,
+	{ 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } },
+    { "NIKON D3X", 0, 0,
+	{ 7171,-1986,-648,-8085,15555,2718,-2170,2512,7457 } },
+    { "NIKON D3", 0, 0,
+	{ 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+    { "NIKON E950", 0, 0x3dd,		/* DJC */
+	{ -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
+    { "NIKON E995", 0, 0,	/* copied from E5000 */
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E2100", 0, 0,	/* copied from Z2, new white balance */
+	{ 13142,-4152,-1596,-4655,12374,2282,-1769,2696,6711} },
+    { "NIKON E2500", 0, 0,
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E4300", 0, 0,	/* copied from Minolta DiMAGE Z2 */
+	{ 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
+    { "NIKON E4500", 0, 0,
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E5000", 0, 0,
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E5400", 0, 0,
+	{ 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } },
+    { "NIKON E5700", 0, 0,
+	{ -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } },
+    { "NIKON E8400", 0, 0,
+	{ 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } },
+    { "NIKON E8700", 0, 0,
+	{ 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
+    { "NIKON E8800", 0, 0,
+	{ 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } },
+    { "NIKON COOLPIX P6000", 0, 0,
+	{ 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } },
+    { "OLYMPUS C5050", 0, 0,
+	{ 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } },
+    { "OLYMPUS C5060", 0, 0,
+	{ 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } },
+    { "OLYMPUS C7070", 0, 0,
+	{ 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } },
+    { "OLYMPUS C70", 0, 0,
+	{ 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } },
+    { "OLYMPUS C80", 0, 0,
+	{ 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } },
+    { "OLYMPUS E-10", 0, 0xffc0,
+	{ 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } },
+    { "OLYMPUS E-1", 0, 0xfff0,
+	{ 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } },
+    { "OLYMPUS E-20", 0, 0xffc0,
+	{ 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } },
+    { "OLYMPUS E-300", 0, 0,
+	{ 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } },
+    { "OLYMPUS E-330", 0, 0,
+	{ 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } },
+    { "OLYMPUS E-30", 0, 0,
+	{ 8144,-1861,-1111,-7763,15894,1929,-1865,2542,7607 } },
+    { "OLYMPUS E-3", 0, 0xf99,
+	{ 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } },
+    { "OLYMPUS E-400", 0, 0xfff0,
+	{ 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } },
+    { "OLYMPUS E-410", 0, 0xf6a,
+	{ 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } },
+    { "OLYMPUS E-420", 0, 0xfd7,
+	{ 8746,-2425,-1095,-7594,15612,2073,-1780,2309,7416 } },
+    { "OLYMPUS E-500", 0, 0,
+	{ 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } },
+    { "OLYMPUS E-510", 0, 0xf6a,
+	{ 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } },
+    { "OLYMPUS E-520", 0, 0xfd2,
+	{ 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } },
+    { "OLYMPUS SP350", 0, 0,
+	{ 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } },
+    { "OLYMPUS SP3", 0, 0,
+	{ 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } },
+    { "OLYMPUS SP500UZ", 0, 0xfff,
+	{ 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } },
+    { "OLYMPUS SP510UZ", 0, 0xffe,
+	{ 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } },
+    { "OLYMPUS SP550UZ", 0, 0xffe,
+	{ 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } },
+    { "OLYMPUS SP560UZ", 0, 0xff9,
+	{ 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } },
+    { "OLYMPUS SP570UZ", 0, 0,
+	{ 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } },
+    { "PENTAX *ist DL2", 0, 0,
+	{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+    { "PENTAX *ist DL", 0, 0,
+	{ 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } },
+    { "PENTAX *ist DS2", 0, 0,
+	{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+    { "PENTAX *ist DS", 0, 0,
+	{ 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } },
+    { "PENTAX *ist D", 0, 0,
+	{ 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } },
+    { "PENTAX K10D", 0, 0,
+	{ 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } },
+    { "PENTAX K1", 0, 0,
+	{ 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } },
+    { "PENTAX K20D", 0, 0,
+	{ 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } },
+    { "PENTAX K200D", 0, 0,
+	{ 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } },
+    { "PENTAX K2000", 0, 0,
+	{ 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+    { "PENTAX K-m", 0, 0,
+	{ 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+    { "Panasonic DMC-FZ8", 0, 0xf7f0,
+	{ 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } },
+    { "Panasonic DMC-FZ18", 0, 0,
+	{ 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } },
+    { "Panasonic DMC-FZ28", 15, 0xfff,
+	{ 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } },
+    { "Panasonic DMC-FZ30", 0, 0xf94c,
+	{ 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
+    { "Panasonic DMC-FZ50", 0, 0xfff0,	/* aka "LEICA V-LUX1" */
+	{ 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
+    { "Panasonic DMC-L10", 15, 0xf96,
+	{ 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } },
+    { "Panasonic DMC-L1", 0, 0xf7fc,	/* aka "LEICA DIGILUX 3" */
+	{ 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
+    { "Panasonic DMC-LC1", 0, 0,	/* aka "LEICA DIGILUX 2" */
+	{ 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
+    { "Panasonic DMC-LX1", 0, 0xf7f0,	/* aka "LEICA D-LUX2" */
+	{ 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
+    { "Panasonic DMC-LX2", 0, 0,	/* aka "LEICA D-LUX3" */
+	{ 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
+    { "Panasonic DMC-LX3", 15, 0xfff,	/* aka "LEICA D-LUX4" */
+	{ 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
+    { "Panasonic DMC-FX150", 15, 0xfff,
+	{ 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } },
+    { "Panasonic DMC-G1", 15, 0xfff,
+	{ 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } },
+    { "Panasonic DMC-GH1", 15, 0xfff,	/* DJC */
+	{ 7808,-2387,-480,-2859,10002,2857,-1001,2012,4915 } },
+    { "Phase One H 20", 0, 0,		/* DJC */
+	{ 1313,1855,-109,-6715,15908,808,-327,1840,6020 } },
+    { "Phase One P 2", 0, 0,
+	{ 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } },
+    { "Phase One P 30", 0, 0,
+	{ 4516,-245,-37,-7020,14976,2173,-3206,4671,7087 } },
+    { "Phase One P 45", 0, 0,
+	{ 5053,-24,-117,-5684,14076,1702,-2619,4492,5849 } },
+    { "SAMSUNG GX-1", 0, 0,
+	{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+    { "Sinar", 0, 0,			/* DJC */
+	{ 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } },
+    { "SONY DSC-F828", 491, 0,
+	{ 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } },
+    { "SONY DSC-R1", 512, 0,
+	{ 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } },
+    { "SONY DSC-V3", 0, 0,
+	{ 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } },
+    { "SONY DSLR-A100", 0, 0xfeb,
+	{ 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } },
+    { "SONY DSLR-A200", 0, 0,
+	{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+    { "SONY DSLR-A300", 0, 0,
+	{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+    { "SONY DSLR-A350", 0, 0xffc,
+	{ 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } },
+    { "SONY DSLR-A700", 254, 0x1ffe,
+	{ 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } },
+    { "SONY DSLR-A900", 254, 0x1ffe,
+	{ 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } }
+  };
+  double cam_xyz[4][3];
+  char name[130];
+  int i, j;
+
+  sprintf (name, "%s %s", make, model);
+  for (i=0; i < sizeof table / sizeof *table; i++)
+    if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) {
+      if (table[i].black)   black   = (ushort) table[i].black;
+      if (table[i].maximum) maximum = (ushort) table[i].maximum;
+      for (j=0; j < 12; j++)
+	cam_xyz[0][j] = table[i].trans[j] / 10000.0;
+      cam_xyz_coeff (cam_xyz);
+      break;
+    }
+}
+
+void CLASS simple_coeff (int index)
+{
+  static const float table[][12] = {
+  /* index 0 -- all Foveon cameras */
+  { 1.4032,-0.2231,-0.1016,-0.5263,1.4816,0.017,-0.0112,0.0183,0.9113 },
+  /* index 1 -- Kodak DC20 and DC25 */
+  { 2.25,0.75,-1.75,-0.25,-0.25,0.75,0.75,-0.25,-0.25,-1.75,0.75,2.25 },
+  /* index 2 -- Logitech Fotoman Pixtura */
+  { 1.893,-0.418,-0.476,-0.495,1.773,-0.278,-1.017,-0.655,2.672 },
+  /* index 3 -- Nikon E880, E900, and E990 */
+  { -1.936280,  1.800443, -1.448486,  2.584324,
+     1.405365, -0.524955, -0.289090,  0.408680,
+    -1.204965,  1.082304,  2.941367, -1.818705 }
+  };
+  int i, c;
+
+  for (raw_color = i=0; i < 3; i++)
+    FORCC rgb_cam[i][c] = table[index][i*colors+c];
+}
+
+short CLASS guess_byte_order (int words)
+{
+  uchar test[4][2];
+  int t=2, msb;
+  double diff, sum[2] = {0,0};
+
+  fread (test[0], 2, 2, ifp);
+  for (words-=2; words--; ) {
+    fread (test[t], 2, 1, ifp);
+    for (msb=0; msb < 2; msb++) {
+      diff = (test[t^2][msb] << 8 | test[t^2][!msb])
+	   - (test[t  ][msb] << 8 | test[t  ][!msb]);
+      sum[msb] += diff*diff;
+    }
+    t = (t+1) & 3;
+  }
+  return sum[0] < sum[1] ? 0x4d4d : 0x4949;
+}
+
+/*
+   Identify which camera created this file, and set global variables
+   accordingly.
+ */
+void CLASS identify()
+{
+  char head[32], *cp;
+  unsigned hlen, fsize, i, c, is_canon;
+  struct jhead jh;
+  static const struct {
+    int fsize;
+    char make[12], model[19], withjpeg;
+  } table[] = {
+    {    62464, "Kodak",    "DC20"            ,0 },
+    {   124928, "Kodak",    "DC20"            ,0 },
+    {  1652736, "Kodak",    "DCS200"          ,0 },
+    {  4159302, "Kodak",    "C330"            ,0 },
+    {  4162462, "Kodak",    "C330"            ,0 },
+    {   460800, "Kodak",    "C603v"           ,0 },
+    {   614400, "Kodak",    "C603v"           ,0 },
+    {  6163328, "Kodak",    "C603"            ,0 },
+    {  6166488, "Kodak",    "C603"            ,0 },
+    {  9116448, "Kodak",    "C603y"           ,0 },
+    {   311696, "ST Micro", "STV680 VGA"      ,0 },  /* SPYz */
+    {   614400, "Kodak",    "KAI-0340"        ,0 },
+    {   787456, "Creative", "PC-CAM 600"      ,0 },
+    {  1138688, "Minolta",  "RD175"           ,0 },
+    {  3840000, "Foculus",  "531C"            ,0 },
+    {   786432, "AVT",      "F-080C"          ,0 },
+    {  1447680, "AVT",      "F-145C"          ,0 },
+    {  1920000, "AVT",      "F-201C"          ,0 },
+    {  5067304, "AVT",      "F-510C"          ,0 },
+    { 10134608, "AVT",      "F-510C"          ,0 },
+    { 16157136, "AVT",      "F-810C"          ,0 },
+    {  1409024, "Sony",     "XCD-SX910CR"     ,0 },
+    {  2818048, "Sony",     "XCD-SX910CR"     ,0 },
+    {  3884928, "Micron",   "2010"            ,0 },
+    {  6624000, "Pixelink", "A782"            ,0 },
+    { 13248000, "Pixelink", "A782"            ,0 },
+    {  6291456, "RoverShot","3320AF"          ,0 },
+    {  6553440, "Canon",    "PowerShot A460"  ,0 },
+    {  6653280, "Canon",    "PowerShot A530"  ,0 },
+    {  6573120, "Canon",    "PowerShot A610"  ,0 },
+    {  9219600, "Canon",    "PowerShot A620"  ,0 },
+    { 10341600, "Canon",    "PowerShot A720"  ,0 },
+    { 10383120, "Canon",    "PowerShot A630"  ,0 },
+    { 12945240, "Canon",    "PowerShot A640"  ,0 },
+    { 15636240, "Canon",    "PowerShot A650"  ,0 },
+    {  5298000, "Canon",    "PowerShot SD300" ,0 },
+    {  7710960, "Canon",    "PowerShot S3 IS" ,0 },
+    { 15467760, "Canon",    "PowerShot SX110 IS",0 },
+    {  5939200, "OLYMPUS",  "C770UZ"          ,0 },
+    {  1581060, "NIKON",    "E900"            ,1 },  /* or E900s,E910 */
+    {  2465792, "NIKON",    "E950"            ,1 },  /* or E800,E700 */
+    {  2940928, "NIKON",    "E2100"           ,1 },  /* or E2500 */
+    {  4771840, "NIKON",    "E990"            ,1 },  /* or E995, Oly C3030Z */
+    {  4775936, "NIKON",    "E3700"           ,1 },  /* or Optio 33WR */
+    {  5869568, "NIKON",    "E4300"           ,1 },  /* or DiMAGE Z2 */
+    {  5865472, "NIKON",    "E4500"           ,1 },
+    {  7438336, "NIKON",    "E5000"           ,1 },  /* or E5700 */
+    {  8998912, "NIKON",    "COOLPIX S6"      ,1 },
+    {  1976352, "CASIO",    "QV-2000UX"       ,1 },
+    {  3217760, "CASIO",    "QV-3*00EX"       ,1 },
+    {  6218368, "CASIO",    "QV-5700"         ,1 },
+    {  6054400, "CASIO",    "QV-R41"          ,1 },
+    {  7530816, "CASIO",    "QV-R51"          ,1 },
+    {  7684000, "CASIO",    "QV-4000"         ,1 },
+    {  4948608, "CASIO",    "EX-S100"         ,1 },
+    {  7542528, "CASIO",    "EX-Z50"          ,1 },
+    {  7753344, "CASIO",    "EX-Z55"          ,1 },
+    {  7426656, "CASIO",    "EX-P505"         ,1 },
+    {  9313536, "CASIO",    "EX-P600"         ,1 },
+    { 10979200, "CASIO",    "EX-P700"         ,1 },
+    {  3178560, "PENTAX",   "Optio S"         ,1 },
+    {  4841984, "PENTAX",   "Optio S"         ,1 },
+    {  6114240, "PENTAX",   "Optio S4"        ,1 },  /* or S4i, CASIO EX-Z4 */
+    { 10702848, "PENTAX",   "Optio 750Z"      ,1 },
+    { 16098048, "SAMSUNG",  "S85"             ,1 },
+    { 16215552, "SAMSUNG",  "S85"             ,1 },
+    { 12582980, "Sinar",    ""                ,0 },
+    { 33292868, "Sinar",    ""                ,0 },
+    { 44390468, "Sinar",    ""                ,0 } };
+  static const char *corp[] =
+    { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX",
+      "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One",
+      "SAMSUNG", "Mamiya", "MOTOROLA" };
+
+  tiff_flip = flip = filters = -1;	/* 0 is valid, so -1 is unknown */
+  raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0;
+  maximum = height = width = top_margin = left_margin = 0;
+  cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0;
+  iso_speed = shutter = aperture = focal_len = unique_id = 0;
+  memset (gpsdata, 0, sizeof gpsdata);
+  memset (white, 0, sizeof white);
+  thumb_offset = thumb_length = thumb_width = thumb_height = 0;
+  load_raw = thumb_load_raw = 0;
+  write_thumb = &CLASS jpeg_thumb;
+  data_offset = meta_length = tiff_bps = tiff_compress = 0;
+  kodak_cbpp = zero_after_ff = dng_version = load_flags = 0;
+  timestamp = shot_order = tiff_samples = black = is_foveon = 0;
+  mix_green = profile_length = data_error = zero_is_bad = 0;
+  pixel_aspect = is_raw = raw_color = 1;
+  tile_width = tile_length = INT_MAX;
+  for (i=0; i < 4; i++) {
+    cam_mul[i] = i == 1;
+    pre_mul[i] = i < 3;
+    FORC3 cmatrix[c][i] = 0;
+    FORC3 rgb_cam[c][i] = c == i;
+  }
+  colors = 3;
+  tiff_bps = 12;
+  for (i=0; i < 0x4000; i++) curve[i] = i;
+
+  order = get2();
+  hlen = get4();
+  fseek (ifp, 0, SEEK_SET);
+  fread (head, 1, 32, ifp);
+  fseek (ifp, 0, SEEK_END);
+  fsize = ftell(ifp);
+  if ((cp = (char *) memmem (head, 32, "MMMM", 4)) ||
+      (cp = (char *) memmem (head, 32, "IIII", 4))) {
+    parse_phase_one (cp-head);
+    if (cp-head) parse_tiff(0);
+  } else if (order == 0x4949 || order == 0x4d4d) {
+    if (!memcmp (head+6,"HEAPCCDR",8)) {
+      data_offset = hlen;
+      parse_ciff (hlen, fsize - hlen);
+    } else {
+      parse_tiff(0);
+    }
+  } else if (!memcmp (head,"\xff\xd8\xff\xe1",4) &&
+	     !memcmp (head+6,"Exif",4)) {
+    fseek (ifp, 4, SEEK_SET);
+    data_offset = 4 + get2();
+    fseek (ifp, data_offset, SEEK_SET);
+    if (fgetc(ifp) != 0xff)
+      parse_tiff(12);
+    thumb_offset = 0;
+  } else if (!memcmp (head+25,"ARECOYK",7)) {
+    strcpy (make, "Contax");
+    strcpy (model,"N Digital");
+    fseek (ifp, 33, SEEK_SET);
+    get_timestamp(1);
+    fseek (ifp, 60, SEEK_SET);
+    FORC4 cam_mul[c ^ (c >> 1)] = get4();
+  } else if (!strcmp (head, "PXN")) {
+    strcpy (make, "Logitech");
+    strcpy (model,"Fotoman Pixtura");
+  } else if (!strcmp (head, "qktk")) {
+    strcpy (make, "Apple");
+    strcpy (model,"QuickTake 100");
+  } else if (!strcmp (head, "qktn")) {
+    strcpy (make, "Apple");
+    strcpy (model,"QuickTake 150");
+  } else if (!memcmp (head,"FUJIFILM",8)) {
+    fseek (ifp, 84, SEEK_SET);
+    thumb_offset = get4();
+    thumb_length = get4();
+    fseek (ifp, 92, SEEK_SET);
+    parse_fuji (get4());
+    if (thumb_offset > 120) {
+      fseek (ifp, 120, SEEK_SET);
+      is_raw += (i = get4()) && 1;
+      if (is_raw == 2 && shot_select)
+	parse_fuji (i);
+    }
+    fseek (ifp, 100, SEEK_SET);
+    data_offset = get4();
+    parse_tiff (thumb_offset+12);
+  } else if (!memcmp (head,"RIFF",4)) {
+    fseek (ifp, 0, SEEK_SET);
+    parse_riff();
+  } else if (!memcmp (head,"\0\001\0\001\0@",6)) {
+    fseek (ifp, 6, SEEK_SET);
+    fread (make, 1, 8, ifp);
+    fread (model, 1, 8, ifp);
+    fread (model2, 1, 16, ifp);
+    data_offset = get2();
+    get2();
+    raw_width = get2();
+    raw_height = get2();
+    load_raw = &CLASS nokia_load_raw;
+    filters = 0x61616161;
+  } else if (!memcmp (head,"DSC-Image",9))
+    parse_rollei();
+  else if (!memcmp (head,"PWAD",4))
+    parse_sinar_ia();
+  else if (!memcmp (head,"\0MRM",4))
+    parse_minolta(0);
+  else if (!memcmp (head,"FOVb",4))
+    parse_foveon();
+  else if (!memcmp (head,"CI",2))
+    parse_cine();
+  else
+    for (i=0; i < sizeof table / sizeof *table; i++)
+      if (fsize == table[i].fsize) {
+	strcpy (make,  table[i].make );
+	strcpy (model, table[i].model);
+	if (table[i].withjpeg)
+	  parse_external_jpeg();
+      }
+  if (make[0] == 0) parse_smal (0, fsize);
+  if (make[0] == 0) parse_jpeg (is_raw = 0);
+
+  for (i=0; i < sizeof corp / sizeof *corp; i++)
+    if (strstr (make, corp[i]))		/* Simplify company names */
+	strcpy (make, corp[i]);
+  if (!strncmp (make,"KODAK",5) &&
+	((cp = strstr(model,"DIGITAL CAMERA")) ||
+	 (cp = strstr(model,"FILE VERSION"))))
+     *cp = 0;
+  cp = make + strlen(make);		/* Remove trailing spaces */
+  while (*--cp == ' ') *cp = 0;
+  cp = model + strlen(model);
+  while (*--cp == ' ') *cp = 0;
+  i = strlen(make);			/* Remove make from model */
+  if (!strncasecmp (model, make, i) && model[i++] == ' ')
+    memmove (model, model+i, 64-i);
+  if (!strncmp (model,"Digital Camera ",15))
+    strcpy (model, model+15);
+  desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0;
+  if (!is_raw) goto notraw;
+
+  if (!maximum) maximum = (1 << tiff_bps) - 1;
+  if (!height) height = raw_height;
+  if (!width)  width  = raw_width;
+  if (fuji_width) {
+    width = height + fuji_width;
+    height = width - 1;
+    pixel_aspect = 1;
+  }
+  if (height == 2624 && width == 3936)	/* Pentax K10D and Samsung GX10 */
+    { height  = 2616;   width  = 3896; }
+  if (height == 3136 && width == 4864)	/* Pentax K20D */
+    { height  = 3124;   width  = 4688; }
+  if (height == 3014 && width == 4096)	/* Ricoh GX200 */
+			width  = 4014;
+  if (dng_version) {
+    if (filters == UINT_MAX) filters = 0;
+    if (filters) is_raw = tiff_samples;
+    else	 colors = tiff_samples;
+    if (tiff_compress == 1)
+      load_raw = &CLASS adobe_dng_load_raw_nc;
+    if (tiff_compress == 7)
+      load_raw = &CLASS adobe_dng_load_raw_lj;
+    goto dng_skip;
+  }
+  if ((is_canon = !strcmp(make,"Canon")))
+    load_raw = memcmp (head+6,"HEAPCCDR",8) ?
+	&CLASS lossless_jpeg_load_raw : &CLASS canon_compressed_load_raw;
+  if (!strcmp(make,"NIKON")) {
+    if (!load_raw)
+      load_raw = &CLASS packed_12_load_raw;
+    if (model[0] == 'E')
+      load_flags |= !data_offset << 2 | 2;
+  }
+  if (!strcmp(make,"CASIO")) {
+    load_raw = &CLASS packed_12_load_raw;
+    maximum = 0xf7f;
+  }
+
+/* Set parameters based on camera name (for non-DNG files). */
+
+  if (is_foveon) {
+    if (height*2 < width) pixel_aspect = 0.5;
+    if (height   > width) pixel_aspect = 2;
+    filters = 0;
+    load_raw = &CLASS foveon_load_raw;
+    simple_coeff(0);
+  } else if (is_canon && tiff_bps == 15) {
+    switch (width) {
+      case 3344: width -= 66;
+      case 3872: width -= 6;
+    }
+    filters = 0;
+    load_raw = &CLASS canon_sraw_load_raw;
+  } else if (!strcmp(model,"PowerShot 600")) {
+    height = 613;
+    width  = 854;
+    raw_width = 896;
+    pixel_aspect = 607/628.0;
+    colors = 4;
+    filters = 0xe1e4e1e4;
+    load_raw = &CLASS canon_600_load_raw;
+  } else if (!strcmp(model,"PowerShot A5") ||
+	     !strcmp(model,"PowerShot A5 Zoom")) {
+    height = 773;
+    width  = 960;
+    raw_width = 992;
+    pixel_aspect = 256/235.0;
+    colors = 4;
+    filters = 0x1e4e1e4e;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A50")) {
+    height =  968;
+    width  = 1290;
+    raw_width = 1320;
+    colors = 4;
+    filters = 0x1b4e4b1e;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot Pro70")) {
+    height = 1024;
+    width  = 1552;
+    colors = 4;
+    filters = 0x1e4b4e1b;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot SD300")) {
+    height = 1752;
+    width  = 2344;
+    raw_height = 1766;
+    raw_width  = 2400;
+    top_margin  = 12;
+    left_margin = 12;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A460")) {
+    height = 1960;
+    width  = 2616;
+    raw_height = 1968;
+    raw_width  = 2664;
+    top_margin  = 4;
+    left_margin = 4;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A530")) {
+    height = 1984;
+    width  = 2620;
+    raw_height = 1992;
+    raw_width  = 2672;
+    top_margin  = 6;
+    left_margin = 10;
+    load_raw = &CLASS canon_a5_load_raw;
+    raw_color = 0;
+  } else if (!strcmp(model,"PowerShot A610")) {
+    if (canon_s2is()) strcpy (model+10, "S2 IS");
+    height = 1960;
+    width  = 2616;
+    raw_height = 1968;
+    raw_width  = 2672;
+    top_margin  = 8;
+    left_margin = 12;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A620")) {
+    height = 2328;
+    width  = 3112;
+    raw_height = 2340;
+    raw_width  = 3152;
+    top_margin  = 12;
+    left_margin = 36;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A720")) {
+    height = 2472;
+    width  = 3298;
+    raw_height = 2480;
+    raw_width  = 3336;
+    top_margin  = 5;
+    left_margin = 6;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A630")) {
+    height = 2472;
+    width  = 3288;
+    raw_height = 2484;
+    raw_width  = 3344;
+    top_margin  = 6;
+    left_margin = 12;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A640")) {
+    height = 2760;
+    width  = 3672;
+    raw_height = 2772;
+    raw_width  = 3736;
+    top_margin  = 6;
+    left_margin = 12;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A650")) {
+    height = 3024;
+    width  = 4032;
+    raw_height = 3048;
+    raw_width  = 4104;
+    top_margin  = 12;
+    left_margin = 48;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot S3 IS")) {
+    height = 2128;
+    width  = 2840;
+    raw_height = 2136;
+    raw_width  = 2888;
+    top_margin  = 8;
+    left_margin = 44;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot SX110 IS")) {
+    height = 2760;
+    width  = 3684;
+    raw_height = 2772;
+    raw_width  = 3720;
+    top_margin  = 12;
+    left_margin = 6;
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 40;
+    zero_is_bad = 1;
+  } else if (!strcmp(model,"PowerShot Pro90 IS")) {
+    width  = 1896;
+    colors = 4;
+    filters = 0xb4b4b4b4;
+  } else if (is_canon && raw_width == 2144) {
+    height = 1550;
+    width  = 2088;
+    top_margin  = 8;
+    left_margin = 4;
+    if (!strcmp(model,"PowerShot G1")) {
+      colors = 4;
+      filters = 0xb4b4b4b4;
+    }
+  } else if (is_canon && raw_width == 2224) {
+    height = 1448;
+    width  = 2176;
+    top_margin  = 6;
+    left_margin = 48;
+  } else if (is_canon && raw_width == 2376) {
+    height = 1720;
+    width  = 2312;
+    top_margin  = 6;
+    left_margin = 12;
+  } else if (is_canon && raw_width == 2672) {
+    height = 1960;
+    width  = 2616;
+    top_margin  = 6;
+    left_margin = 12;
+  } else if (is_canon && raw_width == 3152) {
+    height = 2056;
+    width  = 3088;
+    top_margin  = 12;
+    left_margin = 64;
+    if (unique_id == 0x80000170)
+      adobe_coeff ("Canon","EOS 300D");
+  } else if (is_canon && raw_width == 3160) {
+    height = 2328;
+    width  = 3112;
+    top_margin  = 12;
+    left_margin = 44;
+  } else if (is_canon && raw_width == 3344) {
+    height = 2472;
+    width  = 3288;
+    top_margin  = 6;
+    left_margin = 4;
+  } else if (!strcmp(model,"EOS D2000C")) {
+    filters = 0x61616161;
+    black = curve[200];
+  } else if (is_canon && raw_width == 3516) {
+    top_margin  = 14;
+    left_margin = 42;
+    if (unique_id == 0x80000189)
+      adobe_coeff ("Canon","EOS 350D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 3596) {
+    top_margin  = 12;
+    left_margin = 74;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 3944) {
+    height = 2602;
+    width  = 3908;
+    top_margin  = 18;
+    left_margin = 30;
+  } else if (is_canon && raw_width == 3948) {
+    top_margin  = 18;
+    left_margin = 42;
+    height -= 2;
+    if (unique_id == 0x80000236)
+      adobe_coeff ("Canon","EOS 400D");
+    if (unique_id == 0x80000254)
+      adobe_coeff ("Canon","EOS 1000D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 3984) {
+    top_margin  = 20;
+    left_margin = 76;
+    height -= 2;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4104) {
+    height = 3024;
+    width  = 4032;
+    top_margin  = 12;
+    left_margin = 48;
+  } else if (is_canon && raw_width == 4152) {
+    top_margin  = 12;
+    left_margin = 192;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4312) {
+    top_margin  = 18;
+    left_margin = 22;
+    height -= 2;
+    if (unique_id == 0x80000176)
+      adobe_coeff ("Canon","EOS 450D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4476) {
+    top_margin  = 34;
+    left_margin = 90;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4480) {
+    height = 3326;
+    width  = 4432;
+    top_margin  = 10;
+    left_margin = 12;
+    filters = 0x49494949;
+  } else if (is_canon && raw_width == 1208) {
+    top_margin = unique_id == 0x80000261 ? 51:26;
+    left_margin = 62;
+    raw_width = width *= 4;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 1448) {
+    top_margin  = 51;
+    left_margin = 158;
+    raw_width = width *= 4;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 5108) {
+    top_margin  = 13;
+    left_margin = 98;
+canon_cr2:
+    height -= top_margin;
+    width  -= left_margin;
+  } else if (is_canon && raw_width == 5712) {
+    height = 3752;
+    width  = 5640;
+    top_margin  = 20;
+    left_margin = 62;
+  } else if (!strcmp(model,"D1")) {
+    cam_mul[0] *= 256/527.0;
+    cam_mul[2] *= 256/317.0;
+  } else if (!strcmp(model,"D1X")) {
+    width -= 4;
+    pixel_aspect = 0.5;
+  } else if (!strcmp(model,"D40X") ||
+	     !strcmp(model,"D60")  ||
+	     !strcmp(model,"D80")) {
+    height -= 3;
+    width  -= 4;
+  } else if (!strcmp(model,"D3")   ||
+	     !strcmp(model,"D700")) {
+    width -= 4;
+    left_margin = 2;
+  } else if (!strncmp(model,"D40",3) ||
+	     !strncmp(model,"D50",3) ||
+	     !strncmp(model,"D70",3)) {
+    width--;
+  } else if (!strcmp(model,"D90")) {
+    width -= 42;
+  } else if (!strcmp(model,"D100")) {
+    if (tiff_compress == 34713 && !nikon_is_compressed()) {
+      load_raw = &CLASS packed_12_load_raw;
+      load_flags |= 1;
+      raw_width = (width += 3) + 3;
+    }
+  } else if (!strcmp(model,"D200")) {
+    left_margin = 1;
+    width -= 4;
+    filters = 0x94949494;
+  } else if (!strncmp(model,"D2H",3)) {
+    left_margin = 6;
+    width -= 14;
+  } else if (!strncmp(model,"D2X",3)) {
+    if (width == 3264) width -= 32;
+    else width -= 8;
+  } else if (!strcmp(model,"D300")) {
+    width -= 32;
+  } else if (!strcmp(model,"COOLPIX P6000")) {
+    load_flags = 24;
+    filters = 0x94949494;
+  } else if (fsize == 1581060) {
+    height = 963;
+    width = 1287;
+    raw_width = 1632;
+    load_raw = &CLASS nikon_e900_load_raw;
+    maximum = 0x3f4;
+    colors = 4;
+    filters = 0x1e1e1e1e;
+    simple_coeff(3);
+    pre_mul[0] = 1.2085;
+    pre_mul[1] = 1.0943;
+    pre_mul[3] = 1.1103;
+  } else if (fsize == 2465792) {
+    height = 1203;
+    width  = 1616;
+    raw_width = 2048;
+    load_raw = &CLASS nikon_e900_load_raw;
+    colors = 4;
+    filters = 0x4b4b4b4b;
+    adobe_coeff ("NIKON","E950");
+  } else if (fsize == 4771840) {
+    height = 1540;
+    width  = 2064;
+    colors = 4;
+    filters = 0xe1e1e1e1;
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 6;
+    if (!timestamp && nikon_e995())
+      strcpy (model, "E995");
+    if (strcmp(model,"E995")) {
+      filters = 0xb4b4b4b4;
+      simple_coeff(3);
+      pre_mul[0] = 1.196;
+      pre_mul[1] = 1.246;
+      pre_mul[2] = 1.018;
+    }
+  } else if (!strcmp(model,"E2100")) {
+    if (!timestamp && !nikon_e2100()) goto cp_e2500;
+    height = 1206;
+    width  = 1616;
+    load_flags = 30;
+  } else if (!strcmp(model,"E2500")) {
+cp_e2500:
+    strcpy (model, "E2500");
+    height = 1204;
+    width  = 1616;
+    colors = 4;
+    filters = 0x4b4b4b4b;
+  } else if (fsize == 4775936) {
+    height = 1542;
+    width  = 2064;
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 30;
+    pre_mul[0] = 1.818;
+    pre_mul[2] = 1.618;
+    if (!timestamp) nikon_3700();
+    if (model[0] == 'E' && atoi(model+1) < 3700)
+      filters = 0x49494949;
+    if (!strcmp(model,"Optio 33WR")) {
+      flip = 1;
+      filters = 0x16161616;
+      pre_mul[0] = 1.331;
+      pre_mul[2] = 1.820;
+    }
+  } else if (fsize == 5869568) {
+    height = 1710;
+    width  = 2288;
+    filters = 0x16161616;
+    if (!timestamp && minolta_z2()) {
+      strcpy (make, "Minolta");
+      strcpy (model,"DiMAGE Z2");
+    }
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 6 + 24*(make[0] == 'M');
+  } else if (!strcmp(model,"E4500")) {
+    height = 1708;
+    width  = 2288;
+    colors = 4;
+    filters = 0xb4b4b4b4;
+  } else if (fsize == 7438336) {
+    height = 1924;
+    width  = 2576;
+    colors = 4;
+    filters = 0xb4b4b4b4;
+  } else if (fsize == 8998912) {
+    height = 2118;
+    width  = 2832;
+    maximum = 0xf83;
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 30;
+  } else if (!strcmp(model,"FinePix S5100") ||
+	     !strcmp(model,"FinePix S5500")) {
+    load_raw = &CLASS unpacked_load_raw;
+  } else if (!strcmp(make,"FUJIFILM")) {
+    if (!strcmp(model+7,"S2Pro")) {
+      strcpy (model+7," S2Pro");
+      height = 2144;
+      width  = 2880;
+      flip = 6;
+    } else
+      maximum = 0x3e00;
+    if (is_raw == 2 && shot_select)
+      maximum = 0x2f00;
+    top_margin = (raw_height - height)/2;
+    left_margin = (raw_width - width )/2;
+    if (is_raw == 2)
+      data_offset += (shot_select > 0) * ( fuji_layout ?
+		(raw_width *= 2) : raw_height*raw_width*2 );
+    fuji_width = width >> !fuji_layout;
+    width = (height >> fuji_layout) + fuji_width;
+    raw_height = height;
+    height = width - 1;
+    load_raw = &CLASS fuji_load_raw;
+    if (!(fuji_width & 1)) filters = 0x49494949;
+  } else if (!strcmp(model,"RD175")) {
+    height = 986;
+    width = 1534;
+    data_offset = 513;
+    filters = 0x61616161;
+    load_raw = &CLASS minolta_rd175_load_raw;
+  } else if (!strcmp(model,"KD-400Z")) {
+    height = 1712;
+    width  = 2312;
+    raw_width = 2336;
+    goto konica_400z;
+  } else if (!strcmp(model,"KD-510Z")) {
+    goto konica_510z;
+  } else if (!strcasecmp(make,"MINOLTA")) {
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xfff;
+    if (!strncmp(model,"DiMAGE A",8)) {
+      if (!strcmp(model,"DiMAGE A200"))
+	filters = 0x49494949;
+      load_raw = &CLASS packed_12_load_raw;
+    } else if (!strncmp(model,"ALPHA",5) ||
+	       !strncmp(model,"DYNAX",5) ||
+	       !strncmp(model,"MAXXUM",6)) {
+      sprintf (model+20, "DYNAX %-10s", model+6+(model[0]=='M'));
+      adobe_coeff (make, model+20);
+      load_raw = &CLASS packed_12_load_raw;
+    } else if (!strncmp(model,"DiMAGE G",8)) {
+      if (model[8] == '4') {
+	height = 1716;
+	width  = 2304;
+      } else if (model[8] == '5') {
+konica_510z:
+	height = 1956;
+	width  = 2607;
+	raw_width = 2624;
+      } else if (model[8] == '6') {
+	height = 2136;
+	width  = 2848;
+      }
+      data_offset += 14;
+      filters = 0x61616161;
+konica_400z:
+      load_raw = &CLASS unpacked_load_raw;
+      maximum = 0x3df;
+      order = 0x4d4d;
+    }
+  } else if (!strcmp(model,"*ist DS")) {
+    height -= 2;
+  } else if (!strcmp(model,"K20D")) {
+    filters = 0x16161616;
+  } else if (!strcmp(model,"Optio S")) {
+    if (fsize == 3178560) {
+      height = 1540;
+      width  = 2064;
+      load_raw = &CLASS eight_bit_load_raw;
+      cam_mul[0] *= 4;
+      cam_mul[2] *= 4;
+      pre_mul[0] = 1.391;
+      pre_mul[2] = 1.188;
+    } else {
+      height = 1544;
+      width  = 2068;
+      raw_width = 3136;
+      load_raw = &CLASS packed_12_load_raw;
+      maximum = 0xf7c;
+      pre_mul[0] = 1.137;
+      pre_mul[2] = 1.453;
+    }
+  } else if (fsize == 6114240) {
+    height = 1737;
+    width  = 2324;
+    raw_width = 3520;
+    load_raw = &CLASS packed_12_load_raw;
+    maximum = 0xf7a;
+    pre_mul[0] = 1.980;
+    pre_mul[2] = 1.570;
+  } else if (!strcmp(model,"Optio 750Z")) {
+    height = 2302;
+    width  = 3072;
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 30;
+  } else if (!strcmp(model,"S85")) {
+    height = 2448;
+    width  = 3264;
+    raw_width = fsize/height/2;
+    order = 0x4d4d;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xffff;
+  } else if (!strcmp(model,"STV680 VGA")) {
+    height = 484;
+    width  = 644;
+    load_raw = &CLASS eight_bit_load_raw;
+    flip = 2;
+    filters = 0x16161616;
+    black = 16;
+    pre_mul[0] = 1.097;
+    pre_mul[2] = 1.128;
+  } else if (!strcmp(model,"KAI-0340")) {
+    height = 477;
+    width  = 640;
+    order = 0x4949;
+    data_offset = 3840;
+    load_raw = &CLASS unpacked_load_raw;
+    pre_mul[0] = 1.561;
+    pre_mul[2] = 2.454;
+  } else if (!strcmp(model,"N95")) {
+    height = raw_height - (top_margin = 2);
+  } else if (!strcmp(model,"531C")) {
+    height = 1200;
+    width  = 1600;
+    load_raw = &CLASS unpacked_load_raw;
+    filters = 0x49494949;
+    pre_mul[1] = 1.218;
+  } else if (!strcmp(model,"F-080C")) {
+    height = 768;
+    width  = 1024;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"F-145C")) {
+    height = 1040;
+    width  = 1392;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"F-201C")) {
+    height = 1200;
+    width  = 1600;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"F-510C")) {
+    height = 1958;
+    width  = 2588;
+    load_raw = fsize < 7500000 ?
+	&CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+    maximum = 0xfff0;
+  } else if (!strcmp(model,"F-810C")) {
+    height = 2469;
+    width  = 3272;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xfff0;
+  } else if (!strcmp(model,"XCD-SX910CR")) {
+    height = 1024;
+    width  = 1375;
+    raw_width = 1376;
+    filters = 0x49494949;
+    maximum = 0x3ff;
+    load_raw = fsize < 2000000 ?
+	&CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+  } else if (!strcmp(model,"2010")) {
+    height = 1207;
+    width  = 1608;
+    order = 0x4949;
+    filters = 0x16161616;
+    data_offset = 3212;
+    maximum = 0x3ff;
+    load_raw = &CLASS unpacked_load_raw;
+  } else if (!strcmp(model,"A782")) {
+    height = 3000;
+    width  = 2208;
+    filters = 0x61616161;
+    load_raw = fsize < 10000000 ?
+	&CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+    maximum = 0xffc0;
+  } else if (!strcmp(model,"3320AF")) {
+    height = 1536;
+    raw_width = width = 2048;
+    filters = 0x61616161;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0x3ff;
+    pre_mul[0] = 1.717;
+    pre_mul[2] = 1.138;
+    fseek (ifp, 0x300000, SEEK_SET);
+    if ((order = guess_byte_order(0x10000)) == 0x4d4d) {
+      height -= (top_margin = 16);
+      width -= (left_margin = 28);
+      maximum = 0xf5c0;
+      strcpy (make, "ISG");
+      model[0] = 0;
+    }
+  } else if (!strcmp(make,"Hasselblad")) {
+    if (load_raw == &CLASS lossless_jpeg_load_raw)
+      load_raw = &CLASS hasselblad_load_raw;
+    if (raw_width == 7262) {
+      height = 5444;
+      width  = 7248;
+      top_margin  = 4;
+      left_margin = 7;
+      filters = 0x61616161;
+    } else if (raw_width == 4090) {
+      strcpy (model, "V96C");
+      height -= (top_margin = 6);
+      width -= (left_margin = 3) + 7;
+      filters = 0x61616161;
+    }
+  } else if (!strcmp(make,"Sinar")) {
+    if (!memcmp(head,"8BPS",4)) {
+      fseek (ifp, 14, SEEK_SET);
+      height = get4();
+      width  = get4();
+      filters = 0x61616161;
+      data_offset = 68;
+    }
+    if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+    maximum = 0x3fff;
+  } else if (!strcmp(make,"Leaf")) {
+    maximum = 0x3fff;
+    fseek (ifp, data_offset, SEEK_SET);
+    if (ljpeg_start (&jh, 1) && jh.bits == 15)
+      maximum = 0x1fff;
+    if (tiff_samples > 1) filters = 0;
+    if (tiff_samples > 1 || tile_length < raw_height)
+      load_raw = &CLASS leaf_hdr_load_raw;
+    if ((width | height) == 2048) {
+      if (tiff_samples == 1) {
+	filters = 1;
+	strcpy (cdesc, "RBTG");
+	strcpy (model, "CatchLight");
+	top_margin =  8; left_margin = 18; height = 2032; width = 2016;
+      } else {
+	strcpy (model, "DCB2");
+	top_margin = 10; left_margin = 16; height = 2028; width = 2022;
+      }
+    } else if (width+height == 3144+2060) {
+      if (!model[0]) strcpy (model, "Cantare");
+      if (width > height) {
+	 top_margin = 6; left_margin = 32; height = 2048;  width = 3072;
+	filters = 0x61616161;
+      } else {
+	left_margin = 6;  top_margin = 32;  width = 2048; height = 3072;
+	filters = 0x16161616;
+      }
+      if (!cam_mul[0] || model[0] == 'V') filters = 0;
+      else is_raw = tiff_samples;
+    } else if (width == 2116) {
+      strcpy (model, "Valeo 6");
+      height -= 2 * (top_margin = 30);
+      width -= 2 * (left_margin = 55);
+      filters = 0x49494949;
+    } else if (width == 3171) {
+      strcpy (model, "Valeo 6");
+      height -= 2 * (top_margin = 24);
+      width -= 2 * (left_margin = 24);
+      filters = 0x16161616;
+    }
+  } else if (!strcmp(make,"LEICA") || !strcmp(make,"Panasonic")) {
+    maximum = 0xfff0;
+    if ((fsize-data_offset) / (width*8/7) == height)
+      load_raw = &CLASS panasonic_load_raw;
+    if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+    switch (width) {
+      case 2568:
+	adobe_coeff ("Panasonic","DMC-LC1");  break;
+      case 3130:
+	left_margin = -14;
+      case 3170:
+	left_margin += 18;
+	width = 3096;
+	if (height > 2326) {
+	  height = 2326;
+	  top_margin = 13;
+	  filters = 0x49494949;
+	}
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ8");  break;
+      case 3213:
+	width -= 27;
+      case 3177:
+	width -= 10;
+	filters = 0x49494949;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-L1");  break;
+      case 3304:
+	width -= 17;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ30");  break;
+      case 3330:
+	width += 43;
+	left_margin = -6;
+	maximum = 0xf7f0;
+      case 3370:
+	width -= 82;
+	left_margin += 15;
+	if (height > 2480)
+	    height = 2480 - (top_margin = 10);
+	filters = 0x49494949;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ18");  break;
+      case 3690:
+	height -= 2;
+	left_margin = -14;
+	maximum = 0xf7f0;
+      case 3770:
+	width = 3672;
+	if (--height == 2798 && (height = 2760))
+	  top_margin = 15;
+	else filters = 0x49494949;
+	left_margin += 17;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ50");  break;
+      case 3710:
+	width = 3682;
+	filters = 0x49494949;
+	adobe_coeff ("Panasonic","DMC-L10");  break;
+      case 3724:
+	width -= 14;
+	if (height == 2450) height -= 2;
+      case 3836:
+	width -= 42;
+lx3:	filters = 0x16161616;
+	if (make[0] != 'P')
+	  adobe_coeff ("Panasonic","DMC-LX3");
+	break;
+      case 3880:
+	width -= 22;
+	left_margin = 6;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-LX1");  break;
+      case 4060:
+	if (!strcmp(model,"DMC-GH1")) goto gh1;
+	width = 3982;
+	if (height == 2250) goto lx3;
+	width = 4018;
+	filters = 0x49494949;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-G1");  break;
+      case 4172:
+      case 4396:
+gh1:	width -= 28;
+	filters = 0x49494949;
+	adobe_coeff ("Panasonic","DMC-GH1");  break;
+      case 4290:
+	height += 38;
+	left_margin = -14;
+	filters = 0x49494949;
+      case 4330:
+	width = 4248;
+	if ((height -= 39) == 2400)
+	  top_margin = 15;
+	left_margin += 17;
+	adobe_coeff ("Panasonic","DMC-LX2");  break;
+      case 4508:
+	height -= 6;
+	width = 4429;
+	filters = 0x16161616;
+	adobe_coeff ("Panasonic","DMC-FX150");  break;
+    }
+  } else if (!strcmp(model,"C770UZ")) {
+    height = 1718;
+    width  = 2304;
+    filters = 0x16161616;
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 30;
+  } else if (!strcmp(make,"OLYMPUS")) {
+    height += height & 1;
+    filters = exif_cfa;
+    if (width == 4100) width -= 4;
+    if (load_raw == &CLASS olympus_e410_load_raw) {
+      black >>= 4;
+    } else if (!strcmp(model,"E-10") ||
+	      !strncmp(model,"E-20",4)) {
+      black <<= 2;
+    } else if (!strcmp(model,"E-300") ||
+	       !strcmp(model,"E-500")) {
+      width -= 20;
+      if (load_raw == &CLASS unpacked_load_raw) {
+	maximum = 0xfc30;
+	black = 0;
+      }
+    } else if (!strcmp(model,"E-330")) {
+      width -= 30;
+      if (load_raw == &CLASS unpacked_load_raw)
+	maximum = 0xf790;
+    } else if (!strcmp(model,"SP550UZ")) {
+      thumb_length = fsize - (thumb_offset = 0xa39800);
+      thumb_height = 480;
+      thumb_width  = 640;
+    }
+  } else if (!strcmp(model,"N Digital")) {
+    height = 2047;
+    width  = 3072;
+    filters = 0x61616161;
+    data_offset = 0x1a00;
+    load_raw = &CLASS packed_12_load_raw;
+  } else if (!strcmp(model,"DSC-F828")) {
+    width = 3288;
+    left_margin = 5;
+    data_offset = 862144;
+    load_raw = &CLASS sony_load_raw;
+    filters = 0x9c9c9c9c;
+    colors = 4;
+    strcpy (cdesc, "RGBE");
+  } else if (!strcmp(model,"DSC-V3")) {
+    width = 3109;
+    left_margin = 59;
+    data_offset = 787392;
+    load_raw = &CLASS sony_load_raw;
+  } else if (!strcmp(make,"SONY") && raw_width == 3984) {
+    adobe_coeff ("SONY","DSC-R1");
+    width = 3925;
+    order = 0x4d4d;
+  } else if (!strcmp(model,"DSLR-A100")) {
+    height--;
+  } else if (!strcmp(model,"DSLR-A350")) {
+    height -= 4;
+  } else if (!strcmp(model,"PIXL")) {
+    height -= top_margin = 4;
+    width -= left_margin = 32;
+    gamma_curve (0, 7, 1, 255);
+  } else if (!strcmp(model,"C603v")) {
+    height = 480;
+    width  = 640;
+    goto c603v;
+  } else if (!strcmp(model,"C603y")) {
+    height = 2134;
+    width  = 2848;
+c603v:
+    filters = 0;
+    load_raw = &CLASS kodak_yrgb_load_raw;
+    gamma_curve (0, 3.875, 1, 255);
+  } else if (!strcmp(model,"C603")) {
+    raw_height = height = 2152;
+    raw_width  = width  = 2864;
+    goto c603;
+  } else if (!strcmp(model,"C330")) {
+    height = 1744;
+    width  = 2336;
+    raw_height = 1779;
+    raw_width  = 2338;
+    top_margin = 33;
+    left_margin = 1;
+c603:
+    order = 0x4949;
+    if ((data_offset = fsize - raw_height*raw_width)) {
+      fseek (ifp, 168, SEEK_SET);
+      read_shorts (curve, 256);
+    } else gamma_curve (0, 3.875, 1, 255);
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"EASYSHARE Z1015 IS")) {
+    height = 2742;
+    width  = 3664;
+    data_offset = 0x15000;
+    load_raw = &CLASS packed_12_load_raw;
+  } else if (!strcasecmp(make,"KODAK")) {
+    if (filters == UINT_MAX) filters = 0x61616161;
+    if (!strncmp(model,"NC2000",6)) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"EOSDCS3B")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"EOSDCS1")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"DCS420")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strncmp(model,"DCS460 ",7)) {
+      model[6] = 0;
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"DCS460A")) {
+      width -= 4;
+      left_margin = 2;
+      colors = 1;
+      filters = 0;
+    } else if (!strcmp(model,"DCS660M")) {
+      black = 214;
+      colors = 1;
+      filters = 0;
+    } else if (!strcmp(model,"DCS760M")) {
+      colors = 1;
+      filters = 0;
+    }
+    if (!strcmp(model+4,"20X"))
+      strcpy (cdesc, "MYCY");
+    if (strstr(model,"DC25")) {
+      strcpy (model, "DC25");
+      data_offset = 15424;
+    }
+    if (!strncmp(model,"DC2",3)) {
+      height = 242;
+      if (fsize < 100000) {
+	raw_width = 256; width = 249;
+	pixel_aspect = (4.0*height) / (3.0*width);
+      } else {
+	raw_width = 512; width = 501;
+	pixel_aspect = (493.0*height) / (373.0*width);
+      }
+      data_offset += raw_width + 1;
+      colors = 4;
+      filters = 0x8d8d8d8d;
+      simple_coeff(1);
+      pre_mul[1] = 1.179;
+      pre_mul[2] = 1.209;
+      pre_mul[3] = 1.036;
+      load_raw = &CLASS eight_bit_load_raw;
+    } else if (!strcmp(model,"40")) {
+      strcpy (model, "DC40");
+      height = 512;
+      width  = 768;
+      data_offset = 1152;
+      load_raw = &CLASS kodak_radc_load_raw;
+    } else if (strstr(model,"DC50")) {
+      strcpy (model, "DC50");
+      height = 512;
+      width  = 768;
+      data_offset = 19712;
+      load_raw = &CLASS kodak_radc_load_raw;
+    } else if (strstr(model,"DC120")) {
+      strcpy (model, "DC120");
+      height = 976;
+      width  = 848;
+      pixel_aspect = height/0.75/width;
+      load_raw = tiff_compress == 7 ?
+	&CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw;
+    } else if (!strcmp(model,"DCS200")) {
+      thumb_height = 128;
+      thumb_width  = 192;
+      thumb_offset = 6144;
+      thumb_misc   = 360;
+      write_thumb = &CLASS layer_thumb;
+      height = 1024;
+      width  = 1536;
+      data_offset = 79872;
+      load_raw = &CLASS eight_bit_load_raw;
+      black = 17;
+    }
+  } else if (!strcmp(model,"Fotoman Pixtura")) {
+    height = 512;
+    width  = 768;
+    data_offset = 3632;
+    load_raw = &CLASS kodak_radc_load_raw;
+    filters = 0x61616161;
+    simple_coeff(2);
+  } else if (!strcmp(model,"QuickTake 100")) {
+    fseek (ifp, 544, SEEK_SET);
+    height = get2();
+    width  = get2();
+    data_offset = (get4(),get2()) == 30 ? 738:736;
+    if (height > width) {
+      SWAP(height,width);
+      fseek (ifp, data_offset-6, SEEK_SET);
+      flip = ~get2() & 3 ? 5:6;
+    }
+    load_raw = &CLASS quicktake_100_load_raw;
+    filters = 0x61616161;
+  } else if (!strcmp(model,"QuickTake 150")) {
+    data_offset = 738 - head[5];
+    if (head[5]) strcpy (model+10, "200");
+    load_raw = &CLASS kodak_radc_load_raw;
+    height = 480;
+    width  = 640;
+    filters = 0x61616161;
+  } else if (!strcmp(make,"Rollei") && !load_raw) {
+    switch (raw_width) {
+      case 1316:
+	height = 1030;
+	width  = 1300;
+	top_margin  = 1;
+	left_margin = 6;
+	break;
+      case 2568:
+	height = 1960;
+	width  = 2560;
+	top_margin  = 2;
+	left_margin = 8;
+    }
+    filters = 0x16161616;
+    load_raw = &CLASS rollei_load_raw;
+    pre_mul[0] = 1.8;
+    pre_mul[2] = 1.3;
+  } else if (!strcmp(model,"PC-CAM 600")) {
+    height = 768;
+    data_offset = width = 1024;
+    filters = 0x49494949;
+    load_raw = &CLASS eight_bit_load_raw;
+    pre_mul[0] = 1.14;
+    pre_mul[2] = 2.73;
+  } else if (!strcmp(model,"QV-2000UX")) {
+    height = 1208;
+    width  = 1632;
+    data_offset = width * 2;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (fsize == 3217760) {
+    height = 1546;
+    width  = 2070;
+    raw_width = 2080;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"QV-4000")) {
+    height = 1700;
+    width  = 2260;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xffff;
+  } else if (!strcmp(model,"QV-5700")) {
+    height = 1924;
+    width  = 2576;
+    load_raw = &CLASS casio_qv5700_load_raw;
+  } else if (!strcmp(model,"QV-R41")) {
+    height = 1720;
+    width  = 2312;
+    raw_width = 3520;
+    left_margin = 2;
+  } else if (!strcmp(model,"QV-R51")) {
+    height = 1926;
+    width  = 2580;
+    raw_width = 3904;
+    pre_mul[0] = 1.340;
+    pre_mul[2] = 1.672;
+  } else if (!strcmp(model,"EX-S100")) {
+    height = 1544;
+    width  = 2058;
+    raw_width = 3136;
+    pre_mul[0] = 1.631;
+    pre_mul[2] = 1.106;
+  } else if (!strcmp(model,"EX-Z50")) {
+    height = 1931;
+    width  = 2570;
+    raw_width = 3904;
+    pre_mul[0] = 2.529;
+    pre_mul[2] = 1.185;
+  } else if (!strcmp(model,"EX-Z55")) {
+    height = 1960;
+    width  = 2570;
+    raw_width = 3904;
+    pre_mul[0] = 1.520;
+    pre_mul[2] = 1.316;
+  } else if (!strcmp(model,"EX-P505")) {
+    height = 1928;
+    width  = 2568;
+    raw_width = 3852;
+    maximum = 0xfff;
+    pre_mul[0] = 2.07;
+    pre_mul[2] = 1.88;
+  } else if (fsize == 9313536) {	/* EX-P600 or QV-R61 */
+    height = 2142;
+    width  = 2844;
+    raw_width = 4288;
+    pre_mul[0] = 1.797;
+    pre_mul[2] = 1.219;
+  } else if (!strcmp(model,"EX-P700")) {
+    height = 2318;
+    width  = 3082;
+    raw_width = 4672;
+    pre_mul[0] = 1.758;
+    pre_mul[2] = 1.504;
+  }
+  if (!model[0])
+    sprintf (model, "%dx%d", width, height);
+  if (filters == UINT_MAX) filters = 0x94949494;
+  if (raw_color) adobe_coeff (make, model);
+  if (load_raw == &CLASS kodak_radc_load_raw)
+    if (raw_color) adobe_coeff ("Apple","Quicktake");
+  if (thumb_offset && !thumb_height) {
+    fseek (ifp, thumb_offset, SEEK_SET);
+    if (ljpeg_start (&jh, 1)) {
+      thumb_width  = jh.wide;
+      thumb_height = jh.high;
+    }
+  }
+dng_skip:
+  if (!load_raw || height < 22) is_raw = 0;
+#ifdef NO_JPEG
+  if (load_raw == &CLASS kodak_jpeg_load_raw) {
+    fprintf (stderr,_("%s: You must link dcraw with libjpeg!!\n"), ifname);
+    is_raw = 0;
+  }
+#endif
+  if (!cdesc[0])
+    strcpy (cdesc, colors == 3 ? "RGB":"GMCY");
+  if (!raw_height) raw_height = height;
+  if (!raw_width ) raw_width  = width;
+  if (filters && colors == 3)
+    for (i=0; i < 32; i+=4) {
+      if ((filters >> i & 15) == 9)
+	filters |= 2 << i;
+      if ((filters >> i & 15) == 6)
+	filters |= 8 << i;
+    }
+notraw:
+  if (flip == -1) flip = tiff_flip;
+  if (flip == -1) flip = 0;
+}
+
+#ifndef NO_LCMS
+void CLASS apply_profile (const char *input, const char *output)
+{
+  char *prof;
+  cmsHPROFILE hInProfile=0, hOutProfile=0;
+  cmsHTRANSFORM hTransform;
+  FILE *fp;
+  unsigned size;
+
+  cmsErrorAction (LCMS_ERROR_SHOW);
+  if (strcmp (input, "embed"))
+    hInProfile = cmsOpenProfileFromFile (input, "r");
+  else if (profile_length) {
+    prof = (char *) malloc (profile_length);
+    merror (prof, "apply_profile()");
+    fseek (ifp, profile_offset, SEEK_SET);
+    fread (prof, 1, profile_length, ifp);
+    hInProfile = cmsOpenProfileFromMem (prof, profile_length);
+    free (prof);
+  } else
+    fprintf (stderr,_("%s has no embedded profile.\n"), ifname);
+  if (!hInProfile) return;
+  if (!output)
+    hOutProfile = cmsCreate_sRGBProfile();
+  else if ((fp = fopen (output, "rb"))) {
+    fread (&size, 4, 1, fp);
+    fseek (fp, 0, SEEK_SET);
+    oprof = (unsigned *) malloc (size = ntohl(size));
+    merror (oprof, "apply_profile()");
+    fread (oprof, 1, size, fp);
+    fclose (fp);
+    if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) {
+      free (oprof);
+      oprof = 0;
+    }
+  } else
+    fprintf (stderr,_("Cannot open file %s!\n"), output);
+  if (!hOutProfile) goto quit;
+  if (verbose)
+    fprintf (stderr,_("Applying color profile...\n"));
+  hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16,
+	hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0);
+  cmsDoTransform (hTransform, image, image, width*height);
+  raw_color = 1;		/* Don't use rgb_cam with a profile */
+  cmsDeleteTransform (hTransform);
+  cmsCloseProfile (hOutProfile);
+quit:
+  cmsCloseProfile (hInProfile);
+}
+#endif
+
+void CLASS convert_to_rgb()
+{
+  int row, col, c, i, j, k;
+  ushort *img;
+  float out[3], out_cam[3][4];
+  double num, inverse[3][3];
+  static const double xyzd50_srgb[3][3] =
+  { { 0.436083, 0.385083, 0.143055 },
+    { 0.222507, 0.716888, 0.060608 },
+    { 0.013930, 0.097097, 0.714022 } };
+  static const double rgb_rgb[3][3] =
+  { { 1,0,0 }, { 0,1,0 }, { 0,0,1 } };
+  static const double adobe_rgb[3][3] =
+  { { 0.715146, 0.284856, 0.000000 },
+    { 0.000000, 1.000000, 0.000000 },
+    { 0.000000, 0.041166, 0.958839 } };
+  static const double wide_rgb[3][3] =
+  { { 0.593087, 0.404710, 0.002206 },
+    { 0.095413, 0.843149, 0.061439 },
+    { 0.011621, 0.069091, 0.919288 } };
+  static const double prophoto_rgb[3][3] =
+  { { 0.529317, 0.330092, 0.140588 },
+    { 0.098368, 0.873465, 0.028169 },
+    { 0.016879, 0.117663, 0.865457 } };
+  static const double (*out_rgb[])[3] =
+  { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb };
+  static const char *name[] =
+  { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" };
+  static const unsigned phead[] =
+  { 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0,
+    0x61637370, 0, 0, 0x6e6f6e65, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d };
+  unsigned pbody[] =
+  { 10, 0x63707274, 0, 36,	/* cprt */
+	0x64657363, 0, 40,	/* desc */
+	0x77747074, 0, 20,	/* wtpt */
+	0x626b7074, 0, 20,	/* bkpt */
+	0x72545243, 0, 14,	/* rTRC */
+	0x67545243, 0, 14,	/* gTRC */
+	0x62545243, 0, 14,	/* bTRC */
+	0x7258595a, 0, 20,	/* rXYZ */
+	0x6758595a, 0, 20,	/* gXYZ */
+	0x6258595a, 0, 20 };	/* bXYZ */
+  static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc };
+  unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 };
+
+  gamma_curve (gamm[0], gamm[1], 0, 0);
+  memcpy (out_cam, rgb_cam, sizeof out_cam);
+  raw_color |= colors == 1 || document_mode ||
+		output_color < 1 || output_color > 5;
+  if (!raw_color) {
+    oprof = (unsigned *) calloc (phead[0], 1);
+    merror (oprof, "convert_to_rgb()");
+    memcpy (oprof, phead, sizeof phead);
+    if (output_color == 5) oprof[4] = oprof[5];
+    oprof[0] = 132 + 12*pbody[0];
+    for (i=0; i < pbody[0]; i++) {
+      oprof[oprof[0]/4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874;
+      pbody[i*3+2] = oprof[0];
+      oprof[0] += (pbody[i*3+3] + 3) & -4;
+    }
+    memcpy (oprof+32, pbody, sizeof pbody);
+    oprof[pbody[5]/4+2] = strlen(name[output_color-1]) + 1;
+    memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite);
+    pcurve[3] = (short)(256/gamm[5]+0.5) << 16;
+    for (i=4; i < 7; i++)
+      memcpy ((char *)oprof+pbody[i*3+2], pcurve, sizeof pcurve);
+    pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3);
+    for (i=0; i < 3; i++)
+      for (j=0; j < 3; j++) {
+	for (num = k=0; k < 3; k++)
+	  num += xyzd50_srgb[i][k] * inverse[j][k];
+        oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5;
+      }
+    for (i=0; i < phead[0]/4; i++)
+      oprof[i] = htonl(oprof[i]);
+    strcpy ((char *)oprof+pbody[2]+8, "auto-generated by dcraw");
+    strcpy ((char *)oprof+pbody[5]+12, name[output_color-1]);
+    for (i=0; i < 3; i++)
+      for (j=0; j < colors; j++)
+	for (out_cam[i][j] = k=0; k < 3; k++)
+	  out_cam[i][j] += out_rgb[output_color-1][i][k] * rgb_cam[k][j];
+  }
+  if (verbose)
+    fprintf (stderr, raw_color ? _("Building histograms...\n") :
+	_("Converting to %s colorspace...\n"), name[output_color-1]);
+
+  memset (histogram, 0, sizeof histogram);
+  for (img=image[0], row=0; row < height; row++)
+    for (col=0; col < width; col++, img+=4) {
+      if (!raw_color) {
+	out[0] = out[1] = out[2] = 0;
+	FORCC {
+	  out[0] += out_cam[0][c] * img[c];
+	  out[1] += out_cam[1][c] * img[c];
+	  out[2] += out_cam[2][c] * img[c];
+	}
+	FORC3 img[c] = CLIP((int) out[c]);
+      }
+      else if (document_mode)
+	img[0] = img[FC(row,col)];
+      FORCC histogram[c][img[c] >> 3]++;
+    }
+  if (colors == 4 && output_color) colors = 3;
+  if (document_mode && filters) colors = 1;
+}
+
+void CLASS fuji_rotate()
+{
+  int i, row, col;
+  double step;
+  float r, c, fr, fc;
+  unsigned ur, uc;
+  ushort wide, high, (*img)[4], (*pix)[4];
+
+  if (!fuji_width) return;
+  if (verbose)
+    fprintf (stderr,_("Rotating image 45 degrees...\n"));
+  fuji_width = (fuji_width - 1 + shrink) >> shrink;
+  step = sqrt(0.5);
+  wide = fuji_width / step;
+  high = (height - fuji_width) / step;
+  img = (ushort (*)[4]) calloc (wide*high, sizeof *img);
+  merror (img, "fuji_rotate()");
+
+  for (row=0; row < high; row++)
+    for (col=0; col < wide; col++) {
+      ur = r = fuji_width + (row-col)*step;
+      uc = c = (row+col)*step;
+      if (ur > height-2 || uc > width-2) continue;
+      fr = r - ur;
+      fc = c - uc;
+      pix = image + ur*width + uc;
+      for (i=0; i < colors; i++)
+	img[row*wide+col][i] =
+	  (pix[    0][i]*(1-fc) + pix[      1][i]*fc) * (1-fr) +
+	  (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr;
+    }
+  free (image);
+  width  = wide;
+  height = high;
+  image  = img;
+  fuji_width = 0;
+}
+
+void CLASS stretch()
+{
+  ushort newdim, (*img)[4], *pix0, *pix1;
+  int row, col, c;
+  double rc, frac;
+
+  if (pixel_aspect == 1) return;
+  if (verbose) fprintf (stderr,_("Stretching the image...\n"));
+  if (pixel_aspect < 1) {
+    newdim = height / pixel_aspect + 0.5;
+    img = (ushort (*)[4]) calloc (width*newdim, sizeof *img);
+    merror (img, "stretch()");
+    for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) {
+      frac = rc - (c = rc);
+      pix0 = pix1 = image[c*width];
+      if (c+1 < height) pix1 += width*4;
+      for (col=0; col < width; col++, pix0+=4, pix1+=4)
+	FORCC img[row*width+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
+    }
+    height = newdim;
+  } else {
+    newdim = width * pixel_aspect + 0.5;
+    img = (ushort (*)[4]) calloc (height*newdim, sizeof *img);
+    merror (img, "stretch()");
+    for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) {
+      frac = rc - (c = rc);
+      pix0 = pix1 = image[c];
+      if (c+1 < width) pix1 += 4;
+      for (row=0; row < height; row++, pix0+=width*4, pix1+=width*4)
+	FORCC img[row*newdim+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
+    }
+    width = newdim;
+  }
+  free (image);
+  image = img;
+}
+
+int CLASS flip_index (int row, int col)
+{
+  if (flip & 4) SWAP(row,col);
+  if (flip & 2) row = iheight - 1 - row;
+  if (flip & 1) col = iwidth  - 1 - col;
+  return row * iwidth + col;
+}
+
+struct tiff_tag {
+  ushort tag, type;
+  int count;
+  union { char c[4]; short s[2]; int i; } val;
+};
+
+struct tiff_hdr {
+  ushort order, magic;
+  int ifd;
+  ushort pad, ntag;
+  struct tiff_tag tag[23];
+  int nextifd;
+  ushort pad2, nexif;
+  struct tiff_tag exif[4];
+  ushort pad3, ngps;
+  struct tiff_tag gpst[10];
+  short bps[4];
+  int rat[10];
+  unsigned gps[26];
+  char desc[512], make[64], model[64], soft[32], date[20], artist[64];
+};
+
+void CLASS tiff_set (ushort *ntag,
+	ushort tag, ushort type, int count, int val)
+{
+  struct tiff_tag *tt;
+  int c;
+
+  tt = (struct tiff_tag *)(ntag+1) + (*ntag)++;
+  tt->tag = tag;
+  tt->type = type;
+  tt->count = count;
+  if (type < 3 && count <= 4)
+    FORC(4) tt->val.c[c] = val >> (c << 3);
+  else if (type == 3 && count <= 2)
+    FORC(2) tt->val.s[c] = val >> (c << 4);
+  else tt->val.i = val;
+}
+
+#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
+
+void CLASS tiff_head (struct tiff_hdr *th, int full)
+{
+  int c, psize=0;
+  struct tm *t;
+
+  memset (th, 0, sizeof *th);
+  th->order = htonl(0x4d4d4949) >> 16;
+  th->magic = 42;
+  th->ifd = 10;
+  if (full) {
+    tiff_set (&th->ntag, 254, 4, 1, 0);
+    tiff_set (&th->ntag, 256, 4, 1, width);
+    tiff_set (&th->ntag, 257, 4, 1, height);
+    tiff_set (&th->ntag, 258, 3, colors, output_bps);
+    if (colors > 2)
+      th->tag[th->ntag-1].val.i = TOFF(th->bps);
+    FORC4 th->bps[c] = output_bps;
+    tiff_set (&th->ntag, 259, 3, 1, 1);
+    tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1));
+  }
+  tiff_set (&th->ntag, 270, 2, 512, TOFF(th->desc));
+  tiff_set (&th->ntag, 271, 2, 64, TOFF(th->make));
+  tiff_set (&th->ntag, 272, 2, 64, TOFF(th->model));
+  if (full) {
+    if (oprof) psize = ntohl(oprof[0]);
+    tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize);
+    tiff_set (&th->ntag, 277, 3, 1, colors);
+    tiff_set (&th->ntag, 278, 4, 1, height);
+    tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8);
+  } else
+    tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0');
+  tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0]));
+  tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2]));
+  tiff_set (&th->ntag, 284, 3, 1, 1);
+  tiff_set (&th->ntag, 296, 3, 1, 2);
+  tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft));
+  tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date));
+  tiff_set (&th->ntag, 315, 2, 64, TOFF(th->artist));
+  tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif));
+  if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th);
+  tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
+  tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
+  tiff_set (&th->nexif, 34855, 3, 1, iso_speed);
+  tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
+  if (gpsdata[1]) {
+    tiff_set (&th->ntag, 34853, 4, 1, TOFF(th->ngps));
+    tiff_set (&th->ngps,  0, 1,  4, 0x202);
+    tiff_set (&th->ngps,  1, 2,  2, gpsdata[29]);
+    tiff_set (&th->ngps,  2, 5,  3, TOFF(th->gps[0]));
+    tiff_set (&th->ngps,  3, 2,  2, gpsdata[30]);
+    tiff_set (&th->ngps,  4, 5,  3, TOFF(th->gps[6]));
+    tiff_set (&th->ngps,  5, 1,  1, gpsdata[31]);
+    tiff_set (&th->ngps,  6, 5,  1, TOFF(th->gps[18]));
+    tiff_set (&th->ngps,  7, 5,  3, TOFF(th->gps[12]));
+    tiff_set (&th->ngps, 18, 2, 12, TOFF(th->gps[20]));
+    tiff_set (&th->ngps, 29, 2, 12, TOFF(th->gps[23]));
+    memcpy (th->gps, gpsdata, sizeof th->gps);
+  }
+  th->rat[0] = th->rat[2] = 300;
+  th->rat[1] = th->rat[3] = 1;
+  FORC(6) th->rat[4+c] = 1000000;
+  th->rat[4] *= shutter;
+  th->rat[6] *= aperture;
+  th->rat[8] *= focal_len;
+  strncpy (th->desc, desc, 512);
+  strncpy (th->make, make, 64);
+  strncpy (th->model, model, 64);
+  strcpy (th->soft, "dcraw v"VERSION);
+  t = gmtime (&timestamp);
+  sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d",
+      t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
+  strncpy (th->artist, artist, 64);
+}
+
+void CLASS jpeg_thumb()
+{
+  char *thumb;
+  ushort exif[5];
+  struct tiff_hdr th;
+
+  thumb = (char *) malloc (thumb_length);
+  merror (thumb, "jpeg_thumb()");
+  fread (thumb, 1, thumb_length, ifp);
+  fputc (0xff, ofp);
+  fputc (0xd8, ofp);
+  if (strcmp (thumb+6, "Exif")) {
+    memcpy (exif, "\xff\xe1  Exif\0\0", 10);
+    exif[1] = htons (8 + sizeof th);
+    fwrite (exif, 1, sizeof exif, ofp);
+    tiff_head (&th, 0);
+    fwrite (&th, 1, sizeof th, ofp);
+  }
+  fwrite (thumb+2, 1, thumb_length-2, ofp);
+  free (thumb);
+}
+
+void CLASS write_ppm_tiff()
+{
+  struct tiff_hdr th;
+  uchar *ppm;
+  ushort *ppm2;
+  int c, row, col, soff, rstep, cstep;
+  int perc, val, total, white=0x2000;
+
+  perc = width * height * 0.01;		/* 99th percentile white level */
+  if (fuji_width) perc /= 2;
+  if (!((highlight & ~2) || no_auto_bright))
+    for (white=c=0; c < colors; c++) {
+      for (val=0x2000, total=0; --val > 32; )
+	if ((total += histogram[c][val]) > perc) break;
+      if (white < val) white = val;
+    }
+  gamma_curve (gamm[0], gamm[1], 2, (white << 3)/bright);
+  iheight = height;
+  iwidth  = width;
+  if (flip & 4) SWAP(height,width);
+  ppm = (uchar *) calloc (width, colors*output_bps/8);
+  ppm2 = (ushort *) ppm;
+  merror (ppm, "write_ppm_tiff()");
+  if (output_tiff) {
+    tiff_head (&th, 1);
+    fwrite (&th, sizeof th, 1, ofp);
+    if (oprof)
+      fwrite (oprof, ntohl(oprof[0]), 1, ofp);
+  } else if (colors > 3)
+    fprintf (ofp,
+      "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
+	width, height, colors, (1 << output_bps)-1, cdesc);
+  else
+    fprintf (ofp, "P%d\n%d %d\n%d\n",
+	colors/2+5, width, height, (1 << output_bps)-1);
+  soff  = flip_index (0, 0);
+  cstep = flip_index (0, 1) - soff;
+  rstep = flip_index (1, 0) - flip_index (0, width);
+  for (row=0; row < height; row++, soff += rstep) {
+    for (col=0; col < width; col++, soff += cstep)
+      if (output_bps == 8)
+	   FORCC ppm [col*colors+c] = curve[image[soff][c]] >> 8;
+      else FORCC ppm2[col*colors+c] = curve[image[soff][c]];
+    if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa)
+      swab (ppm2, ppm2, width*colors*2);
+    fwrite (ppm, colors*output_bps/8, width, ofp);
+  }
+  free (ppm);
+}
+
+int CLASS main (int argc, const char **argv)
+{
+  int arg, status=0;
+  int timestamp_only=0, thumbnail_only=0, identify_only=0;
+  int user_qual=-1, user_black=-1, user_sat=-1, user_flip=-1;
+  int use_fuji_rotate=1, write_to_stdout=0, quality, i, c;
+  const char *sp, *bpfile=0, *dark_frame=0, *write_ext;
+  char opm, opt, *ofname, *cp;
+  struct utimbuf ut;
+#ifndef NO_LCMS
+  const char *cam_profile=0, *out_profile=0;
+#endif
+
+#ifndef LOCALTIME
+  putenv ((char *) "TZ=UTC");
+#endif
+#ifdef LOCALEDIR
+  setlocale (LC_CTYPE, "");
+  setlocale (LC_MESSAGES, "");
+  bindtextdomain ("dcraw", LOCALEDIR);
+  textdomain ("dcraw");
+#endif
+
+  if (argc == 1) {
+    printf(_("\nRaw photo decoder \"dcraw\" v%s"), VERSION);
+    printf(_("\nby Dave Coffin, dcoffin a cybercom o net\n"));
+    printf(_("\nUsage:  %s [OPTION]... [FILE]...\n\n"), argv[0]);
+    puts(_("-v        Print verbose messages"));
+    puts(_("-c        Write image data to standard output"));
+    puts(_("-e        Extract embedded thumbnail image"));
+    puts(_("-i        Identify files without decoding them"));
+    puts(_("-i -v     Identify files and show metadata"));
+    puts(_("-z        Change file dates to camera timestamp"));
+    puts(_("-w        Use camera white balance, if possible"));
+    puts(_("-a        Average the whole image for white balance"));
+    puts(_("-A <x y w h> Average a grey box for white balance"));
+    puts(_("-r <r g b g> Set custom white balance"));
+    puts(_("+M/-M     Use/don't use an embedded color matrix"));
+    puts(_("-C <r b>  Correct chromatic aberration"));
+    puts(_("-P <file> Fix the dead pixels listed in this file"));
+    puts(_("-K <file> Subtract dark frame (16-bit raw PGM)"));
+    puts(_("-k <num>  Set the darkness level"));
+    puts(_("-S <num>  Set the saturation level"));
+    puts(_("-n <num>  Set threshold for wavelet denoising"));
+    puts(_("-H [0-9]  Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)"));
+    puts(_("-t [0-7]  Flip image (0=none, 3=180, 5=90CCW, 6=90CW)"));
+    puts(_("-o [0-5]  Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)"));
+#ifndef NO_LCMS
+    puts(_("-o <file> Apply output ICC profile from file"));
+    puts(_("-p <file> Apply camera ICC profile from file or \"embed\""));
+#endif
+    puts(_("-d        Document mode (no color, no interpolation)"));
+    puts(_("-D        Document mode without scaling (totally raw)"));
+    puts(_("-j        Don't stretch or rotate raw pixels"));
+    puts(_("-W        Don't automatically brighten the image"));
+    puts(_("-b <num>  Adjust brightness (default = 1.0)"));
+    puts(_("-g <p ts> Set custom gamma curve (default = 2.222 4.5)"));
+    puts(_("-q [0-3]  Set the interpolation quality"));
+    puts(_("-h        Half-size color image (twice as fast as \"-q 0\")"));
+    puts(_("-f        Interpolate RGGB as four colors"));
+    puts(_("-m <num>  Apply a 3x3 median filter to R-G and B-G"));
+    puts(_("-s [0..N-1] Select one raw image or \"all\" from each file"));
+    puts(_("-6        Write 16-bit instead of 8-bit"));
+    puts(_("-4        Linear 16-bit, same as \"-6 -W -g 1 1\""));
+    puts(_("-T        Write TIFF instead of PPM"));
+    puts("");
+    return 1;
+  }
+  argv[argc] = "";
+  for (arg=1; (((opm = argv[arg][0]) - 2) | 2) == '+'; ) {
+    opt = argv[arg++][1];
+    if ((cp = strchr (sp="nbrkStqmHACg", opt)))
+      for (i=0; i < "114111111422"[cp-sp]-'0'; i++)
+	if (!isdigit(argv[arg+i][0])) {
+	  fprintf (stderr,_("Non-numeric argument to \"-%c\"\n"), opt);
+	  return 1;
+	}
+    switch (opt) {
+      case 'n':  threshold   = atof(argv[arg++]);  break;
+      case 'b':  bright      = atof(argv[arg++]);  break;
+      case 'r':
+	   FORC4 user_mul[c] = atof(argv[arg++]);  break;
+      case 'C':  aber[0] = 1 / atof(argv[arg++]);
+		 aber[2] = 1 / atof(argv[arg++]);  break;
+      case 'g':  gamm[0] =     atof(argv[arg++]);
+		 gamm[1] =     atof(argv[arg++]);
+		 if (gamm[0]) gamm[0] = 1/gamm[0]; break;
+      case 'k':  user_black  = atoi(argv[arg++]);  break;
+      case 'S':  user_sat    = atoi(argv[arg++]);  break;
+      case 't':  user_flip   = atoi(argv[arg++]);  break;
+      case 'q':  user_qual   = atoi(argv[arg++]);  break;
+      case 'm':  med_passes  = atoi(argv[arg++]);  break;
+      case 'H':  highlight   = atoi(argv[arg++]);  break;
+      case 's':
+	shot_select = abs(atoi(argv[arg]));
+	multi_out = !strcmp(argv[arg++],"all");
+	break;
+      case 'o':
+	if (isdigit(argv[arg][0]) && !argv[arg][1])
+	  output_color = atoi(argv[arg++]);
+#ifndef NO_LCMS
+	else     out_profile = argv[arg++];
+	break;
+      case 'p':  cam_profile = argv[arg++];
+#endif
+	break;
+      case 'P':  bpfile     = argv[arg++];  break;
+      case 'K':  dark_frame = argv[arg++];  break;
+      case 'z':  timestamp_only    = 1;  break;
+      case 'e':  thumbnail_only    = 1;  break;
+      case 'i':  identify_only     = 1;  break;
+      case 'c':  write_to_stdout   = 1;  break;
+      case 'v':  verbose           = 1;  break;
+      case 'h':  half_size         = 1;		/* "-h" implies "-f" */
+      case 'f':  four_color_rgb    = 1;  break;
+      case 'A':  FORC4 greybox[c]  = atoi(argv[arg++]);
+      case 'a':  use_auto_wb       = 1;  break;
+      case 'w':  use_camera_wb     = 1;  break;
+      case 'M':  use_camera_matrix = (opm == '+');  break;
+      case 'D':
+      case 'd':  document_mode = 1 + (opt == 'D');
+      case 'j':  use_fuji_rotate   = 0;  break;
+      case 'W':  no_auto_bright    = 1;  break;
+      case 'T':  output_tiff       = 1;  break;
+      case '4':  gamm[0] = gamm[1] =
+		 no_auto_bright    = 1;
+      case '6':  output_bps       = 16;  break;
+      default:
+	fprintf (stderr,_("Unknown option \"-%c\".\n"), opt);
+	return 1;
+    }
+  }
+  if (use_camera_matrix < 0)
+      use_camera_matrix = use_camera_wb;
+  if (arg == argc) {
+    fprintf (stderr,_("No files to process.\n"));
+    return 1;
+  }
+  if (write_to_stdout) {
+    if (isatty(1)) {
+      fprintf (stderr,_("Will not write an image to the terminal!\n"));
+      return 1;
+    }
+#if defined(WIN32) || defined(DJGPP) || defined(__CYGWIN__)
+    if (setmode(1,O_BINARY) < 0) {
+      perror ("setmode()");
+      return 1;
+    }
+#endif
+  }
+  for ( ; arg < argc; arg++) {
+    status = 1;
+    image = 0;
+    oprof = 0;
+    meta_data = ofname = 0;
+    ofp = stdout;
+    if (setjmp (failure)) {
+      if (fileno(ifp) > 2) fclose(ifp);
+      if (fileno(ofp) > 2) fclose(ofp);
+      status = 1;
+      goto cleanup;
+    }
+    ifname = argv[arg];
+    if (!(ifp = fopen (ifname, "rb"))) {
+      perror (ifname);
+      continue;
+    }
+    status = (identify(),!is_raw);
+    if (user_flip >= 0)
+      flip = user_flip;
+    switch ((flip+3600) % 360) {
+      case 270:  flip = 5;  break;
+      case 180:  flip = 3;  break;
+      case  90:  flip = 6;
+    }
+    if (timestamp_only) {
+      if ((status = !timestamp))
+	fprintf (stderr,_("%s has no timestamp.\n"), ifname);
+      else if (identify_only)
+	printf ("%10ld%10d %s\n", (long) timestamp, shot_order, ifname);
+      else {
+	if (verbose)
+	  fprintf (stderr,_("%s time set to %d.\n"), ifname, (int) timestamp);
+	ut.actime = ut.modtime = timestamp;
+	utime (ifname, &ut);
+      }
+      goto next;
+    }
+    write_fun = &CLASS write_ppm_tiff;
+    if (thumbnail_only) {
+      if ((status = !thumb_offset)) {
+	fprintf (stderr,_("%s has no thumbnail.\n"), ifname);
+	goto next;
+      } else if (thumb_load_raw) {
+	load_raw = thumb_load_raw;
+	data_offset = thumb_offset;
+	height = thumb_height;
+	width  = thumb_width;
+	filters = 0;
+      } else {
+	fseek (ifp, thumb_offset, SEEK_SET);
+	write_fun = write_thumb;
+	goto thumbnail;
+      }
+    }
+    if (load_raw == &CLASS kodak_ycbcr_load_raw) {
+      height += height & 1;
+      width  += width  & 1;
+    }
+    if (identify_only && verbose && make[0]) {
+      printf (_("\nFilename: %s\n"), ifname);
+      printf (_("Timestamp: %s"), ctime(&timestamp));
+      printf (_("Camera: %s %s\n"), make, model);
+      if (artist[0])
+	printf (_("Owner: %s\n"), artist);
+      if (dng_version) {
+	printf (_("DNG Version: "));
+	for (i=24; i >= 0; i -= 8)
+	  printf ("%d%c", dng_version >> i & 255, i ? '.':'\n');
+      }
+      printf (_("ISO speed: %d\n"), (int) iso_speed);
+      printf (_("Shutter: "));
+      if (shutter > 0 && shutter < 1)
+	shutter = (printf ("1/"), 1 / shutter);
+      printf (_("%0.1f sec\n"), shutter);
+      printf (_("Aperture: f/%0.1f\n"), aperture);
+      printf (_("Focal length: %0.1f mm\n"), focal_len);
+      printf (_("Embedded ICC profile: %s\n"), profile_length ? _("yes"):_("no"));
+      printf (_("Number of raw images: %d\n"), is_raw);
+      if (pixel_aspect != 1)
+	printf (_("Pixel Aspect Ratio: %0.6f\n"), pixel_aspect);
+      if (thumb_offset)
+	printf (_("Thumb size:  %4d x %d\n"), thumb_width, thumb_height);
+      printf (_("Full size:   %4d x %d\n"), raw_width, raw_height);
+    } else if (!is_raw)
+      fprintf (stderr,_("Cannot decode file %s\n"), ifname);
+    if (!is_raw) goto next;
+    shrink = filters &&
+	(half_size || threshold || aber[0] != 1 || aber[2] != 1);
+    iheight = (height + shrink) >> shrink;
+    iwidth  = (width  + shrink) >> shrink;
+    if (identify_only) {
+      if (verbose) {
+	if (use_fuji_rotate) {
+	  if (fuji_width) {
+	    fuji_width = (fuji_width - 1 + shrink) >> shrink;
+	    iwidth = fuji_width / sqrt(0.5);
+	    iheight = (iheight - fuji_width) / sqrt(0.5);
+	  } else {
+	    if (pixel_aspect < 1) iheight = iheight / pixel_aspect + 0.5;
+	    if (pixel_aspect > 1) iwidth  = iwidth  * pixel_aspect + 0.5;
+	  }
+	}
+	if (flip & 4)
+	  SWAP(iheight,iwidth);
+	printf (_("Image size:  %4d x %d\n"), width, height);
+	printf (_("Output size: %4d x %d\n"), iwidth, iheight);
+	printf (_("Raw colors: %d"), colors);
+	if (filters) {
+	  printf (_("\nFilter pattern: "));
+	  if (!cdesc[3]) cdesc[3] = 'G';
+	  for (i=0; i < 16; i++)
+	    putchar (cdesc[fc(i >> 1,i & 1)]);
+	}
+	printf (_("\nDaylight multipliers:"));
+	FORCC printf (" %f", pre_mul[c]);
+	if (cam_mul[0] > 0) {
+	  printf (_("\nCamera multipliers:"));
+	  FORC4 printf (" %f", cam_mul[c]);
+	}
+	putchar ('\n');
+      } else
+	printf (_("%s is a %s %s image.\n"), ifname, make, model);
+next:
+      fclose(ifp);
+      continue;
+    }
+    if (use_camera_matrix && cmatrix[0][0] > 0.25) {
+      memcpy (rgb_cam, cmatrix, sizeof cmatrix);
+      raw_color = 0;
+    }
+    image = (ushort (*)[4]) calloc (iheight*iwidth, sizeof *image);
+    merror (image, "main()");
+    if (meta_length) {
+      meta_data = (char *) malloc (meta_length);
+      merror (meta_data, "main()");
+    }
+    if (verbose)
+      fprintf (stderr,_("Loading %s %s image from %s ...\n"),
+	make, model, ifname);
+    if (shot_select >= is_raw)
+      fprintf (stderr,_("%s: \"-s %d\" requests a nonexistent image!\n"),
+	ifname, shot_select);
+    fseeko (ifp, data_offset, SEEK_SET);
+    (*load_raw)();
+    if (zero_is_bad) remove_zeroes();
+    bad_pixels (bpfile);
+    if (dark_frame) subtract (dark_frame);
+    quality = 2 + !fuji_width;
+    if (user_qual >= 0) quality = user_qual;
+    if (user_black >= 0) black = user_black;
+    if (user_sat > 0) maximum = user_sat;
+#ifdef COLORCHECK
+    colorcheck();
+#endif
+    if (is_foveon && !document_mode) foveon_interpolate();
+    if (!is_foveon && document_mode < 2) scale_colors();
+    pre_interpolate();
+    if (filters && !document_mode) {
+      if (quality == 0)
+	lin_interpolate();
+      else if (quality == 1 || colors > 3)
+	vng_interpolate();
+      else if (quality == 2)
+	ppg_interpolate();
+      else ahd_interpolate();
+    }
+    if (mix_green)
+      for (colors=3, i=0; i < height*width; i++)
+	image[i][1] = (image[i][1] + image[i][3]) >> 1;
+    if (!is_foveon && colors == 3) median_filter();
+    if (!is_foveon && highlight == 2) blend_highlights();
+    if (!is_foveon && highlight > 2) recover_highlights();
+    if (use_fuji_rotate) fuji_rotate();
+#ifndef NO_LCMS
+    if (cam_profile) apply_profile (cam_profile, out_profile);
+#endif
+    convert_to_rgb();
+    if (use_fuji_rotate) stretch();
+thumbnail:
+    if (write_fun == &CLASS jpeg_thumb)
+      write_ext = ".jpg";
+    else if (output_tiff && write_fun == &CLASS write_ppm_tiff)
+      write_ext = ".tiff";
+    else
+      write_ext = ".pgm\0.ppm\0.ppm\0.pam" + colors*5-5;
+    ofname = (char *) malloc (strlen(ifname) + 64);
+    merror (ofname, "main()");
+    if (write_to_stdout)
+      strcpy (ofname,_("standard output"));
+    else {
+      strcpy (ofname, ifname);
+      if ((cp = strrchr (ofname, '.'))) *cp = 0;
+      if (multi_out)
+	sprintf (ofname+strlen(ofname), "_%0*d",
+		snprintf(0,0,"%d",is_raw-1), shot_select);
+      if (thumbnail_only)
+	strcat (ofname, ".thumb");
+      strcat (ofname, write_ext);
+      ofp = fopen (ofname, "wb");
+      if (!ofp) {
+	status = 1;
+	perror (ofname);
+	goto cleanup;
+      }
+    }
+    if (verbose)
+      fprintf (stderr,_("Writing data to %s ...\n"), ofname);
+    (*write_fun)();
+    fclose(ifp);
+    if (ofp != stdout) fclose(ofp);
+cleanup:
+    if (meta_data) free (meta_data);
+    if (ofname) free (ofname);
+    if (oprof) free (oprof);
+    if (image) free (image);
+    if (multi_out) {
+      if (++shot_select < is_raw) arg--;
+      else shot_select = 0;
+    }
+  }
+  return status;
+}
diff --git a/libfspotraw/LibRaw/doc/API-C-eng.html b/libfspotraw/LibRaw/doc/API-C-eng.html
new file mode 100644
index 0000000..6a7f1ac
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/API-C-eng.html
@@ -0,0 +1,200 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw: C API</title>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+  </head>
+
+  <body>
+    <a href=index-eng.html>[back to Index]</a>
+    <h1>LibRaw: C API</h1>
+    <p>LibRaw C API is a wrapper around C++ API; therefore, virtually all documentation to C 
+      API functions  is represented by a set of hyperlinks to the corresponding places in the <a href="API-CXX-eng.html">description of C++ API</a>.
+    </p>
+    <p>Contents</p>
+    <ol>
+      <li><a href="#init">Initialization:  libraw_data_t       *libraw_init(unsigned int flags);</a></li>
+      <li><a href="#return">Returned values</a></li>
+      <li><a href="#dataload">Data loading</a></li>
+      <li><a href="#utility">Auxiliary Functions</a></li>
+      <li><a href="#dcrawemu">Data Postprocessing, Emulation of dcraw Behavior</a>
+        <ul>
+          <li><a href="#dcrawparams">Setting of Parameters</a></li>
+          <li><a href="#emu">Emulation of dcraw Behavior</a></li>
+        </ul>
+        </li>
+      <li><a href="#write">Writing to Output Files</a></li>
+      <li><a href="#memwrite">Writing processing results to memory buffer</a></li>
+    </ol>
+
+
+    <a name="init"></a>
+    <h2>Initialization:  libraw_data_t       *libraw_init(unsigned int flags);</h2>
+    <p>
+      The function returns the pointer to the <a href=#API-datastruct-eng.html#libraw_data_t>instance of
+        libraw_data_t structure</a>.<br/>
+      The resultant pointer should be passed as the first argument to all C API functions (except for libraw_strerror).
+    </p>
+    <p>Returns NULL in case of error, pointer to the structure in all other cases.</p>
+
+    <a name="return"></a>
+    <h2>Returned values</h2>
+    <p>Functions of C API return EINVAL (see errno.h) if the null pointer was passed to them as the first argument. 
+In all other cases, the <a href="API-CXX-eng.html#return">C++ API return code</a> is returned.
+    </p>
+
+    <a name="dataload"></a>
+    <h2>Data Loading from a File</h2>
+    <dl>
+      <dt>int libraw_open_file(libraw_data_t*, const char *)</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#open_file">LibRaw::open_file()</a>
+      </dd>
+      <dt>int libraw_open_buffer(libraw_data_t*, void *buffer, size_t bufsize)</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#open_buffer">LibRaw::open_buffer()</a>
+      </dd>
+      <dt>    int                 libraw_unpack(libraw_data_t*);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#unpack">LibRaw::unpack()</a>
+      </dd>
+      <dt>    int                 libraw_unpack_thumb(libraw_data_t*);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#unpack_thumb">LibRaw::unpack_thumb()</a>
+      </dd>
+
+    </dl>
+    <a name="utility"></a>
+    <h2>Auxiliary Functions</h2>
+    <dl>
+      <dt>const char* libraw_version()</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#version">LibRaw::version()</a>
+      </dd>
+      <dt>const char* libraw_versionNumber()</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#versionNumber">LibRaw::versionNumber()</a>
+      </dd>
+      <dt>bool LIBRAW_CHECK_VERSION(major,minor,patch)</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#LIBRAW_CHECK_VERSION">LIBRAW_CHECK_VERSION</a> â îïèñàíèè C++ API
+      </dd>
+    <dt>int libraw_cameraCount()</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#cameraCount">LibRaw::cameraCount()</a>
+      </dd>
+    <dt>int libraw_cameraList()</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#cameraList">LibRaw::cameraList()</a>
+      </dd>
+      <dt>void                libraw_unpack_function_name(libraw_data_t*);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#unpack_function_name">LibRaw::unpack_function_name()</a>
+      </dd>
+      <dt>void                libraw_add_masked_borders_to_bitmap(libraw_data_t*);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#add_masked_borders_to_bitmap">LibRaw::add_masked_borders_to_bitmap()</a>
+        <p>
+          This call is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>.
+        </p>
+      </dd>
+      <dt>void                libraw_rotate_fuji_raw(libraw_data_t*);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#rotate_fuji_raw">LibRaw::rotate_fuji_raw()</a>
+        <p>
+          This call is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. Fuji sensor data  extracted
+          in already rotated bitmap.
+        </p>
+      </dd>
+    <dt>void                libraw_recycle(libraw_data_t*);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#recycle">LibRaw::recycle()</a>
+      </dd>
+    <dt>void                libraw_close(libraw_data_t*);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#~LibRaw">LibRaw::~LibRaw()</a>
+      </dd>
+    <dt>const char          *libraw_strerror(int errorcode);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#libraw_strerror">LibRaw::strerror</a>
+      </dd>
+    <dt>const char          *libraw_strprogress(enum LibRaw_progress);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#strprogress">LibRaw::strprogress</a>
+      </dd>
+    <dt>void                libraw_set_memerror_handler(libraw_data_t*, memory_callback cb);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#memerror">LibRaw::set_memerror_handler()</a>
+      </dd>
+    <dt>void                libraw_set_dataerror_handler(libraw_data_t*,data_callback func);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#dataerror">LibRaw::set_dataerror_handler()</a>
+      </dd>
+    <dt>void                libraw_set_progress_handler(libraw_data_t*,progress_callback func);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#progress">LibRaw::set_progress_handler()</a>
+      </dd>
+    </dl>
+    <a name="dcrawemu"></a>
+    <h2>Data Postprocessing, Emulation of dcraw Behavior</h2>
+    <a name="dcrawparams"></a>
+    <h3>Setting of Parameters</h3>
+    <p>
+      The postprocessing parameters for the calls described below are set, just as for C++ API, via setting of fields in the
+      libraw_output_params_t structure:
+    </p>
+    <pre>
+ libraw_data_t *ptr = libraw_init(0);
+ ptr->params.output_tiff = 1; //  output to TIFF
+    </pre>
+    <p>
+    Fields of this structure are described in the <a href="API-datastruct-eng.html#libraw_output_params_t">documentation to
+      libraw_output_params_t</a>. For notes on their use, see <a href=API-notes-eng.html>API notes</a>.
+    </p>
+    <a name="emu"></a>
+    <h3>Emulation of dcraw Behavior</h3>
+    <dl>
+    <dt>int                 libraw_adjust_sizes_info_only(libraw_data_t*);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#adjust_sizes_info_only">LibRaw::adjust_sizes_info_only()</a>
+      </dd>
+    <dt>int                 libraw_dcraw_document_mode_processing(libraw_data_t*);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#dcraw_document_mode_processing">LibRaw::dcraw_document_mode_processing()</a>
+      </dd>
+    <dt>int                 libraw_dcraw_process(libraw_data_t* lr);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#dcraw_process">LibRaw::dcraw_process()</a>
+      </dd>
+    </dl>
+    <h2>Writing to Output Files</h2>
+    <dl>
+      <dt>int                 libraw_dcraw_ppm_tiff_writer(libraw_data_t* lr,const char *filename);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#dcraw_ppm_tiff_writer">LibRaw::dcraw_ppm_tiff_writer()</a>
+      </dd>
+      <dt>int                 libraw_dcraw_thumb_writer(libraw_data_t* lr,const char *fname);</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#dcraw_thumb_writer">LibRaw::dcraw_thumb_writer()</a>
+      </dd>
+    </dl>
+    <h2>Writing processing results to memory buffer</h2>
+    <dl>
+      <dt>libraw_processed_image_t *dcraw_make_mem_image(libraw_data_t* lr,int * errcode)</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#dcraw_make_mem_image">LibRaw::dcraw_make_mem_image()</a>
+      </dd>
+      <dt>libraw_processed_image_t *dcraw_make_mem_thumb(libraw_data_t* lr,int * errcode)</dt>
+      <dd>
+        See <a href="API-CXX-eng.html#dcraw_make_mem_thumb">LibRaw::dcraw_make_mem_thumb()</a>
+      </dd>
+    </dl>
+    <a href=index-eng.html>[back to Index]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 14:44:49 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:10:26 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/API-C-rus.html b/libfspotraw/LibRaw/doc/API-C-rus.html
new file mode 100644
index 0000000..6647a76
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/API-C-rus.html
@@ -0,0 +1,197 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw: C API</title>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+  </head>
+
+  <body>
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <h1>LibRaw: C API</h1>
+    <p>LibRaw C API ÿâëÿåòñÿ "îáåðòêîé" (wrapper) âîêðóã Ñ++ API, ïîýòîìó ïðàêòè÷åñêè âñÿ  äîêóìåíòàöèÿ ê ôóíêöèÿì C
+      API  ÿâëÿåòñÿ íàáîðîì ãèïåðññûëîê íà ñîîòâåòñòâóþùèå ìåñòà <a href="API-CXX-rus.html">îïèñàíèÿ C++ API</a>.
+    </p>
+
+    <p>Ñîäåðæàíèå</p>
+    <ol>
+      <li><a href="#init">Èíèöèàëèçàöèÿ:  libraw_data_t       *libraw_init(unsigned int flags);</a></li>
+      <li><a href="#return">Âîçâðàùàåìûå çíà÷åíèÿ</a></li>
+      <li><a href="#dataload">Çàãðóçêà äàííûõ èç ôàéëà</a></li>
+      <li><a href="#utility">Âñïîìîãàòåëüíûå ôóíêöèè</a></li>
+      <li><a href="#dcrawemu">Ïîñòîáðàáîòêà äàííûõ, ýìóëÿöèÿ ïîâåäåíèÿ dcraw</a>
+        <ul>
+          <li><a href="#dcrawparams">Óñòàíîâêà ïàðàìåòðîâ</a></li>
+          <li><a href="#emu">Ýìóëÿöèÿ ïîâåäåíèÿ  dcraw</a></li>
+        </ul>
+        </li>
+      <li><a href="#write">Çàïèñü âûõîäíûõ ôàéëîâ</a></li>
+      <li><a href="#memwrite">Çàïèñü ðåçóëüòàòîâ ðàñïàêîâêè â ïàìÿòü</a></li>
+    </ol>
+
+    <a name="init"></a>
+    <h2>Èíèöèàëèçàöèÿ:  libraw_data_t       *libraw_init(unsigned int flags);</h2>
+    <p>
+      Ôóíêöèÿ âîçâðàùàåò óêàçàòåëü íà <a href=#API-datastruct-rus.html#libraw_data_t>ýêçåìïëÿð ñòðóêòóðû
+        libraw_data_t</a>.<br/>
+      Ïîëó÷åííûé óêàçàòåëü íóæíî ïåðåäàâàòü â êà÷åñòâå ïåðâîãî àðãóìåíòà âî âñå ôóíêöèè C API (êðîìå libraw_strerror).
+    </p>
+    <p>Âîçâðàùàåò: NULL ïðè îøèáêå, óêàçàòåëü íà ñòðóêòóðó âî âñåõ îñòàëüíûõ ñëó÷àÿõ.</p>
+
+    <a name="return"></a>
+    <h2>Âîçâðàùàåìûå çíà÷åíèÿ</h2>
+    <p>Ôóíêöèè C API âîçâðàùàþò EINVAL (ñì. errno.h) åñëè èì ïåðåäàí íóëåâîé óêàçàòåëü â êà÷åñòâå ïåðâîãî
+      àðãóìåíòà. Âî âñåõ ïðî÷èõ ñëó÷àÿõ òðàíñëèðóåòñÿ <a href="API-CXX-rus.html#return">êîä âîçâðàòà C++ API</a>.
+    </p>
+
+    <a name="dataload"></a>
+    <h2>Çàãðóçêà äàííûõ èç ôàéëà</h2>
+    <dl>
+      <dt>int libraw_open_file(libraw_data_t*, const char *)</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#open_file">LibRaw::open_file()</a>
+      </dd>
+      <dt>int libraw_open_buffer(libraw_data_t*, void *buffer, size_t bufsize)</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#open_buffer">LibRaw::open_buffer()</a>
+      </dd>
+      <dt>    int                 libraw_unpack(libraw_data_t*);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#unpack">LibRaw::unpack()</a>
+      </dd>
+      <dt>    int                 libraw_unpack_thumb(libraw_data_t*);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#unpack_thumb">LibRaw::unpack_thumb()</a>
+      </dd>
+
+    </dl>
+    <a name="utility"></a>
+    <h2>Âñïîìîãàòåëüíûå ôóíêöèè</h2>
+    <dl>
+      <dt>const char* libraw_version()</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#version">LibRaw::version()</a>
+      </dd>
+      <dt>const char* libraw_versionNumber()</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#versionNumber">LibRaw::versionNumber()</a>
+      </dd>
+      <dt>bool LIBRAW_CHECK_VERSION(major,minor,patch)</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#LIBRAW_CHECK_VERSION">LIBRAW_CHECK_VERSION</a> â îïèñàíèè C++ API
+      </dd>
+    <dt>int libraw_cameraCount()</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#cameraCount">LibRaw::cameraCount()</a>
+      </dd>
+    <dt>int libraw_cameraList()</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#cameraList">LibRaw::cameraList()</a>
+      </dd>
+      <dt>void                libraw_unpack_function_name(libraw_data_t*);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#unpack_function_name">LibRaw::unpack_function_name()</a>
+      </dd>
+      <dt>void                libraw_add_masked_borders_to_bitmap(libraw_data_t*);</dt>
+      <dd>
+        Âûçîâ íå ïîääåðæèâàåòñÿ â <a href=API-notes-rus.html#versions>LibRaw-Lite</a><br/>
+        Ñì. <a href="API-CXX-rus.html#add_masked_borders_to_bitmap">LibRaw::add_masked_borders_to_bitmap()</a>
+      </dd>
+      <dt>void                libraw_rotate_fuji_raw(libraw_data_t*);</dt>
+      <dd>
+        Âûçîâ íå ïîääåðæèâàåòñÿ (è íå íóæåí) â <a href=API-notes-rus.html#versions>LibRaw-Lite</a><br/>
+        Ñì. <a href="API-CXX-rus.html#rotate_fuji_raw">LibRaw::rotate_fuji_raw()</a>
+      </dd>
+      <dt>void                libraw_recycle(libraw_data_t*);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#recycle">LibRaw::recycle()</a>
+      </dd>
+    <dt>void                libraw_close(libraw_data_t*);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#~LibRaw">LibRaw::~LibRaw()</a>
+      </dd>
+    <dt>const char          *libraw_strerror(int errorcode);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#libraw_strerror">libraw_strerror</a>
+      </dd>
+    <dt>const char          *libraw_streprogress(enum LibRaw_progress);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#strprogress">LibRaw::strprogress</a>
+      </dd>
+    <dt>void                libraw_set_memerror_handler(libraw_data_t*, memory_callback cb);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#memerror">LibRaw::set_memerror_handler()</a>
+      </dd>
+    <dt>void                libraw_set_dataerror_handler(libraw_data_t*,data_callback func);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#dataerror">LibRaw::set_dataerror_handler()</a>
+      </dd>
+    <dt>void                libraw_set_progress_handler(libraw_data_t*,progress_callback func);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#progress">LibRaw::set_progress_handler()</a>
+      </dd>
+    </dl>
+    <a name="dcrawemu"></a>
+    <h2>Ïîñòîáðàáîòêà äàííûõ, ýìóëÿöèÿ ïîâåäåíèÿ dcraw</h2>
+    <a name="dcrawparams"></a>
+    <h3>Óñòàíîâêà ïàðàìåòðîâ</h3>
+    <p>
+      Ïàðàìåòðû ïîñòîáðàáîòêè äëÿ îïèñàííûõ íèæå âûçîâîâ ñòàâÿòñÿ, êàê è äëÿ  Ñ++ API, ìîäèôèêàöèåé ïîëåé ñòðóêòóðû
+      libraw_output_params_t:
+    </p>
+    <pre>
+ libraw_data_t *ptr = libraw_init(0);
+ ptr->params.output_tiff = 1; //  âûâîäèòü â TIFF
+    </pre>
+    <p>
+    Ïîëÿ ñòðóêòóðû îïèñàíû â <a href="API-datastruct-rus.html#libraw_output_params_t">äîêóìåíòàöèè íà
+      libraw_output_params_t</a>, çàìå÷àíèÿ ïî èõ èñïîëüçîâàíèþ óêàçàíû â <a href=API-notes-rus.html>API notes</a>.
+    </p>
+    <a name="emu"></a>
+    <h3>Ýìóëÿöèÿ ïîâåäåíèÿ  dcraw</h3>
+    <dl>
+    <dt>int                 libraw_adjust_sizes_info_only(libraw_data_t*);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#adjust_sizes_info_only">LibRaw::adjust_sizes_info_only()</a>
+      </dd>
+    <dt>int                 libraw_dcraw_document_mode_processing(libraw_data_t*);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#dcraw_document_mode_processing">LibRaw::dcraw_document_mode_processing()</a>
+      </dd>
+    <dt>int                 libraw_dcraw_process(libraw_data_t* lr);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#dcraw_process">LibRaw::dcraw_process()</a>
+      </dd>
+    </dl>
+    <a name="write"></a>
+    <h2>Çàïèñü âûõîäíûõ ôàéëîâ</h2>
+    <dl>
+      <dt>int                 libraw_dcraw_ppm_tiff_writer(libraw_data_t* lr,const char *filename);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#dcraw_ppm_tiff_writer">LibRaw::dcraw_ppm_tiff_writer()</a>
+      </dd>
+      <dt>int                 libraw_dcraw_thumb_writer(libraw_data_t* lr,const char *fname);</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#dcraw_thumb_writer">LibRaw::dcraw_thumb_writer()</a>
+      </dd>
+    </dl>
+    <a name="memwrite"></a>
+    <h2>Çàïèñü ðåçóëüòàòîâ ðàñïàêîâêè â ïàìÿòü</h2>
+    <dl>
+      <dt>libraw_processed_image_t *dcraw_make_mem_image(libraw_data_t* lr,int * errcode)</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#dcraw_make_mem_image">LibRaw::dcraw_make_mem_image()</a>
+      </dd>
+      <dt>libraw_processed_image_t *dcraw_make_mem_thumb(libraw_data_t* lr,int * errcode)</dt>
+      <dd>
+        Ñì. <a href="API-CXX-rus.html#dcraw_make_mem_thumb">LibRaw::dcraw_make_mem_thumb()</a>
+      </dd>
+    </dl>
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 14:44:49 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:59 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/API-CXX-eng.html b/libfspotraw/LibRaw/doc/API-CXX-eng.html
new file mode 100644
index 0000000..840e31d
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/API-CXX-eng.html
@@ -0,0 +1,811 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw C++ API</title>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+  </head>
+
+  <body>
+    <a href=index-eng.html>[back to Index]</a>
+    <h1>LibRaw C++ API</h1>
+    <p>Contents</p>
+    <ol>
+      <li><a href="#LibRaw">LibRaw Objects</a> </li>
+      <li><a href="#return">Returned values</a></li>
+      <li><a  href="#dataload">Methods Loading Data from a File</a>
+        <ul>
+          <li><a href="#open_datastream">int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)</a></li>
+          <li><a  href="#open_file">int LibRaw::open_file(const char *rawfile)</a></li>
+          <li><a  href="#open_buffer">int LibRaw::open_buffer(void *buffer, size_t bufsize)</a></li>
+          <li><a  href="#unpack">int LibRaw::unpack(void)</a></li>
+          <li><a  href="#unpack_thumb">int LibRaw::unpack_thumb(void)</a></li>
+          </ul>
+        </li>
+      <li><a  href="#utility">Auxiliary Functions</a>
+        <ul>
+          <li>Library version info
+            <ul>
+              <li><a href="#version">const char* LibRaw::version()</a></li>
+              <li><a href="#versionNumber">int LibRaw::versionNumber()</a></li>
+              <li><a href="#LIBRAW_CHECK_VERSION">bool LIBRAW_CHECK_VERSION(major,minor,patch)</a>
+            </ul>
+          </li>
+          <li>List of supported cameras
+            <ul>
+              <li><a href="#cameraCount">int LibRaw::cameraCount()</a></li>
+              <li><a href="#cameraList">const char** LibRaw::cameraList()</a></li>
+            </ul>
+          </li>
+          <li<<a href="#unpack_function_name">const char* LibRaw::unpack_function_name()</a></li>
+          <li><a href="#add_masked_borders_to_bitmap">void LibRaw::add_masked_borders_to_bitmap</a></li>
+          <li><a href="#rotate_fuji_raw">int LibRaw:: rotate_fuji_raw()</a>
+          <li><a  href="#recycle">void LibRaw::recycle(void)</a></li>
+          <li><a  href="#~LibRaw">LibRaw::~LibRaw()</a></li>
+          <li><a href="#strprogress">const char* LibRaw::strprogress(enum LibRaw_progress code)</a></li>
+          <li><a  href="#libraw_strerror">const char* LibRaw::strerror(int errorcode)</a></li>
+          <li><a  href="#callbacks">Setting Error Notification Functions</a>
+            <ul>
+              <li><a href="#progress">User callback for progress indication/interruption</a></li>
+              <li><a  href="#memerror">Out-of-Memory Notifier</a></li>
+              <li><a  href="#dataerror">File Reading Notifier</a></li>
+              </ul>
+            </li>
+          </ul>
+        </li>
+    <li><a  href="#dcrawemu">Data Postprocessing: Emulation of dcraw Behavior</a>
+        <ul>
+          <li><a  href="#dcraw_params">Parameter Setting</a></li>
+          <li><a  href="#adjust_sizes_info_only">int LibRaw::adjust_sizes_info_only(void)</a></li>
+          <li><a  href="#dcraw_document_mode_processing">int LibRaw::dcraw_document_mode_processing(void)</a></li>
+          <li><a  href="#dcraw_process">int LibRaw::dcraw_process(void)</a></li>
+        </ul>
+      </li>
+      <li><a  href="#dcrawrite">Data Output to Files: Emulation of dcraw Behavior</a>
+        <ul>
+          <li><a  href="#dcraw_ppm_tiff_writer">int LibRaw::dcraw_ppm_tiff_writer(const char *outfile)</a></li>
+          <li><a  href="#dcraw_thumb_writer">int LibRaw::dcraw_thumb_writer(const char *thumbfile)</a></li>
+        </ul>
+      </li>
+      <li>
+        <a href="#memwrite">Copying unpacked data into memory buffer</a>
+        <ul>
+          <li>
+            <a href="#dcraw_make_mem_image">libraw_processed_image_t *dcraw_make_mem_image(int *errorcode)</a>
+          </li>
+          <li>
+            <a href="#dcraw_make_mem_thumb">libraw_processed_image_t *dcraw_make_mem_thumb(int *errorcode)</a>
+          </li>
+        </ul>
+      </li>
+      <li><a href="#datastream">Input layer abstraction</a>
+        <ul>
+          <li><a href="LibRaw_abstract_datastream">class LibRaw_abstract_datastream - abstract RAW read interface<a>
+            <ul>
+              <li><a href="#datastream_methods">LibRaw_abstract_datastream class methods</a>
+                <ul>
+                  <li><a href="#datastream_methods_utility">Object verification</a></li>
+                  <li><a href="#datastream_methods_read">Stream read and positioning</a></li>
+                  <li><a href="#datastream_methods_other">Other methods</a></li>
+                </ul>
+              </li>
+            </ul>
+          </li>
+          <li><a href="#datastream_derived">Derived input classes included in LibRaw</a>
+            <ul>
+              <li><a href="#file_datastream">class LibRaw_file_datastream - file input interface</a></li>
+            </ul>
+          </li>
+          <li><a href="#own_datastreams">Own datastream derived classes</a>
+            <ul>
+              <li><a href="#substream">substream field: secondary input stream</a></li>
+            </ul>
+          <li>
+        </ul>
+      </li>
+    </ol>
+
+    <a name="LibRaw"></a>
+    <h2>LibRaw Objects</h2> 
+    <p>
+     The main LibRaw object (class) is created either without parameters or with flags determining the object behavior.
+    </p>
+    <pre>
+#include "libraw/libraw.h"
+...
+
+   LibRaw ImageProcessor(unsigned int flags=0);
+...
+    </pre>
+    <p>Flags (several flags are combined via operator |, i.e., bitwise OR):</P>
+    <ul>
+      <li><b>LIBRAW_OPTIONS_NO_MEMERR_CALLBACK</b>: do not set the standard
+<a href="#callbacks">out-of-memory error handler</a> (standard handler outputs the error report in stderr);</li>
+      <li><b>LIBRAW_OPTIONS_NO_DATAERR_CALLBACK</b>: do not set the standard
+<a href="#callbacks">file read error handler</a> (standard handler outputs the error report in stderr).</li>
+    </ul>
+    <p>
+    Three groups of methods are used for image processing
+    </p>
+    <ul>
+      <li><a href="#dataload">Data loading from the RAW file</a></li>
+      <li><a href="#dcrawemu">Postprocessing functions emulating the dcraw behavior</a></li>
+      <li><a href="#dcrawrite">File output functions emulating the dcraw behavior</a>.</li>
+    </ul>
+    <p>
+      The results of processing are placed in the imgdata field of type <a
+        href=API-datastruct-eng.html>libraw_data_t</a>; the same data set contains fields that control the postprocessing
+and output.
+    </p>
+    <a name="return"></a>
+    <h2>Returned Values</h2>
+    <p>
+      All LibRaw API functions return an integer number in accordance with the
+<a href=API-notes-eng.html#errors>return code convention</a>. Please read the descriptions of 
+<a href=API-notes-eng.html#errors>this convention</a> and <a href="#callbacks">LibRaw behavior
+in cases of fatal errors</a>.
+    </p>
+
+    <a name="dataload"></a>
+    <h2>Methods Loading Data from a File</h2>
+    <a name=open_datastream></a>
+    <h3>int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)</h3>
+    <p>Opens a datastream with RAW data, reads metadata (EXIF) from it, and fills the following structures:
+    </p>
+    <ul>
+      <li>imgdata.idata (<a href="API-datastruct-eng.html#libraw_iparams_t">libraw_iparams_t</a>),</li>
+      <li>imgdata.sizes (<a href="API-datastruct-eng.html#libraw_image_sizes_t">libraw_image_sizes_t</a>),</li>
+      <li>imgdata.color (<a href="API-datastruct-eng.html#libraw_colordata_t">libraw_colordata_t</a>),</li>
+      <li>imgdata.other (<a href="API-datastruct-eng.html#libraw_imgother_t">libraw_imgother_t</a>), and </li>
+      <li>imgdata.thumbnail (<a href="API-datastruct-eng.html#libraw_thumbnail_t">libraw_thumbnail_t</a>).</li>
+    </ul>
+    <p>The function returns an integer number in accordance with the <a href=API-notes-eng.html#errors>return
+code convention</a>: positive if any system call has returned an error, negative
+  (from the  <a href=API-datastruct-eng.html#LibRaw_errors>LibRaw error list</a>) if there has been an error
+situation within LibRaw.
+    </p>
+    <p>Before file opening, <a href="#recycle">recycle()</a> is always called; hence, if several images
+are processed in the batch mode, there is no need to call recycle() at the end of each processing cycle.
+    </p>
+    <p><b>Input data</b>: pointer to object, derived from <a href="#datastream">LibRaw_abstract_datastream</a> class.
+      This object should be initialized and ready to read. This object should be destroyed in calling application
+      after use.
+    </p>
+    <a name=open_file></a>
+    <h3>int LibRaw::open_file(const char *filename)</h3>
+    <p>
+      Creates an <a href="#file_datastream">LibRaw_file_datastream</a> object, calls 
+      <a href="#open_datastream">open_datastream()</a>. If succeed, sets internal flag which signals
+      to destroy internal datastream object on <a href="#recycle">recycle()</a>. On failure,
+      just created file_datastream destroyed immediately.
+    </p>
+    <p>The function returns an integer number in accordance with the 
+      <a href=API-notes-eng.html#errors>return code convention</a>: positive if any system call has returned an error, negative
+      (from the  <a href=API-datastruct-eng.html#LibRaw_errors>LibRaw error list</a>) if there has been an error
+      situation within LibRaw.
+    </p>
+
+    <a name=open_buffer></a>
+    <h3>int LibRaw::open_buffer(void *buffer, size_t bufsize)</h3>
+    <p>
+      Created an <a href="#buffer_datastream">LibRaw_buffer_datastream</a> object, calls 
+      <a href="#open_datastream">open_datastream()</a>. If succeed, sets internal flag which signals
+      to destroy internal datastream object on <a href="#recycle">recycle()</a>. On failure,
+      just created file_datastream destroyed immediately.
+    </p>
+    <p>The function returns an integer number in accordance with the 
+      <a href=API-notes-eng.html#errors>return code convention</a>: positive if any system call has returned an error, negative
+      (from the  <a href=API-datastruct-eng.html#LibRaw_errors>LibRaw error list</a>) if there has been an error
+      situation within LibRaw.
+    </p>
+
+    <a name="unpack"></a>
+    <h3> int LibRaw::unpack(void)</h3>
+    <p>
+      Unpacks the RAW files of the image, calculates the black level (not for all formats), subtracts black
+(not for all formats). The results are placed in imgdata.image.
+    </p>
+    <p>
+ Data reading is sometimes (not frequently) affected by settings made in imgdata.params (<a
+        href="API-datastruct-eng.html#libraw_output_params_t">libraw_output_params_t</a>); see <a
+        href=API-notes-eng.html>API notes</a> for details.
+    </p>
+    <p>The function returns an integer number in accordance with the <a href=API-notes-eng.html#errors>return code
+convention</a>: positive if any system call has returned an error, negative (from the
+      <a href=API-datastruct-eng.html#LibRaw_errors>LibRaw error list</a>) if there has been an error
+situation within LibRaw.
+    </p>
+    
+    <a name="unpack_thumb"></a>
+    <h3>int LibRaw::unpack_thumb(void)</h3>
+    <p>
+ Reads (or unpacks) the image preview (thumbnail), placing the result into the imgdata.thumbnail.thumb buffer.<br/>
+ JPEG previews are placed into this buffer without any changes (with the header etc.). Other preview
+formats are placed into the buffer in the form of the unpacked bitmap image (three components, 8 bits per component).<br/>
+ The thumbnail format is written to the imgdata.thumbnail.tformat field; for the possible values, see
+<a href="API-datastruct-eng.html#LibRaw_thumbnail_formats">description of constants and data structures</a>.
+
+    </p>
+    <p>The function returns an integer number in accordance with the <a href=API-notes-eng.html#errors>return code
+convention</a>: positive if any system call has returned an error, negative (from the
+<a href=API-datastruct-eng.html#LibRaw_errors>LibRaw error list</a>) if there has been an error situation within
+LibRaw.
+    </p>
+    <a name="utility"></a>
+    <h2>Auxiliary Functions</h2>
+    <h3>Library version check</h3>
+    <a name="version"></a>
+    <h4>const char* LibRaw::version()</h4>
+    <p>
+      Returns string representation of LibRaw version in MAJOR.MINOR.PATCH-Status format (i.e. 0.6.0-Alpha2
+      or 0.6.1-Release).
+    </p>
+    <a name="versionNumber"></a>
+    <h4>int LibRaw::versionNumber()</h4>
+    <p>
+      Returns integer representation of LibRaw version. During LibRaw development, the version number is always
+      increase .
+    </p>
+    <a name="LIBRAW_CHECK_VERSION"></a>
+    <h4>bool LIBRAW_CHECK_VERSION(major,minor,patch)</h4>
+    <p>
+      Macro for version check in caller applications. Returns 'true' if current library version is greater or equal to
+      set in macro parameters. This macro executes at runtime (not at compile time) and may be used for checking
+      version of dynamically loaded LibRaw (from DLL/shared library).
+    </p>
+    <h3>List of supported RAW formats (cameras)</h3>
+    <a name="cameraCount"></a>
+    <h4>int LibRaw::cameraCount()</h4>
+    <p>
+      Returns count of cameras supported.
+    </p>
+    <a name="cameraList"></a>
+    <h4>const char** LibRaw::cameraList()</h4>
+    <p>
+      Returns list of supported cameras. Latest item of list is set to NULL (for easy printing).
+    </p>
+    <a name="unpack_function_name"></a>
+    <h3>const char* LibRaw::unpack_function_name()</h3>
+    <p>
+      Returns function name of file unpacking function. Intended only for LibRaw test suite designers to use in test
+      coverage evaluation.
+    </p>
+
+    <a name="add_masked_borders_to_bitmap"></a>
+    <h3>void LibRaw::add_masked_borders_to_bitmap</h3>
+    <p>
+      This call is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>.
+    </p>
+    <p>
+      This call rebuilds <b>imgdata.image</b> bitmap and makes full bitmap, contains both image data (active 
+      pixels) and 'black border' (masked pixels). If no masked pixels data present, then this call does nothing.
+      Function call changes data fields <b>sizes.width,sizes.height,sizes.iwidth,sizes.iheight</b> to full image
+      size (i.e. raw_width/raw_height).<br/>
+      This call does nothing:
+      </p>
+    <ul>
+      <li>for images containing more than one color component per pixel (Sigma Foveon, full-color DNG,
+        already demosaiced files: Canon sRAW, Sinar 4-shot etc).</li>
+      <li>for images, unpacked with half resolution (one of parameters set in options: half_mode, wavelet denoising
+        threshold, aberration fixing data).
+      </li>
+    </ul>
+    <p>The function returns an integer number in accordance with the <a href=API-notes-eng.html#errors>return code
+        convention</a>: positive if any system call has returned an error, negative (from the
+      <a href=API-datastruct-eng.html#LibRaw_errors>LibRaw error list</a>) if there has been an error situation within
+      LibRaw. 
+    </p>
+    <a name="rotate_fuji_raw"></a>
+    <h3> int LibRaw:: rotate_fuji_raw()</h3>
+    <p>
+      This function rotates non-interpolated RAW bitmap from FujiCCD sensors into 45-degree-rotated position,
+      compatible with old LibRaw versions (prior to LibRaw 0.7). This call is intended for applications,
+      which works with non-interpolated/non-demosaiced RAW data itself. If 
+      dcraw_process/dcraw_document_mode_processing calls are used, these call make the rotation internally.
+    </p>
+    <p>The function returns an integer number in accordance with the <a href=API-notes-eng.html#errors>return code
+        convention</a>: positive if any system call has returned an error, negative (from the
+      <a href=API-datastruct-eng.html#LibRaw_errors>LibRaw error list</a>) if there has been an error situation within
+      LibRaw. 
+    </p>
+        <p>
+          This call is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. Fuji sensor data  extracted
+          in already rotated bitmap.
+        </p>
+
+    <a name="recycle"></a>
+    <h3>void LibRaw::recycle(void)</h3>
+    <p>Frees the allocated data of LibRaw instance, enabling one to process the next file using
+the same processor. Repeated calls of recycle() are quite possible and do not conflict with anything. 
+    </p>
+
+    <a name="~LibRaw"></a>
+    <h3>LibRaw::~LibRaw()</h3>
+    <p>Destructor, which consists in calling recycle().</p>
+
+    <a name="strprogress"></a>
+    <h3>const char* LibRaw::strprogress(enum LibRaw_progress code)</h3>
+    <p>Converts progress stage code to description string (in English).</p>
+
+    <a name="libraw_strerror"></a>
+    <h3>const char* LibRaw::strerror(int errorcode)</h3>
+    <p>Analog of strerror(3) function: outputs the text descriptions of LibRaw error codes (in English).</p>
+
+    <a name="callbacks"></a>
+    <h3>Setting Error Notification Functions</h3>
+    <p>
+      In process of RAW conversion LibRaw can call user-setted callback. This callback can be used for:
+    </p>
+    <ul>
+      <li>Dynamic status update (progress bar and so on).</li>
+      <li>Cancel of processing (for example, user pressed Cancel button).</li>
+    </ul>
+    <p>Also, work of the library may cause two types of exceptional situations that require notification of the calling application:
+    </p>
+    <ul>
+      <li>Memory shortage</li>
+      <li>Data read error.</li>
+    </ul>
+    <p>
+ An application may set its own callbacks that will be called in the cases mentioned above to notify the user (or the calling program).
+    </p>
+    <a name="progress"></a>
+    <h4>Progress indication/processing termination</h4>
+    <pre>
+        typedef int (*progress_callback)(void *callback_data,enum LibRaw_progress stage, int iteration, int expected);
+        void LibRaw::set_progress_handler(progress_callback func,void *callback_data);
+    </pre>
+    <p>
+      LibRaw user can set own callback which will be called 10-50 times during RAW postprocessing
+       by dcraw_process()/dcraw_document_mode_processing();
+    </p>
+    <p>
+      This callback may terminate current image processing by returning of non-zero value. In such case all processing
+      will be cancelled immediately and all resources will be returned to system by recycle() call.
+      Current call of dcraw_process()/dcraw_document_mode_processing() will return error code
+      LIBRAW_CANCELLED_BY_CALLBACK.
+      </p>
+    <p>
+      Callback parameters:
+      <dl>
+      <dt>void *callback_data</dt>
+      <dd>void*-pointer, passed as 2nd argument to set_progress_handler(). This pointer should be used to pass
+        additional data to callback (i.e. thread local data and so on).
+        </dd>
+      <dt>enum LibRaw_progress stage</dt>
+      <dd>Current processing stage. This number can be converted to string by call to 
+        <a href="#strprogress">LibRaw::strprogress</a>. Not all processing stages are covered by callback calls.
+      </dd>
+      <dt>int iteration</dt>
+      <dd>Iteration number within current stage (from 0 to expected-1).
+      </dd>
+      <dt>int expected</dt>
+      <dd>Expected number of iterations on current stage.</dd>
+      </dl>
+    Callback should return value of: <b>0</b> for continue processing and <b>non-zero</b> for immediate cancel of processing.
+    </p>
+    <p>
+      If LibRaw compiled with OpenMP support, iteration parameter may not always increase within one stage. Out of
+      order callback calls are possible.
+    </p>
+    <p>
+      Callback code sample:
+<pre>
+int my_progress_callback(void *data,enum LibRaw_progress p,int iteration, int expected)
+{
+    char *passed_string = (char *data);
+    printf("Callback: %s  pass %d of %d, data passed: %s\n",libraw_strprogress(p),iteration,expected,passed_string);
+    if(timeout || key_pressed )
+        return 1; // cancel processing immediately
+    else
+        return 0; // can continue
+}
+
+</pre>
+
+    <a name="memerror"></a>
+    <h4>Out-of-Memory Notifier</h4>
+    <pre>
+        typedef void (* memory_callback)(void *callback_data,const char *file, const char *where);
+        void LibRaw::set_memerror_handler(memory_callback func,void *callback_data);
+    </pre>
+    <p>The user may set his or her own function called in the case of memory shortage. It is a void function
+receiving two string parameters:
+    </p>
+    <ul>
+      <li><b>void *callback_data</b> - void*-pointer, passed as 2nd argument to set_progress_handler(). This pointer
+        should be used to pass         additional data to callback (i.e. thread local data and so on).</li>
+      <li><b>file</b> is the name of the RAW file whose processing evoked the out-of-memory error.
+        This name <b>can be NULL</b> if underlying data input layer does not know the name. So, if calling
+        application sets own callback, this callback should work with NULL file name.
+      </li>
+      <li><b>where</b> is the name of the function where memory shortage occurred.</li>
+    </ul>
+    <p>The callback function is intended for information purposes: it notifies the user
+or the program code that processing is impossible.</p> 
+    <p>If the user does not set his or her own handler, the standard one (output of error message in stderr) will be used.</p>
+    <p>One can set the null handler by passing NULL to set_memerror_handler; then no notifier
+function will be called. The same effect can be achieved by creating a LibRaw object with the LIBRAW_OPTIONS_NO_MEMERR_CALLBACK
+flag in the contructor.
+    </p>
+    <p>In the case of memory shortage, processing of the current file is terminated and a notifier is called; all
+allocated resources are freed, and <a href="#recycle">recycle()</a> is performed. The current call will return
+LIBRAW_UNSUFFICIENT_MEMORY. 
+      <br/>
+At an attempt to continue data processing, all subsequent calls will return LIBRAW_OUT_OF_ORDER_CALL. 
+Processing of a new file may be started in the usual way, by calling LibRaw::open_file().
+    </p>
+    <a name="dataerror"></a>
+    <h4>File Read Error Notifier</h4>
+    <pre>
+        typedef void (*data_callback)(void *callback_data,const char *file, const int offset);
+        void LibRaw::set_dataerror_handler(data_callback func, void *callback_data); 
+    </pre>
+    <p>
+      The user can define his or her own function to be called in the case of error in the input data. It is a void function receiving
+two parameters:
+    </p>
+    <ul>
+      <li><b>void *callback_data</b> - void*-pointer, passed as 2nd argument to set_progress_handler(). This pointer
+        should be used to pass         additional data to callback (i.e. thread local data and so on).</li>
+      <li><b>file</b> is the name of the RAW file whose processing evoked the file read error.
+        This name <b>can be NULL</b> if underlying data input layer does not know the name. So, if calling
+        application sets own callback, this callback should work with NULL file name.
+      </li>
+      <li><b>offset</b> is -1 at end-of-file (if LibRaw expects more data) or a positive number equal to
+the file position (bytes from file beginning) where the unpacking error occurred.</li>
+    </ul>
+    <p>The callback function is intended for information purposes: it notifies the user
+or the program code that processing is impossible.</p> 
+    <p>If the user does not set his or her own handler, the standard one (output of error message in stderr) will be used.</p>
+    <p>One can set the null handler by passing NULL to set_memerror_handler; then no notifier
+function will be called. The same effect can be achieved by creating a LibRaw object with the LIBRAW_OPTIONS_NO_DATAERR_CALLBACK
+flag in the contructor. </p>
+    <p>In the case of error in the input data, processing of the current file is terminated and a notifier is called; all
+allocated resources are freed, and <a href="#recycle">recycle()</a> is performed. The current call will return
+LIBRAW_IO_ERROR. 
+      <br/>
+At an attempt to continue data processing, all subsequent calls will return LIBRAW_OUT_OF_ORDER_CALL. 
+Processing of a new file may be started in the usual way, by calling LibRaw::open_file().
+    </p>
+
+    <a name="dcrawemu"></a>
+    <h2>Data Postprocessing: Emulation of dcraw Behavior</h2>
+    <p>
+Instead of writing one's own Bayer pattern postprocessing, one can use the dcraw functions, which are called
+after the calls of open_file() + unpack() /+ unpack_thumb()/
+    </p>
+    <a name="dcraw_params"></a>
+    <h3>Parameter Setting</h3>
+    <p>
+Virtually all parameters that can be set through the dcraw command line are specified by assigning values to
+fields of the <b>LibRaw::imgdata.params</b> structure. The type of this structure is <b>libraw_output_params_t</b>;
+all fields are listed and described in sufficient detail in the <a href="API-datastruct-eng.html#libraw_output_params_t">description
+of data structures</a>.
+    </p>
+
+    <a name="adjust_sizes_info_only"></a>
+    <h3>int LibRaw::adjust_sizes_info_only(void)</h3>
+    <p>
+      The function calculates the correct size of the output image (imgdata.sizes.iwidth and imgdata.sizes.iheight) for the
+            following cases: 
+      </p>
+    <ul>
+      <li>Files from Fuji cameras (with a 45-degree rotation)</li>
+      <li>Files from cameras with non-square pixels</li>
+      <li>Images shot by a rotated camera.</li>
+    </ul>
+    <p>
+      In the aforementioned cases, the function changes the fields of the image output size; note that
+this change cannot be repeated again.
+    </p>
+    <p>
+      The function should be used for information purposes; it is incompatible with <a
+        href="#dcraw_document_mode_processing">dcraw_document_mode_processing()</a> and <a
+        href="#dcraw_process">dcraw_process()</a> calls. 
+    </p>
+
+    <a name="dcraw_document_mode_processing"></a>
+    <h3>int LibRaw::dcraw_document_mode_processing(void)</h3>
+    <p>
+     The function emulates <b>dcraw -D</b>: no interpolation, white balance, and color conversion.<br/> 
+It is called after calling LibRaw::unpack();
+    </p>
+    <p>The function returns an integer number in accordance with the <a href=API-notes-eng.html#errors>error
+code convention</a>: positive if any system call has returned an error, negative (from the
+<a href=API-datastruct-eng.html#LibRaw_errors>LibRaw error list</a>) if there has been an error situation within
+LibRaw.
+    </p>
+    
+    <a name="dcraw_process"></a>
+    <h3>int LibRaw::dcraw_process(void)</h3>
+    <p>
+      The function emulates the postprocessing capabilities available in <b>dcraw</b>.<br/>
+      Called after calling LibRaw::unpack();
+    </p>
+    <p>The entire functionality of dcraw (set via the field values in <a
+        href="API-datastruct-eng.html#libraw_output_params_t">imgdata.params</a>) is supported, except for
+      </p>
+    <ul>
+      <li>Dark frame subtraction</li>
+      <li>Work with bad pixels.</li>
+    </ul>
+    <p>The function is intended solely for demonstration and testing purposes; it is assumed that its source code
+will be used in most real applications as the reference material concerning the order of RAW data processing. 
+    </p>
+    <p>The function returns an integer number in accordance with the <a href=API-notes-eng.html#errors>error
+code convention</a>: positive if any system call has returned an error, negative (from the
+<a href=API-datastruct-eng.html#LibRaw_errors>LibRaw error list</a>) if there has been an error situation within
+LibRaw.
+    </p>
+    <a name="dcrawrite"></a>
+    <h2>Data Output to Files: Emulation of dcraw Behavior</h2>
+    <p>In spite of the abundance of libraries for file output in any formats, LibRaw includes calls that emulate
+the file output provided by dcraw. This is done primarily for easier verification of library work: the resultant
+files must be binary identical.
+    </p>
+
+    <a name="dcraw_ppm_tiff_writer"></a>
+    <h3>int LibRaw::dcraw_ppm_tiff_writer(const char *outfile)</h3>
+    <p>
+     The function outputs the postprocessing results to a file in the PPM/PGM or TIFF format (the format is set via 
+      imgdata.params.output_tiff). The results are binary identical to those provided by dcraw.
+    </p>
+    <p>The function returns an integer number in accordance with the <a href=API-notes-eng.html#errors>error
+code convention</a>: positive if any system call has returned an error, negative (from the
+<a href=API-datastruct-eng.html#LibRaw_errors>LibRaw error list</a>) if there has been an error situation within
+LibRaw.
+    </p>
+    <a name="dcraw_thumb_writer"></a>
+    <h3>int LibRaw::dcraw_thumb_writer(const char *thumbfile)</h3>
+    <p>Writes the thumbnail to a file in the PPM format for bitmap thumbnails and in the JPEG format for JPEG thumbnails, i.e.,
+in the format completely identical to the results provided by dcraw.
+    </p>
+    <p>The function returns an integer number in accordance with the <a href=API-notes-eng.html#errors>error
+code convention</a>: positive if any system call has returned an error, negative (from the
+<a href=API-datastruct-eng.html#LibRaw_errors>LibRaw error list</a>) if there has been an error situation within
+LibRaw.
+    </p>
+    <a name="memwrite"></a>
+    <h2>Copying unpacked data into memory buffer</h2>
+    <p>
+      There is two function calls for store unpacked data into memory buffer (after using dcraw_process() and so on):
+      <ul>
+      <li><b>dcraw_make_mem_image</b> - store processed image data into allocated buffer;
+        </li>
+      <li><b>dcraw_make_mem_thumb</b> -  store extracted thumbnail into buffer as JPEG-file image (for most cameras)
+        or as RGB-bitmap.
+      </li>
+      </ul>
+    For usage primer see samples/mem_image.c sample.
+    </p>
+    <a name="dcraw_make_mem_image"></a>
+    <h3>libraw_processed_image_t *dcraw_make_mem_image(int *errorcode=NULL) - store unpacked and processed image into
+      memory buffer as RGB-bitmap</h3>
+    <p>
+      This function allocates memory buffer and stores unpacked-preprocessed image into this buffer. Function returns
+      allocated structure <a href="API-datastruct-eng.html#libraw_processed_image_t">libraw_processed_image_t</a> with
+      filled fields. Always returns data as RGB bitmap  (i.e. <b>type</b> field is equal to LIBRAW_IMAGE_BITMAP).
+    </p>
+    <p>
+      
+      dcraw_process() or dcraw_document_mode_processing() should be called before dcraw_make_mem_image();
+    </p>
+    <p>
+      Returns NULL in case of an error. If caller has passed not-NULL value as errorcode parameter, than *errorcode
+      will be set to error code according to <a href="API-notes-eng.html#errors">error code convention</a>.
+    </p>
+    <p><b>NOTE!</b> Memory, allocated for return value will not be fried at destructor or <b>LibRaw::recycle</b>
+      calls. Caller of dcraw_make_mem_image should free this memory by call to free().
+    </p>
+
+    <a name="dcraw_make_mem_thumb"></a>
+    <h3>libraw_processed_image_t *dcraw_make_mem_thumb(int *errorcode=NULL) - store unpacked thumbnail into memory buffer</h3>
+    <p>
+      This function allocates memory buffer and stores thumbnail data in it. Function returns allocated
+      structure <a href="API-datastruct-eng.html#libraw_processed_image_t">libraw_processed_image_t</a> with
+      filled fields. For most RAW images allocated structure will contains JPEG image (i.e. <b>type</b>
+      field is equal to  LIBRAW_IMAGE_JPEG). For some cameras with RGB-bitmap thumbnail (Kodak SLRs, Foveon) 
+      returned structure contains RGB bitmap (<b>type</b> field is equal to  LIBRAW_IMAGE_JPEG, see structure
+      description for details).
+    </p>
+    <p>
+      unpack_thumb() should be called before dcraw_make_mem_thumb();
+    </p>
+    <p>
+      Returns NULL in case of an error. If caller has passed not-NULL value as errorcode parameter, than *errorcode
+      will be set to error code according to ñ <a href=API-notes-eng.html#errors>error code convention</a>.
+    </p>
+    <p><b>NOTE!</b> Memory, allocated for return value will not be fried at destructor or <b>LibRaw::recycle</b>
+      calls. Caller of dcraw_make_mem_image should free this memory by call to free().
+    </p>
+
+    <a name="datastream"></a>
+    <h2>Input layer abstraction</h2>
+    <a name="LibRaw_abstract_datastream"></a>
+    <h3>class LibRaw_abstract_datastream - abstract RAW read interface</h3>
+    <p>
+      LibRaw reads RAW-data by calling (virtual) methods of C++ object derived from 
+      <b>LibRaw_abstract_datastream</b>. This C++ class does not implement any read, but defines interface to be
+      called. Call to base class methods always results in error.
+    </p>
+    <a name="datastream_methods"></a>
+    <h4>LibRaw_abstract_datastream class methods</h4>
+    <a name="datastream_methods_utility"></a>
+    <h5>Object verification</h5>
+    <dl>
+      <dt><b>    virtual int         valid()</b></dt>
+      <dd>Checks input datastream validity. Returns 1 on valid stream and 0 if datastream was created on non-valid
+        input parameters (wrong filename for file stream and so on).
+      </dd>
+    <a name="datastream_methods_read"></a>
+    <h5>Stream read and positioning</h5>
+    <p>This group of methods implements file object (FILE*) semantics.</p>
+    <dl>
+      <dt><b>virtual int         read(void * ptr,size_t size, size_t nmemb)</b></dt>
+      <dd>
+        Similar to fread(ptr,size,nmemb,file).
+      </dd>
+      <dt><b>virtual int         seek(off_t o, int whence)</b></dt>
+      <dd>
+        Similar to fseek(file,o,whence).
+      </dd>
+      <dt><b>virtual int         tell(</b></dt>
+      <dd>
+        Similar to ftell(file).
+      </dd>
+      <dt><b>virtual int         get_char()</b></dt>
+      <dd>
+        Similar to getc(file)/fgetc(file).
+      </dd>
+      <dt><b>virtual char*       gets(char *s, int n)</b></dt>
+      <dd>
+        Similar to fgets(s,n,file).
+      </dd>
+      <dt><b>virtual int         eof()</b></dt>
+      <dd>
+        Similar to feof(file).
+      </dd>
+      <dt><b>virtual int         scanf_one(const char *fmt, void *val)</b></dt>
+      <dd>
+        Simplified variant of fscanf(file,fmt,val): format string is always contains one argument to read. So,
+        variable args call is not needed and only one pointer to data passed.
+      </dd>
+    </dl>
+    <a name="datastream_methods_other"></a>
+    <h5>Other methods</h5>
+    <p>This group of methods includes several supplementary calls. These calls are used to temporary switch to another
+      data stream (file and/or memory buffer).
+    </p>
+    <dl>
+      <dt><b>virtual const char* fname()</b></dt>
+      <dd>
+        Returns name of opened file if datastream object knows it (for example,
+        <b>LibRaw_file_datastream</b> used). Filename used in:
+        <ul>
+          <li>error notofocation callbacks;</li>
+          <li>generation of filename of JPEG-file with metadata when needed (i.e. cameras with 'Diag RAW hack').
+        </ul>
+      </dd>
+      <dt><b>virtual int         subfile_open(const char *fn)</b></dt>
+      <dd>
+        This call temporary switches input to file <b>fn</b>. Returns 0 on success and error code on error.<br/>
+        The function used to read metadata from external JPEG file (on cameras with "Diag RAW hack").
+        <br/>
+        This call is not implemented for <a href="#buffer_datastream">LibRaw_buffer_datastream</a>, so
+        external JPEG processing is not possible when buffer datastream used.
+        <br/>
+        This functon should be implemented in real input class, base class call always return error.
+        <br/>
+        Working implementation sample can be found in 
+        <a href="#file_datastream">LibRaw_file_datastream</a> implementation in <b>libraw/libraw_datastream.h</b> file.
+      </dd>
+      <dt><b>    virtual void subfile_close()</b></dt>
+      <dd>
+        This call switches input stream from temporary open file back to main data stream.
+      </dd>
+      <dt><b>    virtual int		tempbuffer_open(void  *buf, size_t size)</b></dt>
+      <dd>
+        This call temporary switches input to <a href="#buffer_datastream">LibRaw_buffer_datastream</a> object,
+        created from <b>buf</b>.<br/>
+        This method is needed for Sony encrypted metadata parser.
+        <p>
+          This call implemented in base class (<b>LibRaw_abstract_datastream</b>), there is no need to
+          reimplement in in derived classes.<br/>
+          Possible activity of temporary datastream requires very accurate programming when implementing
+          datastreams derived from base <b>LibRaw_abstract_datastream</b>. See  <a href="#substream">below</a>
+          for more details.
+      </dd>
+      <dt><b>    virtual void	tempbuffer_close()</b></dt>
+      <dd>
+        This call switch input back from temporary datastream to main stream. This call implemented
+        in base <b>LibRaw_abstract_datastream</b> class.
+      </dd>
+    </dl>
+    
+    <a name="datastream_derived"></a>
+    <h3>Derived input classes included in LibRaw</h3>
+    <p>
+       There is two "standard" input classes in LibRaw distribution:
+    </p>
+    <ul>
+      <li><a href="#file_datastream">LibRaw_file_datastream</a> implements input from file (in filesystem).</li>
+      <li><a href="#buffer_datastream">LibRaw_buffer_datastream</a> implements input from memory buffer.</li>
+    </ul>
+    <p>
+      LibRaw C++ interface users can implement their own input classes and use them via 
+      <a href="#open_datastream">LibRaw::open_datastream</a> call. Requirements and implementation specifics are
+      described below.
+    </p>
+    <a name="file_datastream"></a>
+    <h4>class LibRaw_file_datastream - file input interface</h4>
+    <p>
+      This class implements input from file.
+    </p>
+    <p><b>Class methods:</b></p>
+    <dl>
+      <dt><b> LibRaw_file_datastream(const char *fname) </b></dt>
+      <dd>
+        This constructor creates <b>LibRaw_file_datastream</b> object from file <b>fname</b>.<br/>
+        Unfortunately, C++ constructor cannot return an error. So if bad filename passed (e.g. nonexistent file)
+        object is created as non-valid (valid() call returns zero).
+      </dd>
+    </dl>
+    <p>
+      All other class methods are <a href="#datastream_methods">described above</a>.<br/>
+      This class implements all possble methods, including fname() and subfile_open().
+    </p>
+    <a name="buffer_datastream"></a>
+    <h4>class LibRaw_buffer_datastream - memory buffer input interface</h4>
+    <p>
+      This class implements input from memory buffer.
+    </p>
+    <p><b>Class methods:</b></p>
+    <dl>
+      <dt><b>    LibRaw_buffer_datastream(void *buffer, size_t bsize)</b></dt>
+      <dd>
+        This constructor creates datastream object from  <b>buffer</b> with size  <b>bsize</b>.<br/>
+        It is not possibly to verify the pointer passed, so buffer address is checked against 0 and -1 only.
+      </dd>
+    </dl>
+    <p>
+      All other class methods are <a href="#datastream_methods">described above</a>.<br/>
+      This class does not implement fname() and subfile_open() calls, so external JPEG metadata parsing
+      is not possible.
+    </p>
+    <a name="own_datastreams"></a>
+    <h3>Own datastream derived classes</h3>
+    <p>
+      To create own read interface LibRaw user should implement C++ class derived from 
+      <b>LibRaw_abstract_datastream</b> with all read methods.<br/>
+      LibRaw standard implementations may be used as reference. See <b>libraw/libraw_datastream.h</b> file for details
+      (all standard LibRaw input classes are implemented using inline functions only).
+    </p>
+    <a name="substream"></a>
+    <h4>substream field: secondary input stream</h4>
+    <p>
+      <b>substream</b> field, defined in base LibRaw_abstract_datastream class requires some additional notes.
+      This field is used when input switched to temporary buffer (used for Sony metadata processing). Unfortunately,
+      there is now ideal C++ way to hide this functionality into base class internals. So, any read call in
+      derived class should include 1-line statement like this:<br/>
+      <b>int method(...args...){ if(substream) return substream-&gt;method(...args...)</b>. For example:
+<pre>
+    virtual int eof() 
+    { 
+        if(substream) return substream-&gt;eof();
+....
+    virtual int scanf_one(const char *fmt, void* val) 
+    { 
+        if(substream) return substream-&gt;scanf_one(fmt,val);
+</pre>
+
+
+
+    <a href=index-eng.html>[back to Index]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 10:08:29 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:59 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/API-CXX-rus.html b/libfspotraw/LibRaw/doc/API-CXX-rus.html
new file mode 100644
index 0000000..ab812bf
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/API-CXX-rus.html
@@ -0,0 +1,810 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw C++ API</title>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+  </head>
+
+  <body>
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <h1>LibRaw C++ API</h1>
+    <p>Ñîäåðæàíèå</p>
+    <ol>
+      <li><a href="#LibRaw">Îáúåêò LibRaw</a> </li>
+      <li><a href="#return">Âîçâðàùàåìûå çíà÷åíèÿ</a></li>
+      <li><a  href="#dataload">Ìåòîäû, çàãðóæàþùèå äàííûå èç ôàéëà</a>
+        <ul>
+          <li><a href="#open_datastream">int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)</a>
+          <li><a  href="#open_file">int LibRaw::open_file(const char *rawfile)</a></li>
+          <li><a href="#open_buffer">int LibRaw::open_buffer(void *buffer, size_t bufsize)<a></li>
+          <li><a  href="#unpack">int LibRaw::unpack(void)</a></li>
+          <li><a  href="#unpack_thumb">int LibRaw::unpack_thumb(void)</a></li>
+          </ul>
+        </li>
+      <li><a  href="#utility">Âñïîìîãàòåëüíûå ôóíêöèè</a>
+        <ul>
+          <li>Èíôîðìàöèÿ î âåðñèè áèáëèîòåêè
+            <ul>
+              <li><a href="#version">const char* LibRaw::version()</a></li>
+              <li><a href="#versionNumber">int LibRaw::versionNumber()</a></li>
+              <li><a href="#LIBRAW_CHECK_VERSION">bool LIBRAW_CHECK_VERSION(major,minor,patch)</a>
+            </ul>
+          </li>
+          <li>Ñïèñîê ïîääåðæèâàåìûõ ôîðìàòîâ (êàìåð)
+            <ul>
+              <li><a href="#cameraCount">int LibRaw::cameraCount()</a></li>
+              <li><a href="#cameraList">const char** LibRaw::cameraList()</a></li>
+            </ul>
+          </li>
+          <li<<a href="#unpack_function_name">const char* LibRaw::unpack_function_name()</a></li>
+          <li><a href="#add_masked_borders_to_bitmap">void LibRaw::add_masked_borders_to_bitmap</a></li>
+          <li><a href="#rotate_fuji_raw">int LibRaw:: rotate_fuji_raw()</a>
+          <li><a  href="#recycle">void LibRaw::recycle(void)</a></li>
+          <li><a  href="#~LibRaw">LibRaw::~LibRaw()</a></li>
+          <li><a href="#strprogress">const char* LibRaw::strprogress(enum LibRaw_progress code)</a></li>
+          <li><a  href="#libraw_strerror">const char* LibRaw::strerror(int errorcode)</a></li>
+          <li><a  href="#callbacks">Óñòàíîâêà ôóíêöèé íîòèôèêàöèè îá îøèáêàõ</a>
+            <ul>
+              <li><a href="#progress">Èíäèêàöèÿ ñòàäèé îáðàáîòêè/äîñðî÷íîå åå ïðåêðàùåíèå</a></li>
+              <li><a  href="#memerror">Óâåäîìèòåëü î íåõâàòêå ïàìÿòè</a></li>
+              <li><a  href="#dataerror">Óâåäîìèòåëü îá îøèáêå ÷òåíèÿ ôàéëà</a></li>
+              </ul>
+            </li>
+          </ul>
+        </li>
+    <li><a  href="#dcrawemu">Ïîñòîáðàáîòêà äàííûõ, ýìóëÿöèÿ ïîâåäåíèÿ dcraw</a>
+        <ul>
+          <li><a  href="#dcraw_params">Çàäàíèå ïàðàìåòðîâ</a></li>
+          <li><a  href="#adjust_sizes_info_only">int LibRaw::adjust_sizes_info_only(void)</a></li>
+          <li><a  href="#dcraw_document_mode_processing">int LibRaw::dcraw_document_mode_processing(void)</a></li>
+          <li><a  href="#dcraw_process">int LibRaw::dcraw_process(void)</a></li>
+        </ul>
+      </li>
+      <li><a  href="#dcrawrite">Çàïèñü äàííûõ â ôàéëû, ýìóëÿöèÿ ïîâåäåíèÿ dcraw</a>
+        <ul>
+          <li><a  href="#dcraw_ppm_tiff_writer">int LibRaw::dcraw_ppm_tiff_writer(const char *outfile)</a></li>
+          <li><a  href="#dcraw_thumb_writer">int LibRaw::dcraw_thumb_writer(const char *thumbfile)</a></li>
+        </ul>
+      </li>
+      <li><a href="#memwrite">Çàïèñü ðàñïàêîâàíûõ äàííûõ â áóôåð â ïàìÿòè</a>
+        <ul>
+          <li><a href="#dcraw_make_mem_image">libraw_processed_image_t *dcraw_make_mem_image(int * errcode)</a>
+          </li>
+          <li><a href="#dcraw_make_mem_thumb">libraw_processed_image_t *dcraw_make_mem_thumb(int *errorcode)</a>
+          </li>
+        </ul>
+      </li>
+      <li><a href="#datastream">Àáñòðàêöèÿ ââîäà</a> <!-- h2-->
+        <ul>
+          <li><a href="#LibRaw_abstract_datastream">class LibRaw_abstract_datastream - àáñòðàêòíûé èíòåðôåéñ ÷òåíèÿ
+              RAW-ôàéëîâ</a> <!-- h3 -->
+            <ul>
+              <li><a href="#datastream_methods">Ìåòîäû êëàññà LibRaw_abstract_datastream</a> <!-- h4 -->
+                <ul>
+                  <li><a href="#datastream_methods_utility">Âåðèôèêàöèÿ îáúåêòà</a></li>
+                  <li><a href="#datastream_methods_read">×òåíèå äàííûõ è ïîçèöèîíèðîâàíèå</a></li>
+                  <li><a href="#datastream_methods_other">Ïðî÷èå ìåòîäû</a></li>
+                </ul>
+                </li>
+            </ul>
+          </li>
+          <li><a href="#datastream_derived">Ïðîèçâîäíûå êëàññû, âõîäÿùèå â LibRaw</a> <!-- h3 -->
+            <ul>
+              <li><a href="#file_datastream">class LibRaw_file_datastream - èíòåðôåéñ ÷òåíèÿ RAW-äàííûõ èç ôàéëà</a></li>
+              <li><a href="#buffer_datastream">class LibRaw_buffer_datastream - èíòåðôåéñ ÷òåíèÿ RAW-äàííûõ èç áóôåðà â ïàìÿòè</a></li>
+            </ul>
+          </li>
+          <li><a href="#own_datastreams">Ñîçäàíèå ñîáñòâåííûõ èíòåðôåéñîâ ÷òåíèÿ</a>
+            <ul>
+              <li><a href="#substream">Ïîëå substream: âòîðîé ïîòîê ÷òåíèÿ äàííûõ</a></li>
+            </ul>
+          </li>
+      </li>
+    </ol>
+
+    <a name="LibRaw"></a>
+    <h2>Îáúåêò LibRaw</h2> 
+    <p>
+      Îñíîâíîé îáúåêò (êëàññ) LibRaw, ñîçäàåòñÿ ëèáî áåç ïàðàìåòðîâ, ëèáî ïåðåäàþòñÿ ôëàãè, îïðåäåëÿþùèå ïîâåäåíèå
+      îáúåêòà. 
+    </p>
+    <pre>
+#include "libraw/libraw.h"
+...
+
+   LibRaw ImageProcessor(unsigned int flags=0);
+...
+    </pre>
+    <p>Ôëàãè (íåñêîëüêî ôëàãîâ çàäàþòñÿ ÷åðåç | - îïåðàòîð bitwise-OR):</P>
+    <ul>
+      <li><b>LIBRAW_OPTIONS_NO_MEMERR_CALLBACK</b> íå óñòàíàâëèâàòü ñòàíäàðòíûé <a href="#callbacks">îáðàáîò÷èê îøèáêè
+          íåõâàòêè ïàìÿòè</a> (ñòàíäàðòíûé îáðàáîò÷èê ïå÷àòàåò ñîîáùåíèå îá îøèáêå â stderr).</li>
+      <li><b>LIBRAW_OPTIONS_NO_DATAERR_CALLBACK</b> íå óñòàíàâëèâàòü ñòàíäàðòíûé <a href="#callbacks">îáðàáîò÷èê îøèáêè
+          ÷òåíèÿ ôàéëà</a> (ñòàíäàðòíûé îáðàáîò÷èê ïå÷àòàåò ñîîáùåíèå îá îøèáêå â stderr).</li>
+    </ul>
+    <p>
+    Äëÿ îáðàáîòêè èçîáðàæåíèÿ èñïîëüçóþòñÿ òðè ãðóïïû ìåòîäîâ
+    </p>
+    <ul>
+      <li><a href="#dataload">Çàãðóçêà äàííûõ èç RAW-ôàéëà</a></li>
+      <li><a href="#dcrawemu">Ôóíêöèè ïîñò-îáðàáîòêè, ýìóëèðóþùèå ïîâåäåíèå dcraw</a></li>
+      <li><a href="#dcrawrite">Ôóíêöèè çàïèñè â ôàéë, ýìóëèðóþùèå ïîâåäåíèå dcraw</a></li>
+    </ul>
+    <p>
+      Ðåçóëüòàòû îáðàáîòêè ðàçìåùàþòñÿ â ïîëå imgdata, êîòîðîå èìååò òèï <a
+        href=API-datastruct-rus.html>libraw_data_t</a>, â ýòîì æå íàáîðå äàííûõ ñîäåðæàòñÿ ïîëÿ, óïðàâëÿþùèå
+      ïîñòîáðàáîòêîé è âûâîäîì.
+    </p>
+    <a name="return"></a>
+    <h2>Âîçâðàùàåìûå çíà÷åíèÿ</h2>
+    <p>
+      Âñå ôóíêöèè LibRaw API âîçâðàùàþò öåëîå ÷èñëî â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î
+        êîäàõ âîçâðàòà</a>. Ïîæàëóéñòà, ïðî÷èòàéòå <a href=API-notes-rus.html#errors>îïèñàíèå ýòîãî ñîãëàøåíèÿ</a> è
+      <a href="#callbacks">îïèñàíèå ïîâåäåíèÿ LibRaw ïðè ôàòàëüíûõ îøèáêàõ</a>.
+    </p>
+
+    <a name="dataload"></a>
+    <h2>Ìåòîäû, çàãðóæàþùèå äàííûå èç ôàéëà</h2>
+    <a name=open_datastream></a>
+    <h3>int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)</h3>
+    <p>Îòêðûâàåò ïîòîê ñ RAW-äàííûìè, ñ÷èòûâàåò îòòóäà ìåòàäàííûå (EXIF), çàïîëíÿåò
+      ñòðóêòóðû:
+    </p>
+    <ul>
+      <li>imgdata.idata (<a href="API-datastruct-rus.html#libraw_iparams_t">libraw_iparams_t</a>),</li>
+      <li>imgdata.sizes (<a href="API-datastruct-rus.html#libraw_image_sizes_t">libraw_image_sizes_t</a>),</li>
+      <li>imgdata.color (<a href="API-datastruct-rus.html#libraw_colordata_t">libraw_colordata_t</a>),</li>
+      <li>imgdata.other (<a href="API-datastruct-rus.html#libraw_imgother_t">libraw_imgother_t</a>) è</li>
+      <li>imgdata.thumbnail (<a href="API-datastruct-rus.html#libraw_thumbnail_t">libraw_thumbnail_t</a>).</li>
+    </ul>
+    <p>Ôóíêöèÿ âîçâðàùàåò öåëîå ÷èñëî â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>: ïîëîæèòåëüíîå ÷èñëî, åñëè êàêîé-òî èç ñèñòåìíûõ âûçîâîâ âåðíóë îøèáêó, îòðèöàòåëüíîå ÷èñëî (èç
+      <a href=API-datastruct-rus.html#LibRaw_errors>ñïèñêà îøèáîê LibRaw</a>) ïðè îøèáî÷íîé ñèòóàöèè
+      âíóòðè LibRaw.
+    </p>
+    <p>Ïåðåä íà÷àëîì îáðàáîòêè âûçûâàåòñÿ <a href="#recycle">recycle()</a>, ñëåäîâàòåëüíî ïðè îáðàáîòêå íåñêîëüêèõ
+      èçîáðàæåíèé â batch-ðåæèìå íåîáÿçàòåëüíî  âûçûâàåòü recycle() â êîíöå öèêëà îáðàáîòêè.
+    </p>
+    <p><b>Âõîäíîé ïàðàìåòð</b>: Îáúåêò êëàññà, ïðîèçâîäíîãî îò <a href="#datastream">LibRaw_abstract_datastream</a>.
+      Îáúåêò äîëæåí áûòü ïðîèíèöàëèçèðîâàí è ãîòîâ ê ÷òåíèþ. Äåèíèöèàëèçàöèÿ îáúåêòà ïðîèçâîäèòñÿ â âûçâàâøåì
+      ïðèëîæåíèè.
+    </p>
+    <a name=open_file></a>
+    <h3>int LibRaw::open_file(const char *filename)</h3>
+    <p>
+      Ñîçäàåò îáúåêò <a href="#file_datastream">LibRaw_file_datastream</a>, âûçûâàåò <a
+        href="#open_datastream">open_datastream()</a>,  ïðè óñïåõå âûñòàâëÿåò âíóòðåííèé ôëàã, ñèãíàëèçèðóþùèé î òîì,
+      ÷òî ñîçäàííûé îáúåêò äîëæåí áûòü óíè÷òîæåí ïðè <a href="#recycle">recycle()</a>, ïðè íåóñïåõå îòêðûòèÿ -
+      óíè÷òîæàåò òîëüêî ÷òî ñîçäàííûé îáúåêò. 
+    </p>
+    <p>Ôóíêöèÿ âîçâðàùàåò öåëîå ÷èñëî â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>: ïîëîæèòåëüíîå ÷èñëî, åñëè êàêîé-òî èç ñèñòåìíûõ âûçîâîâ âåðíóë îøèáêó, îòðèöàòåëüíîå ÷èñëî (èç
+      <a href=API-datastruct-rus.html#LibRaw_errors>ñïèñêà îøèáîê LibRaw</a>) ïðè îøèáî÷íîé ñèòóàöèè
+      âíóòðè LibRaw.
+    </p>
+
+    <a name=open_buffer></a>
+    <h3>int LibRaw::open_buffer(void *buffer, size_t bufsize)</h3>
+    <p>
+      Ñîçäàåò îáúåêò <a href="#buffer_datastream">LibRaw_buffer_datastream</a>, âûçûâàåò <a
+        href="#open_datastream">open_datastream()</a>,  ïðè óñïåõå âûñòàâëÿåò âíóòðåííèé ôëàã, ñèãíàëèçèðóþùèé î òîì,
+      ÷òî ñîçäàííûé îáúåêò äîëæåí áûòü óíè÷òîæåí ïðè <a href="#recycle">recycle()</a>, ïðè íåóñïåõå îòêðûòèÿ -
+      óíè÷òîæàåò òîëüêî ÷òî ñîçäàííûé îáúåêò. 
+    </p>
+    <p>Ôóíêöèÿ âîçâðàùàåò öåëîå ÷èñëî â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>: ïîëîæèòåëüíîå ÷èñëî, åñëè êàêîé-òî èç ñèñòåìíûõ âûçîâîâ âåðíóë îøèáêó, îòðèöàòåëüíîå ÷èñëî (èç
+      <a href=API-datastruct-rus.html#LibRaw_errors>ñïèñêà îøèáîê LibRaw</a>) ïðè îøèáî÷íîé ñèòóàöèè
+      âíóòðè LibRaw.
+    </p>
+    <a name="unpack"></a>
+    <h3> int LibRaw::unpack(void)</h3>
+    <p>
+      Ïðîèçâîäèò ðàñïàêîâêó RAW-äàííûõ èçîáðàæåíèÿ, âû÷èñëåíèå óðîâíÿ ÷åðíîãî (íå äëÿ âñåõ ôîðìàòîâ), âû÷èòàíèå
+      ÷åðíîãî (íå äëÿ âñåõ ôîðìàòîâ). Ðåçóëüòàòû ðàáîòû ïîìåùàþòñÿ â imgdata.image.
+    </p>
+    <p>
+      Íà ÷òåíèå äàííûõ â ðÿäå (ðåäêèõ) ñëó÷àåâ âëèÿþò íàñòðîéêè, ñäåëàííûå â imgdata.params (<a
+        href="API-datastruct-rus.html#libraw_output_params_t">libraw_output_params_t</a>), ïîäðîáíåå ñì. â <a
+        href=API-notes-rus.html>API notes</a>.
+    </p>
+    <p>Ôóíêöèÿ âîçâðàùàåò öåëîå ÷èñëî â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>: ïîëîæèòåëüíîå ÷èñëî, åñëè êàêîé-òî èç ñèñòåìíûõ âûçîâîâ âåðíóë îøèáêó, îòðèöàòåëüíîå ÷èñëî (èç
+      <a href=API-datastruct-rus.html#LibRaw_errors>ñïèñêà îøèáîê LibRaw</a>) ïðè îøèáî÷íîé ñèòóàöèè
+      âíóòðè LibRaw.
+    </p>
+    
+    <a name="unpack_thumb"></a>
+    <h3>int LibRaw::unpack_thumb(void)</h3>
+    <p>
+      Ïðîèçâîäèò ÷òåíèå (ëèáî ðàñïàêîâêó) preview (thumbnail) èçîáðàæåíèÿ,
+      ïîìåùàÿ ðåçóëüòàò â áóôåð imgdata.thumbnail.thumb.<br/>
+      JPEG-preview ïîìåùàþòñÿ â äàííûé áóôåð áåç êàêèõ-ëèáî èçìåíåíèé (ñ
+      çàãîëîâêîì è ò.ï.),  Äðóãèå ôîðìàòû preview ïîìåùàþòñÿ â áóôåð â âèäå ðàñïàêîâàíîãî 
+      image bitmap (3 êîìïîíåíòà, 8 áèò íà êîìïîíåíò).<br/>
+      Ôîðìàò thumbnail çàïèñûâàåòñÿ â ïîëå imgdata.thumbnail.tformat,
+      âîçìîæíûå çíà÷åíèÿ  îïèñàíû â <a
+        href="API-datastruct-rus.html#LibRaw_thumbnail_formats">îïèñàíèè êîíñòàíò è ñòðóêòóð äàííûõ</a>.
+
+    </p>
+    <p>Ôóíêöèÿ âîçâðàùàåò öåëîå ÷èñëî â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>: ïîëîæèòåëüíîå ÷èñëî, åñëè êàêîé-òî èç ñèñòåìíûõ âûçîâîâ âåðíóë îøèáêó, îòðèöàòåëüíîå ÷èñëî (èç
+      <a href=API-datastruct-rus.html#LibRaw_errors>ñïèñêà îøèáîê LibRaw</a>) ïðè îøèáî÷íîé ñèòóàöèè
+      âíóòðè LibRaw.
+    </p>
+    <a name="utility"></a>
+    <h2>Âñïîìîãàòåëüíûå ôóíêöèè</h2>
+    <h3>Èíôîðìàöèÿ î âåðñèè áèáëèîòåêè</h3>
+    <a name="version"></a>
+    <h4>const char* LibRaw::version()</h4>
+    <p>
+      Âîçâðàùàåò ñòðîêîâîå ïðåäñòàâëåíèå âåðñèè áèáëèîòåêè â ôîðìàòå MAJOR.MINOR.PATCH-Status (íàïðèìåð, 0.6.0-Alpha2
+      èëè 0.6.1-Release).
+    </p>
+    <a name="versionNumber"></a>
+    <h4>int LibRaw::versionNumber()</h4>
+    <p>
+      Âîçâðàùàåò öåëî÷èñëåííîå ïðåäñòàâëåíèå âåðñèè áèáëèîòåêè. Ïðè âûõîäå íîâûõ âåðñèé áèáëèîòåêè âåðñèÿ âñåãäà íå óáûâàåò.
+    </p>
+    <a name="LIBRAW_CHECK_VERSION"></a>
+    <h4>bool LIBRAW_CHECK_VERSION(major,minor,patch)</h4>
+    <p>
+      Ìàêðîñ äëÿ ïðîâåðêè âåðñèè â ïðèêëàäíûõ ïðîãðàììàõ. Âîçâðàùàåò true åñëè òåêóùàÿ âåðñèÿ áèáëèîòåêè áîëüøå èëè
+      ðàâíà ïåðåäàííîé â ïàðàìåòðàõ. Ìàêðîñ âûïîëíÿåòñÿ äèíàìè÷åñêè è ìîæåò èñïîëüçîâàòüñÿ äëÿ ïðîâåðêè âåðñèè
+      áèáëèîòåêè, çàãðóæàåìîé èç shared library/DLL.
+    </p>
+    <h3>Ñïèñîê ïîääåðæèâàåìûõ ôîðìàòîâ (êàìåð)</h3>
+    <a name="cameraCount"></a>
+    <h4>int LibRaw::cameraCount()</h4>
+    <p>
+      Âîçâðàùàåò êîëè÷åñòâî êàìåð, ïîääåðæèâàåìûõ òåêóùåé âåðñèåé áèáëèîòåêè.
+    </p>
+    <a name="cameraList"></a>
+    <h4>const char** LibRaw::cameraList()</h4>
+    <p>
+      Âîçâðàùàåò cïèñîê êàìåð, ïîääåðæèâàåìûõ áèáëèîòåêîé. Ñïèñîê íà 1 ýëåìåíò äëèííåå, ÷åì êîëè÷åñòâî êàìåð, â
+      ïîñëåäíåì ýëåìåíòå ñïèñêà ñîäåðæèòñÿ NULL.
+    </p>
+    <a name="unpack_function_name"></a>
+    <h3>const char* LibRaw::unpack_function_name()</h3>
+    <p>
+      Âîçâðàùàåò èìÿ ôóíêöèè-ðàñïàêîâùèêà ôàéëà. Èíòåðåñíà òîëüêî ðàçðàáîò÷èêàì òåñòîâ äëÿ LibRaw, ÷òîáû ïðîâåðèòü
+      test coverage.
+    </p>
+    <a name="add_masked_borders_to_bitmap"></a>
+    <h3>void LibRaw::add_masked_borders_to_bitmap</h3>
+    <p>
+      Âûçîâ íå ïîääåðæèâàåòñÿ â <a href=API-notes-rus.html#versions>LibRaw-Lite</a>.<br/>
+      Âûçîâ ïåðåñòðàèâàåò áèòìýï <b>imgdata.image</b> äîáàâëÿÿ ê íåìó äàííûå ÷åðíîé ðàìêè (ìàñêèðîâàííûõ ïèêñåëîâ),
+      åñëè ýòà ðàìêà åñòü â äàííûõ, âûäàâàåìûõ êàìåðîé (åñëè ðàìêè íåò, òî âûçîâ íè÷åãî íå äåëàåò).<br/>
+      Âûçîâ ìåíÿåò ïîëÿ <b>sizes.width,sizes.height,sizes.iwidth,sizes.iheight</b> íà ïîëíûé ðàçìåð èçîáðàæåíèÿ.<br/>
+      Âûçîâ íè÷åãî íå äåëàåò:
+      </p>
+    <ul>
+        <li>äëÿ èçîáðàæåíèé, ñîäåðæàùèõ áîëåå îäíîãî êîìïîíåíòà â êàæäîì ïèêñåëå (Sigma Foveon, ïîëíîöâåòíûå DNG,
+        ôàéëû, äåìîçàèêà êîòîðûõ óæå ïðîâåäåíà: Canon sRAW, Sinar 4-shot è ò.ï.).</li>
+      <li>äëÿ èçîáðàæåíèé, êîòîðûì óêàçàíî ïîëîâèííîå ðàçðåøåíèå ïðè ðàñïàêîâêå (ïîëîâèííàÿ èíòåðïîëÿöèÿ,
+        èñïðàâëåíèå àáåððàöèé, wavelet denoise).
+      </li>
+    </ul>
+    <p>Ôóíêöèÿ âîçâðàùàåò öåëîå ÷èñëî â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>: ïîëîæèòåëüíîå ÷èñëî, åñëè êàêîé-òî èç ñèñòåìíûõ âûçîâîâ âåðíóë îøèáêó, îòðèöàòåëüíîå ÷èñëî (èç
+      <a href=API-datastruct-rus.html#LibRaw_errors>ñïèñêà îøèáîê LibRaw</a>) ïðè îøèáî÷íîé ñèòóàöèè
+      âíóòðè LibRaw.
+    </p>
+    <a name="rotate_fuji_raw"></a>
+    <h3> int LibRaw:: rotate_fuji_raw()</h3>
+    <p>
+      Âûçîâ îñóùåñòâëÿåò ïîâîðîò RAW-bitmap (äî ïîñòïðîöåññèíãà) äàííûõ ñ êàìåð Fuji, ïðèâîäÿ âñå â âèä,
+      àíàëîãè÷íûé ïðåäûäóùèì âåðñèÿì LibRaw (äî 0.6 âêëþ÷èòåëüíî). Âûçîâ ïðåäíàçíà÷åí äëÿ èñïîëüçîâàíèÿ â
+      ïðîãðàììàõ, ðàáîòàþùèõ ñ íåèíòåðïîëèðîâàííûìè äàííûìè ñàìîñòîÿòåëüíî. Ïðè èñïîëüçîâàíèè âûçîâîâ
+      dcraw_process/dcraw_document_mode_processing ïîâîðîò áóäåò ïðîèçâåäåí èìè.
+    </p>
+    <p>Ôóíêöèÿ âîçâðàùàåò öåëîå ÷èñëî â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>: ïîëîæèòåëüíîå ÷èñëî, åñëè êàêîé-òî èç ñèñòåìíûõ âûçîâîâ âåðíóë îøèáêó, îòðèöàòåëüíîå ÷èñëî (èç
+      <a href=API-datastruct-rus.html#LibRaw_errors>ñïèñêà îøèáîê LibRaw</a>) ïðè îøèáî÷íîé ñèòóàöèè
+      âíóòðè LibRaw.
+    </p>
+    <p>
+      Âûçîâ íå ïîääåðæèâàåòñÿ â <a href=API-notes-rus.html#versions>LibRaw-Lite</a>: â äàííîé âåðñèè èçâëå÷åíèå
+      äàííûõ ñ êàìåð Fuji îñóùåñòâëÿåòñÿ ñðàçó â ïîâåðíóòûé bitmap.
+    </p>
+      <a name="recycle"></a>
+    <h3>void LibRaw::recycle(void)</h3>
+    <p>
+      Îñâîáîæäàåò àëëîöèðîâàííûå äàííûå ýêçåìïëÿðà LibRaw, äåëàÿ  âîçìîæíûì îáðàáîòêó ñëåäóþùåãî ôàéëà òåì æå
+      ïðîöåññîðîì. Ïîâòîðíûå âûçîâû recycle() âïîëíå âîçìîæíû è íè÷åìó íå ïðîòèâîðå÷àò. 
+    </p>
+
+    <a name="~LibRaw"></a>
+    <h3>LibRaw::~LibRaw()</h3>
+    <p>Äåñòðóêòîð, ñâîäèòñÿ ê âûçîâó recycle()</p>
+
+    <a name="strprogress"></a>
+    <h3>const char* LibRaw::strprogress(enum LibRaw_progress code)</h3>
+    <p>Âûäàåò òåêñòîâóþ ðàñøèôðîâêó (íà àíãëèéñêîì ÿçûêå) äëÿ êîäîâ òåêóùåé ñòàäèè îáðàáîòêè LibRaw</p>
+    <a name="libraw_strerror"></a>
+    <h3>const char* LibRaw::strerror(int errorcode)</h3>
+    <p>Àíàëîã ôóíêöèè strerror(3) - âûäàåò òåêñòîâóþ ðàñøèôðîâêó (íà àíãëèéñêîì ÿçûêå) äëÿ êîäîâ îøèáîê LibRaw</p>
+
+    <a name="callbacks"></a>
+    <h3>Óñòàíîâêà ôóíêöèé íîòèôèêàöèè</h3>
+    <p>
+      Ïðè ðàáîòå áèáëèîòåêè ìîæíî âûçûâàòü ïîëüçîâàòåëüñêèé callback, êîòîðûé ìîæåò áûòü èñïîëüçîâàí äëÿ
+      äâóõ öåëåé:
+    </p>
+    <ul>
+      <li>Äèíàìè÷åñêàÿ îòðèñîâêà ñòàòóñà îáðàáîòêè èçîáðàæåíèÿ.</li>
+      <li>Äîñðî÷íîå ïðåêðàùåíèå ïðîöåññà îáðàáîòêè (íàïðèìåð, ïî çàïðîñó ïîëüçîâàòåëÿ)</li>
+    </ul>
+    <p>Êðîìå òîãî, ïðè ðàáîòå áèáëèîòåêè âîçìîæíû äâà òèïà èñêëþ÷èòåëüíûõ ñèòóàöèé, êîòîðûå ìîãóò òðåáîâàòü
+      óâåäîìëåíèÿ âûçûâàþùåãî ïðèëîæåíèÿ:
+    </p>
+    <ul>
+      <li>íåõâàòêà ïàìÿòè</li>
+      <li>îøèáêà ÷òåíèÿ äàííûõ</li>
+    </ul>
+    <p>
+      Ïðèëîæåíèå ìîæåò óñòàíîâèòü ñâîè callbacks, êîòîðûå áóäóò âûçâàíû â âûøåïåðå÷èñëåííûõ ñëó÷àÿõ, ñ öåëüþ
+      óâåäîìëåíèÿ ïîëüçîâàòåëÿ (èëè âûçûâàþùåé ïðîãðàììû).
+    </p>
+    <a name="progress"></a>
+    <h4>Èíäèêàöèÿ ñòàäèé îáðàáîòêè/äîñðî÷íîå åå ïðåêðàùåíèå</h4>
+    <pre>
+        typedef int (*progress_callback)(void *callback_data,enum LibRaw_progress stage, int iteration, int expected);
+        void LibRaw::set_progress_handler(progress_callback func,void *callback_data);
+    </pre>
+    <p>
+      Ïîëüçîâàòåëü ìîæåò îïðåäåëèòü ñâîþ ôóíêöèþ, êîòîðàÿ áóäåò ìíîãîêðàòíî (10-50 ðàç) âûçûâàòüñÿ â ïðîöåññå
+      îáðàáîòêè äàííûõ  RAW-ôàéëà âûçîâàìè  dcraw_process()/dcraw_document_mode_processing();
+    </p>
+    <p>
+      Ýòîò callback ìîæåò ñèãíàëèçèðîâàòü î íåîáõîäèìîñòè ïðåêðàòèòü îáðàáîòêó ïóòåì âîçâðàòà íåíóëåâîãî çíà÷åíèÿ. Â
+      ýòîì ñëó÷àå îáðàáîòêà áóäåò çàâåðøåíà, ïàìÿòü îñâîáîæäåíà âûçîâîì recycle() è îáúåêò LibRaw áóäåò ãîòîâ ê
+      îáðàáîòêå ñëåäóþùåãî ôàéëà. Òåêóùèé âûçîâ dcraw_process()/dcraw_document_mode_processing() âåðíåò êîä îøèáêè 
+      LIBRAW_CANCELLED_BY_CALLBACK.
+      </p>
+    <p>
+      Ïàðàìåòðû âûçîâà:
+      <dl>
+      <dt>void *callback_data</dt>
+      <dd>void*-óêàçàòåëü, ïåðåäàííûé ïðè óñòàíîâêå callback ÷åðåç
+        set_memerror_handler. Èñïîëüçóåòñÿ äëÿ ïåðåäà÷è â callback äîïîëíèòåëüíûõ äàííûõ</dd>
+      <dt>enum LibRaw_progress stage</dt>
+      <dd>Òåêóùàÿ ñòàäèÿ îáðàáîòêè. Êîä ìîæåò áûòü ïðåâðàùåí â ñòðîêó ïóòåì âûçîâà ôóíêöèè 
+        <a href="#strprogress">LibRaw::strprogress</a>. Callback âûçûâàåòñÿ íå íà âñåõ ñòàäèÿõ îáðàáîòêè, à òîëüêî íà
+        òåõ, êîòîðûå ìîãóò çàíÿòü áîëüøîå âðåìÿ.
+      </dd>
+      <dt>int iteration</dt>
+      <dd>Íîìåð èòåðàöèè îáðàáîòêè (îò 0 äî    expected-1). Âíóòðè ñòàäèè îáðàáîòêè callback âûçûâàåòñÿ áîëåå îäíîãî
+        ðàçà, íîìåð èòåðàöèè âíóòðè îäíîé ñòàäèè âñåãäà âîçðàñòàåò.
+      </dd>
+      <dt>int expected</dt>
+      <dd>Îæèäàåìîå êîëè÷åñòâî èòåðàöèé íà ýòîé ñòàäèè îáðàáîòêè</dd>
+      </dl>
+    Âîçâðàùàåìûå çíà÷åíèÿ: <b>0</b> åñëè îáðàáîòêó ìîæíî ïðîäîëæèòü, íåíóëåâîå ÷èñëî - åñëè îáðàáîòêó ñëåäóåò
+    íåìåäëåííî ïðåêðàòèòü.
+    </p>
+    <p>
+      Ïðè èñïîëüçîâàíèè OpenMP ïîðÿäîê ñëåäîâàíèÿ iteration íåîïðåäåëåí, îíè íå îáÿçàíû ñòðîãî âîçðàñòàòü.
+    </p>
+    <p>
+      Ïðèìåð êîäà callback:
+<pre>
+int my_progress_callback(void *data,enum LibRaw_progress p,int iteration, int expected)
+{
+    char *passed_string = (char *data);
+    printf("Callback: %s  pass %d of %d, data passed: %s\n",libraw_strprogress(p),iteration,expected,passed_string);
+    if(timeout || key_pressed )
+        return 1; // cancel processing immediately
+    else
+        return 0; // can continue
+}
+
+</pre>
+    <a name="memerror"></a>
+    <h4>Óâåäîìèòåëü î íåõâàòêå ïàìÿòè</h4>
+    <pre>
+        typedef void (* memory_callback)(void *callback_data,const char *file, const char *where);
+        void LibRaw::set_memerror_handler(memory_callback func,void *callback_data);
+    </pre>
+    <p>
+      Ïîëüçîâàòåëü ìîæåò îïðåäåëèòü ñâîþ ôóíêöèþ, âûçûâàåìóþ ïî
+      íåõâàòêå ïàìÿòè. Ýòî void-ôóíêöèÿ, ïîëó÷àþùàÿ òðè ïàðàìåòðà:
+    </p>
+    <ul>
+      <li><b>callback_data</b> - void*-óêàçàòåëü, ïåðåäàííûé ïðè óñòàíîâêå callback ÷åðåç
+        set_memerror_handler. Èñïîëüçóåòñÿ äëÿ ïåðåäà÷è â callback äîïîëíèòåëüíûõ äàííûõ</li>
+      <li><b>file</b> - èìÿ RAW-ôàéëà ïðè îáðàáîòêå êîòîðîãî ïðîèçîøëà îøèáêà íåõâàòêè ïàìÿòè. Ýòî èìÿ ôàéëà <b>ìîæåò
+          áûòü íóëåâûì</b> - â ñëó÷àå, êîãäà îíî íåèçâåñòíî ìîäóëþ ïîëó÷åíèÿ äàííûõ. Callback äîëæåí ïðàâèëüíî
+        îáðàáàòûâàòü ñëó÷àé íóëåâîãî èìåíè.</li>
+      <li><b>where</b> - èìÿ ôóíêöèè â êîòîðîé íå õâàòèëî ïàìÿòè;</li>
+    </ul>
+    <p>Çàäà÷à callback - èíôîðìàöèîííàÿ (óâåäîìëåíèå ïîëüçîâàòåëÿ èëè êîäà ïðîãðàììû î íåâîçìîæíîñòè âûïîëíèòü
+      îáðàáîòêó).</p> 
+    <p>Åñëè íå óñòàíîâèòü ñâîé îáðàáîò÷èê, òî áóäåò èñïîëüçîâàí ñòàíäàðòíûé (ïå÷àòü ñîîáùåíèÿ îá îøèáêå â stderr).</p>
+    <p>Ìîæíî óñòàíîâèòü íóëåâîé îáðàáîò÷èê, ïåðåäàâ NULL â set_memerror_handler, òîãäà ôóíêöèÿ óâåäîìëåíèÿ âûçûâàòüñÿ
+      íå áóäåò. Òîãî æå ýôôåêòà ìîæíî äîáèòüñÿ, åñëè ñîçäàòü îáúåêò LibRaw ñ ôëàãîì êîíñòðóêòîðà
+      LIBRAW_OPTIONS_NO_MEMERR_CALLBACK.
+    </p>
+    <p> ñëó÷àå íåõâàòêè ïàìÿòè, îáðàáîòêà òåêóùåãî ôàéëà ïðåêðàùàåòñÿ, âûçûâàåòñÿ óâåäîìèòåëü, âñå àëëîöèðîâàííûå
+      ðåñóðñû îñâîáîæäàþòñÿ, äåëàåòñÿ <a href="#recycle">recycle()</a>. Òåêóùèé âûçîâ âåðíåò îøèáêó
+      LIBRAW_UNSUFFICIENT_MEMORY. 
+      <br/>
+      Ïðè ïîïûòêå ïðîäîëæèòü îáðàáîòêó äàííûõ,  âñå âûçîâû ïîñëåäóùèå áóäóò âîçâðàùàòü
+      LIBRAW_OUT_OF_ORDER_CALL. Îáðàáîòêó íîâîãî ôàéëà ìîæíî íà÷àòü îáû÷íûì îáðàçîì: âûçâàâ LibRaw::open_file().
+    </p>
+    <a name="dataerror"></a>
+    <h4>Óâåäîìèòåëü îá îøèáêå ÷òåíèÿ ôàéëà</h4>
+    <pre>
+        typedef void (*data_callback)(void *callback_data,const char *file, const int offset);
+        void LibRaw::set_dataerror_handler(data_callback func,void *callback_data); 
+    </pre>
+    <p>
+      Ïîëüçîâàòåëü ìîæåò îïðåäåëèòü ñâîþ ôóíêöèþ, âûçûâàåìóþ ïî îøèáêå âõîäíûõ äàííûõ. Ýòî void-ôóíêöèÿ, ïîëó÷àþùàÿ
+      òðè  ïàðàìåòðà:
+    </p>
+    <ul>
+      <li><b>callback_data</b> - void*-óêàçàòåëü, ïåðåäàííûé ïðè óñòàíîâêå callback ÷åðåç
+        set_memerror_handler. Èñïîëüçóåòñÿ äëÿ ïåðåäà÷è â callback äîïîëíèòåëüíûõ äàííûõ</li>
+      <li><b>file</b>:  èìÿ RAW-ôàéëà ïðè îáðàáîòêå êîòîðîãî ïðîèçîøëà îøèáêà íåõâàòêè ïàìÿòè, ýòîò ïàðàìåòð ìîæåò
+        áûòü íóëåâûì (NULL), âûçûâàåìûé callback äîëæåí êîððåêòíî îáðàáàòûâàòü ýòîò ñëó÷àé.</li>
+      <li><b>offset</b>:  -1 åñëè ôàéë çàêîí÷èëñÿ (òîãäà êàê LibRaw îæèäàåò òàì åùå äàííûå), ïîëîæèòåëüíîå ÷èñëî -
+        ïîçèöèÿ â ôàéëå (â áàéòàõ îò íà÷àëà), ãäå âîçíèêëà îøèáêà ðàñïàêîâêè.</li>
+    </ul>
+    <p>Çàäà÷à callback - èíôîðìàöèîííàÿ (óâåäîìëåíèå ïîëüçîâàòåëÿ èëè êîäà ïðîãðàììû î íåâîçìîæíîñòè âûïîëíèòü
+      îáðàáîòêó).</p> 
+    <p>Åñëè íå óñòàíîâèòü ñâîé îáðàáîò÷èê, òî áóäåò èñïîëüçîâàí ñòàíäàðòíûé (ïå÷àòü ñîîáùåíèÿ îá îøèáêå â stderr).</p>
+    <p>Ìîæíî óñòàíîâèòü íóëåâîé îáðàáîò÷èê, ïåðåäàâ NULL â set_dataerror_handler, òîãäà ôóíêöèÿ óâåäîìëåíèÿ âûçûâàòüñÿ
+      íå áóäåò. Òîãî æå ýôôåêòà ìîæíî äîáèòüñÿ, åñëè ñîçäàòü îáúåêò LibRaw ñ ôëàãîì êîíñòðóêòîðà
+      LIBRAW_OPTIONS_NO_DATAERR_CALLBACK.
+    </p>
+    <p> ñëó÷àå îøèáêè âî âõîäíûõ äàííûõ, îáðàáîòêà òåêóùåãî ôàéëà ïðåêðàùàåòñÿ, âûçûâàåòñÿ óâåäîìèòåëü, âñå
+      àëëîöèðîâàííûå ðåñóðñû îñâîáîæäàþòñÿ, äåëàåòñÿ <a href="#recycle">recycle()</a>. Òåêóùèé âûçîâ âåðíåò îøèáêó
+      LIBRAW_IO_ERROR. 
+      <br/>
+      Ïðè ïîïûòêå ïðîäîëæèòü îáðàáîòêó äàííûõ,  âñå âûçîâû ïîñëåäóùèå áóäóò âîçâðàùàòü
+      LIBRAW_OUT_OF_ORDER_CALL. Îáðàáîòêó íîâîãî ôàéëà ìîæíî íà÷àòü îáû÷íûì îáðàçîì: âûçâàâ LibRaw::open_file().
+    </p>
+
+    <a name="dcrawemu"></a>
+    <h2>Ïîñòîáðàáîòêà äàííûõ, ýìóëÿöèÿ ïîâåäåíèÿ dcraw</h2>
+    <p>
+      Âìåñòî íàïèñàíèÿ ñâîåé ïîñò-îáðàáîòêè Bayer Pattern, ìîæíî
+      âîñïîëüçîâàòüñÿ âûçîâàìè dcraw (êîòîðûå âûçûâàþòñÿ ïîñëå âûçîâà 
+      open_file() + unpack() /+ unpack_thumb()/).
+    </p>
+    <a name="dcraw_params"></a>
+    <h3>Çàäàíèå ïàðàìåòðîâ</h3>
+    <p>
+      Ïðàêòè÷åñêè âñå ïàðàìåòðû, êîòîðûå ìîæíî çàäàòü ÷åðåç êîìàíäíóþ ñòðîêó dcraw, çàäàþòñÿ ïóòåì ïðèñâàèâàíèÿ
+      çíà÷åíèé ïîëÿì ñòðóêòóðû <b>LibRaw::imgdata.params</b>, ñòðóêòóðà èìååò òèï <b>libraw_output_params_t</b>, âñå
+      ïîëÿ ïåðå÷èñëåíû è äîñòàòî÷íî ïîäðîáíî îïèñàíû <a href="API-datastruct-rus.html#libraw_output_params_t">â
+        îïèñàíèè ñòðóêòóð äàííûõ</a>.
+    </p>
+
+    <a name="adjust_sizes_info_only"></a>
+    <h3>int LibRaw::adjust_sizes_info_only(void)</h3>
+    <p>
+      Ôóíêöèÿ ðàññ÷èòûâàåò ïðàâèëüíûå ðàçìåðû âûõîäíîãî èçîáðàæåíèÿ (imgdata.sizes.iwidth è imgdata.sizes.iheight) äëÿ
+            ñëåäóþùèõ ñëó÷àåâ: 
+      </p>
+    <ul>
+      <li>ôàéëû îò êàìåð Fuji (ïîâåðíóòûå íà 45 ãðàäóñîâ);</li>
+      <li>ôàéëû îò êàìåð ñ íåêâàäðàòíûìè ïèêñåëàìè;</li>
+      <li>èçîáðàæåíèÿ, ñíÿòûå ïîâåðíóòîé êàìåðîé.</li>
+    </ul>
+    <p>
+       ïåðå÷èñëåííûõ âûøå ñëó÷àÿõ, ôóíêöèÿ ìåíÿåò çíà÷åíèÿ ïîëåé âûõîäíîãî ðàçìåðà èçîáðàæåíèÿ, ïðè÷åì ýòî èçìåíåíèå
+      íå ìîæåò áûòü âûïîëíåíî ïîâòîðíî.
+    </p>
+    <p>
+      Ôóíêöèÿ äîëæíà èñïîëüçîâàòüñÿ â èíôîðìàöèîííûõ öåëÿõ, îíà íåñîâìåñòèìà ñ âûçîâàìè <a
+        href="#dcraw_document_mode_processing">dcraw_document_mode_processing()</a> è <a
+        href="#dcraw_process">dcraw_process()</a>. 
+    </p>
+
+    <a name="dcraw_document_mode_processing"></a>
+    <h3>int LibRaw::dcraw_document_mode_processing(void)</h3>
+    <p>
+      Ôóíêöèÿ ýìóëèðóåò <b>dcraw -D</b> - îòêëþ÷åíèå èíòåðïîëÿöèè, áàëàíñà áåëîãî è ïðåîáðàçîâàíèÿ öâåòîâ.<br/> 
+      Âûçûâàåòñÿ ïîñëå âûçîâà LibRaw::unpack();
+    </p>
+    <p>Ôóíêöèÿ âîçâðàùàåò öåëîå ÷èñëî â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>: ïîëîæèòåëüíîå ÷èñëî, åñëè êàêîé-òî èç ñèñòåìíûõ âûçîâîâ âåðíóë îøèáêó, îòðèöàòåëüíîå ÷èñëî (èç
+      <a href=API-datastruct-rus.html#LibRaw_errors>ñïèñêà îøèáîê LibRaw</a>) ïðè îøèáî÷íîé ñèòóàöèè
+      âíóòðè LibRaw.
+    </p>
+    
+    <a name="dcraw_process"></a>
+    <h3>int LibRaw::dcraw_process(void)</h3>
+    <p>
+      Ôóíêöèÿ ýìóëèðóåò âîçìîæíîñòè ïîñòîáðàáîòêè, èìåþùèåñÿ â <b>dcraw</b><br/>
+      Âûçûâàåòñÿ ïîñëå âûçîâà LibRaw::unpack();
+    </p>
+    <p>Ïîääåðæèâàåòñÿ âñÿ ôóíêöèîíàëüíîñòü dcraw (çàäàâàåìàÿ ÷åðåç çíà÷åíèå ïîëåé â <a
+        href="API-datastruct-rus.html#libraw_output_params_t">imgdata.params</a>) çà èñêëþ÷åíèåì:
+      </p>
+    <ul>
+      <li>âû÷èòàíèÿ dark frame</li>
+      <li>ðàáîòû ñ bad pixels</li>
+    </ul>
+    <p> Ôóíêöèÿ ïðåäíàçíà÷åíà èñêëþ÷èòåëüíî äëÿ äåìîíñòðàöèîííûõ è òåñòîâûõ öåëåé, ïðåäïîëàãàåòñÿ ÷òî â áîëüøèíñòâå
+      ðåàëüíûõ ïðèëîæåíèé åå èñõîäíûé òåêñò áóäåò èñïîëüçîâàí êàê ñïðàâî÷íèê ïî ïîðÿäêó îáðàáîòêè RAW-äàííûõ.
+    </p>
+    <p>Ôóíêöèÿ âîçâðàùàåò öåëîå ÷èñëî â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>: ïîëîæèòåëüíîå ÷èñëî, åñëè êàêîé-òî èç ñèñòåìíûõ âûçîâîâ âåðíóë îøèáêó, îòðèöàòåëüíîå ÷èñëî (èç
+      <a href=API-datastruct-rus.html#LibRaw_errors>ñïèñêà îøèáîê LibRaw</a>) ïðè îøèáî÷íîé ñèòóàöèè
+      âíóòðè LibRaw.
+    </p>
+    <a name="dcrawrite"></a>
+    <h2>Çàïèñü äàííûõ â ôàéëû, ýìóëÿöèÿ ïîâåäåíèÿ dcraw</h2>
+    <p>Íåñìîòðÿ íà îáèëèå áèáëèîòåê, ïðåäíàçíà÷åííûõ äëÿ çàïèñè ôàéëîâ ëþáûõ ôîðìàòîâ, â LibRaw âêëþ÷åíû âûçîâû,
+      ýìóëèðóþùèå çàïèñü â ôàéëû, ïðîèçâîäèìóþ dcraw.  ïåðâóþ î÷åðåäü ýòî ñäåëàíî äëÿ îáëåã÷åíèÿ âåðèôèêàöèè ðàáîòû
+      áèáëèîòåêè - ïðîèçâîäèìûå åé ôàéëû äîëæíû áèíàðíî ñîâïàäàòü.
+    </p>
+
+    <a name="dcraw_ppm_tiff_writer"></a>
+    <h3>int LibRaw::dcraw_ppm_tiff_writer(const char *outfile)</h3>
+    <p>
+      Çàïèñûâàåò ðåçóëüòàòû ïîñòîáðàáîòêè â ôàéë â ôîðìàòå PPM/PGM èëè TIFF (ôîðìàò çàäàåòñÿ ÷åðåç
+      imgdata.params.output_tiff). Ïðîèçâîäèò ðåçóëüòàòû, áèíàðíî èäåíòè÷íûå ñ dcraw.
+    </p>
+    <p>Ôóíêöèÿ âîçâðàùàåò öåëîå ÷èñëî â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>: ïîëîæèòåëüíîå ÷èñëî, åñëè êàêîé-òî èç ñèñòåìíûõ âûçîâîâ âåðíóë îøèáêó, îòðèöàòåëüíîå ÷èñëî (èç
+      <a href=API-datastruct-rus.html#LibRaw_errors>ñïèñêà îøèáîê LibRaw</a>) ïðè îøèáî÷íîé ñèòóàöèè
+      âíóòðè LibRaw.
+    </p>
+    <a name="dcraw_thumb_writer"></a>
+    <h3>int LibRaw::dcraw_thumb_writer(const char *thumbfile)</h3>
+    <p>Çàïèñûâàåò thumbnail â ôàéë â ôîðìàòå PPM äëÿ bitmap-thumbnails è JPEG äëÿ  JPEG-thumbnails, â ôîðìàòå
+      ïîëíîñòüþ èäåíòè÷íîì ðåçóëüòàòàì ðàáîòû dcraw.
+    </p>
+    <p>Ôóíêöèÿ âîçâðàùàåò öåëîå ÷èñëî â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>: ïîëîæèòåëüíîå ÷èñëî, åñëè êàêîé-òî èç ñèñòåìíûõ âûçîâîâ âåðíóë îøèáêó, îòðèöàòåëüíîå ÷èñëî (èç
+      <a href=API-datastruct-rus.html#LibRaw_errors>ñïèñêà îøèáîê LibRaw</a>) ïðè îøèáî÷íîé ñèòóàöèè
+      âíóòðè LibRaw.
+    </p>
+
+    <a name="memwrite"></a>
+    <h2>Çàïèñü ðàñïàêîâàíûõ äàííûõ â áóôåð â ïàìÿòè</h2>
+    <p>
+      Ïîìèìî çàïèñè â ôàéë, áèáëèîòåêà ïðåäîñòàâëÿåò âîçìîæíîñòè çàïèñè èçâëå÷åííûõ è îáðàáîòàííûõ ôóíêöèÿìè
+        dcraw_* äàííûõ â áóôåð â ïàìÿòè. Äëÿ ýòîãî èìåþòñÿ òàêèå âûçîâû:
+      <ul>
+      <li><b>dcraw_make_mem_image</b> - ïðåîáðàçîâàíèå èçâëå÷åííûõ äàííûõ â RGB-áèòìýï íóæíîãî ðàçìåðà.
+        </li>
+      <li><b>dcraw_make_mem_thumb</b> -  èçâëå÷åíèå thumbnail â âèäå îáðàçà JPEG-ôàéëà â ïàìÿòè, ëèáî (äëÿ òåõ êàìåð,
+        ãäå preview - íå JPEG) â âèäå RGB-bitmap.
+      </li>
+      </ul>
+    Ïðèìåð èñïîëüçîâàíèÿ ýòèõ ôóíêöèé - mem_image (ñì. êàòàëîã samples/  äèñòðèáóòèâà).
+    </p>
+    <a name="dcraw_make_mem_image"></a>
+    <h3>libraw_processed_image_t *dcraw_make_mem_image(int *errorcode=NULL) - çàïèñü ðàñïàêîâàííîãî èçîáðàæåíèÿ â áóôåð â ïàìÿòè</h3>
+    <p>
+      Àëëîöèðóåò áóôåð íåîáõîäèìîãî ðàçìåðà è çàïèñûâàåò â íåãî ðàñïàêîâàííîå è îáðàáîòàííîå èçîáðàæåíèå. Âîçâðàùàåò
+      àëëîöèðîâàííóþ ñòðóêòóðó <a href="API-datastruct-rus.html#libraw_processed_image_t">libraw_processed_image_t</a>
+      ñ çàïîëíåííûìè ïîëÿìè. Âñåãäà âîçâðàùàåò ðàñïàêîâàíûé bitmap (ò.å. ïîëå type âîçâðàùàåìîé ñòðóêòóðû ðàâíî
+      LIBRAW_IMAGE_BITMAP).
+    </p>
+    <p>
+      Ïåðåä âûçîâîì ýòîé ôóíêöèè äîëæíà áûòü âûçâàíà dcraw_process() èëè dcraw_document_mode_processing().
+    </p>
+    <p>
+       ñëó÷àå îøèáêè âîçâðàùàåòñÿ NULL. Åñëè â êà÷åñòâå àðãóìåíòà errorcode ïåðåäàí íåíóëåâîé óêàçàòåëü, òî ïî àäðåñó
+      óêàçàòåëÿ çàïèñûâàåòñÿ êîä
+      îøèáêè â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>.
+    </p>
+    <p><b>Âíèìàíèå!</b> Ïàìÿòü, àëëîöèðîâàííàÿ ôóíêöèåé, íå îñâîáîæäàåòñÿ ïðè âûçîâå äåñòðóêòîðà èëè
+      <b>LibRaw::recycle</b> è äîëæíà áûòü îñâîáîæäåíà âûçâàâøèì ïðèëîæåíèåì. 
+    </p>
+
+    <a name="dcraw_make_mem_thumb"></a>
+    <h3>libraw_processed_image_t *dcraw_make_mem_thumb(int *errorcode=NULL) - çàïèñü ðàñïàêîâàííîãî thumbnail â áóôåð â ïàìÿòè</h3>
+    <p>
+      Àëëîöèðóåò áóôåð íåîáõîäèìîãî ðàçìåðà è çàïèñûâàåò â íåãî thumbnail. Âîçâðàùàåò
+      àëëîöèðîâàííóþ ñòðóêòóðó <a href="API-datastruct-rus.html#libraw_processed_image_t">libraw_processed_image_t</a>
+      ñ çàïîëíåííûìè ïîëÿìè. Äëÿ áîëüøèíñòâà òèïîâ RAW-ôàéëîâ â ñòðóêòóðå áóäåò ñîäåðæàòüñÿ  JPEG,
+      (ò.å. ïîëå type âîçâðàùàåìîé ñòðóêòóðû ðàâíî LIBRAW_IMAGE_JPEG), äëÿ íåêîòîðûõ òèïîâ êàìåð - RGB-bitmap.
+    </p>
+    <p>
+      Ïåðåä âûçîâîì ýòîé ôóíêöèè äîëæíà áûòü âûçâàíà unpack_thumb();
+    </p>
+    <p>
+       ñëó÷àå îøèáêè âîçâðàùàåòñÿ NULL. Åñëè â êà÷åñòâå àðãóìåíòà errorcode ïåðåäàí íåíóëåâîé óêàçàòåëü, òî ïî àäðåñó
+      óêàçàòåëÿ çàïèñûâàåòñÿ êîä
+      îøèáêè â ñîîòâåòñòâèè ñ <a href=API-notes-rus.html#errors>ñîãëàøåíèåì î êîäàõ
+        âîçâðàòà</a>.
+    </p>
+     <p><b>Âíèìàíèå!</b> Ïàìÿòü, àëëîöèðîâàííàÿ ôóíêöèåé, íå îñâîáîæäàåòñÿ ïðè âûçîâå äåñòðóêòîðà èëè
+      <b>LibRaw::recycle</b> è äîëæíà áûòü îñâîáîæäåíà âûçâàâøèì ïðèëîæåíèåì. 
+    </p>
+    <a name="datastream"></a>
+    <h2>Àáñòðàêöèÿ ââîäà</h2>
+    <a name="LibRaw_abstract_datastream"></a>
+    <h3>class LibRaw_abstract_datastream - àáñòðàêòíûé èíòåðôåéñ ÷òåíèÿ RAW-ôàéëîâ</h3>
+    <p>
+      ×òåíèå RAW-äàííûõ â LibRaw ïðîèçâîäèòñÿ ïðè ïîìîùè îáúåêòà êëàññà, ïðîèçâîäíîãî îò
+      <b>LibRaw_abstract_datastream</b>. Ñàì ýòîò êëàññ íå ðåàëèçóåò íèêàêîãî ÷òåíèÿ, íî çàäàåò ñïèñîê âèðòóàëüíûõ
+      ìåòîäîâ, èñïîëüçóåìûõ â  LibRaw. Ðåàëèçàöèè ìåòîäîâ â áàçîâîì êëàññå âîçâðàùàþò îøèáêó.
+    </p>
+    <a name="datastream_methods"></a>
+    <h4>Ìåòîäû êëàññà LibRaw_abstract_datastream</h4>
+    <a name="datastream_methods_utility"></a>
+    <h5>Âåðèôèêàöèÿ îáúåêòà</h5>
+    <dl>
+      <dt><b>    virtual int         valid()</b></dt>
+      <dd>Ïðîâåðêà âàëèäíîñòè ïîòîêà. Ìåòîä âîçâðàùàåò 1 åñëè ïîòîê ñêîíñòðóèðîâàí ïðàâèëüíî è 0 åñëè èç äàííîãî
+        ïîòîêà íåëüçÿ ÷èòàòü (ïåðåäàëè íåñóùåñòâóþùåå èìÿ ôàéëà äëÿ ôàéëîâîãî ïîòîêà è ò.ï.).
+      </dd>
+    <a name="datastream_methods_read"></a>
+    <h5>×òåíèå äàííûõ è ïîçèöèîíèðîâàíèå</h5>
+    <p>Äàííàÿ ãðóïïà ìåòîäîâ âîñïðîèçâîäèò ñåìàíòèêó îáúåêòà ôàéë (FILE*) ñ ïðîèçâîëüíûì ïîçèöèîíèðîâàíèåì.</p>
+    <dl>
+      <dt><b>virtual int         read(void * ptr,size_t size, size_t nmemb)</b></dt>
+      <dd>
+        Àíàëîã âûçîâà fread(ptr,size,nmemb,file).
+      </dd>
+      <dt><b>virtual int         seek(off_t o, int whence)</b></dt>
+      <dd>
+        Àíàëîã fseek(file,o,whence).
+      </dd>
+      <dt><b>virtual int         tell(</b></dt>
+      <dd>
+        Àíàëîã ftell(file).
+      </dd>
+      <dt><b>virtual int         get_char()</b></dt>
+      <dd>
+        Àíàëîã getc(file)/fgetc(file).
+      </dd>
+      <dt><b>virtual char*       gets(char *s, int n)</b></dt>
+      <dd>
+        Àíàëîã fgets(s,n,file).
+      </dd>
+      <dt><b>virtual int         eof()</b></dt>
+      <dd>
+        Àíàëîã feof(file).
+      </dd>
+      <dt><b>virtual int         scanf_one(const char *fmt, void *val)</b></dt>
+      <dd>
+        Óïðîùåííûé àíàëîã fscanf(file,fmt,val): ôîðìàò âñåãäà îïèñûâàåò îäèí àðãóìåíò, â ðåçóëüòàòå ôóíêöèÿ ñ
+        ïåðåìåííûì ÷èñëîì ïàðàìåòðîâ íå íóæíà: óêàçàòåëü â êîòîðûé ñ÷èòûâàþòñÿ äàííûå âñåãäà îäèí.
+      </dd>
+    </dl>
+    <a name="datastream_methods_other"></a>
+    <h5>Ïðî÷èå ìåòîäû</h5>
+    <p>Äàííàÿ ãðóïïà ìåòîäîâ âêëþ÷àåò â ñåáÿ ðàçíîîáðàçíûå âñïîìîãàòåëüíûå ìåòîäû, îáåñïå÷èâàþùèå âðåìåííîå
+      ïåðåêëþ÷åíèå ïîòîêà ââîäà íà äðóãîé îáúåêò.
+    </p>
+    <dl>
+      <dt><b>virtual const char* fname()</b></dt>
+      <dd>
+        Âûçîâ âîçâðàùàåò èìÿ îòêðûòîãî ôàéëà, åñëè äàííîìó îáúåêòó ââîäà èçâåñòíî ýòî èìÿ (íàïðèìåð, èñïîëüçóåòñÿ
+        <b>LibRaw_file_datastream</b>). Ýòî èìÿ èñïîëüçóåòñÿ â ñëåäóþùèõ ñëó÷àÿõ:
+        <ul>
+          <li>Ïåðåäàåòñÿ â ôóíêöèè íîòèôèêàöèè îá îøèáêàõ.</li>
+          <li>Èñïîëüçóþòñÿ äëÿ ãåíåðàöèè èìåíè JPEG-ôàéëà ñ ìåòàäàííûìè â ñîîòâåòñòâóþùèõ ñëó÷àÿõ (ôàéëû ñ êàìåð, ãäå
+            RAW-èçîáðàæåíèå ïîëó÷àåòñÿ ÷åðåç íåäîêóìåíòèðîâàííûå äèàãíîñòè÷åñêèå ôóíêöèè).
+        </ul>
+      </dd>
+      <dt><b>virtual int         subfile_open(const char *fn)</b></dt>
+      <dd>
+        Âûçîâ âðåìåííî ïåðåêëþ÷àåò ââîä íà ôàéë ñ èìåíåì fn. Ïðè óñïåõå âîçâðàùàåòñÿ 0, ïðè íåóñïåõå - íåíóëåâîå
+        çíà÷åíèå (íàïðèìåð, êîä îøèáêè).<br/>
+        Äàííûé âûçîâ èñïîëüçóåòñÿ ïðè ðàçáîðå JPEG-ôàéëîâ ñ ìåòàäàííûìè äëÿ êàìåð ñ "Diag RAW Hack".
+        <br/>
+        Äàííûé âûçîâ íå ðåàëèçîâàí â <a href="#buffer_datastream">LibRaw_buffer_datastream</a>,  ñîîòâåòñòâåííî
+        ðàçáîð âíåøíèõ ìåòàäàííûõ äëÿ ôàéëîâ, îòêðûòûõ ÷åðåç ýòîò èíòåðôåéñ - íåâîçìîæåí.
+        <br/>
+        Ñòàíäàðòíàÿ ðåàëèçàöèÿ ìåòîäà (ðåàëèçîâàííàÿ â áàçîâîì êëàññå) âñåãäà âîçâðàùàåò îøèáêó.
+        <br/>
+        Ïðèìåð ðàáîòàþùåé ðåàëèçàöèè ìîæíî ïîñìîòðåòü â ðåàëèçàöèè êëàññà
+        <a href="#file_datastream">LibRaw_file_datastream</a> â ôàéëå <b>libraw/libraw_datastream.h</b>.
+      </dd>
+      <dt><b>    virtual void subfile_close()</b></dt>
+      <dd>
+        Çàêðûâàåò âðåìåííî îòêðûòûé ôàéë ñ ìåòàäàííûìè, âîçâðàùàÿ ââîä íà èñõîäíûé ïîòîê äàííûõ.
+      </dd>
+      <dt><b>    virtual int		tempbuffer_open(void  *buf, size_t size)</b></dt>
+      <dd>
+        Âûçîâ âðåìåííî ïåðåêëþ÷àåò ââîä íà îáúåêò <a href="#buffer_datastream">LibRaw_buffer_datastream</a>,
+        ïîñòðîåííûé íà áóôåðå buf ðàçìåðà        size.<br/>
+        Ýòî ìåòîä íóæåí äëÿ ðåàëèçàöèè ðàçáîðà øèôðîâàíûõ ìåòàäàííûõ êàìåð Sony.
+        <p>
+          Ýòîò ìåòîä ðåàëèçîâàí â ðàìêàõ áàçîâîãî êëàññà, ïåðåîïðåäåëåíèå â ïðîèçâîäíûõ êëàññàõ íå òðåáóåòñÿ. Îäíàêî
+          íàëè÷èå è âîçìîæíàÿ àêòèâíîñòü âðåìåííîãî ïîòîêà äàííûõ òðåáóåò àêêóðàòíîãî ïðîãðàììèðîâàíèÿ ïðè ðåàëèçàöèè
+          ñîáñòâåííûõ ìåòîäîâ ââîäà-âûâîäà. Ïîäðîáíåå ýòî îïèñàíî â ðàçäåëå <a href="#substream">ðåàëèçàöèÿ
+            ñîáñòâåííûõ èíòåðôåéñîâ ÷òåíèÿ</a> íèæå.
+      </dd>
+      <dt><b>    virtual void	tempbuffer_close()</b></dt>
+      <dd>
+        Âûçîâ âîññòàíàâëèâàåò ââîä îáðàòíî íà ïîëíûé ïîòîê äàííûõ.
+      </dd>
+    </dl>
+    
+    <a name="datastream_derived"></a>
+    <h3>Ïðîèçâîäíûå êëàññû, âõîäÿùèå â LibRaw</h3>
+    <p>
+       Â ñîñòàâ LibRaw âõîäÿò äâà ñòàíäàðòíûõ êëàññà, ðåàëèçóþùèõ ââîä äàííûõ:
+    </p>
+    <ul>
+      <li><a href="#file_datastream">LibRaw_file_datastream</a> ðåàëèçóåò ââîä èç ôàéëà â ôàéëîâîé ñèñòåìå.</li>
+      <li><a href="#buffer_datastream">LibRaw_buffer_datastream</a> ðåàëèçóåò ââîä èç áóôåðà â ïàìÿòè.</li>
+    </ul>
+    <p>
+      Êðîìå òîãî, ïîëüçîâàòåëè C++-èíòåðôåéñà ìîãóò ðåàëèçîâûâàòü ñîáñòâåííûå ìåòîäû ÷òåíèÿ è èñïîëüçîâàòü èõ ÷åðåç
+      ìåòîä <a href="#open_datastream">LibRaw::open_datastream</a>, òðåáîâàíèÿ è îñîáåííîñòè ðåàëèçàöèè îïèñàíû íèæå.
+    </p>
+    <a name="file_datastream"></a>
+    <h4>class LibRaw_file_datastream - èíòåðôåéñ ÷òåíèÿ RAW-äàííûõ èç ôàéëà</h4>
+    <p>
+      Äàííûé êëàññ ðåàëèçóåò ââîä äàííûõ èç ôàéëà.
+    </p>
+    <p><b>Ìåòîäû êëàññà:</b></p>
+    <dl>
+      <dt><b>    LibRaw_file_datastream(const char *fname) </b></dt>
+      <dd>
+        Êîíñòðóêòîð: ñîçäàåò îáúåêò <b>LibRaw_file_datastream</b> äëÿ ôàéëà <b>fname</b>.<br/>
+        Ê ñîæàëåíèþ, â C++ íåëüçÿ íå ñîçäàòü îáúåêò â êîíñòðóêòîðå, ïîýòîìó ìîæåò áûòü ñîçäàí íåâàëèäíûé îáúåêò (äëÿ
+        íåñóùåñòâóþùåãî ôàéëà). Ðàáîòîñïîñîáíîñòü îáúåêòà ïðîâåðÿåòñÿ ìåòîäîì <b>valid()</b>, îïèñàííûì âûøå.
+      </dd>
+    </dl>
+    <p>
+      Âñå ïðî÷èå ìåòîäû êëàññà ïîëíîñòüþ ñîîòâåòñòâóþò <a href="#datastream_methods">îïèñàííûì âûøå</a>.<br/>
+      Äàííûé êëàññ ðåàëèçóåò âñå ìåòîäû, âêëþ÷àÿ fname()    è subfile_open().
+    </p>
+    <a name="buffer_datastream"></a>
+    <h4>class LibRaw_buffer_datastream - èíòåðôåéñ ÷òåíèÿ RAW-äàííûõ èç áóôåðà â ïàìÿòè</h4>
+    <p>
+      Äàííûé êëàññ ðåàëèçóåò ââîä äàííûõ èç áóôåðà â ïàìÿòè.
+    </p>
+    <p><b>Ìåòîäû êëàññà:</b></p>
+    <dl>
+      <dt><b>    LibRaw_buffer_datastream(void *buffer, size_t bsize)</b></dt>
+      <dd>
+        Êîíñòðóêòîð: ñîçäàåò îáúåêò íàä áóôåðîì            <b>buffer</b> ðàçìåðà <b>bsize</b>.<br/>
+        Âåðèôèöèðîâàòü âàëèäíîñòü ïåðåäàííîãî óêàçàòåëÿ íîðìàëüíî íåâîçìîæíî, îí ïðîâåðÿåòñÿ òîëüêî íà íîëü è -1.
+        Âàëèäíîñòü âñåõ ïðî÷èõ çíà÷åíèé - íà ñîâåñòè âûçâàâøåãî.
+      </dd>
+    </dl>
+    <p>
+      Âñå ïðî÷èå ìåòîäû êëàññà ïîëíîñòüþ ñîîòâåòñòâóþò <a href="#datastream_methods">îïèñàííûì âûøå</a>.<br/>
+      Äàííûé êëàññ íå ïîääåðæèâàåò  ìåòîäû fname() subfile_open(), ñëåäîâàòåëüíî ðàçáîð âíåøíèõ JPEG-ôàéëîâ
+      ñ ìåòàäàííûìè íåâîçìîæåí.
+    </p>
+    <a name="own_datastreams"></a>
+    <h3>Ñîçäàíèå ñîáñòâåííûõ èíòåðôåéñîâ ÷òåíèÿ</h3>
+    <p>
+      Äëÿ ñîçäàíèÿ ñîáñòâåííûõ èíòåðôåéñîâ ÷òåíèÿ íåîáõîäèìî ñäåëàòü êëàññ, ïðîèçâîäíûé îò
+      <b>LibRaw_abstract_datastream</b> è ðåàëèçîâàòü â íåì âñå ìåòîäû ÷òåíèÿ, îïèñàííûå âûøå.
+       êà÷åñòâå îáðàçöà ìîæíî èñïîëüçîâàòü ðåàëèçàöèþ ñòàíäàðòíûõ êëàññîâ, ïîñòàâëÿåìûõ ñ LibRaw,
+      ïîñìîòðåòü êîòîðóþ ìîæíî  â ôàéëå <b>libraw/libraw_datastream.h</b> â ïîñòàâêå (îáà ñòàíäàðòíûõ èíòåðôåéñà ââîäà
+      ðåàëèçîâàíû òîëüêî íà inline-ôóíêöèÿõ).
+    </p>
+    <a name="substream"></a>
+    <h4>Ïîëå substream: âòîðîé ïîòîê ÷òåíèÿ äàííûõ</h4>
+    <p>
+      Îòäåëüíîãî îïèñàíèÿ òðåáóåò ïîëå substream, êîòîðîå îáúÿâëåíî â áàçîâîì êëàññå è èñïîëüçóåòñÿ ïðè âðåìåííîì
+      ïåðåêëþ÷åíèè ââîäà íà äðóãîé ïîòîê äàííûõ. C++ íå äàåò ñðåäñòâ äëÿ êðàñèâîé ðåàëèçàöèè íóæíîé ôóíêöèîíàëüíîñòè,
+      ïîýòîìó ëþáîé ÷èòàþùèé ìåòîä ââîäà äîëæåí ñîäåðæàòü â íà÷àëå ïðèáëèçèòåëüíî òàêóþ ñòðîêó:<br/>
+      <b>int method(...args...){ if(substream) return substream-&gt;method(...args...)</b>. Íàïðèìåð:
+<pre>
+    virtual int eof() 
+    { 
+        if(substream) return substream-&gt;eof();
+....
+    virtual int scanf_one(const char *fmt, void* val) 
+    { 
+        if(substream) return substream-&gt;scanf_one(fmt,val);
+</pre>
+
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 10:08:29 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:58 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/API-datastruct-eng.html b/libfspotraw/LibRaw/doc/API-datastruct-eng.html
new file mode 100644
index 0000000..c097207
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/API-datastruct-eng.html
@@ -0,0 +1,1067 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw: Data Structures and Constants</title>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+  </head>
+
+  <body>
+    <a href=index-eng.html>[back to Index]</a>
+    <h1>LibRaw: Data Structures and Constants</h1>
+    <p>
+      LibRaw data structures are defined in header file libraw/libraw_types.h<br/>
+      Constants used in its work are defined in file libraw/libraw_const.h
+    </p>
+    <h2>Contents:</h2>
+    <ol>
+      <li><a href="#datastruct">Data structures</a>
+        <ol>
+          <li><a href="#libraw_data_t">libraw_data_t: Main Data Structure in LibRaw</a></li>
+          <li><a href="#libraw_iparams_t">Structure libraw_iparams_t: Main Parameters of the Image</a></li>
+          <li><a href="#libraw_image_sizes_t">Structure libraw_image_sizes_t: Image Dimensions</a></li>
+          <li><a href="#libraw_colordata_t">Structure libraw_colordata_t: Color Information</a></li>
+          <li><a href="#color_data_state_t">Structure  color_data_state_t: Description of Color Data Source</a></li>
+          <li><a href="#libraw_imgother_t">Structure  libraw_imgother_t: Other Parameters of the Image</a></li>
+          <li><a href="#libraw_thumbnail_t">Structure libraw_thumbnail_t: Description of Thumbnail</a></li>
+          <li><a href="#libraw_output_params_t">Structure libraw_output_params_t: Management of dcraw-Style Postprocessing</a>.</li>
+          <li><a href="#libraw_masked_t">Structure libraw_masked_t - black (masked) pixels data</a></li>
+          <li><a href="#libraw_processed_image_t">Stucture libraw_processed_image_t - result set for  dcraw_make_mem_image()/dcraw_make_mem_thumb() functions</a></li>
+        </ol>
+      </li>
+      <li>
+        <a href="#datastream">Input abstraction layer</a>
+        <ul>
+          <li><a href="#datastream_data">Data fields</a></li>
+        </ul>
+      </li>
+      <li><a href="#const">Constants</a>
+        <ol>
+          <li><a href="#LibRaw_errors">enum LibRaw_errors: Error Codes</a></li>       
+          <li><a href="#progress">enum LibRaw_progress: Current State of LibRaw Object</a></li>
+          <li><a href="#LibRaw_thumbnail_formats">enum LibRaw_thumbnail_formats: Thumbnail Data Formats</a></li>
+          <li><a href="#warnings">Nonstandard Situations (Warnings) during RAW Data Processing</a></li>
+          <li><a href="#LibRaw_colorstate">enum LibRaw_colorstate: Type of Color Data Source</a>.</li> 
+          <li><a href="#LibRaw_filtering">enum LibRaw_filtering - RAW data filtering settings</a></li> 
+          <li><a href="#LibRaw_image_formats">enum LibRaw_image_formats - possible types of data, contains in  libraw_processed_image_t structure</a>
+        </ol>
+      </li>
+    </ol>
+
+    <a name="datastruct"></a>
+    <h2>Data Structures</h2>
+    <a name="libraw_data_t"></a>
+    <h3>libraw_data_t: Main Data Structure of LibRaw</h3>
+    <p>
+      Structure libraw_data_t is a &quot;wrapping&quot; for data structures accessible to the user of the library.<br/>
+      When one uses C++ API, it is accessible as LibRaw::imgdata (class_instance.imgdata). The data in this structure appear after
+      a file is opened through open_file (and other open_ calls), except for the image itself (filled by unpack()) and data containing
+the preview information (filled by calling unpack_thumb()).<br/>
+     Data fields:
+    </p>
+    <dl>
+      <dt><b>unsigned int                progress_flags;</b></dt>
+      <dd>
+        This field records the past <a href="#progress">phases of image processing</a>.
+      </dd>
+      <dt><b>unsigned int                progress_flags;</b></dt>
+      <dd>
+        This field records <a href="#warnings">suspicious situations (warnings)</a> that have emerged during image processing.
+      </dd>
+      <dt><b>libraw_iparams_t            idata;</b></dt>
+      <dd>
+        The structure describes the main image parameters retrieved from the RAW file. Fields of this structure 
+are described in detail <a href="#libraw_iparams_t">below</a>.
+      </dd>
+      <dt><b>libraw_image_sizes_t        sizes;</b></dt>
+      <dd>
+        The structure describes the geometrical parameters of the image. Fields of this structure
+ are described in detail <a href="#libraw_image_sizes_t">below</a>.
+      </dd>
+      <dt><b>libraw_colordata_t          color;</b></dt>
+      <dd>
+   The structure contains color data retrieved from the file. Fields of this structure
+are described in detail <a href="#libraw_colordata_t">below</a>.
+      </dd>
+      <dt><b>libraw_imgother_t           other;</b></dt>
+      <dd>
+Data structure for information purposes: it contains the image parameters that have been extracted from the file but are
+not needed in further file processing. Fields of this structure are described in detail <a href="#libraw_imgother_t">below</a>.
+      </dd>
+      <dt><b>libraw_thumbnail_t          thumbnail;</b></dt>
+      <dd>
+        Data structure containing information on the preview and the preview data themselves. All fields of this
+        structure but thumbnail itself are filled when open_file() is called. Thumbnail readed by unpack_thumb() call.
+        The fields are described in detail <a href="#libraw_thumbnail_t">below</a>.
+      </dd>
+      <dt><b>libraw_masked_t             masked_pixels;</b></dt>
+      <dd>
+        Structure containing pixel data for black (masked) border pixels.
+        Fields of this structure are described <a href="#libraw_masked_t">below</a>. It is filled
+        when unpack() is called.
+        <p>
+          This field is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>
+
+      </dd>
+      <dt><b>ushort                      (*image)[4];</b></dt>
+      <dd>
+        The memory area that contains the image pixels per se. It is filled when unpack() is called. 
+      </dd>
+
+      <dt><b>libraw_output_params_t     params;</b></dt>
+      <dd>
+        Data structure intended for management of image postprocessing (using the dcraw emulator).
+Fields of this structure are described in detail <a href="#libraw_iparams_t">below</a>.
+      </dd>
+    </dl>
+    <a name="libraw_iparams_t"></a>
+    <h3> Structure libraw_iparams_t: Main Parameters of the Image</h3>
+    <p>
+
+    </p>
+    <dl>
+      <dt><b>char        make[64];</b></dt>
+      <dd>
+        Camera manufacturer.
+      </dd>
+      <dt><b>char        model[64];</b></dt>
+      <dd>
+        Camera model.
+      </dd>
+      <dt><b>unsigned    raw_count;</b></dt>
+      <dd>
+        Number of  RAW images in file (0 means that the file has not been recognized).
+      </dd>
+      <dt><b>unsigned    dng_version;</b></dt>
+      <dd>
+        DNG version (for the DNG format).
+      </dd>
+      <dt><b>unsigned    is_foveon;</b></dt>
+      <dd>
+        1 for Foveon matrices, 0 for others.
+        <p>
+          This field is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>      
+      </dd>
+      <dt><b>int         colors;</b></dt>
+      <dd>
+        Number of colors in the file.
+      </dd>
+      <dt><b>unsigned    filters;</b></dt>
+      <dd>
+        Bit mask describing the order of color pixels in the matrix (0 for Foveon). 32 bits of this field describe 16 pixels
+(8 rows with two pixels in each, from left to right and from top to bottom). Each two bits have values 0 to 3, which
+correspond to four possible colors. Convenient work with this field is ensured by the FC(row,column) function,
+which returns the number of the active color for a given pixel.
+      </dd>
+      <dt><b>char        cdesc[5];</b></dt>
+      <dd>
+        Description of colors numbered from 0 to 3 (RGBG,RGBE,GMCY, or GBTG). 
+      </dd>
+    </dl>
+    <a name="libraw_image_sizes_t"></a>
+    <h3>Structure libraw_image_sizes_t: Image Dimensions</h3>
+    <p>Structure libraw_image_sizes_t is a collection of all file data that describe the size of the image.<br/>
+      Data fields: 
+      </p>
+    <dl>
+      <dt><b>ushort    raw_height, raw_width;</b></dt>
+      <dd>
+        Full size of RAW image (including the frame) in pixels.
+      </dd>
+      <dt><b>ushort    height, width;</b></dt>
+      <dd>
+       Size of visible (&quot;meaningful&quot;) part of the image (without the frame). 
+      </dd>
+      <dt><b>ushort    top_margin, left_margin;</b></dt>
+      <dd>
+        Coordinates of the top left corner of the frame (the second corner is calculated from the full size of the image and size of its visible part).
+      </dd>
+      <dt><b>ushort    bottom_margin, right_margin;</b></dt>
+      <dd>
+        Width (in pixels) of bottom and right part of masked pixels area.
+      </dd>
+      <dt><b>ushort      iheight, iwidth;</b></dt>
+      <dd>
+        Size of the output image (may differ from height/width for cameras that require image rotation or have non-square pixels). 
+      </dd>
+      <dt><b>double      pixel_aspect;</b></dt>
+      <dd>
+      Pixel width/height ratio. If it is not unity, scaling of the image along one of the axes is required during output. 
+       </dd>
+      <dt><b>int         flip;</b></dt>
+      <dd>
+        Image orientation (0 if does not require rotation; 3 if requires 180-deg rotation; 5 if 90 deg counterclockwise, 6 if 90 deg clockwise). 
+      </dd>
+    </dl>
+    <a name="libraw_colordata_t"></a>
+    <h3>Structure libraw_colordata_t: Color Information</h3>
+    <p>Structure libraw_colordata_t unites all color data, both retrieved from the RAW file and calculated on the basis of the
+image itself. For different cameras, there are different ways of color handling. <br/>    
+     Data fields:
+    </p>
+    <dl>
+      <dt><b>color_data_state_t   color_flags;</b></dt>
+      <dd>
+        Data structure describing the sources of color data. Described <a href="#color_data_state_t">below</a> in more detail.
+        <p>
+          This field is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>      
+      </dd>
+      <dt><b>ushort      white[8][8];</b></dt>
+      <dd>
+     Block of white pixels extracted from files CIFF/CRW. Not extracted for other formats. Used to calculate white
+balance coefficients.
+      </dd>
+      <dt><b>float       cam_xyz[4][3]; </b></dt>
+      <dd>
+        Camera RGB - XYZ conversion matrix. This matrix is constant (different for different models).
+        Last row is zero for RGB cameras and non-zero for different color models (CMYG and so on).
+      </dd>
+      <dt><b>float       cam_mul[4]; </b></dt>
+      <dd>
+        White balance coefficients (as shot). Either read from file or calculated.
+      </dd>
+      <dt><b>float       pre_mul[4]; </b></dt>
+      <dd>
+        White balance coefficients for daylight (daylight balance). Either read from file, or calculated on the basis of file data, 
+or taken from hardcoded constants.
+      </dd>
+      <dt><b>float       cmatrix[3][4];</b></dt>
+      <dd>
+        White balance matrix. Read from file for some cameras, calculated for others.
+      </dd>
+      <dt><b>float       rgb_cam[3][4];</b></dt>
+      <dd>
+        Another white balance matrix, read from file for Leaf and Kodak cameras.
+      </dd>
+      <dt><b>ushort      curve[0x4001];</b></dt>
+      <dd>
+        Camera tone curve, read from file for Nikon, Sony and some other cameras.
+      </dd>
+      <dt><b>unsigned    black;</b></dt>
+      <dd>
+      Black level. Depending on the camera, it may be zero (this means that black has been subtracted at the unpacking stage 
+or by the camera itself), calculated at the unpacking stage, read from the RAW file, or hardcoded. 
+      </dd>
+      <dt><b>unsigned    maximum;</b></dt>
+      <dd>
+       Maximum pixel value. Calculated from the data for some cameras, hardcoded for others. 
+      </dd>
+      <dt><b>ph1_t       phase_one_data;</b></dt>
+      <dd>
+        Color data block that is read for Phase One cameras.
+      </dd>
+      <dt><b>float       flash_used;</b></dt>
+      <dt><b>float       canon_ev;</b></dt>
+      <dd>
+        Fields used for white balance calculations (for some P&amp;S Canon cameras).
+      </dd>
+      <dt><b>char          model2[64];</b></dt>
+      <dd>
+        White balance description for Foveon cameras.
+      </dd>
+      <dt><b>void    *profile;</b></dt>
+      <dd>
+        Pointer to the retrieved ICC profile (if it is present in the RAW file).
+      </dd>
+      <dt><b>unsigned    profile_length;</b></dt>
+      <dd>
+        Length of ICC profile in bytes.
+      </dd>
+    </dl>
+    <a name="color_data_state_t"></a>
+    <h3>Structure  color_data_state_t: Description of Color Data Source</h3>
+    <p>This structure (actually, a bit field) describes the source of color data for each field of structure <a
+ href="#libraw_colordata_t">libraw_colordata_t</a>, which may be obtained from different data sources.<br/>
+      Data fields:
+    </p>
+    <pre>
+        unsigned curve_state        : 3;
+        unsigned rgb_cam_state      : 3;
+        unsigned cmatrix_state      : 3;
+        unsigned pre_mul_state      : 3;
+        unsigned cam_mul_state      : 3;
+    </pre>
+    <p>
+   Each field assumes one of the values that are possible for enum <a href="#LibRaw_colorstate">LibRaw_colorstate</a>. 
+    </p>
+        <p>
+          This field is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>      
+    <a name="libraw_imgother_t"></a>
+    <h3>Structure  libraw_imgother_t: Other Parameters of the Image</h3>
+    <p>
+      Structure libraw_imgother_t is a collection of data that have been read from the RAW file but are not needed for image postprocessing.<br/>
+      Data fields:
+    </p>
+    <dl>
+      <dt><b>float       iso_speed; </b></dt>
+      <dd>
+        ISO sensitivity.
+      </dd>
+      <dt><b>float       shutter;</b></dt>
+      <dd>
+        Shutter speed.
+      </dd>
+      <dt><b>float       aperture;</b></dt>
+      <dd>
+        Aperture.
+      </dd>
+      <dt><b>float       focal_len;</b></dt>
+      <dd>
+        Focal length.
+      </dd>
+      <dt><b>time_t      timestamp; </b></dt>
+      <dd>
+        Date of shooting.
+      </dd>
+      <dt><b>unsigned    shot_order;</b></dt>
+      <dd>
+        Serial number of image.
+      </dd>
+      <dt><b>unsigned    gpsdata[32];</b></dt>
+      <dd>
+        GPS data.
+      </dd>
+      <dt><b>char        desc[512];</b></dt>
+      <dd>
+        Image description.
+      </dd>
+      <dt><b>char          artist[64];</b></dt>
+      <dd>
+        Author of image.
+      </dd>
+    </dl>
+    
+    <a name="libraw_thumbnail_t"></a>
+    <h3>Structure libraw_thumbnail_t: Description of Thumbnail</h3>
+    <p>Structure libraw_thumbnail_t describes all parameters associated with the preview saved in the RAW file.<br/>
+      Data fields:
+    </p>
+    <dl>
+      <dt><b>LibRaw_thumbnail_formats tformat;</b></dt>
+      <dd>
+        Thumbnail data format. One of the values among enum <a
+          href="#LibRaw_thumbnail_formats">LibRaw_thumbnail_formats</a>. 
+      </dd>
+      <dt><b>ushort      twidth, theight;</b></dt>
+      <dd>
+        Dimensions of the preview image in pixels.
+      </dd>
+      <dt><b>unsigned    tlength;</b></dt>
+      <dd>
+        Thumbnail length in bytes.
+      </dd>
+      <dt><b>int         tcolors;</b></dt>
+      <dd>
+        Number of colors in the preview.
+      </dd>
+      <dt><b>char       *thumb;</b></dt>
+      <dd>
+        Pointer to thumbmail, extracted from the data file.
+      </dd>
+    </dl>
+
+    <a name="libraw_output_params_t"></a>
+    <h3>Structure libraw_output_params_t: Management of dcraw-Style Postprocessing</h3>
+    <p>Structure libraw_output_params_t is used for management of dcraw-compatible calls dcraw_process(),
+      dcraw_ppm_tiff_writer(), dcraw_thumb_writer(), and dcraw_document_mode_processing(). Fields of this structure
+correspond to command line keys of dcraw.<br/>
+      Data fields:
+    </p>
+    <dl>
+      <dt><b>unsigned    greybox[4];</b></dt>
+      <dd>
+        <b>dcraw keys:</b> -A  x1 y1 x2 y2 <br/>
+       4 numbers corresponding to the coordinates (in pixels) of the rectangle that is used to calculate the white balance.
+      </dd>
+      <dt><b>double      aber[4];</b></dt>
+      <dd>
+        <b>dcraw keys:</b>         -C <br/>
+        Correction of chromatic aberrations; the only specified values are<br/>
+        aber[0], the red multiplier<br/>
+        aber[2], the green multiplier.
+        For some formats, it affects <a href=API-notes-eng.html>RAW data reading</a>, since correction of aberrations
+changes the output size.
+      </dd>
+      <dt><b>double      gamm[6];</b></dt>
+      <dd>
+        <b>dcraw keys:</b>         -g power toe_slope <br/>
+        Sets user gamma-curve. Library user should set first two fields of gamm array:<br/>
+        gamm[0] -  <b>inverted</b> gamma value)<br/>
+        gamm[1] - slope for linear part (so called toe slope). Set to zero for simple power curve.
+        <br/>
+        Remaining 4 values are filled automatically.
+        <p>
+          By default settings for rec. BT.709 are used: power 2.222 (i.e. gamm[0]=1/2.222) and slope 4.5. 
+          For sRGB curve use gamm[0]=1/2.4 and gamm[1]=12.92, for linear curve set gamm[0]/gamm[1] to 1.0.
+      </dd>
+      <dt><b>float       user_mul[4];</b></dt>
+      <dd>
+        <b>dcraw keys:</b>     -r mul0 mul1 mul2 mul3 <br/>
+        4 multipliers (r,g,b,g) of the user's white balance.
+      </dd>
+      <dt><b>unsigned    shot_select, multi_out;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>  -s <br/>
+        Selection of image number for processing (for formats that contain several RAW images in one file). The
+        multi_out ( -s all) mode should be programmed by the user, since dcraw_process() does not support it. 
+      </dd>
+      <dt><b>float       bright;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>          -b <br/>
+        Brightness (default 1.0).
+      </dd>
+      <dt><b>float       threshold;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>        -n <br/>
+        Parameter for noise reduction through wavelet denoising.
+      </dd>
+      <dt><b>int         half_size;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>       -h <br/>
+        Outputs the image in 50% size. For some formats, it affects <a href=API-notes-eng.html>RAW data reading</a>. 
+      </dd>
+      <dt><b>int         four_color_rgb;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>  -f <br/>
+     Switches on separate interpolations for two green components.
+      </dd>
+      <dt><b>int         document_mode;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>   -d/-D <br/>
+         0: standard processing (with white balance)<br/>
+         1: corresponds to -d (without color processing or debayer)<br/>
+         2: corresponds to -D (-d without white balance).
+      </dd>
+      <dt><b>int         highlight;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>       -H <br/>
+         0-9: Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild).
+      </dd>
+      <dt><b>int         use_auto_wb;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>     -a <br/>
+       Use automatic white balance obtained after averaging over the entire image.
+      </dd>
+      <dt><b>int         use_camera_wb;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>   -w <br/>
+        If possible, use the white balance from the camera.
+      </dd>
+      <dt><b>int         use_camera_matrix;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>  +M/-M <br/>
+        Use (1)/don't use camera color matrix.
+      </dd>
+      <dt><b>int         output_color;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>    -o <br/>
+        [0-5]  Output colorspace (raw, sRGB, Adobe, Wide, ProPhoto, XYZ).
+      </dd>
+      <dt><b>char*         output_profile;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>    -o filename<br/>
+        Path to output profile ICC file (used only if LibRaw compiled with LCMS support)
+      </dd>
+      <dt><b>char*         camera_profile;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>    -o file<br/>
+        Path to input (camera) profile ICC file (or 'embed' for embedded profile). Used only if LCMS support compiled in.
+      </dd>
+      <dt><b>char*         bad_pixels;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>    -P file<br/>
+        Path to file with bad pixels map (in dcraw format: "column row date-of-pixel-death-in-UNIX-format", one pixel
+        per row).
+      </dd>
+      <dt><b>char*         dark_frame;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>    -K file<br/>
+        Path to dark frame file (in 16-bit PGM format)
+      </dd>
+      <dt><b>enum LibRaw_filtering  filtering_mode;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>     none <br/>
+        Sets RAW data filtering mode (black level subtraction, zero pixels cleaning, tone curve processing)
+        See details in <a href=API-notes-eng.html#filtering>filtration modes description</a> and in 
+        <a href="#LibRaw_filtering">mode list below</a>.
+        <p>
+          This field is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>      
+      </dd>
+      <dt><b>int         output_bps;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>      -4 <br/>
+        8 bit (default)/16 bit (key -4).
+      </dd>
+      <dt><b>int         output_tiff;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>     -T <br/>
+        0/1: output PPM/TIFF.
+      </dd>
+      <dt><b>int         user_flip;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>       -t <br/>
+        [0-7]  Flip image (0=none, 3=180, 5=90CCW, 6=90CW).
+        Default -1, which means taking the corresponding value from RAW. <br/>
+        For some formats, <a href=API-notes-eng.html>affects RAW data reading</a>, e.g., unpacking of thumbnails
+      from Kodak cameras.
+      </dd>
+      <dt><b>int         user_qual;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>       -q <br/>
+        0-3: interpolation quality (0 - linear, 1- VNG, 2 - PPG, 3 - AHD). 
+      </dd>
+      <dt><b>int         user_black;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>      -k <br/>
+        User black level.
+      </dd>
+      <dt><b>int         user_sat;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>        -S <br/>
+        Saturation adjustment.
+      </dd>
+      <dt><b>int         med_passes;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>      -m <br/>
+        Number of median filter passes.
+      </dd>
+      <dt><b>int         no_auto_bright;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>  -W <br/>
+        Don't use automatic increase of brightness by histogram.
+      </dd>
+      <dt><b>float         auto_bright_thr;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>none<br/>
+        Portion of clipped pixels when auto brighness increase is used. Default value is 0.01 (1%) for dcraw
+        compatibility. Recommended value for modern low-noise multimegapixel cameras depends on shooting style. Values
+        in 0.001-0.00003 range looks reasonable.
+      </dd>
+      <dt><b>int         use_fuji_rotate;</b></dt>
+      <dd>
+        <b>dcraw keys:</b> -j <br/>
+         Default -1 (use), 0 - don't use rotation for cameras on a Fuji sensor.
+      </dd>
+      <dt><b>char        *bpfile;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>         -P <br/>
+        Name of file with bad pixel map.
+      </dd>
+      <dt><b>char        *dark_frame;</b></dt>
+      <dd>
+        <b>dcraw keys:</b>     -K <br/>
+         Name of file with dark frame.
+      </dd>
+    </dl>
+    <a name="libraw_masked_t"></a>
+    <h3>Structure libraw_masked_t - saved masked pixels (black frame) data</h3>
+    <p>
+      Structure libraw_masked_t designed for storing pixel data for dark frame (black or masked pixels, not included
+      in active image sensor area). These pixel values can be used for black level subtraction, noise and banding
+      removal and so on.<br/>
+      Unlike imgdata.image bitmap which has 4-component pixels, masked pixel data stored in 1-component 16-bit values.
+      Different parts of border are stored in different buffers within libraw_masked_t structure, see picture:
+    </p>
+    <center><img src=corner-scheme.png width="600" height="400" border=1/></center>
+    <p>
+      Data fields:
+    </p>
+    <dl>
+      <dt><b>ushort  *buffer;</b></dt>
+      <dd>Whole allocated buffer. Buffer size is (raw_width*raw_height - width*height).
+        </dd>
+      <dt><b>ushort  *tl;</b></dt>
+      <dd>Pointer to part of buffer designated for storing top-left corner of black frame.
+        Data size equal to (top_margin*left_margin).
+        </dd>
+      <dt><b>ushort  *top;</b></dt>
+      <dd>Pointer to part of buffer for storing top part of black frame. Size is (top_margin*width).
+      </dd>
+      <dt><b>ushort  *tr;</b></dt>
+      <dd>Pointer to right top corned data. Size is (top_margin*right_margin).
+        </dd>
+      <dt><b>ushort  *left;</b></dt>
+      <dd>Pointer to pixel data of left frame side. (left_margin*height) pixels.
+      </dd>
+      <dt><b>ushort  *right;</b></dt>
+      <dd>Right side of frame. (right_margin*height) pixels.
+      </dd>
+      <dt><b>ushort  *bl;</b></dt>
+      <dd>Bottom left corner of frame. (bottom_margin*left_margin) pixels.
+        </dd>
+      <dt><b>ushort  *bottom;</b></dt>
+      <dd>Bottom side of frame. Pixel count is (bottom_margin*width).
+      </dd>
+      <dt><b>ushort  *br;</b></dt>
+      <dd>Bottom right corner with (bottom_margin*right_margin) pixels.
+        </dd>
+      <dt><b>ushort  (*ph1_black)[2];</b</dt>
+      <dd>Buffer containing black level data, read from RAW file. Each item contains two elements, one for
+        left half-row, one for right half row. Number of items is equal to row count.
+        </dd>
+    </dl>
+    <p>Some cameras does not provide dark frame data. In this case buffer for frame data is not allocated and
+      all pointers are initialized to zero.
+      Also, structure data is not allocated if image is extracted into half-sized bitmap (i.e. if half_size,
+      wavelet threshold or aber[] fields is set in processing options).<br/>
+      Some cameras provides not full masked frame, but only several sides of it (only left and top for Canons, only
+      left and right for some Nikons and so on). In this case all structure fields are initialized, but allocated
+      size for this part of frame is equal to zero and corresponding size parameter (top_/left_/bottom_/right_margin)
+      is set too zero too.
+    </p>
+        <p>
+          This structure is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>      
+
+    <a name="libraw_processed_image_t"></a>
+    <h3>Stucture libraw_processed_image_t - result set for  dcraw_make_mem_image()/dcraw_make_mem_thumb() functions</h3>
+    <p>Structure libraw_processed_image_t is produced by call of dcraw_make_mem_image()/dcraw_make_mem_thumb() and contains
+      in-memory image of interpolated data or thumbnail.<br/>
+      Data fields:
+    </p>
+    <dl>
+      <dt><b>LibRaw_image_formats type</b></dt>
+      <dd> This field records type of data, containing in remaining fields of structure.
+        <ul>
+          <li><b>LIBRAW_IMAGE_BITMAP</b> - structure contains RGB bitmap. All metadata fields (see below) are valid
+            and describes image data.
+          <li><b>LIBRAW_IMAGE_JPEG</b> - structure contain in-memory image of JPEG file. Only type, data_size and
+            data fields are valid (and nonzero);
+        </ul>
+      </dd>
+      <dt><b>ushort height,width</b></dt>
+      <dd> Image size (in pixels). Valid only if  type==LIBRAW_IMAGE_BITMAP.</dd>
+      <dt><b>ushort colors, bits</b></dt>
+      <dd> Number of colors components (1 or 3) and color depth in bits (8 or 16). These fields are valid only  if
+        type==LIBRAW_IMAGE_BITMAP.
+        </dd>
+      <dt><b>ushort gamma_corrected</b></dt>
+      <dd> Is bitmap data gamma-corrected (always 1 for 8-bit data, may be 0 or 1 for 16-bit).
+        Valid only if  type==LIBRAW_IMAGE_BITMAP.</dd>
+      <dt><b>unsigned int data_size</b></dt>
+      <dd> Size of <b>data</b> field (in bytes). For bitmap image equal to (height*width*colors * (bits/8)). 
+        For JPEG image - exact JPEG size (i.e. extracted  thnumbnail size + JPEG header + EXIF header).
+      </dd>
+      <dt><b>unsigned char data[]</b></dt>
+      <dd> Data array itself. Should be interpreted as RGB triplets for bitmap type and as JPEG file for JPEG type.
+        </dd>
+      </dl>
+
+    <a name="datastream"></a>
+    <h2>Input abstraction layer</h2>
+    <p>
+      RAW data input (read) in LibRaw implemented by calling methods of object derived from 
+      <b>LibRaw_abstract_datastream</b> abstract class. Full list of methods is described in 
+        href="API-CXX-eng.html#datastream">C++ API reference</a>. 
+    </p>
+    <p>
+      There is two ready to use implementations of datastream objects:
+    </p>
+    <ul>
+      <li><a href="API-CXX-eng.html#file_datastream">LibRaw_file_datastream</a> - file input (filename provided 
+        to LibRaw).</li>
+      <li><a href="API-CXX-eng.html#buffer_datastream">LibRaw_buffer_datastream</a> - input from memory buffer.</li>
+    </ul>
+    <p>
+      LibRaw user can create own datastream object derived from 
+      <a href="API-CXX-eng.html#datastream">LibRaw_abstract_datastream</a>. For example, such object may
+      implement reading RAW data directly from camera (by remote interface). LibRaw can use these
+      objects via 
+      <a href="API-CXX-eng.html#open_datastream">LibRaw::open_datastream()</a> interface.
+    </p>
+    <p>
+      Datastreams can be used either via 
+      <a href="API-CXX-eng.html#open_datastream">LibRaw::open_datastream()</a> call (in this case datastream
+      object should be created an maintained by user) or via 
+      <a href="API-CXX-eng.html#open_file">LibRaw::open_file()</a> and
+      <a href="API-CXX-eng.html#open_buffer">LibRaw::open_buffer()</a> shortcuts.
+    </p>
+    <p>
+      Only <a href="API-CXX-eng.html">C++ API</a> users may use object-oriented interface and
+      implement own input interfaces. For <a href="API-C-eng.html">C API</a> users only
+      built-on <b>libraw_open_file()/libraw_open_buffer()</b> shortcuts are avaliable.
+    </p>
+    <a name="datastream_data"></a>
+    <h3>Data fields</h3>
+    <p>Definition:</p>
+    <pre>
+class LibRaw_abstract_datastream {
+...
+protected:
+    LibRaw_abstract_datastream *substream;
+}
+</pre>
+    <p><b>Description:</b>
+      Ojects derived from LibRaw_abstract_datastream always contains pointer to secondary data stream
+      (substream). This substream initialized internally when needed (really used only for Sony RAW data) and
+      used for temporary switch input stream to temporary memory buffer allocated internally in LibRaw.
+    </p>
+    <p>
+      Substream usage details described more precisely in 
+      <a href="API-CXX-eng.html#own_datastreams">own datastream objects creation guide</a>.
+    </p>
+
+    <a name="const"></a>
+    <h2>Constants</h2>
+    <a name=LibRaw_errors></a>
+    <h3>enum LibRaw_errors: Error Codes</h3>
+    <p>All functions returning integer numbers must return either errno or one of the following error codes (see also <a
+        href="API-notes-eng.html#errors">error code conventions</a>).</p>
+    <p><b>Fatal errors</b> (return of such an error code implies that file processing has to be terminated, since
+the state of data structures is unknown).</p>
+    <dl>
+      <dt><b> LIBRAW_UNSUFFICIENT_MEMORY</b></dt>
+      <dd>Attempt to get memory from the system has failed.<br/>
+      All allocated resources will be freed, <a href="API-CXX-eng.html#recycle">recycle()</a> will be called, and the LibRaw 
+object will be brought to the state &quot;right after creation.&quot;
+        </dd>
+    <dt><b>LIBRAW_DATA_ERROR</b></dt>
+      <dd>A fatal error emerged during data unpacking.<br/>
+        All allocated resources will be freed, <a href="API-CXX-eng.html#recycle">recycle()</a> will be called, and the LibRaw 
+object will be brought to the state &quot;right after creation.&quot;
+      </dd>
+    <dt><b>LIBRAW_IO_ERROR</b></dt>
+      <dd>A fatal error emerged during file reading (premature end-of-file encountered or file is corrupt).<br/>
+        All allocated resources will be freed, <a href="API-CXX-eng.html#recycle">recycle()</a> will be called, and the LibRaw 
+object will be brought to the state &quot;right after creation.&quot;
+        </dd>
+    <dt><b>LIBRAW_CANCELLED_BY_CALLBACK</b></dt>
+      <dd>Processing cancelled due to calling application demand (by returning nonzero code from 
+        <a  href=API-CXX-eng.html#progress">progress callback</a>).<br/>
+        All allocated resources will be freed, <a href="API-CXX-eng.html#recycle">recycle()</a> will be called, and
+        the LibRaw  object will be brought to the state &quot;right after creation.&quot;
+        </dd>
+    </dl>
+    <p><b>Non-Fatal Errors</b></p>
+    <dl>
+      <dt><b>LIBRAW_SUCCESS=0</b></dt>
+      <dd>No error; function terminated successfully.</dd>
+      <dt><b>LIBRAW_UNSPECIFIED_ERROR</b></dt>
+      <dd>An unknown error has been encountered. This code should never be generated.</dd>
+      <dt><b>LIBRAW_FILE_UNSUPPORTED</b></dt>
+      <dd>Unsupported file format (attempt to open a RAW file with a format unknown to the program).</dd>
+      <dt><b>LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE</b></dt>
+      <dd>Attempt to retrieve a RAW image with a number absent in the data file (only for formats supporting storage
+      of several images in a file).</dd>
+      <dt><b>LIBRAW_OUT_OF_ORDER_CALL</b></dt>
+      <dd>API functions have been called in wrong order (e.g., <a href="API-CXX-eng.html#unpack">unpack()</a> before
+        <a href="API-CXX-eng.html#open_file">open_file()</a>) or the previous stage has ended with an error (e.g.,
+         <a href="API-CXX-eng.html#unpack">unpack()</a> is called after <a
+          href="API-CXX-eng.html#open_file">open_file()</a> has returned an error).
+      </dd> 
+      <dt><b>LIBRAW_NO_THUMBNAIL</b></dt>
+      <dd>Returned upon an attempt to retrieve a thumbnail from a file containing no preview.</dd>
+      <dt><b>LIBRAW_UNSUPPORTED_THUMBNAIL</b></dt>
+      <dd>RAW file contains a preview of unsupported format.</dd>
+    </dl>
+
+    <a name="progress"></a>    
+    <h3>enum LibRaw_progress: Current State of LibRaw Object</h3>
+    <p>LibRaw::imgdata.progress_flags contains a bit mask describing all stages of file processing that have already been performed.
+    </p>
+    <p><b>File opening and RAW data extraction phase.</b></p>
+    <dl>
+      <dt><b>LIBRAW_PROGRESS_START=0</b></dt>
+      <dd>
+        Object just created, no processing carried out.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_OPEN</b></dt>
+      <dd>
+        File to be processed has been opened.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_IDENTIFY</b></dt>
+      <dd>
+        Data identification performed, format recognized, metadata extracted.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_SIZE_ADJUST</b></dt>
+      <dd>
+        Data sizes adjusted (for files that require such adjustment, namely, certain files from Kodak cameras). 
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_LOAD_RAW</b></dt>
+      <dd>
+        RAW data loaded.
+      </dd>
+    </dl>
+    <p><b>The following flags are set during usage of image processing that has been taken from dcraw.</b></p>
+    <dl>
+      <dt><b>LIBRAW_PROGRESS_REMOVE_ZEROES</b></dt>
+      <dd>
+        Zero values removed for cameras that require such removal (Panasonic cameras).
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_BAD_PIXELS</b></dt>
+      <dd>
+        Bad (dead) pixels removed.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_DARK_FRAME</b></dt>
+      <dd>
+        Dark frame subtracted from RAW data.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_FOVEON_INTERPOLATE</b></dt>
+      <dd>
+        Interpolation for cameras with a Foveon sensor performed.
+        <p>
+          This progress stage is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>      
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_SCALE_COLORS</b></dt>
+      <dd>
+        White balance performed.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_PRE_INTERPOLATE</b></dt>
+      <dd>
+       Image size reduction (for the half_size mode) performed, as well as copying of 2nd green channel to the 1st one in points
+    where the second channel is present and the first one is absent. 
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_INTERPOLATE</b></dt>
+      <dd>
+        Interpolation (debayer) performed.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_MIX_GREEN</b></dt>
+      <dd>
+        Averaging of green channels performed.
+       </dd>
+      <dt><b>LIBRAW_PROGRESS_MEDIAN_FILTER</b></dt>
+      <dd>
+        Median filtration performed.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_HIGHLIGHTS</b></dt>
+      <dd>
+        Work with highlights performed.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_FUJI_ROTATE</b></dt>
+      <dd>
+        For images from Fuji cameras, rotation performed (or adjust_sizes_info_only() called).
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_FLIP</b></dt>
+      <dd>
+        Dimensions recalculated for images shot with a rotated camera (sizes.iwidth/sizes.iheight swapped).
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_CONVERT_RGB</b></dt>
+      <dd>
+        Conversion into output RGB space performed.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_STRETCH</b></dt>
+      <dd>
+        Image dimensions changed for cameras with non-square pixels.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_STAGE17 - LIBRAW_PROGRESS_STAGE27</b></dt>
+      <dd>
+        Reserved for possible appearance of other processing stages.
+      </dd>
+    </dl>
+    <p><b>The following flags are set during loading of thumbnails.</b></p>
+      <dt><b>LIBRAW_PROGRESS_THUMB_LOAD</b></dt>
+      <dd>
+        Thumbnail data have been loaded (for Kodak cameras, the necessary conversions have also been made).
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_TRESERVED1 - LIBRAW_PROGRESS_TRESERVED3</b></dt>
+      <dd>
+        Reserved for possible future processing stages.
+      </dd>
+    </dl>
+    
+    <a name="LibRaw_thumbnail_formats"></a>
+    <h3>enum LibRaw_thumbnail_formats: Thumbnail Data Formats</h3>
+    <p>Thumbnail data format is written in the imgdata.thumbnail.tformat data field.<br/>
+      Presently LibRaw knows about four thumbnail formats, among which two are unpacked:
+    </p>
+    <dl>
+      <dt><b>LIBRAW_THUMBNAIL_UNKNOWN</b></dt>
+      <dd>Format unknown or thumbnail  not yet read.
+      </dd>
+      <dt><b>LIBRAW_THUMBNAIL_JPEG</b></dt>
+      <dd>The thumbnail buffer contains a JPEG file (read from the RAW file &quot;as is,&quot; without any manipulations performed on it). 
+      </dd>
+      <dt><b>LIBRAW_THUMBNAIL_BITMAP</b></dt>
+      <dd>
+        The thumbnail buffer contains the gamma-adjusted RGB bitmap (for Kodak cameras, the gamma correction is performed with allowance
+       for maximum values and the white balance is set in accordance with the camera settings).<br/>
+        In this format, each pixel of the image is represented by a 8-bit RGB triplet.
+      </dd>
+      <dt><b>LIBRAW_THUMBNAIL_LAYER</b></dt>
+      <dd>
+        Data format is presently recognized upon opening of RAW file but not supported: not unpacked into LibRaw::unpack_thumb.
+      </dd>
+      <dt><b>LIBRAW_THUMBNAIL_ROLLEI</b></dt>
+      <dd>
+        Data format is presently recognized upon opening of RAW file but not supported: not unpacked into LibRaw::unpack_thumb. 
+      </dd>
+    </dl>
+    <a name="warnings"></a>
+    <h3>Nonstandard Situations (Warnings) during RAW Data Processing</h3>
+    <p>Some suspicious situations emerging during image processing are not fatal but may affect the result of data
+retrieval or postprocessing. Such states are indicated by setting a bit in the imgdata.process_warnings field.</p>
+    <dl>
+      <dt><b>LIBRAW_WARN_FOVEON_NOMATRIX</b></dt>
+      <dd>
+      Only for cameras with Foveon: extraction of one of data matrices has failed.
+        <p>
+          This warning is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>      
+      </dd>
+      <dt><b>LIBRAW_WARN_FOVEON_INVALIDWB</b></dt>
+      <dd>
+        Only for cameras with Foveon: extraction of white balance data has failed.
+        <p>
+          This warning is not present in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>      
+      </dd>
+      <dt><b>LIBRAW_WARN_BAD_CAMERA_WB</b></dt>
+      <dd>
+       Postprocessing must use white balance of the camera but this balance is not suitable for use.
+      </dd>
+      <dt><b>LIBRAW_WARN_NO_METADATA</b></dt>
+      <dd>
+        Only for cameras where the metadata are taken from an external JPEG file: metadata extraction has failed.
+      </dd>
+      <dt><b>LIBRAW_WARN_NO_JPEGLIB</b></dt>
+      <dd>
+        Only for P&S Kodak cameras: data in JPEG format. At the same time, open_file() will return LIBRAW_FILE_UNSUPPORTED.
+     </dd>
+      <dt><b>LIBRAW_WARN_NO_EMBEDDED_PROFILE</b></dt>
+      <dd>
+        (only if LCMS support compiled in).
+        Caller set embedded input profile use, but no such profile exists in RAW.
+      </dd>
+      <dt><b>LIBRAW_WARN_NO_INPUT_PROFILE</b></dt>
+      <dd>
+        (only if LCMS support compiled in).
+        Error when opening input profile ICC file.
+      </dd>
+      <dt><b>LIBRAW_WARN_BAD_OUTPUT_PROFILE</b></dt>
+      <dd>
+        (only if LCMS support compiled in).
+        Error when opening output profile ICC file.
+      </dd>
+      <dt><b>LIBRAW_WARN_NO_BADPIXELMAP</b></dt>
+      <dd>
+        Error when opening bad pixels map file.
+      </dd>
+      <dt><b>LIBRAW_WARN_BAD_DARKFRAME_FILE</b></dt>
+      <dd>
+        Error when opening dark frame file.
+      </dd>
+      <dt><b>LIBRAW_WARN_BAD_DARKFRAME_DIM</b></dt>
+      <dd>
+        Dark frame file either differs in dimensions from RAW-file processed, or have wrong format.
+        Dark frame should be in 16-bit PGM format (one can generate it using simple_dcraw -4 -D).
+      </dd>
+    </dl>
+    <a name="LibRaw_filtering"></a>
+    <h3>enum LibRaw_filtering - RAW data filtering settings</h3>
+    <p>
+      This enum describes possible RAW data filtration modes during data unpacking and postprocessing.
+      Usage recommendations are described in <a href="API-notes-eng.html#filtering">API comments</a>. 
+      Filtering mode should be set by altering <b>filtering_mode</b> option before 
+      <a href="API-CXX-eng.html#unpack">unpack()</a> is called.
+    </p>
+        <p>
+          There is no RAW data filtering control in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>      
+    <dl>
+      <dt><b>LIBRAW_FILTERING_DEFAULT</b></dt>
+      <dd>Default value: dcraw filtration mode (for compatibility with previous LibRaw versions without
+        data filtering options).
+      </dd>
+      <dt><b>LIBRAW_FILTERING_NOZEROES</b></dt>
+      <dd>
+        If this bit set, then zero values in RAW data will not be cleared (averaged). Zero averaging
+        is needed for some cameras, such as Point-and-Shot Canon cameras, Panasonic cameras and some other.
+      </dd>
+      <dt><b>LIBRAW_FILTERING_NOBLACK</b></dt>
+      <dd>
+        If this bit is set, then no black level subtraction will be done on unpacking stage (for cameras
+        with black subtraction on unpacking stage: e.g. Canon cameras). Also, if this bit is set, then 
+        automatically calculated black level (this value is subtracted on postprocessing stage) is set
+        to zero. This bit does not affects black subtraction set via <b>user_black</b> option.
+      </dd>
+      <dt><b>LIBRAW_FILTERING_NORAWCURVE</b></dt>
+      <dd>
+        This bit turns off tone curve processing (for tone curves read from file metadata or calculated from
+        constants). This setting is supported only for bayer-pattern cameras with tone curve;
+      </dd>
+      <dt><b>LIBRAW_FILTERING_NONE</b></dt>
+      <dd>
+        Equal to  (LIBRAW_FILTERING_NOZEROES|LIBRAW_FILTERING_NOBLACK|LIBRAW_FILTERING_NORAWCURVE)
+      </dd>
+      <dt><b>LIBRAW_FILTERING_LIBRAWOWN</b></dt>
+      <dd>
+        This bit turns on LibRaw specialized functions for data filtering. These funcions will be made
+        individually for each camera model (and, possibly, firmware version). For now, no such subroutines
+        ready, so this parameter is reserved for future.
+      </dd>
+      <dt><b>LIBRAW_FILTERING_AUTOMATIC</b></dt>
+      <dd>
+        Equals to LIBRAW_FILTERING_LIBRAWOWN with fallback to LIBRAW_FILTERING_DEFAULT if no
+        specialized filtering function exists for given camera. 
+      </dd>
+      <dt><b>LIBRAW_FILTERING_AUTOMATIC_BIT</b></dt>
+      <dd>
+        This bit reserved for LIBRAW_FILTERING_AUTOMATIC support.
+      </dd>
+    </dl>
+    <p>
+      Best possible setting for common RAW-processing software is LIBRAW_FILTERING_AUTOMATIC. 
+      For RAW analyzers we recommend use LIBRAW_FILTERING_NONE or LIBRAW_FILTERING_NOBLACK.
+    </p>
+
+    <a name="LibRaw_colorstate"></a>
+    <h3>enum LibRaw_colorstate:  Types of Color Data Source</h3>
+    <p>For each type of retrieved color information (see above for description of structure imgdata.color.color_flags), the
+data source is recorded. The possible values are listed below. 
+    </p>
+    <dl>
+      <dt><b>LIBRAW_COLORSTATE_UNKNOWN</b></dt>  
+      <dd>
+        Data source unknown.
+      </dd>
+      <dt><b>LIBRAW_COLORSTATE_INIT</b></dt>  
+      <dd>
+        Data field initialized by default (the same value for all cameras) before opening the RAW file.
+      </dd>
+      <dt><b>LIBRAW_COLORSTATE_CONST</b></dt>    
+      <dd>
+        Data source is a hardcoded constant.
+      </dd>
+      <dt><b>LIBRAW_COLORSTATE_LOADED</b></dt>   
+      <dd>
+        Data loaded from RAW file.
+      </dd>
+      <dt><b>LIBRAW_COLORSTATE_CALCULATED</b></dt>
+      <dd>
+        Data calculated on the basis of RAW data.
+      </dd>
+      <dt><b>LIBRAW_COLORSTATE_RESERVED1-LIBRAW_COLORSTATE_RESERVED3</b></dt>
+      <dd>
+        Reserved.
+      </dd>
+    </dl>
+    <a name="LibRaw_image_formats"></a>
+    <h3>enum LibRaw_image_formats - possible types of data, contains in  libraw_processed_image_t structure</h3>
+    <p><b>type</b> field of  libraw_processed_image_t structure may have one of these values:
+      </p>
+    <dl>
+      <dt><b>LIBRAW_IMAGE_BITMAP</b></dt>    
+      <dd>
+        The structure contains RGB-bitmap, metadata described in other fields of  libraw_processed_image_t.
+      </dd>
+      <dt><b>LIBRAW_IMAGE_JPEG</b></dt>    
+      <dd>
+        libraw_processed_image_t structure contains JPEG image (in memory). Only data_size field is meaningful.
+      </dd>
+    </dl>
+
+
+    <a href=index-eng.html>[back to Index]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 14:42:41 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Fri Jun  5 11:55:11 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/API-datastruct-rus.html b/libfspotraw/LibRaw/doc/API-datastruct-rus.html
new file mode 100644
index 0000000..341d9aa
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/API-datastruct-rus.html
@@ -0,0 +1,1099 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw: ñòðóêòóðû äàííûõ è êîíñòàíòû</title>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+  </head>
+
+  <body>
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <h1>LibRaw: ñòðóêòóðû äàííûõ è êîíñòàíòû</h1>
+    <p>
+      Ñòðóêòóðû äàííûõ LibRaw îïðåäåëåíû â çàãîëîâî÷íîì ôàéëå libraw/libraw_types.h<br/>
+      Èñïîëüçóåìûå êîíñòàíòû îïðåäåëåíû â ôàéëå libraw/libraw_const.h
+    </p>
+    <h2>Ñîäåðæàíèå:</h2>
+    <ol>
+    <li><a href="#datastruct">Ñòðóêòóðû äàííûõ</a>
+        <ol>
+          <li><a href="#libraw_data_t">libraw_data_t - îñíîâíàÿ ñòðóêòóðà äàííûõ LibRaw</a></li>
+          <li><a href="#libraw_iparams_t">Ñòðóêòóðà libraw_iparams_t - îñíîâíûå ïàðàìåòðû èçîáðàæåíèÿ</a></li>
+          <li><a href="#libraw_image_sizes_t">Ñòðóêòóðà libraw_image_sizes_t - ðàçìåðû èçîáðàæåíèÿ</a></li>
+          <li><a href="#libraw_colordata_t">Ñòðóêòóðà libraw_colordata_t - èíôîðìàöèÿ î öâåòå</a></li>
+          <li><a href="#color_data_state_t">Ñòðóêòóðà  color_data_state_t - îïèñàíèå èñòî÷íèêà öâåòîâûõ äàííûõ</a></li>
+          <li><a href="#libraw_imgother_t">Ñòðóêòóðà  libraw_imgother_t - ïðî÷èå ïàðàìåòðû èçîáðàæåíèÿ</a></li>
+          <li><a href="#libraw_thumbnail_t">Ñòðóêòóðà libraw_thumbnail_t - îïèñàíèå Thumbnail</a></li>
+          <li><a href="#libraw_output_params_t">Ñòðóêòóðà libraw_output_params_t - óïðàâëåíèå ïîñòîáðàáîòêîé â ñòèëå
+              dcraw</a></li>
+          <li><a href="#libraw_masked_t">Ñòðóêòóðà libraw_masked_t - ñîõðàíåííûå çíà÷åíèÿ ïèêñåëîâ ÷åðíîé ðàìêè
+              (ìàñêèðîâàííûõ ïèêñåëîâ)</a></li>
+        <li><a href="#libraw_processed_image_t">Ñòðóêòóðà libraw_processed_image_t - äàííûå, âûâîäèìûå ôóíêöèÿìè
+              dcraw_make_mem_image()/dcraw_make_mem_thumb()</a></li> 
+        </ol>
+      </li>
+      <li><a href="#datastream">Îáúåêòû àáñòðàêöèè ââîäà äàííûõ</a>
+        <ul>
+            <li><a href="#datastream_data">Ïîëÿ äàííûõ</a></li>
+        </ul>
+      </li>
+      <li><a href="#const">Êîíñòàíòû</a>
+        <ol>
+          <li><a href="#LibRaw_errors">enum LibRaw_errors - êîäû îøèáîê</a></li>
+          <li><a href="#warnings">Íåøòàòíûå ñèòóàöèè (warnings) âîçíèêàþùèå ïðè îáðàáîòêå RAW-äàííûõ</a></li>
+          <li><a href="#progress">enum LibRaw_progress - òåêóùåå ñîñòîÿíèå îáúåêòà LibRaw</a></li>
+          <li><a href="#LibRaw_thumbnail_formats">enum LibRaw_thumbnail_formats - ôîðìàòû äàííûõ Thumbnails</a></li>
+          <li><a href="#LibRaw_colorstate">enum LibRaw_colorstate - îïèñàíèå èñòî÷íèêà äàííûõ î öâåòîâîé
+              èíôîðìàöèè</a></li> 
+          <li><a href="#LibRaw_filtering">enum LibRaw_filtering - íàñòðîéêè ôèëüòðàöèè äàííûõ íà ýòàïå ðàñïàêîâêè è
+              ïîñòîáðàáîòêè</a></li> 
+          <li><a href="#LibRaw_image_formats">enum LibRaw_image_formats - îïèñàíèå òèïîâ äàííûõ, ñîäåðæàùèõñÿ â
+              ñòðóêòóðå libraw_processed_image_t</a> </li>
+        </ol>
+      </li>
+    </ol>
+
+    <a name="datastruct"></a>
+    <h2>Ñòðóêòóðû äàííûõ</h2>
+    <a name="libraw_data_t"></a>
+    <h3>libraw_data_t - îñíîâíàÿ ñòðóêòóðà äàííûõ LibRaw</h3>
+    <p>
+      Ñòðóêòóðà libraw_data_t - ýòî "îáåðòêà" äëÿ ñòðóêòóð äàííûõ, äîñòóïíûõ ïîëüçîâàòåëþ áèáëèîòåêè.<br/>
+      Ïðè èñïîëüçîâàíèè C++ API îíà äîñòóïíà êàê LibRaw::imgdata (ýêçåìïëÿð_êëàññà.imgdata). Äàííûå â ýòîé ñòðóêòóðå
+      ïîÿâëÿþòñÿ ïîñëå îòêðûòèÿ ôàéëà ÷åðåç open_file, çà èñêëþ÷åíèåì ñîáñòâåííî èçîáðàæåíèÿ (çàïîëíÿåòñÿ ïî unpack())
+      è äàííûõ ñîäåðæàùèõ preview-äàííûå (çàïîëíÿþòñÿ ïî âûçîâó unpack_thumb())<br/>
+      Ïîëÿ äàííûõ:
+    </p>
+    <dl>
+      <dt><b>unsigned int                progress_flags;</b></dt>
+      <dd>
+        Â ýòîì ïîëå ôèêñèðóþòñÿ ïðîâåäåííûå <a href="#progress">ôàçû îáðàáîòêè èçîáðàæåíèÿ</a>.
+      </dd>
+      <dt><b>unsigned int                progress_flags;</b></dt>
+      <dd>
+        Â ýòîì ïîëå ôèêñèðóþòñÿ <a href="#warnings">ïîäîçðèòåëüíûå ñèòóàöèè (warnings)</a>, âîçíèêøèå ïðè îáðàáîòêå èçîáðàæåíèÿ.
+      </dd>
+      <dt><b>libraw_iparams_t            idata;</b></dt>
+      <dd>
+         ýòîé ñòðóêòóðå îïèñàíû èçâëå÷åííûå èç RAW-ôàéëà îñíîâíûå ïàðàìåòðû  èçîáðàæåíèÿ. 
+        Äåòàëüíî ïîëÿ ñòðóêòóðû îïèñàíû <a href="#libraw_iparams_t">íèæå</a>.
+      </dd>
+      <dt><b>libraw_image_sizes_t        sizes;</b></dt>
+      <dd>
+         ýòîé ñòðóêòóðå îïèñàíû ãåîìåòðè÷åñêèå ïàðàìåòðû èçîáðàæåíèÿ.
+        Äåòàëüíî ïîëÿ ñòðóêòóðû îïèñàíû <a href="#libraw_image_sizes_t">íèæå</a>.
+      </dd>
+      <dt><b>libraw_colordata_t          color;</b></dt>
+      <dd>
+         ýòîé ñòðóêòóðå íàõîäÿòñÿ èçâëå÷åííûå èç ôàéëà öâåòîâûå äàííûå.
+        Äåòàëüíî ïîëÿ ñòðóêòóðû îïèñàíû <a href="#libraw_colordata_t">íèæå</a>.
+      </dd>
+      <dt><b>libraw_imgother_t           other;</b></dt>
+      <dd>
+        Èíôîðìàöèîííàÿ ñòðóêòóðà äàííûõ, â íåå ïîìåùàþòñÿ èçâëå÷åííûå èç ôàéëà ïàðàìåòðû èçîáðàæåíèÿ, êîòîðûå íå íóæíû
+        ïðè äàëüíåéøåé îáðàáîòêå ôàéëà.
+        Äåòàëüíî ïîëÿ ñòðóêòóðû îïèñàíû <a href="#libraw_imgother_t">íèæå</a>.
+      </dd>
+      <dt><b>libraw_thumbnail_t          thumbnail;</b></dt>
+      <dd>
+        Ñòðóêòóðà äàííûõ, ñîäåðæàùàÿ èíôîðìàöèþ î preview è ñàìè äàííûå preview.
+        Âñå ïîëÿ ñòðóêòóðû êðîìå ñîáñòâåííî äàííûõ preview çàïîëíÿþòñÿ â 
+        <a href="API-CXX-rus.html#open_file">open_file()</a> èëè äðóãèõ âûçîâàõ îòêðûòèÿ ïîòîêà
+        (open_buffer(),open_datastream()), ñàìî èçîáðàæåíèå-preview ñ÷èòûâàåòñÿ îòäåëüíûì âûçîâîì 
+        <a href="API-CXX-rus.html#unpack_thumb">unpack_thumb()</a>.
+        Äåòàëüíî ïîëÿ ñòðóêòóðû îïèñàíû <a href="#libraw_thumbnail_t">íèæå</a>.
+      </dd>
+      <dt><b>libraw_masked_t             masked_pixels;</b></dt>
+      <dd>
+        Ñòðóêòóðà äàííûõ, ñîäåðæàùàÿ ïèêñåëû "òåìíîé ðàìêè" (ìàñêèðîâàííûõ ïèêñåëîâ).
+        Ïîëÿ ñòðóêòóðû äåòàëüíî îïèñàíû <a href="#libraw_masked_t">íèæå</a>. Ñòðóêòóðà çàïîëíÿåòñÿ
+        íà ýòàïå ÷òåíèÿ äàííûõ <a href="API-CXX-rus.html#unpack">unpack()</a>.
+        <br/>
+        Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> ýòî ïîëå äàííûõ îòñóòñòâóåò.
+      </dd>
+      <dt><b>ushort                      (*image)[4];</b></dt>
+      <dd>
+        Ðåãèîí ïàìÿòè, ñîäåðæàùèé ñîáñòâåííî ïèêñåëè èçîáðàæåíèÿ, çàïîëíÿåòñÿ ïðè âûçîâå unpack();
+      </dd>
+      <dt><b>libraw_output_params_t     params;</b></dt>
+      <dd>
+        Ñòðóêòóðà äàííûõ, ïðåäíàçíà÷åííàÿ äëÿ óïðàâëåíèÿ ïîñò-îáðàáîòêîé èçîáðàæåíèÿ (ïðè èñïîëüçîâàíèè ýìóëÿòîðà
+        dcraw).
+        Äåòàëüíî ïîëÿ ñòðóêòóðû îïèñàíû <a href="#libraw_iparams_t">íèæå</a>.
+      </dd>
+    </dl>
+    <a name="libraw_iparams_t"></a>
+    <h3> Ñòðóêòóðà libraw_iparams_t - îñíîâíûå ïàðàìåòðû èçîáðàæåíèÿ</h3>
+    <p>
+
+    </p>
+    <dl>
+      <dt><b>char        make[64];</b></dt>
+      <dd>
+        Èçãîòîâèòåëü êàìåðû.
+      </dd>
+      <dt><b>char        model[64];</b></dt>
+      <dd>
+        Ìîäåëü êàìåðû.
+      </dd>
+      <dt><b>unsigned    raw_count;</b></dt>
+      <dd>
+        Êîëè÷åñòâî  RAW-èçîáðàæåíèé â ôàéëå (0 - îçíà÷àåò ÷òî ôàéë íå ðàñïîçíàí).
+      </dd>
+      <dt><b>unsigned    dng_version;</b></dt>
+      <dd>
+        Âåðñèÿ DNG (äëÿ DNG-ôîðìàòà).
+      </dd>
+      <dt><b>unsigned    is_foveon;</b></dt>
+      <dd>
+        1 äëÿ ìàòðèö Foveon, 0 - äëÿ îñòàëüíûõ.
+        <br/>
+        Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> ýòî ïîëå äàííûõ îòñóòñòâóåò.
+      </dd>
+      <dt><b>int         colors;</b></dt>
+      <dd>
+        Êîëè÷åñòâî öâåòîâ â ôàéëå.
+      </dd>
+      <dt><b>unsigned    filters;</b></dt>
+      <dd>
+        Áèòîâàÿ ìàñêà, îïèñûâàþùàÿ ïîðÿäîê öâåòîâûõ ïèêñåëåé â ìàòðèöå (0 - äëÿ Foveon). 32 áèòà ïîëÿ îïèñûâàþò 16
+        ïèêñåëîâ (8 ñòðîê ïî 2 ïèêñåëà, ñëåâà íàïðàâà è ñâåðõó âíèç), êàæäûå äâà áèòà èìåþò çíà÷åíèÿ îò 0 äî 3,
+        ñîîòâåòñòâóþùèå 4-ì âîçìîæíûì öâåòàì. Äëÿ óäîáíîé ðàáîòû ñ ýòèì ïîëåì ïðåäíàçíà÷åíà ôóíêöèÿ FC(row,column)
+        âîçâðàùàþùàÿ íîìåð àêòèâíîãî öâåòà äëÿ äàííîãî ïèêñåëà.
+      </dd>
+      <dt><b>char        cdesc[5];</b></dt>
+      <dd>
+        Îïèñàíèå öâåòîâ ñ íîìåðàìè 0-3 (RGBG,RGBE,GMCY èëè GBTG).
+      </dd>
+    </dl>
+    <a name="libraw_image_sizes_t"></a>
+    <h3>Ñòðóêòóðà libraw_image_sizes_t - ðàçìåðû èçîáðàæåíèÿ</h3>
+    <p>Â ñòðóêòóðó libraw_image_sizes_t ñîáðàíû âñå äàííûå èç ôàéëà, îïèñûâàþùèå ðàçìåðû èçîáðàæåíèÿ.<br/>
+      Ïîëÿ äàííûõ:
+      </p>
+    <dl>
+      <dt><b>ushort    raw_height, raw_width;</b></dt>
+      <dd>
+        Ïîëíûé ðàçìåð RAW-èçîáðàæåíèÿ (âêëþ÷àÿ ðàìêó) â ïèêñåëàõ.
+      </dd>
+      <dt><b>ushort    height, width;</b></dt>
+      <dd>
+        Ðàçìåð âèäèìîé (ñîäåðæàòåëüíîé) ÷àñòè èçîáðàæåíèÿ (áåç ðàìêè).
+      </dd>
+      <dt><b>ushort    top_margin, left_margin;</b></dt>
+      <dd>
+        Êîîðäèíàòû âåðõíåãî ëåâîãî óãëà ðàìêè (âòîðîé óãîë ðàññ÷èòûâàåòñÿ èñõîäÿ èç ïîëíîãî ðàçìåðà èçîáðàæåíèÿ è
+        ðàçìåðà âèäèìîé ÷àñòè).
+      </dd>
+      <dt><b>ushort    bottom_margin, right_margin;</b></dt>
+      <dd>
+        Øèðèíà â ïèêñåëàõ íèæíåé è ïðàâîé ÷àñòè ÷åðíîé ðàìêè (ìàñêèðîâàííûõ ïèêñåëîâ).
+      </dd>
+      <dt><b>ushort      iheight, iwidth;</b></dt>
+      <dd>
+        Ðàçìåð âûõîäíîãî èçîáðàæåíèÿ (ìîæåò îòëè÷àòüñÿ îò height/width äëÿ êàìåð, ãäå òðåáóåòñÿ ïîâîðîò èçîáðàæåíèÿ,
+        ëèáî ãäå ïèêñåëè íåêâàäðàòíûå).
+      </dd>
+      <dt><b>double      pixel_aspect;</b></dt>
+      <dd>
+        Îòíîøåíèå øèðèíû ïèêñåëÿ ê âûñîòå. Åñëè îíî îòëè÷àåòñÿ îò åäèíèöû, òî ïðè âûâîäå òðåáóåòñÿ ìàñøòàáèðîâàíèå
+        èçîáðàæåíèÿ ïî îäíîé èç îñåé.
+      </dd>
+      <dt><b>int         flip;</b></dt>
+      <dd>
+        Îðèåíòàöèÿ èçîáðàæåíèÿ (0 - íå òðåáóåò ïîâîðîòà, 3 - òðåáóåòñÿ ïîâîðîò íà 180, 5 - 90 ãðàäóñîâ ïðîòèâ ÷àñîâîé
+        ñòðåëêè, 6 - 90 ãðàäóñîâ ïî ÷àñîâîé).
+      </dd>
+    </dl>
+    <a name="libraw_colordata_t"></a>
+    <h3>Ñòðóêòóðà libraw_colordata_t - èíôîðìàöèÿ î öâåòå</h3>
+    <p> ñòðóêòóðó libraw_colordata_t ñîáðàíû âñå öâåòîâûå äàííûå, êàê ïîëó÷åííûå èç RAW-ôàéëà, òàê è ðàññ÷èòàííûå íà
+      îñíîâàíèè ñàìîãî èçîáðàæåíèÿ. Äëÿ ðàçíûõ êàìåð ðàáîòàþò ðàçíûå ñïîñîáû ðàáîòû ñ öâåòîì.<br/>
+      Ïîëÿ äàííûõ:
+    </p>
+    <dl>
+      <dt><b>color_data_state_t   color_flags;</b></dt>
+      <dd>
+        Ñòðóêòóðà äàííûõ, îïèñûâàþùàÿ èñòî÷íèêè ïîëó÷åíèÿ öâåòîâûõ äàííûõ. Ïîäðîáíåå <a
+          href="#color_data_state_t">îïèñàíà íèæå</a>
+        <br/>
+        Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> ýòî ïîëå äàííûõ îòñóòñòâóåò.
+      </dd>
+      <dt><b>ushort      white[8][8];</b></dt>
+      <dd>
+      Áëîê áåëûõ ïèêñåëåé, èçâëåêàåìûé èç ôàéëîâ CIFF/CRW. Äëÿ äðóãèõ ôîðìàòîâ íå èçâëåêàåòñÿ, èñïîëüçóåòñÿ äëÿ
+      ðàñ÷åòîâ êîýôôèöèåíòîâ áàëàíñà áåëîãî.
+      </dd>
+      <dt><b>float       cam_mul[4]; </b></dt>
+      <dd>
+        Êîýôôèöèåíòû áàëàíñà áåëîãî (as shot). Ëèáî ñ÷èòûâàåòñÿ èç ôàéëà, ëèáî ðàññ÷èòûâàåòñÿ.
+      </dd>
+      <dt><b>float       pre_mul[4]; </b></dt>
+      <dd>
+        Êîýôôèöèåíòû áàëàíñà áåëîãî äëÿ äíåâíîãî ñâåòà (Daylight balance). Ëèáî ñ÷èòûâàåòñÿ èç ôàéëà, ëèáî
+        ðàññ÷èòûâàåòñÿ èç äàííûõ ôàéëà, ëèáî áåðóòñÿ hardcoded-êîíñòàíòû.
+      </dd>
+      <dt><b>float       cam_xyz[4][3]; </b></dt>
+      <dd>
+        Ìàòðèöà ïðåîáðàçîâàíèÿ èç êàìåðíîãî RGB â XYZ. Êîíñòàíòíàÿ òàáëèöà, ðàçíàÿ äëÿ ðàçíûõ êàìåð,
+        ïîëíûé àíàëîã ColorMatrix ôîðìàòà DNG. Ïîñëåäíÿÿ ñòðîêà äëÿ RGB-êàìåð êàê ïðàâèëî íóëåâàÿ,
+        äëÿ  CMYG è ïîäîáíûõ - íå íóëåâàÿ.
+      </dd>
+      <dt><b>float       cmatrix[3][4];</b></dt>
+      <dd>
+        Ìàòðèöà áàëàíñà áåëîãî, äëÿ ÷àñòè êàìåð ñ÷èòûâàåòñÿ èç ôàéëà, èç îñòàëüíûõ ðàññ÷èòûâàåòñÿ.
+      </dd>
+      <dt><b>float       rgb_cam[3][4];</b></dt>
+      <dd>
+        Åùå îäíà ìàòðèöà áàëàíñà áåëîãî, ñ÷èòûâàåòñÿ èç ôàéëà äëÿ êàìåð Leaf è Kodak.
+      </dd>
+      <dt><b>ushort      curve[0x4001];</b></dt>
+      <dd>
+        Camera tone curve, ñ÷èòûâàåòñÿ äëÿ êàìåð  Nikon, Sony è íåêîòîðûõ äðóãèõ.
+      </dd>
+      <dt><b>unsigned    black;</b></dt>
+      <dd>
+        Óðîâåíü ÷åðíîãî. Äëÿ íåêîòîðûõ êàìåð áóäåò ðàâåí íóëþ (÷òî îçíà÷àåò, ÷òî âû÷èòàíèå ÷åðíîãî ïðîâåäåíî íà ýòàïå
+        ðàñïàêîâêè èëè ñàìîé êàìåðîé), äëÿ íåêîòîðûõ êàìåð ðàññ÷èòûâàåòñÿ íà ýòàïå ðàñïàêîâêè, äëÿ íåêîòîðûõ -
+        ñ÷èòûâàåòñÿ èç RAW-ôàéëà, äëÿ íåêîòîðûõ - hardcoded. 
+      </dd>
+      <dt><b>unsigned    maximum;</b></dt>
+      <dd>
+        Ìàêñèìàëüíîå çíà÷åíèå ïèêñåëÿ. Äëÿ ðÿäà êàìåð ðàññ÷èòûâàåòñÿ èç äàííûõ, äëÿ ðÿäà - hardcoded. 
+      </dd>
+      <dt><b>ph1_t       phase_one_data;</b></dt>
+      <dd>
+        Áëîê öâåòîâûõ äàííûõ, ñ÷èòûâàåìûé äëÿ êàìåð Phase One.
+      </dd>
+      <dt><b>float       flash_used;</b></dt>
+      <dt><b>float       canon_ev;</b></dt>
+      <dd>
+        Ïîëÿ èñïîëüçóþòñÿ äëÿ ðàñ÷åòà áàëàíñà áåëîãî (äëÿ íåêîòîðûõ P&amp;S êàìåð Canon).
+      </dd>
+      <dt><b>char          model2[64];</b></dt>
+      <dd>
+        Îïèñàíèå áàëàíñà áåëîãî äëÿ êàìåð Foveon.
+      </dd>
+
+      <dt><b>void    *profile;</b></dt>
+      <dd>
+        Óêàçàòåëü íà èçâëå÷åííûé ICC-ïðîôèëü (åñëè îí åñòü â RAW-ôàéëå).
+      </dd>
+      <dt><b>unsigned    profile_length;</b></dt>
+      <dd>
+        Äëèíà ICC-ïðîôèëÿ â áàéòàõ.
+      </dd>
+    </dl>
+    <a name="color_data_state_t"></a>
+    <h3>Ñòðóêòóðà  color_data_state_t - îïèñàíèå èñòî÷íèêà öâåòîâûõ äàííûõ</h3>
+    <p>Ñòðóêòóðà (íà ñàìîì äåëå - áèòîâîå ïîëå) îïèñûâàåò èñòî÷íèê ïîëó÷åíèÿ öâåòîâûõ äàííûõ äëÿ êàæäîãî èç ïîëåé
+      ñòðóêòóðû  <a href="#libraw_colordata_t">libraw_colordata_t</a>, äëÿ êîòîðûõ âîçìîæíû ðàçíûå èñòî÷íèêè
+      ïîëó÷åíèÿ.<br/>
+      Ïîëÿ äàííûõ:
+    </p>
+    <pre>
+        unsigned curve_state        : 3;
+        unsigned rgb_cam_state      : 3;
+        unsigned cmatrix_state      : 3;
+        unsigned pre_mul_state      : 3;
+        unsigned cam_mul_state      : 3;
+    </pre>
+    <p>
+      Êàæäîå èç ïîëåé ïðèíèìàåò îäíî èç çíà÷åíèé, âîçìîæíûõ äëÿ enum <a
+        href="#LibRaw_colorstate">LibRaw_colorstate</a>. 
+        <br/>
+        Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> ýòî ïîëå äàííûõ îòñóòñòâóåò.
+    </p>
+
+    <a name="libraw_imgother_t"></a>
+    <h3>Ñòðóêòóðà  libraw_imgother_t - ïðî÷èå ïàðàìåòðû èçîáðàæåíèÿ</h3>
+    <p>
+       ñòðóêòóðó libraw_imgother_t ñîáðàíû äàííûå, ñ÷èòàííûå èç RAW-ôàéëà è íå íóæíûå äëÿ ïîñò-îáðàáîòêè
+      èçîáðàæåíèÿ.<br/>
+      Ïîëÿ äàííûõ:
+    </p>
+    <dl>
+      <dt><b>float       iso_speed; </b></dt>
+      <dd>
+        ×óâñòâèòåëüíîñòü ISO.
+      </dd>
+      <dt><b>float       shutter;</b></dt>
+      <dd>
+        Âûäåðæêà.
+      </dd>
+      <dt><b>float       aperture;</b></dt>
+      <dd>
+        Äèàôðàãìà.
+      </dd>
+      <dt><b>float       focal_len;</b></dt>
+      <dd>
+        Ôîêóñíîå ðàññòîÿíèå.
+      </dd>
+      <dt><b>time_t      timestamp; </b></dt>
+      <dd>
+        Äàòà ñúåìêè.
+      </dd>
+      <dt><b>unsigned    shot_order;</b></dt>
+      <dd>
+        Ñåðèéíûé íîìåð èçîáðàæåíèÿ.
+      </dd>
+      <dt><b>unsigned    gpsdata[32];</b></dt>
+      <dd>
+        GPS-äàííûå.
+      </dd>
+      <dt><b>char        desc[512];</b></dt>
+      <dd>
+        Îïèñàíèå èçîáðàæåíèÿ.
+      </dd>
+      <dt><b>char          artist[64];</b></dt>
+      <dd>
+        Àâòîð èçîáðàæåíèÿ.
+      </dd>
+    </dl>
+    
+    <a name="libraw_thumbnail_t"></a>
+    <h3>Ñòðóêòóðà libraw_thumbnail_t - îïèñàíèå Thumbnail</h3>
+    <p>Ñòðóêòóðà libraw_thumbnail_t îïèñûâàåò âñå ïàðàìåòðû, ñâÿçàííûå ñ ñîõðàíåííûì â RAW-ôàéëå preview.<br/>
+      Ïîëÿ äàííûõ:
+    </p>
+    <dl>
+      <dt><b>LibRaw_thumbnail_formats tformat;</b></dt>
+      <dd>
+        Ôîðìàò äàííûõ thumbnail. Îäíî èç çíà÷åíèé enum <a
+          href="#LibRaw_thumbnail_formats">LibRaw_thumbnail_formats</a>. 
+      </dd>
+      <dt><b>ushort      twidth, theight;</b></dt>
+      <dd>
+        Ðàçìåð preview-èçîáðàæåíèÿ â ïèêñåëàõ.
+      </dd>
+      <dt><b>unsigned    tlength;</b></dt>
+      <dd>
+        Äëèíà thumbnail â áàéòàõ.
+      </dd>
+      <dt><b>int         tcolors;</b></dt>
+      <dd>
+        Êîëè÷åñòâî öâåòîâ preview.
+      </dd>
+      <dt><b>char       *thumb;</b></dt>
+      <dd>
+        Óêàçàòåëü íà thumbmail, èçâëå÷åííûé èç ôàéëà äàííûõ.
+      </dd>
+    </dl>
+
+    <a name="libraw_output_params_t"></a>
+    <h3>Ñòðóêòóðà libraw_output_params_t - óïðàâëåíèå ïîñòîáðàáîòêîé â ñòèëå dcraw</h3>
+    <p>Ñòðóêòóðà libraw_output_params_t èñïîëüçóåòñÿ äëÿ óïðàâëåíèÿ dcraw-ñîâìåñòèìûìè âûçîâàìè dcraw_process(),
+      dcraw_ppm_tiff_writer(), dcraw_thumb_writer(), dcraw_document_mode_processing(). Ïîëÿ ýòîé ñòðóêòóðû
+      ñîîòâåòñòâóþò êëþ÷àì êîìàíäíîé ñòðîêè ïðîãðàììû dcraw.<br/>
+      Ïîëÿ äàííûõ:
+    </p>
+    <dl>
+      <dt><b>unsigned    greybox[4];</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b> -A  x1 y1 x2 y2 <br/>
+       4 ÷èñëà, îòâå÷àþùèå êîîðäèíàòàì (â ïèêñåëàõ) ïðÿìîóãîëüíèêà ïî êîòîðîìó  ðàññ÷èòûâàåòñÿ áàëàíñ áåëîãî.
+      </dd>
+      <dt><b>double      aber[4];</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>         -C <br/>
+        Èñïðàâëåíèå õðîìàòè÷åñêèõ àááåðàöèé, çàäàþòñÿ òîëüêî <br/>
+        aber[0] - ìíîæèòåëü êðàñíîãî<br/>
+        aber[2] - ìíîæèòåëü çåëåíîãî.
+        Äëÿ ðÿäà ôîðìàòîâ <a href=API-notes-rus.html>âëèÿåò íà ÷òåíèå RAW-äàííûõ</a> ò.ê. ïðè êîððåêöèè àáåððàöèé
+        âûõîäíîé ðàçìåð ìåíÿåòñÿ.
+      </dd>
+      <dt><b>double      gamm[6];</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>         -g <br/>
+        Çàäàíèå ïîëüçîâàòåëüñêîé ãàììà-êðèâîé. Äîëæíû áûòü óñòàíîâëåíû ïåðâûå äâà ïîëÿ â ìàññèâå:<br/>
+        gamm[0] -  <b>èíâåðòèðîâàííûé</b> (1.0/g) ïîêàçàòåëü ñòåïåíè<br/>
+        gamm[1] - íàêëîí äëÿ íà÷àëüíîé ëèíåéíîé ÷àñòè. Äëÿ ïîëó÷åíèÿ ÷èñòîé ñòåïåííîé ôóíêöèè äîëæíî áûòü óñòàíîâëåíî
+        â 0.
+        <br/>
+        Îñòàëüíûå 4 çíà÷åíèÿ â ýòîì ïîëå çàïîëíÿþòñÿ àâòîìàòè÷åñêè.
+        <p>
+          Ïî-óìîë÷àíèþ èñïîëüçóþòñÿ íàñòðîéêè ñïåöèôèêàöèè BT.709: ñòåïåíü 2.222, íàêëîí 4.5. Äëÿ çàäàíèÿ sRGB-êðèâîé
+          íóæíî ñòàâèòü çíà÷åíèÿ gamm[0]=1/2.4 è gamm[1]=12.92. Äëÿ ïðîñòîé ñòåïåííîé ôóíêöèè áåç ëèíåéíîãî ó÷àñòêà
+          íàêëîí ëèíåéíîé ÷àñòè çàäàåòñÿ íóëåâûì, äëÿ ëèíåéíîé êðèâîé íóæíî óñòàíàâëèâàòü gamm[0]=gamm[1]=1.
+      </dd>
+
+      <dt><b>float       user_mul[4];</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>     -r mul0 mul1 mul2 mul3 <br/>
+        4 ìíîæèòåëÿ (r,g,b,g)  ïîëüçîâàòåëüñêîãî áàëàíñà áåëîãî
+      </dd>
+      <dt><b>unsigned    shot_select, multi_out;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>  -s <br/>
+        âûáîð íîìåðà èçîáðàæåíèÿ äëÿ îáðàáîòêè (äëÿ ôîðìàòîâ, ñîäåðæàùèõ íåñêîëüêî  RAW-èçîáðàæåíèé â îäíîì ôàéëå)
+        Ðåæèì multi_out ( -s all) íóæíî ïðîãðàììèðîâàòü ñàìîñòîÿòåëüíî, dcraw_process() åãî íå ïîääåðæèâàåò.
+      </dd>
+      <dt><b>float       bright;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>          -b <br/>
+        ßðêîñòü (óìîë÷àíèå 1.0)
+      </dd>
+      <dt><b>float       threshold;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>        -n <br/>
+        Ïàðàìåòð äëÿ ïîäàâëåíèÿ øóìà ÷åðåç wavelet denoising.
+      </dd>
+      <dt><b>int         half_size;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>       -h <br/>
+        Âûâîäèòü èçîáðàæåíèå â ïîëîâèííîì ðàçìåðå. Äëÿ ðÿäà ôîðìàòîâ <a href=API-notes-rus.html>âëèÿåò íà ÷òåíèå
+          RAW-äàííûõ</a>. 
+      </dd>
+      <dt><b>int         four_color_rgb;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>  -f <br/>
+        Âêëþ÷àåò îòäåëüíóþ èíòåðïîëÿöèþ äëÿ äâóõ çåëåíûõ êîìïîíåíò.
+      </dd>
+      <dt><b>int         document_mode;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>   -d/-D <br/>
+         0 - ñòàíäàðòíàÿ îáðàáîòêà (ñ áàëàíñîì áåëîãî)<br/>
+         1 - ñîîòâåòñòâóåò -d (áåç öâåòîâîé îáðàáîòêè è áåç äåáàéåðèçàöèè)<br/>
+         2 - ñîîòâåòñòâóåò -D (-d áåç áàëàíñà áåëîãî)
+      </dd>
+      <dt><b>int         highlight;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>       -H <br/>
+         0-9 - Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)
+      </dd>
+      <dt><b>int         use_auto_wb;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>     -a <br/>
+        Èñïîëüçîâàòü àâòîáàëàíñ áåëîãî, ïîëó÷åííûé ïîñëå óñðåäíåíèÿ âñåãî èçîáðàæåíèÿ.
+      </dd>
+      <dt><b>int         use_camera_wb;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>   -w <br/>
+        Èñïîëüçîâàòü áàëàíñ áåëîãî ïîëó÷åííûé èç êàìåðû, åñëè ýòî âîçìîæíî.
+      </dd>
+      <dt><b>int         use_camera_matrix;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>  +M/-M <br/>
+        Èñïîëüçîâàòü (1)/íå èñïîëüçîâàòü(0) camera color matrix.
+      </dd>
+      <dt><b>int         output_color;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>    -o ÷èñëî <br/>
+        [0-5]  Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)
+      </dd>
+      <dt><b>char*         output_profile;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>    -o èìÿ ôàéëà<br/>
+        Ïóòü ê ICC-ôàéëó âûõîäíîãî ïðîôèëÿ (èñïîëüçóåòñÿ òîëüêî åñëè áèáëèîòåêà ñîáðàíà ñ ïîääåðæêîé LCMS)
+      </dd>
+      <dt><b>char*         camera_profile;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>    -o èìÿ ôàéëà<br/>
+        Ïóòü ê ICC-ôàéëó ïðîôèëÿ êàìåðû (èñïîëüçóåòñÿ òîëüêî åñëè áèáëèîòåêà ñîáðàíà ñ ïîääåðæêîé LCMS)
+      </dd>
+      <dt><b>char*         bad_pixels;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>    -P èìÿ ôàéëà<br/>
+        Ïóòü ê ôàéëó ñ êàðòîé ïëîõèõ ïèêñåëîâ (â ôîðìàòå "ñòîëáåö ñòðîêà äàòà-ïîÿâëåíèÿ â unix-ôîðìàòå", ïî îäíîé
+        çàïèñè íà ñòðîêó).
+      </dd>
+      <dt><b>char*         dark_frame;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>    -K èìÿ ôàéëà<br/>
+        Ïóòü ê ôàéëó ñ òåìíîâûì êàäðîì (16-áèòíûé PGM-ôàéë, ïîëó÷åííûé, íàïðèìåð, çàïóñêîì dcraw -D).
+      </dd>
+      <dt><b>int         output_bps;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>      -4 <br/>
+        8 bit (default)/ 16 bit (êëþ÷ -4)
+      </dd>
+      <dt><b>int         output_tiff;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>     -T <br/>
+        0/1 - âûâîäèòü PPM/TIFF
+      </dd>
+      <dt><b>int         user_flip;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>       -t <br/>
+        [0-7]  Flip image (0=none, 3=180, 5=90CCW, 6=90CW)
+        Óìîë÷àíèå -1, îçíà÷àåò áðàòü èç RAW. <br/>
+        Äëÿ ðÿäà ôîðìàòîâ <a href=API-notes-rus.html>âëèÿåò íà ÷òåíèå RAW-äàííûõ</a>, â ÷àñòíîñòè íà ðàñïàêîâêó
+        thumbnails îò êàìåð Kodak.
+      </dd>
+      <dt><b>int         user_qual;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>       -q <br/>
+        0-3 - êà÷åñòâî èíòåðïîëÿöèè (0 - linear, 1- VNG, 2 - PPG, 3 - AHD). 
+      </dd>
+      <dt><b>int         user_black;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>      -k <br/>
+        Ïîëüçîâàòåëüñêèé óðîâåíü ÷åðíîãî.
+      </dd>
+      <dt><b>int         user_sat;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>        -S <br/>
+        Ðåãóëèðîâêà íàñûùåííîñòè.
+      </dd>
+      <dt><b>int         med_passes;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>      -m <br/>
+        Êîëè÷åñòâî ïðîõîäîâ median filter
+      </dd>
+      <dt><b>int         no_auto_bright;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>  -W <br/>
+        Íå èñïîëüçîâàòü àâòîìàòè÷åñêîå ïîâûøåíèå ÿðêîñòè ïî ãèñòîãðàììå.
+      </dd>
+      <dt><b>float         auto_bright_thr;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>íåò <br/>
+        Äîëÿ ïèêñåëîâ, êîòîðûå áóäóò íàñûùåíû ïðè èñïîëüçîâàíèè àâòîìàòè÷åñêîãî ïîâûøåíèÿ ÿðêîñòè. Çíà÷åíèå
+        ïî-óìîë÷àíèþ 0.01 (äëÿ ñîâìåñòèìîñòè ñ dcraw), ðåêîìåíäîâàííîå ñòàðòîâîå çíà÷åíèå äëÿ ñîâðåìåííûõ
+        ìíîãîìåãàïèêñåëüíûõ ìàëîøóìíûõ êàìåð  0.001-0.00003.
+      </dd>
+      <dt><b>int         use_fuji_rotate;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b> -j <br/>
+         Óìîë÷àíèå - 1 (èñïîëüçîâàòü), 0 - îòêëþ÷àåò ïîâîðîò äëÿ êàìåð íà ñåíñîðå Fuji.
+      </dd>
+      <dt><b>char        *bpfile;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>         -P <br/>
+        Èìÿ ôàéëà ñ êàðòîé ïëîõèõ ïèêñåëîâ.
+      </dd>
+      <dt><b>char        *dark_frame;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>     -K <br/>
+         Èìÿ ôàéëà ñ dark frame.
+      </dd>
+      <dt><b>enum LibRaw_filtering  filtering_mode;</b></dt>
+      <dd>
+        <b>Êëþ÷è dcraw:</b>  íåò <br/>
+        Çàäàåò ðåæèì ôèëüòðàöèè RAW-äàííûõ (âû÷èòàíèå óðîâíÿ ÷åðíîãî, ñãëàæèâàíèå íóëåâûõ ïèêñåëîâ, íàëîæåíèå òîíîâîé êðèâîé).
+        Ïîäðîáíåå ñì. â <a href=API-notes-rus.html#filtering>îïèñàíèè ðåæèìîâ ôèëüòðàöèè</a> è â
+        <a href="#LibRaw_filtering">ïåðå÷èñëåíèè ýòèõ ðåæèìîâ</a> íèæå.
+        <br/>
+        Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> ýòî ïîëå äàííûõ îòñóòñòâóåò.
+      </dd>
+    </dl>
+    <a name="libraw_masked_t"></a>
+    <h3>Ñòðóêòóðà libraw_masked_t - ñîõðàíåííûå çíà÷åíèÿ ïèêñåëîâ ÷åðíîé ðàìêè (ìàñêèðîâàííûõ ïèêñåëîâ)</h3>
+    <p>
+      Ñòðóêòóðà äàííûõ libraw_masked_t ïðåäíàçíà÷åíà äëÿ õðàíåíèÿ ïèêñåëîâ "÷åðíîé ðàìêè" - íå âõîäÿùèõ â âèäèìîå
+      èçîáðàæåíèå, íî èñïîëüçóåìûõ äëÿ ðàñ÷åòà óðîâíÿ ÷åðíîãî, óðîâíÿ òåìíîâîãî øóìà è ïðî÷èõ ïîäîáíûõ âû÷èñëåíèé.
+       îòëè÷èå îò áóôåðà èçîáðàæåíèÿ, ãäå äëÿ êàæäîãî ïèêñåëà àëëîöèðîâàíî 4 ushort-çíà÷åíèÿ (îäíî èç íèõ
+      çàïîëíÿåòñÿ ïðè ÷òåíèè RAW, à îñòàëüíûå èñïîëüçóþòñÿ ïðè ïîñòïðîöåññèíãå), â áóôåðå äëÿ ìàñêèðîâàííûõ ïèêñåëîâ
+      íåò èçáûòî÷íîé àëëîêàöèè è êàæäîìó ïèêñåëó ñîîòâåòñòâóåò îäíî 16-áèòíîå çíà÷åíèå.
+      Ðàçíûå ó÷àñòêè ðàìêè õðàíÿòñÿ â îòäåëüíûõ áóôåðàõ âíóòðè äàííîé ñòðóêòóðû, êàê ïîêàçàíî íà ðèñóíêå:
+    </p>
+    <center><img src=corner-scheme.png width="600" height="400" border=1/></center>
+    <p>
+      Ïîëÿ äàííûõ:
+    </p>
+    <dl>
+      <dt><b>ushort  *buffer;</b></dt>
+      <dd>Áóôåð äëÿ õðàíåíèÿ âñåõ äàííûõ, èìååò ðàçìåð (raw_width*raw_height - width*height).
+        </dd>
+      <dt><b>ushort  *tl;</b></dt>
+      <dd>Óêàçàòåëü íà ó÷àñòîê áóôåðà, ïðåäíàçíà÷åííûé äëÿ õðàíåíèÿ âåðõíåãî ëåâîãî óãëà ðàìêè.
+        Ðàçìåð ýòîãî ó÷àñòêà áóôåðà ðàâåí (top_margin*left_margin).
+        </dd>
+      <dt><b>ushort  *top;</b></dt>
+      <dd>Óêàçàòåëü íà ó÷àñòîê áóôåðà, ïðåäíàçíà÷åííûé äëÿ õðàíåíèÿ âåðõíåé ÷àñòè ðàììêè, íàä àêòèâíîé îáëàñòüþ
+        èçîáðàæåíèÿ. Ðàçìåð ðàâåí (top_margin*width).
+      </dd>
+      <dt><b>ushort  *tr;</b></dt>
+      <dd>Óêàçàòåëü íà ó÷àñòîê áóôåðà, ïðåäíàçíà÷åííûé äëÿ õðàíåíèÿ âåðõíåãî ïðàâîãî óãëà ðàìêè.
+        Ðàçìåð ýòîãî ó÷àñòêà áóôåðà ðàâåí (top_margin*right_margin).
+        </dd>
+      <dt><b>ushort  *left;</b></dt>
+      <dd>Óêàçàòåëü íà ó÷àñòîê áóôåðà, ïðåäíàçíà÷åííûé äëÿ õðàíåíèÿ ÷àñòè ðàììêè, ðàñïîëîæåííîé ñëåâà 
+        àêòèâíîé îáëàñòè èçîáðàæåíèÿ. Ðàçìåð ðàâåí (left_margin*height).
+      </dd>
+      <dt><b>ushort  *right;</b></dt>
+      <dd>Óêàçàòåëü íà ó÷àñòîê áóôåðà, ïðåäíàçíà÷åííûé äëÿ õðàíåíèÿ ÷àñòè ðàììêè, ðàñïîëîæåííîé ñïðàâà
+        àêòèâíîé îáëàñòè èçîáðàæåíèÿ. Ðàçìåð ðàâåí (right_margin*height).
+      </dd>
+      <dt><b>ushort  *bl;</b></dt>
+      <dd>Óêàçàòåëü íà ó÷àñòîê áóôåðà, ïðåäíàçíà÷åííûé äëÿ õðàíåíèÿ íèæíåãî ëåâîãî óãëà ðàìêè.
+        Ðàçìåð ýòîãî ó÷àñòêà áóôåðà ðàâåí (bottom_margin*left_margin).
+        </dd>
+      <dt><b>ushort  *bottom;</b></dt>
+      <dd>Óêàçàòåëü íà ó÷àñòîê áóôåðà, ïðåäíàçíà÷åííûé äëÿ õðàíåíèÿ íèæíåé ÷àñòè ðàììêè, ïîä àêòèâíîé îáëàñòüþ
+        èçîáðàæåíèÿ. Ðàçìåð ðàâåí (bottom_margin*width).
+      </dd>
+      <dt><b>ushort  *br;</b></dt>
+      <dd>Óêàçàòåëü íà ó÷àñòîê áóôåðà, ïðåäíàçíà÷åííûé äëÿ õðàíåíèÿ íèæíåãî ïðàâîãî óãëà ðàìêè.
+        Ðàçìåð ýòîãî ó÷àñòêà áóôåðà ðàâåí (bottom_margin*right_margin).
+      <dt><b>ushort  (*ph1_black)[2];</b</dt>
+      <dd> ýòîò áóôåð ñ÷èòûâàþòñÿ äàííûå îá óðîâíå ÷åðíîãî äëÿ çàäíèêîâ PhaseOne (êîëè÷åñòâî
+        ýëåìåíòîâ ðàâíî ÷èñëó ñòðîê â äàííûõ, ïåðâîå ÷èñëî â ýëåìåíòå îòíîñèòñÿ ê ëåâîé ïîëóñòðîêå,
+        âòîðîå - ê ïðàâîé.
+        </dd>
+    </dl>
+    <p>Íåêîòîðûå êàìåðû íå âûäàþò ðàìêè âîâñå, â ýòîì ñëó÷àå áóôåð íå àëëîöèðóåòñÿ, à îñòàëüíûå ïîëÿ
+      èíèöèàëèçèðóþòñÿ â 0. Òàê æå, àëëîöèðîâàíèå ñòðóêòóðû äàííûõ è åå çàïîëíåíèå íå ïðîèçâîäèòñÿ, åñëè èçâëå÷åíèå
+      äàííûõ ïðîèçâîäèòñÿ ïðè ïîëîâèííîì ðàçðåøåíèè (åñëè â íàñòðîéêàõ óêàçàíà ïîëîâèííàÿ èíòåðïîëÿöèÿ,
+      âåéâëåò-øóìîïîíèæåíèå  èëè èñïðàâëåíèå àáåððàöèé).<br/>
+      Ðÿä êàìåð èìååò ðàìêó íå ñî âñåõ ñòîðîí àêòèâíîé ÷àñòè èçîáðàæåíèÿ.  ýòîì ñëó÷àå óêàçàòåëè íà íåèñïîëüçóåìûå
+      ó÷àñòêè áóôåðà âñå-ðàâíî èíèöèàëèçèðóþòñÿ ïðàâèëüíî, ïðîñòî ñîîòâåòñòâóþùèé èì ðàçìåð ó÷àñòêà áóôåðà ðàâåí íóëþ.
+      Ñîîòâåòñòâóþùèé ïàðàìåòð øèðèíû ðàìêè (top-left-right-bottom_margin) â ýòîì ñëó÷àå òîæå íóëåâîé.
+    </p>
+    <p>
+      Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> ýòà ñòðóêòóðà äàííûõ îòñóòñòâóåò.
+    </p>
+    <a name="libraw_processed_image_t"></a>
+    <h3>Ñòðóêòóðà libraw_processed_image_t - äàííûå, âûâîäèìûå ôóíêöèÿìè dcraw_make_mem_image()/dcraw_make_mem_thumb() </h3>
+    <p>Ñòðóêòóðà libraw_processed_image_t - ïîðîæäàåòñÿ â ðåçóëüòàòå ðàáîòû ôóíêöèé 
+      dcraw_make_mem_image()/dcraw_make_mem_thumb() è ñîäåðæèò îáðàç äàííûõ èçîáðàæåíèÿ èëè preview.<br/>
+      Ïîëÿ äàííûõ:
+    </p>
+    <dl>
+      <dt><b>LibRaw_image_formats type</b></dt>
+      <dd> Òèï äàííûõ, ñîäåðæàùèõñÿ â ñòðóêòóðå:
+        <ul>
+          <li><b>LIBRAW_IMAGE_BITMAP</b> - ñòðóêòóðà ñîäåðæèò îáû÷íûé RGB èëè ñåðûé bitmap, ðàçìåðû êîòîðîãî è ïðî÷èå
+            õàðàêòåðèñòèêè îïèñûâàþòñÿ ïàðàìåòðàìè äàííîé ñòðóêòóðû (ñì. íèæå).
+          <li><b>LIBRAW_IMAGE_JPEG</b> - ñòðóêòóðà ñîäåðæèò çíà÷èìûå ïîëÿ data_size è  data,  â ïîëå  data íàõîäèòñÿ
+            ñòðóêòóðà äàííûõ JPEG-ôàéëà.
+        </ul>
+      </dd>
+      <dt><b>ushort height,width</b></dt>
+      <dd> Ðàçìåð èçîáðàæåíèÿ â ïèêñåëàõ. Ýòè ïîëÿ äàííûõ âàëèäíû òîëüêî åñëè type==LIBRAW_IMAGE_BITMAP.</dd>
+      <dt><b>ushort colors, bits</b></dt>
+      <dd> Êîëè÷åñòâî öâåòîâ (3 èëè 1) è ãëóáèíà öâåòà â áèòàõ (8 èëè 16). Ýòè ïîëÿ âàëèäíû òîëüêî åñëè type==LIBRAW_IMAGE_BITMAP </dd>
+      <dt><b>ushort gamma_corrected</b></dt>
+      <dd> ßâëÿþòñÿ ëè çíà÷åíèÿ äàííûõ ãàììà-êîððåêòèðîâàíûìè (0 èëè 1).Ýòè ïîëÿ äàííûõ âàëèäíû òîëüêî åñëè
+        type==LIBRAW_IMAGE_BITMAP.</dd>
+      <dt><b>unsigned int data_size</b></dt>
+      <dd> Ðàçìåð ñëåäóþùåãî ïîëÿ (data) â áàéòàõ.  ñëó÷àå type==LIBRAW_IMAGE_BITMAP åãî, êîíå÷íî, íåñëîæíî
+        âû÷èñëèòü êàê (height*width*colors * (bits/8)).  ñëó÷àå type==LIBRAW_IMAGE_JPEG - âû÷èñëèòü íèêàê íåëüçÿ, à
+        ðàçìåð äàííûõ ìîæåò áûòü íóæåí.
+      </dd>
+      <dt><b>unsigned char data[]</b></dt>
+      <dd> Ìàññèâ äàííûõ,  ñîäåðæàùèé ëèáî  RGB-áèòìýï, ëèáî JPEG-ôàéë (â ïàìÿòè), â çàâèñèìîñòè îò çíà÷åíèÿ ïîëÿ
+        type.
+        </dd>
+      </dl>
+    <a name="datastream"></a>
+    <h2>Îáúåêòû àáñòðàêöèè ââîäà äàííûõ</h2>
+    <p>
+      Ââîä (÷òåíèå) RAW-äàííûõ â LibRaw îáåñïå÷èâàåòñÿ îáúåêòîì, ïðîèçâîäíûì îò êëàññà
+      <b>LibRaw_abstract_datastream</b>. Ôóíêöèîíàëüíîñòü ýòèõ îáúåêòîâ ïîäðîáíî îïèñàíà â <a
+        href="API-CXX-rus.html#datastream">îïèñàíèè C++ API</a>. 
+    </p>
+    <p>
+      LibRaw ïðåäëàãàåò äâå ãîòîâûõ ðåàëèçàöèè îáúåêòîâ datastream:
+    </p>
+    <ul>
+      <li><a href="API-CXX-rus.html#file_datastream">LibRaw_file_datastream</a> - ââîä èç ôàéëà (îáúåêò ñîçäàåòñÿ äëÿ
+        ôàéëà ñ çàäàííûì èìåíåì).</li>
+      <li><a href="API-CXX-rus.html#buffer_datastream">LibRaw_buffer_datastream</a> - ââîä èç áóôåðà â ïàìÿòè (ýòî
+        ìîæåò áûòü mmap()-ed ôàéë èëè áóôåð ñî ñ÷èòàííûìè RAW-äàííûìè).</li>
+    </ul>
+    <p>
+      Ïîëüçîâàòåëü áèáëèîòåêè ìîæåò çàïðîãðàìèðîâàòü ñâîé îáúåêò, ïðîèçâîäíûé îò <a
+        href="API-CXX-rus.html#datastream">LibRaw_abstract_datastream</a>, ðåàëèçóþùèé, íàïðèìåð, ÷òåíèå RAW-ôàéëà
+      ÷åðåç èíòåðôåéñ óäàëåííîãî óïðàâëåíèÿ êàìåðîé, è èñïîëüçîâàòü LibRaw c ýòèì îáúåêòîì ÷åðåç èíòåðôåéñ 
+      <a href="API-CXX-rus.html#open_datastream">LibRaw::open_datastream()</a>.
+    </p>
+    <p>Âõîäÿùèå â áèáëèîòåêó ðåàëèçàöèè ïîòîêà äàííûõ ìîãóò áûòü èñïîëüçîâàíû êàê ÷åðåç ïîñðåäñòâî èíòåðôåéñà
+      <a href="API-CXX-rus.html#open_datastream">LibRaw::open_datastream()</a>, òàê è ÷åðåç shortcuts
+      <a href="API-CXX-rus.html#open_file">LibRaw::open_file()</a> è 
+      <a href="API-CXX-rus.html#open_buffer">LibRaw::open_buffer()</a>.
+    </p>
+    <p>Ïåðåîïðåäåëåíèå èíòåðôåéñà ââîäà è èíòåðôåéñ <a
+        href="API-CXX-rus.html#open_datastream">LibRaw::open_datastream()</a> äîñòóïíû òîëüêî ïîëüçîâàòåëÿì
+      <a href="API-CXX-rus.html">C++ API</a>, ïîëüçîâàòåëè <a href="API-C-rus.html">C API</a> ìîãóò èñïîëüçîâàòü
+      òîëüêî âñòðîåííûå èíòåðôåéñû <b>libraw_open_file()/libraw_open_buffer()</b>.
+    </p>
+    <a name="datastream_data"></a>
+    <h3>Ïîëÿ äàííûõ</h3>
+    <p>Îïðåäåëåíèå:</p>
+    <pre>
+class LibRaw_abstract_datastream {
+...
+protected:
+    LibRaw_abstract_datastream *substream;
+}
+</pre>
+    <p><b>Îïèñàíèå:</b>
+      Îáúåêòû ïðîèçâîäíûå îò LibRaw_abstract_datastream âñåãäà ñîäåðæàò óêàçàòåëü íà âòîðè÷íûé ïîòîê äàííûõ
+      (substream), ýòîò ïîòîê äàííûõ èíèöèàëèçèðóåòñÿ ïðè íåîáõîäèìîñòè âðåìåííî ïåðåêëþ÷èòü ââîä íà ðàñøèôðîâàííûå
+      ìåòàäàííûå, ñ÷èòàííûå èç ôàéëà âî âðåìåííûé áóôåð (àêòóàëüíî òîëüêî äëÿ êàìåð Sony).
+    </p>
+    <p>
+      Ïîäðîáíåå ðàáîòà ñ âòîðè÷íûì ïîòîêîì äàííûõ îïèñàíà â 
+      <a href="API-CXX-rus.html#own_datastreams">îïèñàíèè ðåàëèçàöèè ñîáñòâåííûõ îáúåêòîâ ââîäà  äàííûõ</a>.
+    </p>
+
+    <a name="const"></a>
+    <h2>Êîíñòàíòû</h2>
+    <a name=LibRaw_errors></a>
+    <h3>enum LibRaw_errors - êîäû îøèáîê</h3>
+    <p>Âñå ôóíêöèè, âîçâðàùàþùèå öåëûå ÷èñëà, âîçâðàùàþò ëèáî errno, ëèáî îäèí èç ñëåäóþùèõ êîäîâ îøèáîê (ñì. òàêæå <a
+        href="API-notes-rus.html#errors">ñîãëàøåíèÿ î êîäàõ îøèáîê</a>)</p>
+    <p><b>Ôàòàëüíûå îøèáêè</b> (ïîëó÷åíèå òàêîãî êîäà îøèáêè îçíà÷àåò áåçóñëîâíîå ïðåêðàùåíèå îáðàáîòêè ôàéëà, èáî
+      ñòðóêòóðû äàííûõ íàõîäÿòñÿ â íåèçâåñòíîì ñîñòîÿíèè).</p>
+    <dl>
+      <dt><b> LIBRAW_UNSUFFICIENT_MEMORY</b></dt>
+      <dd>Ïîïûòêà ïîëó÷åíèÿ ïàìÿòè îò ñèñòåìû çàêîí÷èëàñü íåóäà÷åé. <br/>
+        Âñå àëëîöèðîâàííûå ðåñóðñû áóäóò îñâîáîæäåíû, âûçâàíà ôóíêöèÿ <a
+          href="API-CXX-rus.html#recycle">recycle()</a>, îáúåêò LibRaw ïðèâåäåí â ñîñòîÿíèå "ñðàçó ïîñëå ñîçäàíèÿ".
+        </dd>
+    <dt><b>LIBRAW_DATA_ERROR</b></dt>
+      <dd>Ïðè ðàñïàêîâêå äàííûõ âîçíèêëà ôàòàëüíàÿ îøèáêà.<br/>
+        Âñå àëëîöèðîâàííûå ðåñóðñû áóäóò îñâîáîæäåíû, âûçâàíà ôóíêöèÿ <a
+          href="API-CXX-rus.html#recycle">recycle()</a>, îáúåêò LibRaw ïðèâåäåí â ñîñòîÿíèå "ñðàçó ïîñëå ñîçäàíèÿ".
+      </dd>
+    <dt><b>LIBRAW_IO_ERROR</b></dt>
+      <dd>Ïðè  ÷òåíèè ôàéëà âîçíèêëà ôàòàëüíàÿ îøèáêà (ôàéë çàêîí÷èëñÿ ðàíüøå âðåìåíè, ëèáî ïîâðåæäåí).<br/>
+        Âñå àëëîöèðîâàííûå ðåñóðñû áóäóò îñâîáîæäåíû, âûçâàíà ôóíêöèÿ <a
+          href="API-CXX-rus.html#recycle">recycle()</a>, îáúåêò LibRaw ïðèâåäåí â ñîñòîÿíèå "ñðàçó ïîñëå ñîçäàíèÿ".
+        </dd>
+    <dt><b>LIBRAW_CANCELLED_BY_CALLBACK</b></dt>
+      <dd>Îáðàáîòêà çàâåðøåíà äîñðî÷íî ïî òðåáîâàíèþ âûçûâàþùåãî ïðèëîæåíèÿ (ïóòåì âîçâðàòà íåíóëåâîãî êîäà èç  <a
+          href=API-CXX-rus.html#progress">progress callback</a>.<br/>
+        Âñå àëëîöèðîâàííûå ðåñóðñû áóäóò îñâîáîæäåíû, âûçâàíà ôóíêöèÿ <a
+          href="API-CXX-rus.html#recycle">recycle()</a>, îáúåêò LibRaw ïðèâåäåí â ñîñòîÿíèå "ñðàçó ïîñëå ñîçäàíèÿ".
+        </dd>
+    </dl>
+    <p><b>Íåôàòàëüíûå îøèáêè</b></p>
+    <dl>
+      <dt><b>LIBRAW_SUCCESS=0</b></dt>
+      <dd>Íåò îøèáêè, ôóíêöèÿ çàâåðøèëàñü óñïåøíî.</dd>
+      <dt><b>LIBRAW_UNSPECIFIED_ERROR</b></dt>
+      <dd>Ïðîèçîøëà íåèçâåñòíàÿ îøèáêà. Ýòîò êîä íå äîëæåí âûäàâàòüñÿ íèêîãäà.</dd>
+      <dt><b>LIBRAW_FILE_UNSUPPORTED</b></dt>
+      <dd>Íå ïîääåðæèâàåìûé ôîðìàò ôàéëà (ïîïûòêà îòêðûòü RAW-ôàéë íåèçâåñòíîãî ïðîãðàììå ôîðìàòà).</dd>
+      <dt><b>LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE</b></dt>
+      <dd>Ïîïûòêà èçâëå÷ü RAW-èçîáðàæåíèå ñ íîìåðîì, íå ñóùåñòâóþùèì â ôàéëå äàííûõ (òîëüêî äëÿ ôîðìàòîâ,
+        ïîääåðæèâàþùèõ õðàíåíèå íåñêîëüêèõ èçîáðàæåíèé â îäíîì ôàéëå).</dd>
+      <dt><b>LIBRAW_OUT_OF_ORDER_CALL</b></dt>
+      <dd>Ôóíêöèè API âûçûâàëèñü â íåïðàâèëüíîì ïîðÿäêå (íàïðèìåð, <a href="API-CXX-rus.html#unpack">unpack()</a> äî
+        <a href="API-CXX-rus.html#open_file">open_file()</a>), ëèáî ïðåäûäóùàÿ ñòàäèÿ 
+        çàâåðøèëàñü ñ îøèáêîé (íàïðèìåð, âûçûâàåì <a href="API-CXX-rus.html#unpack">unpack()</a> åñëè <a
+          href="API-CXX-rus.html#open_file">open_file()</a> âåðíóëà îøèáêó).</dd> 
+      <dt><b>LIBRAW_NO_THUMBNAIL</b></dt>
+      <dd>Âîçâðàùàåòñÿ ïðè ïîïûòêå ïîëó÷èòü thumbnail èç ôàéëà, íå ñîäåðæàùåãî preview.</dd>
+      <dt><b>LIBRAW_UNSUPPORTED_THUMBNAIL</b></dt>
+      <dd>RAW-ôàéë ñîäåðæèò preview íåïîääåðæèâàåìîãî ôîðìàòà.</dd>
+    </dl>
+
+    <a name="progress"></a>    
+    <h3>enum LibRaw_progress - òåêóùåå ñîñòîÿíèå îáúåêòà LibRaw</h3>
+    <p>Â LibRaw::imgdata.progress_flags ñîäåðæèòñÿ áèòîâàÿ ìàñêà, îïèñûâàþùàÿ âñå ñòàäèè îáðàáîòêè, óæå ïðîâåäåííûå
+      íàä ôàéëîì.
+    </p>
+    <p><b>Ôàçà îòêðûòèÿ ôàéëà è èçâëå÷åíèÿ RAW-äàííûõ.</b></p>
+    <dl>
+      <dt><b>LIBRAW_PROGRESS_START=0</b></dt>
+      <dd>
+        Îáúåêò òîëüêî ñîçäàí, íèêàêîé îáðàáîòêè íå ïðîâîäèëîñü.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_OPEN</b></dt>
+      <dd>
+        Îáðàáàòûâàåìûé ôàéë îòêðûò
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_IDENTIFY</b></dt>
+      <dd>
+        Ïðîâåäåíà èäåíòèôèêàöèÿ äàííûõ, ôîðìàò îïîçíàí, èçâëå÷åíû ìåòàäàííûå.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_SIZE_ADJUST</b></dt>
+      <dd>
+        Ïðîâåäåíî âûðàâíèâàíèå ðàçìåðîâ äàííûõ (äëÿ òåõ ôàéëîâ, êîòîðûì ýòî íóæíî, à ýòî íåêîòîðûå ôàéëû ñ êàìåð
+        Kodak). 
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_LOAD_RAW</b></dt>
+      <dd>
+        Çàãðóæåíû RAW-äàííûå.
+      </dd>
+    </dl>
+    <p><b>Ñëåäóþùèå ôëàãè âûñòàâëÿþòñÿ ïðè èñïîëüçîâàíèè îáðàáîòêè èçîáðàæåíèé, ïîçàèìñòâîâàííîé ó dcraw.</b></p>
+    <dl>
+      <dt><b>LIBRAW_PROGRESS_REMOVE_ZEROES</b></dt>
+      <dd>
+        Óäàëåíû íóëåâûå çíà÷åíèÿ äëÿ òåõ êàìåð, äëÿ êîòîðûõ ýòî íóæíî (êàìåðû Panasonic).
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_BAD_PIXELS</b></dt>
+      <dd>
+        Óäàëåíû ïëîõèå ïèêñåëû (åñëè âêëþ÷åíà ñîîòâ. îïöèÿ)
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_DARK_FRAME</b></dt>
+      <dd>
+        Ïðîâåäåíî âû÷èòàíèå òåìíîâîãî êàäðà (åñëè âêëþ÷åíà ñîîòâ. îïöèÿ)
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_FOVEON_INTERPOLATE</b></dt>
+      <dd>
+        Ïðîâåäåíà èíòåðïîëÿöèÿ äëÿ êàìåð ñ ñåíñîðîì Foveon.
+        <p>
+          Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> ýòà ñòàäèÿ îáðàáîòêè îòñóòñòâóåò.
+        </p>
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_SCALE_COLORS</b></dt>
+      <dd>
+        Ïðîèçâåäåíà áàëàíñèðîâêà áåëîãî.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_PRE_INTERPOLATE</b></dt>
+      <dd>
+        Ïðîâåäåíî óäàëåíèå ïëîõèõ ïèêñåëîâ (åñëè ñîîòâåòñòâóþùèé ðåæèì çàäàí â íàñòðîéêàõ).<br/>
+        Ïðîâåäåíî âû÷èòàíèå òåìíîâîãî êàäðà (åñëè ñîîòâåòñòâóþùèé ðåæèì çàäàí â íàñòðîéêàõ).<br/>
+        Ïðîâåäåíî óìåíüøåíèå èçîáðàæåíèÿ (äëÿ ðåæèìà half_size) è êîïèðîâàíèå 2-ãî êàíàëà çåëåíîãî â ïåðâûé
+        â òåõ òî÷êàõ, ãäå 2-é êàíàë åñòü, à ïåðâîãî - íåò.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_INTERPOLATE</b></dt>
+      <dd>
+        Ïðîâåäåíà èíòåðïîëÿöèÿ (äå-áàéåðèçàöèÿ).
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_MIX_GREEN</b></dt>
+      <dd>
+        Ïðîâåäåíî óñðåäíåíèå êàíàëîâ çåëåíîãî.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_MEDIAN_FILTER</b></dt>
+      <dd>
+        Ïðîâåäåíà ìåäèàííàÿ ôèëüòðàöèÿ.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_HIGHLIGHTS</b></dt>
+      <dd>
+        Ïðîâåäåíà ðàáîòà ñî ñâåòàìè.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_FUJI_ROTATE</b></dt>
+      <dd>
+        Äëÿ èçîáðàæåíèé ñ êàìåð Fuji  ïðîâåäåí ïîâîðîò (ëèáî âûçâàíà adjust_sizes_info_only()).
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_FLIP</b></dt>
+      <dd>
+        Äëÿ èçîáðàæåíèé, ñíÿòûõ ïîâåðíóòîé êàìåðîé, ïðîèçâåäåí ïåðåñ÷åò ðàçìåðîâ (sizes.iwidth/sizes.iheight ïîìåíÿëè ìåñòàìè).
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_CONVERT_RGB</b></dt>
+      <dd>
+        Ïðîâåäåíà êîíâåðñèÿ â âûõîäíîå RGB-ïðîñòðàíñòâî.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_STRETCH</b></dt>
+      <dd>
+        Ïðîèçâåäåíî èçìåíåíèå ðàçìåðîâ èçîáðàæåíèÿ äëÿ êàìåð ñ íåêâàäðàòíûìè ïèêñåëàìè.
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_STAGE17 - LIBRAW_PROGRESS_STAGE27</b></dt>
+      <dd>
+        Çàðåçåðâèðîâàíî íà ñëó÷àé ïîÿâëåíèÿ äðóãèõ ñòàäèé îáðàáîòêè.
+      </dd>
+    </dl>
+    <p><b>Ñëåäóþùèå ôëàãè âûñòàâëÿþòñÿ ïðè çàãðóçêå  thumbnails.</b></p>
+      <dt><b>LIBRAW_PROGRESS_THUMB_LOAD</b></dt>
+      <dd>
+        Ïðîèçâåäåíà çàãðóçêà äàííûõ Thumbnail (äëÿ êàìåð Kodak - åùå ñäåëàíû íåîáõîäèìûå ïðåîáðàçîâàíèÿ).
+      </dd>
+      <dt><b>LIBRAW_PROGRESS_TRESERVED1 - LIBRAW_PROGRESS_TRESERVED3</b></dt>
+      <dd>
+        Çàðåçåðâèðîâàíî íà ñëó÷àé ïîÿâëåíèÿ äðóãèõ ñòàäèé îáðàáîòêè.
+      </dd>
+    </dl>
+    
+    <a name="LibRaw_thumbnail_formats"></a>
+    <h3>enum LibRaw_thumbnail_formats - ôîðìàòû äàííûõ Thumbnails</h3>
+    <p>Ôîðìàò äàííûõ thumbnail çàïèñûâàåòñÿ â ïîëå äàííûõ imgdata.thumbnail.tformat.<br/>
+      Íà ñåãîäíÿøíèé äåíü LibRaw çíàåò î ÷åòûðåõ ôîðìàòàõ thumbnail èç êîòîðûõ ðàñïàêîâûâàþòñÿ äâà:
+    </p>
+    <dl>
+      <dt><b>LIBRAW_THUMBNAIL_UNKNOWN</b></dt>
+      <dd>Ôîðìàò íåèçâåñòåí èëè thumbnail åùå íå ÷èòàëñÿ.
+      </dd>
+      <dt><b>LIBRAW_THUMBNAIL_JPEG</b></dt>
+      <dd> áóôåðå thumbnail ëåæèò JPEG-ôàéë (ñ÷èòàííûé as-is èç RAW-ôàéëà, êàêèõ-ëèáî ìàíèïóëÿöèé íàä íèì íå
+        ïðîâîäèòñÿ). 
+      </dd>
+      <dt><b>LIBRAW_THUMBNAIL_BITMAP</b></dt>
+      <dd>
+        Â áóôåðå äëÿ thumbnaill ëåæèò ãàììà-ñêîððåêòèðîâàííûé RGB-bitmaip (äëÿ êàìåð Kodak ãàììà-êîððåêöèÿ ïðîâîäèòñÿ
+        ñ ó÷åòîì ìàêñèìàëüíûõ çíà÷åíèé, à áàëàíñ áåëîãî  âûñòàâëÿåòñÿ â ñîîòâåòñòâèè ñ íàñòðîéêàìè êàìåðû)<br/>
+        Â ýòîì ôîðìàòå êàæäûé ïèêñåëü èçîáðàæåíèÿ ïðåäñòàâëåí 8-áèòíûì RGB-òðèïëåòîì.
+      </dd>
+      <dt><b>LIBRAW_THUMBNAIL_LAYER</b></dt>
+      <dd>
+        Ôîðìàò äàííûõ â íàñòîÿùåå âðåìÿ ðàñïîçíàåòñÿ ïðè îòêðûòèè  RAW-ôàéëà, íî íå ïîääåðæèâàåòñÿ:  íå ðàñïàêîâûâàåòñÿ
+        â LibRaw::unpack_thumb. 
+      </dd>
+      <dt><b>LIBRAW_THUMBNAIL_ROLLEI</b></dt>
+      <dd>
+        Ôîðìàò äàííûõ â íàñòîÿùåå âðåìÿ ðàñïîçíàåòñÿ ïðè îòêðûòèè  RAW-ôàéëà, íî íå ïîääåðæèâàåòñÿ:  íå ðàñïàêîâûâàåòñÿ
+        â LibRaw::unpack_thumb. 
+      </dd>
+    </dl>
+    <a name="warnings"></a>
+    <h3>Íåøòàòíûå ñèòóàöèè (warnings) âîçíèêàþùèå ïðè îáðàáîòêå RAW-äàííûõ</h3>
+    <p>Ïðè îáðàáîòêå èçîáðàæåíèé ìîãóò âîçíèêíóòü ñîìíèòåëüíûå ñèòóàöèè, íå ÿâëÿþùèåñÿ ôàòàëüíûìè, íî âîçìîæíî
+      âëèÿþùèå íà ðåçóëüòàò èçâëå÷åíèÿ äàííûõ èëè èõ ïîñòîáðàáîòêè. Èíäèêàöèÿ òàêèõ ñîñòîÿíèé ïðîèçâîäèòñÿ ïóòåì
+      óñòàíîâêè áèòà â ïîëå imgdata.process_warnings</p>
+    <dl>
+      <dt><b>LIBRAW_WARN_FOVEON_NOMATRIX</b></dt>
+      <dd>Òîëüêî äëÿ êàìåð íà Foveon: íå óäàëîñü èçâëå÷ü îäíó èç ìàòðèö äàííûõ.
+        <p>
+          Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> ýòî ïðåäóïðåæäåíèå îòñóòñòâóåò.
+        </p>
+      </dd>
+      <dt><b>LIBRAW_WARN_FOVEON_INVALIDWB</b></dt>
+      <dd>
+        Òîëüêî äëÿ êàìåð íà Foveon: íå óäàëîñü èçâëå÷ü äàííûå î áàëàíñå áåëîãî.
+        <p>
+          Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> ýòî ïðåäóïðåæäåíèå îòñóòñòâóåò.
+        </p>
+      </dd>
+      <dt><b>LIBRAW_WARN_BAD_CAMERA_WB</b></dt>
+      <dd>
+        Ïðè ïîñòîáðàáîòêå çàäàíî èñïîëüçîâàòü áàëàíñ áåëîãî êàìåðû, à îí íåïðèãîäåí äëÿ èñïîëüçîâàíèÿ.
+      </dd>
+      <dt><b>LIBRAW_WARN_NO_METADATA</b></dt>
+      <dd>
+        Òîëüêî äëÿ êàìåð, ãäå ìåòàäàííûå áåðóòñÿ èç âíåøíåãî jpeg: íå óäàëîñü èçâëå÷ü ìåòàäàííûå.
+      </dd>
+      <dt><b>LIBRAW_WARN_NO_JPEGLIB</b></dt>
+      <dd>
+        Òîëüêî äëÿ P&S êàìåð Kodak: äàííûå â ôîðìàòå JPEG. Îäíîâðåìåííî open_file() âåðíåò LIBRAW_FILE_UNSUPPORTED.
+      </dd>
+      <dt><b>LIBRAW_WARN_NO_EMBEDDED_PROFILE</b></dt>
+      <dd>
+        (Òîëüêî ïðè âêëþ÷åííîé ïîääåðæêå ICC). 
+        Çàäàíî èñïîëüçîâàíèå âëîæåííîãî ïðîôèëÿ êàìåðû, íî â RAW-ôàéëå íåò ïðîôèëÿ.
+      </dd>
+      <dt><b>LIBRAW_WARN_NO_INPUT_PROFILE</b></dt>
+      <dd>
+        (Òîëüêî ïðè âêëþ÷åííîé ïîääåðæêå ICC). 
+        Çàäàííûé ôàéë ñ ïðîôèëåì âõîäíûõ äàííûõ íå óäàëîñü îòêðûòü.
+      </dd>
+      <dt><b>LIBRAW_WARN_BAD_OUTPUT_PROFILE</b></dt>
+      <dd>
+        (Òîëüêî ïðè âêëþ÷åííîé ïîääåðæêå ICC). 
+        Çàäàííûé ôàéë ñ âûõîäíûì ïðîôèëåì íå óäàëîñü îòêðûòü.
+      </dd>
+      <dt><b>LIBRAW_WARN_NO_BADPIXELMAP</b></dt>
+      <dd>
+        Çàäàííûé ôàéë ñ êàðòîé ïëîõèõ ïèêñåëîâ íå óäàëîñü îòêðûòü.
+      </dd>
+      <dt><b>LIBRAW_WARN_BAD_DARKFRAME_FILE</b></dt>
+            <dd>
+        Çàäàííûé ôàéë ñ òåìíîâûì êàäðîì íå óäàëîñü îòêðûòü.
+      </dd>
+      <dt><b>LIBRAW_WARN_BAD_DARKFRAME_DIM</b></dt>
+      <dd>
+        Òåìíîâîé êàäð ëèáî èìååò ðàçìåðû, îòëè÷àþùèåñÿ îò îáðàáàòûâàåìîãî êàäðà, ëèáî èìååò íåâåðíûé ôîðìàò (íóæåí
+        16-bit PGM, ìîæíî ñãåíåðèðîâàòü çàïóñêîì ïðèìåðà simple_dcraw -4 -D)
+      </dd>
+    </dl>
+    <a name="LibRaw_filtering"></a>
+    <h3>enum LibRaw_filtering - íàñòðîéêè ôèëüòðàöèè äàííûõ íà ýòàïå ðàñïàêîâêè è ïîñòîáðàáîòêè</h3>
+    <p>
+      Äàííîå ïåðå÷èñëåíèå îïèñûâàåò âîçìîæíûå ðåæèìû ôèëüòðàöèè RAW-äàííûõ íà ýòàïå ÷òåíèÿ RAW è ïîñòîáðàáîòêè.
+      Ðåêîìåíäàöèè ïî èñïîëüçîâàíèþ äàííûõ ðåæèìîâ îïèñàíû â 
+      <a href="API-notes-rus.html#filtering">êîììåíòàðèÿõ ê API</a>. Óñòàíîâêà ðåæèìà ôèëüòðàöèè ïðîèçâîäèòñÿ
+      óñòàíîâêîé ïàðàìåòðà <b>filtering_mode</b> äî ÷òåíèÿ äàííûõ èç ôàéëà 
+      (<a href="API-CXX-rus.html#unpack">unpack()</a>).
+    </p>
+    <p>
+      Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> óïðàâëåíèå ôèëüòðàöèåé äàííûõ îòñóòñòâóåò.
+    </p>
+    <dl>
+      <dt><b>LIBRAW_FILTERING_DEFAULT</b></dt>
+      <dd>Óìîë÷àíèå: ôèëüòðàöèÿ äàííûõ òàê, êàê ýòî äåëàåòñÿ â dcraw (ñîâìåñòèìîñòü ñ ïðåäûäóùèìè âåðñèÿìè LibRaw, ãäå
+        ôèëüòðàöèÿ íå íàñòðàèâàëàñü.
+      </dd>
+      <dt><b>LIBRAW_FILTERING_NOZEROES</b></dt>
+      <dd>
+        Óñòàíîâêà ýòîãî áèòà âûêëþ÷àåò çàòèðàíèå íóëåâûõ çíà÷åíèé äëÿ òåõ êàìåð, ãäå âîçìîæíû íóëåâûå çíà÷åíèÿ (Point
+        and Shot êàìåðû Canon, êàìåðû Panasonic è íåêîòîðûå äðóãèå).
+      </dd>
+      <dt><b>LIBRAW_FILTERING_NOBLACK</b></dt>
+      <dd>
+        Óñòàíîâêà ýòîãî áèòà âûêëþ÷àåò ÷àñòè÷íîå âû÷èòàíèå óðîâíÿ ÷åðíîãî äëÿ òåõ êàìåð, ãäå ýòî äåëàåòñÿ íà ýòàïå
+        ðàñïàêîâêè. Òàê æå, óñòàíîâêà ýòîãî áèòà îáíóëÿåò çíà÷åíèå óðîâíÿ ÷åðíîãî, àâòîìàòè÷åñêè ðàññ÷èòàííîå ïî
+        äàííûì ÷åðíîé ðàìêè ò.å. àâòîìàòè÷åñêîå âû÷èòàíèå ÷åðíîãî íà ýòàïå ïîñòïðîöåññèíãà ïðîèçâîäèòüñÿ íå áóäåò 
+        (ïðè ýòîì, ïàðàìåòð <b>user_black</b> ïðîäîëæàåò ðàáîòàòü),
+      </dd>
+      <dt><b>LIBRAW_FILTERING_NORAWCURVE</b></dt>
+      <dd>
+        Óñòàíîâêà ýòîãî áèòà âûêëþ÷àåò íàëîæåíèå òîíîâîé êðèâîé, ðàññ÷èòàííîé ïî êîíñòàíòàì èëè 
+        ñ÷èòàííîé èç ìåòàäàííûõ ôàéëà. Ïàðàìåòð âëèÿåò òîëüêî íà ðåëåâàíòíûå êàìåðû, ãäå òàêàÿ òîíîâàÿ
+        êðèâàÿ èìååòñÿ.
+      </dd>
+      <dt><b>LIBRAW_FILTERING_NONE</b></dt>
+      <dd>
+        Ýêâèâàëåíòíî (LIBRAW_FILTERING_NOZEROES|LIBRAW_FILTERING_NOBLACK|LIBRAW_FILTERING_NORAWCURVE)
+      </dd>
+      <dt><b>LIBRAW_FILTERING_LIBRAWOWN</b></dt>
+      <dd>
+        Óñòàíîâêà ýòîãî çíà÷åíèÿ îçíà÷àåò, ÷òî âû÷èòàíèå áàçîâûõ (÷åðíûõ) çíà÷åíèé è ôèëüòðàöèÿ íóëåâûõ ïèêñåëîâ áóäåò
+        ïðîèçâîäèòüñÿ ñïåöèàëèçèðîâàííûìè ïîäïðîãðàììàìè LibRaw, íàñòðîåííûìè íà êîíêðåòíûå êàìåðû (à íå íà êîíêðåòíûé
+        ôîðìàò âõîäíûõ äàííûõ, êàê ýòî ñäåëàíî â dcraw). Â íàñòîÿùåå âðåìÿ òàêèõ ïîäïðîãðàìì åùå íåò, äàííàÿ íàñòðîéêà
+        çàðåçåðâèðîâàíà íà áóäóùåå.
+      </dd>
+      <dt><b>LIBRAW_FILTERING_AUTOMATIC</b></dt>
+      <dd>
+        Êîìïðîìèññíîå çíà÷åíèå: äëÿ êàìåð, äëÿ êîòîðûé ñóùåñòâóåò ñïåöèàëèçèðîâàííàÿ ôóíêöèÿ îáðàáîòêè áóäåò
+        èñïîëüçîâàòüñÿ LIBRAW_FILTERING_LIBRAWOWN, äëÿ âñåõ îñòàëüíûõ - íàñòðîéêà LIBRAW_FILTERING_DEFAULT.
+      </dd>
+      <dt><b>LIBRAW_FILTERING_AUTOMATIC_BIT</b></dt>
+      <dd>
+        Ñëóæåáíîå çíà÷åíèå, çàðåçåðâèðîâàííîå äëÿ ïðîçðà÷íîé ïîääåðæêè àâòîìàòè÷åñêîãî ðåæèìà.
+      </dd>
+    </dl>
+    <p>
+      Äëÿ ïðîãðàìì ôîòîãðàôè÷åñêîé îáðàáîòêè RAW-äàííûõ ðåêîìåíäóåòñÿ íàñòðîéêà LIBRAW_FILTERING_AUTOMATIC. 
+      Äëÿ àíàëèçàòîðîâ èñõîäíûõ RAW-äùàííûõ ïðåäíàçíà÷åíî çíà÷åíèÿ LIBRAW_FILTERING_NONE è LIBRAW_FILTERING_NOBLACK.
+    </p>
+    <a name="LibRaw_colorstate"></a>
+    <h3>enum LibRaw_colorstate - îïèñàíèå èñòî÷íèêà äàííûõ î öâåòîâîé èíôîðìàöèè</h3>
+    <p>Äëÿ êàæäîãî òèïà èçâëåêàåìîé öâåòîâîé èíôîðìàöèè (ñì. âûøå îïèñàíèå ñòðóêòóðû imgdata.color.color_flags)
+      çàïèñûâàåòñÿ èñòî÷íèê ïîëó÷åíèÿ äàííûõ. Âîçìîæíûå çíà÷åíèÿ ïåðå÷èñëåíû íèæå.
+    </p>
+    <p>
+       <a href=API-notes-rus.html#versions>LibRaw-Lite</a> äàííûå îá èñòî÷íèêå öâåòîâîé èíôîðìàöèè îòñóòñòâóþò.
+    </p>
+    <dl>
+      <dt><b>LIBRAW_COLORSTATE_UNKNOWN</b></dt>  
+      <dd>
+        Èñòî÷íèê äàííûõ íåèçâåñòåí.
+      </dd>
+      <dt><b>LIBRAW_COLORSTATE_INIT</b></dt>  
+      <dd>
+        Ïîëå äàííûõ èíèöèàëèçèðîâàíî â óìîë÷àíèå (îáùåå äëÿ âñåõ
+        êàìåð) ïåðåä îòêðûòèåì  RAW-ôàéëà.
+      </dd>
+      <dt><b>LIBRAW_COLORSTATE_CONST</b></dt>    
+      <dd>
+        Èñòî÷íèê äàííûõ - êîíñòàíòà, çàáèòàÿ â êîä.
+      </dd>
+      <dt><b>LIBRAW_COLORSTATE_LOADED</b></dt>   
+      <dd>
+        Äàííûå çàãðóæåíû èç  RAW-ôàéëà.
+      </dd>
+      <dt><b>LIBRAW_COLORSTATE_CALCULATED</b></dt>
+      <dd>
+        Äàííûå ðàññ÷èòàíû íà îñíîâàíèè RAW-äàííûõ.
+      </dd>
+      <dt><b>LIBRAW_COLORSTATE_RESERVED1-LIBRAW_COLORSTATE_RESERVED3</b></dt>
+      <dd>
+        Çàðåçåðâèðîâàíî.
+      </dd>
+    </dl>
+    <a name="LibRaw_image_formats"></a>
+    <h3>enum LibRaw_image_formats - îïèñàíèå òèïîâ äàííûõ, ñîäåðæàùèõñÿ â ñòðóêòóðå libraw_processed_image_t</h3>
+    <p>Ïîëå type ñòðóêòóðû libraw_processed_image_t ìîæåò ïðèíèìàòü îäíî èç ñëåäóþùèõ çíà÷åíèé:
+      </p>
+    <dl>
+      <dt><b>LIBRAW_IMAGE_BITMAP</b></dt>    
+      <dd>
+         ñòðóêòóðå äàííûõ íàõîäèòñÿ îáû÷íûé RGB-bitmap (åãî ïàðàìåòðû îïðåäåëåíû â ïðî÷èõ ïîëÿõ ñòðóêòóðû).
+      </dd>
+      <dt><b>LIBRAW_IMAGE_JPEG</b></dt>    
+      <dd>
+        Â ñòðóêòóðå äàííûõ íàõîäèòñÿ îáðàç JPEG-ôàéëà, â ìåòàäàííûõ îïðåäåëåíà òîëüêî åãî äëèíà.
+      </dd>
+    </dl>
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 14:42:41 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Fri Jun  5 11:57:56 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/API-notes-eng.html b/libfspotraw/LibRaw/doc/API-notes-eng.html
new file mode 100644
index 0000000..c7f4653
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/API-notes-eng.html
@@ -0,0 +1,443 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw: General Notes on API</title>
+  </head>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+
+  <body>
+    <a href=index-eng.html>[back to Index]</a>
+    <h1>LibRaw: General Notes on API</h1>
+    <h2>Contents</h2>
+
+    <ol>
+      <li><a href="#versions">LibRaw editions</a></li>
+      <li><a href="#errors">Error Code Conventions and Error Handling</a></li>
+      <li><a href="#warnings">Nonstandard Situations That Are Not Errors</a></li>
+      <li><a href="#io">Input Layer Abstraction</a></li>
+      <li><a href="threads">Thread Safety</a></li>
+      <li><a href="#CXX">The Use of C++</a></li>
+      <li><a href="#imgdata_params">Parameters of the LibRaw::imgdata.params Structure Affecting the Behavior of
+          open_file/unpack/unpack_thumb</a></li>
+      <li><a href="#filtering">RAW-data filtering</a></li>
+      <li><a href="#masked-border">Masked pixels storage</a></li>
+      <li><a href="#memory">Memory Usage</a>
+        <ol>
+          <li><a href="#stack">Stack Usage</a></li>
+          <li><a href="#memmgr">Dynamic Memory Management</a></li>
+          <li><a href="#memuse">Dynamic Memory Usage</a>
+            <ol>
+              <li><a href="#memimage">Memory for the Decoded Image</a></li>
+              <li><a href="#memthumb">Memory for the Decoded Thumbnail</a></li>
+              <li><a href="#memprofile">Memory for the Decoded ICC Profile</a></li>
+	      <li><a name="#memraw">Memory for RAW Unpacking</a></li>
+              <li><a href="#mempostproces">Memory for Postprocessing</a></li>
+              <li><a href="#memwrite">Memory for File Writing</a></li>
+              <li><a href="#memunpack">Unpacking into memory buffer</a></li>
+            </ol>
+            </li>
+        </ol>
+      </li>
+      <li><a href="#incompat">Incompatibilities with dcraw</a>
+        <ol>
+          <li><a href="#incompat_kodak">Processing of Thumbnails from Kodak cameras</a></li>
+        </ol>
+      </li>
+    </ol>
+
+    <a name=versions></a>
+    <h2>Âàðèàíòû LibRaw</h2>
+    <p>There is three different LibRaw editions with different licensing and different feature sets:
+    </p>
+    <dl>
+      <dt><b>LibRaw/GPL License</b> (also known as LibRaw itself)</dt>
+      <dd>
+        This is Most functional LibRaw versions. All developed features are supported, all development is in this
+        edition.<br/>
+        This version can be used only with GPL-licensed programs.
+      </dd>
+      <dt><b>LibRaw/non-GPL (so called commercial edition)</dt>
+      <dd>
+        This version is targeted to non-GPL programs (commercial, non-opensource, non-GPL opensource).<br/>
+        The only difference from GPL-edition is lack of Foveon sensor support due to licensing restrictions (this code
+        derived from Dave Coffin's dcraw which is GPLed).
+        <br/>
+        This LibRaw version is not public avaliable. License is free (and royalty-free), please contact <a
+          href=mailto:info libraw org>info libraw org</a> for details.
+        </dd>
+      <dt><b>LibRaw-Lite</b> (LGPL license)</dt>
+      <dd>
+        LibRaw-Lite is a simplified LibRaw edition. There is no some improvements made for base LibRaw version:
+        <ul>
+          <li>black (masked) pixels extraction is not supported;</li>
+          <li>color data source information is missing;</li>
+          <li>it is not possible to control RAW data filtration and pre-interpolation phase preprocessing;</li>
+          <li>there is no OpenMP support;</li>
+        </ul>
+        And, of course, no Foveon support because of dcraw license restrictions.
+        <br/>
+        So, LibRaw-Lite is just a 'librarizied dcraw'. If your application needs basic RAW format support and/or can
+        rely on LibRaw's own postprocessing routines, this version is for you.
+        <br/>
+        LibRaw-Lite is LGPL licensed.
+      </dd>
+    </dl>
+
+    <a name=errors></a>
+    <h2>Error Code Conventions and Error Handling</h2>
+    <p>
+     The following conventions concern the returned errors: 
+    </p>
+    <ol>
+      <li>All functions that can return an error code have integer type of return data.</li>
+      <li>If there is no error, the return value is 0 (LIBRAW_SUCCESS).</li>
+      <li>If an error has happened in a system call, the return value is errno 
+(a positive number), which can be analyzed using strerror() or similar means.</li>
+      <li>All LibRaw's own error codes are negative; each of these errors belongs to one of two types:
+        <dl>
+          <dt><b>Non-fatal errors</b></dt>
+          <dd>
+         Non-fatal errors do not forbid execution of other functions in the processing succession
+     (e.g., <a href="API-CXX-eng.html#unpack_thumb">unpack_thumb()</a> can easily return the code corresponding to &quot;preview is absent&quot;
+     but this does not prevent further call of <a href="API-CXX-eng.html#unpack">unpack()</a>.
+          </dd>
+          <dt><b>Fatal errors</b></dt>
+          <dd>
+            In the case of fatal errors (memory shortage, input data error, data unpacking failure), the current stage of processing
+            is terminated and all allocated resouces are freed.<br/>
+            If an attempt to continue processing is made, all subsequent API calls will return the LIBRAW_OUT_OF_ORDER_CALL error.<br/>
+            At the same time, the LibRaw instance in which a fatal error has occurred can process the next RAW
+            files in the usual way (by calling <a href="API-CXX-eng.html#open_file">open_file()</a> (or other input methods),  then <a href="API-CXX-eng.html#unpack">unpack()</a>,
+            etc.). 
+            </dd>
+        </dl>
+      <li>The macro LIBRAW_FATAL_ERROR(error code) checks if an error is fatal or not.</li> 
+      <li>The error codes are <a href="API-datastruct-eng.html#errors">listed and deciphered here</a>.</li>
+    </ol>
+
+    <a name=warnings></a>
+    <h2>Nonstandard Situations That Are Not Errors</h2>
+    <p>If the program has encountered a nonstandard situation that does not prevent retrieval of some data
+     from a file, it sends a signal by setting the corresponding bit in <a href="API-datastruct-eng.html#libraw_data_t">imgdata.process_warnings</a>. 
+     The possible types of warnings are <a href="API-datastruct-eng.html#warnings">listed and deciphered here</a>.
+      </p>
+
+    <a name="io"></a>
+    <h2>Input Layer Abstraction</h2>
+    <p>
+      LibRaw uses objects derived from 
+      <a href="API-CXX-eng.html#datastream">LibRaw_abstract_datastream</a> for data input.
+      Semantics of these objects is similar to 'file with arbitrary seek' object: both read and seek
+      operations are used. 
+    </p>
+    <p>
+      Some RAW formats requires temporary switch to another data stream created on top on memory buffer for metadata
+      read. Methods for doing so are implemented in base class 
+      <a href="API-CXX-eng.html#datastream">LibRaw_abstract_datastream</a> by internal data field <b>substream</b>.
+      Look into source code of  <a href="API-CXX-eng.html#file_datastream">LibRaw_file_datastream</a> class 
+      in  <b>libraw/libraw_datastream.h</b> file for more details.
+      <br/>
+      When implementing own datastream classes, you need to take <b>substream</b> into account and pass control to
+      methods of this field if it is active (not NULL).
+    </p>
+    <p>
+      If datastream implementaton knows name of input file, it should provide fname() call. This name will be used
+      in <a href="API-CXX-eng.html#callbacks">error callbacks</a> and in guessing name of JPEG file with metadata
+      (for RAW files with external metadata).
+    </p>
+    <p>
+      For external metadata support input class should implement
+      <b>subfile_open()/subfile_close()</b> methods.
+      âîçâðàøàþò êîä îøèáêè.
+      <br/>
+      Sample of these methods implementation may be found in 
+      <a href="API-CXX-eng.html#file_datastream">LibRaw_file_datastream</a> class (look into 
+      <b>libraw/libraw_datastream.h</b> file for details).
+    </p>
+
+    <a name="threads"></a>
+    <h2>Thread safety</h2>
+    <p>
+      Thread safety is ensured if a LibRaw object is created and used within one thread. At the same time, the number
+      of threads (each with its own LibRaw object) is not limited in any way (except by memory requirements).
+      </p>
+    <p>
+      If a LibRaw object is created in one execution thread and used in another, external synchronization is
+      necessary. 
+    </p>
+    <p>
+      There is two libraries under  Unix enviroment (Linux/FreeBSD/MacOS): libraw_r.a (thread-safe) and libraw.a
+      (single-threaded, slightly faster).
+      </p>
+    <p>
+      Thread-safe library version stores intermediate unpacker data into LibRaw class data. So, several copies of
+      LibRaw, working in parallel, is possible.
+    </p>
+    <p>
+      Not thread-safe library uses global variable for intermediate data store which is faster but not reenterant.
+      This library may be used in multi-threaded apps, but only if exactly one LibRaw class copy exists in program.
+    </p>
+    <p>
+      Windows version is similar to multi-threaded Unix one.
+    </p>
+    <a name="CXX"></a>
+    <h2>The Use of C++</h2>
+    <p>
+      Exception situations within LibRaw are handled using the C++ exception mechanism. All exceptions are caught inside
+   the library functions and should not penetrate outside. 
+    </p>
+    <p>
+      Memory is allocated/freed using functions malloc(calloc)/free rather than new/delete.
+    </p>
+    <p>
+    No specific libraries (STL, Boost, smart pointers) are used. </p>
+    <p>
+    If C API is used, references to C++ calls new/delete still remain, and so linking with libstdc++(Unix)/....(Windows) is necessary. 
+    </p>
+    <a name="imgdata_params"></a>
+    <h2>Parameters of the LibRaw::imgdata.params Structure Affecting the Behavior of open_file/unpack/unpack_thumb</h2>
+    <p>
+      Most data fields of structure LibRaw::imgdata.params affect only  <a href="API-CXX-eng.html#dcrawemu">data
+        postprocessing</a>,  but there are some exceptions, which have been inherited by the current version of LibRaw
+      from/ dcraw source texts (these dependences will be gradually removed).
+       <dl>
+      <dt><b>imgdata.params.use_camera_matrix and imgdata.params.use_camera_wb</b></dt>
+      <dd>
+        These fields affect loading of RAW data for cameras with a color matrix.<br/>
+        <b>Attention!</b> If parameter <b>imgdata.params.use_camera_matrix</b> is not set by the user, it is copied from 
+      <b>imgdata.params.use_camera_wb</b> at the stage of file opening.
+      </dd>
+      <dt><b>imgdata.params.user_flip</b></dt>
+      <dd>
+        If this parameter is greater than or equal to zero, assignment <code>imgdata.sizes.flip = imgdata.params.user_flip</code> is
+     performed at the <a href="API-CXX-eng.html#open_file">open_file()</a> stage.
+       </dd>
+      <dt><b>imgdata.params.shot_select</b></dt>
+      <dd>
+        This parameter makes it possible to select the number of the extracted image for data formats in which storage
+    of several RAW images in one data file is possible. 
+      </dd>
+      <dt><b>imgdata.params.half_size</b></dt>
+      <dd>
+        Affects RAW data loading for Phase One and Sinar backs. Also, it this parameter is set then image bitmap
+        will be reduced by half in each dimension. In later case, all 4 components of bitmap will be filled during
+        data extraction phase.
+      </dd>
+      <dt><b>imgdata.params.threshold, imgdata.params.aber</b></dt>
+      <dd>
+        If these parameters used, then half-sized bitmap will be used for data unpacking. See above for details.
+      </dd>
+
+      <dt><b>imgdata.params.filtering_mode</b></dt>
+      <dd>
+        Affects RAW data loading for cameras with black level subtraction/de-banding during RAW read phase:
+        Canon A600, A5, CRW/CR2; cameras with LJPEG-compression (some Nikon, Kodak and Hasselblad cameras).
+      </dd>
+      <dt><b>imgdata.params.use_camera_wb</b></dt>
+      <dd>
+        Affects loading of white balance matrix for Leaf backs.
+      </dd>
+      <dt><b>imgdata.params.document_mode</b></dt>
+      <dd>
+        <b>Does not affect data reading in the current version of LibRaw</b>. In dcraw, this parameter affects the thumbnail data
+      for certain Kodak cameras and the RAW data of images for cameras with a Foveon matrix.
+      </dd>
+      </dl>
+
+    <a name="filtering"></a>
+    <h2>RAW-data filtration</h2>
+    <p>
+      During RAW unpacking and post-process stages LibRaw can filter RAW data:
+    </p>
+    <ul>
+      <li>Black level subtraction (required if not already done by camera firmware).</li>
+      <li>Zero pixels removal (averaging with nearest pixel values).</li>
+      <li>Tone curve operations on RAW-data.</li>
+    </ul>
+    <p>
+      There is no RAW data filtration control in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>.
+    </p>
+
+    <p>
+      Current LibRaw version allows tuning of filtration process by setting <b>imgdata.params.filtering_mode</b>
+      option to one of <a href="API-datastruct-eng.html#LibRaw_filtering">enum LibRaw_filtering</a> vales:
+      </p>
+    <ul>
+      <li>Dcraw-compatible filtration. This mode is default for old LibRaw versions compatibility. This mode
+        is not recommended for new applications.</li>
+      <li>One or several (or all) filtering stages can be turned off. This mode recommended for
+        RAW analysers and advanced data filtration made by calling program (this programs may 
+        calculate black level by analyzing <a href=#masked-border>masked frame data</a>.</li>
+      <li>Automatic selection of best filtration  avaliable in LibRaw (e.g. camera/model specific
+        routines). This mode is recommended for most applications.
+        </li>
+      </ul>
+    <p>
+      Current LibRaw version cannot turn off black subtraction for Foveon-sensor cameras.
+    </p>
+    <a name="masked-border"></a>
+    <h2>Masked pixels storage</h2>
+    <p>
+      Some of RAW images contains data for not-active ("black","masked") pixels. For some of these formats
+      LibRaw can extract these pixels values and store it in 
+      <a href="API-datastruct-eng.html#libraw_masked_t">imgdata.masked_pixels</a> data structure. 
+      These values can be explored for:
+    </p>
+    <ul>
+      <li>Black level calculation (with banding suppression on some cameras).</li>
+      <li>Noise level calculation, e.g. per-channel noise. This is useful for cameras with per-channel
+        amplification.</li>
+    </ul>
+    <p>Masked pixel data avaliable only for bayer-pattern data (one component per pixel) and only for cameras
+      with masked frame. Masked pixels extraction for other color models (Foveon, Canon sRAW, Kodak YRGB, Sinar 4-shot
+      files) will possibly be added in future LibRaw versions.</p>
+    <p>
+      LibRaw provides interface for merging active pixel data and masked pixels into one bitmap:
+      <a href="API-CXX-eng.html#add_masked_borders_to_bitmap">add_masked_borders_to_bitmap()</a>.
+      This call is useful for RAW analyzers.
+    </p>
+    <p>
+      There is no masked pixel storage and associated API calls in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>.
+    </p>
+
+    <a name="memory"></a>
+    <h2>Memory Usage</h2>
+    <a name="stack"></a>
+    <h3>Stack Usage</h3>
+    <p>
+      An instance of the LibRaw class has its own size about <b>100 Kb</b>; if constructions like <code>LibRaw
+        imageProcessor;</code>  are used, this memory is stack-allocated. 
+    </p>
+    <p>
+      Methods of class LibRaw (and C API calls) may allocate up to 130-140 Kb of data on the stack (to place auto
+      variables) during their work. 
+    </p>
+    <p>Thus, the work of one LibRaw instance may require about 250 Kb of stack memory. This is not a problem for most
+      contemporary architectures.  However, when working in a multithreaded environment, one should not forget to
+      allocate a sufficient amount of memory for the thread stack. 
+    </p>
+    <p>In the case of dynamic allocation (<code>LibRaw *iProcessor = new LibRaw;</code>), the requirements to stack
+      memory will decrease by 100 Kb, which is the size of a class instance). If <a href="API-C-eng.html">C API</a> is
+      used, the LibRaw instance is allocated dynamically.
+    </p>
+
+    <a name="memmgr"></a>
+    <h3>Dynamic Memory Management</h3>
+    <p>LibRaw keeps record of all allocated dynamic memory blocks; in the case of an exceptional situation (fatal
+      error), they are all freed. The code for keeping this record is fairly primitive and not designed to consider
+      allocation of many blocks (in the normal situation, allocation takes place from 2 to 6 times during file
+      processing); this fact should be taken into account by developers trying to add new methods to LibRaw.
+     </p>
+    <a name="memuse"></a>
+    <h3>Dynamic Memory Usage</h3>
+    <p>LibRaw uses dynamic memory</p>
+    <ul>
+      <li>for the decoded image;</li>
+      <li>for the decoded thumbnail;</li>
+      <li>for the ICC profile retrieved from the RAW file (if available);</li>
+      <li>for temporary data at the stage of RAW file unpacking;</li>
+      <li>for temporary data at the stage of postprocessing and result output;</li>
+      <li>for reading of the RAW source file (only under Win32).</li>
+    </ul>
+    <a name="memimage"></a>
+    <h4>Memory for the Decoded Image</h4>
+    <p>
+      To simplify further processing, memory for the extracted RAW data is allocated with a fourfold (for Bayer sensor
+      cameras) excess: <b>for each pixel, four 16-bit components are available</b> (three of them will be zero after
+      RAW unpacking). Thus, one can perform debayer and other postprocessing actions directly in the same buffer as
+      the one used for data extraction, but the required amount of memory becomes four times higher. <br/>
+   <b>Hence, the size of memory for the image buffer is 6-10 times greater than the size of the source RAW
+        file.</b><br/> <i>It is quite likely that allocation of this buffer in next versions of LibRaw will be more
+        economical, under the condition that postprocessing calls inherited from dcraw will not be used.</i>.
+    </p>
+    <p>The buffer for the decoded image is allocated upon calling <a href="API-CXX-eng.html#unpack">unpack()</a> and
+      freed upon calling <a href="API-CXX-eng.html#recycle">recycle()</a>.
+    </p> 
+    <a name="memthumb"></a>
+    <h4>Memory for the Decoded Thumbnail</h4>
+    <p>
+      Memory for the thumbmail is allocated upon calling <a href="API-CXX-eng.html#unpack_thumb">unpack_thumb()</a> and freed upon
+      calling <a href="API-CXX-eng.html#recycle">recycle()</a>. The size of the allocated buffer is precisely adjusted to the thumbnail size,
+     i.e., up to several Mb. 
+    </p>
+
+    <a name="memprofile"></a>
+    <h4>Memory for the Decoded ICC Profile</h4>
+    <p>
+      Memory for the ICC profile is allocated upon calling  <a href="API-CXX-eng.html#unpack_profile">unpack_profile()</a> and freed upon
+      calling <a href="API-CXX-eng.html#recycle">recycle()</a>. The size of the allocated buffer is precisely adjusted to the ICC profile size,
+     i.e., up to several hundred Kb. 
+    </p>
+    <a name="memraw"></a>
+    <h4>Memory for RAW Unpacking</h4>
+    <p>
+      Memory for temporary buffer needed during RAW data unpacking may be allocated during the work of <a
+        href="API-CXX-eng.html#unpack">unpack()</a> and freed before completion of this function. The sizes of the allocated
+    buffers are small, up to tens of Kb. 
+    </p>
+
+    <a name="mempostproces"></a>
+    <h4>Memory for Postprocessing</h4>
+    <p>During image postprocessing (inherited from dcraw), memory for the histogram (128 Kb) is allocated.
+      This memory is allocated upon calling <a
+        href="API-CXX-eng.html#dcraw_document_mode_processing">dcraw_document_mode_processing()</a> and
+      <a href="API-CXX-eng.html#dcraw_process">dcraw_process()</a> and freed upon calling
+      <a href="API-CXX-eng.html#recycle">recycle()</a>.
+    </p>
+    <p>
+      In addition, during the work of <a href="API-CXX-eng.html#dcraw_process">dcraw_process()</a> and during the
+   usage of some available possibilities, like
+     </p>
+      <ul>
+      <li>rotation of images from FUJI cameras;</li>
+      <li>correction of chromatic aberrations;</li>
+      <li>image size changes (including correction of non-square pixels);</li>
+      <li>highlight recovery;</li>
+    </ul>
+    <p>
+     a temporary buffer with the size equal to the size of the resultant image (6-8 bytes per pixel for various processing stages)
+ will be allocated. As soon as the intermediate substage of processing is completed, the buffer with the previous copy 
+   of the image will be freed.<br/>
+  If postprocessing is not used, then temporary buffers are not allocated.
+    </p>
+
+    <a name="memwrite"></a>
+    <h4>Memory for File Writing</h4>
+    <p>
+      Upon calling <a href="API-CXX-eng.html#dcraw_ppm_tiff_writer">dcraw_ppm_tiff_writer()</a>, memory for a single row of the
+   output image is allocated. The allocated memory is freed before the end of this call. 
+    </p>
+    <a name="memunpack"></a>
+    <h4>Unpacking into memory buffer</h4>
+    <p>
+      Functons <a href="API-CXX-eng.html#dcraw_make_mem_image">dcraw_make_mem_image()</a> è 
+      <a href="API-CXX-eng.html#dcraw_make_mem_thumb">dcraw_make_mem_thumb()</a> (and complementary calls in C-API)
+      allocates memory for entire output datasets  (full RGB bitmap and thumbnail, respectively).
+      <b>Calling function should free() this memory themself.</b>
+    </p>
+
+
+    <a name="incompat"></a>
+    <h2>Incompatibilities with dcraw</h2>
+    <a name="incompat_kodak"></a>
+    <h3>Processing of Thumbnails from Kodak cameras</h3>
+    <p>In some Kodak cameras, the preview (thumbnail) is stored in the form of uncorrected image. During its extraction using
+   <b>dcraw -e</b>, the white balance, color conversion, and other settings are the same as those used for extraction of the main RAW data
+   (including defect removal and dark frame subtraction, which is erroneous, since the image size is different).
+    <br/>
+      In LibRaw::unpack_thumb() calls, the white balance taken from the camera (&quot;as shot&quot;) is used and no settings from
+     imgdata.params are considered.
+    </p>
+    <p>
+      For all other cameras, thumbnails are extracted &quot;as is,&quot; without any color conversions, both in dcraw and in LibRaw.
+    </p>
+
+    <a href=index-eng.html>[back to Index]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 10:05:08 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:56 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/API-notes-rus.html b/libfspotraw/LibRaw/doc/API-notes-rus.html
new file mode 100644
index 0000000..f665485
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/API-notes-rus.html
@@ -0,0 +1,469 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw: îáùèå êîììåíòàðèè ê  API</title>
+  </head>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+
+  <body>
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <h1>LibRaw: îáùèå êîììåíòàðèè ê  API</h1>
+    <h2>Ñîäåðæàíèå</h2>
+
+    <ol>
+      <li><a href="#versions">Âàðèàíòû LibRaw</a></li>
+      <li><a href="#errors">Ñîãëàøåíèÿ î êîäàõ îøèáîê è äåéñòâèÿõ ïðè îøèáêàõ</a></li>
+      <li><a href="#warnings">Íåøòàòíûå ñèòóàöèè, íå ÿâëÿþùèåñÿ îøèáêîé</a></li>
+      <li><a href="#io">Àáñòðàêöèÿ ââîäà äàííûõ</a></li>
+      <li><a href="threads">Thread safety</a></li>
+      <li><a href="#CXX">Èñïîëüçîâàíèå C++</a></li>
+      <li><a href="#imgdata_params">Ïàðàìåòðû ñòðóêòóðû LibRaw::imgdata.params, âëèÿþùèå íà ïîâåäåíèå
+          open_file/unpack/unpack_thumb</a></li>
+      <li><a href="#filtering">Ôèëüòðàöèÿ RAW-äàííûõ</a></li>
+      <li><a href="#masked-border">Õðàíåíèå äàííûõ ìàñêèðîâàííûõ ïèêñåëîâ</a></li>
+      <li><a href="#memory">Èñïîëüçîâàíèå ïàìÿòè</a>
+        <ol>
+          <li><a href="#stack">Èñïîëüçîâàíèå ñòåêà</a></li>
+          <li><a href="#memmgr">Óïðàâëåíèå äèíàìè÷åñêîé ïàìÿòüþ</a></li>
+          <li><a href="#memuse">Èñïîëüçîâàíèå äèíàìè÷åñêîé ïàìÿòè</a>
+            <ol>
+              <li><a href="#memimage">Ïàìÿòü äëÿ ðàñêîäèðîâàííîãî èçîáðàæåíèÿ</a></li>
+              <li><a href="#memthumb">Ïàìÿòü äëÿ ðàñêîäèðîâàííîãî thumbnail</a></li>
+              <li><a href="#memprofile">Ïàìÿòü äëÿ ðàñêîäèðîâàííîãî ICC-profile</a></li>
+              <li><a href="#rawmem">Ïàìÿòü äëÿ ðàñïàêîâêè RAW</a></li>
+              <li><a href="#mempostproces">Ïàìÿòü äëÿ ïîñòîáðàáîòêè</a></li>
+              <li><a href="#memwrite">Ïàìÿòü äëÿ çàïèñè ôàéëà</a></li>
+              <li><a href="#memunpack">Ïàìÿòü äëÿ ðàñïàêîâêè â áóôåð â ïàìÿòè</a></li>
+            </ol>
+            </li>
+        </ol>
+      </li>
+      <li><a href="#incompat">Íåñîâìåñòèìîñòè ñ dcraw</a>
+        <ol>
+          <li><a href="#incompat_kodak">Îáðàáîòêà Thumbnails îò êàìåð Kodak</a></li>
+        </ol>
+      </li>
+    </ol>
+
+    <a name=versions></a>
+    <h2>Âàðèàíòû LibRaw</h2>
+    <p>Áèáëèîòåêà LibRaw ñóùåñòâóåò â òðåõ âàðèàíòàõ (ðåäàêöèÿõ), îòëè÷àþùèõñÿ íàáîðîì ïîääåðæèâàåìûõ ôîðìàòîâ è
+      ñäåëàííûìè óëó÷øåíèÿìè: 
+    </p>
+    <dl>
+      <dt><b>LibRaw c  GPL-ëèöåíçèåé</b> (äàëåå âåçäå ïðîñòî LibRaw)</dt>
+      <dd>
+        Îñíîâíàÿ è íàèáîëåå ôóíêöèîíàëüíàÿ âåðñèÿ áèáëèîòåêè, ïîääåðæèâàþùàÿ âñþ ðàçðàáîòàííóþ ôóíêöèîíàëüíîñòü. Âñÿ
+        ðàçðàáîòêà âåäåòñÿ â ýòîé âåðñèè, âñå äðóãèå ðåäàêöèè èçãîòàâëèâàþòñÿ èç ýòîé âåðñèè.<br/>
+        Ýòà âåðñèÿ áèáëèîòåêè ìîæåò  áûòü èñïîëüçîâàíà òîëüêî â ïðîãðàììàõ, ðàñïðîñòðàíÿåìûõ ïî ëèöåíçèè GPL âåðñèè 2
+        (èëè áîëåå ïîçäíåé âåñèñèè).
+      </dd>
+      <dt><b>LibRaw äëÿ èñïîëüçîâàíèÿ â íå-GPL ïðîãðàììàõ</dt>
+      <dd>
+        Ýòà âåðñèÿ ïðåäíàçíà÷åíà äëÿ èñïîëüçîâàíèÿ â ïðîãðàììàõ, ðàñïðîñòðàíÿåìûõ íå ïî GPL-ëèöåíçèè. Åäèíñòâåííûì
+        îòëè÷èåì îò áàçîâîé âåðñèè LibRaw ÿâëÿåòñÿ îòñóòñòâèå ïîääåðæêè ñåíñîðîâ Foveon, ÷òî ñâÿçàíî ñ ëèöåíçèîííûìè
+        îãðàíè÷åíèÿìè: ýòà ÷àñòü êîäà, óíàñëåäîâàííîãî îò dcraw ðàñïðîñòðàíÿåòñÿ òîëüêî ïîä GPL.<br/>
+        Ýòà âåðñèÿ LibRaw íå ÿâëÿåòñÿ ïóáëè÷íî äîñòóïíîé, äëÿ ïîëó÷åíèÿ áåñïëàòíîé ëèöåíçèè íà èñïîëüçîâàíèå <a
+          href=mailto:info libraw org>ïèøèòå</a>.
+        </dd>
+      <dt><b>LibRaw-Lite</b></dt>
+      <dd>
+        LibRaw-Lite - ýòî óïðîùåííàÿ âåðñèÿ LibRaw, íå ñîäåðæàùàÿ ìíîãèõ óëó÷øåíèé, ñäåëàííûõ â LibRaw îòíîñèòåëüíî
+        dcraw.  ÷àñòíîñòè:
+        <ul>
+          <li>îòñóòñòâóåò èçâëå÷åíèå ÷åðíîé ðàìêè;</li>
+          <li>îòñóòñòâóåò èíôîðìàöèÿ îá èñòî÷íèêå öâåòîâûõ äàííûõ;</li>
+          <li>îòñóòñòâóåò âîçìîæíîñòü îòêëþ÷èòü âû÷èòàíèå óðîâíÿ ÷åðíîãî è ïðåïðîöåññèíã RAW-äàííûõ;</li>
+          <li>îòñóòñòâóåò ïîääåðæêà ïàðàëëåëüíîé îáðàáîòêè (OpenMP);</li>
+          <li>îáðàáîòêà äàííûõ ñ êàìåð Fuji ïðîèñõîäèò òàê æå, êàê â dcraw: ñ èçâëå÷åíèåì äàííûõ â ïîâåðíóòûé bitmap è
+            äàëüíåéøèé ïîâîðîò ñ ìàñøòàáèðîâàíèåì. Íåïîâåðíóòûå RAW-äàííûå íè íà êàêîì ýòàïå íå âîçíèêàþò.</li>
+        </ul>
+        Ïîìèìî ýòîãî, íå ïîääåðæèâàåòñÿ ðàñïàêîâêà äàííûõ ñ ñåíñîðîâ Foveon â ñèëó ëèöåíçèîííûõ îãðàíè÷åíèé dcraw.
+        <br/>
+        Äðóãèìè ñëîâàìè, ýòî ïðîñòî áèáëèîòåêà íà îñíîâå dcraw (ñ ó÷åòîì ëèöåíçèè íà êîä ðàñïàêîâêè Foveon) áåç
+        äîïîëíèòåëüíûõ óëó÷øåíèé.
+        <br/>
+        Äàííàÿ âåðñèÿ ðàñïðîñòðàíÿåòñÿ íà óñëîâèÿõ LGPL è ïðåäíàçíà÷àåòñÿ äëÿ ïðîãðàìì, êîòîðûì äîñòàòî÷íî âñòðîåííûõ
+        â LibRaw(-Lite) ïðîöåäóð ïîñòîáðàáîòêè RAW.
+      </dd>
+    </dl>
+    <a name=errors></a>
+    <h2>Ñîãëàøåíèÿ î êîäàõ îøèáîê è äåéñòâèÿõ ïðè îøèáêàõ</h2>
+    <p>
+      Ïðèíÿòû ñëåäóþùèå ñîãëàøåíèÿ î âîçâðàùàåìûõ îøèáêàõ
+    </p>
+    <ol>
+      <li>Âñå ôóíêöèè, êîòîðûå ìîãóò âåðíóòü êîä îøèáêè èìåþò öåëûé  òèï âîçâðàùàåìûõ äàííûõ.</li>
+      <li>Ïðè îòñóòñòâèè îøèáêè âîçâðàùàåòñÿ 0 (LIBRAW_SUCCESS).</li>
+      <li>Åñëè ñëó÷èëàñü îøèáêà â ñèñòåìíîì âûçîâå, òî âîçâðàùàåòñÿ çíà÷åíèå errno (ýòî ïîëîæèòåëüíîå ÷èñëî), êîòîðîå
+        ìîæåò áûòü ïðîàíàëèçèðîâàíî ñ ïîìîùüþ strerror() èëè ïîäîáíûõ ñðåäñòâ.</li>
+      <li>Âñå ñîáñòâåííûå êîäû îøèáîê LibRaw - îòðèöàòåëüíûå, ïðè ýòîì îøèáêè äåëÿòñÿ íà äâà òèïà:
+        <dl>
+          <dt><b>Íåôàòàëüíûå îøèáêè</b></dt>
+          <dd>
+            Íåôàòàëüíûå îøèáêè íå çàïðåùàþò èñïîëíåíèå äðóãèõ ôóíêöèé â ïîñëåäîâàòåëüíîñòè îáðàáîòêè (íàïðèìåð,
+            <a href="API-CXX-rus.html#unpack_thumb">unpack_thumb()</a> âïîëíå ìîæåò âåðíóòü êîä, îçíà÷àþùèé "preview
+            îòñóòñòâóåò" è ýòî íå ìåøàåò çàòåì âûçâàòü <a href="API-CXX-rus.html#unpack">unpack()</a>).
+          </dd>
+          <dt><b>Ôàòàëüíûå îøèáêè</b></dt>
+          <dd>
+             ñëó÷àå âîçíèêíîâåíèÿ ôàòàëüíîé îøèáêè (íåõâàòêà ïàìÿòè, îøèáêà âî âõîäíûõ äàííûõ, íåâîçìîæíîñòü
+            ðàñïàêîâêè äàííûõ) òåêóùàÿ ñòàäèÿ îáðàáîòêè çàâåðøàåòñÿ, âñå àëëîöèðîâàííûå ðåñóðñû îñâîáîæäàþòñÿ.<br/>
+             ñëó÷àå ïîïûòêè ïðîäîëæåíèÿ îáðàáîòêè -  âñå ïîñëåäóùèå âûçîâû API âåðíóò îøèáêó
+            LIBRAW_OUT_OF_ORDER_CALL.<br/>
+            Âìåñòå ñ òåì, ýêçåìïëÿð LibRaw, â êîòîðîì âîçíèêëà ôàòàëüíàÿ îøèáêà, ìîæåò 
+            îáðàáàòûâàòü ñëåäóùèå RAW-ôàéëû îáû÷íûì îáðàçîì (âûçîâ 
+            <a href="API-CXX-rus.html#open_file">open_file()</a> (ëèáî 
+            <a href="API-CXX-rus.html#open_datastream">open_datastream()</a>, 
+            <a href="API-CXX-rus.html#open_buffer">open_buffer()</a>) 
+            çàòåì <a href="API-CXX-rus.html#unpack">unpack()</a> è òàê äàëåå). 
+            </dd>
+        </dl>
+      <li>Ïðîâåðêà ôàòàëüíîñòè îøèáêè îñóùåñòâëÿåòñÿ ìàêðîñîì LIBAW_FATAL_ERROR(êîä îøèáêè)</li> 
+      <li>Êîäû îøèáîê <a href="API-datastruct-rus.html#errors">ïåðå÷èñëåíû è ðàñøèôðîâàíû çäåñü</a>.</li>
+    </ol>
+
+    <a name=warnings></a>
+    <h2>Íåøòàòíûå ñèòóàöèè, íå ÿâëÿþùèåñÿ îøèáêîé</h2>
+    <p> ñëó÷àå âîçíèêíîâåíèÿ íåøòàòíîé ñèòóàöèè, íå ìåøàþùåé ïîëó÷èòü èç ôàéëà êàêèå-òî äàííûå, î íåé áóäåò
+      ïðîñèãíàëèçèðîâàíî ïóòåì âçâåäåíèÿ ñîîòâåòñòâóþùåãî áèòà  â <a
+        href="API-datastruct-rus.html#libraw_data_t">imgdata.process_warnings</a>. Âîçìîæíûå òèïû ïðåäóïðåæäåíèé  <a
+        href=href="API-datastruct-rus.html#warnings>ïåðå÷èñëåíû è ðàñøèôðîâàíû çäåñü</a>.
+      </p>
+
+    <a name="io"></a>
+    <h2>Àáñòðàêöèÿ ââîäà äàííûõ</h2>
+    <p>
+      LibRaw èñïîëüçóåò äëÿ ÷òåíèÿ ôàéëà îáúåêò, ïðîèçâîäíûé îò êëàññà 
+      <a href="API-CXX-rus.html#datastream">LibRaw_abstract_datastream</a>.  
+      Cåìàíòèêà ýòîãî êëàññà ñõîæà ñ ñåìàíòèêîé îáúåêòîâ òèïà "ôàéë ñ ïðîèçâîëüíûì ïîçèöèîíèðîâàíèåì", îáúåêò
+      ðåàëèçóþùèé ââîä äîëæåí ïîääåðæèâàòü îïåðàöèè ïîçèöèîíèðîâàíèÿ è ÷òåíèÿ.
+    </p>
+    <p>
+      Äëÿ ðàáîòû ñ íåêîòîðûìè ôîðìàòàìè, ñîäåðæàùèìè çàøèôðîâàíûå êóñêè TIFF-êàòàëîãîâ, òðåáóåòñÿ âðåìåííîå
+      ïåðåêëþ÷åíèå ââîäà íà âðåìåííûé ïîòîê, ïðèâÿçàííûé ê ñîçäàííîìó LibRaw áóôåðó â ïàìÿòè. Ýòà ôóíêöèîíàëüíîñòü
+      ðåàëèçóåòñÿ â áàçîâîì êëàññå  <a href="API-CXX-rus.html#datastream">LibRaw_abstract_datastream</a> ÷åðåç
+      èìåþùååòñÿ òàì ïîëå <b>substream</b>, êîòîðîå ÿâëÿåòñÿ óêàçàòåëåì íà îáúåêò êëàññà 
+      <a href="API-CXX-rus.html#buffer_datastream">LibRaw_buffer_datastream</a>.  
+      <br/>
+      Ïðè èñïîëüçîâàíèè ñîáñòâåííûõ ðåàëèçàöèé ïîòîêîâ äàííûõ, íåîáõîäèìî â ìåòîäàõ ÷òåíèÿ è ïîçèöèîíèðîâàíèÿ
+      ïðîâåðÿòü èíèöèàëèçèðîâàííîñòü ýòîãî ïîëÿ è åñëè îíî íå íóëåâîå - ïåðåäàâàòü óïðàâëåíèå òóäà. Ïîäðîáíåå
+      ñì. ðåàëèçàöèþ êëàññà 
+      <a href="API-CXX-rus.html#file_datastream">LibRaw_file_datastream</a> â çàãîëîâî÷íîì ôàéëå
+      <b>libraw/libraw_datastream.h</b>.
+    </p>
+    <p>
+      Åñëè ïîòîê äàííûõ çíàåò èìÿ îáðàáàòûâàåìîãî ôàéëà â ôàéëîâîé ñèñòåìå, îí äîëæåí óìåòü ñîîáùèòü åãî âñåì, êòî â
+      íåì íóæäàåòñÿ âûçîâîì <b>fname()</b>. Ýòî èìÿ áóäåò èñïîëüçîâàíî ïðè âûçîâå 
+      <a href="API-CXX-rus.html#callbacks">callbacks</a> (óâåäîìèòåëÿõ îá îøèáêàõ) è ìîæåò áûòü èñïîëüçîâàíî äëÿ
+      ãåíåðàöèè èìåíè ôàéëà ñ ìåòàäàííûìè, åñëè ýòî íóæíî äëÿ ðàñïàêîâûâàåìîãî ôîðìàòà.
+    </p>
+    <p>
+      Äëÿ íåêîòîðûõ ôîðìàòîâ äàííûõ ìåòàäàííûå (ýêñïîçèöèîííûå ïàðàìåòðû, áàëàíñ áåëîãî) íå õðàíÿòñÿ â RAW-ôàéëå, íî
+      ìîãóò áûòü ñ÷èòàíû èç JPEG-âåðñèè òîãî æå ñíèìêà. Åñëè ðåàëèçàöèÿ  íàäñòðîéêè íàä
+      <a href="API-CXX-rus.html#datastream">LibRaw_abstract_datastream</a> óìååò âåðíóòü èìÿ îáðàáàòûâàåìîãî ôàéëà ïðè
+      âûçîâå <b>fname()</b>, òî ïðåäïîëàãàåòñÿ, ÷òî äëÿ òàêîé ðåàëèçàöèè âîçìîæíî âðåìåííîå ïåðåêëþ÷åíèå ïîòîêà ââîäà
+      íà äðóãîé ôàéë. ×òîáû ýòî áûëî äåéñòâèòåëüíî òàê, 
+      <a href="API-CXX-rus.html#own_datastreams">ðåàëèçàöèÿ ïîòîêà äàííûõ</a>  äîëæíà ðåàëèçîâàòü ìåòîäû
+      <b>subfile_open()/subfile_close()</b>. Ñòàíäàðòíûå ðåàëèçàöèè, óíàñëåäîâàííûå îò áàçîâîãî êëàññà, ïðîñòî
+      âîçâðàøàþò êîä îøèáêè.
+      <br/>
+      Ïðèìåð ðåàëèçàöèè ìåòîäîâ îòêðûòèÿ äîïîëíèòåëüíîãî ïîòîêà äàííûõ ìîæíî ïîäñìîòðåòü â ðåàëèçàöèè êëàññà
+      <a href="API-CXX-rus.html#file_datastream">LibRaw_file_datastream</a> â çàãîëîâî÷íîì ôàéëå
+      <b>libraw/libraw_datastream.h</b>.
+    </p>
+
+    <a name="threads"></a>
+    <h2>Thread safety</h2>
+    <p>
+      Thread safety îáåñïå÷èâàåòñÿ, åñëè îáúåêò LibRaw ñîçäàåòñÿ è ècïîëüçóåòñÿ âíóòðè îäíîãî thread. Ïðè ýòîì
+      êîëè÷åñòâî threads (êàæäàÿ ñî ñâîèì îáúåêòîì LibRaw) íè÷åì íå îãðàíè÷åíî (êðîìå ïîòðåáíîñòåé â ïàìÿòè).
+      </p>
+    <p>
+       ñëó÷àå ñîçäàíèÿ îáúåêòà LibRaw â îäíîì ïîòîêå èñïîëíåíèÿ, à èñïîëüçîâàíèÿ â äðóãîì - íåîáõîäèìà âíåøíÿÿ
+      ñèíõðîíèçàöèÿ, íå äàþùàÿ ïðîèçâåñòè îäíîâðåìåííûé äîñòóï ê îäíîìó îáúåêòó.
+    </p>
+    <p>
+      Â Unix (Linux/FreeBSD/MacOS) ñîáèðàþòñÿ äâå âåðñèè áèáëèîòåêè: thread-safe âåðñèÿ libraw_r.a è áîëåå áûñòðàÿ
+      íå thread-safe libraw.a.
+      </p>
+    <p>
+      Thread-safe âåðñèÿ èñïîëüçóåò äëÿ õðàíåíèÿ ëîêàëüíûõ äàííûõ ïîëÿ â êëàññå LibRaw, ÷òî ïîçâîëÿåò èìåòü íåñêîëüêî
+      ýêçåìïëÿðîâ êëàññà LibRaw, ðàáîòàþùèõ îäíîâðåìåííî.
+    </p>
+    <p>
+      Íå thread-safe âåðñèÿ õðàíèò ïðîìåæóòî÷íûå äàííûå â ãëîáàëüíûõ ïåðåìåííûõ, ÷òî íåñêîëüêî áûñòðåå. Íå thread-safe
+      âåðñèÿ ìîæåò èñïîëüçîâàòüñÿ è â multithreaded-ïðèëîæåíèÿõ, íî òîëüêî åñëè ýêçåìïëÿð êëàññà LibRaw ãàðàíòèðîâàííî
+      îäèí.
+    </p>
+    <p>
+      Ïîä Windows ñîáèðàåòñÿ òîëüêî thread-safe âåðñèÿ.
+    </p>
+    <a name="CXX"></a>
+    <h2>Èñïîëüçîâàíèå C++</h2>
+    <p>
+      Ïðè îáðàáîòêå èñêëþ÷èòåëüíûõ ñèòóàöèé âíóòðè LibRaw èñïîëüçóåòñÿ  ìåõàíèçì C++ exceptions. Âñå èñêëþ÷åíèÿ
+      ïåðåõâàòûâàþòñÿ âíóòðè ôóíêöèé áèáëèîòåêè è ïðîíèêàòü íàðóæó íå äîëæíû.
+    </p>
+    <p>
+      Äëÿ àëëîêàöèè/îñâîáîæäåíèÿ ïàìÿòè èñïîëüçóþòñÿ ôóíêöèè malloc(calloc)/free,  à íå new/delete.
+    </p>
+    <p>Êàêèå-ëèáî ñïåöèôè÷åñêèå áèáëèîòåêè (STL, Boost, smart pointers) - íå èñïîëüçóþòñÿ. </p>
+    <p>Ïðè èñïîëüçîâàíèè  Ñ API ññûëêè íà C++-âûçîâû new/delete îñòàþòñÿ, ïîýòîìó ëèíêîâàòüñÿ íàäî ñ
+      libstdc++(Unix)/....(Windows). 
+    </p>
+    <a name="imgdata_params"></a>
+    <h2>Ïàðàìåòðû ñòðóêòóðû LibRaw::imgdata.params, âëèÿþùèå íà ïîâåäåíèå open_file/unpack/unpack_thumb</h2>
+    <p>
+      Áîëüøèíñòâî ïîëåé äàííûõ ñòðóêòóðû LibRaw::imgdata.params âëèÿþò òîëüêî íà <a
+        href="API-CXX-rus.html#dcrawemu">ïîñòîáðàáîòêó äàííûõ</a>, íî åñòü ðÿä èñêëþ÷åíèé, óíàñëåäîâàííûõ òåêóùåé
+      âåðñèåé LibRaw îò îñîáåííîñòåé èñõîäíûõ òåêñòîâ dcraw (ïîñòåïåííî ýòè çàâèñèìîñòè áóäóò óäàëÿòüñÿ).
+      <dl>
+      <dt><b>imgdata.params.use_camera_matrix è imgdata.params.use_camera_wb</b></dt>
+      <dd>
+        Âëèÿþò íà çàãðóçêó RAW-äàííûõ äëÿ êàìåð ó êîòîðûõ åñòü colormatrix.<br/>
+        <b>Âíèìàíèå!</b> Åñëè ïàðàìåòð <b>imgdata.params.use_camera_matrix</b> íå óñòàíîâëåí ïîëüçîâàòåëåì, òî îí
+        êîïèðóåòñÿ èç <b>imgdata.params.use_camera_wb</b> íà ýòàïå îòêðûòèÿ ôàéëà.
+      </dd>
+      <dt><b>imgdata.params.user_flip</b></dt>
+      <dd>
+        Åñëè ýòîò ïàðàìåòð áîëüøå èëè ðàâåí íóëþ, òî íà ýòàïå îòêðûòèÿ ôàéëà 
+        (<a href="API-CXX-rus.html#open_file">open_file()</a> è îñòàëüíûå ïîäîáíûå âûçîâû)
+        ïðîèçâîäèòñÿ ïðèñâàèâàíèå <code>imgdata.sizes.flip = imgdata.params.user_flip</code>.
+      </dd>
+      <dt><b>imgdata.params.shot_select</b></dt>
+      <dd>
+        Ïîçâîëÿåò âûáðàòü íîìåð èçâëåêàåìîãî èçîáðàæåíèÿ äëÿ òåõ ôîðìàòîâ äàííûõ, ãäå âîçìîæíî õðàíåíèå íåñêîëüêèõ
+        RAW-èçîáðàæåíèé â îäíîì ôàéëå äàííûõ. 
+      </dd>
+      <dt><b>imgdata.params.half_size</b></dt>
+      <dd>
+        Âëèÿåò íà çàãðóçêó RAW-äàííûõ äëÿ çàäíèêîâ Phase One è Sinar. Êðîìå òîãî, åñëè óñòàíîâëåí ýòîò ïàðàìåòð, òî
+        ñ÷èòûâàíèå äàííûõ áóäåò ïðîèçâîäèòüñÿ â áèòìýï ïîëîâèííîãî ðàçìåðà â êîòîðîì áóäóò çàïîëíÿòüñÿ 4 êîìïîíåíòà.
+      </dd>
+      <dt><b>imgdata.params.threshold, imgdata.params.aber</b></dt>
+      <dd>
+        Èñïîëüçîâàíèå ýòèõ ïàðàìåòðîâ (ò.å. óêàçàíèå, ÷òî áóäåò èñïîëüçîâàòüñÿ, ñîîòâåòñòâåííî,  wavelet denoising è
+        èñïðàâëåíèå àáåððàöèé) òî ÷òåíèå äàííûõ áóäåò ïðîèçâîäèòüñÿ â áèòìýï ïîëîâèííîãî ðàçìåðà, ó êàæäîãî ïèêñåëà
+        áóäóò çàïîëíåíû â÷å 4 êîìïîíåíòà (äëÿ áàéåðîâñêèõ ìàòðèö).
+      </dd>
+
+      <dt><b>imgdata.params.filtering_mode</b></dt>
+      <dd>
+        Âëèÿåò íà çàãðóçêó RAW-äàííûõ äëÿ òåõ êàìåð, ó êîòîðûõ âû÷èòàíèå óðîâíÿ ÷åðíîãî (âîçìîæíî, ÷àñòè÷íîå)
+        ïðîèçâîäèòñÿ  íà ýòàïå ÷òåíèÿ RAW: Canon A600, A5, CRW/CR2; êàìåðû ñ LJPEG-ñæàòèåì (íåêîòîðûå êàìåðû Nikon,
+        Kodak è Hasselblad).
+      </dd>
+      <dt><b>imgdata.params.use_camera_wb</b></dt>
+      <dd>
+        Âëèÿåò íà çàãðóçêó ìàòðèöû áàëàíñà áåëîãî äëÿ çàäíèêîâ Leaf.
+      </dd>
+      <dt><b>imgdata.params.document_mode</b></dt>
+      <dd>
+        <b>Â òåêóùåé âåðñèè LibRaw íå âëèÿåò íà ÷òåíèå äàííûõ</b>. Â dcraw -  âëèÿåò íà äàííûå thumbnails äëÿ
+        íåêîòîðûõ êàìåð Kodak è íà RAW-äàííûå èçîáðàæåíèÿ äëÿ êàìåð ñ ìàòðèöåé Foveon.
+      </dd>
+      </dl>
+    <a name="filtering"></a>
+    <h2>Ôèëüòðàöèÿ RAW-äàííûõ</h2>
+    <p>
+      Íà ýòàïå îáðàáîòêè RAW-äàííûõ LibRaw ìîæåò îñóùåñòâëÿòü òàêèå ñòàäèè îáðàáîòêè:
+    </p>
+    <ul>
+      <li>Âû÷èòàíèå óðîâíÿ ÷åðíîãî, ðàññ÷èòàííîãî ïî ÷åðíîé ðàìêå.</li>
+      <li>Óäàëåíèå íóëåâûõ çíà÷åíèé (óñðåäíåíèå çíà÷åíèé ñîñåäíèõ ïèêñåëîâ).</li>
+      <li>Ïðèìåíåíèå ê äàííûì êðèâîé, ñ÷èòàííûõ èç ìåòàäàííûõ èçîáðàæåíèÿ</li>
+    </ul>
+    <p>
+      Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> óïðàâëåíèå ôèëüòðàöèåé RAW-äàííûõ îòñóòñòâóåò.
+    </p>
+    <p>
+       òåêóùåé âåðñèè LibRaw âîçìîæíû ñëåäóþùèå íàñòðîéêè ôèëüòðàöèè (íàñòðîéêà ïðîèçâîäèòñÿ ÷åðåç çàäàíèå ïàðàìåòðà 
+      <b>imgdata.params.filtering_mode</b> â îäíî èç çíà÷åíèé <a href="API-datastruct-rus.html#LibRaw_filtering">enum
+        LibRaw_filtering</a>:
+      </p>
+    <ul>
+      <li>Ñîâìåñòèìàÿ ñ  dcraw ôèëüòðàöèÿ (óìîë÷àíèå). Ýòîò ðåæèì îñòàâëåí êàê óìîë÷àíèå äëÿ ñîâìåñòèìîñòè ñ
+        ïðåäûäóùèìè âåðñèÿìè LibRaw, åãî èñïîëüçîâàíèå íå ðåêîìåíäóåòñÿ.</li>
+      <li>Îòêëþ÷åíèå îäíîãî èëè íåñêîëüêèõ âèäîâ ôèëüòðàöèè. Ýòè ðåæèìû
+        ïðåäíàçíà÷åíû äëÿ ñèòóàöèè, êîãäà ôèëüòðàöèÿ íå íóæíà (àíàëèçàòîðû RAW è ïîäîáíûå ïðîãðàììû), ëèáî êîãäà
+        âûçûâàþùàÿ ïðîãðàììà âûïîëíÿåò ôèëüòðàöèþ ñàìîñòîÿòåëüíî (íàïðèìåð, áàçèðóÿñü íà 
+        <a href=#masked-border>äàííûõ, ñ÷èòàííûõ ñ ÷åðíîé ðàìêè</a>.</li>
+      <li>Àâòîìàòè÷åñêèé âûáîð íàèëó÷øåé ôèëüòðàöèè, äîñòóïíîé â LibRaw: óëó÷øåííûõ ðåæèìîâ äëÿ îòäåëüíûõ êàìåð,
+        ïîääåðæàííûõ ñïåöèàëèçèðîâàííûìè ïðîöåäóðàìè ôèëüòðàöèè; ôèëüòðàöèÿ êîäîì dcraw äëÿ âñåõ îñòàëüíûõ êàìåð. Ýòîò
+        ðåæèì ðåêîìåíäóåòñÿ ê èñïîëüçîâàíèþ äëÿ âñåõ ïðèëîæåíèé, ïåðåêëàäûâàþùèõ âñå òîíêîñòè îáðàáîòêè RAW íà LibRaw.
+        </li>
+      </ul>
+    <p>
+       òåêóùåé âåðñèè LibRaw âû÷èòàíèå óðîâíÿ ÷åðíîãî íå îòêëþ÷àåòñÿ äëÿ êàìåð Foveon (ðàçðàáîò÷èêè LibRaw íå âèäÿò
+      ñìûñëà ðàçâèâàòü ýòîò êîä).
+    <a name="masked-border"></a>
+    <h2>Õðàíåíèå äàííûõ ìàñêèðîâàííûõ ïèêñåëîâ</h2>
+    <p>
+      Äëÿ ÷àñòè ôîðìàòîâ RAW LibRaw èçâëåêàåò äàííûå íåàêòèâíûõ ñåíñîðîâ ìàòðèöû ("ìàñêèðîâàííûå ïèêñåëû" èëè "÷åðíàÿ
+      ðàìêà") è ñîõðàíÿåò èõ â ñòðóêòóðå äàííûõ 
+      <a href="API-datastruct-rus.html#libraw_masked_t">imgdata.masked_pixels</a>. Ýòè äàííûå çàòåì ìîãóò áûòü
+      èñïîëüçîâàíû äëÿ:
+    </p>
+    <ul>
+      <li>Ðàñ÷åòà óðîâíÿ ÷åðíîãî (â òîì ÷èñëå, ïî ñòîëáöàì, ñîîòâåòñòâóþùèì ðàçíûì êàíàëàì ÀÖÏ äëÿ ïîäàâëåíèÿ
+        banding).</li>
+      <li>Ðàñ÷åò óðîâíÿ øóìîâ, â òîì ÷èñëå ïî öâåòîâûì êàíàëàì, ÷òî àêòóàëüíî äëÿ êàìåð ó êîòîðûõ ðàçíîå ïîêàíàëüíîå
+        óñèëåíèå ñèãíàëà.</li>
+    </ul>
+    <p>Äàííûå ÷åðíîé ðàìêè äîñòóïíû òîëüêî RAW-äàííûõ ñ áàéåðîâñêèìè äàííûìè (îäèí êîìïîíåíò íà ïèêñåëü) è òîëüêî
+      äëÿ òåõ êàìåð, ãäå ýòà ðàìêà äîñòóïíà. Èçâëå÷åíèå äàííûõ äëÿ ìíîãîöâåòíûõ RAW (Foveon, Canon sRAW,
+      Kodak YRGB, Sinar 4-shot) âîçìîæíî áóäåò äîáàâëåíî â ñëåäóþùèõ âåðñèÿõ.
+    </p>
+    <p>
+      Ìàñêèðîâàííûå ïèêñåëû è àêòèâíûå ïèêñåëû èçîáðàæåíèÿ ìîæíî îáúåäèíèòü â îáùèé 4-êîìïîíåíòíûé áèòìýï âûçîâîì
+      <a href="API-CXX-rus.html#add_masked_borders_to_bitmap">add_masked_borders_to_bitmap()</a>.
+    </p>
+    <p>
+      Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> ìàñêèðîâàííûå ïèêñåëû íå èçâëåêàþòñÿ, âûçîâ äëÿ ðàáîòû ñ
+      íèìè - îòñóòñòâóåò.
+    </p>
+    <a name="memory"></a>
+    <h2>Èñïîëüçîâàíèå ïàìÿòè</h2>
+    <a name="stack"></a>
+    <h3>Èñïîëüçîâàíèå ñòåêà</h3>
+    <p>
+      Ýêçåìïëÿð êëàññà  LibRaw èìååò ñîáñòâåííûé ðàçìåð  <b>îêîëî 100 êèëîáàéò</b>, ïðè èñïîëüçîâàíèè êîíñòðóêöèé âèäà
+      <code>LibRaw imageProcessor;</code> ýòà ïàìÿòü àëëîöèðóåòñÿ íà ñòåêå.
+    </p>
+    <p>
+      Ìåòîäû êëàññà LibRaw (è âûçîâû  Ñ API) ïðè ðàáîòå ìîãóò àëëîöèðîâàòü äî 130-140 êèëîáàéò äàííûõ íà ñòåêå ïîä
+      àâòîìàòè÷åñêèå ïåðåìåííûå.
+    </p>
+    <p>Òàêèì îáðàçîì, äëÿ ðàáîòû îäíîãî ýêçåìïëÿðà LibRaw ìîæåò òðåáîâàòüñÿ îêîëî 250 êèëîáàéò ñòåêà. Â áîëüøèíñòâå
+      ñîâðåìåííûõ àðõèòåêòóð ýòî íå ÿâëÿåòñÿ ïðîáëåìîé, íî ïðè èñïîëüçîâàíèè LibRaw â multi-threaded-îêðóæåíèè
+      íåîáõîäèìî íå çàáûâàòü àëëîöèðîâàòü äîñòàòî÷íî ïàìÿòè äëÿ ñòåêà thread.
+    </p>
+    <p>Ïðè äèíàìè÷åñêîé àëëîêàöèè (<code>LibRaw *iProcessor = new LibRaw;</code>) òðåáîâàíèÿ ê ïàìÿòè íà ñòåêå
+      ñíèæàþòñÿ (íà 100 êèëîáàéò - ðàçìåð ýêçåìïëÿðà êëàññà). Ïðè èñïîëüçîâàíèè <a href="API-C-rus.html">C API</a>
+        ýêçåìïëÿð LibRaw àëëîöèðóåòñÿ  äèíàìè÷åñêè. 
+    </p>
+
+    <a name="memmgr"></a>
+    <h3>Óïðàâëåíèå äèíàìè÷åñêîé ïàìÿòüþ</h3>
+    <p>LibRaw âåäåò ó÷åò âñåõ áëîêîâ àëëîöèðîâàííîé äèíàìè÷åñêîé ïàìÿòè, ïðè âîçíèêíîâåíèè èñêëþ÷èòåëüíîé ñèòóàöèè
+      (ôàòàëüíîé îøèáêè) âñå îíè îñâîáîæäàþòñÿ. Êîä ó÷åòà äîâîëüíî ïðèìèòèâíûé è íå ðàñ÷èòàí íà àëëîêàöèþ áîëüøîãî
+      ÷èñëà áëîêîâ (â îáû÷íîé ñèòóàöèè ïðè îáðàáîòêå ôàéëà àëëîêàöèÿ ïðîèñõîäè 2-6 ðàç), ïðè ðàñøèðåíèè LibRaw
+      ñîáñòâåííûìè ìåòîäàìè ýòî íàäëåæèò ó÷èòûâàòü.
+    </p>
+    <a name="memuse"></a>
+    <h3>Èñïîëüçîâàíèå äèíàìè÷åñêîé ïàìÿòè</h3>
+    <p>LibRaw èñïîëüçóåò äèíàìè÷åñêóþ ïàìÿòü:</p>
+    <ul>
+      <li>äëÿ ðàñêîäèðîâàííîãî èçîáðàæåíèÿ;</li>
+      <li>äëÿ ðàñêîäèðîâàííîãî thumbnail;</li>
+      <li>äëÿ èçâëå÷åííîãî èç  RAW-ôàéëà ICC-ïðîôèëÿ (åñëè îí òàì åñòü);</li>
+      <li>äëÿ âðåìåííûõ äàííûõ íà ýòàïå ðàñïàêîâêè  RAW-ôàéëà;</li>
+      <li>äëÿ âðåìåííûõ äàííûõ íà ýòàïå ïîñòîáðàáîòêè è çàïèñè ðåçóëüòàòà;</li>
+      <li>äëÿ ÷òåíèÿ èñõîäíîãî RAW-ôàéëà (òîëüêî íà Win32)</li>
+    </ul>
+    <a name="memimage"></a>
+    <h4>Ïàìÿòü äëÿ ðàñêîäèðîâàííîãî èçîáðàæåíèÿ</h4>
+    <p>
+      Ñ öåëüþ óïðîùåíèÿ äàëüíåéøåé îáðàáîòêè, ïàìÿòü ïîä èçâëåêàåìûå RAW-äàííûå àëëîöèðóåòñÿ ñ 4-êðàòíûì (äëÿ
+      áàéåðîâñêèõ êàìåð) çàïàñîì: <b>äëÿ êàæäîãî ïèêñåëÿ îòâîäèòñÿ 4 16-áèòíûõ êîìïîíåíòà</b> (òðè èç êîòîðûõ áóäóò
+      íóëåâûìè ïîñëå ðàñïàêîâêè RAW). Ýòî ïîçâîëÿåò ïðîâîäèòü äåáàéåðèçàöèþ è ïðî÷èå äåéñòâèÿ ïî ïîñòîáðàáîòêå ïðÿìî â
+      òîì æå áóôåðå, êóäà áûëè èçâëå÷åíû äàííûå, íî ïîâûøàåò òðåáîâàíèÿ ê ïàìÿòè â÷åòâåðî.<br/>
+      <b>Òàêèì îáðàçîì, ðàçìåð ïàìÿòè ïîä áóôåð èçîáðàæåíèÿ â 6-10 ðàç ïðåâûøàåò ðàçìåð èñõîäíîãî RAW-ôàéëà.</b><br/> 
+      <i>Âïîëíå âåðîÿòíî, ÷òî â ñëåäóþùèõ âåðñèÿõ LibRaw àëëîêàöèÿ ýòîãî áóôåðà áóäåò áîëåå ýêîíîìíîé, ïðè óñëîâèè
+        íåèñïîëüçîâàíèÿ âûçîâîâ ïîñòîáðàáîòêè, óíàñëåäîâàííûõ îò dcraw.</i>.
+    </p>
+    <p>Áóôåð äëÿ ðàñêîäèðîâàííîãî èçîáðàæåíèÿ àëëîöèðóåòñÿ ïðè âûçîâå <a href="API-CXX-rus.html#unpack">unpack()</a> è
+      îñâîáîæäàåòñÿ ïðè <a href="API-CXX-rus.html#recycle">recycle()</a>.
+    </p> 
+    
+    <a name="memthumb"></a>
+    <h4>Ïàìÿòü äëÿ ðàñêîäèðîâàííîãî thumbnail</h4>
+    <p>
+      Ïàìÿòü äëÿ thumbnail àëëîöèðóåòñÿ ïðè âûçîâå <a href="API-CXX-rus.html#unpack_thumb">unpack_thumb()</a> è
+      îñâîáîæäàåòñÿ ïðè <a href="API-CXX-rus.html#recycle">recycle()</a>. Àëëîöèðóåòñÿ áóôåð ðàçìåðîì ðîâíî ïîä
+      thumbnail ò.å. äî íåñêîëüêèõ ìåãàáàéò.
+    </p>
+
+    <a name="memprofile"></a>
+    <h4>Ïàìÿòü äëÿ ðàñêîäèðîâàííîãî ICC-profile</h4>
+    <p>
+      Ïàìÿòü äëÿ ICC-ïðîôèëÿ  àëëîöèðóåòñÿ ïðè âûçîâå <a href="API-CXX-rus.html#unpack_profile">unpack_profile()</a> è
+      îñâîáîæäàåòñÿ ïðè <a href="API-CXX-rus.html#recycle">recycle()</a>. Àëëîöèðóåòñÿ áóôåð ðàçìåðîì ðîâíî ïîä
+      ðàçìåð ICC-ïðîôèëÿ ò.å. äî íåñêîëüêèõ ñîòåí êèëîáàéò.
+    </p>
+    <a name="rawmem"></a>
+    <h4>Ïàìÿòü äëÿ ðàñïàêîâêè RAW</h4>
+    <p>
+      Ïàìÿòü äëÿ âðåìåííûõ áóôåðîâ, íóæíûõ ïðè ðàñïàêîâêå RAW-äàííûõ ìîæåò áûò àëëîöèðîâàíà âî âðåìÿ ðàáîòû <a
+        href="API-CXX-rus.html#unpack">unpack()</a> è îñâîáîæäàåòñÿ äî çàâåðøåíèÿ ýòîé ôóíêöèè. Ðàçìåðû àëëîöèðîâàííûõ
+      áóôåðîâ íåâåëèêè, â ïðåäåëàõ íåñêîëüêèõ äåñÿòêîâ êèëîáàéò.
+    </p>
+
+    <a name="mempostproces"></a>
+    <h4>Ïàìÿòü äëÿ ïîñòîáðàáîòêè</h4>
+    <p>Ïðè ïîñòîáðàáîòêå èçîáðàæåíèé (óíàñëåäîâàííîé îò dcraw) âûäåëÿåòñÿ ïàìÿòü ïîä ãèñòîãðàììó (128 êèëîáàéò). Ýòà
+      ïàìÿòü âûäåëÿåòñÿ ïðè âûçîâå <a
+        href="API-CXX-rus.html#dcraw_document_mode_processing">dcraw_document_mode_processing()</a> è 
+      <a href="API-CXX-rus.html#dcraw_process">dcraw_process()</a>, à îñâîáîæäàåòñÿ ïðè âûçîâå
+      <a href="API-CXX-rus.html#recycle">recycle()</a>.
+    </a>
+    <p>
+      Ïîìèìî ýòîãî, ïðè ðàáîòå <a href="API-CXX-rus.html#dcraw_process">dcraw_process()</a> è èñïîëüçîâàíèè ðÿäà
+      èìåþùèõñÿ âîçìîæíîñòåé:
+    </p>
+      <ul>
+      <li>ðîòàöèè èçîáðàæåíèé ñ êàìåð FUJI;</li>
+      <li>êîððåêöèè õðîìàòè÷åñêèõ àáåððàöèé;</li>
+      <li>èçìåíåíèè ðàçìåðîâ èçîáðàæåíèÿ (âêëþ÷àÿ ñëó÷àè êîððåêöèè íåêâàäðàòíîãî ïèêñåëà);</li>
+      <li>highlight recovery;</li>
+    </ul>
+    <p>
+      áóäåò àëëîöèðîâàí âðåìåííûé áóôåð, ðàçìåð êîòîðîãî ðàâåí ðàçìåðó ðåçóëüòèðóþùåãî èçîáðàæåíèÿ (èç ðàñ÷åòà 6-8
+      áàéò íà ïèêñåë äëÿ ðàçíûõ ñòàäèé îáðàáîòêè). Ïðè çàâåðøåíèè ïðîìåæóòî÷íîé ïîäñòàäèè îáðàáîòêè, áóôåð ñ
+      ïðåäûäóùåé êîïèåé èçîáðàæåíèÿ áóäåò îñâîáîæäåí.<br/>
+      Åñëè ïîñòîáðàáîòêà íå èñïîëüçóåòñÿ, òî âðåìåííûå áóôåðû íå àëëîöèðóþòñÿ.
+    </p>
+
+    <a name="memwrite"></a>
+    <h4>Ïàìÿòü äëÿ çàïèñè ôàéëà</h4>
+    <p>
+      Âûçîâ <a href="API-CXX-rus.html#dcraw_ppm_tiff_writer">dcraw_ppm_tiff_writer()</a> àëëîöèðóåò ïàìÿòü ïîä îäíó
+      ñòðîêó âûõîäíîãî èçîáðàæåíèÿ. Àëëîöèðîâàííàÿ ïàìÿòü îñâîáîæäàåòñÿ ïåðåä âûõîäîì èç âûçîâà.
+    </p>
+
+    <a name="memunpack"></a>
+    <h4>Ïàìÿòü äëÿ ðàñïàêîâêè â áóôåð â ïàìÿòè</h4>
+    <p>
+      Âûçîâû <a href="API-CXX-rus.html#dcraw_make_mem_image">dcraw_make_mem_image()</a> è 
+      <a href="API-CXX-rus.html#make_mem_thumb">dcraw_make_mem_thumb()</a> (è èõ àíàëîãè â C-API)
+      àëëîöèðóþò äîïîëíèòåëüíóþ ïàìÿòü â îáúåìå, íåîáõîäèìîì äëÿ õðàíåíèÿ âûâîäèìûõ äàííûõ (èçîáðàæåíèÿ
+      è thumbnail, ñîîòâåòñòâåííî).<b>Îñâîáîæäåíèå ýòîé ïàìÿòè - çàäà÷à âûçûâàþùåé ôóíêöèè</b>.
+    </p>
+
+    <a name="incompat"></a>
+    <h2>Íåñîâìåñòèìîñòè ñ dcraw</h2>
+    <a name="incompat_kodak"></a>
+    <h3>Îáðàáîòêà Thumbnails îò êàìåð Kodak</h3>
+    <p> ðÿäå êàìåð Kodak preview (thumbnail) õðàíèòñÿ â âèäå íåñêîððåêòèðîâàííîãî èçîáðàæåíèÿ. Ïðè èçâëå÷åíèè åãî ñ
+      ïîìîùüþ <b>dcraw -e</b> èñïîëüçóþòñÿ òå æå íàñòðîéêè áàëàíñà áåëîãî, êîððåêöèè öâåòîâ è òàê äàëåå, ÷òî è äëÿ
+      èçâëå÷åíèÿ îñíîâíûõ RAW-äàííûõ (âêëþ÷àÿ óäàëåíèå äåôåêòîâ è âû÷èòàíèå dark frame, ÷òî îøèáî÷íî ò.ê. ðàçìåð
+      èçîáðàæåíèÿ äðóãîé).
+    <br/>
+      Â âûçîâå LibRaw::unpack_thumb() âñåãäà èñïîëüçóåòñÿ áàëàíñ áåëîãî, âçÿòûé èç êàìåðû (as shot), êàêèå-ëèáî
+      íàñòðîêè èç imgdata.params íå èñïîëüçóþòñÿ.
+    </p>
+    <p>
+      Äëÿ Âñåõ îñòàëüíûõ êàìåð thumbnails èçâëåêàþòñÿ as-is, áåç êàêèõ-ëèáî öâåòîâûõ
+      ïðåîáðàçîâàíèé, êàê â dcraw, òàê è â LibRaw.
+    </p>
+
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 10:05:08 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:55 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/API-overview-eng.html b/libfspotraw/LibRaw/doc/API-overview-eng.html
new file mode 100644
index 0000000..89c6113
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/API-overview-eng.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>Overview of LibRaw API (C++)</title>
+  </head>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+
+  <body>
+    <a href=index-eng.html>[back to Index]</a>
+    <h1>Overview of LibRaw API (C++)</h1>
+    <h2>General Remarks</h2>
+    <ol>
+      <li>The entire processing is carried out by an instance of the LibRaw class, which is an image processor.</li>
+      <li>One image processor can simultaneously process only one data source file, but consecutive processing of any number of files
+is possible.</li>
+      <li>There may be several simultaneously working image processors in a software program (e.g., in different threads), although one
+should remember that each image processor may require much memory.</li>
+      <li>Reading of source data from the RAW file requires virtually no customization (see <a
+          href="API-notes-eng.html">API Notes</a> for exceptions to this rule).</li>
+      <li>All data extracted from the RAW file are accessible through data fields of the image processor (LibRaw class instance).</li>
+      <li>Although LibRaw <b>is not intended for RAW data postprocessing</b>, the library includes calls that enable complete
+emulation of the <b>dcraw</b> utility.
+      <li>All customization for the processing is performed via data fields of the LibRaw class.</li>
+    </ol>
+        
+    <h2>Brief Demonstration</h2>
+    <p> 
+      The example below contains no error processing for the sake of brevity.
+    </p>
+    <pre>
+#include "libraw/libraw.h"
+int process_image(char *file)
+{
+        // Let us create an image processor
+        LibRaw iProcessor;
+
+        // Open the file and read the metadata
+        iProcessor.open_file(file);
+
+        // The metadata are accessible through <a href="API-datastruct-eng.html">data fields of the class</a>
+        printf("Image size: %d x %d\n",iProcessor.imgdata.sizes.width,iProcessor.imgdata.sizes.height);
+
+        // Let us unpack the image
+        iProcessor.unpack();
+
+        // And let us print its dump; the data are accessible through <a href="API-datastruct-eng.html">data fields of the class</a>
+        for(i = 0;i lt; iProcessor.imgdata.sizes.iwidth *  iProcessor.imgdata.sizes.iheight; i++)
+           printf("i=%d R=%d G=%d B=%d G2=%d\n",
+                        i,
+                        iProcessor.imgdata.image[i][0],
+                        iProcessor.imgdata.image[i][1],
+                        iProcessor.imgdata.image[i][2],
+                        iProcessor.imgdata.image[i][3]
+                );
+
+        // Finally, let us free the image processor for work with the next image
+        iProcessor.recycle();
+}
+</pre>
+
+
+    <a href=index-eng.html>[back to Index]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 09:15:41 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:54 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/API-overview-rus.html b/libfspotraw/LibRaw/doc/API-overview-rus.html
new file mode 100644
index 0000000..239b600
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/API-overview-rus.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>Îáçîð LibRaw API (C++)</title>
+  </head>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+
+  <body>
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <h1>Îáçîð LibRaw API (C++)</h1>
+    <h2>Îáùèå ïîëîæåíèÿ</h2>
+    <ol>
+      <li>Âñÿ îáðàáîòêà âåäåòñÿ ýêçåìïëÿðîì êëàññà LibRaw - îáðàáîò÷èêîì èçîáðàæåíèé.</li>
+      <li>Îäèí îáðàáîò÷èê èçîáðàæåíèé îäíîâðåìåííî ìîæåò îáðàáàòûâàòü òîëüêî îäèí èñõîäíûé ôàéë, ïîñëåäîâàòåëüíî -
+      ñêîëüêî óãîäíî ôàéëîâ.</li>
+      <li> ïðîãðàììå (íàïðèìåð, â ðàçíûõ threads) ìîãóò îäíîâðåìåííî ðàáîòàòü íåñêîëüêî îáðàáîò÷èêîâ, õîòÿ ñëåäóåò
+        ó÷èòûâàòü, ÷òî ïîòðåáëåíèå ïàìÿòè â îáðàáîò÷èêå ìîæåò áûòü çíà÷èòåëüíûì.</li>
+      <li>×òåíèå èñõîäíûõ äàííûõ RAW-ôàéëà ïðàêòè÷åñêè íå òðåáóåò íàñòðîåê (îá èñêëþ÷åíèÿõ ñêàçàíî â <a
+          href="API-notes-rus.html">API Notes</a>).</li>
+      <li>Âñå äàííûå, èçâëå÷åííûå èç RAW-ôàéëà äîñòóïíû ÷åðåç ïîëÿ äàííûõ îáðàáîò÷èêà (ýêçåìïëÿðà êëàññà LibRaw).</li>
+      <li>Íåñìîòðÿ íà òî, ÷òî LibRaw <b>íå ïðåäíàçíà÷åíà äëÿ ïîñòîáðàáîòêè RAW-äàííûõ</b>, â áèáëèîòåêó âêëþ÷åíû
+        âûçîâû, ïîçâîëÿþùèå ïîëíîñòüþ âîñïðîèçâåñòè ïîâåäåíèå óòèëèòû <b>dcraw</b>.
+      <li>Âñå íàñòðîéêè îáðàáîòêè ïðîèçâîäÿòñÿ ÷åðåç ïîëÿ äàííûõ êëàññà LibRaw.</li>
+    </ol>
+        
+    <h2>Êðàòêàÿ äåìîíñòðàöèÿ</h2>
+    <p> 
+      Ïðèìåð íèæå íå ñîäåðæèò êàêîé-ëèáî îáðàáîòêè îøèáîê â öåëÿõ êîìïàêòíîñòè äåìîíñòðàöèè
+    </p>
+    <pre>
+#include "libraw/libraw.h"
+int process_image(char *file)
+{
+        // Cîçäàäèì îáðàáîò÷èê èçîáðàæåíèé
+        LibRaw iProcessor;
+
+        // Îòêðûòü ôàéë è ñ÷èòàòü ìåòàäàííûå
+        iProcessor.open_file(file);
+
+        // Ìåòàäàííûå äîñòóïíû â <a href="API-datastruct-rus.html">ïîëÿõ äàííûõ êëàññà</a>
+        printf("Image size: %d x %d\n",iProcessor.imgdata.sizes.width,iProcessor.imgdata.sizes.height);
+
+        // Ðàñïàêóåì èçîáðàæåíèå
+        iProcessor.unpack();
+
+        // È íàïå÷àòàåì åãî äàìï, äàííûå äîñòóïíû â <a href="API-datastruct-rus.html">ïîëÿõ äàííûõ êëàññà</a>
+        for(i = 0;i lt; iProcessor.imgdata.sizes.iwidth *  iProcessor.imgdata.sizes.iheight; i++)
+           printf("i=%d R=%d G=%d B=%d G2=%d\n",
+                        i,
+                        iProcessor.imgdata.image[i][0],
+                        iProcessor.imgdata.image[i][1],
+                        iProcessor.imgdata.image[i][2],
+                        iProcessor.imgdata.image[i][3]
+                );
+
+        // Îñâîáîäèì ïðîöåññîð äëÿ ðàáîòû ñî ñëåäóþùèì èçîáðàæåíèåì
+        iProcessor.recycle();
+}
+</pre>
+
+
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 09:15:41 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:53 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/Install-LibRaw-eng.html b/libfspotraw/LibRaw/doc/Install-LibRaw-eng.html
new file mode 100644
index 0000000..2aac424
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/Install-LibRaw-eng.html
@@ -0,0 +1,133 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw Compilation and Installation</title>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+  </head>
+
+  <body>
+    <a href=index-eng.html>[back to Index]</a>
+    <h1>LibRaw Compilation and Installation</h1>
+    <p>LibRaw is distributed in the form of source codes. For further use, they should be compiled (and, if desired, placed into
+   system folders with libraries and include-files).</p>
+    <a name="unix"></a>
+    <h2>Unix Systems (FreeBSD, Linux, Mac OS X)</h2>
+    <p>
+      To build the library, you will need a working C++ compiler (gcc ver. 3.x or 4.x will be OK; other compilers have not been tested) and
+    the make utility. No other libraries or utilities are required.</p>
+    <p>
+      LibRaw has been tested on 32- and 64-bit Unix systems working on x86- (and AMD64-) compatible processors. 
+      Building and work on other architectures have not been tested.
+    </p>
+    <h3>Compilation of Library and Examples</h3>
+    <p>
+     Unpack the downloaded distribution package, go to the resultant folder and run make:
+    </p>
+    <pre>
+        tar xzvf LibRaw-X.YY.tar.gz
+        cd  LibRaw-X.YY
+        make
+    </pre>
+    <p>As a result, you will compile</p>
+    <ul>
+      <li>Library libraw.a in the lib/ folder</li>
+      <li><a href=Samples-LibRaw-eng.html>Examples</a> in the bin/ folder (source codes of examples are in the samples/ folder).</li>
+    </ul>
+    <p>In the current version, only static libraries are built:</p>
+    <ul>
+      <li>libraw.a: non-thread-safe version</li>
+      <li>libraw_r.a: thread-safe</li>
+    </ul>
+    <h3>Compilation with LCMS (ICC profiles) support</h3>
+    <p>
+      For LCMS support one should uncomment two lines of Makefile after the line
+<pre>
+# LCMS support
+</pre>
+    It is assumed, that LCMS library is installed in /usr/local/lib or /usr/lib, and lcms.h installed in
+    /usr/local/include or /usr/include. If you have different LCMS installation path, you should edit Makefile
+    settings.
+    </p>
+    <h3>OpenMP Support</h3>
+    <p>For compilation with OpenMP support uncomennt line of Makefile next after the line
+<pre>
+# OpenMP support
+</pre>
+        <p>
+          There is no OpenMP support  in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>      
+    <h3>Installation and Usage</h3>
+    <p>To install the library, run</p>
+    <pre>
+    make install
+    </pre>
+    <p>
+    It will place the libraries in <b>/usr/local/lib</b> and the include-files in <b>/usr/local/include</b> (subfolder of libraw).
+    <br/>
+      To use LibRaw, add the following parameters to the compiler call (when building your own projects):
+    </p>
+    <ul>
+      <li>Path to include-files: -I/usr/local/include</li>
+      <li>Path to libraries: -L/usr/local/lib</li>
+      <li>Library: -lraw (ordinary version) or -lraw_r (thread-safe version).</li>
+    </ul>
+    <h4>Installation of Examples</h4>
+    <p>
+      To install examples, run <b>make install-binaries</b>. This command will copy all compiled examples to <b>/usr/local/bin</b>.
+    </p>
+    <h2>Windows: Building under Cygwin</h2>
+    <p>
+     Building and installation are completely similar to <a href="#unix">building and installation under Unix systems</a>.    
+    </p>
+    <h2>Windows: Native Building</h2> 
+    <p>
+      Building under Windows has three steps:
+    </p>
+    <ul>
+      <li>Unpack the distribution package (if you have got no tar+gzip, take the LibRaw distribution package in the .ZIP format) and go to folder
+         LibRaw-X.YYY.
+      </li>
+      <li>Set the environment parameters so that the compiler/linker would find the libraries and include-files. For Visual C++, this is
+     done by running <b>vcvars32.bat</b>.
+      </li>
+      <li>
+        Run<br/>
+        <b>nmake -f Makefile.msvc</b><br/>
+      </li>
+    </ul>
+    <p>
+    If all paths are set correctly and the include-files/libraries have been found, then the following will be compiled:</p>
+    <ul>
+      <li>Library libraw_static.lib in folder lib</li>
+      <li>Dynamic library bin/libraw.dll and linking library for it lib/libraw.lib</li>
+      <li>Examples in folder bin/.</li>
+    </ul>
+    <p>Only the thread-safe library is built under Win32, but it can be used with non-threaded applications as well. All examples are linked
+    with the dynamic library (DLL); if static linking is necessary, one should link applications with library libraw_static.lib and 
+   set the preprocessor option /DLIBRAW_NODLL during compilation.
+     </p>
+    <p>
+      Windows-version compiles without LCMS support for now.
+    </p>
+    <p>
+      During building of DLL, all public functions are exported; further, the exported subset may be reduced. 
+    </p>
+    <p>
+      Unfortunately, paths to include/ libraries depend on the way Visual C (or other compiler) is installed; therefore, it is impossible
+      to specify some standard paths in Makefile.msvc.
+    </p>
+    <h2>Windows Installation</h2> 
+    <p>
+      No installation under Windows is supported. It is assumed that all DLLs will be supplied together with the software using them
+     (and this software will perform the installation). Accordingly, in building of programs using LibRaw, the paths to libraries, DLLs,
+   and include-files should be specified manually.
+    </p>
+    <a href=index-eng.html>[back to Index]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 11:53:43 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:53 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/Install-LibRaw-rus.html b/libfspotraw/LibRaw/doc/Install-LibRaw-rus.html
new file mode 100644
index 0000000..7918df6
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/Install-LibRaw-rus.html
@@ -0,0 +1,139 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw: êîìïèëÿöèÿ è óñòàíîâêà</title>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+  </head>
+
+  <body>
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <h1>LibRaw: êîìïèëÿöèÿ è óñòàíîâêà</h1>
+    <p>LibRaw ïîñòàâëÿåòñÿ â èñõîäíûõ òåêñòàõ, äëÿ èñïîëüçîâàíèÿ íåîáõîäèìî èõ ñêîìïèëèðîâàòü (è, ïðè æåëàíèè,
+      óñòàíîâèòü â ñèñòåìíûå êàòàëîãè ñ áèáëèîòåêàìè è include-ôàéëàìè)</p>
+    <a name="unix"></a>
+    <h2>Unix-ñèñòåìû (FreeBSD, Linux, Mac OS X)</h2>
+    <p>
+      Äëÿ ñáîðêè áèáëèîòåêè âàì íóæåí ðàáîòàþùèé êîìïèëÿòîð C++ (gcc âåðñèé 3.x èëè 4.x âïîëíå ïîäîéäåò, ñáîðêà
+      äðóãèìè êîìïèëÿòîðàìè íå òåñòèðîâàëàñü) è ïðîãðàììà make. Íèêàêèõ äðóãèõ áèáëèîòåê, óòèëèò è ò.ï. - íå
+      òðåáóåòñÿ.</p>
+    <p>
+      LibRaw òåñòèðîâàëàñü íà 32-áèòíûõ è 64-áèòíûõ Unix-ñèñòåìàõ íà x86- (è AMD64-) ñîâìåñòèìûõ ïðîöåññîðàõ. Ñáîðêà
+      è ðàáîòîñïîñîáíîñòü íà êàêèõ-ëèáî åùå àðõèòåêòóðàõ íå òåñòèðîâàëàñü.
+    </p>
+    <h3>Êîìïèëÿöèÿ áèáëèîòåêè è ïðèìåðîâ</h3>
+    <p>
+      Ðàñïàêóéòå ñêà÷àííûé äèñòðèáóòèâ, ïåðåéäèòå â ïîëó÷øâøèéñÿ êàòàëîã è çàïóñòèòå make:
+    </p>
+    <pre>
+        tar xzvf LibRaw-X.YY.tar.gz
+        cd  LibRaw-X.YY
+        make
+    </pre>
+    <p>Â ðåçóëüòàòå ñêîìïèëèðóþòñÿ:</p>
+    <ul>
+      <li>Áèáëèîòåêó libraw.a â êàòàëîãå lib/</li>
+      <li><a href=Samples-LibRaw-rus.html>Ïðèìåðû</a> â êàòàëîãå bin/ (èñõîäíûå òåêñòû ïðèìåðîâ íàõîäÿòñÿ â êàòàëîãå
+        samples).</li>
+    </ul>
+    <p> òåêóùåé âåðñèè ñîáèðàþòñÿ òîëüêî ñòàòè÷åñêèå áèáëèîòåêè:</p>
+    <ul>
+      <li>libraw.a - íå thread_safe âàðèàíò</li>
+      <li>libraw_r.a - thread safe</li>
+    </ul>
+    <h3>Ñáîðêà ñ lcms</h3>
+    <p>
+      Äëÿ ñáîðêè ñ ïîääåðæêîé ICC-ïðîôèëåé íåîáõîäèìî ðàñêîììåíòèðîâàòü â Makefile äâå ñòðî÷êè, ñëåäóþùèå ïîñëå ñòðîêè
+<pre>
+# LCMS support
+</pre>
+    Ïðåäïîëàãàåòñÿ, ÷òî áèáëèîòåêà lcms óñòàíîâëåíà â /usr/local/lib èëè /usr/lib, à lcms.h - â /usr/local/include èëè
+    /usr/include. Åñëè íà âàøåé ñèñòåìå ýòî íå òàê, òî ïðèäåòñÿ ïîäïðàâèòü ïóòè â LCMS_DEF è LCMS_LIB â Makefile
+    </p>
+    <h3>Ïîääåðæêà OpenMP</h3>
+    <p>Äëÿ ñáîðêè ñ àâòîìàòè÷åñêèì ðàñïàðàëëåëèâàíèåì ðÿäà ðåñóðñîåìêèõ ñòàäèé îáðàáîòêè íåîáõîäèìî ðàñêîììåíòèðîâàòü
+      â Makefile îäíó ñòðî÷êó, ñëåäóþùóþ ïîñëå ñòðîêè
+<pre>
+# OpenMP support
+</pre>
+    <p>
+      Â <a href=API-notes-rus.html#versions>LibRaw-Lite</a> ïîääåðæêà OpenMP îòñóòñòâóåò.
+    </p>
+
+    <h3>Óñòàíîâêà è èñïîëüçîâàíèå</h3>
+    <p> Äëÿ óñòàíîâêè áèáëèîòåêè âûïîëíèòå êîìàíäó</p>
+    <pre>
+make install
+    </pre>
+    <p>
+    Îíà óñòàíîâèò áèáëèîòåêè â <b>/usr/local/lib</b>, à include-ôàéëû â /usr/local/include (â ïîäêàòàëîã libraw).
+    <br/>
+      Äëÿ èñïîëüçîâàíèÿ LibRaw äîáàâüòå ñëåäóþùèå ïàðàìåòðû ê âûçîâó êîìïèëÿòîðà (ïðè ñáîðêå ñîáñòâåííûõ ïðîåêòîâ):
+    </p>
+    <ul>
+      <li>Ïóòü ê Include-ôàéëàì: -I/usr/local/include</li>
+      <li>Ïóòü ê áèáëèîòåêàì: -L/usr/local/lib</li>
+      <li>Áèáëèîòåêà: -lraw (îáû÷íàÿ âåðñèÿ) èëè -lraw_r (thread-safe âåðñèÿ)</li>
+    </ul>
+    <h4>Óñòàíîâêà ïðèìåðîâ</h4>
+    <p>
+      Äëÿ óñòàíîâêè ïðèìåðîâ âûïîëíèòå êîìàíäó <b>make install-binaries</b>, êîòîðàÿ ñêîïèðóåò âñå ñêîìïèëèðîâàííûå
+      ïðèìåðû â <b>/usr/local/bin</b>
+    </p>
+    <h2>Windows, ñáîðêà ïîä Cygwin</h2>
+    <p>
+      Ñáîðêà è óñòàíîâêà ïîëíîñòüþ àíàëîãè÷íà <a href="#unix">ñáîðêå è óñòàíîâêå íà unix-ñèñòåìàõ</a>.
+    </p>
+    <h2>Windows, native-ñáîðêà</h2> 
+    <p>
+      Ñáîðêà ïîä Windows äåëàåòñÿ â òðè øàãà:
+    </p>
+    <ul>
+      <li>Ðàñïàêóéòå äèñòðèáóòèâ (åñëè ó âàñ íåò tar+gzip, âîçüìèòå äèñòðèáóòèâ LibRaw â ôîðìàòå .ZIP), ïåðåéäèòå â
+        êàòàëîã LibRaw-X.YYY
+      </li>
+      <li>Íóæíî óñòàíîâèòü ïåðåìåííûå îêðóæåíèÿ òàê, ÷òîáû êîìïèëÿòîð/ëèíêîâùèê íàõîäèë áèáëèîòåêè è
+        include-ôàéëû. Äëÿ Visual C++ ýòî äåëàåòñÿ çàïóñêîì <b>vcvars32.bat</b>.
+      </li>
+      <li>
+        Çàïóñêàåòñÿ<br/>
+        <b>nmake -f Makefile.msvc</b><br/>
+      </li>
+    </ul>
+    <p>
+    Åñëè âñå ïóòè óñòàíîâëåíû ïðàâèëüíî è include-ôàéëû/áèáëèîòåêè íàøëèñü, òî ñêîìïèëèðóþòñÿ:</p>
+    <ul>
+      <li>Áèáëèîòåêà libraw_static.lib â êàòàëîãå lib</li>
+      <li>Äèíàìè÷åñêàÿ áèáëèîòåêà bin/libraw.dll è ëèíêîâî÷íàÿ áèáëèîòåêà ê íåé lib/libraw.lib</li>
+      <li>Ïðèìåðû â êàòàëîãå bin</li>
+    </ul>
+    <p> Ïîä Win32 ñîáèðàåòñÿ òîëüêî thread-safe áèáëèîòåêà, åå ìîæíî èñïîëüçîâàòü è íå ñ
+      multi-threaded-ïðèëîæåíèÿìè. Âñå ïðèìåðû ñîáèðàþòñÿ ñ äèíàìè÷åñêîé áèáëèîòåêîé (DLL),
+      ïðè íåîáõîäèìîñòè èñïîëüçîâàòü ñòàòè÷åñêóþ ñáîðêó, íóæíî ëèíêîâàòüñÿ ñ áèáëèîòåêîé libraw_static.lib à ïðè
+      êîìïèëÿöèè óêàçûâàòü äèðåêòèâó ïðåïðîöåññîðà /DLIBRAW_NODLL.
+    </p>
+    <p>
+      Windows-âåðñèÿ â íàñòîÿùåå âðåìÿ ñîáèðàåòñÿ áåç ïîääåðæêè áèáëèîòåêè LCMS (ICC-ïðîôèëåé).
+    </p>
+    <p>
+      Ïðè ñáîðêå DLL ýêñïîðòèðóþòñÿ âñå ïóáëè÷íûå ôóíêöèè, â äàëüíåéøåì ýêñïîðòèðóåìîå ïîäìíîæåñòâî ìîæåò áûòü
+      óìåíüøåíî. 
+    </p>
+    <p>
+      Ê ñîæàëåíèþ, ïóòè ê include/áèáëèîòåêàì çàâèñÿò îò ñïîñîáà, êîòîðûì ó âàñ óñòàíîâëåí Visual C (èëè äðóãîé
+      êîìïèëÿòîð), ïîýòîìó âïèñàòü êàêèå-òî ñòàíäàðòíûå ïóòè â Makefile.msvc íåâîçìîæíî.
+    </p>
+    <h2>Windows,  óñòàíîâêà</h2> 
+    <p>
+      Êàêàÿ-ëèáî óñòàíîâêà ïîä Windows íå ïîääåðæèâàåòñÿ, ïðåäïîëàãàåòñÿ ÷òî âñå .DLL áóäóò ïîñòàâëÿòüñÿ âìåñòå ñ
+      èñïîëüçóþùåé èõ ïðîãðàììîé (êîòîðàÿ è ñäåëàåò óñòàíîâêó). Ñîîòâåòñòâåííî, ïðè ñáîðêå ïðîãðàìì, èñïîëüçóþùèõ
+      LibRaw ïóòü äî áèáëèîòåê, DLL è include-ôàéëîâ äîëæåí çàäàâàòüñÿ âðó÷íóþ.
+    </p>
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 11:53:43 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:52 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/Samples-LibRaw-eng.html b/libfspotraw/LibRaw/doc/Samples-LibRaw-eng.html
new file mode 100644
index 0000000..3290921
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/Samples-LibRaw-eng.html
@@ -0,0 +1,190 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw: Usage Examples</title>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+  </head>
+
+  <body>
+    <a href=index-eng.html>[back to Index]</a>
+    <h1>LibRaw: Usage Examples</h1>
+    
+    <h2>Overview of Examples in the Distribution Package (samples/*)</h2>
+    <p>The LibRaw package contains several examples illustrating the use of this library.
+Their source codes are located in the samples/ folder, and after library build they will be in the bin/ folder:</p>
+    <ul>
+      <li><b>raw-identify</b> The only LibRaw call it uses is <a href="API-CXX-eng.html#open_file">open_file()</a>; 
+        further code prints the values of the fields of the imgdata structure. The output of 
+        <b>raw-identify</b>/<b>raw-identify -v</b> is virtually identical to the output of 
+        <b>dcraw -i</b>/<b>dcraw -i -v </b> (in the output of this example, the sources of color data in the numeric
+        form are additionally printed). Command line key <b>-u</b> shows unpacking function name.   
+      </li>
+      <li><b>simple_dcraw</b> A simple &quot;emulation&quot; of dcraw reproducing the behavior of  
+        <b>dcraw [-D] [-e] [-v] [-T]</b>. The result of its work must be binary identical to the result produced by a
+        dcraw run with relevant keys. A simplified version of this example is <a href="#code">considered below</a>.
+        <br/>
+        <b>-B</b> command-line switch turns on use of <a href="API-CXX-eng.html#open_buffer">open_buffer() API call</a>
+        used via mmap() of input file (Unix only).     
+      </li>
+      <li><b>dcraw_half</b> Demonstrates the use of <a href="API-C-eng.html">C API</a>. The example emulates the 
+        behavior of <b>dcraw -h</b> (no other control parameters can be specified in this example). The result of its
+        work must be binary identical to the results produced by <b>dcraw -h</b>. 
+      </li>
+      <li><b>dcraw_emu</b> Complete emulation of dcraw (except for keys -D -d -P -K -i -e, which are considered in
+        other usage examples). Of most interest is processing of command line keys (copied from dcraw).  The result of
+        its work must be binary identical to the results produced by dcraw with the same command line keys. 
+        <br/>
+        This sample supports gamma-corrected output of 16-bit data (use <b>-1</b> command-line switch).
+        <br/>
+        <b>-B</b> command-line switch turns on use of <a href="API-CXX-eng.html#open_buffer">open_buffer() API call</a>
+        used via mmap() of input file (Unix only).     
+      </li>
+      <li><b>half_mt</b> Emulation of <b>dcraw -h</b>. It &quot;understands&quot; the following keys: -a (automatic
+        white balance over the entire image), -w (white balance of the camera), -T (output in the tiff format), and -J
+        n (number of parallel threads launched for image processing).<br/>
+        On multiprocessor/multicore computers, the speed gain is notable in the case of mass processing. On a 
+        Win32 machine, the example is assembled from the initial file half_mt_win32.c, since
+        work with threads under Windows is fundamentally different and it it easier to copy simple source codes
+        than write one complex code. 
+      </li>
+      <li><b>mem_image</b> This sample uses 
+        <a  href="API-CXX-eng.html#dcraw_make_mem_image">dcraw_make_mem_image</a> and
+        <a  href="API-CXX-eng.html#dcraw_make_mem_thumb">dcraw_make_mem_thumb</a> calls, than writes data in PPM
+        format.  Results should be identical with dcraw with same command-line options (options supported: 
+        <b>-4, -1, -e, -h</b>). 
+      </li>
+      <li><b>unprocessed_raw</b> This sample extracts (mostly) unaltered RAW data including masked pixels
+        data (on supported cameras). Black level subtraction and zero pixel averaging is turned off.
+        If black frame exists and black frame extraction is supported for given format, masked pixels
+        data is added to resulting .TIFF file.
+        Command line options: <b>-q</b> - be quiet, <b>-A</b> - autoscale data (integer multiplier),
+        <b>-g</b> gamma-correction (gamma 2.2) for data (instead of precise linear one), <b>-N</b> turns off tone
+        curve correction of RAW data.
+        <p>
+          This sample is not included in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>      
+
+        </li>
+      <li><b>4channnels</b> - splits RAW-file into four separate 16-bit grayscale TIFFs (per RAW channel).<br/>
+        Command line switches:
+        <ul>
+          <li><b>-s N</b> selects  N-th image from RAW with multiple images</li>
+          <li><b>-g</b> gamma correction (gamma 2.2)</li>
+          <li><b>-A</b> values autoscale by auto-calculated integer factor</li>
+          <li><b>-B</b> turn off black subtraction</li>
+          <li><b>-N</b> no RAW curve </li>
+        </ul>
+        <p>
+          -N and -B command-line keys are not supported  in <a href=API-notes-eng.html#versions>LibRaw-Lite</a>. 
+        </p>      
+      </li>
+    </ul>
+    <h2>Example of docmode</h2>
+    <p>Below we consider the samples/simple_dcraw.cpp example, which emulates the behavior of 
+      <b>dcraw [-D] [-e][-v][-t]</b>. To save space, let us assume that keys -t -v are always specified (to avoid
+      comments on command line parsing) and there is always one parameter (name of file), which is the only one and
+      always passed to the program.  
+    </p>
+<pre>
+int main(int ac, char *av[])
+{
+    int  i, ret, verbose=0, output_thumbs=0;
+    char outfn[1024],thumbfn[1024]; 
+
+    // Creation of image processing object
+    LibRaw RawProcessor;
+    
+    // The date in TIFF is written in the local format; let us specify the timezone for compatibility with dcraw 
+    putenv ((char*)"TZ=UTC"); 
+
+// Let us define variables for convenient access to fields of RawProcessor
+
+#define P1  RawProcessor.imgdata.idata
+#define S   RawProcessor.imgdata.sizes
+#define C   RawProcessor.imgdata.color
+#define T   RawProcessor.imgdata.thumbnail
+#define P2  RawProcessor.imgdata.other
+#define OUT RawProcessor.imgdata.params
+
+    OUT.output_tiff = 1; // Let us output TIFF
+
+   // Let us open the file
+   if( (ret = RawProcessor.open_file(av[1])) != LIBRAW_SUCCESS)
+      {
+          fprintf(stderr,"Cannot open %s: %s\n",av[i],libraw_strerror(ret));
+
+          // recycle() is needed only if we want to free the resources right now. 
+          // If we process files in a cycle, the next open_file() 
+          // will also call recycle(). If a fatal error has happened, it means that recycle()
+          // has already been called (repeated call will not cause any harm either).
+
+          RawProcessor.recycle(); 
+          goto end;
+      }
+
+   // Let us unpack the image
+   if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS)
+      {
+          fprintf(stderr,"Cannot unpack_thumb %s: %s\n",av[i],libraw_strerror(ret));
+
+          if(LIBRAW_FATAL_ERROR(ret))
+                    goto end;
+          // if there has been a non-fatal error, we will try to continue
+      }
+  // Let us unpack the thumbnail
+  if( (ret = RawProcessor.unpack_thumb() ) != LIBRAW_SUCCESS)
+     {
+          // error processing is completely similar to the previous case
+           fprintf(stderr,"Cannot unpack_thumb %s: %s\n",av[i],libraw_strerror(ret));
+           if(LIBRAW_FATAL_ERROR(ret))
+                   goto end; 
+    }
+  else // We have successfully unpacked the thumbnail, now let us write it to a file
+    {
+      snprintf(thumbfn,sizeof(thumbfn),"%s.%s",av[i],T.tformat == LIBRAW_THUMBNAIL_JPEG ? "thumb.jpg" : "thumb.ppm");
+      if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_thumb_writer(thumbfn)))
+        {
+                fprintf(stderr,"Cannot write %s: %s\n",thumbfn,libraw_strerror(ret));
+
+                // in the case of fatal error, we should terminate processing of the current file
+                if(LIBRAW_FATAL_ERROR(ret))
+                          goto end; 
+        }
+    }
+   // Data unpacking
+   if(OUT.document_mode)
+           ret = RawProcessor.dcraw_document_mode_processing();
+   else
+           ret = RawProcessor.dcraw_process();
+
+    if(LIBRAW_SUCCESS != ret ) // error at the previous step
+          {
+               fprintf(stderr,"Cannot do postprocessing on %s: %s\n",av[i],libraw_strerror(ret));
+               if(LIBRAW_FATAL_ERROR(ret))
+                        goto end;
+          }
+   else  // Successful document processing
+     {
+        snprintf(outfn,sizeof(outfn),"%s.%s", av[i], "tiff");
+        if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
+                fprintf(stderr,"Cannot write %s: error %d\n",outfn,ret);
+     }
+
+  // we don't evoke recycle() or call the desctructor; C++ will do everything for us
+  return 0;
+end:
+  // got here after an error
+  return 1;
+}
+</pre>
+
+
+    <a href=index-eng.html>[back to Index]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 12:19:36 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:52 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/Samples-LibRaw-rus.html b/libfspotraw/LibRaw/doc/Samples-LibRaw-rus.html
new file mode 100644
index 0000000..43fa54d
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/Samples-LibRaw-rus.html
@@ -0,0 +1,186 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw: ïðèìåðû èñïîëüçîâàíèÿ</title>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+  </head>
+
+  <body>
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <h1>LibRaw: ïðèìåðû èñïîëüçîâàíèÿ</h1>
+    
+    <h2>Îáçîð ïðèìåðîâ â äèñòðèáóòèâå (samples/*)</h2>
+    <p> ïîñòàâêó  LibRaw  âêëþ÷åíî íåñêîëüêî ïðèìåðîâ èñïîëüçîâàíèÿ áèáëèîòåêè, èõ èñõîäíûå òåêñòû ðàñïîëîæåíû â
+      êàòàëîãå samples/, ïîñëå ñáîðêè îíè îêàçûâàþòñÿ â êàòàëîãå bin/:</p>
+    <ul>
+      <li><b>raw-identify</b> Èç âûçîâîâ  LibRaw èñïîëüçóåòñÿ òîëüêî <a
+          href="API-CXX-rus.html#open_file">open_file()</a>, äàëåå èäåò êîä, ïå÷àòàþùèé çíà÷åíèÿ ïîëåé ñòðóêòóðû
+        imgdata. Âûäà÷à <b>raw-identify</b>/<b>raw-identify -v</b> ïðàêòè÷åñêè ïîëíîñòüþ êîïèðóåò âûäà÷ó <b>dcraw
+          -i</b>/<b>dcraw -i -v </b> (â âûäà÷å ïðèìåðà äîïîëíèòåëüíî ïå÷àòàþòñÿ èñòî÷íèêè öâåòîâûõ äàííûõ è ëåãåíäà ê
+        íèì). 
+      </li>
+      <li><b>simple_dcraw</b> Ïðîñòîé "ýìóëÿòîð" dcraw, âîñïðîèçâîäÿùèé ïîâåäåíèå <b>dcraw [-D] [-e] [-v]
+          [-T]</b>. Ðåçóëüòàò ðàáîòû äîëæåí áèíàðíî ñîâïàäàòü ñ ðåçóëüòàòàìè ðàáîòû dcraw çàïóùåííîé ñ íóæíûìè
+        êëþ÷àìè. Óïðîùåííûé âàðèàíò ýòîãî ïðèìåðà <a href="#code">ðàññìîòðåí íèæå</a>.<br/>
+        Êëþ÷ <b>-B</b> âêëþ÷àåò èñïîëüçîâàíèå <a href="API-CXX-rus.html#open_buffer">èíòåðôåéñà open_buffer()</a>
+        êóäà ïåðåäàåòñÿ mmap()-ed ôàéë (Unix only).
+
+      </li>
+      <li><b>dcraw_half</b> Äåìîíñòðàöèÿ èñïîëüçîâàíèÿ <a href="API-C-rus.html">C API</a>. Ïðèìåð ýìóëèðóåò ïîâåäåíèå
+        <b>dcraw -h</b> (êàêèå-òî åùå óïðàâëÿþùèå ïàðàìåòðû ýòîìó ïðèìåðó  çàäàòü íåëüçÿ). Ðåçóëüòàò ðàáîòû äîëæåí
+        áèíàðíî ñîâïàäàòü ñ ðåçóëüòàòàìè ðàáîòû <b>dcraw -h</b>.
+      </li>
+      <li><b>dcraw_emu</b> Ïîëíûé ýìóëÿòîð dcraw (çà èñêëþ÷åíèåì êëþ÷åé -D -d -P -K -i -e, êîòîðûå îáðàáàòûâàþòñÿ â
+        äðóãèõ ïðèìåðàõ èñïîëüçîâàíèÿ). Îñíîâíîé èíòåðåñ ïðåäñòàâëÿåò îáðàáîòêà êëþ÷åé êîìàíäíîé ñòðîêè (ñêîïèðîâàííàÿ
+        èç  dcraw). Ðåçóëüòàò ðàáîòû äîëæåí áèíàðíî ñîâïàäàòü ñ ðåçóëüòàòîì ðàáîòû  dcraw ñ òåìè æå êëþ÷àìè êîìàíäíîé
+        ñòðîêè.<br/>
+        Ýòîò ïðèìåð ïîääåðæèâàåò äîïîëíèòåëüíûé êëþ÷ êîìàíäíîé ñòðîêè <b>-1</b>, îçíà÷àþùèé "âûâîäèòü 16-áèòíûå
+        äàííûå (tiff/ppm/pgm) ñ ãàììà-êîððåêöèåé".<br/>
+        Êëþ÷ <b>-B</b> âêëþ÷àåò èñïîëüçîâàíèå <a href="API-CXX-rus.html#open_buffer">èíòåðôåéñà open_buffer()</a>
+        êóäà ïåðåäàåòñÿ mmap()-ed ôàéë (Unix only).
+      </li>
+      <li><b>half_mt</b> Ýìóëÿòîð <b>dcraw -h</b>, ïîíèìàåò êëþ÷è -a (àâòîìàòè÷åñêèé áàëàíñ áåëîãî ïî âñåìó
+        èçîáðàæåíèþ), -w (áàëàíñ áåëîãî êàìåðû), -T (âûâîäèòü â tiff) è -J n - êîëè÷åñòâî ïàðàëëåëüíûõ threads,
+        çàïóñêàåìûõ äëÿ îáðàáîòêè èçîáðàæåíèé.<br/>
+        Íà ìóëüòèïðîöåññîðíûõ/multicore  ìàøèíàõ äàåò ñóùåñòâåííûé âûèãðûø â ñêîðîñòè ïðè ìàññîâîé îáðàáîòêå.<br/>
+        Íà Win32-ìàøèíå ïðèìåð ñîáèðàåòñÿ èç èñõîäíîãî ôàéëà half_mt_win32.c, ïðè÷èíà â òîì, ÷òî ðàáîòà ñ threads íà
+        Windows ïðèíöèïèàëüíî äðóãàÿ è ïðîùå ðàçìíîæèòü ïðîñòûå èñõîäíèêè, ÷åì íàïèñàòü îäèí ñëîæíûé. 
+      </li>
+      <li><b>mem_image</b> Ïðèìåð èñïîëüçîâàíèÿ ôóíêöèé 
+        <a  href="API-CXX-rus.html#dcraw_make_mem_image">dcraw_make_mem_image</a> è 
+        <a  href="API-CXX-rus.html#dcraw_make_mem_thumb">dcraw_make_mem_thumb</a>: ðàñïàêîâêà èçîáðàæåíèé è preview()
+        â ïàìÿòü ñ ïîñëåäóþùåé ïðîñòîé çàïèñüþ â ôîðìàòàõ PPM (è JPEG äëÿ thumbnail). Ðåçóëüòàò ðàáîòû äîëæåí áûòü
+        èäåíòè÷åí ðåçóëüòàòàì ðàáîòû dcraw ñ òåìè æå êëþ÷àìè (ïîääåðæèâàþòñÿ êëþ÷è <b>-4, -1, -e, -h</b>). 
+      </li>
+      <li><b>unprocessed_raw</b> - èçâëå÷åíèå ìàêñèìàëüíî íåèçìåíåííûõ RAW-äàííûõ, áåç âû÷èòàíèÿ óðîâíÿ ÷åðíîãî
+        è ìàñêèðîâàíèÿ ÷åðíûõ ïèêñåëîâ (íà òåõ êàìåðàõ, ãäå âîçìîæíî ìàñêèðîâàíèå). Äëÿ òåõ êàìåð, êîòîðûå âûäàþò
+        â RAW-äàííûå ÷åðíóþ ðàìêó (ìàñêèðîâàííûå ïèêñåëû) - ðàìêà âêëþ÷àåòñÿ â âûäàâàåìûå äàííûå. 
+        Êëþ÷è êîìàíäíîé ñòðîêè: <b>-q</b> - íå âûäàâàòü òåêñòîâóþ ñïðàâêó î ðàçìåðàõ ôàéëà, <b>-A</b> -
+        àâòîìàñøòàáèðîâàíèå äàííûõ â öåëîå ÷èñëî ðàç, <b>-g</b> âûäàâàòü ãàììà-êîððåêòèðîâàííûå (2.2) äàííûå, à íå
+        ëèíåéíûå, <b>-N</b> - âûêëþ÷àåò íàëîæåíèå òîíîâîé êðèâîé íà RAW-äàííûå.
+        <p>
+          Â ñîñòàâ <a href=API-notes-rus.html#versions>LibRaw-Lite</a> äàííûé ïðèìåð íå âõîäèò.
+        </p>
+        
+        </li>
+      <li><b>4channnels</b> - ñîõðàíÿåò RAW-ôàéë â âèäå 4 îòäåëüíûõ 16-áèòíûõ grayscale TIFF-ôàéëîâ (ïîêàíàëüíî).<br/>
+        Êëþ÷è êîìàíäíîé ñòðîêè:
+        <ul>
+          <li><b>-s N</b> âûáðàòü N-å èçîáðàæåíèå (äëÿ ôàéëîâ ñ íåñêîëüêèìè èçîáðàæåíèÿìè)</li>
+          <li><b>-g</b> âûâîäèòü ãàììà-êîððåêòèðîâàííîå (2.2) èçîáðàæåíèå</li>
+          <li><b>-A</b> àâòîìàñøòàáèðîâàíèå çíà÷åíèé â öåëîå ÷èñëî ðàç</li>
+          <li><b>-B</b> îòêëþ÷èòü âû÷èòàíèå óðîâíÿ ÷åðíîãî</li>
+          <li><b>-N</b> îòêëþ÷èòü òîíîâóþ êðèâóþ äëÿ RAW</li>
+        </ul>
+        <p>
+           ïðèìåðå äëÿ <a href=API-notes-rus.html#versions>LibRaw-Lite</a> êëþ÷è -B è -N íå ïîääåðæèâàþòñÿ.
+        </p>
+      </li>
+    </ul>
+
+    <h2>Ïðèìåð simple_dcraw</h2>
+    <p>Íèæå ðàññìîòðåí ïðèìåð samples/simple_dcraw.cpp - ýìóëèðóþùèé ïîâåäåíèå <b>dcraw [-D] [-e][-v][-t]</b>. Äëÿ
+      ýêîíîìèè ìåñòà ïðåäñòàâèì, ÷òî âñåãäà çàäàíû êëþ÷è -t -v (÷òîáû íå êîììåíòèðîâàòü ðàçáîð êîìàíäíîé ñòðîêè)
+      è ÷òî ïàðàìåòð (èìÿ ôàéëà) âñåãäà îäèí è âñåãäà ïåðåäàåòñÿ.
+    </p>
+<pre>
+int main(int ac, char *av[])
+{
+    int  i, ret, verbose=0, output_thumbs=0;
+    char outfn[1024],thumbfn[1024]; 
+
+    // Ñîçäàäèì îáúåêò - îáðàáîò÷èê èçîáðàæåíèé.
+    LibRaw RawProcessor;
+    
+    // Â TIFF ïèøåòñÿ äàòà â ëîêàëüíîì ôîðìàòå, äëÿ ñîâìåñòèìîñòè ñ dcraw ïîñòàâèì òàéìçîíó
+    putenv ((char*)"TZ=UTC"); 
+
+// Îïðåäåëèì ïåðåìåííûå äëÿ óäîáíîãî äîñòóïà ê ïîëÿì RawProcessor
+#define P1  RawProcessor.imgdata.idata
+#define S   RawProcessor.imgdata.sizes
+#define C   RawProcessor.imgdata.color
+#define T   RawProcessor.imgdata.thumbnail
+#define P2  RawProcessor.imgdata.other
+#define OUT RawProcessor.imgdata.params
+
+    OUT.output_tiff = 1; // Âûâîäèòü áóäåì TIFF
+
+   // Îòêðîåì ôàéë
+   if( (ret = RawProcessor.open_file(av[1])) != LIBRAW_SUCCESS)
+      {
+          fprintf(stderr,"Cannot open %s: %s\n",av[i],libraw_strerror(ret));
+
+          // recycle() íóæåí òîëüêî åñëè ìû õîòèì îñâîáîäèòü ðåñóðñû ïðÿìî ñåé÷àñ.
+          // Åñëè ìû îáðàáàòûâàåì ôàéëû â öèêëå, òî ñëåäóþùèé open_file() 
+          // òîæå âûçîâåò recycle. Åñëè ñëó÷èëàñü ôàòàëüíàÿ îøèáêà, òî recycle()
+          // óæå âûçâàí (âðåäà îò ïîâòîðíîãî âûçîâà òîæå íåò)
+
+          RawProcessor.recycle(); 
+          goto end;
+      }
+
+   // Ðàñïàêóåì èçîáðàæåíèå
+   if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS)
+      {
+          fprintf(stderr,"Cannot unpack_thumb %s: %s\n",av[i],libraw_strerror(ret));
+
+          if(LIBRAW_FATAL_ERROR(ret))
+                    goto end;
+          // äëÿ íåôàòàëüíîé îøèáêè - ïðîáóåì ïðîäîëæèòü
+      }
+  // Ðàñïàêóåì thumbnail
+  if( (ret = RawProcessor.unpack_thumb() ) != LIBRAW_SUCCESS)
+     {
+          // îáðàáîòêà îøèáêè ïîëíîñòüþ àíàëîãè÷íà ïðåäûäóùåìó ñëó÷àþ
+           fprintf(stderr,"Cannot unpack_thumb %s: %s\n",av[i],libraw_strerror(ret));
+           if(LIBRAW_FATAL_ERROR(ret))
+                   goto end; 
+    }
+  else // Óñïåøíî ðàñïàêîâàëè thumbnail, çàïèøåì åãî â ôàéë
+    {
+      snprintf(thumbfn,sizeof(thumbfn),"%s.%s",av[i],T.tformat == LIBRAW_THUMBNAIL_JPEG ? "thumb.jpg" : "thumb.ppm");
+      if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_thumb_writer(thumbfn)))
+        {
+                fprintf(stderr,"Cannot write %s: %s\n",thumbfn,libraw_strerror(ret));
+
+                // â ñëó÷àå ôàòàëüíîé îøèáêè ìû äîëæíû çàêàí÷èâàòü îáðàáîòêó òåêóùåãî ôàéëà
+                if(LIBRAW_FATAL_ERROR(ret))
+                          goto end; 
+        }
+    }
+   // Ðàñïàêîâêà äàííûõ
+   if(OUT.document_mode)
+           ret = RawProcessor.dcraw_document_mode_processing();
+   else
+           ret = RawProcessor.dcraw_process();
+
+    if(LIBRAW_SUCCESS != ret ) // îøèáêà íà ïðåäûäóùåì øàãå
+          {
+               fprintf(stderr,"Cannot do postprocessing on %s: %s\n",av[i],libraw_strerror(ret));
+               if(LIBRAW_FATAL_ERROR(ret))
+                        goto end;
+          }
+   else  // Óñïåøíàÿ îáðàáîòêà äîêóìåíòà
+     {
+        snprintf(outfn,sizeof(outfn),"%s.%s", av[i], "tiff");
+        if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
+                fprintf(stderr,"Cannot write %s: error %d\n",outfn,ret);
+     }
+
+  // Íå äåëàåì recycle, íå çîâåì äåñòðóêòîð, C++ âñå äåëàåò çà íàñ.
+  return 0;
+end:
+  // ñþäà ïîïàëè ïîñëå îøèáêè
+  return 1;
+}
+</pre>
+
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 12:19:36 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:59 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/Why-LibRaw-eng.html b/libfspotraw/LibRaw/doc/Why-LibRaw-eng.html
new file mode 100644
index 0000000..5785b9c
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/Why-LibRaw-eng.html
@@ -0,0 +1,230 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>Purpose and Objectives</title>
+  </head>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+
+  <body>
+    <a href=index-eng.html>[back to Index]</a>
+    <h1>LibRaw Project Goals and Objectives</h1>
+    <h2>Contents</h2>
+    <ol>
+      <li><a href="#audience">Who May Be Interested in This Project</a></li>
+      <li><a href="#goals">Goals and Objectives</a></li>
+      <li><a href="#support">LibRaw Support Principles</a></li>
+      <li><a href="#better">Implemented Improvements of dcraw</a></li>
+      <li><a href="#todo">Planned Improvements</a></li>
+    </ol>
+    
+    <a name="audience"></a>
+    <h2>Who May Be Interested in This Project</h2>
+    <p>The proposed project and the software products generated within this project are intended for</p>
+    <ul>
+      <li>Developers of RAW converters, including current and new developments</li>
+      <li>Those willing to write their own graphic interface for RAW file processing</li>
+      <li>Developers and enthusiasts creating their own primary and auxiliary data processing algorithms,
+including
+        <ul>
+          <li>Interpolation (de-Bayer),</li>
+          <li>Noise reduction</li>
+          <li>White balance</li>
+          <li>Correction of aberrations and distortions</li>
+          <li>Color conversions (e.g., creation, editing and application of camera profiles )</li>
+          <li>RAW data analysis</li>
+          <li>Comparison of cameras and lenses</li>
+          <li>and so on...</li>
+        </ul>
+      </li>
+      </ul>
+    <p>Among the few existing implementations of RAW converters, those based on the 
+      <A  HREF="http://cybercom.net/~dcoffin/dcraw/";>dcraw</A> utility by Dave Coffin are the most used.
+It is hard to find a more or less popular camera that is not supported by this 
+utility; while the implementation of RAW data extraction in dcraw is of
+a very high quality.
+    </p>
+    <P>However, developers and enthusiasts who use or are going to use dcraw for
+ 	fulfilling the above-listed and similar objectives encounter a
+	number of difficulties. First, the author of dcraw refuses to turn his
+	product into a handy library, yet permitting anybody else to do so.
+	Besides, dcraw contains a number of questionable features which may
+	hinder its use without modifications, as well as instances of
+	distortions in the photographic sense of it. As a result, once every
+	several months, virtually all developers, part of them listed on the
+    	dcraw Web site, independently convert each subsequent release of the
+   	software into the library.
+	</p>
+    <p>
+        As for enthusiasts, the "entry cost" of verifying their own ideas and
+        implementing their own algorithms is often unreasonably high: they have
+        to either use the dcraw command line, thus being forced to use the
+        unavoidable early processing stages, or understand the source code and
+        maintain their own library based on it.
+    </p>
+    <p>
+        Thus, the inconveniences of dcraw make the developers' community quite
+        small and halt further evolution and improvement of RAW format
+        converters.
+     </p>
+    <a name="goals"></a>
+    <h2>Goals and Objectives</h2>
+    <p>We are going to create LibRaw in order to &quot;<b>get a library based on dcraw, only better</b>&quot;. Thus:
+    </p>
+    <ol>
+      <li>To &quot;librarize&quot; dcraw, i.e., to develop a stable and consistent API suitable for other applications
+  (RAW converters, data analyzers, panorama stitchers, etc.).
+      </li>
+      <li>To divide processing into independent parts (groups of API calls)
+        <ul>
+          <li> Reading, decoding, and unpacking of RAW data: <b>this is the main functionality of LibRaw</b></li>
+          <li> Data conversions: interpolation, white balance, etc.</li>
+          <li> File output of the processing results.</li>
+        </ul>
+        The latter two groups of functions are maintained primarily for dcraw  compatibility testing.
+      </li>
+      <li>To improve the procedures of RAW data retrieval and decoding (see below for details)
+      </li>
+      <li>To supply other developers with a &quot;framework&quot; (freeware and open-source), e.g.,
+for experimenting with their own methods of RAW data processing 
+(interpolation, noise reduction, white balance, etc.; some directions
+of the possible efforts are <a href="#audience">listed above</a>), 
+so that they could create their own GUI programs and interfaces without developing the entire RAW converter.</li>
+      <li>To ensure easy modification for code synchronization with dcraw releases.</li>
+    </ol>
+
+    <a name="support"></a>
+    <h2>LibRaw Support Principles</h2>
+      <ol>
+      <li>To reproduce the functionality of dcraw using its source code as the basis for our work; to
+achieve binary identity of results generated by dcraw and by LibRaw-based utilities, provided the same processing settings are used.
+      </li>
+      <li>To eliminate the shortcomings of dcraw (see sections 
+<a href="#better">Implemented Improvements of dcraw</a> and <a  href="#todo">Planned Improvements</a>).
+      </li>
+      <li>To monitor future improvements in dcraw (support of new cameras,  error correction, 
+use of better algorithms) and import them from dcraw to LibRaw.
+      </li>
+      <li>API modifications: the <a href="#todo">planned improvements</a> will <b>require</b> extending
+of the API. Such changes will be introduced in the form of large change-sets, 
+while the compatibility mode supporting older
+        applications based on the legacy API set will be preserved as long
+        as possible.
+      </li>
+      </ol>
+
+    <a name="better"></a>
+    <h2>Implemented Improvements of  dcraw</h2>
+    <p>
+    As of the time of writing, additional improvements to the dcraw source
+       code have been introduced into LibRaw:
+	</p>
+      <ul>
+      <li>
+      All global variables have been removed (while linking the
+              thread-safe version, static variables of functions have been
+              removed as well).
+      </li>
+      <li>Thread safety. An example of its use in the multithreaded model is included into the library distribution package.
+      </li>
+      <li>
+      Data extracted from a RAW file is already somewhat structured:
+      geometry is separated from color data.
+        <i>This work has not yet been completed; it will be continued simultaneously with the
+<a href="#todo">work on improvement of EXIF processing</a></i>.
+      </li> 
+      <li>Retrieval of RAW data and thumbnail can be performed in two or three API calls with a very simple
+program interface.
+      </li> 
+      <li>Work with color information: color data (white balance coefficients, tone curve, etc.) has flags referencing the source of this information: retrieved from RAW data, calculated
+from the image itself, or taken from the code as constants.
+      </li>
+      <li>ICC profile is extracted (for those RAW files that contain it).</li>
+      <li>The image itself and the thumbnail can be retrieved by successive calls, without reopening the file
+or relaunching the library. 
+      </li>
+      <li>The required amount of RAM is somewhat lower.</li>
+    <li><b>Work with masked pixels and black subtraction:</b>: it is possible to turn off all data filtering 
+	and black level subtraction.</li>
+    </ul>
+
+    <a name="todo"></a>
+    <h2>Planned Improvements</h2>
+    <p>The dcraw code needs significant modifications and additions:</p>
+    <ul>
+      <li><b>Output of unpacked data in various memory layouts</b>: depending on the requirements of
+the calling program, the results of RAW unpacking will be output in one of the following runtime-selected formats:
+        <ul>
+          <li>Four-component pixels (internal dcraw data format)</li>
+          <li>Bayer format: 2D array with each element corresponding to a pixel in the matrix</li>
+          <li>4 two-dimensional arrays (one per component).</li>
+          </ul>
+        </li>
+      <li><b>Single-pass unpacking of RAW files containing several image variants/planes</b>: for applicable cameras (Fuji cameras, cameras with 4-shot/16-shot modes), several planes of the same image will be
+extracted.
+        </li>
+      <li><b>Processing the extremes of the value range</b>: minimum values (often referred to as black point) and
+        maximum values (saturation point).
+        <ul>
+          <li>The black point should not be subtracted from the data at the unpacking stage, in contrast to the implementation found in dcraw: the calling
+application may have its own plans, e.g., channel-wise subtraction of the minimum.
+          </li>
+          <li>The maximum values may also be nonidentical for different channels; accordingly, these values
+should be calculated at the stage of RAW data unpacking and output within the framework of the API. Calculation of the maximum
+values for a given camera sample at a specified sensitivity (converter calibration) is to be done in the
+application that calls LibRaw.
+          </li>
+        </ul>
+      </li>
+      <li><b>Processing of the black frame</b>: black subtraction and zero pixel cleaning already can be turned off. 
+	Code for accurate black level calculation and banding suppression is planned.</li>
+
+      <li><b>Data unpacking verifications for the widest possible set of file formats</b>. According to some studies, dcraw
+does not completely ensure correct unpacking of some data formats.
+      </li>
+
+      <li><b>Processing of the EXIF/Makernote</b> data: retrieval of large data amounts, including
+        <ul>
+          <li>Extraction of the maximum possible amount of color data (white balance settings, 
+profile, tone curve, contrast settings, etc.)</li>
+
+          <li>Color data generalization: reduction of color data from different cameras 
+&quot;to a common denominator&quot; in order to facilitate color processing (without loss of quality)</li>
+
+          <li>Extraction of camera data  (firmware version, serial number)</li>
+
+          <li>Extraction of photographic data (lens used, focusing distance, focus points and their coordinates, etc.)</li>
+
+          <li>Extraction of the bulk EXIF data set without analyzing the structure in order to 
+facilitate copying of that EXIF data to output files.</li>
+        </ul>
+      </li>
+      <li>Generalization of work with complex formats, including
+        <ul>
+          <li>RAW files from Fuji cameras (with two sets of sensors)</li>
+          <li>RAW files from digital backs with 4-shot and 16-shot modes.</li>
+        </ul>
+      </li>
+      <li>Technical improvements, including
+        <ul>
+          <li>Extraction of ICC profile (for those RAW files that contain it)</li>
+          <li>Cutting down on the size of the allocated memory - in cases where post-processing will not be performed in the
+same buffer as the one used for reading the RAW data.</li>
+        </ul>
+      </li>
+    </ul>
+    <p>At the same time, we are not planning any modifications or extensions of the dcraw data processing code
+ (de-Bayer, color conversions, etc.); all of this is up to the calling application. Standard processing modes
+     included in dcraw will be preserved for an indefinite time in the set
+     of dcraw-emulating API calls, with the exception of LCMS and libjpeg
+     support, as well as certain processing stages of minor importance.
+    </p>
+
+    <a href=index-eng.html>[back to Index]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 09:12:42 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:51 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/Why-LibRaw-rus.html b/libfspotraw/LibRaw/doc/Why-LibRaw-rus.html
new file mode 100644
index 0000000..3c3d658
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/Why-LibRaw-rus.html
@@ -0,0 +1,223 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>Öåëè è çàäà÷è</title>
+  </head>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+
+  <body>
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <h1>Öåëè è çàäà÷è ïðîåêòà LibRaw</h1>
+    <h2>Ñîäåðæàíèå</h2>
+    <ol>
+      <li><a href="#audience">Êîìó ìîæåò áûòü èíòåðåñåí ýòîò ïðîåêò, è ÷òî ìû õîòèì ïîëó÷èòü</a></li>
+      <li><a href="#goals">Öåëè è çàäà÷è</a></li>
+      <li><a href="#support">Ïðèíöèïû ñîïðîâîæäåíèÿ LibRaw</a></li>
+      <li><a href="#better">Ïðîèçâåäåííûå óëó÷øåíèÿ dcraw</a></li>
+      <li><a href="#todo">Ïëàíèðóåìûå óëó÷øåíèÿ</a></li>
+    </ol>
+    
+    <a name="audience"></a>
+    <h2>Êîìó ìîæåò áûòü èíòåðåñåí ýòîò ïðîåêò</h2>
+    <p>Ïðåäëàãàåìûé âàøåìó âíèìàíèþ ïðîåêò è ïîðîæäàåìûé èì ïðîãðàììíûé ïðîäóêò ïðåäíàçíà÷åíû äëÿ:</p>
+    <ul>
+      <li>ðàçðàáîò÷èêîâ íîâûõ raw-êîíâåðòîðîâ,</li>
+      <li>æåëàþùèõ íàïèñàòü ñâîé ãðàôè÷åñêèé èíòåðôåéñ äëÿ îáðàáîòêè raw-ôàéëîâ</li>
+      <li> ðàçðàáîò÷èêîâ è ýíòóçèàñòîâ, ñîçäàþùèõ îòäåëüíûå ñîáñòâåííûå îñíîâíûå è âñïîìîãàòåëüíûå àëãîðèòìû îáðàáîòêè
+        èçîáðàæåíèé, êàê òî:
+        <ul>
+          <li>èíòåðïîëÿöèÿ (äåáàéåðèçàöèÿ),</li>
+          <li>øóìîïîíèæåíèå,</li>
+          <li>áàëàíñ áåëîãî,</li>
+          <li>êîððåêöèÿ àáåððàöèé è äèñòîðñèé,</li>
+          <li>ïðåîáðàçîâàíèÿ öâåòà (íàïðèìåð, îáðàáîòêà ïðîôèëåé êàìåð),</li>
+          <li>àíàëèç äàííûõ raw,</li>
+          <li>ñðàâíåíèå êàìåð è îáúåêòèâîâ</li>
+          <li>è òàê äàëåå...</li>
+        </ul>
+      </li>
+      </ul>
+    <p>Ñðåäè ñóùåñòâóþùèõ ñåãîäíÿ îòíîñèòåëüíî íåìíîãî÷èñëåííûõ ðåàëèçàöèé ðàñïàêîâêè RAW-äàííûõ, ïîëó÷àåìûõ ñ öèôðîâûõ
+      ôîòîêàìåð  íàèáîëåå ðàñïðîñòðàíåíû è íàèáîëåå øèðîêî èñïîëüçóþòñÿ ðåàëèçàöèè íà îñíîâå óòèëèòû 
+      <A  HREF="http://cybercom.net/~dcoffin/dcraw/";>dcraw</A>, íàïèñàííîé Dave Coffin. Åå ïîïóëÿðíîñòü
+      ñâÿçàíà ñ òåì, ÷òî òðóäíî íàéòè ñêîëüêî-íèáóäü ðàñïðîñòðàí¸ííóþ êàìåðó, êîòîðàÿ íå áûëà áû ïîääåðæàíà äàííîé
+      óòèëèòîé, à ñàì óðîâåíü ïîääåðæêè ðàñïàêîâêè âåñüìà õîðîøèé.
+    </p>
+    <P>Îäíàêî íà ïóòè ðàçðàáîò÷èêîâ è ýíòóçèàñòîâ, èñïîëüçóþùèõ èëè ñîáèðàþùèõñÿ èñïîëüçîâàòü dcraw äëÿ ðåøåíèÿ
+      óêàçàííûõ âûøå çàäà÷, ñòîÿò íåñêîëüêî ïðåïÿòñòâèé. Ïåðâîå èç íèõ ñîñòîèò â òîì, ÷òî àâòîð dcraw ïðèíöèïèàëüíî íå
+      îôîðìëÿåò ñâîé ïðîãðàììíûé ïðîäóêò â âèäå áèáëèîòåêè, óäîáíîé äëÿ èñïîëüçîâàíèÿ, îñòàâëÿÿ ýòî íà îòêóï âñåì
+      æåëàþùèì (è íå âîçðàæàÿ ïðîòèâ ýòîãî).   Ïîìèìî ýòîãî, dcraw ñîäåðæèò ðÿä îñîáåííîñòåé è ôîòîãðàôè÷åñêèõ
+      íåêîððåêòíîñòåé, êîòîðûå ìîãóò ìåøàòü åå èñïîëüçîâàíèþ áåç ìîäèôèêàöèé. 
+       ðåçóëüòàòå, ïðàêòè÷åñêè âñå
+      ðàçðàáîò÷èêè (÷àñòü èç êîòîðûõ ïåðå÷èñëåíà íà ñàéòå dcraw) ðàç â íåñêîëüêî ìåñÿöåâ, íåçàâèñèìî äðóã îò äðóãà
+      ïåðåâîäÿò î÷åðåäíóþ âåðñèþ óòèëèòû â áèáëèîòå÷íûé âèä. 
+    </p>
+    <p>
+      Äëÿ ýíòóçèàñòîâ æå &laquo;âõîäíàÿ ñòîèìîñòü&raquo;
+      âîçìîæíîñòè ïðîâåðêè ñîáñòâåííûõ èäåé è ðåàëèçàöèè ñîáñòâåííûõ àëãîðèòìîâ îêàçûâàåòñÿ, çà÷àñòóþ, íåïîìåðíî
+      âûñîêîé: íóæíî ëèáî ïîëüçîâàòüñÿ êîìàíäíîé ñòðîêîé dcraw (÷òî ïðèâîäèò ê îáÿçàòåëüíîìó èñïîëüçîâàíèþ
+      íåîòêëþ÷àåìûõ ðàííèõ ñòàäèé îáðàáîòêè), ëèáî ðàçîáðàòüñÿ â èñõîäíîì êîäå dcraw è ïîääåðæèâàòü ñîáñòâåííóþ
+      áèáëèîòåêó íà åå îñíîâå.
+    </p>
+    <p>Òàêèì îáðàçîì, íåóäîáñòâà, ïðèñóùèå dcraw, çíà÷èòåëüíî ñóæàþò ñîîáùåñòâî ðàçðàáîò÷èêîâ è òîðìîçÿò ïðîöåññ
+      ðàçâèòèÿ è ñîâåðøåíñòâîâàíèÿ êîíâåðòîðîâ RAW-ôîðìàòà. 
+    </p>
+
+    <a name="goals"></a>
+    <h2>Öåëè è çàäà÷è</h2>
+    <p>Ïðè ñîçäàíèè LibRaw ìû õîòèì "<b>ïîëó÷èòü áèáëèîòåêó íà îñíîâå dcraw, òîëüêî ëó÷øå</b>":
+    </p>
+    <ol>
+      <li>"îáèáëèîòå÷èòü" dcraw, ò.å. ðàçðàáîòàòü ñòàáèëüíûé è êîíñèñòåíòíûé API, ïðèãîäíûé äëÿ èñïîëüçîâàíèÿ â äðóãèõ
+      ïðèëîæåíèÿõ (RAW-êîíâåðòîðàõ, àíàëèçàòîðàõ äàííûõ, ñêëåéùèêàõ ïàíîðàì è òàê äàëåå).
+      </li>
+      <li>Ðàçäåëèòü íà íåçàâèñèìûå ÷àñòè (ãðóïïû âûçîâîâ API):
+        <ul>
+          <li> ÷òåíèå, ðàñêîäèðîâàíèå è ðàñïàêîâêó  RAW-äàííûõ - <b>è ýòî îñíîâíàÿ ôóíêöèîíàëüíîñòü LibRaw</b>;</li>
+          <li> ïðåîáðàçîâàíèÿ äàííûõ: èíòåðïîëÿöèþ, áàëàíñ áåëîãî è ò.ï.;</li>
+          <li> âûâîä ðåçóëüòàòîâ îáðàáîòêè â ôàéëû.</li>
+        </ul>
+        Äâå ïîñëåäíèå ãðóïïû ôóíêöèé ïîääåðæèâàþòñÿ, â ïåðâóþ î÷åðåäü, äëÿ öåëåé òåñòèðîâàíèÿ ñîâìåñòèìîñòè ñ dcraw.
+      </li>
+      <li>Óëó÷øèòü ïðîöåäóðû èçâëå÷åíèÿ è ðàñêîäèðîâàíèÿ RAW-äàííûõ (ïîäðîáíåå - íèæå)
+      </li>
+      <li>Äàòü äðóãèì ðàçðàáîò÷èêàì "ðàìêó" (áåñïëàòíóþ è â îòêðûòûõ èñõîäíèêàõ) â êîòîðîé ìîæíî áûëî áû, íàïðèìåð,
+        ýêñïåðèìåíòèðîâàòü ñî ñâîèìè ñïîñîáàìè îáðàáîòêè RAW-äàííûõ (èíòåðïîëÿöèÿ, øóìîïîíèæåíèå, áàëàíñ áåëîãî è òàê
+        äàëåå, âîçìîæíûå âàðèàíòû ïðèëîæåíèÿ ñâîèõ óñèëèé <a href="#audience">÷àñòè÷íî ïåðå÷èñëåíû âûøå</a>), è
+        ñîçäàâàòü ñâîè ãðàôè÷åñêèå îáîëî÷êè è èíòåðôåéñû íå ðàçðàáàòûâàÿ RAW-êîíâåðòîð öåëèêîì.
+      </li>
+      <li>Îáåñïå÷èòü ë¸ãêîñòü âíåñåíèÿ èçìåíåíèé äëÿ ñèíõðîíèçàöèè êîäà ñ ðåëèçàìè ñàìîé dcraw.</li>
+    </ol>
+
+    <a name="support"></a>
+    <h2>Ïðèíöèïû ñîïðîâîæäåíèÿ LibRaw</h2>
+      <ol>
+      <li>Ïîâòîðèòü ôóíêöèîíàëüíîñòü dcraw, âçÿâ åå èñõîäíûå òåêñòû çà îñíîâó, äîáèòüñÿ áèíàðíîé èäåíòè÷íîñòè (ïðè
+        îäèíàêîâûõ íàñòðîéêàõ) ðåçóëüòàòîâ ðàáîòû dcraw è óòèëèò íà îñíîâå LibRaw.
+      </li>
+      <li>Èçáàâëÿòüñÿ îò íåäîñòàòêîâ dcraw (î íåêîòîðûõ èç íèõ ñì. íèæå <a href="#better">óëó÷øåíèÿ dcraw</a> è 
+        <a  href="#todo">ïëàí ðàáîò</a>).
+      </li>
+      <li>Ïî ìåðå ñîâåðøåíñòâîâàíèÿ dcraw (ïîääåðæêà íîâûõ êàìåð, èñïðàâëåíèå îøèáîê, óëó÷øåíèå àëãîðèòìîâ) -
+        èìïîðòèðîâàòü óëó÷øåíèÿ èç dcraw â LibRaw.
+      </li>
+      <li>Èçìåíåíèÿ API: <a href="#todo">çàïëàíèðîâàííûå óëó÷øåíèÿ</a> <b>ïîòðåáóþò</b> ðàñøèðåíèÿ API. Òàêèå
+        èçìåíåíèÿ áóäóò äåëàòüñÿ áîëüøèìè change-set-àìè, à ðåæèìû ñîâìåñòìîñòè ñî ñòàðûìè ïðèëîæåíèÿìè
+        áóäóò ñîõðàíÿòüñÿ, íàñêîëüêî âîçìîæíî.
+      </li>
+      </ol>
+
+    <a name="better"></a>
+    <h2>Ïðîèçâåäåííûå óëó÷øåíèÿ dcraw</h2>
+    <p>Íà ìîìåíò íàïèñàíèÿ äàííîãî òåêñòà â LibRaw âíåñåíû ñëåäóþùèå äîïîëíèòåëüíûå óëó÷øåíèÿ îòíîñèòåëüíî èñõîäíîãî
+      êîäà dcraw:</p>
+      <ul>
+      <li>Ïîëíîñòüþ óáðàíû ãëîáàëüíûå ïåðåìåííûå (à ïðè ñáîðêå thread-safe âàðèàíòà - è ñòàòè÷åñêèå ïåðåìåííûå
+        ôóíêöèé). 
+      </li>
+      <li>Thread-safety. Ïðèìåð èñïîëüçîâàíèÿ â ìíîãîïîòî÷íîì ðåæèìå âêëþ÷åí â ïîñòàâêó áèáëèîòåêè.
+      </li>
+      <li>Èçâëåêàåìûå èç RAW-ôàéëà äàííûå íåñêîëüêî ñòðóêòóðèðîâàíû: ãåîìåòðèÿ îòäåëüíî, öâåòîâûå äàííûå îòäåëüíî. 
+        <i>Ýòà ðàáîòà åùå íå çàêîí÷åíà è áóäåò ïðîäîëæåíà îäíîâðåìåííî ñ <a href="#todo">ðàáîòîé íàä óëó÷øåíèåì
+            îáðàáîòêè EXIF</a></i>.
+      </li> 
+      <li>Èçâëå÷åíèå RAW-äàííûõ è thumbnail ìîæåò áûòü ñäåëàíî çà 2-3 âûçîâà API ñ î÷åíü ïðîñòûì ïðîãðàììíûì
+        èíòåðôåéñîì.
+      </li> 
+      <li>Ðàáîòà ñ öâåòîâîé èíôîðìàöèåé: äëÿ öâåòîâûõ äàííûõ (êîýôôèöèåíòû áàëàíñà áåëîãî, òîíîâàÿ êðèâàÿ è ò.ä.)
+        äîáàâëåíû ôëàãè, ïîêàçûâàþùèå îòêóäà ýòà èíôîðìàöèÿ: èçâëå÷åíà èç RAW-äàííûõ, âû÷èñëåíà ïî ñàìîìó èçîáðàæåíèþ,
+        âçÿòû êîíñòàíòû èç êîäà.
+      </li>
+      <li>Èçâëåêàåòñÿ ICC-ïðîôèëü (äëÿ òåõ RAW-ôàéëîâ, ãäå îí åñòü)</li>
+      <li>Ñàìî èçîáðàæåíèå è thumbnail ìîæíî èçâëå÷ü ïîñëåäîâàòåëüíûìè âûçîâàìè, áåç ïåðåîòêðûòèÿ ôàéëà è ïåðåçàïóñêà
+        áèáëèîòåêè. 
+      </li>
+      <li>Íåñêîëüêî ñíèæåíû òðåáîâàíèÿ ê íåîáõîäèìîìó êîëè÷åñòâó îïåðàòèâíîé ïàìÿòè</li>
+      <li>Ðàáîòà ñ ìàñêèðîâàííûìè ïèêñåëÿìè è óðîâíåì ÷åðíîãî</b>: âîçìîæíî îòêëþ÷èòü îáÿçàòåëüíîå âû÷èòàíèå óðîâíÿ
+        ÷åðíîãî è ôèëüòðàöèþ íóëåâûõ ïèêñåëîâ</li>
+    </ul>
+
+    <a name="todo"></a>
+    <h2>Ïëàíèðóåìûå óëó÷øåíèÿ</h2>
+    <p>Êîä dcraw íóæäàåòñÿ â ñóùåñòâåííûõ èçìåíåíèÿõ è äîïîëíåíèÿõ:</p>
+    <ul>
+      <li><b>Âûäà÷à ðàñïàêîâàííûõ äàííûõ â ðàçëè÷íûõ memory layouts</b>: â çàâèñèìîñòè îò ïîòðåáíîñòåé âûçûâàþùåé
+        ïðîãðàììû, ðåçóëüòàòû ðàñïàêîâêè RAW áóäóò âûäàâàòüñÿ â îäíîì èç âàðèàíòîâ, âûáèðàåìîì íà runtime:
+        <ul>
+          <li>4-êîìïîíåíòíûå ïèêñåëè (âíóòðåííèé ôîðìàò äàííûõ  dcraw)</li>
+          <li>áàéåðîâñêèé ôîðìàò: äâóìåðíûé ìàññèâ, êàæäûé ýëåìåíò êîòîðîãî ñîîòâåòñòâóåò ïèêñåëþ ìàòðèöû</li>
+          <li>4 äâóìåðíûõ ìàññèâà (ïî îäíîìó íà êàæäûé êîìïîíåíò)</li>
+          </ul>
+        </li>
+      <li><b>Îäíîïðîõîäíàÿ ðàñïàêîâêà RAW-ôàéëîâ ñ íåñêîëüêèìè âàðèàíòàìè èçîáðàæåíèÿ</b>: äëÿ òåõ êàìåð, äëÿ êîòîðûõ
+        ýòî ïðèìåíèìî (êàìåðû FUJI, êàìåðû ñ ðåæèìàìè 4-shot/16-shot) áóäóò èçâëåêàòüñÿ íåñêîëüêî ïëàíîâ îäíîãî
+        èçîáðàæåíèÿ.
+        </li>
+      <li><b>Ðàáîòà ñ êðàÿìè äèàïàçîíà çíà÷åíèé</b>: ìèíèìàëüíûìè çíà÷åíèÿìè (÷àñòî íàçûâàåìûìè òî÷êîé ÷åðíîãî) è
+        ìàêñèìàëüíûìè çíà÷åíèÿìè (òî÷êîé íàñûùåíèÿ).
+        <ul>
+          <li>Âû÷èòàíèå òî÷êè ÷åðíîãî óæå ñäåëàíî íåîáÿçàòåëüíûì.  ñëåäóþùèå âåðñèè LibRaw áóäåò âêëþ÷åí êîä,
+            âûïîëíÿþùèé âû÷èñëåíèå óðîâíÿ ÷åðíîãî ñïåöèôè÷åñêèì äëÿ êîíêðåòíîé êàìåðû ñïîñîáîì.
+          </li>
+          <li>Ìàêñèìàëüíûå çíà÷åíèÿ òàê æå ìîãóò áûòü ðàçíûìè ïî êàíàëàì, ñîîòâåòñòâåííî ýòè çíà÷åíèÿ íàäëåæèò
+            ðàññ÷èòûâàòü íà ýòàïå ðàñïàêîâêè RAW-äàííûõ è âûäàâàòü â ðàìêàõ API. Âû÷èñëåíèå ìàêñèìàëüíûõ çíà÷åíèé äëÿ
+            êîíêðåòíîãî ýêçåìïëÿðà êàìåðû ïðè êîíêðåòíîé ÷óâñòâèòåëüíîñòè (êàëèáðîâêà êîíâåðòîðà) - çàäà÷à ïðèëîæåíèÿ,
+            âûçûâàþùåãî LibRaw.
+          </li>
+        </ul>
+      </li>
+      <li><b>Ðàáîòà ñ ÷åðíîé ðàìêîé</b>: äàííûå, ñ÷èòàííûå ñ ÷åðíîé ðàìêè (èëè äâóõ ÷åðíûõ ðàìîê, íà òåõ êàìåðàõ, ãäå
+        èõ äâå) íóæíî äåëàòü äîñòóïíûìè â âûçûâàþùåì ïðèëîæåíèè (íàïðèìåð, ýòî íåîáõîäèìî äëÿ ïîäàâëåíèÿ
+        îïðåäåë¸ííûõ àðòåôàêòîâ, â ÷àñòíîñòè - banding).</li>
+
+      <li><b>Âåðèôèêàöèÿ ðàñïàêîâêè äàííûõ äëÿ ìàêñèìàëüíîãî íàáîðà ôîðìàòîâ ôàéëîâ</b>. Ñóùåñòâóåò ìíåíèå, ÷òî
+        íåêîòîðûå ôîðìàòû äàííûõ dcraw ðàñïàêîâûâàåò íå âïîëíå êîððåêòíî.
+      </li>
+
+      <li><b>Ðàáîòà ñ EXIF/Makernote</b>: èçâëå÷åíèå äàííûõ â áîëüøåì îáúåìå, â ÷àñòíîñòè:
+        <ul>
+          <li>Èçâëå÷åíèå ìàêñèìàëüíî âîçìîæíîãî êîëè÷åñòâà äàííûõ î öâåòå (íàñòðîéêè áàëàíñà áåëîãî, ïðîôèëü, òîíîâàÿ 
+            êðèâàÿ, íàñòðîéêè êîíòðàñòà è ò.ï.)</li>
+
+          <li>Ãåíåðàëèçàöèÿ äàííûõ î öâåòå: ïðèâåäåíèå öâåòîâûõ äàííûõ îò ðàçëè÷íûõ êàìåð ê "îáùåìó çíàìåíàòåëþ" ñ
+            öåëüþ óïðîñòèòü îáðàáîòêó öâåòà (áåç ïîòåðè êà÷åñòâà îáðàáîòêè).</li>
+
+          <li>Èçâëå÷åíèå äàííûõ î êàìåðå (âåðñèÿ firmware, ñåðèéíûé íîìåð)</li>
+
+          <li>Èçâëå÷åíèå äàííûõ î êàäðå (îïòèêà, äèñòàíöèÿ ôîêóñèðîâêè, ôîêóñèðîâî÷íûå òî÷êè è èõ êîîðäèíàòû è
+            ò.ï.)</li>
+
+          <li>Èçâëå÷åíèå ïîëíîãî ìàññèâà EXIF-äàííûõ áåç àíàëèçà ñòðóêòóðû ñ öåëüþ îáëåã÷åíèÿ êîïèðîâàíèÿ EXIF-äàííûõ
+            â âûõîäíûå ôàéëû.</li>
+        </ul>
+      </li>
+      <li>Ãåíåðàëèçàöèÿ ðàáîòû ñî ñëîæíûìè ôîðìàòàìè, â ÷àñòíîñòè:
+        <ul>
+          <li>RAW-ôàéëû îò êàìåð Fuji (ñ äâóìÿ íàáîðàìè ñåíñîðîâ)</li>
+          <li>RAW-ôàéëû îò çàäíèêîâ ñ ðåæèìàìè 4-shot è 16-shot</li>
+        </ul>
+      </li>
+      <li>Òåõíîëîãè÷åñêèå óëó÷øåíèÿ, â ÷àñòíîñòè:
+        <ul>
+          <li>Èçâëå÷åíèå ICC-ïðîôèëÿ (äëÿ òåõ RAW-ôàéëîâ, ãäå îí èìååòñÿ).</li>
+          <li>Óìåíüøåíèå îáúåìîâ àëëîöèðóåìîé ïàìÿòè â òåõ ñëó÷àÿõ, êîãäà ïîñòîáðàáîòêà íå áóäåò âåñòèñü â òîì æå
+            áóôåðå, êóäà áûëè ïðî÷èòàíû RAW-äàííûå.</li>
+        </ul>
+      </li>
+    </ul>
+    <p>Â òî æå âðåìÿ, íèêàêèõ ìîäèôèêàöèé è ðàñøèðåíèé êîäà îáðàáîòêè äàííûõ dcraw (äå-áàéåðèçàöèÿ, öâåòîâûå
+      ïðåîáðàçîâàíèÿ è òàê äàëåå) ìû ïðîèçâîäèòü íå ïëàíèðóåì, ýòî âñå äîëæíî áûòü çàäà÷åé âûçûâàþùåãî
+      ïðèëîæåíèÿ. Ñòàíäàðòíûå ðåæèìû îáðàáîòêè, âêëþ÷åííûå â dcraw (çà èñêëþ÷åíèåì ïîääåðæêè LCMS è libjpeg è
+      íåêîòîðûõ íåñóùåñòâåííûõ ýòàïîâ îáðàáîòêè) áóäóò ñîõðàíåíû íåîïðåäåëåííîå âðåìÿ (â íàáîðå âûçîâîâ API,
+      ýìóëèðóþùèõ dcraw). 
+    </p>
+
+    <a href=index-rus.html>[âåðíóòüñÿ ê îãëàâëåíèþ]</a>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sun Mar 16 09:12:42 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:50 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/corner-scheme.png b/libfspotraw/LibRaw/doc/corner-scheme.png
new file mode 100644
index 0000000..573a2db
Binary files /dev/null and b/libfspotraw/LibRaw/doc/corner-scheme.png differ
diff --git a/libfspotraw/LibRaw/doc/index-eng.html b/libfspotraw/LibRaw/doc/index-eng.html
new file mode 100644
index 0000000..2feec30
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/index-eng.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw: better dcraw (library)</title>
+  </head>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+  <body>
+    <h1>LibRaw: A Better dcraw</h1>
+
+    <p>LibRaw is a library for reading RAW files from digital photo cameras (CRW/CR2, NEF, RAF, DNG, MOS, KDC, DCR, etc.;
+virtually all RAW formats are supported). It pays special attention to correct retrieval of data required for
+subsequent RAW conversion.</p>
+    <p>The library is intended for embedding in RAW converters, data analyzers, and other programs
+using RAW files as the initial data.</p>
+
+    <p>
+      Contents
+    </p>
+    <ol>
+      <li><a href="#copyright">Copyright</a> <!-- + -->
+      <li><a href="#ack">Acknowledgments</a> <!-- + -->
+      <li><a href="Why-LibRaw-eng.html">Purpose and Objectives</a> <!-- + -->
+      <li><a href="API-overview-eng.html">Overview of LibRaw API (C++)</a><!-- + -->
+      <li><a href="Install-LibRaw-eng.html">Compilation and Installation</a><!-- + -->
+      <li><a href="API-datastruct-eng.html">Data Structures, Error Codes, and Constants</a>
+      <li><a href="API-CXX-eng.html">C++ API</a>
+      <li><a href="API-C-eng.html">C API</a><!-- + -->
+      <li><a href="API-notes-eng.html">Notes on API (error code conventions, memory usage)</a><!-- + -->
+      <li><a href="Samples-LibRaw-eng.html">Examples</a>
+    </ol>
+    <a name="copyright"></a>
+    <h2>Copyright</h2>
+    <p>
+      LibRaw library, Copyright (C) 2008-2009 LibRaw LLC (info libraw org)<br/>
+      The library includes source code from<br/>
+      <i>dcraw.c, Dave Coffin's raw photo decoder<br/>
+        Copyright 1997-2008 by Dave Coffin, dcoffin a cybercom o net<br/>
+      </i>
+    </p>
+    <p>
+      LibRaw is distributed for free under <a href=http://www.gnu.org/licenses/gpl-2.0.html>GNU General Public
+        License</a> ver. 2 or any later version. Thus, you may use LibRaw within any software distributed under the terms of 
+GNU GPL. If you want to use LibRaw within some software program with other terms of distribution,
+either freeware or commercial, please contact the <a href="mailto:info libraw org">authors</a> and receive a license
+for your product (this is free of charge). 
+    </p>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sat Mar 15 15:01:26 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:50 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/index-rus.html b/libfspotraw/LibRaw/doc/index-rus.html
new file mode 100644
index 0000000..7112f38
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/index-rus.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw: better dcraw (library)</title>
+  </head>
+  <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+  <body>
+    <h1>LibRaw: better dcraw</h1>
+
+    <p>LibRaw: áèáëèîòåêà äëÿ ÷òåíèÿ RAW-ôàéëîâ öèôðîâûõ ôîòîêàìåð (CRW/CR2,NEF,RAF,DNG,MOS,KDC,DCR è òàê äàëåå,
+      ïîääåðæèâàþòñÿ ïðàêòè÷åñêè âñå RAW-ôîðìàòû). Îñíîâíîå âíèìàíèå óäåëåíî êîððåêòíîìó èçâëå÷åíèþ äàííûõ,
+      íåîáõîäèìûõ äëÿ äàëüíåéøåãî ïðåîáðàçîâàíèÿ RAW.</p>
+    <p>Áèáëèîòåêà ïðåäíàçíà÷åíà äëÿ âñòðàèâàíèÿ â RAW-êîíâåðòîðû, àíàëèçàòîðû äàííûõ è ïðî÷èå ïðîãðàììû, èñïîëüçóþùèå
+      RAW-ôàéëû â êà÷åñòâå âõîäíûõ äàííûõ.</p>
+
+    <p>
+      Îãëàâëåíèå
+    </p>
+    <ol>
+      <li><a href="#copyright">Copyright</a> <!-- + -->
+      <li><a href="#ack">Áëàãîäàðíîñòè</a> <!-- + -->
+      <li><a href="Why-LibRaw-rus.html">Öåëè è çàäà÷è ïðîåêòà</a> <!-- + -->
+      <li><a href="API-overview-rus.html">Îáçîð LibRaw API (C++)</a><!-- + -->
+      <li><a href="Install-LibRaw-rus.html">Êîìïèëÿöèÿ è óñòàíîâêà</a><!-- + -->
+      <li><a href="API-datastruct-rus.html">Ñòðóêòóðû äàííûõ, êîäû îøèáîê è êîíñòàíòû</a>
+      <li><a href="API-CXX-rus.html">C++ API</a>
+      <li><a href="API-C-rus.html">C API</a><!-- + -->
+      <li><a href="API-notes-rus.html">Ïîÿñíåíèÿ ê  API (ñîãëàøåíèÿ î
+          êîäàõ îøèáîê, èñïîëüçîâàíèå ïàìÿòè)</a><!-- + -->
+      <li><a href="Samples-LibRaw-rus.html">Ïðèìåðû èñïîëüçîâàíèÿ</a>
+    </ol>
+    <a name="copyright"></a>
+    <h2>Copyright</h2>
+    <p>
+      Áèáëèîòåêà LibRaw Copyright (C) 2008-2009 LibRaw LLC (info libraw org)<br/>
+      Áèáëèîòåêà âêëþ÷àåò â ñåáÿ êîä èç<br/>
+      <i>dcraw.c -- Dave Coffin's raw photo decoder<br/>
+        Copyright 1997-2008 by Dave Coffin, dcoffin a cybercom o net<br/>
+      </i>
+    </p>
+    <p>
+      LibRaw ñâîáîäíî ðàñïðîñòðàíÿåòñÿ íà óñëîâèÿõ <a href=http://www.gnu.org/licenses/gpl-2.0.htmll>GNU General Public
+        License</a>  âåðñèè 2 èëè áîëåå ïîçäíåé. Òàêèì îáðàçîì, âû ìîæåòå èñïîëüçîâàòü LibRaw â ñîñòàâå ëþáîé
+      ïðîãðàììû, ðàñïðîñòðàíÿåìîé íà óñëîâèÿõ GNU GPL.
+      Åñëè âû õîòèòå èñïîëüçîâàòü LibRaw â ñîñòàâå ïðîãðàììû, ðàñïðîñòðàíÿåìîé íà äðóãèõ óñëîâèÿõ, áåñïëàòíî èëè çà
+      äåíüãè, ñâÿæèòåñü ñ <a href="mailto:info libraw su">àâòîðàìè</a> è ïîëó÷èòå ëèöåíçèþ äëÿ âàøåãî ïðîäóêòà (ýòî
+      áåñïëàòíî). 
+    </p>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Sat Mar 15 15:01:26 MSK 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:49 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/doc/index.html b/libfspotraw/LibRaw/doc/index.html
new file mode 100644
index 0000000..5091790
--- /dev/null
+++ b/libfspotraw/LibRaw/doc/index.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>LibRaw Documentation</title>
+  </head>
+
+  <body>
+    <h1>LibRaw Documentation</h1>
+    <ul>
+      <li><a href=index-rus.html>Russian version/Ðóññêàÿ âåðñèÿ</a> (cp1251 encoding)</li>
+      <li><a href=index-eng.html>English version/Àíãëèéñêàÿ âåðñèÿ</a></li>
+    </ul>
+    <hr>
+    <address><a href="mailto:info libraw org">LibRaw Team</a></address>
+<!-- Created: Mon Apr 21 13:03:04 MSD 2008 -->
+<!-- hhmts start -->
+Last modified: Mon May  4 22:11:48 MSD 2009
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/libfspotraw/LibRaw/internal/dcraw_common.cpp b/libfspotraw/LibRaw/internal/dcraw_common.cpp
new file mode 100644
index 0000000..db4e58c
--- /dev/null
+++ b/libfspotraw/LibRaw/internal/dcraw_common.cpp
@@ -0,0 +1,8383 @@
+/* 
+   GENERATED FILE, DO NOT EDIT
+   Generated from dcraw/dcraw.c at Mon Jun  8 13:24:08 2009
+   Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
+   for copyright information.
+*/
+
+#define CLASS LibRaw::
+#include "libraw/libraw_types.h"
+#define LIBRAW_LIBRARY_BUILD
+#define LIBRAW_IO_REDEFINED
+#include "libraw/libraw.h"
+#include "internal/defines.h"
+#include "internal/var_defines.h"
+
+
+#ifndef __GLIBC__
+char *my_memmem (char *haystack, size_t haystacklen,
+	      char *needle, size_t needlelen)
+{
+  char *c;
+  for (c = haystack; c <= haystack + haystacklen - needlelen; c++)
+    if (!memcmp (c, needle, needlelen))
+      return c;
+  return 0;
+}
+#define memmem my_memmem
+#endif
+
+
+ushort CLASS sget2 (uchar *s)
+{
+  if (order == 0x4949)		/* "II" means little-endian */
+    return s[0] | s[1] << 8;
+  else				/* "MM" means big-endian */
+    return s[0] << 8 | s[1];
+}
+
+ushort CLASS get2()
+{
+  uchar str[2] = { 0xff,0xff };
+  fread (str, 1, 2, ifp);
+  return sget2(str);
+}
+
+unsigned CLASS sget4 (uchar *s)
+{
+  if (order == 0x4949)
+    return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
+  else
+    return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
+}
+#define sget4(s) sget4((uchar *)s)
+
+unsigned CLASS get4()
+{
+  uchar str[4] = { 0xff,0xff,0xff,0xff };
+  fread (str, 1, 4, ifp);
+  return sget4(str);
+}
+
+unsigned CLASS getint (int type)
+{
+  return type == 3 ? get2() : get4();
+}
+
+float CLASS int_to_float (int i)
+{
+  union { int i; float f; } u;
+  u.i = i;
+  return u.f;
+}
+
+double CLASS getreal (int type)
+{
+  union { char c[8]; double d; } u;
+  int i, rev;
+
+  switch (type) {
+    case 3: return (unsigned short) get2();
+    case 4: return (unsigned int) get4();
+    case 5:  u.d = (unsigned int) get4();
+      return u.d / (unsigned int) get4();
+    case 8: return (signed short) get2();
+    case 9: return (signed int) get4();
+    case 10: u.d = (signed int) get4();
+      return u.d / (signed int) get4();
+    case 11: return int_to_float (get4());
+    case 12:
+      rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234));
+      for (i=0; i < 8; i++)
+	u.c[i ^ rev] = fgetc(ifp);
+      return u.d;
+    default: return fgetc(ifp);
+  }
+}
+
+void CLASS read_shorts (ushort *pixel, int count)
+{
+  if (fread (pixel, 2, count, ifp) < count) derror();
+  if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
+      swab ((char*)pixel, (char*)pixel, count*2);
+}
+void CLASS canon_black (double dark[2], int nblack)
+{
+  int c, diff, row, col;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  if(!( filtering_mode & LIBRAW_FILTERING_NOBLACKS) )
+      {
+#endif
+  if (!nblack || document_mode > 1) return;
+  FORC(2) dark[c] /= nblack >> 1;
+  if ((diff = dark[0] - dark[1]))
+    for (row=0; row < height; row++)
+      for (col=1; col < width; col+=2)
+	BAYER(row,col) += diff;
+#ifdef LIBRAW_LIBRARY_BUILD
+      }
+#endif
+  dark[1] += diff;
+  black = (dark[0] + dark[1] + 1) / 2;
+}
+
+void CLASS canon_600_fixed_wb (int temp)
+{
+  static const short mul[4][5] = {
+    {  667, 358,397,565,452 },
+    {  731, 390,367,499,517 },
+    { 1119, 396,348,448,537 },
+    { 1399, 485,431,508,688 } };
+  int lo, hi, i;
+  float frac=0;
+
+  for (lo=4; --lo; )
+    if (*mul[lo] <= temp) break;
+  for (hi=0; hi < 3; hi++)
+    if (*mul[hi] >= temp) break;
+  if (lo != hi)
+    frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]);
+  for (i=1; i < 5; i++)
+    pre_mul[i-1] = 1 / (frac * mul[hi][i] + (1-frac) * mul[lo][i]);
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+}
+
+/* Return values:  0 = white  1 = near white  2 = not white */
+int CLASS canon_600_color (int ratio[2], int mar)
+{
+  int clipped=0, target, miss;
+
+  if (flash_used) {
+    if (ratio[1] < -104)
+      { ratio[1] = -104; clipped = 1; }
+    if (ratio[1] >   12)
+      { ratio[1] =   12; clipped = 1; }
+  } else {
+    if (ratio[1] < -264 || ratio[1] > 461) return 2;
+    if (ratio[1] < -50)
+      { ratio[1] = -50; clipped = 1; }
+    if (ratio[1] > 307)
+      { ratio[1] = 307; clipped = 1; }
+  }
+  target = flash_used || ratio[1] < 197
+	? -38 - (398 * ratio[1] >> 10)
+	: -123 + (48 * ratio[1] >> 10);
+  if (target - mar <= ratio[0] &&
+      target + 20  >= ratio[0] && !clipped) return 0;
+  miss = target - ratio[0];
+  if (abs(miss) >= mar*4) return 2;
+  if (miss < -20) miss = -20;
+  if (miss > mar) miss = mar;
+  ratio[0] = target - miss;
+  return 1;
+}
+
+void CLASS canon_600_auto_wb()
+{
+  int mar, row, col, i, j, st, count[] = { 0,0 };
+  int test[8], total[2][8], ratio[2][2], stat[2];
+
+  memset (&total, 0, sizeof total);
+  i = canon_ev + 0.5;
+  if      (i < 10) mar = 150;
+  else if (i > 12) mar = 20;
+  else mar = 280 - 20 * i;
+  if (flash_used) mar = 80;
+  for (row=14; row < height-14; row+=4)
+    for (col=10; col < width; col+=2) {
+      for (i=0; i < 8; i++)
+	test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] =
+		    BAYER(row+(i >> 1),col+(i & 1));
+      for (i=0; i < 8; i++)
+	if (test[i] < 150 || test[i] > 1500) goto next;
+      for (i=0; i < 4; i++)
+	if (abs(test[i] - test[i+4]) > 50) goto next;
+      for (i=0; i < 2; i++) {
+	for (j=0; j < 4; j+=2)
+	  ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j];
+	stat[i] = canon_600_color (ratio[i], mar);
+      }
+      if ((st = stat[0] | stat[1]) > 1) goto next;
+      for (i=0; i < 2; i++)
+	if (stat[i])
+	  for (j=0; j < 2; j++)
+	    test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10;
+      for (i=0; i < 8; i++)
+	total[st][i] += test[i];
+      count[st]++;
+next: ;
+    }
+  if (count[0] | count[1]) {
+    st = count[0]*200 < count[1];
+    for (i=0; i < 4; i++)
+      pre_mul[i] = 1.0 / (total[st][i] + total[st][i+4]);
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+  }
+}
+
+void CLASS canon_600_coeff()
+{
+  static const short table[6][12] = {
+    { -190,702,-1878,2390,   1861,-1349,905,-393, -432,944,2617,-2105  },
+    { -1203,1715,-1136,1648, 1388,-876,267,245,  -1641,2153,3921,-3409 },
+    { -615,1127,-1563,2075,  1437,-925,509,3,     -756,1268,2519,-2007 },
+    { -190,702,-1886,2398,   2153,-1641,763,-251, -452,964,3040,-2528  },
+    { -190,702,-1878,2390,   1861,-1349,905,-393, -432,944,2617,-2105  },
+    { -807,1319,-1785,2297,  1388,-876,769,-257,  -230,742,2067,-1555  } };
+  int t=0, i, c;
+  float mc, yc;
+
+  mc = pre_mul[1] / pre_mul[2];
+  yc = pre_mul[3] / pre_mul[2];
+  if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1;
+  if (mc > 1.28 && mc <= 2) {
+    if  (yc < 0.8789) t=3;
+    else if (yc <= 2) t=4;
+  }
+  if (flash_used) t=5;
+  for (raw_color = i=0; i < 3; i++)
+    FORCC rgb_cam[i][c] = table[t][i*4 + c] / 1024.0;
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.rgb_cam_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+}
+
+void CLASS canon_600_load_raw()
+{
+  uchar  data[1120], *dp;
+  ushort pixel[896], *pix;
+  int irow, row, col, val;
+  static const short mul[4][2] =
+  { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
+
+  for (irow=row=0; irow < height; irow++) {
+    if (fread (data, 1, raw_width*5/4, ifp) < raw_width*5/4) derror();
+    for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) {
+      pix[0] = (dp[0] << 2) + (dp[1] >> 6    );
+      pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
+      pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
+      pix[3] = (dp[4] << 2) + (dp[1]      & 3);
+      pix[4] = (dp[5] << 2) + (dp[9]      & 3);
+      pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3);
+      pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
+      pix[7] = (dp[8] << 2) + (dp[9] >> 6    );
+    }
+    for (col=0; col < width; col++)
+      BAYER(row,col) = pixel[col];
+    for (col=width; col < raw_width; col++)
+        {
+            black += pixel[col];
+#ifdef LIBRAW_LIBRARY_BUILD
+            ushort *dfp = get_masked_pointer(row,col);
+            if(dfp) *dfp = pixel[col];
+#endif
+        }
+    if ((row+=2) > height) row = 1;
+  }
+  if (raw_width > width)
+    black = black / ((raw_width - width) * height) - 4;
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++) {
+#ifdef LIBRAW_LIBRARY_BUILD
+     if( filtering_mode & LIBRAW_FILTERING_NOBLACKS)  
+         val = BAYER(row,col);
+     else
+#endif
+      if ((val = BAYER(row,col) - black) < 0) val = 0;
+      val = val * mul[row & 3][col & 1] >> 9;
+      BAYER(row,col) = val;
+    }
+  canon_600_fixed_wb(1311);
+  canon_600_auto_wb();
+  canon_600_coeff();
+  maximum = (0x3ff - black) * 1109 >> 9;
+  black = 0;
+}
+
+void CLASS remove_zeroes()
+{
+  unsigned row, col, tot, n, r, c;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES,0,2);
+#endif
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      if (BAYER(row,col) == 0) {
+	tot = n = 0;
+	for (r = row-2; r <= row+2; r++)
+	  for (c = col-2; c <= col+2; c++)
+	    if (r < height && c < width &&
+		FC(r,c) == FC(row,col) && BAYER(r,c))
+	      tot += (n++,BAYER(r,c));
+	if (n) BAYER(row,col) = tot/n;
+      }
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES,1,2);
+#endif
+}
+
+int CLASS canon_s2is()
+{
+  unsigned row;
+
+  for (row=0; row < 100; row++) {
+    fseek (ifp, row*3340 + 3284, SEEK_SET);
+    if (getc(ifp) > 15) return 1;
+  }
+  return 0;
+}
+
+void CLASS canon_a5_load_raw()
+{
+  ushort data[2565], *dp, pixel;
+  int vbits=0, buf=0, row, col, bc=0;
+
+  order = 0x4949;
+  for (row=-top_margin; row < raw_height-top_margin; row++) {
+    read_shorts (dp=data, raw_width * 10 / 16);
+    for (col=-left_margin; col < raw_width-left_margin; col++) {
+      if ((vbits -= 10) < 0)
+	buf = (vbits += 16, (buf << 16) + *dp++);
+      pixel = buf >> vbits & 0x3ff;
+#ifdef LIBRAW_LIBRARY_BUILD
+          ushort *dfp = get_masked_pointer(row+top_margin,col+left_margin);
+          if(dfp) *dfp = pixel;
+#endif
+      if ((unsigned) row < height && (unsigned) col < width)
+	BAYER(row,col) = pixel;
+      else if (col > 1-left_margin && col != width)
+	black += (bc++,pixel);
+    }
+  }
+  if (bc) black /= bc;
+  maximum = 0x3ff;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  if(!(filtering_mode & LIBRAW_FILTERING_NOZEROES))
+#endif
+  if (raw_width > 1600) remove_zeroes();
+}
+
+/*
+   getbits(-1) initializes the buffer
+   getbits(n) where 0 <= n <= 25 returns an n-bit integer
+ */
+unsigned CLASS getbits (int nbits)
+{
+#ifdef LIBRAW_NOTHREADS
+  static unsigned bitbuf=0;
+  static int vbits=0, reset=0;
+#else
+#define bitbuf tls->getbits.bitbuf
+#define vbits  tls->getbits.vbits
+#define reset  tls->getbits.reset
+#endif
+  unsigned c;
+
+  if (nbits == -1)
+    return bitbuf = vbits = reset = 0;
+  if (nbits == 0 || reset) return 0;
+  while (vbits < nbits) {
+    if ((c = fgetc(ifp)) == EOF) derror();
+    if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) return 0;
+    bitbuf = (bitbuf << 8) + (uchar) c;
+    vbits += 8;
+  }
+  vbits -= nbits;
+  return bitbuf << (32-nbits-vbits) >> (32-nbits);
+#ifndef LIBRAW_NOTHREADS
+#undef bitbuf
+#undef vbits
+#undef reset
+#endif
+}
+
+void CLASS init_decoder()
+{
+  memset (first_decode, 0, sizeof first_decode);
+  free_decode = first_decode;
+}
+
+/*
+   Construct a decode tree according to the specification in *source.
+   The first 16 bytes specify how many codes should be 1-bit, 2-bit
+   3-bit, etc.  Bytes after that are the leaf values.
+
+   For example, if the source is
+
+    { 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  },
+
+   then the code is
+
+	00		0x04
+	010		0x03
+	011		0x05
+	100		0x06
+	101		0x02
+	1100		0x07
+	1101		0x01
+	11100		0x08
+	11101		0x09
+	11110		0x00
+	111110		0x0a
+	1111110		0x0b
+	1111111		0xff
+ */
+uchar * CLASS make_decoder (const uchar *source, int level)
+{
+  struct decode *cur;
+#ifndef LIBRAW_NOTHREADS
+#define t_leaf tls->make_decoder_leaf
+#else
+  static int t_leaf;
+#endif
+  int i, next;
+
+  if (level==0) t_leaf=0;
+  cur = free_decode++;
+  if (free_decode > first_decode+2048) {
+#ifdef LIBRAW_LIBRARY_BUILD
+      throw LIBRAW_EXCEPTION_DECODE_RAW;
+#else
+    fprintf (stderr,_("%s: decoder table overflow\n"), ifname);
+    longjmp (failure, 2);
+#endif
+  }
+  for (i=next=0; i <= t_leaf && next < 16; )
+    i += source[next++];
+  if (i > t_leaf) {
+    if (level < next) {
+      cur->branch[0] = free_decode;
+      make_decoder (source, level+1);
+      cur->branch[1] = free_decode;
+      make_decoder (source, level+1);
+    } else
+      cur->leaf = source[16 + t_leaf++];
+  }
+  return (uchar *) source + 16 + t_leaf;
+#ifndef LIBRAW_NOTHREADS
+#undef t_leaf
+#endif
+}
+
+void CLASS crw_init_tables (unsigned table)
+{
+  static const uchar first_tree[3][29] = {
+    { 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  },
+  };
+  static const uchar second_tree[3][180] = {
+    { 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  }
+  };
+  if (table > 2) table = 2;
+  init_decoder();
+  make_decoder ( first_tree[table], 0);
+  second_decode = free_decode;
+  make_decoder (second_tree[table], 0);
+}
+
+/*
+   Return 0 if the image starts with compressed data,
+   1 if it starts with uncompressed low-order bits.
+
+   In Canon compressed data, 0xff is always followed by 0x00.
+ */
+int CLASS canon_has_lowbits()
+{
+  uchar test[0x4000];
+  int ret=1, i;
+
+  fseek (ifp, 0, SEEK_SET);
+  fread (test, 1, sizeof test, ifp);
+  for (i=540; i < sizeof test - 1; i++)
+    if (test[i] == 0xff) {
+      if (test[i+1]) return 1;
+      ret=0;
+    }
+  return ret;
+}
+
+void CLASS canon_compressed_load_raw()
+{
+  ushort *pixel, *prow;
+  int nblocks, lowbits, i, row, r, col, save, val, nblack=0;
+  unsigned irow, icol;
+  struct decode *decode, *dindex;
+  int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
+  double dark[2] = { 0,0 };
+  uchar c;
+
+  crw_init_tables (tiff_compress);
+  pixel = (ushort *) calloc (raw_width*8, sizeof *pixel);
+  merror (pixel, "canon_compressed_load_raw()");
+  lowbits = canon_has_lowbits();
+  if (!lowbits) maximum = 0x3ff;
+  fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET);
+  zero_after_ff = 1;
+  getbits(-1);
+  for (row=0; row < raw_height; row+=8) {
+    nblocks = MIN (8, raw_height-row) * raw_width >> 6;
+    for (block=0; block < nblocks; block++) {
+      memset (diffbuf, 0, sizeof diffbuf);
+      decode = first_decode;
+      for (i=0; i < 64; i++ ) {
+	for (dindex=decode; dindex->branch[0]; )
+	  dindex = dindex->branch[getbits(1)];
+	leaf = dindex->leaf;
+	decode = second_decode;
+	if (leaf == 0 && i) break;
+	if (leaf == 0xff) continue;
+	i  += leaf >> 4;
+	len = leaf & 15;
+	if (len == 0) continue;
+	diff = getbits(len);
+	if ((diff & (1 << (len-1))) == 0)
+	  diff -= (1 << len) - 1;
+	if (i < 64) diffbuf[i] = diff;
+      }
+      diffbuf[0] += carry;
+      carry = diffbuf[0];
+      for (i=0; i < 64; i++ ) {
+	if (pnum++ % raw_width == 0)
+	  base[0] = base[1] = 512;
+	if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10)
+	  derror();
+      }
+    }
+    if (lowbits) {
+      save = ftell(ifp);
+      fseek (ifp, 26 + row*raw_width/4, SEEK_SET);
+      for (prow=pixel, i=0; i < raw_width*2; i++) {
+	c = fgetc(ifp);
+	for (r=0; r < 8; r+=2, prow++) {
+	  val = (*prow << 2) + ((c >> r) & 3);
+	  if (raw_width == 2672 && val < 512) val += 2;
+	  *prow = val;
+	}
+      }
+      fseek (ifp, save, SEEK_SET);
+    }
+    for (r=0; r < 8; r++) {
+      irow = row - top_margin + r;
+#ifndef LIBRAW_LIBRARY_BUILD
+      if (irow >= height) continue;
+#endif
+      for (col=0; col < raw_width; col++) {
+#ifdef LIBRAW_LIBRARY_BUILD
+          ushort *dfp = get_masked_pointer(row+r,col);
+          if(dfp) *dfp = pixel[r*raw_width+col];
+          if (irow >= height) continue; // skip for top/bottom rows
+#endif
+	icol = col - left_margin;
+	if (icol < width)
+	  BAYER(irow,icol) = pixel[r*raw_width+col];
+	else if (col > 1 && (unsigned) (col-left_margin+2) > width+3)
+	  dark[icol & 1] += (nblack++,pixel[r*raw_width+col]);
+      }
+    }
+  }
+  free (pixel);
+  canon_black (dark, nblack);
+}
+
+int CLASS ljpeg_start (struct jhead *jh, int info_only)
+{
+  int c, tag, len;
+  uchar data[0x10000], *dp;
+
+  if (!info_only) init_decoder();
+  memset (jh, 0, sizeof *jh);
+  FORC(6) jh->huff[c] = free_decode;
+  jh->restart = INT_MAX;
+  fread (data, 2, 1, ifp);
+  if (data[1] != 0xd8) return 0;
+  do {
+    fread (data, 2, 2, ifp);
+    tag =  data[0] << 8 | data[1];
+    len = (data[2] << 8 | data[3]) - 2;
+    if (tag <= 0xff00) return 0;
+    fread (data, 1, len, ifp);
+    switch (tag) {
+      case 0xffc3:
+	jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
+      case 0xffc0:
+	jh->bits = data[0];
+	jh->high = data[1] << 8 | data[2];
+	jh->wide = data[3] << 8 | data[4];
+	jh->clrs = data[5] + jh->sraw;
+	if (len == 9 && !dng_version) getc(ifp);
+	break;
+      case 0xffc4:
+	if (info_only) break;
+	for (dp = data; dp < data+len && *dp < 4; ) {
+	  jh->huff[*dp] = free_decode;
+	  dp = make_decoder (++dp, 0);
+	}
+	break;
+      case 0xffda:
+	jh->psv = data[1+data[0]*2];
+	jh->bits -= data[3+data[0]*2] & 15;
+	break;
+      case 0xffdd:
+	jh->restart = data[0] << 8 | data[1];
+    }
+  } while (tag != 0xffda);
+  if (info_only) return 1;
+  if (jh->sraw) {
+    FORC(4)        jh->huff[2+c] = jh->huff[1];
+    FORC(jh->sraw) jh->huff[1+c] = jh->huff[0];
+  }
+  jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4);
+  merror (jh->row, "ljpeg_start()");
+  return zero_after_ff = 1;
+}
+
+int CLASS ljpeg_diff (struct decode *dindex)
+{
+  int len, diff;
+
+  while (dindex->branch[0])
+    dindex = dindex->branch[getbits(1)];
+  len = dindex->leaf;
+  if (len == 16 && (!dng_version || dng_version >= 0x1010000))
+    return -32768;
+  diff = getbits(len);
+  if ((diff & (1 << (len-1))) == 0)
+    diff -= (1 << len) - 1;
+  return diff;
+}
+
+ushort * CLASS ljpeg_row (int jrow, struct jhead *jh)
+{
+  int col, c, diff, pred, spred=0;
+  ushort mark=0, *row[3];
+
+  if (jrow * jh->wide % jh->restart == 0) {
+    FORC(6) jh->vpred[c] = 1 << (jh->bits-1);
+    if (jrow)
+      do mark = (mark << 8) + (c = fgetc(ifp));
+      while (c != EOF && mark >> 4 != 0xffd);
+    getbits(-1);
+  }
+  FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
+  for (col=0; col < jh->wide; col++)
+    FORC(jh->clrs) {
+      diff = ljpeg_diff (jh->huff[c]);
+      if (jh->sraw && c <= jh->sraw && (col | c))
+		    pred = spred;
+      else if (col) pred = row[0][-jh->clrs];
+      else	    pred = (jh->vpred[c] += diff) - diff;
+      if (jrow && col) switch (jh->psv) {
+	case 1:	break;
+	case 2: pred = row[1][0];					break;
+	case 3: pred = row[1][-jh->clrs];				break;
+	case 4: pred = pred +   row[1][0] - row[1][-jh->clrs];		break;
+	case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1);	break;
+	case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1);	break;
+	case 7: pred = (pred + row[1][0]) >> 1;				break;
+	default: pred = 0;
+      }
+      if ((**row = pred + diff) >> jh->bits) derror();
+      if (c <= jh->sraw) spred = **row;
+      row[0]++; row[1]++;
+    }
+  return row[2];
+}
+
+void CLASS lossless_jpeg_load_raw()
+{
+  int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0, nblack=0;
+  double dark[2] = { 0,0 };
+  struct jhead jh;
+  int min=INT_MAX;
+  ushort *rp;
+
+  if (!ljpeg_start (&jh, 0)) return;
+  jwide = jh.wide * jh.clrs;
+
+  for (jrow=0; jrow < jh.high; jrow++) {
+    rp = ljpeg_row (jrow, &jh);
+    for (jcol=0; jcol < jwide; jcol++) {
+      val = *rp++;
+      if (jh.bits <= 12)
+#ifdef LIBRAW_LIBRARY_BUILD
+          if( !(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+#endif
+	val = curve[val & 0xfff];
+      if (cr2_slice[0]) {
+	jidx = jrow*jwide + jcol;
+	i = jidx / (cr2_slice[1]*jh.high);
+	if ((j = i >= cr2_slice[0]))
+		 i  = cr2_slice[0];
+	jidx -= i * (cr2_slice[1]*jh.high);
+	row = jidx / cr2_slice[1+j];
+	col = jidx % cr2_slice[1+j] + i*cr2_slice[1];
+      }
+      if (raw_width == 3984 && (col -= 2) < 0)
+	col += (row--,raw_width);
+#ifdef LIBRAW_LIBRARY_BUILD
+      ushort *dfp = get_masked_pointer(row,col);
+      if(dfp) *dfp = val;
+#endif
+      if ((unsigned) (row-top_margin) < height) {
+	if ((unsigned) (col-left_margin) < width) {
+	  BAYER(row-top_margin,col-left_margin) = val;
+	  if (min > val) min = val;
+	} else if (col > 1 && (unsigned) (col-left_margin+2) > width+3)
+	  dark[(col-left_margin) & 1] += (nblack++,val);
+      }
+      if (++col >= raw_width)
+	col = (row++,0);
+    }
+  }
+  free (jh.row);
+  canon_black (dark, nblack);
+  if (!strcasecmp(make,"KODAK"))
+    black = min;
+}
+
+void CLASS canon_sraw_load_raw()
+{
+  struct jhead jh;
+  short *rp=0, (*ip)[4];
+  int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c;
+  int v[3]={0,0,0}, ver, hue;
+  char *cp;
+
+  if (!ljpeg_start (&jh, 0)) return;
+  jwide = (jh.wide >>= 1) * jh.clrs;
+
+  for (ecol=slice=0; slice <= cr2_slice[0]; slice++) {
+    scol = ecol;
+    ecol += cr2_slice[1] * 2 / jh.clrs;
+    if (!cr2_slice[0] || ecol > raw_width-1) ecol = raw_width & -2;
+    for (row=0; row < height; row += (jh.clrs >> 1) - 1) {
+      ip = (short (*)[4]) image + row*width;
+      for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) {
+	if ((jcol %= jwide) == 0)
+	  rp = (short *) ljpeg_row (jrow++, &jh);
+	if (col >= width) continue;
+	FORC (jh.clrs-2)
+	  ip[col + (c >> 1)*width + (c & 1)][0] = rp[jcol+c];
+	ip[col][1] = rp[jcol+jh.clrs-2] - 16384;
+	ip[col][2] = rp[jcol+jh.clrs-1] - 16384;
+      }
+    }
+  }
+  for (cp=model2; *cp && !isdigit(*cp); cp++);
+  sscanf (cp, "%d.%d.%d", v, v+1, v+2);
+  ver = (v[0]*1000 + v[1])*1000 + v[2];
+  hue = (jh.sraw+1) << 2;
+  if (unique_id == 0x80000218 && ver > 1000006 && ver < 3000000)
+    hue = jh.sraw << 1;
+  ip = (short (*)[4]) image;
+  rp = ip[0];
+  for (row=0; row < height; row++, ip+=width) {
+    if (row & (jh.sraw >> 1))
+      for (col=0; col < width; col+=2)
+	for (c=1; c < 3; c++)
+	  if (row == height-1)
+	       ip[col][c] =  ip[col-width][c];
+	  else ip[col][c] = (ip[col-width][c] + ip[col+width][c] + 1) >> 1;
+    for (col=1; col < width; col+=2)
+      for (c=1; c < 3; c++)
+	if (col == width-1)
+	     ip[col][c] =  ip[col-1][c];
+	else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
+  }
+  for ( ; rp < ip[0]; rp+=4) {
+    if (unique_id < 0x80000200) {
+      pix[0] = rp[0] + rp[2] - 512;
+      pix[2] = rp[0] + rp[1] - 512;
+      pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12) - 512;
+    } else {
+      rp[1] = (rp[1] << 2) + hue;
+      rp[2] = (rp[2] << 2) + hue;
+      pix[0] = rp[0] + ((  200*rp[1] + 22929*rp[2]) >> 14);
+      pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14);
+      pix[2] = rp[0] + ((29040*rp[1] -   101*rp[2]) >> 14);
+    }
+    FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
+  }
+  free (jh.row);
+  maximum = 0x3fff;
+}
+
+void CLASS adobe_copy_pixel (int row, int col, ushort **rp)
+{
+  unsigned r, c;
+
+  r = row -= top_margin;
+  c = col -= left_margin;
+  if (is_raw == 2 && shot_select) (*rp)++;
+  if (filters) {
+#ifndef LIBRAW_LIBRARY_BUILD
+    if (fuji_width) {
+      r = row + fuji_width - 1 - (col >> 1);
+      c = row + ((col+1) >> 1);
+    }
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+    ushort val = **rp;
+    if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+        val = **rp < 0x1000 ? curve[**rp] : **rp;
+    if (r < height && c < width)
+        BAYER(r,c) = val;
+    else
+        {
+            ushort *dfp = get_masked_pointer(row+top_margin,col+left_margin);
+            if(dfp) *dfp = val;
+        }
+#else
+    if (r < height && c < width)
+      BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp;
+#endif
+    *rp += is_raw;
+  } else {
+    if (r < height && c < width)
+      FORC(tiff_samples)
+	image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c];
+    *rp += tiff_samples;
+  }
+  if (is_raw == 2 && shot_select) (*rp)--;
+}
+
+void CLASS adobe_dng_load_raw_lj()
+{
+  unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col;
+  struct jhead jh;
+  ushort *rp;
+
+  while (trow < raw_height) {
+    save = ftell(ifp);
+    if (tile_length < INT_MAX)
+      fseek (ifp, get4(), SEEK_SET);
+    if (!ljpeg_start (&jh, 0)) break;
+    jwide = jh.wide;
+    if (filters) jwide *= jh.clrs;
+    jwide /= is_raw;
+    for (row=col=jrow=0; jrow < jh.high; jrow++) {
+      rp = ljpeg_row (jrow, &jh);
+      for (jcol=0; jcol < jwide; jcol++) {
+	adobe_copy_pixel (trow+row, tcol+col, &rp);
+	if (++col >= tile_width || col >= raw_width)
+	  row += 1 + (col = 0);
+      }
+    }
+    fseek (ifp, save+4, SEEK_SET);
+    if ((tcol += tile_width) >= raw_width)
+      trow += tile_length + (tcol = 0);
+    free (jh.row);
+  }
+}
+
+void CLASS adobe_dng_load_raw_nc()
+{
+  ushort *pixel, *rp;
+  int row, col;
+
+  pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel);
+  merror (pixel, "adobe_dng_load_raw_nc()");
+  for (row=0; row < raw_height; row++) {
+    if (tiff_bps == 16)
+      read_shorts (pixel, raw_width * tiff_samples);
+    else {
+      getbits(-1);
+      for (col=0; col < raw_width * tiff_samples; col++)
+	pixel[col] = getbits(tiff_bps);
+    }
+    for (rp=pixel, col=0; col < raw_width; col++)
+      adobe_copy_pixel (row, col, &rp);
+  }
+  free (pixel);
+}
+
+void CLASS pentax_tree()
+{
+  ushort bit[2][13];
+  struct decode *cur;
+  int c, i, j;
+
+  init_decoder();
+  FORC(13) bit[0][c] = get2();
+  FORC(13) bit[1][c] = fgetc(ifp) & 15;
+  FORC(13) {
+    cur = first_decode;
+    for (i=0; i < bit[1][c]; i++) {
+      j = bit[0][c] >> (11-i) & 1;
+      if (!cur->branch[j]) cur->branch[j] = ++free_decode;
+      cur = cur->branch[j];
+    }
+    cur->leaf = c;
+  }
+}
+
+void CLASS pentax_k10_load_raw()
+{
+  int row, col, diff;
+  ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2];
+
+  getbits(-1);
+  for (row=0; row < raw_height; row++)
+      {
+#ifndef LIBRAW_LIBRARY_BUILD
+          if(row >= height) break;
+#endif
+    for (col=0; col < raw_width; col++) {
+      diff = ljpeg_diff (first_decode);
+      if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+      else	   hpred[col & 1] += diff;
+      if (col < width && row < height)
+	BAYER(row,col) = hpred[col & 1];
+#ifdef LIBRAW_LIBRARY_BUILD
+      else
+        {
+          ushort *dfp = get_masked_pointer(row,col);
+          if(dfp) *dfp = hpred[col & 1];
+        }
+      
+      if (col < width && row < height)
+#endif
+        if (hpred[col & 1] >> 12) derror();
+    }
+      }
+}
+
+void CLASS nikon_compressed_load_raw()
+{
+  static const uchar nikon_tree[][32] = {
+    { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0,	/* 12-bit lossy */
+      5,4,3,6,2,7,1,0,8,9,11,10,12 },
+    { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0,	/* 12-bit lossy after split */
+      0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 },
+    { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,  /* 12-bit lossless */
+      5,4,6,3,7,2,8,1,9,0,10,11,12 },
+    { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0,	/* 14-bit lossy */
+      5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 },
+    { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0,	/* 14-bit lossy after split */
+      8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 },
+    { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0,	/* 14-bit lossless */
+      7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } };
+  struct decode *dindex;
+  ushort ver0, ver1, vpred[2][2], hpred[2], csize;
+  int i, min, max, step=0, huff=0, split=0, row, col, len, shl, diff;
+
+  fseek (ifp, meta_offset, SEEK_SET);
+  ver0 = fgetc(ifp);
+  ver1 = fgetc(ifp);
+  if (ver0 == 0x49 || ver1 == 0x58)
+    fseek (ifp, 2110, SEEK_CUR);
+  if (ver0 == 0x46) huff = 2;
+  if (tiff_bps == 14) huff += 3;
+  read_shorts (vpred[0], 4);
+  max = 1 << tiff_bps & 0x7fff;
+  if ((csize = get2()) > 1)
+    step = max / (csize-1);
+  if (ver0 == 0x44 && ver1 == 0x20 && step > 0) {
+    for (i=0; i < csize; i++)
+      curve[i*step] = get2();
+    for (i=0; i < max; i++)
+      curve[i] = ( curve[i-i%step]*(step-i%step) +
+		   curve[i-i%step+step]*(i%step) ) / step;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    fseek (ifp, meta_offset+562, SEEK_SET);
+    split = get2();
+  } else if (ver0 != 0x46 && csize <= 0x4001)
+      {
+    read_shorts (curve, max=csize);
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      }
+  while (curve[max-2] == curve[max-1]) max--;
+  init_decoder();
+  make_decoder (nikon_tree[huff], 0);
+  fseek (ifp, data_offset, SEEK_SET);
+  getbits(-1);
+  for (min=row=0; row < height; row++) {
+    if (split && row == split) {
+      init_decoder();
+      make_decoder (nikon_tree[huff+1], 0);
+      max += (min = 16) << 1;
+    }
+    for (col=0; col < raw_width; col++) {
+      for (dindex=first_decode; dindex->branch[0]; )
+	dindex = dindex->branch[getbits(1)];
+      len = dindex->leaf & 15;
+      shl = dindex->leaf >> 4;
+      diff = ((getbits(len-shl) << 1) + 1) << shl >> 1;
+      if ((diff & (1 << (len-1))) == 0)
+	diff -= (1 << len) - !shl;
+      if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+      else	   hpred[col & 1] += diff;
+      if ((ushort)(hpred[col & 1] + min) >= max) derror();
+#ifndef LIBRAW_LIBRARY_BUILD
+      if ((unsigned) (col-left_margin) < width)
+	BAYER(row,col-left_margin) =  curve[LIM((short)hpred[col & 1],0,0x3fff)];
+#else
+      ushort xval = hpred[col & 1];
+      if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+          xval = curve[LIM((short)xval,0,0x3fff)];
+      if ((unsigned) (col-left_margin) < width)
+          {
+              BAYER(row,col-left_margin) =  xval;
+          }
+      else
+        {
+          ushort *dfp = get_masked_pointer(row,col);
+          if(dfp) *dfp = xval;
+        }
+#endif
+
+    }
+  }
+}
+
+/*
+   Figure out if a NEF file is compressed.  These fancy heuristics
+   are only needed for the D100, thanks to a bug in some cameras
+   that tags all images as "compressed".
+ */
+int CLASS nikon_is_compressed()
+{
+  uchar test[256];
+  int i;
+
+  fseek (ifp, data_offset, SEEK_SET);
+  fread (test, 1, 256, ifp);
+  for (i=15; i < 256; i+=16)
+    if (test[i]) return 1;
+  return 0;
+}
+
+/*
+   Returns 1 for a Coolpix 995, 0 for anything else.
+ */
+int CLASS nikon_e995()
+{
+  int i, histo[256];
+  const uchar often[] = { 0x00, 0x55, 0xaa, 0xff };
+
+  memset (histo, 0, sizeof histo);
+  fseek (ifp, -2000, SEEK_END);
+  for (i=0; i < 2000; i++)
+    histo[fgetc(ifp)]++;
+  for (i=0; i < 4; i++)
+    if (histo[often[i]] < 200)
+      return 0;
+  return 1;
+}
+
+/*
+   Returns 1 for a Coolpix 2100, 0 for anything else.
+ */
+int CLASS nikon_e2100()
+{
+  uchar t[12];
+  int i;
+
+  fseek (ifp, 0, SEEK_SET);
+  for (i=0; i < 1024; i++) {
+    fread (t, 1, 12, ifp);
+    if (((t[2] & t[4] & t[7] & t[9]) >> 4
+	& t[1] & t[6] & t[8] & t[11] & 3) != 3)
+      return 0;
+  }
+  return 1;
+}
+
+void CLASS nikon_3700()
+{
+  int bits, i;
+  uchar dp[24];
+  static const struct {
+    int bits;
+    char t_make[12], t_model[15];
+  } table[] = {
+    { 0x00, "PENTAX",  "Optio 33WR" },
+    { 0x03, "NIKON",   "E3200" },
+    { 0x32, "NIKON",   "E3700" },
+    { 0x33, "OLYMPUS", "C740UZ" } };
+
+  fseek (ifp, 3072, SEEK_SET);
+  fread (dp, 1, 24, ifp);
+  bits = (dp[8] & 3) << 4 | (dp[20] & 3);
+  for (i=0; i < sizeof table / sizeof *table; i++)
+    if (bits == table[i].bits) {
+      strcpy (make,  table[i].t_make );
+      strcpy (model, table[i].t_model);
+    }
+}
+
+/*
+   Separates a Minolta DiMAGE Z2 from a Nikon E4300.
+ */
+int CLASS minolta_z2()
+{
+  int i, nz;
+  char tail[424];
+
+  fseek (ifp, -sizeof tail, SEEK_END);
+  fread (tail, 1, sizeof tail, ifp);
+  for (nz=i=0; i < sizeof tail; i++)
+    if (tail[i]) nz++;
+  return nz > 20;
+}
+
+/* Here raw_width is in bytes, not pixels. */
+void CLASS nikon_e900_load_raw()
+{
+  int offset=0, irow, row, col;
+
+  for (irow=0; irow < height; irow++) {
+    row = irow * 2 % height;
+    if (row == 1)
+      offset = - (-offset & -4096);
+    fseek (ifp, offset, SEEK_SET);
+    offset += raw_width;
+    getbits(-1);
+    for (col=0; col < width; col++)
+      BAYER(row,col) = getbits(10);
+  }
+}
+
+/*
+   The Fuji Super CCD is just a Bayer grid rotated 45 degrees.
+ */
+void CLASS fuji_load_raw()
+{
+  ushort *pixel;
+#ifndef LIBRAW_LIBRARY_BUILD
+  int wide, row, col, r, c;
+
+  fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+  wide = fuji_width << !fuji_layout;
+  pixel = (ushort *) calloc (wide, sizeof *pixel);
+  merror (pixel, "fuji_load_raw()");
+  for (row=0; row < raw_height; row++) {
+    read_shorts (pixel, wide);
+    fseek (ifp, 2*(raw_width - wide), SEEK_CUR);
+    for (col=0; col < wide; col++) {
+      if (fuji_layout) {
+	r = fuji_width - 1 - col + (row >> 1);
+	c = col + ((row+1) >> 1);
+      } else {
+	r = fuji_width - 1 + row - (col >> 1);
+	c = row + ((col+1) >> 1);
+      }
+      BAYER(r,c) = pixel[col];
+    }
+  }
+  free (pixel);
+#else
+  int row,col;
+  int wide, r, c;
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "fuji_load_raw()");
+  for (row=0; row < raw_height; row++) {
+    read_shorts (pixel, raw_width);
+    for (col=0; col < raw_width; col++) {
+        if(col >= left_margin && col < width+left_margin
+           && row >= top_margin && row < height+top_margin)
+            {
+                int rrow = row-top_margin;
+                int ccol = col-left_margin;
+                if (fuji_layout) {
+                    r = fuji_width - 1 - ccol + (rrow >> 1);
+                    c = ccol + ((rrow+1) >> 1);
+                } else {
+                    r = fuji_width - 1 + rrow - (ccol >> 1);
+                    c = rrow + ((ccol+1) >> 1);
+                }
+
+                image[((row-top_margin) >> shrink)*iwidth + ((col-left_margin) >> shrink)][FC(r,c)] = pixel[col];
+            }
+        else
+            {
+                ushort *dfp = get_masked_pointer(row,col);
+                if(dfp) *dfp = pixel[col];
+            }
+    }
+  }
+  free (pixel);
+#endif
+}
+void CLASS ppm_thumb()
+{
+  char *thumb;
+  thumb_length = thumb_width*thumb_height*3;
+  thumb = (char *) malloc (thumb_length);
+  merror (thumb, "ppm_thumb()");
+  fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+  fread  (thumb, 1, thumb_length, ifp);
+  fwrite (thumb, 1, thumb_length, ofp);
+  free (thumb);
+}
+
+void CLASS layer_thumb()
+{
+  int i, c;
+  char *thumb, map[][4] = { "012","102" };
+
+  colors = thumb_misc >> 5 & 7;
+  thumb_length = thumb_width*thumb_height;
+  thumb = (char *) calloc (colors, thumb_length);
+  merror (thumb, "layer_thumb()");
+  fprintf (ofp, "P%d\n%d %d\n255\n",
+	5 + (colors >> 1), thumb_width, thumb_height);
+  fread (thumb, thumb_length, colors, ifp);
+  for (i=0; i < thumb_length; i++)
+    FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], ofp);
+  free (thumb);
+}
+
+void CLASS rollei_thumb()
+{
+  unsigned i;
+  ushort *thumb;
+
+  thumb_length = thumb_width * thumb_height;
+  thumb = (ushort *) calloc (thumb_length, 2);
+  merror (thumb, "rollei_thumb()");
+  fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+  read_shorts (thumb, thumb_length);
+  for (i=0; i < thumb_length; i++) {
+    putc (thumb[i] << 3, ofp);
+    putc (thumb[i] >> 5  << 2, ofp);
+    putc (thumb[i] >> 11 << 3, ofp);
+  }
+  free (thumb);
+}
+
+void CLASS rollei_load_raw()
+{
+  uchar pixel[10];
+  unsigned iten=0, isix, i, buffer=0, row, col, todo[16];
+
+  isix = raw_width * raw_height * 5 / 8;
+  while (fread (pixel, 1, 10, ifp) == 10) {
+    for (i=0; i < 10; i+=2) {
+      todo[i]   = iten++;
+      todo[i+1] = pixel[i] << 8 | pixel[i+1];
+      buffer    = pixel[i] >> 2 | buffer << 6;
+    }
+    for (   ; i < 16; i+=2) {
+      todo[i]   = isix++;
+      todo[i+1] = buffer >> (14-i)*5;
+    }
+    for (i=0; i < 16; i+=2) {
+      row = todo[i] / raw_width - top_margin;
+      col = todo[i] % raw_width - left_margin;
+      if (row < height && col < width)
+	BAYER(row,col) = (todo[i+1] & 0x3ff);
+#ifdef LIBRAW_LIBRARY_BUILD
+      else
+          {
+              ushort *dfp = get_masked_pointer(todo[i] / raw_width,todo[i] % raw_width);
+              if(dfp) *dfp = (todo[i+1] & 0x3ff);
+          }
+#endif
+    }
+  }
+  maximum = 0x3ff;
+}
+
+int CLASS bayer (unsigned row, unsigned col)
+{
+  return (row < height && col < width) ? BAYER(row,col) : 0;
+}
+
+void CLASS phase_one_flat_field (int is_float, int nc)
+{
+  ushort head[8];
+  unsigned wide, y, x, c, rend, cend, row, col;
+  float *mrow, num, mult[4];
+
+  read_shorts (head, 8);
+  wide = head[2] / head[4];
+  mrow = (float *) calloc (nc*wide, sizeof *mrow);
+  merror (mrow, "phase_one_flat_field()");
+  for (y=0; y < head[3] / head[5]; y++) {
+    for (x=0; x < wide; x++)
+      for (c=0; c < nc; c+=2) {
+	num = is_float ? getreal(11) : get2()/32768.0;
+	if (y==0) mrow[c*wide+x] = num;
+	else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5];
+      }
+    if (y==0) continue;
+    rend = head[1]-top_margin + y*head[5];
+    for (row = rend-head[5]; row < height && row < rend; row++) {
+      for (x=1; x < wide; x++) {
+	for (c=0; c < nc; c+=2) {
+	  mult[c] = mrow[c*wide+x-1];
+	  mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4];
+	}
+	cend = head[0]-left_margin + x*head[4];
+	for (col = cend-head[4]; col < width && col < cend; col++) {
+	  c = nc > 2 ? FC(row,col) : 0;
+	  if (!(c & 1)) {
+	    c = BAYER(row,col) * mult[c];
+	    BAYER(row,col) = LIM(c,0,65535);
+	  }
+	  for (c=0; c < nc; c+=2)
+	    mult[c] += mult[c+1];
+	}
+      }
+      for (x=0; x < wide; x++)
+	for (c=0; c < nc; c+=2)
+	  mrow[c*wide+x] += mrow[(c+1)*wide+x];
+    }
+  }
+  free (mrow);
+}
+
+void CLASS phase_one_correct()
+{
+  unsigned entries, tag, data, save, col, row, type;
+  int len, i, j, k, cip, val[4], dev[4], sum, max;
+  int head[9], diff, mindiff=INT_MAX, off_412=0;
+  static const signed char dir[12][2] =
+    { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0},
+      {-2,-2}, {-2,2}, {2,-2}, {2,2} };
+  float poly[8], num, cfrac, frac, mult[2], *yval[2];
+  ushort *xval[2];
+
+  if (half_size || !meta_length) return;
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Phase One correction...\n"));
+#endif
+  fseek (ifp, meta_offset, SEEK_SET);
+  order = get2();
+  fseek (ifp, 6, SEEK_CUR);
+  fseek (ifp, meta_offset+get4(), SEEK_SET);
+  entries = get4();  get4();
+  while (entries--) {
+    tag  = get4();
+    len  = get4();
+    data = get4();
+    save = ftell(ifp);
+    fseek (ifp, meta_offset+data, SEEK_SET);
+    if (tag == 0x419) {				/* Polynomial curve */
+      for (get4(), i=0; i < 8; i++)
+	poly[i] = getreal(11);
+      poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1;
+      for (i=0; i < 0x10000; i++) {
+	num = (poly[5]*i + poly[3])*i + poly[1];
+	curve[i] = LIM(num,0,65535);
+      } goto apply;				/* apply to right half */
+    } else if (tag == 0x41a) {			/* Polynomial curve */
+      for (i=0; i < 4; i++)
+	poly[i] = getreal(11);
+      for (i=0; i < 0x10000; i++) {
+	for (num=0, j=4; j--; )
+	  num = num * i + poly[j];
+	curve[i] = LIM(num+i,0,65535);
+      } apply:					/* apply to whole image */
+      for (row=0; row < height; row++)
+	for (col = (tag & 1)*ph1.split_col; col < width; col++)
+	  BAYER(row,col) = curve[BAYER(row,col)];
+    } else if (tag == 0x400) {			/* Sensor defects */
+      while ((len -= 8) >= 0) {
+	col  = get2() - left_margin;
+	row  = get2() - top_margin;
+	type = get2(); get2();
+	if (col >= width) continue;
+	if (type == 131)			/* Bad column */
+	  for (row=0; row < height; row++)
+	    if (FC(row,col) == 1) {
+	      for (sum=i=0; i < 4; i++)
+		sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]);
+	      for (max=i=0; i < 4; i++) {
+		dev[i] = abs((val[i] << 2) - sum);
+		if (dev[max] < dev[i]) max = i;
+	      }
+	      BAYER(row,col) = (sum - val[max])/3.0 + 0.5;
+	    } else {
+	      for (sum=0, i=8; i < 12; i++)
+		sum += bayer (row+dir[i][0], col+dir[i][1]);
+	      BAYER(row,col) = 0.5 + sum * 0.0732233 +
+		(bayer(row,col-2) + bayer(row,col+2)) * 0.3535534;
+	    }
+	else if (type == 129) {			/* Bad pixel */
+	  if (row >= height) continue;
+	  j = (FC(row,col) != 1) * 4;
+	  for (sum=0, i=j; i < j+8; i++)
+	    sum += bayer (row+dir[i][0], col+dir[i][1]);
+	  BAYER(row,col) = (sum + 4) >> 3;
+	}
+      }
+    } else if (tag == 0x401) {			/* All-color flat fields */
+      phase_one_flat_field (1, 2);
+    } else if (tag == 0x416 || tag == 0x410) {
+      phase_one_flat_field (0, 2);
+    } else if (tag == 0x40b) {			/* Red+blue flat field */
+      phase_one_flat_field (0, 4);
+    } else if (tag == 0x412) {
+      fseek (ifp, 36, SEEK_CUR);
+      diff = abs (get2() - ph1.tag_21a);
+      if (mindiff > diff) {
+	mindiff = diff;
+	off_412 = ftell(ifp) - 38;
+      }
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  if (off_412) {
+    fseek (ifp, off_412, SEEK_SET);
+    for (i=0; i < 9; i++) head[i] = get4() & 0x7fff;
+    yval[0] = (float *) calloc (head[1]*head[3] + head[2]*head[4], 6);
+    merror (yval[0], "phase_one_correct()");
+    yval[1] = (float  *) (yval[0] + head[1]*head[3]);
+    xval[0] = (ushort *) (yval[1] + head[2]*head[4]);
+    xval[1] = (ushort *) (xval[0] + head[1]*head[3]);
+    get2();
+    for (i=0; i < 2; i++)
+      for (j=0; j < head[i+1]*head[i+3]; j++)
+	yval[i][j] = getreal(11);
+    for (i=0; i < 2; i++)
+      for (j=0; j < head[i+1]*head[i+3]; j++)
+	xval[i][j] = get2();
+    for (row=0; row < height; row++)
+      for (col=0; col < width; col++) {
+	cfrac = (float) col * head[3] / raw_width;
+	cfrac -= cip = cfrac;
+	num = BAYER(row,col) * 0.5;
+	for (i=cip; i < cip+2; i++) {
+	  for (k=j=0; j < head[1]; j++)
+	    if (num < xval[0][k = head[1]*i+j]) break;
+	  frac = (j == 0 || j == head[1]) ? 0 :
+		(xval[0][k] - num) / (xval[0][k] - xval[0][k-1]);
+	  mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac);
+	}
+	i = ((mult[0] * (1-cfrac) + mult[1] * cfrac)
+		* (row + top_margin) + num) * 2;
+	BAYER(row,col) = LIM(i,0,65535);
+      }
+    free (yval[0]);
+  }
+}
+
+void CLASS phase_one_load_raw()
+{
+  int row, col, a, b;
+  ushort *pixel, akey, bkey, mask;
+
+  fseek (ifp, ph1.key_off, SEEK_SET);
+  akey = get2();
+  bkey = get2();
+  mask = ph1.format == 1 ? 0x5555:0x1354;
+#ifndef LIBRAW_LIBRARY_BUILD
+  fseek (ifp, data_offset + top_margin*raw_width*2, SEEK_SET);
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "phase_one_load_raw()");
+  for (row=0; row < height; row++) {
+    read_shorts (pixel, raw_width);
+    for (col=0; col < raw_width; col+=2) {
+      a = pixel[col+0] ^ akey;
+      b = pixel[col+1] ^ bkey;
+      pixel[col+0] = (a & mask) | (b & ~mask);
+      pixel[col+1] = (b & mask) | (a & ~mask);
+    }
+    for (col=0; col < width; col++)
+      BAYER(row,col) = pixel[col+left_margin];
+  }
+  free (pixel);
+#else
+  fseek (ifp, data_offset, SEEK_SET);
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "phase_one_load_raw()");
+  for (row=0; row < raw_height; row++) {
+    read_shorts (pixel, raw_width);
+    for (col=0; col < raw_width; col+=2) {
+      a = pixel[col+0] ^ akey;
+      b = pixel[col+1] ^ bkey;
+      pixel[col+0] = (a & mask) | (b & ~mask);
+      pixel[col+1] = (b & mask) | (a & ~mask);
+    }
+    for (col=0; col < raw_width; col++)
+        {
+            ushort *dfp = get_masked_pointer(row,col);
+            if(dfp)
+                *dfp = pixel[col];
+            else
+                BAYER(row,col-left_margin) = pixel[col];
+        }
+  }
+  free (pixel);
+  if(!( filtering_mode & LIBRAW_FILTERING_NORAWCURVE) )
+#endif
+  phase_one_correct();
+}
+
+unsigned CLASS ph1_bits (int nbits)
+{
+#ifndef LIBRAW_NOTHREADS
+#define bitbuf tls->ph1_bits.bitbuf
+#define vbits  tls->ph1_bits.vbits    
+#else
+  static UINT64 bitbuf=0;
+  static int vbits=0;
+#endif
+  if (nbits == -1)
+    return bitbuf = vbits = 0;
+  if (nbits == 0) return 0;
+  if ((vbits -= nbits) < 0) {
+    bitbuf = bitbuf << 32 | get4();
+    vbits += 32;
+  }
+  return bitbuf << (64-nbits-vbits) >> (64-nbits);
+#ifndef LIBRAW_NOTHREADS
+#undef bitbuf
+#undef vbits
+#endif
+}
+
+void CLASS phase_one_load_raw_c()
+{
+  static const int length[] = { 8,7,6,9,11,10,5,12,14,13 };
+  int *offset, len[2], pred[2], row, col, i, j;
+  ushort *pixel;
+  short (*t_black)[2];
+
+  pixel = (ushort *) calloc (raw_width + raw_height*4, 2);
+  merror (pixel, "phase_one_load_raw_c()");
+  offset = (int *) (pixel + raw_width);
+  fseek (ifp, strip_offset, SEEK_SET);
+  for (row=0; row < raw_height; row++)
+    offset[row] = get4();
+  t_black = (short (*)[2]) offset + raw_height;
+  fseek (ifp, ph1.black_off, SEEK_SET);
+  if (ph1.black_off)
+      {
+    read_shorts ((ushort *) t_black[0], raw_height*2);
+#ifdef LIBRAW_LIBRARY_BUILD
+    imgdata.masked_pixels.ph1_black = (ushort (*)[2])calloc(raw_height*2,sizeof(ushort));
+    merror (imgdata.masked_pixels.ph1_black, "phase_one_load_raw_c()");
+    memmove(imgdata.masked_pixels.ph1_black,(ushort *) t_black[0],raw_height*2*sizeof(ushort));
+#endif
+      }
+  for (i=0; i < 256; i++)
+    curve[i] = i*i / 3.969 + 0.5;
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.curve_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+  for (row=0; row < raw_height; row++) {
+    fseek (ifp, data_offset + offset[row], SEEK_SET);
+    ph1_bits(-1);
+    pred[0] = pred[1] = 0;
+    for (col=0; col < raw_width; col++) {
+      if (col >= (raw_width & -8))
+	len[0] = len[1] = 14;
+      else if ((col & 7) == 0)
+	for (i=0; i < 2; i++) {
+	  for (j=0; j < 5 && !ph1_bits(1); j++);
+	  if (j--) len[i] = length[j*2 + ph1_bits(1)];
+	}
+      if ((i = len[col & 1]) == 14)
+	pixel[col] = pred[col & 1] = ph1_bits(16);
+      else
+	pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1));
+      if (pred[col & 1] >> 16) derror();
+#ifdef LIBRAW_LIBRARY_BUILD
+  if(!( filtering_mode & LIBRAW_FILTERING_NORAWCURVE) )
+#endif
+      if (ph1.format == 5 && pixel[col] < 256)
+	pixel[col] = curve[pixel[col]];
+    }
+    if ((unsigned) (row-top_margin) < height)
+#ifndef LIBRAW_LIBRARY_BUILD
+      for (col=0; col < width; col++) {
+	i = (pixel[col+left_margin] << 2)
+		- ph1.t_black + t_black[row][col >= ph1.split_col];
+	if (i > 0) BAYER(row-top_margin,col) = i;
+      }
+#else
+    {
+      for (col=0; col < raw_width; col++) {
+          if( filtering_mode & LIBRAW_FILTERING_NOBLACKS)  
+              i = (pixel[col] << 2);
+          else
+              i = (pixel[col] << 2)
+                  - ph1.t_black + t_black[row][(col /* - left_margin */) >= ph1.split_col]; // changed to fix Coffin's bug!
+          if(col >= left_margin && col < width+left_margin)
+              {
+                  if (i > 0) BAYER(row-top_margin,col-left_margin) = i;
+              }
+          else
+              {
+                  ushort *dfp = get_masked_pointer(row,col);
+                  if(i>0 && dfp) *dfp = i;
+              }
+      }
+    }
+    else
+        {
+            // top-bottom fields
+            for (col=0; col < raw_width; col++) {
+                i = (pixel[col] << 2)
+                    - ph1.t_black + t_black[row][(col+left_margin) >= ph1.split_col];
+                if (i > 0) 
+                    {
+                        ushort *dfp = get_masked_pointer(row,col);
+                        if(dfp) *dfp = i;
+                    }
+            }
+        }
+#endif
+  }
+  free (pixel);
+#ifdef LIBRAW_LIBRARY_BUILD
+  if(!( filtering_mode & LIBRAW_FILTERING_NORAWCURVE) )
+#endif
+  phase_one_correct();
+  maximum = 0xfffc - ph1.t_black;
+}
+
+void CLASS hasselblad_load_raw()
+{
+  struct jhead jh;
+  struct decode *dindex;
+  int row, col, pred[2], len[2], diff, i;
+
+  if (!ljpeg_start (&jh, 0)) return;
+  free (jh.row);
+  order = 0x4949;
+  ph1_bits(-1);
+  for (row=-top_margin; row < raw_height-top_margin; row++) {
+    pred[0] = pred[1] = 0x8000;
+    for (col=-left_margin; col < raw_width-left_margin; col+=2) {
+      for (i=0; i < 2; i++) {
+	for (dindex=jh.huff[0]; dindex->branch[0]; )
+	  dindex = dindex->branch[ph1_bits(1)];
+	len[i] = dindex->leaf;
+      }
+      for (i=0; i < 2; i++) {
+	diff = ph1_bits(len[i]);
+	if ((diff & (1 << (len[i]-1))) == 0)
+	  diff -= (1 << len[i]) - 1;
+	if (diff == 65535) diff = -32768;
+	pred[i] += diff;
+	if (row >= 0 && row < height && (unsigned)(col+i) < width)
+	  BAYER(row,col+i) = pred[i];
+#ifdef LIBRAW_LIBRARY_BUILD
+        else
+            {
+                ushort *dfp = get_masked_pointer(row+top_margin,col+left_margin);
+                if(dfp) *dfp = pred[i];
+            }
+#endif
+      }
+    }
+  }
+  maximum = 0xffff;
+}
+
+void CLASS leaf_hdr_load_raw()
+{
+  ushort *pixel;
+  unsigned tile=0, r, c, row, col;
+
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "leaf_hdr_load_raw()");
+  FORC(tiff_samples)
+    for (r=0; r < raw_height; r++) {
+      if (r % tile_length == 0) {
+	fseek (ifp, data_offset + 4*tile++, SEEK_SET);
+	fseek (ifp, get4() + 2*left_margin, SEEK_SET);
+      }
+      if (filters && c != shot_select) continue;
+      read_shorts (pixel, raw_width);
+      if ((row = r - top_margin) >= height) continue;
+      for (col=0; col < width; col++)
+	if (filters)  BAYER(row,col) = pixel[col];
+	else image[row*width+col][c] = pixel[col];
+    }
+  free (pixel);
+  if (!filters) {
+    maximum = 0xffff;
+    raw_color = 1;
+  }
+}
+
+void CLASS sinar_4shot_load_raw()
+{
+  ushort *pixel;
+  unsigned shot, row, col, r, c;
+
+  if ((shot = shot_select) || half_size) {
+    if (shot) shot--;
+    if (shot > 3) shot = 3;
+    fseek (ifp, data_offset + shot*4, SEEK_SET);
+    fseek (ifp, get4(), SEEK_SET);
+    unpacked_load_raw();
+    return;
+  }
+  free (image);
+  image = (ushort (*)[4])
+	calloc ((iheight=height)*(iwidth=width), sizeof *image);
+  merror (image, "sinar_4shot_load_raw()");
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "sinar_4shot_load_raw()");
+  for (shot=0; shot < 4; shot++) {
+    fseek (ifp, data_offset + shot*4, SEEK_SET);
+    fseek (ifp, get4(), SEEK_SET);
+    for (row=0; row < raw_height; row++) {
+      read_shorts (pixel, raw_width);
+      if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue;
+      for (col=0; col < raw_width; col++) {
+	if ((c = col-left_margin - (shot & 1)) >= width) continue;
+        image[r*width+c][FC(row,col)] = pixel[col];
+      }
+    }
+  }
+  free (pixel);
+  shrink = filters = 0;
+}
+
+void CLASS imacon_full_load_raw()
+{
+  int row, col;
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      read_shorts (image[row*width+col], 3);
+}
+
+void CLASS packed_12_load_raw()
+{
+  int vbits=0, rbits=0, bwide, bite, irow, row, col, val, i;
+  UINT64 bitbuf=0;
+
+  if (raw_width * 2 >= width * 3) {	/* If raw_width is in bytes, */
+    rbits = (bwide = raw_width) * 8;
+    raw_width = raw_width * 2 / 3;	/* convert it to pixels and  */
+    rbits -= raw_width * 12;		/* save the remainder.       */
+  } else bwide = raw_width * 3 / 2;
+  if (load_flags & 1) bwide = bwide * 16 / 15;
+  fseek (ifp, top_margin*bwide, SEEK_CUR);
+  bite = 8 + (load_flags & 24);
+  for (irow=0; irow < height; irow++) {
+    row = irow;
+    if (load_flags & 2 &&
+	(row = irow * 2 % height + irow / (height/2)) == 1 &&
+	load_flags & 4) {
+      if (vbits=0, tiff_compress)
+	fseek (ifp, data_offset - (-width*height*3/4 & -2048), SEEK_SET);
+      else {
+	fseek (ifp, 0, SEEK_END);
+	fseek (ifp, ftell(ifp)/2, SEEK_SET);
+      }
+    }
+    for (col=0; col < raw_width; col++) {
+      for (vbits -= 12; vbits < 0; vbits += bite) {
+	bitbuf <<= bite;
+	for (i=0; i < bite; i+=8)
+	  bitbuf |= (unsigned) (fgetc(ifp) << i);
+      }
+      val = bitbuf << (52-vbits) >> 52;
+      i = (col ^ (bite == 24)) - left_margin;
+      if ((unsigned) i < width)
+	BAYER(row,i) = val << (load_flags >> 6);
+      else if (load_flags & 32)
+#ifdef LIBRAW_LIBRARY_BUILD
+          {
+              ushort *dfp = get_masked_pointer(row,col);
+              if(dfp) *dfp = val << (load_flags >> 6);
+#endif
+	black += val;
+#ifdef LIBRAW_LIBRARY_BUILD
+          }
+#endif
+      if (load_flags & 1 && (col % 10) == 9 &&
+	fgetc(ifp) && col < width+left_margin) derror();
+    }
+    vbits -= rbits;
+  }
+  if (load_flags & 32 && raw_width > width)
+    black /= (raw_width - width) * height;
+}
+
+void CLASS unpacked_load_raw()
+{
+  ushort *pixel;
+  int row, col, bits=0;
+
+  while (1 << ++bits < maximum);
+#ifndef LIBRAW_LIBRARY_BUILD
+  fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+  pixel = (ushort *) calloc (width, sizeof *pixel);
+  merror (pixel, "unpacked_load_raw()");
+  for (row=0; row < height; row++) {
+    read_shorts (pixel, width);
+    fseek (ifp, 2*(raw_width - width), SEEK_CUR);
+    for (col=0; col < width; col++)
+      if ((BAYER2(row,col) = pixel[col]) >> bits) derror();
+  }
+  free (pixel);
+#else
+  // fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "unpacked_load_raw()");
+  for (row=0; row < raw_height; row++) {
+    read_shorts (pixel, raw_width);
+    //fseek (ifp, 2*(raw_width - width), SEEK_CUR);
+    for (col=0; col < raw_width; col++)
+        {
+            ushort *dfp = get_masked_pointer(row,col);
+            if(dfp) 
+                *dfp = pixel[col];
+            else
+                {
+                    if ((BAYER2(row-top_margin,col-left_margin) = pixel[col]) >> bits) derror();
+                }
+        }
+  }
+  free (pixel);
+#endif
+}
+
+void CLASS nokia_load_raw()
+{
+  uchar  *data,  *dp;
+  ushort *pixel, *pix;
+  int dwide, row, c;
+
+  dwide = raw_width * 5 / 4;
+  data = (uchar *) malloc (dwide + raw_width*2);
+  merror (data, "nokia_load_raw()");
+  pixel = (ushort *) (data + dwide);
+  for (row=0; row < raw_height; row++) {
+    if (fread (data, 1, dwide, ifp) < dwide) derror();
+    for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=5, pix+=4)
+      FORC4 pix[c] = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
+    if (row < top_margin)
+#ifdef LIBRAW_LIBRARY_BUILD
+        {
+            int col;
+            for(col=0;col<width;col++)
+                {
+                    ushort *dfp = get_masked_pointer(row,col);
+                    if(dfp) 
+                        *dfp = pixel[col];
+                }
+            FORC(width) black += pixel[c];
+        }
+#else
+      FORC(width) black += pixel[c];
+#endif
+    else
+      FORC(width) BAYER(row-top_margin,c) = pixel[c];
+  }
+  free (data);
+  if (top_margin) black /= top_margin * width;
+  maximum = 0x3ff;
+}
+
+unsigned CLASS pana_bits (int nbits)
+{
+#ifndef LIBRAW_NOTHREADS
+#define buf tls->pana_bits.buf
+#define vbits tls->pana_bits.vbits   
+#else
+  static uchar buf[0x4000];
+  static int vbits;
+#endif
+  int byte;
+
+  if (!nbits) return vbits=0;
+  if (!vbits) {
+    fread (buf+load_flags, 1, 0x4000-load_flags, ifp);
+    fread (buf, 1, load_flags, ifp);
+  }
+  vbits = (vbits - nbits) & 0x1ffff;
+  byte = vbits >> 3 ^ 0x3ff0;
+  return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits);
+#ifndef LIBRAW_NOTHREADS
+#undef buf
+#undef vbits
+#endif
+}
+
+void CLASS panasonic_load_raw()
+{
+  int row, col, i, j, sh=0, pred[2], nonz[2];
+
+  pana_bits(0);
+  for (row=0; row < height; row++)
+    for (col=0; col < raw_width; col++) {
+      if ((i = col % 14) == 0)
+	pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
+      if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
+      if (nonz[i & 1]) {
+	if ((j = pana_bits(8))) {
+	  if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
+	       pred[i & 1] &= ~(-1 << sh);
+	  pred[i & 1] += j << sh;
+	}
+      } else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
+	pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
+      if (col < width)
+      if ((BAYER(row,col) = pred[col & 1]) > 4098) derror();
+#ifdef LIBRAW_LIBRARY_BUILD
+      if(col>=width)
+          {
+              ushort *dfp = get_masked_pointer(row,col);
+              if(dfp)*dfp = pred[col & 1];
+          }
+#endif
+    }
+}
+
+void CLASS olympus_e410_load_raw()
+{
+  int row, col, nbits, sign, low, high, i, w, n, nw;
+  int acarry[2][3], *carry, pred, diff;
+
+  fseek (ifp, 7, SEEK_CUR);
+  getbits(-1);
+  for (row=0; row < height; row++) {
+    memset (acarry, 0, sizeof acarry);
+    for (col=0; col < raw_width; col++) {
+      carry = acarry[col & 1];
+      i = 2 * (carry[2] < 3);
+      for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++);
+      sign = getbits(1) * -1;
+      low  = getbits(2);
+      for (high=0; high < 12; high++)
+	if (getbits(1)) break;
+      if (high == 12)
+	high = getbits(16-nbits) >> 1;
+      carry[0] = (high << nbits) | getbits(nbits);
+      diff = (carry[0] ^ sign) + carry[1];
+      carry[1] = (diff*3 + carry[1]) >> 5;
+      carry[2] = carry[0] > 16 ? 0 : carry[2]+1;
+      if (col >= width) continue;
+      if (row < 2 && col < 2) pred = 0;
+      else if (row < 2) pred = BAYER(row,col-2);
+      else if (col < 2) pred = BAYER(row-2,col);
+      else {
+	w  = BAYER(row,col-2);
+	n  = BAYER(row-2,col);
+	nw = BAYER(row-2,col-2);
+	if ((w < nw && nw < n) || (n < nw && nw < w)) {
+	  if (ABS(w-nw) > 32 || ABS(n-nw) > 32)
+	    pred = w + n - nw;
+	  else pred = (w + n) >> 1;
+	} else pred = ABS(w-nw) > ABS(n-nw) ? w : n;
+      }
+      if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror();
+    }
+  }
+}
+
+void CLASS minolta_rd175_load_raw()
+{
+  uchar pixel[768];
+  unsigned irow, box, row, col;
+
+  for (irow=0; irow < 1481; irow++) {
+    if (fread (pixel, 1, 768, ifp) < 768) derror();
+    box = irow / 82;
+    row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2);
+    switch (irow) {
+      case 1477: case 1479: continue;
+      case 1476: row = 984; break;
+      case 1480: row = 985; break;
+      case 1478: row = 985; box = 1;
+    }
+    if ((box < 12) && (box & 1)) {
+      for (col=0; col < 1533; col++, row ^= 1)
+	if (col != 1) BAYER(row,col) = (col+1) & 2 ?
+		   pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
+      BAYER(row,1)    = pixel[1]   << 1;
+      BAYER(row,1533) = pixel[765] << 1;
+    } else
+      for (col=row & 1; col < 1534; col+=2)
+	BAYER(row,col) = pixel[col/2] << 1;
+  }
+  maximum = 0xff << 1;
+}
+
+void CLASS casio_qv5700_load_raw()
+{
+  uchar  data[3232],  *dp;
+  ushort pixel[2576], *pix;
+  int row, col;
+
+  for (row=0; row < height; row++) {
+    fread (data, 1, 3232, ifp);
+    for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) {
+      pix[0] = (dp[0] << 2) + (dp[1] >> 6);
+      pix[1] = (dp[1] << 4) + (dp[2] >> 4);
+      pix[2] = (dp[2] << 6) + (dp[3] >> 2);
+      pix[3] = (dp[3] << 8) + (dp[4]     );
+    }
+    for (col=0; col < width; col++)
+      BAYER(row,col) = (pixel[col] & 0x3ff);
+  }
+  maximum = 0x3fc;
+}
+
+void CLASS quicktake_100_load_raw()
+{
+  uchar pixel[484][644];
+  static const short gstep[16] =
+  { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 };
+  static const short rstep[6][4] =
+  { {  -3,-1,1,3  }, {  -5,-1,1,5  }, {  -8,-2,2,8  },
+    { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } };
+  static const short t_curve[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 };
+  int rb, row, col, sharp, val=0;
+
+  getbits(-1);
+  memset (pixel, 0x80, sizeof pixel);
+  for (row=2; row < height+2; row++) {
+    for (col=2+(row & 1); col < width+2; col+=2) {
+      val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] +
+		pixel[row][col-2]) >> 2) + gstep[getbits(4)];
+      pixel[row][col] = val = LIM(val,0,255);
+      if (col < 4)
+	pixel[row][col-2] = pixel[row+1][~row & 1] = val;
+      if (row == 2)
+	pixel[row-1][col+1] = pixel[row-1][col+3] = val;
+    }
+    pixel[row][col] = val;
+  }
+  for (rb=0; rb < 2; rb++)
+    for (row=2+rb; row < height+2; row+=2)
+      for (col=3-(row & 1); col < width+2; col+=2) {
+	if (row < 4 || col < 4) sharp = 2;
+	else {
+	  val = ABS(pixel[row-2][col] - pixel[row][col-2])
+	      + ABS(pixel[row-2][col] - pixel[row-2][col-2])
+	      + ABS(pixel[row][col-2] - pixel[row-2][col-2]);
+	  sharp = val <  4 ? 0 : val <  8 ? 1 : val < 16 ? 2 :
+		  val < 32 ? 3 : val < 48 ? 4 : 5;
+	}
+	val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1)
+	      + rstep[sharp][getbits(2)];
+	pixel[row][col] = val = LIM(val,0,255);
+	if (row < 4) pixel[row-2][col+2] = val;
+	if (col < 4) pixel[row+2][col-2] = val;
+      }
+  for (row=2; row < height+2; row++)
+    for (col=3-(row & 1); col < width+2; col+=2) {
+      val = ((pixel[row][col-1] + (pixel[row][col] << 2) +
+	      pixel[row][col+1]) >> 1) - 0x100;
+      pixel[row][col] = LIM(val,0,255);
+    }
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      BAYER(row,col) = t_curve[pixel[row+2][col+2]];
+  maximum = 0x3ff;
+}
+
+const int * CLASS make_decoder_int (const int *source, int level)
+{
+  struct decode *cur;
+
+  cur = free_decode++;
+  if (level < source[0]) {
+    cur->branch[0] = free_decode;
+    source = make_decoder_int (source, level+1);
+    cur->branch[1] = free_decode;
+    source = make_decoder_int (source, level+1);
+  } else {
+    cur->leaf = source[1];
+    source += 2;
+  }
+  return source;
+}
+
+int CLASS radc_token (int tree)
+{
+  int t;
+#ifndef LIBRAW_NOTHREADS
+#define dstart tls->radc_token.dstart
+#define dindex tls->radc_token.dindex
+#define s       tls->radc_token.s
+
+  static const  int source[] = {
+#else
+  static struct decode *dstart[18], *dindex;
+  static const int *s, source[] = {
+#endif
+    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
+  };
+
+  if (free_decode == first_decode)
+    for (s=source, t=0; t < 18; t++) {
+      dstart[t] = free_decode;
+      s = make_decoder_int (s, 0);
+    }
+  if (tree == 18) {
+    if (kodak_cbpp == 243)
+      return (getbits(6) << 2) + 2;	/* most DC50 photos */
+    else
+      return (getbits(5) << 3) + 4;	/* DC40, Fotoman Pixtura */
+  }
+  for (dindex = dstart[tree]; dindex->branch[0]; )
+    dindex = dindex->branch[getbits(1)];
+  return dindex->leaf;
+
+#ifndef LIBRAW_NOTHREADS
+#undef dstart
+#undef dindex
+#undef s
+#endif
+}
+
+#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
+
+#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
+: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
+
+void CLASS kodak_radc_load_raw()
+{
+  int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val;
+  short last[3] = { 16,16,16 }, mul[3], buf[3][3][386];
+  static const ushort pt[] =
+    { 0,0, 1280,1344, 2320,3616, 3328,8000, 4095,16383, 65535,16383 };
+
+  for (i=2; i < 12; i+=2)
+    for (c=pt[i-2]; c <= pt[i]; c++)
+      curve[c] = (float)
+	(c-pt[i-2]) / (pt[i]-pt[i-2]) * (pt[i+1]-pt[i-1]) + pt[i-1] + 0.5;
+  init_decoder();
+  getbits(-1);
+  for (i=0; i < sizeof(buf)/sizeof(short); i++)
+    buf[0][0][i] = 2048;
+  for (row=0; row < height; row+=4) {
+    FORC3 mul[c] = getbits(6);
+    FORC3 {
+      val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
+      s = val > 65564 ? 10:12;
+      x = ~(-1 << (s-1));
+      val <<= 12-s;
+      for (i=0; i < sizeof(buf[0])/sizeof(short); i++)
+	buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
+      last[c] = mul[c];
+      for (r=0; r <= !c; r++) {
+	buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7;
+	for (tree=1, col=width/2; col > 0; ) {
+	  if ((tree = radc_token(tree))) {
+	    col -= 2;
+	    if (tree == 8)
+	      FORYX buf[c][y][x] = radc_token(tree+10) * mul[c];
+	    else
+	      FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR;
+	  } else
+	    do {
+	      nreps = (col > 2) ? radc_token(9) + 1 : 1;
+	      for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) {
+		col -= 2;
+		FORYX buf[c][y][x] = PREDICTOR;
+		if (rep & 1) {
+		  step = radc_token(10) << 4;
+		  FORYX buf[c][y][x] += step;
+		}
+	      }
+	    } while (nreps == 9);
+	}
+	for (y=0; y < 2; y++)
+	  for (x=0; x < width/2; x++) {
+	    val = (buf[c][y+1][x] << 4) / mul[c];
+	    if (val < 0) val = 0;
+	    if (c) BAYER(row+y*2+c-1,x*2+2-c) = val;
+	    else   BAYER(row+r*2+y,x*2+y) = val;
+	  }
+	memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
+      }
+    }
+    for (y=row; y < row+4; y++)
+      for (x=0; x < width; x++)
+	if ((x+y) & 1) {
+	  r = x ? x-1 : x+1;
+	  s = x+1 < width ? x+1 : x-1;
+	  val = (BAYER(y,x)-2048)*2 + (BAYER(y,r)+BAYER(y,s))/2;
+	  if (val < 0) val = 0;
+	  BAYER(y,x) = val;
+	}
+  }
+  for (i=0; i < iheight*iwidth*4; i++)
+    image[0][i] = curve[image[0][i]];
+  maximum = 0x3fff;
+}
+
+#undef FORYX
+#undef PREDICTOR
+
+#ifdef NO_JPEG
+void CLASS kodak_jpeg_load_raw() {}
+#else
+
+METHODDEF(boolean)
+fill_input_buffer (j_decompress_ptr cinfo)
+{
+#ifndef LIBRAW_NOTHREADS
+#define jpeg_buffer tls->jpeg_buffer
+#else
+  static uchar jpeg_buffer[4096];
+#endif
+  size_t nbytes;
+
+  nbytes = fread (jpeg_buffer, 1, 4096, ifp);
+  swab (jpeg_buffer, jpeg_buffer, nbytes);
+  cinfo->src->next_input_byte = jpeg_buffer;
+  cinfo->src->bytes_in_buffer = nbytes;
+  return TRUE;
+#ifndef LIBRAW_NOTHREADS
+#undef jpeg_buffer
+#endif
+}
+
+void CLASS kodak_jpeg_load_raw()
+{
+  struct jpeg_decompress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  JSAMPARRAY buf;
+  JSAMPLE (*pixel)[3];
+  int row, col;
+
+  cinfo.err = jpeg_std_error (&jerr);
+  jpeg_create_decompress (&cinfo);
+  jpeg_stdio_src (&cinfo, ifp);
+  cinfo.src->fill_input_buffer = fill_input_buffer;
+  jpeg_read_header (&cinfo, TRUE);
+  jpeg_start_decompress (&cinfo);
+  if ((cinfo.output_width      != width  ) ||
+      (cinfo.output_height*2   != height ) ||
+      (cinfo.output_components != 3      )) {
+#ifdef DCRAW_VERBOSE
+    fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), ifname);
+#endif
+    jpeg_destroy_decompress (&cinfo);
+#ifdef LIBRAW_LIBRARY_BUILD
+    throw LIBRAW_EXCEPTION_DECODE_JPEG;
+#else
+    longjmp (failure, 3);
+#endif
+  }
+  buf = (*cinfo.mem->alloc_sarray)
+		((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1);
+
+  while (cinfo.output_scanline < cinfo.output_height) {
+    row = cinfo.output_scanline * 2;
+    jpeg_read_scanlines (&cinfo, buf, 1);
+    pixel = (JSAMPLE (*)[3]) buf[0];
+    for (col=0; col < width; col+=2) {
+      BAYER(row+0,col+0) = pixel[col+0][1] << 1;
+      BAYER(row+1,col+1) = pixel[col+1][1] << 1;
+      BAYER(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
+      BAYER(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
+    }
+  }
+  jpeg_finish_decompress (&cinfo);
+  jpeg_destroy_decompress (&cinfo);
+  maximum = 0xff << 1;
+}
+#endif
+
+void CLASS kodak_dc120_load_raw()
+{
+  static const int mul[4] = { 162, 192, 187,  92 };
+  static const int add[4] = {   0, 636, 424, 212 };
+  uchar pixel[848];
+  int row, shift, col;
+
+  for (row=0; row < height; row++) {
+    if (fread (pixel, 1, 848, ifp) < 848) derror();
+    shift = row * mul[row & 3] + add[row & 3];
+    for (col=0; col < width; col++)
+      BAYER(row,col) = (ushort) pixel[(col + shift) % 848];
+  }
+  maximum = 0xff;
+}
+
+void CLASS eight_bit_load_raw()
+{
+  uchar *pixel;
+  unsigned row, col, val, lblack=0;
+
+  pixel = (uchar *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "eight_bit_load_raw()");
+#ifndef LIBRAW_LIBRARY_BUILD
+  fseek (ifp, top_margin*raw_width, SEEK_CUR);
+  for (row=0; row < height; row++) {
+    if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
+    for (col=0; col < raw_width; col++) {
+      val = curve[pixel[col]];
+      if ((unsigned) (col-left_margin) < width)
+        BAYER(row,col-left_margin) = val;
+      else lblack += val;
+    }
+  }
+#else
+  for (row=0; row < raw_height; row++) {
+    if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
+    for (col=0; col < raw_width; col++) {
+        if(filtering_mode & LIBRAW_FILTERING_NORAWCURVE)
+            {
+                val = pixel[col];
+                if(val>maximum) maximum = val;
+            }
+        else
+            val = curve[pixel[col]];
+      if((unsigned) (row-top_margin)< height)
+          {
+              if ((unsigned) (col-left_margin) < width)
+                  BAYER(row,col-left_margin) = val;
+              else
+                  {
+                      ushort *dfp = get_masked_pointer(row,col);
+                      if(dfp) *dfp = val;
+                      lblack += val;
+                  }
+          }
+      else // top/bottom margins
+          {
+              ushort *dfp = get_masked_pointer(row,col);
+              if(dfp) *dfp = val;
+          }
+    }
+  }
+#endif
+
+  free (pixel);
+  if (raw_width > width+1)
+    black = lblack / ((raw_width - width) * height);
+  if (!strncmp(model,"DC2",3))
+    black = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+  if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+#endif
+  maximum = curve[0xff];
+}
+
+void CLASS kodak_yrgb_load_raw()
+{
+  uchar *pixel;
+  int row, col, y, cb, cr, rgb[3], c;
+
+  pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel);
+  merror (pixel, "kodak_yrgb_load_raw()");
+  for (row=0; row < height; row++) {
+    if (~row & 1)
+      if (fread (pixel, raw_width, 3, ifp) < 3) derror();
+    for (col=0; col < raw_width; col++) {
+      y  = pixel[width*2*(row & 1) + col];
+      cb = pixel[width + (col & -2)]   - 128;
+      cr = pixel[width + (col & -2)+1] - 128;
+      rgb[1] = y-((cb + cr + 2) >> 2);
+      rgb[2] = rgb[1] + cb;
+      rgb[0] = rgb[1] + cr;
+      FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,255)];
+    }
+  }
+  free (pixel);
+  maximum = curve[0xff];
+}
+
+void CLASS kodak_262_load_raw()
+{
+  static const uchar kodak_tree[2][26] =
+  { { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 },
+    { 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } };
+  struct decode *decode[2];
+  uchar *pixel;
+  int *strip, ns, i, row, col, chess, pi=0, pi1, pi2, pred, val;
+
+  init_decoder();
+  for (i=0; i < 2; i++) {
+    decode[i] = free_decode;
+    make_decoder (kodak_tree[i], 0);
+  }
+  ns = (raw_height+63) >> 5;
+  pixel = (uchar *) malloc (raw_width*32 + ns*4);
+  merror (pixel, "kodak_262_load_raw()");
+  strip = (int *) (pixel + raw_width*32);
+  order = 0x4d4d;
+  for (i=0; i < ns; i++)
+    strip[i] = get4();
+  for (row=0; row < raw_height; row++) {
+    if ((row & 31) == 0) {
+      fseek (ifp, strip[row >> 5], SEEK_SET);
+      getbits(-1);
+      pi = 0;
+    }
+    for (col=0; col < raw_width; col++) {
+      chess = (row + col) & 1;
+      pi1 = chess ? pi-2           : pi-raw_width-1;
+      pi2 = chess ? pi-2*raw_width : pi-raw_width+1;
+      if (col <= chess) pi1 = -1;
+      if (pi1 < 0) pi1 = pi2;
+      if (pi2 < 0) pi2 = pi1;
+      if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2;
+      pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1;
+      pixel[pi] = val = pred + ljpeg_diff (decode[chess]);
+      if (val >> 8) derror();
+#ifdef LIBRAW_LIBRARY_BUILD
+      if(filtering_mode & LIBRAW_FILTERING_NORAWCURVE)
+          val = pixel[pi++];
+      else
+          val = curve[pixel[pi++]];
+#else
+      val = curve[pixel[pi++]];
+#endif
+      if ((unsigned) (col-left_margin) < width)
+	BAYER(row,col-left_margin) = val;
+      else
+#ifndef LIBRAW_LIBRARY_BUILD
+          black += val;
+#else
+      {
+          ushort *dfp = get_masked_pointer(row,col);
+          if(dfp) *dfp = val;
+          black += val;
+      }
+#endif
+    }
+  }
+  free (pixel);
+  if (raw_width > width)
+    black /= (raw_width - width) * height;
+}
+
+int CLASS kodak_65000_decode (short *out, int bsize)
+{
+  uchar c, blen[768];
+  ushort raw[6];
+  INT64 bitbuf=0;
+  int save, bits=0, i, j, len, diff;
+
+  save = ftell(ifp);
+  bsize = (bsize + 3) & -4;
+  for (i=0; i < bsize; i+=2) {
+    c = fgetc(ifp);
+    if ((blen[i  ] = c & 15) > 12 ||
+	(blen[i+1] = c >> 4) > 12 ) {
+      fseek (ifp, save, SEEK_SET);
+      for (i=0; i < bsize; i+=8) {
+	read_shorts (raw, 6);
+	out[i  ] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
+	out[i+1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
+	for (j=0; j < 6; j++)
+	  out[i+2+j] = raw[j] & 0xfff;
+      }
+      return 1;
+    }
+  }
+  if ((bsize & 7) == 4) {
+    bitbuf  = fgetc(ifp) << 8;
+    bitbuf += fgetc(ifp);
+    bits = 16;
+  }
+  for (i=0; i < bsize; i++) {
+    len = blen[i];
+    if (bits < len) {
+      for (j=0; j < 32; j+=8)
+	bitbuf += (INT64) fgetc(ifp) << (bits+(j^8));
+      bits += 32;
+    }
+    diff = bitbuf & (0xffff >> (16-len));
+    bitbuf >>= len;
+    bits -= len;
+    if ((diff & (1 << (len-1))) == 0)
+      diff -= (1 << len) - 1;
+    out[i] = diff;
+  }
+  return 0;
+}
+
+void CLASS kodak_65000_load_raw()
+{
+  short buf[256];
+  int row, col, len, pred[2], ret, i;
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col+=256) {
+      pred[0] = pred[1] = 0;
+      len = MIN (256, width-col);
+      ret = kodak_65000_decode (buf, len);
+      for (i=0; i < len; i++)
+#ifndef LIBRAW_LIBRARY_BUILD
+	if ((BAYER(row,col+i) =	curve[ret ? buf[i] :
+		(pred[i & 1] += buf[i])]) >> 12) derror();
+#else
+      {
+          ushort val = ret ? buf[i] : (pred[i & 1] += buf[i]);
+          if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+              val = curve[val];
+          BAYER(row,col+i)=val;
+          if(curve[val]>>12) derror();
+      }
+#endif
+    }
+}
+
+void CLASS kodak_ycbcr_load_raw()
+{
+  short buf[384], *bp;
+  int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
+  ushort *ip;
+
+  for (row=0; row < height; row+=2)
+    for (col=0; col < width; col+=128) {
+      len = MIN (128, width-col);
+      kodak_65000_decode (buf, len*3);
+      y[0][1] = y[1][1] = cb = cr = 0;
+      for (bp=buf, i=0; i < len; i+=2, bp+=2) {
+	cb += bp[4];
+	cr += bp[5];
+	rgb[1] = -((cb + cr + 2) >> 2);
+	rgb[2] = rgb[1] + cb;
+	rgb[0] = rgb[1] + cr;
+	for (j=0; j < 2; j++)
+	  for (k=0; k < 2; k++) {
+	    if ((y[j][k] = y[j][k^1] + *bp++) >> 10) derror();
+	    ip = image[(row+j)*width + col+i+k];
+#ifndef LIBRAW_LIBRARY_BUILD
+	    FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
+#else
+          if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+              FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
+          else
+              FORC3 ip[c] = y[j][k]+rgb[c];;
+#endif
+	  }
+      }
+    }
+}
+
+void CLASS kodak_rgb_load_raw()
+{
+  short buf[768], *bp;
+  int row, col, len, c, i, rgb[3];
+  ushort *ip=image[0];
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col+=256) {
+      len = MIN (256, width-col);
+      kodak_65000_decode (buf, len*3);
+      memset (rgb, 0, sizeof rgb);
+      for (bp=buf, i=0; i < len; i++, ip+=4)
+	FORC3 if ((ip[c] = rgb[c] += *bp++) >> 12) derror();
+    }
+}
+
+void CLASS kodak_thumb_load_raw()
+{
+  int row, col;
+  colors = thumb_misc >> 5;
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      read_shorts (image[row*width+col], colors);
+  maximum = (1 << (thumb_misc & 31)) - 1;
+}
+
+void CLASS sony_decrypt (unsigned *data, int len, int start, int key)
+{
+#ifndef LIBRAW_NOTHREADS
+#define pad tls->sony_decrypt.pad
+#define p   tls->sony_decrypt.p
+#else
+  static unsigned pad[128], p;
+#endif
+
+  if (start) {
+    for (p=0; p < 4; p++)
+      pad[p] = key = key * 48828125 + 1;
+    pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
+    for (p=4; p < 127; p++)
+      pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
+    for (p=0; p < 127; p++)
+      pad[p] = htonl(pad[p]);
+  }
+  while (len--)
+    *data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
+#ifndef LIBRAW_NOTHREADS
+#undef pad
+#undef p
+#endif
+}
+
+void CLASS sony_load_raw()
+{
+  uchar head[40];
+  ushort *pixel;
+  unsigned i, key, row, col;
+
+  fseek (ifp, 200896, SEEK_SET);
+  fseek (ifp, (unsigned) fgetc(ifp)*4 - 1, SEEK_CUR);
+  order = 0x4d4d;
+  key = get4();
+  fseek (ifp, 164600, SEEK_SET);
+  fread (head, 1, 40, ifp);
+  sony_decrypt ((unsigned int *) head, 10, 1, key);
+  for (i=26; i-- > 22; )
+    key = key << 8 | head[i];
+  fseek (ifp, data_offset, SEEK_SET);
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "sony_load_raw()");
+  for (row=0; row < height; row++) {
+    if (fread (pixel, 2, raw_width, ifp) < raw_width) derror();
+    sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key);
+#ifdef LIBRAW_LIBRARY_BUILD
+    for (col=0; col < left_margin; col++)
+          {
+              ushort *dfp = get_masked_pointer(row,col);
+              if(dfp) *dfp = ntohs(pixel[col]);
+          }
+    for (col=left_margin+width; col < raw_width; col++)
+          {
+              ushort *dfp = get_masked_pointer(row,col);
+              if(dfp) *dfp = ntohs(pixel[col]);
+          }
+#endif
+    for (col=9; col < left_margin; col++)
+      black += ntohs(pixel[col]);
+    for (col=0; col < width; col++)
+      if ((BAYER(row,col) = ntohs(pixel[col+left_margin])) >> 14)
+	derror();
+  }
+  free (pixel);
+  if (left_margin > 9)
+    black /= (left_margin-9) * height;
+  maximum = 0x3ff0;
+}
+
+void CLASS sony_arw_load_raw()
+{
+  int col, row, len, diff, sum=0;
+
+  getbits(-1);
+  for (col = raw_width; col--; )
+    for (row=0; row < raw_height+1; row+=2) {
+      if (row == raw_height) row = 1;
+      len = 4 - getbits(2);
+      if (len == 3 && getbits(1)) len = 0;
+      if (len == 4)
+	while (len < 17 && !getbits(1)) len++;
+      diff = getbits(len);
+      if ((diff & (1 << (len-1))) == 0)
+	diff -= (1 << len) - 1;
+      if ((sum += diff) >> 12) derror();
+      if (row < height) BAYER(row,col) = sum;
+#ifdef LIBRAW_LIBRARY_BUILD
+      else
+          {
+              ushort *dfp = get_masked_pointer(row,col);
+              if(dfp) *dfp = sum;
+          }
+#endif
+    }
+}
+
+void CLASS sony_arw2_load_raw()
+{
+  uchar *data, *dp;
+  ushort pix[16];
+  int row, col, val, max, min, imax, imin, sh, bit, i;
+
+  data = (uchar *) malloc (raw_width);
+  merror (data, "sony_arw2_load_raw()");
+  for (row=0; row < height; row++) {
+    fread (data, 1, raw_width, ifp);
+    for (dp=data, col=0; col < width-30; dp+=16) {
+      max = 0x7ff & (val = sget4(dp));
+      min = 0x7ff & val >> 11;
+      imax = 0x0f & val >> 22;
+      imin = 0x0f & val >> 26;
+      for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++);
+      for (bit=30, i=0; i < 16; i++)
+	if      (i == imax) pix[i] = max;
+	else if (i == imin) pix[i] = min;
+	else {
+	  pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
+	  if (pix[i] > 0x7ff) pix[i] = 0x7ff;
+	  bit += 7;
+	}
+      for (i=0; i < 16; i++, col+=2)
+#ifndef LIBRAW_LIBRARY_BUILD
+	  BAYER(row,col) = curve[pix[i] << 1] >> 1;
+#else
+        {
+            ushort val = pix[i];
+            if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+                val = curve[val<<1]>>1;
+            BAYER(row,col)=val;
+        }
+#endif
+      col -= col & 1 ? 1:31;
+    }
+  }
+  free (data);
+}
+
+#define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1)
+
+/* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */
+void CLASS smal_decode_segment (unsigned seg[2][2], int holes)
+{
+  uchar hist[3][13] = {
+    { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
+    { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
+    { 3, 3, 0, 0, 63,     47,     31,     15,    0 } };
+  int low, high=0xff, carry=0, nbits=8;
+  int s, count, bin, next, i, sym[3];
+  uchar diff, pred[]={0,0};
+  ushort data=0, range=0;
+  unsigned pix, row, col;
+
+  fseek (ifp, seg[0][1]+1, SEEK_SET);
+  getbits(-1);
+  for (pix=seg[0][0]; pix < seg[1][0]; pix++) {
+    for (s=0; s < 3; s++) {
+      data = data << nbits | getbits(nbits);
+      if (carry < 0)
+	carry = (nbits += carry+1) < 1 ? nbits-1 : 0;
+      while (--nbits >= 0)
+	if ((data >> nbits & 0xff) == 0xff) break;
+      if (nbits > 0)
+	  data = ((data & ((1 << (nbits-1)) - 1)) << 1) |
+	((data + (((data & (1 << (nbits-1)))) << 1)) & (-1 << nbits));
+      if (nbits >= 0) {
+	data += getbits(1);
+	carry = nbits - 8;
+      }
+      count = ((((data-range+1) & 0xffff) << 2) - 1) / (high >> 4);
+      for (bin=0; hist[s][bin+5] > count; bin++);
+		low = hist[s][bin+5] * (high >> 4) >> 2;
+      if (bin) high = hist[s][bin+4] * (high >> 4) >> 2;
+      high -= low;
+      for (nbits=0; high << nbits < 128; nbits++);
+      range = (range+low) << nbits;
+      high <<= nbits;
+      next = hist[s][1];
+      if (++hist[s][2] > hist[s][3]) {
+	next = (next+1) & hist[s][0];
+	hist[s][3] = (hist[s][next+4] - hist[s][next+5]) >> 2;
+	hist[s][2] = 1;
+      }
+      if (hist[s][hist[s][1]+4] - hist[s][hist[s][1]+5] > 1) {
+	if (bin < hist[s][1])
+	  for (i=bin; i < hist[s][1]; i++) hist[s][i+5]--;
+	else if (next <= bin)
+	  for (i=hist[s][1]; i < bin; i++) hist[s][i+5]++;
+      }
+      hist[s][1] = next;
+      sym[s] = bin;
+    }
+    diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
+    if (sym[0] & 4)
+      diff = diff ? -diff : 0x80;
+    if (ftell(ifp) + 12 >= seg[1][1])
+      diff = 0;
+    pred[pix & 1] += diff;
+    row = pix / raw_width - top_margin;
+    col = pix % raw_width - left_margin;
+    if (row < height && col < width)
+      BAYER(row,col) = pred[pix & 1];
+#ifdef LIBRAW_LIBRARY_BUILD
+    else
+        {
+            ushort *dfp = get_masked_pointer(row+top_margin,col+left_margin);
+            if(dfp) *dfp = pred[pix &1];
+        }
+#endif
+    if (!(pix & 1) && HOLE(row)) pix += 2;
+  }
+  maximum = 0xff;
+}
+
+void CLASS smal_v6_load_raw()
+{
+  unsigned seg[2][2];
+
+  fseek (ifp, 16, SEEK_SET);
+  seg[0][0] = 0;
+  seg[0][1] = get2();
+  seg[1][0] = raw_width * raw_height;
+  seg[1][1] = INT_MAX;
+  smal_decode_segment (seg, 0);
+}
+
+int CLASS median4 (int *p)
+{
+  int min, max, sum, i;
+
+  min = max = sum = p[0];
+  for (i=1; i < 4; i++) {
+    sum += p[i];
+    if (min > p[i]) min = p[i];
+    if (max < p[i]) max = p[i];
+  }
+  return (sum - min - max) >> 1;
+}
+
+void CLASS fill_holes (int holes)
+{
+  int row, col, val[4];
+
+  for (row=2; row < height-2; row++) {
+    if (!HOLE(row)) continue;
+    for (col=1; col < width-1; col+=4) {
+      val[0] = BAYER(row-1,col-1);
+      val[1] = BAYER(row-1,col+1);
+      val[2] = BAYER(row+1,col-1);
+      val[3] = BAYER(row+1,col+1);
+      BAYER(row,col) = median4(val);
+    }
+    for (col=2; col < width-2; col+=4)
+      if (HOLE(row-2) || HOLE(row+2))
+	BAYER(row,col) = (BAYER(row,col-2) + BAYER(row,col+2)) >> 1;
+      else {
+	val[0] = BAYER(row,col-2);
+	val[1] = BAYER(row,col+2);
+	val[2] = BAYER(row-2,col);
+	val[3] = BAYER(row+2,col);
+	BAYER(row,col) = median4(val);
+      }
+  }
+}
+
+void CLASS smal_v9_load_raw()
+{
+  unsigned seg[256][2], offset, nseg, holes, i;
+
+  fseek (ifp, 67, SEEK_SET);
+  offset = get4();
+  nseg = fgetc(ifp);
+  fseek (ifp, offset, SEEK_SET);
+  for (i=0; i < nseg*2; i++)
+    seg[0][i] = get4() + data_offset*(i & 1);
+  fseek (ifp, 78, SEEK_SET);
+  holes = fgetc(ifp);
+  fseek (ifp, 88, SEEK_SET);
+  seg[nseg][0] = raw_height * raw_width;
+  seg[nseg][1] = get4() + data_offset;
+  for (i=0; i < nseg; i++)
+    smal_decode_segment (seg+i, holes);
+  if (holes) fill_holes (holes);
+}
+
+void CLASS gamma_curve (double pwr, double ts, int mode, int imax)
+{
+  int i;
+  double g[6], bnd[2]={0,0}, r;
+
+  g[0] = pwr;
+  g[1] = ts;
+  g[2] = g[3] = g[4] = 0;
+  bnd[g[1] >= 1] = 1;
+  if (g[1] && (g[1]-1)*(g[0]-1) <= 0) {
+    for (i=0; i < 48; i++) {
+      g[2] = (bnd[0] + bnd[1])/2;
+      if (g[0]) bnd[(pow(g[2]/g[1],-g[0]) - 1)/g[0] - 1/g[2] > -1] = g[2];
+      else	bnd[g[2]/exp(1-1/g[2]) < g[1]] = g[2];
+    }
+    g[3] = g[2] / g[1];
+    if (g[0]) g[4] = g[2] * (1/g[0] - 1);
+  }
+  if (g[0]) g[5] = 1 / (g[1]*SQR(g[3])/2 - g[4]*(1 - g[3]) +
+		(1 - pow(g[3],1+g[0]))*(1 + g[4])/(1 + g[0])) - 1;
+  else      g[5] = 1 / (g[1]*SQR(g[3])/2 + 1
+		- g[2] - g[3] -	g[2]*g[3]*(log(g[3]) - 1)) - 1;
+  if (!mode--) {
+    memcpy (gamm, g, sizeof gamm);
+    return;
+  }
+  for (i=0; i < 0x10000; i++) {
+    curve[i] = 0xffff;
+    if ((r = (double) i / imax) < 1)
+      curve[i] = 0x10000 * ( mode
+	? (r < g[3] ? r*g[1] : (g[0] ? pow( r,g[0])*(1+g[4])-g[4]    : log(r)*g[2]+1))
+	: (r < g[2] ? r/g[1] : (g[0] ? pow((r+g[4])/(1+g[4]),1/g[0]) : exp((r-1)/g[2]))));
+  }
+}
+
+void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size)
+{
+  double work[3][6], num;
+  int i, j, k;
+
+  for (i=0; i < 3; i++) {
+    for (j=0; j < 6; j++)
+      work[i][j] = j == i+3;
+    for (j=0; j < 3; j++)
+      for (k=0; k < size; k++)
+	work[i][j] += in[k][i] * in[k][j];
+  }
+  for (i=0; i < 3; i++) {
+    num = work[i][i];
+    for (j=0; j < 6; j++)
+      work[i][j] /= num;
+    for (k=0; k < 3; k++) {
+      if (k==i) continue;
+      num = work[k][i];
+      for (j=0; j < 6; j++)
+	work[k][j] -= work[i][j] * num;
+    }
+  }
+  for (i=0; i < size; i++)
+    for (j=0; j < 3; j++)
+      for (out[i][j]=k=0; k < 3; k++)
+	out[i][j] += work[j][k+3] * in[i][k];
+}
+
+void CLASS cam_xyz_coeff (double cam_xyz[4][3])
+{
+  double cam_rgb[4][3], inverse[4][3], num;
+  int i, j, k;
+
+  for (i=0; i < colors; i++)		/* Multiply out XYZ colorspace */
+    for (j=0; j < 3; j++)
+      for (cam_rgb[i][j] = k=0; k < 3; k++)
+	cam_rgb[i][j] += cam_xyz[i][k] * xyz_rgb[k][j];
+
+  for (i=0; i < colors; i++) {		/* Normalize cam_rgb so that */
+    for (num=j=0; j < 3; j++)		/* cam_rgb * (1,1,1) is (1,1,1,1) */
+      num += cam_rgb[i][j];
+    for (j=0; j < 3; j++)
+      cam_rgb[i][j] /= num;
+    pre_mul[i] = 1 / num;
+  }
+  pseudoinverse (cam_rgb, inverse, colors);
+  for (raw_color = i=0; i < 3; i++)
+    for (j=0; j < colors; j++)
+      rgb_cam[i][j] = inverse[j][i];
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+  color_flags.rgb_cam_state = LIBRAW_COLORSTATE_CONST;
+#endif
+}
+
+#ifdef COLORCHECK
+void CLASS colorcheck()
+{
+#define NSQ 24
+// Coordinates of the GretagMacbeth ColorChecker squares
+// width, height, 1st_column, 1st_row
+  int cut[NSQ][4];			// you must set these
+// ColorChecker Chart under 6500-kelvin illumination
+  static const double gmb_xyY[NSQ][3] = {
+    { 0.400, 0.350, 10.1 },		// Dark Skin
+    { 0.377, 0.345, 35.8 },		// Light Skin
+    { 0.247, 0.251, 19.3 },		// Blue Sky
+    { 0.337, 0.422, 13.3 },		// Foliage
+    { 0.265, 0.240, 24.3 },		// Blue Flower
+    { 0.261, 0.343, 43.1 },		// Bluish Green
+    { 0.506, 0.407, 30.1 },		// Orange
+    { 0.211, 0.175, 12.0 },		// Purplish Blue
+    { 0.453, 0.306, 19.8 },		// Moderate Red
+    { 0.285, 0.202, 6.6 },		// Purple
+    { 0.380, 0.489, 44.3 },		// Yellow Green
+    { 0.473, 0.438, 43.1 },		// Orange Yellow
+    { 0.187, 0.129, 6.1 },		// Blue
+    { 0.305, 0.478, 23.4 },		// Green
+    { 0.539, 0.313, 12.0 },		// Red
+    { 0.448, 0.470, 59.1 },		// Yellow
+    { 0.364, 0.233, 19.8 },		// Magenta
+    { 0.196, 0.252, 19.8 },		// Cyan
+    { 0.310, 0.316, 90.0 },		// White
+    { 0.310, 0.316, 59.1 },		// Neutral 8
+    { 0.310, 0.316, 36.2 },		// Neutral 6.5
+    { 0.310, 0.316, 19.8 },		// Neutral 5
+    { 0.310, 0.316, 9.0 },		// Neutral 3.5
+    { 0.310, 0.316, 3.1 } };		// Black
+  double gmb_cam[NSQ][4], gmb_xyz[NSQ][3];
+  double inverse[NSQ][3], cam_xyz[4][3], num;
+  int c, i, j, k, sq, row, col, count[4];
+
+  memset (gmb_cam, 0, sizeof gmb_cam);
+  for (sq=0; sq < NSQ; sq++) {
+    FORCC count[c] = 0;
+    for   (row=cut[sq][3]; row < cut[sq][3]+cut[sq][1]; row++)
+      for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++) {
+	c = FC(row,col);
+	if (c >= colors) c -= 2;
+	gmb_cam[sq][c] += BAYER(row,col);
+	count[c]++;
+      }
+    FORCC gmb_cam[sq][c] = gmb_cam[sq][c]/count[c] - black;
+    gmb_xyz[sq][0] = gmb_xyY[sq][2] * gmb_xyY[sq][0] / gmb_xyY[sq][1];
+    gmb_xyz[sq][1] = gmb_xyY[sq][2];
+    gmb_xyz[sq][2] = gmb_xyY[sq][2] *
+		(1 - gmb_xyY[sq][0] - gmb_xyY[sq][1]) / gmb_xyY[sq][1];
+  }
+  pseudoinverse (gmb_xyz, inverse, NSQ);
+  for (i=0; i < colors; i++)
+    for (j=0; j < 3; j++)
+      for (cam_xyz[i][j] = k=0; k < NSQ; k++)
+	cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j];
+  cam_xyz_coeff (cam_xyz);
+#ifdef DCRAW_VERBOSE
+  if (verbose) {
+    printf ("    { \"%s %s\", %d,\n\t{", make, model, black);
+    num = 10000 / (cam_xyz[1][0] + cam_xyz[1][1] + cam_xyz[1][2]);
+    FORCC for (j=0; j < 3; j++)
+      printf ("%c%d", (c | j) ? ',':' ', (int) (cam_xyz[c][j] * num + 0.5));
+    puts (" } },");
+  }
+#endif
+#undef NSQ
+}
+#endif
+
+void CLASS hat_transform (float *temp, float *base, int st, int size, int sc)
+{
+  int i;
+  for (i=0; i < sc; i++)
+    temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)];
+  for (; i+sc < size; i++)
+    temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)];
+  for (; i < size; i++)
+    temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))];
+}
+
+#ifndef _OPENMP
+void CLASS wavelet_denoise()
+{
+  float *fimg=0, *temp, thold, mul[2], avg, diff;
+  int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast;
+  ushort *window[4];
+  static const float noise[] =
+  { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
+
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Wavelet denoising...\n"));
+#endif
+
+  while (maximum << scale < 0x10000) scale++;
+  maximum <<= --scale;
+  black <<= scale;
+  if ((size = iheight*iwidth) < 0x15550000)
+    fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg);
+  merror (fimg, "wavelet_denoise()");
+  temp = fimg + size*3;
+  if ((nc = colors) == 3 && filters) nc++;
+  FORC(nc) {			/* denoise R,G1,B,G3 individually */
+    for (i=0; i < size; i++)
+        fimg[i] = 256 * sqrt((double)(image[i][c] << scale));
+    for (hpass=lev=0; lev < 5; lev++) {
+      lpass = size*((lev & 1)+1);
+      for (row=0; row < iheight; row++) {
+	hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev);
+        for (col=0; col < iwidth; col++)
+	  fimg[lpass + row*iwidth + col] = temp[col] * 0.25;
+      }
+      for (col=0; col < iwidth; col++) {
+	hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev);
+	for (row=0; row < iheight; row++)
+	  fimg[lpass + row*iwidth + col] = temp[row] * 0.25;
+      }
+      thold = threshold * noise[lev];
+      for (i=0; i < size; i++) {
+	fimg[hpass+i] -= fimg[lpass+i];
+	if	(fimg[hpass+i] < -thold) fimg[hpass+i] += thold;
+	else if (fimg[hpass+i] >  thold) fimg[hpass+i] -= thold;
+	else	 fimg[hpass+i] = 0;
+	if (hpass) fimg[i] += fimg[hpass+i];
+      }
+      hpass = lpass;
+    }
+    for (i=0; i < size; i++)
+      image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000);
+  }
+  if (filters && colors == 3) {  /* pull G1 and G3 closer together */
+    for (row=0; row < 2; row++)
+      mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1];
+    for (i=0; i < 4; i++)
+      window[i] = (ushort *) fimg + width*i;
+    for (wlast=-1, row=1; row < height-1; row++) {
+      while (wlast < row+1) {
+	for (wlast++, i=0; i < 4; i++)
+	  window[(i+3) & 3] = window[i];
+	for (col = FC(wlast,1) & 1; col < width; col+=2)
+	  window[2][col] = BAYER(wlast,col);
+      }
+      thold = threshold/512;
+      for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) {
+	avg = ( window[0][col-1] + window[0][col+1] +
+		window[2][col-1] + window[2][col+1] - black*4 )
+	      * mul[row & 1] + (window[1][col] - black) * 0.5 + black;
+	avg = avg < 0 ? 0 : sqrt(avg);
+	diff = sqrt((double)(BAYER(row,col))) - avg;
+	if      (diff < -thold) diff += thold;
+	else if (diff >  thold) diff -= thold;
+	else diff = 0;
+	BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5);
+      }
+    }
+  }
+  free (fimg);
+}
+#else
+void CLASS wavelet_denoise()
+{
+  float *fimg=0, *temp, thold, mul[2], avg, diff;
+  int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast;
+  ushort *window[4];
+  static const float noise[] =
+  { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
+
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Wavelet denoising...\n"));
+#endif
+
+  while (maximum << scale < 0x10000) scale++;
+  maximum <<= --scale;
+  black <<= scale;
+  if ((size = iheight*iwidth) < 0x15550000)
+    fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg);
+  merror (fimg, "wavelet_denoise()");
+  temp = fimg + size*3;
+  if ((nc = colors) == 3 && filters) nc++;
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp parallel default(shared) private(i,col,row,thold,lev,lpass,hpass,temp) firstprivate(c,scale,size) 
+#endif
+  {
+      temp = (float*)malloc( (iheight + iwidth) * sizeof *fimg);
+    FORC(nc) {			/* denoise R,G1,B,G3 individually */
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp for
+#endif
+      for (i=0; i < size; i++)
+        fimg[i] = 256 * sqrt((double)(image[i][c] << scale));
+      for (hpass=lev=0; lev < 5; lev++) {
+	lpass = size*((lev & 1)+1);
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp for
+#endif
+	for (row=0; row < iheight; row++) {
+	  hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev);
+	  for (col=0; col < iwidth; col++)
+	    fimg[lpass + row*iwidth + col] = temp[col] * 0.25;
+	}
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp for
+#endif
+	for (col=0; col < iwidth; col++) {
+	  hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev);
+	  for (row=0; row < iheight; row++)
+	    fimg[lpass + row*iwidth + col] = temp[row] * 0.25;
+	}
+	thold = threshold * noise[lev];
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp for
+#endif
+	for (i=0; i < size; i++) {
+	  fimg[hpass+i] -= fimg[lpass+i];
+	  if	(fimg[hpass+i] < -thold) fimg[hpass+i] += thold;
+	  else if (fimg[hpass+i] >  thold) fimg[hpass+i] -= thold;
+	  else	 fimg[hpass+i] = 0;
+	  if (hpass) fimg[i] += fimg[hpass+i];
+	}
+	hpass = lpass;
+      }
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp for
+#endif
+      for (i=0; i < size; i++)
+	image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000);
+    }
+    free(temp);
+  } /* end omp parallel */
+/* the following loops are hard to parallize, no idea yes,
+ * problem is wlast which is carrying dependency
+ * second part should be easyer, but did not yet get it right.
+ */
+  if (filters && colors == 3) {  /* pull G1 and G3 closer together */
+    for (row=0; row < 2; row++)
+      mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1];
+    for (i=0; i < 4; i++)
+      window[i] = (ushort *) fimg + width*i;
+    for (wlast=-1, row=1; row < height-1; row++) {
+      while (wlast < row+1) {
+	for (wlast++, i=0; i < 4; i++)
+	  window[(i+3) & 3] = window[i];
+	for (col = FC(wlast,1) & 1; col < width; col+=2)
+	  window[2][col] = BAYER(wlast,col);
+      }
+      thold = threshold/512;
+      for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) {
+	avg = ( window[0][col-1] + window[0][col+1] +
+		window[2][col-1] + window[2][col+1] - black*4 )
+	      * mul[row & 1] + (window[1][col] - black) * 0.5 + black;
+	avg = avg < 0 ? 0 : sqrt(avg);
+	diff = sqrt(BAYER(row,col)) - avg;
+	if      (diff < -thold) diff += thold;
+	else if (diff >  thold) diff -= thold;
+	else diff = 0;
+	BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5);
+      }
+    }
+  }
+  free (fimg);
+}
+
+#endif
+
+void CLASS scale_colors()
+{
+  unsigned bottom, right, size, row, col, ur, uc, i, x, y, c, sum[8];
+  int val, dark, sat;
+  double dsum[8], dmin, dmax;
+  float scale_mul[4], fr, fc;
+  ushort *img=0, *pix;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS,0,2);
+#endif
+
+  if (user_mul[0])
+    memcpy (pre_mul, user_mul, sizeof pre_mul);
+  if (use_auto_wb || (use_camera_wb && cam_mul[0] == -1)) {
+    memset (dsum, 0, sizeof dsum);
+    bottom = MIN (greybox[1]+greybox[3], height);
+    right  = MIN (greybox[0]+greybox[2], width);
+    for (row=greybox[1]; row < bottom; row += 8)
+      for (col=greybox[0]; col < right; col += 8) {
+	memset (sum, 0, sizeof sum);
+	for (y=row; y < row+8 && y < bottom; y++)
+	  for (x=col; x < col+8 && x < right; x++)
+	    FORC4 {
+	      if (filters) {
+		c = FC(y,x);
+		val = BAYER(y,x);
+	      } else
+		val = image[y*width+x][c];
+	      if (val > maximum-25) goto skip_block;
+	      if ((val -= black) < 0) val = 0;
+	      sum[c] += val;
+	      sum[c+4]++;
+	      if (filters) break;
+	    }
+	FORC(8) dsum[c] += sum[c];
+skip_block: ;
+      }
+    FORC4 if (dsum[c]) pre_mul[c] = dsum[c+4] / dsum[c];
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+  }
+  if (use_camera_wb && cam_mul[0] != -1) {
+    memset (sum, 0, sizeof sum);
+    for (row=0; row < 8; row++)
+      for (col=0; col < 8; col++) {
+	c = FC(row,col);
+	if ((val = white[row][col] - black) > 0)
+	  sum[c] += val;
+	sum[c+4]++;
+      }
+    if (sum[0] && sum[1] && sum[2] && sum[3])
+        {
+            FORC4 pre_mul[c] = (float) sum[c+4] / sum[c];
+#ifdef LIBRAW_LIBRARY_BUILD
+            color_flags.pre_mul_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+        }
+    else if (cam_mul[0] && cam_mul[2])
+        {
+            memcpy (pre_mul, cam_mul, sizeof pre_mul);
+#ifdef LIBRAW_LIBRARY_BUILD
+            color_flags.pre_mul_state =color_flags.pre_mul_state;
+#endif
+        }
+    else
+        {
+#ifdef LIBRAW_LIBRARY_BUILD
+            imgdata.process_warnings |= LIBRAW_WARN_BAD_CAMERA_WB;
+#endif
+#ifdef DCRAW_VERBOSE
+            fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname);
+#endif
+        }
+  }
+  if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1;
+  dark = black;
+  sat = maximum;
+  if (threshold) wavelet_denoise();
+  maximum -= black;
+  for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) {
+    if (dmin > pre_mul[c])
+	dmin = pre_mul[c];
+    if (dmax < pre_mul[c])
+	dmax = pre_mul[c];
+  }
+  if (!highlight) dmax = dmin;
+  FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum;
+#ifdef DCRAW_VERBOSE
+  if (verbose) {
+    fprintf (stderr,
+      _("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat);
+    FORC4 fprintf (stderr, " %f", pre_mul[c]);
+    fputc ('\n', stderr);
+  }
+#endif
+  size = iheight*iwidth;
+  for (i=0; i < size*4; i++) {
+    val = image[0][i];
+    if (!val) continue;
+    val -= black;
+    val *= scale_mul[i & 3];
+    image[0][i] = CLIP(val);
+  }
+  if ((aber[0] != 1 || aber[2] != 1) && colors == 3) {
+#ifdef DCRAW_VERBOSE
+    if (verbose)
+      fprintf (stderr,_("Correcting chromatic aberration...\n"));
+#endif
+    for (c=0; c < 4; c+=2) {
+      if (aber[c] == 1) continue;
+      img = (ushort *) malloc (size * sizeof *img);
+      merror (img, "scale_colors()");
+      for (i=0; i < size; i++)
+	img[i] = image[i][c];
+      for (row=0; row < iheight; row++) {
+	ur = fr = (row - iheight*0.5) * aber[c] + iheight*0.5;
+	if (ur > iheight-2) continue;
+	fr -= ur;
+	for (col=0; col < iwidth; col++) {
+	  uc = fc = (col - iwidth*0.5) * aber[c] + iwidth*0.5;
+	  if (uc > iwidth-2) continue;
+	  fc -= uc;
+	  pix = img + ur*iwidth + uc;
+	  image[row*iwidth+col][c] =
+	    (pix[     0]*(1-fc) + pix[       1]*fc) * (1-fr) +
+	    (pix[iwidth]*(1-fc) + pix[iwidth+1]*fc) * fr;
+	}
+      }
+      free(img);
+    }
+  }
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS,1,2);
+#endif
+}
+
+void CLASS pre_interpolate()
+{
+  ushort (*img)[4];
+  int row, col, c;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE,0,2);
+#endif
+  if (shrink) {
+    if (half_size) {
+      height = iheight;
+      width  = iwidth;
+    } else {
+      img = (ushort (*)[4]) calloc (height*width, sizeof *img);
+      merror (img, "pre_interpolate()");
+      for (row=0; row < height; row++)
+	for (col=0; col < width; col++) {
+	  c = fc(row,col);
+	  img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c];
+	}
+      free (image);
+      image = img;
+      shrink = 0;
+    }
+  }
+  if (filters && colors == 3) {
+    if ((mix_green = four_color_rgb)) colors++;
+    else {
+      for (row = FC(1,0) >> 1; row < height; row+=2)
+	for (col = FC(row,1) & 1; col < width; col+=2)
+	  image[row*width+col][1] = image[row*width+col][3];
+      filters &= ~((filters & 0x55555555) << 1);
+    }
+  }
+  if (half_size) filters = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE,1,2);
+#endif
+}
+
+void CLASS border_interpolate (int border)
+{
+  unsigned row, col, y, x, f, c, sum[8];
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++) {
+      if (col==border && row >= border && row < height-border)
+	col = width-border;
+      memset (sum, 0, sizeof sum);
+      for (y=row-1; y != row+2; y++)
+	for (x=col-1; x != col+2; x++)
+	  if (y < height && x < width) {
+	    f = fc(y,x);
+	    sum[f] += image[y*width+x][f];
+	    sum[f+4]++;
+	  }
+      f = fc(row,col);
+      FORCC if (c != f && sum[c+4])
+	image[row*width+col][c] = sum[c] / sum[c+4];
+    }
+}
+
+void CLASS lin_interpolate()
+{
+  int code[16][16][32], *ip, sum[4];
+  int c, i, x, y, row, col, shift, color;
+  ushort *pix;
+
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Bilinear interpolation...\n"));
+#endif
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,0,3);
+#endif
+  border_interpolate(1);
+  for (row=0; row < 16; row++)
+    for (col=0; col < 16; col++) {
+      ip = code[row][col];
+      memset (sum, 0, sizeof sum);
+      for (y=-1; y <= 1; y++)
+	for (x=-1; x <= 1; x++) {
+	  shift = (y==0) + (x==0);
+	  if (shift == 2) continue;
+	  color = fc(row+y,col+x);
+	  *ip++ = (width*y + x)*4 + color;
+	  *ip++ = shift;
+	  *ip++ = color;
+	  sum[color] += 1 << shift;
+	}
+      FORCC
+	if (c != fc(row,col)) {
+	  *ip++ = c;
+	  *ip++ = 256 / sum[c];
+	}
+    }
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,1,3);
+#endif
+  for (row=1; row < height-1; row++)
+    for (col=1; col < width-1; col++) {
+      pix = image[row*width+col];
+      ip = code[row & 15][col & 15];
+      memset (sum, 0, sizeof sum);
+      for (i=8; i--; ip+=3)
+	sum[ip[2]] += pix[ip[0]] << ip[1];
+      for (i=colors; --i; ip+=2)
+	pix[ip[0]] = sum[ip[0]] * ip[1] >> 8;
+    }
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,2,3);
+#endif
+}
+
+/*
+   This algorithm is officially called:
+
+   "Interpolation using a Threshold-based variable number of gradients"
+
+   described in http://scien.stanford.edu/class/psych221/projects/99/tingchen/algodep/vargra.html
+
+   I've extended the basic idea to work with non-Bayer filter arrays.
+   Gradients are numbered clockwise from NW=0 to W=7.
+ */
+void CLASS vng_interpolate()
+{
+  static const signed char *cp, terms[] = {
+    -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01,
+    -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01,
+    -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03,
+    -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06,
+    -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04,
+    -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01,
+    -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
+    -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11,
+    -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11,
+    -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
+    -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44,
+    -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10,
+    -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04,
+    +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40,
+    +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20,
+    +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08,
+    +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20,
+    +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44,
+    +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60,
+    +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80,
+    +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40,
+    +1,+0,+2,+1,0,0x10
+  }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
+  ushort (*brow[5])[4], *pix;
+  int prow=7, pcol=1, *ip, *code[16][16], gval[8], gmin, gmax, sum[4];
+  int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
+  int g, diff, thold, num, c;
+  lin_interpolate();
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("VNG interpolation...\n"));
+#endif
+
+  if (filters == 1) prow = pcol = 15;
+  ip = (int *) calloc ((prow+1)*(pcol+1), 1280);
+  merror (ip, "vng_interpolate()");
+  for (row=0; row <= prow; row++)		/* Precalculate for VNG */
+    for (col=0; col <= pcol; col++) {
+      code[row][col] = ip;
+      for (cp=terms, t=0; t < 64; t++) {
+	y1 = *cp++;  x1 = *cp++;
+	y2 = *cp++;  x2 = *cp++;
+	weight = *cp++;
+	grads = *cp++;
+	color = fc(row+y1,col+x1);
+	if (fc(row+y2,col+x2) != color) continue;
+	diag = (fc(row,col+1) == color && fc(row+1,col) == color) ? 2:1;
+	if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
+	*ip++ = (y1*width + x1)*4 + color;
+	*ip++ = (y2*width + x2)*4 + color;
+	*ip++ = weight;
+	for (g=0; g < 8; g++)
+	  if (grads & 1<<g) *ip++ = g;
+	*ip++ = -1;
+      }
+      *ip++ = INT_MAX;
+      for (cp=chood, g=0; g < 8; g++) {
+	y = *cp++;  x = *cp++;
+	*ip++ = (y*width + x) * 4;
+	color = fc(row,col);
+	if (fc(row+y,col+x) != color && fc(row+y*2,col+x*2) == color)
+	  *ip++ = (y*width + x) * 8 + color;
+	else
+	  *ip++ = 0;
+      }
+    }
+  brow[4] = (ushort (*)[4]) calloc (width*3, sizeof **brow);
+  merror (brow[4], "vng_interpolate()");
+  for (row=0; row < 3; row++)
+    brow[row] = brow[4] + row*width;
+  for (row=2; row < height-2; row++) {		/* Do VNG interpolation */
+#ifdef LIBRAW_LIBRARY_BUILD
+      if(!((row-2)%256))RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,(row-2)/256+1,((height-3)/256)+1);
+#endif
+    for (col=2; col < width-2; col++) {
+      pix = image[row*width+col];
+      ip = code[row & prow][col & pcol];
+      memset (gval, 0, sizeof gval);
+      while ((g = ip[0]) != INT_MAX) {		/* Calculate gradients */
+	diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
+	gval[ip[3]] += diff;
+	ip += 5;
+	if ((g = ip[-1]) == -1) continue;
+	gval[g] += diff;
+	while ((g = *ip++) != -1)
+	  gval[g] += diff;
+      }
+      ip++;
+      gmin = gmax = gval[0];			/* Choose a threshold */
+      for (g=1; g < 8; g++) {
+	if (gmin > gval[g]) gmin = gval[g];
+	if (gmax < gval[g]) gmax = gval[g];
+      }
+      if (gmax == 0) {
+	memcpy (brow[2][col], pix, sizeof *image);
+	continue;
+      }
+      thold = gmin + (gmax >> 1);
+      memset (sum, 0, sizeof sum);
+      color = fc(row,col);
+      for (num=g=0; g < 8; g++,ip+=2) {		/* Average the neighbors */
+	if (gval[g] <= thold) {
+	  FORCC
+	    if (c == color && ip[1])
+	      sum[c] += (pix[c] + pix[ip[1]]) >> 1;
+	    else
+	      sum[c] += pix[ip[0] + c];
+	  num++;
+	}
+      }
+      FORCC {					/* Save to buffer */
+	t = pix[color];
+	if (c != color)
+	  t += (sum[c] - sum[color]) / num;
+	brow[2][col][c] = CLIP(t);
+      }
+    }
+    if (row > 3)				/* Write buffer to image */
+      memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
+    for (g=0; g < 4; g++)
+      brow[(g-1) & 3] = brow[g];
+  }
+  memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
+  memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image);
+  free (brow[4]);
+  free (code[0][0]);
+}
+
+/*
+   Patterned Pixel Grouping Interpolation by Alain Desbiolles
+*/
+void CLASS ppg_interpolate()
+{
+  int dir[5] = { 1, width, -1, -width, 1 };
+  int row, col, diff[2], guess[2], c, d, i;
+  ushort (*pix)[4];
+
+  border_interpolate(3);
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("PPG interpolation...\n"));
+#endif
+
+/*  Fill in the green layer with gradients and pattern recognition: */
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,0,3);
+#endif
+  for (row=3; row < height-3; row++)
+    for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) {
+      pix = image + row*width+col;
+      for (i=0; (d=dir[i]) > 0; i++) {
+	guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2
+		      - pix[-2*d][c] - pix[2*d][c];
+	diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) +
+		    ABS(pix[ 2*d][c] - pix[ 0][c]) +
+		    ABS(pix[  -d][1] - pix[ d][1]) ) * 3 +
+		  ( ABS(pix[ 3*d][1] - pix[ d][1]) +
+		    ABS(pix[-3*d][1] - pix[-d][1]) ) * 2;
+      }
+      d = dir[i = diff[0] > diff[1]];
+      pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]);
+    }
+/*  Calculate red and blue for each green pixel:		*/
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,1,3);
+#endif
+  for (row=1; row < height-1; row++)
+    for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) {
+      pix = image + row*width+col;
+      for (i=0; (d=dir[i]) > 0; c=2-c, i++)
+	pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1]
+			- pix[-d][1] - pix[d][1]) >> 1);
+    }
+/*  Calculate blue for red pixels and vice versa:		*/
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,2,3);
+#endif
+  for (row=1; row < height-1; row++)
+    for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) {
+      pix = image + row*width+col;
+      for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) {
+	diff[i] = ABS(pix[-d][c] - pix[d][c]) +
+		  ABS(pix[-d][1] - pix[0][1]) +
+		  ABS(pix[ d][1] - pix[0][1]);
+	guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1]
+		 - pix[-d][1] - pix[d][1];
+      }
+      if (diff[0] != diff[1])
+	pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1);
+      else
+	pix[0][c] = CLIP((guess[0]+guess[1]) >> 2);
+    }
+}
+
+/*
+   Adaptive Homogeneity-Directed interpolation is based on
+   the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
+ */
+#define TS 256		/* Tile Size */
+#ifndef _OPENMP
+void CLASS ahd_interpolate()
+{
+  int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
+  ushort (*pix)[4], (*rix)[3];
+  static const int dir[4] = { -1, 1, -TS, TS };
+  unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
+  float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
+  ushort (*rgb)[TS][TS][3];
+   short (*lab)[TS][TS][3], (*lix)[3];
+   char (*homo)[TS][TS], *buffer;
+
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
+#endif
+
+  for (i=0; i < 0x10000; i++) {
+    r = i / 65535.0;
+    cbrt[i] = r > 0.008856 ? pow((double)r,1/3.0) : 7.787*r + 16/116.0;
+  }
+  for (i=0; i < 3; i++)
+    for (j=0; j < colors; j++)
+      for (xyz_cam[i][j] = k=0; k < 3; k++)
+	xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i];
+
+  border_interpolate(5);
+  buffer = (char *) malloc (26*TS*TS);		/* 1664 kB */
+  merror (buffer, "ahd_interpolate()");
+  rgb  = (ushort(*)[TS][TS][3]) buffer;
+  lab  = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
+  homo = (char  (*)[TS][TS])   (buffer + 24*TS*TS);
+
+  for (top=2; top < height-5; top += TS-6)
+  {    
+      
+#ifdef LIBRAW_LIBRARY_BUILD
+      RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,(top-2)/(TS-6),(height-7)/(TS-6)+1);
+#endif
+    for (left=2; left < width-5; left += TS-6) {
+
+/*  Interpolate green horizontally and vertically:		*/
+      for (row = top; row < top+TS && row < height-2; row++) {
+	col = left + (FC(row,left) & 1);
+	for (c = FC(row,col); col < left+TS && col < width-2; col+=2) {
+	  pix = image + row*width+col;
+	  val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2
+		- pix[-2][c] - pix[2][c]) >> 2;
+	  rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]);
+	  val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2
+		- pix[-2*width][c] - pix[2*width][c]) >> 2;
+	  rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]);
+	}
+      }
+/*  Interpolate red and blue, and convert to CIELab:		*/
+      for (d=0; d < 2; d++)
+	for (row=top+1; row < top+TS-1 && row < height-3; row++)
+	  for (col=left+1; col < left+TS-1 && col < width-3; col++) {
+	    pix = image + row*width+col;
+	    rix = &rgb[d][row-top][col-left];
+	    lix = &lab[d][row-top][col-left];
+	    if ((c = 2 - FC(row,col)) == 1) {
+	      c = FC(row+1,col);
+	      val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
+				 - rix[-1][1] - rix[1][1] ) >> 1);
+	      rix[0][2-c] = CLIP(val);
+	      val = pix[0][1] + (( pix[-width][c] + pix[width][c]
+				 - rix[-TS][1] - rix[TS][1] ) >> 1);
+	    } else
+	      val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c]
+				 + pix[+width-1][c] + pix[+width+1][c]
+				 - rix[-TS-1][1] - rix[-TS+1][1]
+				 - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
+	    rix[0][c] = CLIP(val);
+	    c = FC(row,col);
+	    rix[0][c] = pix[0][c];
+	    xyz[0] = xyz[1] = xyz[2] = 0.5;
+	    FORCC {
+	      xyz[0] += xyz_cam[0][c] * rix[0][c];
+	      xyz[1] += xyz_cam[1][c] * rix[0][c];
+	      xyz[2] += xyz_cam[2][c] * rix[0][c];
+	    }
+	    xyz[0] = cbrt[CLIP((int) xyz[0])];
+	    xyz[1] = cbrt[CLIP((int) xyz[1])];
+	    xyz[2] = cbrt[CLIP((int) xyz[2])];
+	    lix[0][0] = 64 * (116 * xyz[1] - 16);
+	    lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]);
+	    lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]);
+	  }
+/*  Build homogeneity maps from the CIELab images:		*/
+      memset (homo, 0, 2*TS*TS);
+      for (row=top+2; row < top+TS-2 && row < height-4; row++) {
+	tr = row-top;
+	for (col=left+2; col < left+TS-2 && col < width-4; col++) {
+	  tc = col-left;
+	  for (d=0; d < 2; d++) {
+	    lix = &lab[d][tr][tc];
+	    for (i=0; i < 4; i++) {
+	       ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]);
+	      abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1])
+			   + SQR(lix[0][2]-lix[dir[i]][2]);
+	    }
+	  }
+	  leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
+		     MAX(ldiff[1][2],ldiff[1][3]));
+	  abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
+		      MAX(abdiff[1][2],abdiff[1][3]));
+	  for (d=0; d < 2; d++)
+	    for (i=0; i < 4; i++)
+	      if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
+		homo[d][tr][tc]++;
+	}
+      }
+/*  Combine the most homogenous pixels for the final result:	*/
+      for (row=top+3; row < top+TS-3 && row < height-5; row++) {
+	tr = row-top;
+	for (col=left+3; col < left+TS-3 && col < width-5; col++) {
+	  tc = col-left;
+	  for (d=0; d < 2; d++)
+	    for (hm[d]=0, i=tr-1; i <= tr+1; i++)
+	      for (j=tc-1; j <= tc+1; j++)
+		hm[d] += homo[d][i][j];
+	  if (hm[0] != hm[1])
+	    FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c];
+	  else
+	    FORC3 image[row*width+col][c] =
+		(rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
+	}
+      }
+    }
+  }
+  free (buffer);
+}
+#else
+void CLASS ahd_interpolate()
+{
+  int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
+  ushort (*pix)[4], (*rix)[3];
+  static const int dir[4] = { -1, 1, -TS, TS };
+  unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
+  float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
+  ushort (*rgb)[TS][TS][3];
+  short (*lab)[TS][TS][3], (*lix)[3];
+  char (*homo)[TS][TS], *buffer;
+
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
+#endif
+
+  for (i=0; i < 0x10000; i++) {
+    r = i / 65535.0;
+    cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0;
+  }
+  for (i=0; i < 3; i++)
+    for (j=0; j < colors; j++)
+      for (xyz_cam[i][j] = k=0; k < 3; k++)
+	xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i];
+
+  border_interpolate(5);
+
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp parallel private(buffer,rgb,lab,homo,top,left,row,c,col,pix,val,d,rix,xyz,lix,tc,tr,ldiff,abdiff,leps,abeps,hm,i,j) firstprivate(cbrt) shared(xyz_cam)
+#endif
+  {
+    buffer = (char *) malloc (26*TS*TS);		/* 1664 kB */
+    merror (buffer, "ahd_interpolate()");
+    rgb  = (ushort(*)[TS][TS][3]) buffer;
+    lab  = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
+    homo = (char  (*)[TS][TS])   (buffer + 24*TS*TS);
+
+#pragma omp for schedule(dynamic)
+    for (top=2; top < height-5; top += TS-6){
+#ifdef LIBRAW_LIBRARY_BUILD
+        RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,(top-2)/(TS-6)+1,(height-7)/(TS-6)+1);
+#endif
+      for (left=2; left < width-5; left += TS-6) {
+
+  /*  Interpolate green horizontally and vertically:		*/
+        for (row = top; row < top+TS && row < height-2; row++) {
+          col = left + (FC(row,left) & 1);
+          for (c = FC(row,col); col < left+TS && col < width-2; col+=2) {
+            pix = image + row*width+col;
+            val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2
+                  - pix[-2][c] - pix[2][c]) >> 2;
+            rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]);
+            val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2
+                  - pix[-2*width][c] - pix[2*width][c]) >> 2;
+            rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]);
+          }
+        }
+  /*  Interpolate red and blue, and convert to CIELab:		*/
+        for (d=0; d < 2; d++)
+          for (row=top+1; row < top+TS-1 && row < height-3; row++)
+            for (col=left+1; col < left+TS-1 && col < width-3; col++) {
+              pix = image + row*width+col;
+              rix = &rgb[d][row-top][col-left];
+              lix = &lab[d][row-top][col-left];
+              if ((c = 2 - FC(row,col)) == 1) {
+                c = FC(row+1,col);
+                val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
+                                   - rix[-1][1] - rix[1][1] ) >> 1);
+                rix[0][2-c] = CLIP(val);
+                val = pix[0][1] + (( pix[-width][c] + pix[width][c]
+                                   - rix[-TS][1] - rix[TS][1] ) >> 1);
+              } else
+                val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c]
+                                   + pix[+width-1][c] + pix[+width+1][c]
+                                   - rix[-TS-1][1] - rix[-TS+1][1]
+                                   - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
+              rix[0][c] = CLIP(val);
+              c = FC(row,col);
+              rix[0][c] = pix[0][c];
+              xyz[0] = xyz[1] = xyz[2] = 0.5;
+              FORCC {
+                xyz[0] += xyz_cam[0][c] * rix[0][c];
+                xyz[1] += xyz_cam[1][c] * rix[0][c];
+                xyz[2] += xyz_cam[2][c] * rix[0][c];
+              }
+              xyz[0] = cbrt[CLIP((int) xyz[0])];
+              xyz[1] = cbrt[CLIP((int) xyz[1])];
+              xyz[2] = cbrt[CLIP((int) xyz[2])];
+              lix[0][0] = 64 * (116 * xyz[1] - 16);
+              lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]);
+              lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]);
+            }
+  /*  Build homogeneity maps from the CIELab images:		*/
+        memset (homo, 0, 2*TS*TS);
+        for (row=top+2; row < top+TS-2 && row < height-4; row++) {
+          tr = row-top;
+          for (col=left+2; col < left+TS-2 && col < width-4; col++) {
+            tc = col-left;
+            for (d=0; d < 2; d++) {
+              lix = &lab[d][tr][tc];
+              for (i=0; i < 4; i++) {
+                 ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]);
+                abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1])
+                             + SQR(lix[0][2]-lix[dir[i]][2]);
+              }
+            }
+            leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
+                       MAX(ldiff[1][2],ldiff[1][3]));
+            abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
+                        MAX(abdiff[1][2],abdiff[1][3]));
+            for (d=0; d < 2; d++)
+              for (i=0; i < 4; i++)
+                if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
+                  homo[d][tr][tc]++;
+          }
+        }
+  /*  Combine the most homogenous pixels for the final result:	*/
+        for (row=top+3; row < top+TS-3 && row < height-5; row++) {
+          tr = row-top;
+          for (col=left+3; col < left+TS-3 && col < width-5; col++) {
+            tc = col-left;
+            for (d=0; d < 2; d++)
+              for (hm[d]=0, i=tr-1; i <= tr+1; i++)
+                for (j=tc-1; j <= tc+1; j++)
+                  hm[d] += homo[d][i][j];
+            if (hm[0] != hm[1])
+              FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c];
+            else
+              FORC3 image[row*width+col][c] =
+                  (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
+          }
+        }
+      }
+    }
+    free (buffer);
+  }
+}
+
+#endif
+#undef TS
+
+void CLASS median_filter()
+{
+  ushort (*pix)[4];
+  int pass, c, i, j, k, med[9];
+  static const uchar opt[] =	/* Optimal 9-element median search */
+  { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8,
+    0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 };
+
+  for (pass=1; pass <= med_passes; pass++) {
+#ifdef LIBRAW_LIBRARY_BUILD
+      RUN_CALLBACK(LIBRAW_PROGRESS_MEDIAN_FILTER,pass-1,med_passes);
+#endif
+#ifdef DCRAW_VERBOSE
+    if (verbose)
+      fprintf (stderr,_("Median filter pass %d...\n"), pass);
+#endif
+    for (c=0; c < 3; c+=2) {
+      for (pix = image; pix < image+width*height; pix++)
+	pix[0][3] = pix[0][c];
+      for (pix = image+width; pix < image+width*(height-1); pix++) {
+	if ((pix-image+1) % width < 2) continue;
+	for (k=0, i = -width; i <= width; i += width)
+	  for (j = i-1; j <= i+1; j++)
+	    med[k++] = pix[j][3] - pix[j][1];
+	for (i=0; i < sizeof opt; i+=2)
+	  if     (med[opt[i]] > med[opt[i+1]])
+	    SWAP (med[opt[i]] , med[opt[i+1]]);
+	pix[0][c] = CLIP(med[4] + pix[0][1]);
+      }
+    }
+  }
+}
+
+void CLASS blend_highlights()
+{
+  int clip=INT_MAX, row, col, c, i, j;
+  static const float trans[2][4][4] =
+  { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } },
+    { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
+  static const float itrans[2][4][4] =
+  { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } },
+    { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
+  float cam[2][4], lab[2][4], sum[2], chratio;
+
+  if ((unsigned) (colors-3) > 1) return;
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Blending highlights...\n"));
+#endif
+  FORCC if (clip > (i = 65535*pre_mul[c])) clip = i;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,0,2);
+#endif
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++) {
+      FORCC if (image[row*width+col][c] > clip) break;
+      if (c == colors) continue;
+      FORCC {
+	cam[0][c] = image[row*width+col][c];
+	cam[1][c] = MIN(cam[0][c],clip);
+      }
+      for (i=0; i < 2; i++) {
+	FORCC for (lab[i][c]=j=0; j < colors; j++)
+	  lab[i][c] += trans[colors-3][c][j] * cam[i][j];
+	for (sum[i]=0,c=1; c < colors; c++)
+	  sum[i] += SQR(lab[i][c]);
+      }
+      chratio = sqrt(sum[1]/sum[0]);
+      for (c=1; c < colors; c++)
+	lab[0][c] *= chratio;
+      FORCC for (cam[0][c]=j=0; j < colors; j++)
+	cam[0][c] += itrans[colors-3][c][j] * lab[0][j];
+      FORCC image[row*width+col][c] = cam[0][c] / colors;
+    }
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,1,2);
+#endif
+}
+
+#define SCALE (4 >> shrink)
+void CLASS recover_highlights()
+{
+  float *map, sum, wgt, grow;
+  int hsat[4], count, spread, change, val, i;
+  unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x;
+  ushort *pixel;
+  static const signed char dir[8][2] =
+    { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} };
+
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Rebuilding highlights...\n"));
+#endif
+
+  grow = pow (2.0, 4.0-highlight);
+  FORCC hsat[c] = 32000 * pre_mul[c];
+  for (kc=0, c=1; c < colors; c++)
+    if (pre_mul[kc] < pre_mul[c]) kc = c;
+  high = height / SCALE;
+  wide =  width / SCALE;
+  map = (float *) calloc (high*wide, sizeof *map);
+  merror (map, "recover_highlights()");
+  FORCC if (c != kc) {
+#ifdef LIBRAW_LIBRARY_BUILD
+      RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,c-1,colors-1);
+#endif
+    memset (map, 0, high*wide*sizeof *map);
+    for (mrow=0; mrow < high; mrow++)
+      for (mcol=0; mcol < wide; mcol++) {
+	sum = wgt = count = 0;
+	for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
+	  for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
+	    pixel = image[row*width+col];
+	    if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) {
+	      sum += pixel[c];
+	      wgt += pixel[kc];
+	      count++;
+	    }
+	  }
+	if (count == SCALE*SCALE)
+	  map[mrow*wide+mcol] = sum / wgt;
+      }
+    for (spread = 32/grow; spread--; ) {
+      for (mrow=0; mrow < high; mrow++)
+	for (mcol=0; mcol < wide; mcol++) {
+	  if (map[mrow*wide+mcol]) continue;
+	  sum = count = 0;
+	  for (d=0; d < 8; d++) {
+	    y = mrow + dir[d][0];
+	    x = mcol + dir[d][1];
+	    if (y < high && x < wide && map[y*wide+x] > 0) {
+	      sum  += (1 + (d & 1)) * map[y*wide+x];
+	      count += 1 + (d & 1);
+	    }
+	  }
+	  if (count > 3)
+	    map[mrow*wide+mcol] = - (sum+grow) / (count+grow);
+	}
+      for (change=i=0; i < high*wide; i++)
+	if (map[i] < 0) {
+	  map[i] = -map[i];
+	  change = 1;
+	}
+      if (!change) break;
+    }
+    for (i=0; i < high*wide; i++)
+      if (map[i] == 0) map[i] = 1;
+    for (mrow=0; mrow < high; mrow++)
+      for (mcol=0; mcol < wide; mcol++) {
+	for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
+	  for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
+	    pixel = image[row*width+col];
+	    if (pixel[c] / hsat[c] > 1) {
+	      val = pixel[kc] * map[mrow*wide+mcol];
+	      if (pixel[c] < val) pixel[c] = CLIP(val);
+	    }
+	  }
+      }
+  }
+  free (map);
+}
+#undef SCALE
+
+void CLASS tiff_get (unsigned base,
+	unsigned *tag, unsigned *type, unsigned *len, unsigned *save)
+{
+  *tag  = get2();
+  *type = get2();
+  *len  = get4();
+  *save = ftell(ifp) + 4;
+  if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4)
+    fseek (ifp, get4()+base, SEEK_SET);
+}
+
+void CLASS parse_thumb_note (int base, unsigned toff, unsigned tlen)
+{
+  unsigned entries, tag, type, len, save;
+
+  entries = get2();
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    if (tag == toff) thumb_offset = get4()+base;
+    if (tag == tlen) thumb_length = get4();
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS parse_makernote (int base, int uptag)
+{
+  static const uchar xlat[2][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 },
+  { 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 } };
+  unsigned offset=0, entries, tag, type, len, save, c;
+  unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0};
+  uchar buf97[324], ci, cj, ck;
+  short sorder=order;
+  char buf[10];
+/*
+   The MakerNote might have its own TIFF header (possibly with
+   its own byte-order!), or it might just be a table.
+ */
+  fread (buf, 1, 10, ifp);
+  if (!strncmp (buf,"KDK" ,3) ||	/* these aren't TIFF tables */
+      !strncmp (buf,"VER" ,3) ||
+      !strncmp (buf,"IIII",4) ||
+      !strncmp (buf,"MMMM",4)) return;
+  if (!strncmp (buf,"KC"  ,2) ||	/* Konica KD-400Z, KD-510Z */
+      !strncmp (buf,"MLY" ,3)) {	/* Minolta DiMAGE G series */
+    order = 0x4d4d;
+    while ((i=ftell(ifp)) < data_offset && i < 16384) {
+      wb[0] = wb[2];  wb[2] = wb[1];  wb[1] = wb[3];
+      wb[3] = get2();
+      if (wb[1] == 256 && wb[3] == 256 &&
+	  wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640)
+	FORC4 cam_mul[c] = wb[c];
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    goto quit;
+  }
+  if (!strcmp (buf,"Nikon")) {
+    base = ftell(ifp);
+    order = get2();
+    if (get2() != 42) goto quit;
+    offset = get4();
+    fseek (ifp, offset-8, SEEK_CUR);
+  } else if (!strcmp (buf,"OLYMPUS")) {
+    base = ftell(ifp)-10;
+    fseek (ifp, -2, SEEK_CUR);
+    order = get2();  get2();
+  } else if (!strncmp (buf,"FUJIFILM",8) ||
+	     !strncmp (buf,"SONY",4) ||
+	     !strcmp  (buf,"Panasonic")) {
+    order = 0x4949;
+    fseek (ifp,  2, SEEK_CUR);
+  } else if (!strcmp (buf,"OLYMP") ||
+	     !strcmp (buf,"LEICA") ||
+	     !strcmp (buf,"Ricoh") ||
+	     !strcmp (buf,"EPSON"))
+    fseek (ifp, -2, SEEK_CUR);
+  else if (!strcmp (buf,"AOC") ||
+	   !strcmp (buf,"QVC"))
+    fseek (ifp, -4, SEEK_CUR);
+  else fseek (ifp, -10, SEEK_CUR);
+
+  entries = get2();
+  if (entries > 1000) return;
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    tag |= uptag << 16;
+    if (tag == 2 && strstr(make,"NIKON"))
+      iso_speed = (get2(),get2());
+    if (tag == 4 && len > 26 && len < 35) {
+      if ((i=(get4(),get2())) != 0x7fff && !iso_speed)
+	iso_speed = 50 * pow (2, i/32.0 - 4);
+      if ((i=(get2(),get2())) != 0x7fff && !aperture)
+	aperture = pow (2, i/64.0);
+      if ((i=get2()) != 0xffff && !shutter)
+	shutter = pow (2, (short) i/-32.0);
+      wbi = (get2(),get2());
+      shot_order = (get2(),get2());
+    }
+    if (tag == 7 && type == 2 && len > 20)
+      fgets (model2, 64, ifp);
+    if (tag == 8 && type == 4)
+      shot_order = get4();
+    if (tag == 9 && !strcmp(make,"Canon"))
+      fread (artist, 64, 1, ifp);
+    if (tag == 0xc && len == 4) {
+      cam_mul[0] = getreal(type);
+      cam_mul[2] = getreal(type);
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if (tag == 0x10 && type == 4)
+      unique_id = get4();
+    if (tag == 0x11 && is_raw && !strncmp(make,"NIKON",5)) {
+      fseek (ifp, get4()+base, SEEK_SET);
+      parse_tiff_ifd (base);
+    }
+    if (tag == 0x14 && len == 2560 && type == 7) {
+      fseek (ifp, 1248, SEEK_CUR);
+      goto get2_256;
+    }
+    if (tag == 0x15 && type == 2 && is_raw)
+      fread (model, 64, 1, ifp);
+    if (strstr(make,"PENTAX")) {
+      if (tag == 0x1b) tag = 0x1018;
+      if (tag == 0x1c) tag = 0x1017;
+    }
+    if (tag == 0x1d)
+      while ((c = fgetc(ifp)) && c != EOF)
+	serial = serial*10 + (isdigit(c) ? c - '0' : c % 10);
+    if (tag == 0x81 && type == 4) {
+      data_offset = get4();
+      fseek (ifp, data_offset + 41, SEEK_SET);
+      raw_height = get2() * 2;
+      raw_width  = get2();
+      filters = 0x61616161;
+    }
+    if (tag == 0x29 && type == 1) {
+      c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0;
+      fseek (ifp, 8 + c*32, SEEK_CUR);
+      FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4();
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if ((tag == 0x81  && type == 7) ||
+	(tag == 0x100 && type == 7) ||
+	(tag == 0x280 && type == 1)) {
+      thumb_offset = ftell(ifp);
+      thumb_length = len;
+    }
+    if (tag == 0x88 && type == 4 && (thumb_offset = get4()))
+      thumb_offset += base;
+    if (tag == 0x89 && type == 4)
+      thumb_length = get4();
+    if (tag == 0x8c || tag == 0x96)
+      meta_offset = ftell(ifp);
+    if (tag == 0x97) {
+      for (i=0; i < 4; i++)
+	ver97 = ver97 * 10 + fgetc(ifp)-'0';
+      switch (ver97) {
+	case 100:
+	  fseek (ifp, 68, SEEK_CUR);
+	  FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+          color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	  break;
+	case 102:
+	  fseek (ifp, 6, SEEK_CUR);
+	  goto get2_rggb;
+	case 103:
+	  fseek (ifp, 16, SEEK_CUR);
+	  FORC4 cam_mul[c] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+          color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      }
+      if (ver97 >= 200) {
+	if (ver97 != 205) fseek (ifp, 280, SEEK_CUR);
+	fread (buf97, 324, 1, ifp);
+      }
+    }
+    if (tag == 0xa4 && type == 3) {
+      fseek (ifp, wbi*48, SEEK_CUR);
+      FORC3 cam_mul[c] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if (tag == 0xa7 && (unsigned) (ver97-200) < 12 && !cam_mul[0]) {
+      ci = xlat[0][serial & 0xff];
+      cj = xlat[1][fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp)];
+      ck = 0x60;
+      for (i=0; i < 324; i++)
+	buf97[i] ^= (cj += ci * ck++);
+      i = "66666>666;6A"[ver97-200] - '0';
+      FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] =
+	sget2 (buf97 + (i & -2) + c*2);
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if (tag == 0x200 && len == 3)
+      shot_order = (get4(),get4());
+    if (tag == 0x200 && len == 4)
+      black = (get2()+get2()+get2()+get2())/4;
+    if (tag == 0x201 && len == 4)
+      goto get2_rggb;
+    if (tag == 0x220 && len == 53) {
+      fseek (ifp, 14, SEEK_CUR);
+      pentax_tree();
+    }
+    if (tag == 0x401 && len == 4) {
+      black = (get4()+get4()+get4()+get4())/4;
+    }
+    if (tag == 0xe01) {		/* Nikon Capture Note */
+      type = order;
+      order = 0x4949;
+      fseek (ifp, 22, SEEK_CUR);
+      for (offset=22; offset+22 < len; offset += 22+i) {
+	tag = get4();
+	fseek (ifp, 14, SEEK_CUR);
+	i = get4()-4;
+	if (tag == 0x76a43207) flip = get2();
+	else fseek (ifp, i, SEEK_CUR);
+      }
+      order = type;
+    }
+    if (tag == 0xe80 && len == 256 && type == 7) {
+      fseek (ifp, 48, SEEK_CUR);
+      cam_mul[0] = get2() * 508 * 1.078 / 0x10000;
+      cam_mul[2] = get2() * 382 * 1.173 / 0x10000;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if (tag == 0xf00 && type == 7) {
+      if (len == 614)
+	fseek (ifp, 176, SEEK_CUR);
+      else if (len == 734 || len == 1502)
+	fseek (ifp, 148, SEEK_CUR);
+      else goto next;
+      goto get2_256;
+    }
+    if ((tag == 0x1011 && len == 9) || tag == 0x20400200)
+        {
+      for (i=0; i < 3; i++)
+	FORC3 cmatrix[i][c] = ((short) get2()) / 256.0;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cmatrix_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+        }
+    if ((tag == 0x1012 || tag == 0x20400600) && len == 4)
+      for (black = i=0; i < 4; i++)
+	black += get2() << 2;
+    if (tag == 0x1017 || tag == 0x20400100)
+        {
+      cam_mul[0] = get2() / 256.0;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+        }
+    if (tag == 0x1018 || tag == 0x20400100)
+        {
+      cam_mul[2] = get2() / 256.0;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+        }
+    if (tag == 0x2011 && len == 2) {
+get2_256:
+      order = 0x4d4d;
+      cam_mul[0] = get2() / 256.0;
+      cam_mul[2] = get2() / 256.0;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if ((tag | 0x70) == 0x2070 && type == 4)
+      fseek (ifp, get4()+base, SEEK_SET);
+    if (tag == 0x2010 && type != 7)
+      load_raw = &CLASS olympus_e410_load_raw;
+    if (tag == 0x2020)
+      parse_thumb_note (base, 257, 258);
+    if (tag == 0x2040)
+      parse_makernote (base, 0x2040);
+    if (tag == 0xb028) {
+      fseek (ifp, get4(), SEEK_SET);
+      parse_thumb_note (base, 136, 137);
+    }
+    if (tag == 0x4001 && len > 500) {
+      i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126;
+      fseek (ifp, i, SEEK_CUR);
+get2_rggb:
+      FORC4 cam_mul[c ^ (c >> 1)] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      fseek (ifp, 22, SEEK_CUR);
+      FORC4 sraw_mul[c ^ (c >> 1)] = get2();
+    }
+next:
+    fseek (ifp, save, SEEK_SET);
+  }
+quit:
+  order = sorder;
+}
+
+/*
+   Since the TIFF DateTime string has no timezone information,
+   assume that the camera's clock was set to Universal Time.
+ */
+void CLASS get_timestamp (int reversed)
+{
+  struct tm t;
+  char str[20];
+  int i;
+
+  str[19] = 0;
+  if (reversed)
+    for (i=19; i--; ) str[i] = fgetc(ifp);
+  else
+    fread (str, 19, 1, ifp);
+  memset (&t, 0, sizeof t);
+  if (sscanf (str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
+	&t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
+    return;
+  t.tm_year -= 1900;
+  t.tm_mon -= 1;
+  if (mktime(&t) > 0)
+    timestamp = mktime(&t);
+}
+
+void CLASS parse_exif (int base)
+{
+  unsigned kodak, entries, tag, type, len, save, c;
+  double expo;
+
+  kodak = !strncmp(make,"EASTMAN",7);
+  entries = get2();
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    switch (tag) {
+      case 33434:  shutter = getreal(type);		break;
+      case 33437:  aperture = getreal(type);		break;
+      case 34855:  iso_speed = get2();			break;
+      case 36867:
+      case 36868:  get_timestamp(0);			break;
+      case 37377:  if ((expo = -getreal(type)) < 128)
+		     shutter = pow (2, expo);		break;
+      case 37378:  aperture = pow (2, getreal(type)/2);	break;
+      case 37386:  focal_len = getreal(type);		break;
+      case 37500:  parse_makernote (base, 0);		break;
+      case 40962:  if (kodak) raw_width  = get4();	break;
+      case 40963:  if (kodak) raw_height = get4();	break;
+      case 41730:
+	if (get4() == 0x20002)
+	  for (exif_cfa=c=0; c < 8; c+=2)
+	    exif_cfa |= fgetc(ifp) * 0x01010101 << c;
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS parse_gps (int base)
+{
+  unsigned entries, tag, type, len, save, c;
+
+  entries = get2();
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    switch (tag) {
+      case 1: case 3: case 5:
+	gpsdata[29+tag/2] = getc(ifp);			break;
+      case 2: case 4: case 7:
+	FORC(6) gpsdata[tag/3*6+c] = get4();		break;
+      case 6:
+	FORC(2) gpsdata[18+c] = get4();			break;
+      case 18: case 29:
+	fgets ((char *) (gpsdata+14+tag/3), MIN(len,12), ifp);
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS romm_coeff (float romm_cam[3][3])
+{
+  static const float rgb_romm[3][3] =	/* ROMM == Kodak ProPhoto */
+  { {  2.034193, -0.727420, -0.306766 },
+    { -0.228811,  1.231729, -0.002922 },
+    { -0.008565, -0.153273,  1.161839 } };
+  int i, j, k;
+
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      for (cmatrix[i][j] = k=0; k < 3; k++)
+	cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j];
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.cmatrix_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+}
+
+void CLASS parse_mos (int offset)
+{
+  char data[40];
+  int skip, from, i, c, neut[4], planes=0, frot=0;
+  static const char *mod[] =
+  { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22",
+    "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65",
+    "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7" };
+  float romm_cam[3][3];
+
+  fseek (ifp, offset, SEEK_SET);
+  while (1) {
+    if (get4() != 0x504b5453) break;
+    get4();
+    fread (data, 1, 40, ifp);
+    skip = get4();
+    from = ftell(ifp);
+    if (!strcmp(data,"JPEG_preview_data")) {
+      thumb_offset = from;
+      thumb_length = skip;
+    }
+    if (!strcmp(data,"icc_camera_profile")) {
+      profile_offset = from;
+      profile_length = skip;
+    }
+    if (!strcmp(data,"ShootObj_back_type")) {
+      fscanf (ifp, "%d", &i);
+      if ((unsigned) i < sizeof mod / sizeof (*mod))
+	strcpy (model, mod[i]);
+    }
+    if (!strcmp(data,"icc_camera_to_tone_matrix")) {
+      for (i=0; i < 9; i++)
+	romm_cam[0][i] = int_to_float(get4());
+      romm_coeff (romm_cam);
+    }
+    if (!strcmp(data,"CaptProf_color_matrix")) {
+      for (i=0; i < 9; i++)
+	fscanf (ifp, "%f", &romm_cam[0][i]);
+      romm_coeff (romm_cam);
+    }
+    if (!strcmp(data,"CaptProf_number_of_planes"))
+      fscanf (ifp, "%d", &planes);
+    if (!strcmp(data,"CaptProf_raw_data_rotation"))
+      fscanf (ifp, "%d", &flip);
+    if (!strcmp(data,"CaptProf_mosaic_pattern"))
+      FORC4 {
+	fscanf (ifp, "%d", &i);
+	if (i == 1) frot = c ^ (c >> 1);
+      }
+    if (!strcmp(data,"ImgProf_rotation_angle")) {
+      fscanf (ifp, "%d", &i);
+      flip = i - flip;
+    }
+    if (!strcmp(data,"NeutObj_neutrals") && !cam_mul[0]) {
+      FORC4 fscanf (ifp, "%d", neut+c);
+      FORC3 cam_mul[c] = (float) neut[0] / neut[c+1];
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    parse_mos (from);
+    fseek (ifp, skip+from, SEEK_SET);
+  }
+  if (planes)
+    filters = (planes == 1) * 0x01010101 *
+	(uchar) "\x94\x61\x16\x49"[(flip/90 + frot) & 3];
+}
+
+void CLASS linear_table (unsigned len)
+{
+  int i;
+  if (len > 0x1000) len = 0x1000;
+  read_shorts (curve, len);
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+  for (i=len; i < 0x1000; i++)
+    curve[i] = curve[i-1];
+  maximum = curve[0xfff];
+}
+
+void CLASS parse_kodak_ifd (int base)
+{
+  unsigned entries, tag, type, len, save;
+  int i, c, wbi=-2, wbtemp=6500;
+  float mul[3], num;
+
+  entries = get2();
+  if (entries > 1024) return;
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    if (tag == 1020) wbi = getint(type);
+    if (tag == 1021 && len == 72) {		/* WB set in software */
+      fseek (ifp, 40, SEEK_CUR);
+      FORC3 cam_mul[c] = 2048.0 / get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      wbi = -2;
+    }
+    if (tag == 2118) wbtemp = getint(type);
+    if (tag == 2130 + wbi)
+      FORC3 mul[c] = getreal(type);
+    if (tag == 2140 + wbi && wbi >= 0)
+        {
+      FORC3 {
+	for (num=i=0; i < 4; i++)
+	  num += getreal(type) * pow (wbtemp/100.0, i);
+	cam_mul[c] = 2048 / (num * mul[c]);
+      }
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+        }
+    if (tag == 2317) linear_table (len);
+    if (tag == 6020) iso_speed = getint(type);
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+int CLASS parse_tiff_ifd (int base)
+{
+  unsigned entries, tag, type, len, plen=16, save;
+  int ifd, use_cm=0, cfa, i, j, c, ima_len=0;
+  char software[64], *cbuf, *cp;
+  uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256];
+  double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num;
+  double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 };
+  unsigned sony_curve[] = { 0,0,0,0,0,4095 };
+  unsigned *buf, sony_offset=0, sony_length=0, sony_key=0;
+  struct jhead jh;
+  FILE *sfp;
+
+  if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0])
+    return 1;
+  ifd = tiff_nifds++;
+  for (j=0; j < 4; j++)
+    for (i=0; i < 4; i++)
+      cc[j][i] = i == j;
+  entries = get2();
+  if (entries > 512) return 1;
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    switch (tag) {
+      case 17: case 18:
+	if (type == 3 && len == 1)
+            {
+	  cam_mul[(tag-17)*2] = get2() / 256.0;
+#ifdef LIBRAW_LIBRARY_BUILD
+          color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+            }
+	break;
+      case 23:
+	if (type == 3) iso_speed = get2();
+	break;
+      case 36: case 37: case 38:
+	cam_mul[tag-0x24] = get2();
+	break;
+      case 39:
+	if (len < 50 || cam_mul[0]) break;
+	fseek (ifp, 12, SEEK_CUR);
+	FORC3 cam_mul[c] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 46:
+	if (type != 7 || fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) break;
+	thumb_offset = ftell(ifp) - 2;
+	thumb_length = len;
+	break;
+      case 2: case 256:			/* ImageWidth */
+	tiff_ifd[ifd].t_width = getint(type);
+	break;
+      case 3: case 257:			/* ImageHeight */
+	tiff_ifd[ifd].t_height = getint(type);
+	break;
+      case 258:				/* BitsPerSample */
+	tiff_ifd[ifd].samples = len & 7;
+	tiff_ifd[ifd].bps = get2();
+	break;
+      case 259:				/* Compression */
+	tiff_ifd[ifd].comp = get2();
+	break;
+      case 262:				/* PhotometricInterpretation */
+	tiff_ifd[ifd].phint = get2();
+	break;
+      case 270:				/* ImageDescription */
+	fread (desc, 512, 1, ifp);
+	break;
+      case 271:				/* Make */
+	fgets (make, 64, ifp);
+	break;
+      case 272:				/* Model */
+	fgets (model, 64, ifp);
+	break;
+      case 280:				/* Panasonic RW2 offset */
+	if (type != 4) break;
+	load_raw = &CLASS panasonic_load_raw;
+	load_flags = 0x2008;
+      case 273:				/* StripOffset */
+      case 513:
+	tiff_ifd[ifd].offset = get4()+base;
+	if (!tiff_ifd[ifd].bps) {
+	  fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET);
+	  if (ljpeg_start (&jh, 1)) {
+	    tiff_ifd[ifd].comp    = 6;
+	    tiff_ifd[ifd].t_width   = jh.wide << (jh.clrs == 2);
+	    tiff_ifd[ifd].t_height  = jh.high;
+	    tiff_ifd[ifd].bps     = jh.bits;
+	    tiff_ifd[ifd].samples = jh.clrs;
+	  }
+	}
+	break;
+      case 274:				/* Orientation */
+	tiff_ifd[ifd].t_flip = "50132467"[get2() & 7]-'0';
+	break;
+      case 277:				/* SamplesPerPixel */
+	tiff_ifd[ifd].samples = getint(type) & 7;
+	break;
+      case 279:				/* StripByteCounts */
+      case 514:
+	tiff_ifd[ifd].bytes = get4();
+	break;
+      case 305:  case 11:		/* Software */
+	fgets (software, 64, ifp);
+	if (!strncmp(software,"Adobe",5) ||
+	    !strncmp(software,"dcraw",5) ||
+	    !strncmp(software,"UFRaw",5) ||
+	    !strncmp(software,"Bibble",6) ||
+	    !strncmp(software,"Nikon Scan",10) ||
+	    !strcmp (software,"Digital Photo Professional"))
+	  is_raw = 0;
+	break;
+      case 306:				/* DateTime */
+	get_timestamp(0);
+	break;
+      case 315:				/* Artist */
+	fread (artist, 64, 1, ifp);
+	break;
+      case 322:				/* TileWidth */
+	tile_width = getint(type);
+	break;
+      case 323:				/* TileLength */
+	tile_length = getint(type);
+	break;
+      case 324:				/* TileOffsets */
+	tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4();
+	if (len == 4) {
+	  load_raw = &CLASS sinar_4shot_load_raw;
+	  is_raw = 5;
+	}
+	break;
+      case 330:				/* SubIFDs */
+	if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].t_width == 3872) {
+	  load_raw = &CLASS sony_arw_load_raw;
+	  data_offset = get4()+base;
+	  ifd++;  break;
+	}
+	while (len--) {
+	  i = ftell(ifp);
+	  fseek (ifp, get4()+base, SEEK_SET);
+	  if (parse_tiff_ifd (base)) break;
+	  fseek (ifp, i+4, SEEK_SET);
+	}
+	break;
+      case 400:
+	strcpy (make, "Sarnoff");
+	maximum = 0xfff;
+	break;
+      case 28688:
+	FORC4 sony_curve[c+1] = get2() >> 2 & 0xfff;
+	for (i=0; i < 5; i++)
+	  for (j = sony_curve[i]+1; j <= sony_curve[i+1]; j++)
+	    curve[j] = curve[j-1] + (1 << i);
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 29184: sony_offset = get4();  break;
+      case 29185: sony_length = get4();  break;
+      case 29217: sony_key    = get4();  break;
+      case 29264:
+	parse_minolta (ftell(ifp));
+	raw_width = 0;
+	break;
+      case 29443:
+	FORC4 cam_mul[c ^ (c < 2)] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 29459:
+	FORC4 cam_mul[c ^ (c >> 1)] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 33405:			/* Model2 */
+	fgets (model2, 64, ifp);
+	break;
+      case 33422:			/* CFAPattern */
+      case 64777:			/* Kodak P-series */
+	if ((plen=len) > 16) plen = 16;
+	fread (cfa_pat, 1, plen, ifp);
+	for (colors=cfa=i=0; i < plen; i++) {
+	  colors += !(cfa & (1 << cfa_pat[i]));
+	  cfa |= 1 << cfa_pat[i];
+	}
+	if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3);	/* CMY */
+	if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4);	/* GMCY */
+	goto guess_cfa_pc;
+      case 33424:
+	fseek (ifp, get4()+base, SEEK_SET);
+	parse_kodak_ifd (base);
+	break;
+      case 33434:			/* ExposureTime */
+	shutter = getreal(type);
+	break;
+      case 33437:			/* FNumber */
+	aperture = getreal(type);
+	break;
+      case 34306:			/* Leaf white balance */
+	FORC4 cam_mul[c ^ 1] = 4096.0 / get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 34307:			/* Leaf CatchLight color matrix */
+	fread (software, 1, 7, ifp);
+	if (strncmp(software,"MATRIX",6)) break;
+	colors = 4;
+	for (raw_color = i=0; i < 3; i++) {
+	  FORC4 fscanf (ifp, "%f", &rgb_cam[i][c^1]);
+	  if (!use_camera_wb) continue;
+	  num = 0;
+	  FORC4 num += rgb_cam[i][c];
+	  FORC4 rgb_cam[i][c] /= num;
+#ifdef LIBRAW_LIBRARY_BUILD
+          color_flags.rgb_cam_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	}
+	break;
+      case 34310:			/* Leaf metadata */
+	parse_mos (ftell(ifp));
+      case 34303:
+	strcpy (make, "Leaf");
+	break;
+      case 34665:			/* EXIF tag */
+	fseek (ifp, get4()+base, SEEK_SET);
+	parse_exif (base);
+	break;
+      case 34853:			/* GPSInfo tag */
+	fseek (ifp, get4()+base, SEEK_SET);
+	parse_gps (base);
+	break;
+      case 34675:			/* InterColorProfile */
+      case 50831:			/* AsShotICCProfile */
+	profile_offset = ftell(ifp);
+	profile_length = len;
+	break;
+      case 37122:			/* CompressedBitsPerPixel */
+	kodak_cbpp = get4();
+	break;
+      case 37386:			/* FocalLength */
+	focal_len = getreal(type);
+	break;
+      case 37393:			/* ImageNumber */
+	shot_order = getint(type);
+	break;
+      case 37400:			/* old Kodak KDC tag */
+	for (raw_color = i=0; i < 3; i++) {
+	  getreal(type);
+	  FORC3 rgb_cam[i][c] = getreal(type);
+	}
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.rgb_cam_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 46275:			/* Imacon tags */
+	strcpy (make, "Imacon");
+	data_offset = ftell(ifp);
+	ima_len = len;
+	break;
+      case 46279:
+	if (!ima_len) break;
+	fseek (ifp, 78, SEEK_CUR);
+	raw_width  = get4();
+	raw_height = get4();
+	left_margin = get4() & 7;
+	width = raw_width - left_margin - (get4() & 7);
+	top_margin = get4() & 7;
+	height = raw_height - top_margin - (get4() & 7);
+	if (raw_width == 7262) {
+	  height = 5444;
+	  width  = 7244;
+	  left_margin = 7;
+	}
+	fseek (ifp, 52, SEEK_CUR);
+	FORC3 cam_mul[c] = getreal(11);
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	fseek (ifp, 114, SEEK_CUR);
+	flip = (get2() >> 7) * 90;
+	if (width * height * 6 == ima_len) {
+	  if (flip % 180 == 90) SWAP(width,height);
+	  filters = flip = 0;
+	}
+	sprintf (model, "Ixpress %d-Mp", height*width/1000000);
+	load_raw = &CLASS imacon_full_load_raw;
+	if (filters) {
+	  if (left_margin & 1) filters = 0x61616161;
+	  load_raw = &CLASS unpacked_load_raw;
+	}
+	maximum = 0xffff;
+	break;
+      case 50454:			/* Sinar tag */
+      case 50455:
+	if (!(cbuf = (char *) malloc(len))) break;
+	fread (cbuf, 1, len, ifp);
+	for (cp = cbuf-1; cp && cp < cbuf+len; cp = strchr(cp,'\n'))
+	  if (!strncmp (++cp,"Neutral ",8))
+              {
+	    sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2);
+#ifdef LIBRAW_LIBRARY_BUILD
+            color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+              }
+	free (cbuf);
+	break;
+      case 50458:
+	if (!make[0]) strcpy (make, "Hasselblad");
+	break;
+      case 50459:			/* Hasselblad tag */
+	i = order;
+	j = ftell(ifp);
+	c = tiff_nifds;
+	order = get2();
+	fseek (ifp, j+(get2(),get4()), SEEK_SET);
+	parse_tiff_ifd (j);
+	maximum = 0xffff;
+	tiff_nifds = c;
+	order = i;
+	break;
+      case 50706:			/* DNGVersion */
+	FORC4 dng_version = (dng_version << 8) + fgetc(ifp);
+	if (!make[0]) strcpy (make, "DNG");
+	is_raw = 1;
+	break;
+      case 50710:			/* CFAPlaneColor */
+	if (len > 4) len = 4;
+	colors = len;
+	fread (cfa_pc, 1, colors, ifp);
+guess_cfa_pc:
+	FORCC tab[cfa_pc[c]] = c;
+	cdesc[c] = 0;
+	for (i=16; i--; )
+	  filters = filters << 2 | tab[cfa_pat[i % plen]];
+	break;
+      case 50711:			/* CFALayout */
+	if (get2() == 2) {
+	  fuji_width = 1;
+	  filters = 0x49494949;
+	}
+	break;
+      case 291:
+      case 50712:			/* LinearizationTable */
+	linear_table (len);
+	break;
+      case 50714:			/* BlackLevel */
+      case 50715:			/* BlackLevelDeltaH */
+      case 50716:			/* BlackLevelDeltaV */
+	for (dblack=i=0; i < len; i++)
+	  dblack += getreal(type);
+	black += dblack/len + 0.5;
+	break;
+      case 50717:			/* WhiteLevel */
+	maximum = getint(type);
+	break;
+      case 50718:			/* DefaultScale */
+	pixel_aspect  = getreal(type);
+	pixel_aspect /= getreal(type);
+	break;
+      case 50721:			/* ColorMatrix1 */
+      case 50722:			/* ColorMatrix2 */
+	FORCC for (j=0; j < 3; j++)
+	  cm[c][j] = getreal(type);
+	use_cm = 1;
+	break;
+      case 50723:			/* CameraCalibration1 */
+      case 50724:			/* CameraCalibration2 */
+	for (i=0; i < colors; i++)
+	  FORCC cc[i][c] = getreal(type);
+      case 50727:			/* AnalogBalance */
+	FORCC ab[c] = getreal(type);
+	break;
+      case 50728:			/* AsShotNeutral */
+	FORCC asn[c] = getreal(type);
+	break;
+      case 50729:			/* AsShotWhiteXY */
+	xyz[0] = getreal(type);
+	xyz[1] = getreal(type);
+	xyz[2] = 1 - xyz[0] - xyz[1];
+	FORC3 xyz[c] /= d65_white[c];
+	break;
+      case 50740:			/* DNGPrivateData */
+	if (dng_version) break;
+	parse_minolta (j = get4()+base);
+	fseek (ifp, j, SEEK_SET);
+	parse_tiff_ifd (base);
+	break;
+      case 50752:
+	read_shorts (cr2_slice, 3);
+	break;
+      case 50829:			/* ActiveArea */
+	top_margin = getint(type);
+	left_margin = getint(type);
+	height = getint(type) - top_margin;
+	width = getint(type) - left_margin;
+	break;
+      case 64772:			/* Kodak P-series */
+	if (len < 13) break;
+	fseek (ifp, 16, SEEK_CUR);
+	data_offset = get4();
+	fseek (ifp, 28, SEEK_CUR);
+	data_offset += get4();
+	load_raw = &CLASS packed_12_load_raw;
+	break;
+      case 65026:
+	if (type == 2) fgets (model2, 64, ifp);
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  if (sony_length && (buf = (unsigned *) malloc(sony_length))) {
+    fseek (ifp, sony_offset, SEEK_SET);
+    fread (buf, sony_length, 1, ifp);
+    sony_decrypt (buf, sony_length/4, 1, sony_key);
+#ifndef LIBRAW_LIBRARY_BUILD
+    sfp = ifp;
+    if ((ifp = tmpfile())) {
+      fwrite (buf, sony_length, 1, ifp);
+      fseek (ifp, 0, SEEK_SET);
+      parse_tiff_ifd (-sony_offset);
+      fclose (ifp);
+    }
+    ifp = sfp;
+#else
+    if( !ifp->tempbuffer_open(buf,sony_length))
+        {
+            parse_tiff_ifd(-sony_offset);
+            ifp->tempbuffer_close();
+        }
+#endif
+    free (buf);
+  }
+  for (i=0; i < colors; i++)
+    FORCC cc[i][c] *= ab[i];
+  if (use_cm) {
+    FORCC for (i=0; i < 3; i++)
+      for (cam_xyz[c][i]=j=0; j < colors; j++)
+	cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i];
+    cam_xyz_coeff (cam_xyz);
+  }
+  if (asn[0]) {
+    cam_mul[3] = 0;
+    FORCC cam_mul[c] = 1 / asn[c];
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+  }
+  if (!use_cm)
+      {
+    FORCC pre_mul[c] /= cc[c][c];
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      }
+
+  return 0;
+}
+
+void CLASS parse_tiff (int base)
+{
+  int doff, max_samp=0, raw=-1, thm=-1, i;
+  struct jhead jh;
+
+  fseek (ifp, base, SEEK_SET);
+  order = get2();
+  if (order != 0x4949 && order != 0x4d4d) return;
+  get2();
+  memset (tiff_ifd, 0, sizeof tiff_ifd);
+  tiff_nifds = 0;
+  while ((doff = get4())) {
+    fseek (ifp, doff+base, SEEK_SET);
+    if (parse_tiff_ifd (base)) break;
+  }
+  thumb_misc = 16;
+  if (thumb_offset) {
+    fseek (ifp, thumb_offset, SEEK_SET);
+    if (ljpeg_start (&jh, 1)) {
+      thumb_misc   = jh.bits;
+      thumb_width  = jh.wide;
+      thumb_height = jh.high;
+    }
+  }
+  for (i=0; i < tiff_nifds; i++) {
+    if (max_samp < tiff_ifd[i].samples)
+	max_samp = tiff_ifd[i].samples;
+    if (max_samp > 3) max_samp = 3;
+    if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) &&
+	tiff_ifd[i].t_width*tiff_ifd[i].t_height > raw_width*raw_height) {
+      raw_width     = tiff_ifd[i].t_width;
+      raw_height    = tiff_ifd[i].t_height;
+      tiff_bps      = tiff_ifd[i].bps;
+      tiff_compress = tiff_ifd[i].comp;
+      data_offset   = tiff_ifd[i].offset;
+      tiff_flip     = tiff_ifd[i].t_flip;
+      tiff_samples  = tiff_ifd[i].samples;
+      raw = i;
+    }
+  }
+  fuji_width *= (raw_width+1)/2;
+  if (tiff_ifd[0].t_flip) tiff_flip = tiff_ifd[0].t_flip;
+  if (raw >= 0 && !load_raw)
+    switch (tiff_compress) {
+      case 0:  case 1:
+	switch (tiff_bps) {
+	  case  8: load_raw = &CLASS eight_bit_load_raw;	break;
+	  case 12: load_raw = &CLASS packed_12_load_raw;
+		   if (tiff_ifd[raw].phint == 2)
+		     load_flags = 6;
+		   if (strncmp(make,"PENTAX",6)) break;
+	  case 14:
+	  case 16: load_raw = &CLASS unpacked_load_raw;		break;
+	}
+	if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) {
+	  load_raw = &CLASS packed_12_load_raw;
+	  load_flags = 273;
+	}
+	break;
+      case 6:  case 7:  case 99:
+	load_raw = &CLASS lossless_jpeg_load_raw;		break;
+      case 262:
+	load_raw = &CLASS kodak_262_load_raw;			break;
+      case 32767:
+	if (tiff_ifd[raw].bytes*8 != raw_width*raw_height*tiff_bps) {
+	  raw_height += 8;
+	  load_raw = &CLASS sony_arw_load_raw;			break;
+	}
+	if (tiff_bps == 8) {
+	  tiff_bps = 12;
+	  load_raw = &CLASS sony_arw2_load_raw;			break;
+	}
+	load_flags = 79;
+      case 32769:
+	load_flags++;
+      case 32773:
+	load_raw = &CLASS packed_12_load_raw;			break;
+      case 34713:
+	load_raw = &CLASS nikon_compressed_load_raw;		break;
+      case 65535:
+	load_raw = &CLASS pentax_k10_load_raw;			break;
+      case 65000:
+	switch (tiff_ifd[raw].phint) {
+	  case 2: load_raw = &CLASS kodak_rgb_load_raw;   filters = 0;  break;
+	  case 6: load_raw = &CLASS kodak_ycbcr_load_raw; filters = 0;  break;
+	  case 32803: load_raw = &CLASS kodak_65000_load_raw;
+	}
+      case 32867: break;
+      default: is_raw = 0;
+    }
+  if (!dng_version)
+    if ( (tiff_samples == 3 && tiff_ifd[raw].bytes &&
+	  tiff_bps != 14 && tiff_bps != 2048)
+      || (tiff_bps == 8 && !strstr(make,"KODAK") && !strstr(make,"Kodak") &&
+	  !strstr(model2,"DEBUG RAW")))
+      is_raw = 0;
+  for (i=0; i < tiff_nifds; i++)
+    if (i != raw && tiff_ifd[i].samples == max_samp &&
+	tiff_ifd[i].t_width * tiff_ifd[i].t_height / SQR(tiff_ifd[i].bps+1) >
+	      thumb_width *       thumb_height / SQR(thumb_misc+1)) {
+      thumb_width  = tiff_ifd[i].t_width;
+      thumb_height = tiff_ifd[i].t_height;
+      thumb_offset = tiff_ifd[i].offset;
+      thumb_length = tiff_ifd[i].bytes;
+      thumb_misc   = tiff_ifd[i].bps;
+      thm = i;
+    }
+  if (thm >= 0) {
+    thumb_misc |= tiff_ifd[thm].samples << 5;
+    switch (tiff_ifd[thm].comp) {
+      case 0:
+	write_thumb = &CLASS layer_thumb;
+	break;
+      case 1:
+	if (tiff_ifd[thm].bps > 8)
+	  thumb_load_raw = &CLASS kodak_thumb_load_raw;
+	else
+	  write_thumb = &CLASS ppm_thumb;
+	break;
+      case 65000:
+	thumb_load_raw = tiff_ifd[thm].phint == 6 ?
+		&CLASS kodak_ycbcr_load_raw : &CLASS kodak_rgb_load_raw;
+    }
+  }
+}
+
+void CLASS parse_minolta (int base)
+{
+  int save, tag, len, offset, high=0, wide=0, i, c;
+  short sorder=order;
+
+  fseek (ifp, base, SEEK_SET);
+  if (fgetc(ifp) || fgetc(ifp)-'M' || fgetc(ifp)-'R') return;
+  order = fgetc(ifp) * 0x101;
+  offset = base + get4() + 8;
+  while ((save=ftell(ifp)) < offset) {
+    for (tag=i=0; i < 4; i++)
+      tag = tag << 8 | fgetc(ifp);
+    len = get4();
+    switch (tag) {
+      case 0x505244:				/* PRD */
+	fseek (ifp, 8, SEEK_CUR);
+	high = get2();
+	wide = get2();
+	break;
+      case 0x574247:				/* WBG */
+	get4();
+	i = strcmp(model,"DiMAGE A200") ? 0:3;
+	FORC4 cam_mul[c ^ (c >> 1) ^ i] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 0x545457:				/* TTW */
+	parse_tiff (ftell(ifp));
+	data_offset = offset;
+    }
+    fseek (ifp, save+len+8, SEEK_SET);
+  }
+  raw_height = high;
+  raw_width  = wide;
+  order = sorder;
+}
+
+/*
+   Many cameras have a "debug mode" that writes JPEG and raw
+   at the same time.  The raw file has no header, so try to
+   to open the matching JPEG file and read its metadata.
+ */
+void CLASS parse_external_jpeg()
+{
+  const char *file, *ext;
+  char *jname, *jfile, *jext;
+#ifndef LIBRAW_LIBRARY_BUILD
+  FILE *save=ifp;
+#else
+  if(!ifp->fname())
+      {
+          imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ;
+          return;
+      }
+#endif
+
+  ext  = strrchr (ifname, '.');
+  file = strrchr (ifname, '/');
+  if (!file) file = strrchr (ifname, '\\');
+#ifndef LIBRAW_LIBRARY_BUILD
+  if (!file) file = ifname-1;
+#else
+  if (!file) file = (char*)ifname-1;
+#endif
+  file++;
+  if (!ext || strlen(ext) != 4 || ext-file != 8) return;
+  jname = (char *) malloc (strlen(ifname) + 1);
+  merror (jname, "parse_external_jpeg()");
+  strcpy (jname, ifname);
+  jfile = file - ifname + jname;
+  jext  = ext  - ifname + jname;
+  if (strcasecmp (ext, ".jpg")) {
+    strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg");
+    if (isdigit(*file)) {
+      memcpy (jfile, file+4, 4);
+      memcpy (jfile+4, file, 4);
+    }
+  } else
+    while (isdigit(*--jext)) {
+      if (*jext != '9') {
+        (*jext)++;
+	break;
+      }
+      *jext = '0';
+    }
+#ifndef LIBRAW_LIBRARY_BUILD
+  if (strcmp (jname, ifname)) {
+    if ((ifp = fopen (jname, "rb"))) {
+#ifdef DCRAW_VERBOSE
+      if (verbose)
+	fprintf (stderr,_("Reading metadata from %s ...\n"), jname);
+#endif
+      parse_tiff (12);
+      thumb_offset = 0;
+      is_raw = 1;
+      fclose (ifp);
+    }
+  }
+#else
+  if (strcmp (jname, ifname)) 
+      {
+          if(!ifp->subfile_open(jname))
+              {
+                  parse_tiff (12);
+                  thumb_offset = 0;
+                  is_raw = 1;
+                  ifp->subfile_close();
+              }
+          else
+              imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ;
+      }
+#endif
+  if (!timestamp)
+      {
+#ifdef LIBRAW_LIBRARY_BUILD
+          imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ;
+#endif
+#ifdef DCRAW_VERBOSE
+          fprintf (stderr,_("Failed to read metadata from %s\n"), jname);
+#endif
+      }
+  free (jname);
+#ifndef LIBRAW_LIBRARY_BUILD
+  ifp = save;
+#endif
+}
+
+/*
+   CIFF block 0x1030 contains an 8x8 white sample.
+   Load this into white[][] for use in scale_colors().
+ */
+void CLASS ciff_block_1030()
+{
+  static const ushort key[] = { 0x410, 0x45f3 };
+  int i, bpp, row, col, vbits=0;
+  unsigned long bitbuf=0;
+
+  if ((get2(),get4()) != 0x80008 || !get4()) return;
+  bpp = get2();
+  if (bpp != 10 && bpp != 12) return;
+  for (i=row=0; row < 8; row++)
+    for (col=0; col < 8; col++) {
+      if (vbits < bpp) {
+	bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
+	vbits += 16;
+      }
+      white[row][col] =
+	bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp);
+      vbits -= bpp;
+    }
+}
+
+/*
+   Parse a CIFF file, better known as Canon CRW format.
+ */
+void CLASS parse_ciff (int offset, int length)
+{
+  int tboff, nrecs, c, type, len, save, wbi=-1;
+  ushort key[] = { 0x410, 0x45f3 };
+
+  fseek (ifp, offset+length-4, SEEK_SET);
+  tboff = get4() + offset;
+  fseek (ifp, tboff, SEEK_SET);
+  nrecs = get2();
+  if (nrecs > 100) return;
+  while (nrecs--) {
+    type = get2();
+    len  = get4();
+    save = ftell(ifp) + 4;
+    fseek (ifp, offset+get4(), SEEK_SET);
+    if ((((type >> 8) + 8) | 8) == 0x38)
+      parse_ciff (ftell(ifp), len);	/* Parse a sub-table */
+
+    if (type == 0x0810)
+      fread (artist, 64, 1, ifp);
+    if (type == 0x080a) {
+      fread (make, 64, 1, ifp);
+      fseek (ifp, strlen(make) - 63, SEEK_CUR);
+      fread (model, 64, 1, ifp);
+    }
+    if (type == 0x1810) {
+      fseek (ifp, 12, SEEK_CUR);
+      flip = get4();
+    }
+    if (type == 0x1835)			/* Get the decoder table */
+      tiff_compress = get4();
+    if (type == 0x2007) {
+      thumb_offset = ftell(ifp);
+      thumb_length = len;
+    }
+    if (type == 0x1818) {
+      shutter = pow (2.0f, -int_to_float((get4(),get4())));
+      aperture = pow (2.0f, int_to_float(get4())/2);
+    }
+    if (type == 0x102a) {
+      iso_speed = pow (2, (get4(),get2())/32.0 - 4) * 50;
+      aperture  = pow (2, (get2(),(short)get2())/64.0);
+      shutter   = pow (2,-((short)get2())/32.0);
+      wbi = (get2(),get2());
+      if (wbi > 17) wbi = 0;
+      fseek (ifp, 32, SEEK_CUR);
+      if (shutter > 1e6) shutter = get2()/10.0;
+    }
+    if (type == 0x102c) {
+      if (get2() > 512) {		/* Pro90, G1 */
+	fseek (ifp, 118, SEEK_CUR);
+	FORC4 cam_mul[c ^ 2] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      } else {				/* G2, S30, S40 */
+	fseek (ifp, 98, SEEK_CUR);
+	FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      }
+    }
+    if (type == 0x0032) {
+      if (len == 768) {			/* EOS D30 */
+	fseek (ifp, 72, SEEK_CUR);
+	FORC4 cam_mul[c ^ (c >> 1)] = 1024.0 / get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	if (!wbi) cam_mul[0] = -1;	/* use my auto white balance */
+      } else if (!cam_mul[0]) {
+	if (get2() == key[0])		/* Pro1, G6, S60, S70 */
+	  c = (strstr(model,"Pro1") ?
+	      "012346000000000000":"01345:000000006008")[wbi]-'0'+ 2;
+	else {				/* G3, G5, S45, S50 */
+	  c = "023457000000006000"[wbi]-'0';
+	  key[0] = key[1] = 0;
+	}
+	fseek (ifp, 78 + c*8, SEEK_CUR);
+	FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2() ^ key[c & 1];
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	if (!wbi) cam_mul[0] = -1;
+      }
+    }
+    if (type == 0x10a9) {		/* D60, 10D, 300D, and clones */
+      if (len > 66) wbi = "0134567028"[wbi]-'0';
+      fseek (ifp, 2 + wbi*8, SEEK_CUR);
+      FORC4 cam_mul[c ^ (c >> 1)] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if (type == 0x1030 && (0x18040 >> wbi & 1))
+      ciff_block_1030();		/* all that don't have 0x10a9 */
+    if (type == 0x1031) {
+      raw_width = (get2(),get2());
+      raw_height = get2();
+    }
+    if (type == 0x5029) {
+      focal_len = len >> 16;
+      if ((len & 0xffff) == 2) focal_len /= 32;
+    }
+    if (type == 0x5813) flash_used = int_to_float(len);
+    if (type == 0x5814) canon_ev   = int_to_float(len);
+    if (type == 0x5817) shot_order = len;
+    if (type == 0x5834) unique_id  = len;
+    if (type == 0x580e) timestamp  = len;
+    if (type == 0x180e) timestamp  = get4();
+#ifdef LOCALTIME
+    if ((type | 0x4000) == 0x580e)
+      timestamp = mktime (gmtime (&timestamp));
+#endif
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS parse_rollei()
+{
+  char line[128], *val;
+  struct tm t;
+
+  fseek (ifp, 0, SEEK_SET);
+  memset (&t, 0, sizeof t);
+  do {
+    fgets (line, 128, ifp);
+    if ((val = strchr(line,'=')))
+      *val++ = 0;
+    else
+      val = line + strlen(line);
+    if (!strcmp(line,"DAT"))
+      sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
+    if (!strcmp(line,"TIM"))
+      sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
+    if (!strcmp(line,"HDR"))
+      thumb_offset = atoi(val);
+    if (!strcmp(line,"X  "))
+      raw_width = atoi(val);
+    if (!strcmp(line,"Y  "))
+      raw_height = atoi(val);
+    if (!strcmp(line,"TX "))
+      thumb_width = atoi(val);
+    if (!strcmp(line,"TY "))
+      thumb_height = atoi(val);
+  } while (strncmp(line,"EOHD",4));
+  data_offset = thumb_offset + thumb_width * thumb_height * 2;
+  t.tm_year -= 1900;
+  t.tm_mon -= 1;
+  if (mktime(&t) > 0)
+    timestamp = mktime(&t);
+  strcpy (make, "Rollei");
+  strcpy (model,"d530flex");
+  write_thumb = &CLASS rollei_thumb;
+}
+
+void CLASS parse_sinar_ia()
+{
+  int entries, off;
+  char str[8], *cp;
+
+  order = 0x4949;
+  fseek (ifp, 4, SEEK_SET);
+  entries = get4();
+  fseek (ifp, get4(), SEEK_SET);
+  while (entries--) {
+    off = get4(); get4();
+    fread (str, 8, 1, ifp);
+    if (!strcmp(str,"META"))   meta_offset = off;
+    if (!strcmp(str,"THUMB")) thumb_offset = off;
+    if (!strcmp(str,"RAW0"))   data_offset = off;
+  }
+  fseek (ifp, meta_offset+20, SEEK_SET);
+  fread (make, 64, 1, ifp);
+  make[63] = 0;
+  if ((cp = strchr(make,' '))) {
+    strcpy (model, cp+1);
+    *cp = 0;
+  }
+  raw_width  = get2();
+  raw_height = get2();
+  load_raw = &CLASS unpacked_load_raw;
+  thumb_width = (get4(),get2());
+  thumb_height = get2();
+  write_thumb = &CLASS ppm_thumb;
+  maximum = 0x3fff;
+}
+
+void CLASS parse_phase_one (int base)
+{
+  unsigned entries, tag, type, len, data, save, i, c;
+  float romm_cam[3][3];
+  char *cp;
+
+  memset (&ph1, 0, sizeof ph1);
+  fseek (ifp, base, SEEK_SET);
+  order = get4() & 0xffff;
+  if (get4() >> 8 != 0x526177) return;		/* "Raw" */
+  fseek (ifp, get4()+base, SEEK_SET);
+  entries = get4();
+  get4();
+  while (entries--) {
+    tag  = get4();
+    type = get4();
+    len  = get4();
+    data = get4();
+    save = ftell(ifp);
+    fseek (ifp, base+data, SEEK_SET);
+    switch (tag) {
+      case 0x100:  flip = "0653"[data & 3]-'0';  break;
+      case 0x106:
+	for (i=0; i < 9; i++)
+	  romm_cam[0][i] = getreal(11);
+	romm_coeff (romm_cam);
+	break;
+      case 0x107:
+	FORC3 cam_mul[c] = getreal(11);
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 0x108:  raw_width     = data;	break;
+      case 0x109:  raw_height    = data;	break;
+      case 0x10a:  left_margin   = data;	break;
+      case 0x10b:  top_margin    = data;	break;
+      case 0x10c:  width         = data;	break;
+      case 0x10d:  height        = data;	break;
+      case 0x10e:  ph1.format    = data;	break;
+      case 0x10f:  data_offset   = data+base;	break;
+      case 0x110:  meta_offset   = data+base;
+		   meta_length   = len;			break;
+      case 0x112:  ph1.key_off   = save - 4;		break;
+      case 0x210:  ph1.tag_210   = int_to_float(data);	break;
+      case 0x21a:  ph1.tag_21a   = data;		break;
+      case 0x21c:  strip_offset  = data+base;		break;
+      case 0x21d:  ph1.t_black     = data;		break;
+      case 0x222:  ph1.split_col = data - left_margin;	break;
+      case 0x223:  ph1.black_off = data+base;		break;
+      case 0x301:
+	model[63] = 0;
+	fread (model, 1, 63, ifp);
+	if ((cp = strstr(model," camera"))) *cp = 0;
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  load_raw = ph1.format < 3 ?
+	&CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c;
+  maximum = 0xffff;
+  strcpy (make, "Phase One");
+  if (model[0]) return;
+  switch (raw_height) {
+    case 2060: strcpy (model,"LightPhase");	break;
+    case 2682: strcpy (model,"H 10");		break;
+    case 4128: strcpy (model,"H 20");		break;
+    case 5488: strcpy (model,"H 25");		break;
+  }
+}
+
+void CLASS parse_fuji (int offset)
+{
+  unsigned entries, tag, len, save, c;
+
+  fseek (ifp, offset, SEEK_SET);
+  entries = get4();
+  if (entries > 255) return;
+  while (entries--) {
+    tag = get2();
+    len = get2();
+    save = ftell(ifp);
+    if (tag == 0x100) {
+      raw_height = get2();
+      raw_width  = get2();
+    } else if (tag == 0x121) {
+      height = get2();
+      if ((width = get2()) == 4284) width += 3;
+    } else if (tag == 0x130)
+      fuji_layout = fgetc(ifp) >> 7;
+    if (tag == 0x2ff0)
+        {
+      FORC4 cam_mul[c ^ 1] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+        }
+    fseek (ifp, save+len, SEEK_SET);
+  }
+  height <<= fuji_layout;
+  width  >>= fuji_layout;
+}
+
+int CLASS parse_jpeg (int offset)
+{
+  int len, save, hlen, mark;
+
+  fseek (ifp, offset, SEEK_SET);
+  if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return 0;
+
+  while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda) {
+    order = 0x4d4d;
+    len   = get2() - 2;
+    save  = ftell(ifp);
+    if (mark == 0xc0 || mark == 0xc3) {
+      fgetc(ifp);
+      raw_height = get2();
+      raw_width  = get2();
+    }
+    order = get2();
+    hlen  = get4();
+    if (get4() == 0x48454150)		/* "HEAP" */
+      parse_ciff (save+hlen, len-hlen);
+    parse_tiff (save+6);
+    fseek (ifp, save+len, SEEK_SET);
+  }
+  return 1;
+}
+
+void CLASS parse_riff()
+{
+  unsigned i, size, end;
+  char tag[4], date[64], month[64];
+  static const char mon[12][4] =
+  { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
+  struct tm t;
+
+  order = 0x4949;
+  fread (tag, 4, 1, ifp);
+  size = get4();
+  end = ftell(ifp) + size;
+  if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) {
+    get4();
+    while (ftell(ifp)+7 < end)
+      parse_riff();
+  } else if (!memcmp(tag,"nctg",4)) {
+    while (ftell(ifp)+7 < end) {
+      i = get2();
+      size = get2();
+      if ((i+1) >> 1 == 10 && size == 20)
+	get_timestamp(0);
+      else fseek (ifp, size, SEEK_CUR);
+    }
+  } else if (!memcmp(tag,"IDIT",4) && size < 64) {
+    fread (date, 64, 1, ifp);
+    date[size] = 0;
+    memset (&t, 0, sizeof t);
+    if (sscanf (date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday,
+	&t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) == 6) {
+      for (i=0; i < 12 && strcasecmp(mon[i],month); i++);
+      t.tm_mon = i;
+      t.tm_year -= 1900;
+      if (mktime(&t) > 0)
+	timestamp = mktime(&t);
+    }
+  } else
+    fseek (ifp, size, SEEK_CUR);
+}
+
+void CLASS parse_smal (int offset, int fsize)
+{
+  int ver;
+
+  fseek (ifp, offset+2, SEEK_SET);
+  order = 0x4949;
+  ver = fgetc(ifp);
+  if (ver == 6)
+    fseek (ifp, 5, SEEK_CUR);
+  if (get4() != fsize) return;
+  if (ver > 6) data_offset = get4();
+  raw_height = height = get2();
+  raw_width  = width  = get2();
+  strcpy (make, "SMaL");
+  sprintf (model, "v%d %dx%d", ver, width, height);
+  if (ver == 6) load_raw = &CLASS smal_v6_load_raw;
+  if (ver == 9) load_raw = &CLASS smal_v9_load_raw;
+}
+
+void CLASS parse_cine()
+{
+  unsigned off_head, off_setup, off_image, i;
+
+  order = 0x4949;
+  fseek (ifp, 4, SEEK_SET);
+  is_raw = get2() == 2;
+  fseek (ifp, 14, SEEK_CUR);
+  is_raw *= get4();
+  off_head = get4();
+  off_setup = get4();
+  off_image = get4();
+  timestamp = get4();
+  if ((i = get4())) timestamp = i;
+  fseek (ifp, off_head+4, SEEK_SET);
+  raw_width = get4();
+  raw_height = get4();
+  switch (get2(),get2()) {
+    case  8:  load_raw = &CLASS eight_bit_load_raw;  break;
+    case 16:  load_raw = &CLASS  unpacked_load_raw;
+  }
+  fseek (ifp, off_setup+792, SEEK_SET);
+  strcpy (make, "CINE");
+  sprintf (model, "%d", get4());
+  fseek (ifp, 12, SEEK_CUR);
+  switch ((i=get4()) & 0xffffff) {
+    case  3:  filters = 0x94949494;  break;
+    case  4:  filters = 0x49494949;  break;
+    default:  is_raw = 0;
+  }
+  fseek (ifp, 72, SEEK_CUR);
+  switch ((get4()+3600) % 360) {
+    case 270:  flip = 4;  break;
+    case 180:  flip = 1;  break;
+    case  90:  flip = 7;  break;
+    case   0:  flip = 2;
+  }
+  cam_mul[0] = getreal(11);
+  cam_mul[2] = getreal(11);
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+  maximum = ~(-1 << get4());
+  fseek (ifp, 668, SEEK_CUR);
+  shutter = get4()/1000000000.0;
+  fseek (ifp, off_image, SEEK_SET);
+  if (shot_select < is_raw)
+    fseek (ifp, shot_select*8, SEEK_CUR);
+  data_offset  = (INT64) get4() + 8;
+  data_offset += (INT64) get4() << 32;
+}
+void CLASS adobe_coeff (const char *p_make, const char *p_model)
+{
+  static const struct {
+    const char *prefix;
+    short t_black, t_maximum, trans[12];
+  } table[] = {
+    { "Apple QuickTake", 0, 0,		/* DJC */
+	{ 21392,-5653,-3353,2406,8010,-415,7166,1427,2078 } },
+    { "Canon EOS D2000", 0, 0,
+	{ 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+    { "Canon EOS D6000", 0, 0,
+	{ 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+    { "Canon EOS D30", 0, 0,
+	{ 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } },
+    { "Canon EOS D60", 0, 0xfa0,
+	{ 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } },
+    { "Canon EOS 5D Mark II", 0, 0x3cf0,
+	{ 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } },
+    { "Canon EOS 5D", 0, 0xe6c,
+	{ 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } },
+    { "Canon EOS 10D", 0, 0xfa0,
+	{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+    { "Canon EOS 20Da", 0, 0,
+	{ 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } },
+    { "Canon EOS 20D", 0, 0xfff,
+	{ 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } },
+    { "Canon EOS 30D", 0, 0,
+	{ 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } },
+    { "Canon EOS 40D", 0, 0x3f60,
+	{ 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } },
+    { "Canon EOS 50D", 0, 0x3d93,
+	{ 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } },
+    { "Canon EOS 300D", 0, 0xfa0,
+	{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+    { "Canon EOS 350D", 0, 0xfff,
+	{ 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } },
+    { "Canon EOS 400D", 0, 0xe8e,
+	{ 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } },
+    { "Canon EOS 450D", 0, 0x390d,
+	{ 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } },
+    { "Canon EOS 1000D", 0, 0xe43,
+	{ 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } },
+    { "Canon EOS-1Ds Mark III", 0, 0x3bb0,
+	{ 5859,-211,-930,-8255,16017,2353,-1732,1887,7448 } },
+    { "Canon EOS-1Ds Mark II", 0, 0xe80,
+	{ 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } },
+    { "Canon EOS-1D Mark II N", 0, 0xe80,
+	{ 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } },
+    { "Canon EOS-1D Mark III", 0, 0x3bb0,
+	{ 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } },
+    { "Canon EOS-1D Mark II", 0, 0xe80,
+	{ 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } },
+    { "Canon EOS-1DS", 0, 0xe20,
+	{ 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } },
+    { "Canon EOS-1D", 0, 0xe20,
+	{ 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } },
+    { "Canon EOS", 0, 0,
+	{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+    { "Canon PowerShot A50", 0, 0,
+	{ -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } },
+    { "Canon PowerShot A5", 0, 0,
+	{ -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } },
+    { "Canon PowerShot G10", 0, 0,
+	{ 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } },
+    { "Canon PowerShot G1", 0, 0,
+	{ -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } },
+    { "Canon PowerShot G2", 0, 0,
+	{ 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } },
+    { "Canon PowerShot G3", 0, 0,
+	{ 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } },
+    { "Canon PowerShot G5", 0, 0,
+	{ 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } },
+    { "Canon PowerShot G6", 0, 0,
+	{ 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } },
+    { "Canon PowerShot G9", 0, 0,
+	{ 7368,-2141,-598,-5621,13254,2625,-1418,1696,5743 } },
+    { "Canon PowerShot Pro1", 0, 0,
+	{ 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } },
+    { "Canon PowerShot Pro70", 34, 0,
+	{ -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } },
+    { "Canon PowerShot Pro90", 0, 0,
+	{ -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 } },
+    { "Canon PowerShot S30", 0, 0,
+	{ 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } },
+    { "Canon PowerShot S40", 0, 0,
+	{ 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } },
+    { "Canon PowerShot S45", 0, 0,
+	{ 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } },
+    { "Canon PowerShot S50", 0, 0,
+	{ 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } },
+    { "Canon PowerShot S60", 0, 0,
+	{ 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } },
+    { "Canon PowerShot S70", 0, 0,
+	{ 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } },
+    { "Canon PowerShot A610", 0, 0,	/* DJC */
+	{ 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } },
+    { "Canon PowerShot A620", 0, 0,	/* DJC */
+	{ 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } },
+    { "Canon PowerShot A630", 0, 0,	/* DJC */
+	{ 14201,-5308,-1757,-6087,14472,1617,-2191,3105,5348 } },
+    { "Canon PowerShot A640", 0, 0,	/* DJC */
+	{ 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } },
+    { "Canon PowerShot A650", 0, 0,	/* DJC */
+	{ 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } },
+    { "Canon PowerShot A720", 0, 0,	/* DJC */
+	{ 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } },
+    { "Canon PowerShot S3 IS", 0, 0,	/* DJC */
+	{ 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } },
+    { "Canon PowerShot SX1 IS", 0, 0,	/* DJC */
+	{ 10013,-2214,-1111,-3650,11589,2062,342,685,3617 } },
+    { "Canon PowerShot SX110 IS", 0, 0,	/* DJC */
+        { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } },
+    { "CINE 650", 0, 0,
+	{ 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+    { "CINE 660", 0, 0,
+	{ 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+    { "CINE", 0, 0,
+	{ 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } },
+    { "Contax N Digital", 0, 0xf1e,
+	{ 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } },
+    { "EPSON R-D1", 0, 0,
+	{ 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } },
+    { "FUJIFILM FinePix E550", 0, 0,
+	{ 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
+    { "FUJIFILM FinePix E900", 0, 0,
+	{ 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } },
+    { "FUJIFILM FinePix F8", 0, 0,
+	{ 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
+    { "FUJIFILM FinePix F7", 0, 0,
+	{ 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+    { "FUJIFILM FinePix S100FS", 514, 0,
+	{ 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } },
+    { "FUJIFILM FinePix S20Pro", 0, 0,
+	{ 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+    { "FUJIFILM FinePix S2Pro", 128, 0,
+	{ 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } },
+    { "FUJIFILM FinePix S3Pro", 0, 0,
+	{ 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } },
+    { "FUJIFILM FinePix S5Pro", 0, 0,
+	{ 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+    { "FUJIFILM FinePix S5000", 0, 0,
+	{ 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } },
+    { "FUJIFILM FinePix S5100", 0, 0x3e00,
+	{ 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+    { "FUJIFILM FinePix S5500", 0, 0x3e00,
+	{ 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+    { "FUJIFILM FinePix S5200", 0, 0,
+	{ 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+    { "FUJIFILM FinePix S5600", 0, 0,
+	{ 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+    { "FUJIFILM FinePix S6", 0, 0,
+	{ 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } },
+    { "FUJIFILM FinePix S7000", 0, 0,
+	{ 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } },
+    { "FUJIFILM FinePix S9000", 0, 0,
+	{ 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+    { "FUJIFILM FinePix S9500", 0, 0,
+	{ 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+    { "FUJIFILM FinePix S9100", 0, 0,
+	{ 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+    { "FUJIFILM FinePix S9600", 0, 0,
+	{ 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+    { "FUJIFILM IS-1", 0, 0,
+	{ 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } },
+    { "FUJIFILM IS Pro", 0, 0,
+	{ 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+    { "Imacon Ixpress", 0, 0,		/* DJC */
+	{ 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } },
+    { "KODAK NC2000", 0, 0,
+	{ 13891,-6055,-803,-465,9919,642,2121,82,1291 } },
+    { "Kodak DCS315C", 8, 0,
+	{ 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } },
+    { "Kodak DCS330C", 8, 0,
+	{ 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } },
+    { "KODAK DCS420", 0, 0,
+	{ 10868,-1852,-644,-1537,11083,484,2343,628,2216 } },
+    { "KODAK DCS460", 0, 0,
+	{ 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+    { "KODAK EOSDCS1", 0, 0,
+	{ 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+    { "KODAK EOSDCS3B", 0, 0,
+	{ 9898,-2700,-940,-2478,12219,206,1985,634,1031 } },
+    { "Kodak DCS520C", 180, 0,
+	{ 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+    { "Kodak DCS560C", 188, 0,
+	{ 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+    { "Kodak DCS620C", 180, 0,
+	{ 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } },
+    { "Kodak DCS620X", 185, 0,
+	{ 13095,-6231,154,12221,-21,-2137,895,4602,2258 } },
+    { "Kodak DCS660C", 214, 0,
+	{ 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } },
+    { "Kodak DCS720X", 0, 0,
+	{ 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } },
+    { "Kodak DCS760C", 0, 0,
+	{ 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } },
+    { "Kodak DCS Pro SLR", 0, 0,
+	{ 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+    { "Kodak DCS Pro 14nx", 0, 0,
+	{ 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+    { "Kodak DCS Pro 14", 0, 0,
+	{ 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } },
+    { "Kodak ProBack645", 0, 0,
+	{ 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } },
+    { "Kodak ProBack", 0, 0,
+	{ 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } },
+    { "KODAK P712", 0, 0,
+	{ 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } },
+    { "KODAK P850", 0, 0xf7c,
+	{ 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } },
+    { "KODAK P880", 0, 0xfff,
+	{ 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } },
+    { "Leaf CMost", 0, 0,
+	{ 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
+    { "Leaf Valeo 6", 0, 0,
+	{ 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
+    { "Leaf Aptus 54S", 0, 0,
+	{ 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
+    { "Leaf Aptus 65", 0, 0,
+	{ 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+    { "Leaf Aptus 75", 0, 0,
+	{ 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+    { "Leaf", 0, 0,
+	{ 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
+    { "Mamiya ZD", 0, 0,
+	{ 7645,2579,-1363,-8689,16717,2015,-3712,5941,5961 } },
+    { "Micron 2010", 110, 0,		/* DJC */
+	{ 16695,-3761,-2151,155,9682,163,3433,951,4904 } },
+    { "Minolta DiMAGE 5", 0, 0xf7d,
+	{ 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } },
+    { "Minolta DiMAGE 7Hi", 0, 0xf7d,
+	{ 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 } },
+    { "Minolta DiMAGE 7", 0, 0xf7d,
+	{ 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } },
+    { "Minolta DiMAGE A1", 0, 0xf8b,
+	{ 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } },
+    { "MINOLTA DiMAGE A200", 0, 0,
+	{ 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } },
+    { "Minolta DiMAGE A2", 0, 0xf8f,
+	{ 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } },
+    { "Minolta DiMAGE Z2", 0, 0,	/* DJC */
+	{ 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
+    { "MINOLTA DYNAX 5", 0, 0xffb,
+	{ 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } },
+    { "MINOLTA DYNAX 7", 0, 0xffb,
+	{ 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } },
+    { "MOTOROLA PIXL", 0, 0,		/* DJC */
+	{ 8898,-989,-1033,-3292,11619,1674,-661,3178,5216 } },
+    { "NIKON D100", 0, 0,
+	{ 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } },
+    { "NIKON D1H", 0, 0,
+	{ 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } },
+    { "NIKON D1X", 0, 0,
+	{ 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } },
+    { "NIKON D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */
+	{ 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } },
+    { "NIKON D2H", 0, 0,
+	{ 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } },
+    { "NIKON D2X", 0, 0,
+	{ 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } },
+    { "NIKON D40X", 0, 0,
+	{ 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } },
+    { "NIKON D40", 0, 0,
+	{ 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } },
+    { "NIKON D50", 0, 0,
+	{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+    { "NIKON D60", 0, 0,
+	{ 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
+    { "NIKON D700", 0, 0,
+	{ 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+    { "NIKON D70", 0, 0,
+	{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+    { "NIKON D80", 0, 0,
+	{ 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } },
+    { "NIKON D90", 0, 0xf00,
+	{ 7309,-1403,-519,-8474,16008,2622,-2434,2826,8064 } },
+    { "NIKON D200", 0, 0xfbc,
+	{ 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } },
+    { "NIKON D300", 0, 0,
+	{ 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } },
+    { "NIKON D3X", 0, 0,
+	{ 7171,-1986,-648,-8085,15555,2718,-2170,2512,7457 } },
+    { "NIKON D3", 0, 0,
+	{ 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+    { "NIKON E950", 0, 0x3dd,		/* DJC */
+	{ -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
+    { "NIKON E995", 0, 0,	/* copied from E5000 */
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E2100", 0, 0,	/* copied from Z2, new white balance */
+	{ 13142,-4152,-1596,-4655,12374,2282,-1769,2696,6711} },
+    { "NIKON E2500", 0, 0,
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E4300", 0, 0,	/* copied from Minolta DiMAGE Z2 */
+	{ 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
+    { "NIKON E4500", 0, 0,
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E5000", 0, 0,
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E5400", 0, 0,
+	{ 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } },
+    { "NIKON E5700", 0, 0,
+	{ -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } },
+    { "NIKON E8400", 0, 0,
+	{ 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } },
+    { "NIKON E8700", 0, 0,
+	{ 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
+    { "NIKON E8800", 0, 0,
+	{ 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } },
+    { "NIKON COOLPIX P6000", 0, 0,
+	{ 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } },
+    { "OLYMPUS C5050", 0, 0,
+	{ 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } },
+    { "OLYMPUS C5060", 0, 0,
+	{ 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } },
+    { "OLYMPUS C7070", 0, 0,
+	{ 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } },
+    { "OLYMPUS C70", 0, 0,
+	{ 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } },
+    { "OLYMPUS C80", 0, 0,
+	{ 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } },
+    { "OLYMPUS E-10", 0, 0xffc0,
+	{ 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } },
+    { "OLYMPUS E-1", 0, 0xfff0,
+	{ 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } },
+    { "OLYMPUS E-20", 0, 0xffc0,
+	{ 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } },
+    { "OLYMPUS E-300", 0, 0,
+	{ 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } },
+    { "OLYMPUS E-330", 0, 0,
+	{ 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } },
+    { "OLYMPUS E-30", 0, 0,
+	{ 8144,-1861,-1111,-7763,15894,1929,-1865,2542,7607 } },
+    { "OLYMPUS E-3", 0, 0xf99,
+	{ 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } },
+    { "OLYMPUS E-400", 0, 0xfff0,
+	{ 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } },
+    { "OLYMPUS E-410", 0, 0xf6a,
+	{ 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } },
+    { "OLYMPUS E-420", 0, 0xfd7,
+	{ 8746,-2425,-1095,-7594,15612,2073,-1780,2309,7416 } },
+    { "OLYMPUS E-500", 0, 0,
+	{ 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } },
+    { "OLYMPUS E-510", 0, 0xf6a,
+	{ 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } },
+    { "OLYMPUS E-520", 0, 0xfd2,
+	{ 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } },
+    { "OLYMPUS SP350", 0, 0,
+	{ 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } },
+    { "OLYMPUS SP3", 0, 0,
+	{ 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } },
+    { "OLYMPUS SP500UZ", 0, 0xfff,
+	{ 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } },
+    { "OLYMPUS SP510UZ", 0, 0xffe,
+	{ 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } },
+    { "OLYMPUS SP550UZ", 0, 0xffe,
+	{ 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } },
+    { "OLYMPUS SP560UZ", 0, 0xff9,
+	{ 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } },
+    { "OLYMPUS SP570UZ", 0, 0,
+	{ 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } },
+    { "PENTAX *ist DL2", 0, 0,
+	{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+    { "PENTAX *ist DL", 0, 0,
+	{ 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } },
+    { "PENTAX *ist DS2", 0, 0,
+	{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+    { "PENTAX *ist DS", 0, 0,
+	{ 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } },
+    { "PENTAX *ist D", 0, 0,
+	{ 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } },
+    { "PENTAX K10D", 0, 0,
+	{ 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } },
+    { "PENTAX K1", 0, 0,
+	{ 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } },
+    { "PENTAX K20D", 0, 0,
+	{ 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } },
+    { "PENTAX K200D", 0, 0,
+	{ 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } },
+    { "PENTAX K2000", 0, 0,
+	{ 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+    { "PENTAX K-m", 0, 0,
+	{ 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+    { "Panasonic DMC-FZ8", 0, 0xf7f0,
+	{ 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } },
+    { "Panasonic DMC-FZ18", 0, 0,
+	{ 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } },
+    { "Panasonic DMC-FZ28", 15, 0xfff,
+	{ 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } },
+    { "Panasonic DMC-FZ30", 0, 0xf94c,
+	{ 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
+    { "Panasonic DMC-FZ50", 0, 0xfff0,	/* aka "LEICA V-LUX1" */
+	{ 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
+    { "Panasonic DMC-L10", 15, 0xf96,
+	{ 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } },
+    { "Panasonic DMC-L1", 0, 0xf7fc,	/* aka "LEICA DIGILUX 3" */
+	{ 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
+    { "Panasonic DMC-LC1", 0, 0,	/* aka "LEICA DIGILUX 2" */
+	{ 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
+    { "Panasonic DMC-LX1", 0, 0xf7f0,	/* aka "LEICA D-LUX2" */
+	{ 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
+    { "Panasonic DMC-LX2", 0, 0,	/* aka "LEICA D-LUX3" */
+	{ 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
+    { "Panasonic DMC-LX3", 15, 0xfff,	/* aka "LEICA D-LUX4" */
+	{ 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
+    { "Panasonic DMC-FX150", 15, 0xfff,
+	{ 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } },
+    { "Panasonic DMC-G1", 15, 0xfff,
+	{ 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } },
+    { "Panasonic DMC-GH1", 15, 0xfff,	/* DJC */
+	{ 7808,-2387,-480,-2859,10002,2857,-1001,2012,4915 } },
+    { "Phase One H 20", 0, 0,		/* DJC */
+	{ 1313,1855,-109,-6715,15908,808,-327,1840,6020 } },
+    { "Phase One P 2", 0, 0,
+	{ 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } },
+    { "Phase One P 30", 0, 0,
+	{ 4516,-245,-37,-7020,14976,2173,-3206,4671,7087 } },
+    { "Phase One P 45", 0, 0,
+	{ 5053,-24,-117,-5684,14076,1702,-2619,4492,5849 } },
+    { "SAMSUNG GX-1", 0, 0,
+	{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+    { "Sinar", 0, 0,			/* DJC */
+	{ 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } },
+    { "SONY DSC-F828", 491, 0,
+	{ 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } },
+    { "SONY DSC-R1", 512, 0,
+	{ 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } },
+    { "SONY DSC-V3", 0, 0,
+	{ 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } },
+    { "SONY DSLR-A100", 0, 0xfeb,
+	{ 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } },
+    { "SONY DSLR-A200", 0, 0,
+	{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+    { "SONY DSLR-A300", 0, 0,
+	{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+    { "SONY DSLR-A350", 0, 0xffc,
+	{ 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } },
+    { "SONY DSLR-A700", 254, 0x1ffe,
+	{ 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } },
+    { "SONY DSLR-A900", 254, 0x1ffe,
+	{ 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } }
+  };
+  double cam_xyz[4][3];
+  char name[130];
+  int i, j;
+
+  sprintf (name, "%s %s", p_make, p_model);
+  for (i=0; i < sizeof table / sizeof *table; i++)
+    if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) {
+      if (table[i].t_black)   black   = (ushort) table[i].t_black;
+      if (table[i].t_maximum) maximum = (ushort) table[i].t_maximum;
+      for (j=0; j < 12; j++)
+#ifdef LIBRAW_LIBRARY_BUILD
+          imgdata.color.cam_xyz[0][j] = 
+#endif
+	cam_xyz[0][j] = table[i].trans[j] / 10000.0;
+      cam_xyz_coeff (cam_xyz);
+      break;
+    }
+}
+
+void CLASS simple_coeff (int index)
+{
+  static const float table[][12] = {
+  /* index 0 -- all Foveon cameras */
+  { 1.4032,-0.2231,-0.1016,-0.5263,1.4816,0.017,-0.0112,0.0183,0.9113 },
+  /* index 1 -- Kodak DC20 and DC25 */
+  { 2.25,0.75,-1.75,-0.25,-0.25,0.75,0.75,-0.25,-0.25,-1.75,0.75,2.25 },
+  /* index 2 -- Logitech Fotoman Pixtura */
+  { 1.893,-0.418,-0.476,-0.495,1.773,-0.278,-1.017,-0.655,2.672 },
+  /* index 3 -- Nikon E880, E900, and E990 */
+  { -1.936280,  1.800443, -1.448486,  2.584324,
+     1.405365, -0.524955, -0.289090,  0.408680,
+    -1.204965,  1.082304,  2.941367, -1.818705 }
+  };
+  int i, c;
+
+  for (raw_color = i=0; i < 3; i++)
+    FORCC rgb_cam[i][c] = table[index][i*colors+c];
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.rgb_cam_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+}
+
+short CLASS guess_byte_order (int words)
+{
+  uchar test[4][2];
+  int t=2, msb;
+  double diff, sum[2] = {0,0};
+
+  fread (test[0], 2, 2, ifp);
+  for (words-=2; words--; ) {
+    fread (test[t], 2, 1, ifp);
+    for (msb=0; msb < 2; msb++) {
+      diff = (test[t^2][msb] << 8 | test[t^2][!msb])
+	   - (test[t  ][msb] << 8 | test[t  ][!msb]);
+      sum[msb] += diff*diff;
+    }
+    t = (t+1) & 3;
+  }
+  return sum[0] < sum[1] ? 0x4d4d : 0x4949;
+}
+
+
+/*
+   Identify which camera created this file, and set global variables
+   accordingly.
+ */
+void CLASS identify()
+{
+  char head[32], *cp;
+  unsigned hlen, fsize, i, c, is_canon;
+  struct jhead jh;
+  static const struct {
+    int fsize;
+    char t_make[12], t_model[19], withjpeg;
+  } table[] = {
+    {    62464, "Kodak",    "DC20"            ,0 },
+    {   124928, "Kodak",    "DC20"            ,0 },
+    {  1652736, "Kodak",    "DCS200"          ,0 },
+    {  4159302, "Kodak",    "C330"            ,0 },
+    {  4162462, "Kodak",    "C330"            ,0 },
+    {   460800, "Kodak",    "C603v"           ,0 },
+    {   614400, "Kodak",    "C603v"           ,0 },
+    {  6163328, "Kodak",    "C603"            ,0 },
+    {  6166488, "Kodak",    "C603"            ,0 },
+    {  9116448, "Kodak",    "C603y"           ,0 },
+    {   311696, "ST Micro", "STV680 VGA"      ,0 },  /* SPYz */
+    {   614400, "Kodak",    "KAI-0340"        ,0 },
+    {   787456, "Creative", "PC-CAM 600"      ,0 },
+    {  1138688, "Minolta",  "RD175"           ,0 },
+    {  3840000, "Foculus",  "531C"            ,0 },
+    {   786432, "AVT",      "F-080C"          ,0 },
+    {  1447680, "AVT",      "F-145C"          ,0 },
+    {  1920000, "AVT",      "F-201C"          ,0 },
+    {  5067304, "AVT",      "F-510C"          ,0 },
+    { 10134608, "AVT",      "F-510C"          ,0 },
+    { 16157136, "AVT",      "F-810C"          ,0 },
+    {  1409024, "Sony",     "XCD-SX910CR"     ,0 },
+    {  2818048, "Sony",     "XCD-SX910CR"     ,0 },
+    {  3884928, "Micron",   "2010"            ,0 },
+    {  6624000, "Pixelink", "A782"            ,0 },
+    { 13248000, "Pixelink", "A782"            ,0 },
+    {  6291456, "RoverShot","3320AF"          ,0 },
+    {  6553440, "Canon",    "PowerShot A460"  ,0 },
+    {  6653280, "Canon",    "PowerShot A530"  ,0 },
+    {  6573120, "Canon",    "PowerShot A610"  ,0 },
+    {  9219600, "Canon",    "PowerShot A620"  ,0 },
+    { 10341600, "Canon",    "PowerShot A720"  ,0 },
+    { 10383120, "Canon",    "PowerShot A630"  ,0 },
+    { 12945240, "Canon",    "PowerShot A640"  ,0 },
+    { 15636240, "Canon",    "PowerShot A650"  ,0 },
+    {  5298000, "Canon",    "PowerShot SD300" ,0 },
+    {  7710960, "Canon",    "PowerShot S3 IS" ,0 },
+    { 15467760, "Canon",    "PowerShot SX110 IS",0 },
+    {  5939200, "OLYMPUS",  "C770UZ"          ,0 },
+    {  1581060, "NIKON",    "E900"            ,1 },  /* or E900s,E910 */
+    {  2465792, "NIKON",    "E950"            ,1 },  /* or E800,E700 */
+    {  2940928, "NIKON",    "E2100"           ,1 },  /* or E2500 */
+    {  4771840, "NIKON",    "E990"            ,1 },  /* or E995, Oly C3030Z */
+    {  4775936, "NIKON",    "E3700"           ,1 },  /* or Optio 33WR */
+    {  5869568, "NIKON",    "E4300"           ,1 },  /* or DiMAGE Z2 */
+    {  5865472, "NIKON",    "E4500"           ,1 },
+    {  7438336, "NIKON",    "E5000"           ,1 },  /* or E5700 */
+    {  8998912, "NIKON",    "COOLPIX S6"      ,1 },
+    {  1976352, "CASIO",    "QV-2000UX"       ,1 },
+    {  3217760, "CASIO",    "QV-3*00EX"       ,1 },
+    {  6218368, "CASIO",    "QV-5700"         ,1 },
+    {  6054400, "CASIO",    "QV-R41"          ,1 },
+    {  7530816, "CASIO",    "QV-R51"          ,1 },
+    {  7684000, "CASIO",    "QV-4000"         ,1 },
+    {  4948608, "CASIO",    "EX-S100"         ,1 },
+    {  7542528, "CASIO",    "EX-Z50"          ,1 },
+    {  7753344, "CASIO",    "EX-Z55"          ,1 },
+    {  7426656, "CASIO",    "EX-P505"         ,1 },
+    {  9313536, "CASIO",    "EX-P600"         ,1 },
+    { 10979200, "CASIO",    "EX-P700"         ,1 },
+    {  3178560, "PENTAX",   "Optio S"         ,1 },
+    {  4841984, "PENTAX",   "Optio S"         ,1 },
+    {  6114240, "PENTAX",   "Optio S4"        ,1 },  /* or S4i, CASIO EX-Z4 */
+    { 10702848, "PENTAX",   "Optio 750Z"      ,1 },
+    { 16098048, "SAMSUNG",  "S85"             ,1 },
+    { 16215552, "SAMSUNG",  "S85"             ,1 },
+    { 12582980, "Sinar",    ""                ,0 },
+    { 33292868, "Sinar",    ""                ,0 },
+    { 44390468, "Sinar",    ""                ,0 } };
+  static const char *corp[] =
+    { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX",
+      "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One",
+      "SAMSUNG", "Mamiya", "MOTOROLA" };
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY,0,2);
+#endif
+
+  tiff_flip = flip = filters = -1;	/* 0 is valid, so -1 is unknown */
+  raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0;
+  maximum = height = width = top_margin = left_margin = 0;
+  cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0;
+  iso_speed = shutter = aperture = focal_len = unique_id = 0;
+  memset (gpsdata, 0, sizeof gpsdata);
+  memset (white, 0, sizeof white);
+  thumb_offset = thumb_length = thumb_width = thumb_height = 0;
+  load_raw = thumb_load_raw = 0;
+  write_thumb = &CLASS jpeg_thumb;
+  data_offset = meta_length = tiff_bps = tiff_compress = 0;
+  kodak_cbpp = zero_after_ff = dng_version = load_flags = 0;
+  timestamp = shot_order = tiff_samples = black = is_foveon = 0;
+  mix_green = profile_length = data_error = zero_is_bad = 0;
+  pixel_aspect = is_raw = raw_color = 1;
+  tile_width = tile_length = INT_MAX;
+  for (i=0; i < 4; i++) {
+    cam_mul[i] = i == 1;
+    pre_mul[i] = i < 3;
+    FORC3 cmatrix[c][i] = 0;
+    FORC3 rgb_cam[c][i] = c == i;
+  }
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.cmatrix_state = LIBRAW_COLORSTATE_INIT;
+  color_flags.rgb_cam_state = LIBRAW_COLORSTATE_INIT;
+  color_flags.pre_mul_state = LIBRAW_COLORSTATE_INIT;
+  color_flags.cam_mul_state = LIBRAW_COLORSTATE_INIT;
+#endif
+  colors = 3;
+  tiff_bps = 12;
+  for (i=0; i < 0x4000; i++) curve[i] = i;
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.curve_state = LIBRAW_COLORSTATE_INIT;
+#endif
+
+  order = get2();
+  hlen = get4();
+  fseek (ifp, 0, SEEK_SET);
+  fread (head, 1, 32, ifp);
+  fseek (ifp, 0, SEEK_END);
+  fsize = ftell(ifp);
+  if ((cp = (char *) memmem (head, 32, "MMMM", 4)) ||
+      (cp = (char *) memmem (head, 32, "IIII", 4))) {
+    parse_phase_one (cp-head);
+    if (cp-head) parse_tiff(0);
+  } else if (order == 0x4949 || order == 0x4d4d) {
+    if (!memcmp (head+6,"HEAPCCDR",8)) {
+      data_offset = hlen;
+      parse_ciff (hlen, fsize - hlen);
+    } else {
+      parse_tiff(0);
+    }
+  } else if (!memcmp (head,"\xff\xd8\xff\xe1",4) &&
+	     !memcmp (head+6,"Exif",4)) {
+    fseek (ifp, 4, SEEK_SET);
+    data_offset = 4 + get2();
+    fseek (ifp, data_offset, SEEK_SET);
+    if (fgetc(ifp) != 0xff)
+      parse_tiff(12);
+    thumb_offset = 0;
+  } else if (!memcmp (head+25,"ARECOYK",7)) {
+    strcpy (make, "Contax");
+    strcpy (model,"N Digital");
+    fseek (ifp, 33, SEEK_SET);
+    get_timestamp(1);
+    fseek (ifp, 60, SEEK_SET);
+    FORC4 cam_mul[c ^ (c >> 1)] = get4();
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+  } else if (!strcmp (head, "PXN")) {
+    strcpy (make, "Logitech");
+    strcpy (model,"Fotoman Pixtura");
+  } else if (!strcmp (head, "qktk")) {
+    strcpy (make, "Apple");
+    strcpy (model,"QuickTake 100");
+  } else if (!strcmp (head, "qktn")) {
+    strcpy (make, "Apple");
+    strcpy (model,"QuickTake 150");
+  } else if (!memcmp (head,"FUJIFILM",8)) {
+    fseek (ifp, 84, SEEK_SET);
+    thumb_offset = get4();
+    thumb_length = get4();
+    fseek (ifp, 92, SEEK_SET);
+    parse_fuji (get4());
+    if (thumb_offset > 120) {
+      fseek (ifp, 120, SEEK_SET);
+      is_raw += (i = get4()) && 1;
+      if (is_raw == 2 && shot_select)
+	parse_fuji (i);
+    }
+    fseek (ifp, 100, SEEK_SET);
+    data_offset = get4();
+    parse_tiff (thumb_offset+12);
+  } else if (!memcmp (head,"RIFF",4)) {
+    fseek (ifp, 0, SEEK_SET);
+    parse_riff();
+  } else if (!memcmp (head,"\0\001\0\001\0@",6)) {
+    fseek (ifp, 6, SEEK_SET);
+    fread (make, 1, 8, ifp);
+    fread (model, 1, 8, ifp);
+    fread (model2, 1, 16, ifp);
+    data_offset = get2();
+    get2();
+    raw_width = get2();
+    raw_height = get2();
+    load_raw = &CLASS nokia_load_raw;
+    filters = 0x61616161;
+  } else if (!memcmp (head,"DSC-Image",9))
+    parse_rollei();
+  else if (!memcmp (head,"PWAD",4))
+    parse_sinar_ia();
+  else if (!memcmp (head,"\0MRM",4))
+    parse_minolta(0);
+  else if (!memcmp (head,"FOVb",4))
+    parse_foveon();
+  else if (!memcmp (head,"CI",2))
+    parse_cine();
+  else
+    for (i=0; i < sizeof table / sizeof *table; i++)
+      if (fsize == table[i].fsize) {
+	strcpy (make,  table[i].t_make );
+	strcpy (model, table[i].t_model);
+	if (table[i].withjpeg)
+	  parse_external_jpeg();
+      }
+  if (make[0] == 0) parse_smal (0, fsize);
+  if (make[0] == 0) parse_jpeg (is_raw = 0);
+
+  for (i=0; i < sizeof corp / sizeof *corp; i++)
+    if (strstr (make, corp[i]))		/* Simplify company names */
+	strcpy (make, corp[i]);
+  if (!strncmp (make,"KODAK",5) &&
+	((cp = strstr(model,"DIGITAL CAMERA")) ||
+	 (cp = strstr(model,"FILE VERSION"))))
+     *cp = 0;
+  cp = make + strlen(make);		/* Remove trailing spaces */
+  while (*--cp == ' ') *cp = 0;
+  cp = model + strlen(model);
+  while (*--cp == ' ') *cp = 0;
+  i = strlen(make);			/* Remove make from model */
+  if (!strncasecmp (model, make, i) && model[i++] == ' ')
+    memmove (model, model+i, 64-i);
+  if (!strncmp (model,"Digital Camera ",15))
+    strcpy (model, model+15);
+  desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0;
+  if (!is_raw) goto notraw;
+
+  if (!maximum) maximum = (1 << tiff_bps) - 1;
+  if (!height) height = raw_height;
+  if (!width)  width  = raw_width;
+  if (fuji_width) {
+    width = height + fuji_width;
+    height = width - 1;
+    pixel_aspect = 1;
+  }
+  if (height == 2624 && width == 3936)	/* Pentax K10D and Samsung GX10 */
+    { height  = 2616;   width  = 3896; }
+  if (height == 3136 && width == 4864)	/* Pentax K20D */
+    { height  = 3124;   width  = 4688; }
+  if (height == 3014 && width == 4096)	/* Ricoh GX200 */
+			width  = 4014;
+  if (dng_version) {
+    if (filters == UINT_MAX) filters = 0;
+    if (filters) is_raw = tiff_samples;
+    else	 colors = tiff_samples;
+    if (tiff_compress == 1)
+      load_raw = &CLASS adobe_dng_load_raw_nc;
+    if (tiff_compress == 7)
+      load_raw = &CLASS adobe_dng_load_raw_lj;
+    goto dng_skip;
+  }
+  if ((is_canon = !strcmp(make,"Canon")))
+    load_raw = memcmp (head+6,"HEAPCCDR",8) ?
+	&CLASS lossless_jpeg_load_raw : &CLASS canon_compressed_load_raw;
+  if (!strcmp(make,"NIKON")) {
+    if (!load_raw)
+      load_raw = &CLASS packed_12_load_raw;
+    if (model[0] == 'E')
+      load_flags |= !data_offset << 2 | 2;
+  }
+  if (!strcmp(make,"CASIO")) {
+    load_raw = &CLASS packed_12_load_raw;
+    maximum = 0xf7f;
+  }
+
+/* Set parameters based on camera name (for non-DNG files). */
+
+  if (is_foveon) {
+    if (height*2 < width) pixel_aspect = 0.5;
+    if (height   > width) pixel_aspect = 2;
+    filters = 0;
+    load_raw = &CLASS foveon_load_raw;
+    simple_coeff(0);
+  } else if (is_canon && tiff_bps == 15) {
+    switch (width) {
+      case 3344: width -= 66;
+      case 3872: width -= 6;
+    }
+    filters = 0;
+    load_raw = &CLASS canon_sraw_load_raw;
+  } else if (!strcmp(model,"PowerShot 600")) {
+    height = 613;
+    width  = 854;
+    raw_width = 896;
+    pixel_aspect = 607/628.0;
+    colors = 4;
+    filters = 0xe1e4e1e4;
+    load_raw = &CLASS canon_600_load_raw;
+  } else if (!strcmp(model,"PowerShot A5") ||
+	     !strcmp(model,"PowerShot A5 Zoom")) {
+    height = 773;
+    width  = 960;
+    raw_width = 992;
+    pixel_aspect = 256/235.0;
+    colors = 4;
+    filters = 0x1e4e1e4e;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A50")) {
+    height =  968;
+    width  = 1290;
+    raw_width = 1320;
+    colors = 4;
+    filters = 0x1b4e4b1e;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot Pro70")) {
+    height = 1024;
+    width  = 1552;
+    colors = 4;
+    filters = 0x1e4b4e1b;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot SD300")) {
+    height = 1752;
+    width  = 2344;
+    raw_height = 1766;
+    raw_width  = 2400;
+    top_margin  = 12;
+    left_margin = 12;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A460")) {
+    height = 1960;
+    width  = 2616;
+    raw_height = 1968;
+    raw_width  = 2664;
+    top_margin  = 4;
+    left_margin = 4;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A530")) {
+    height = 1984;
+    width  = 2620;
+    raw_height = 1992;
+    raw_width  = 2672;
+    top_margin  = 6;
+    left_margin = 10;
+    load_raw = &CLASS canon_a5_load_raw;
+    raw_color = 0;
+  } else if (!strcmp(model,"PowerShot A610")) {
+    if (canon_s2is()) strcpy (model+10, "S2 IS");
+    height = 1960;
+    width  = 2616;
+    raw_height = 1968;
+    raw_width  = 2672;
+    top_margin  = 8;
+    left_margin = 12;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A620")) {
+    height = 2328;
+    width  = 3112;
+    raw_height = 2340;
+    raw_width  = 3152;
+    top_margin  = 12;
+    left_margin = 36;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A720")) {
+    height = 2472;
+    width  = 3298;
+    raw_height = 2480;
+    raw_width  = 3336;
+    top_margin  = 5;
+    left_margin = 6;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A630")) {
+    height = 2472;
+    width  = 3288;
+    raw_height = 2484;
+    raw_width  = 3344;
+    top_margin  = 6;
+    left_margin = 12;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A640")) {
+    height = 2760;
+    width  = 3672;
+    raw_height = 2772;
+    raw_width  = 3736;
+    top_margin  = 6;
+    left_margin = 12;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot A650")) {
+    height = 3024;
+    width  = 4032;
+    raw_height = 3048;
+    raw_width  = 4104;
+    top_margin  = 12;
+    left_margin = 48;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot S3 IS")) {
+    height = 2128;
+    width  = 2840;
+    raw_height = 2136;
+    raw_width  = 2888;
+    top_margin  = 8;
+    left_margin = 44;
+    load_raw = &CLASS canon_a5_load_raw;
+  } else if (!strcmp(model,"PowerShot SX110 IS")) {
+    height = 2760;
+    width  = 3684;
+    raw_height = 2772;
+    raw_width  = 3720;
+    top_margin  = 12;
+    left_margin = 6;
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 40;
+    zero_is_bad = 1;
+  } else if (!strcmp(model,"PowerShot Pro90 IS")) {
+    width  = 1896;
+    colors = 4;
+    filters = 0xb4b4b4b4;
+  } else if (is_canon && raw_width == 2144) {
+    height = 1550;
+    width  = 2088;
+    top_margin  = 8;
+    left_margin = 4;
+    if (!strcmp(model,"PowerShot G1")) {
+      colors = 4;
+      filters = 0xb4b4b4b4;
+    }
+  } else if (is_canon && raw_width == 2224) {
+    height = 1448;
+    width  = 2176;
+    top_margin  = 6;
+    left_margin = 48;
+  } else if (is_canon && raw_width == 2376) {
+    height = 1720;
+    width  = 2312;
+    top_margin  = 6;
+    left_margin = 12;
+  } else if (is_canon && raw_width == 2672) {
+    height = 1960;
+    width  = 2616;
+    top_margin  = 6;
+    left_margin = 12;
+  } else if (is_canon && raw_width == 3152) {
+    height = 2056;
+    width  = 3088;
+    top_margin  = 12;
+    left_margin = 64;
+    if (unique_id == 0x80000170)
+      adobe_coeff ("Canon","EOS 300D");
+  } else if (is_canon && raw_width == 3160) {
+    height = 2328;
+    width  = 3112;
+    top_margin  = 12;
+    left_margin = 44;
+  } else if (is_canon && raw_width == 3344) {
+    height = 2472;
+    width  = 3288;
+    top_margin  = 6;
+    left_margin = 4;
+  } else if (!strcmp(model,"EOS D2000C")) {
+    filters = 0x61616161;
+    black = curve[200];
+  } else if (is_canon && raw_width == 3516) {
+    top_margin  = 14;
+    left_margin = 42;
+    if (unique_id == 0x80000189)
+      adobe_coeff ("Canon","EOS 350D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 3596) {
+    top_margin  = 12;
+    left_margin = 74;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 3944) {
+    height = 2602;
+    width  = 3908;
+    top_margin  = 18;
+    left_margin = 30;
+  } else if (is_canon && raw_width == 3948) {
+    top_margin  = 18;
+    left_margin = 42;
+    height -= 2;
+    if (unique_id == 0x80000236)
+      adobe_coeff ("Canon","EOS 400D");
+    if (unique_id == 0x80000254)
+      adobe_coeff ("Canon","EOS 1000D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 3984) {
+    top_margin  = 20;
+    left_margin = 76;
+    height -= 2;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4104) {
+    height = 3024;
+    width  = 4032;
+    top_margin  = 12;
+    left_margin = 48;
+  } else if (is_canon && raw_width == 4152) {
+    top_margin  = 12;
+    left_margin = 192;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4312) {
+    top_margin  = 18;
+    left_margin = 22;
+    height -= 2;
+    if (unique_id == 0x80000176)
+      adobe_coeff ("Canon","EOS 450D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4476) {
+    top_margin  = 34;
+    left_margin = 90;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4480) {
+    height = 3326;
+    width  = 4432;
+    top_margin  = 10;
+    left_margin = 12;
+    filters = 0x49494949;
+  } else if (is_canon && raw_width == 1208) {
+    top_margin = unique_id == 0x80000261 ? 51:26;
+    left_margin = 62;
+    raw_width = width *= 4;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 1448) {
+    top_margin  = 51;
+    left_margin = 158;
+    raw_width = width *= 4;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 5108) {
+    top_margin  = 13;
+    left_margin = 98;
+canon_cr2:
+    height -= top_margin;
+    width  -= left_margin;
+  } else if (is_canon && raw_width == 5712) {
+    height = 3752;
+    width  = 5640;
+    top_margin  = 20;
+    left_margin = 62;
+  } else if (!strcmp(model,"D1")) {
+    cam_mul[0] *= 256/527.0;
+    cam_mul[2] *= 256/317.0;
+  } else if (!strcmp(model,"D1X")) {
+    width -= 4;
+    pixel_aspect = 0.5;
+  } else if (!strcmp(model,"D40X") ||
+	     !strcmp(model,"D60")  ||
+	     !strcmp(model,"D80")) {
+    height -= 3;
+    width  -= 4;
+  } else if (!strcmp(model,"D3")   ||
+	     !strcmp(model,"D700")) {
+    width -= 4;
+    left_margin = 2;
+  } else if (!strncmp(model,"D40",3) ||
+	     !strncmp(model,"D50",3) ||
+	     !strncmp(model,"D70",3)) {
+    width--;
+  } else if (!strcmp(model,"D90")) {
+    width -= 42;
+  } else if (!strcmp(model,"D100")) {
+    if (tiff_compress == 34713 && !nikon_is_compressed()) {
+      load_raw = &CLASS packed_12_load_raw;
+      load_flags |= 1;
+      raw_width = (width += 3) + 3;
+    }
+  } else if (!strcmp(model,"D200")) {
+    left_margin = 1;
+    width -= 4;
+    filters = 0x94949494;
+  } else if (!strncmp(model,"D2H",3)) {
+    left_margin = 6;
+    width -= 14;
+  } else if (!strncmp(model,"D2X",3)) {
+    if (width == 3264) width -= 32;
+    else width -= 8;
+  } else if (!strcmp(model,"D300")) {
+    width -= 32;
+  } else if (!strcmp(model,"COOLPIX P6000")) {
+    load_flags = 24;
+    filters = 0x94949494;
+  } else if (fsize == 1581060) {
+    height = 963;
+    width = 1287;
+    raw_width = 1632;
+    load_raw = &CLASS nikon_e900_load_raw;
+    maximum = 0x3f4;
+    colors = 4;
+    filters = 0x1e1e1e1e;
+    simple_coeff(3);
+    pre_mul[0] = 1.2085;
+    pre_mul[1] = 1.0943;
+    pre_mul[3] = 1.1103;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (fsize == 2465792) {
+    height = 1203;
+    width  = 1616;
+    raw_width = 2048;
+    load_raw = &CLASS nikon_e900_load_raw;
+    colors = 4;
+    filters = 0x4b4b4b4b;
+    adobe_coeff ("NIKON","E950");
+  } else if (fsize == 4771840) {
+    height = 1540;
+    width  = 2064;
+    colors = 4;
+    filters = 0xe1e1e1e1;
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 6;
+    if (!timestamp && nikon_e995())
+      strcpy (model, "E995");
+    if (strcmp(model,"E995")) {
+      filters = 0xb4b4b4b4;
+      simple_coeff(3);
+      pre_mul[0] = 1.196;
+      pre_mul[1] = 1.246;
+      pre_mul[2] = 1.018;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+    }
+  } else if (!strcmp(model,"E2100")) {
+    if (!timestamp && !nikon_e2100()) goto cp_e2500;
+    height = 1206;
+    width  = 1616;
+    load_flags = 30;
+  } else if (!strcmp(model,"E2500")) {
+cp_e2500:
+    strcpy (model, "E2500");
+    height = 1204;
+    width  = 1616;
+    colors = 4;
+    filters = 0x4b4b4b4b;
+  } else if (fsize == 4775936) {
+    height = 1542;
+    width  = 2064;
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 30;
+    pre_mul[0] = 1.818;
+    pre_mul[2] = 1.618;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+    if (!timestamp) nikon_3700();
+    if (model[0] == 'E' && atoi(model+1) < 3700)
+      filters = 0x49494949;
+    if (!strcmp(model,"Optio 33WR")) {
+      flip = 1;
+      filters = 0x16161616;
+      pre_mul[0] = 1.331;
+      pre_mul[2] = 1.820;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+    }
+  } else if (fsize == 5869568) {
+    height = 1710;
+    width  = 2288;
+    filters = 0x16161616;
+    if (!timestamp && minolta_z2()) {
+      strcpy (make, "Minolta");
+      strcpy (model,"DiMAGE Z2");
+    }
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 6 + 24*(make[0] == 'M');
+  } else if (!strcmp(model,"E4500")) {
+    height = 1708;
+    width  = 2288;
+    colors = 4;
+    filters = 0xb4b4b4b4;
+  } else if (fsize == 7438336) {
+    height = 1924;
+    width  = 2576;
+    colors = 4;
+    filters = 0xb4b4b4b4;
+  } else if (fsize == 8998912) {
+    height = 2118;
+    width  = 2832;
+    maximum = 0xf83;
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 30;
+  } else if (!strcmp(model,"FinePix S5100") ||
+	     !strcmp(model,"FinePix S5500")) {
+    load_raw = &CLASS unpacked_load_raw;
+  } else if (!strcmp(make,"FUJIFILM")) {
+    if (!strcmp(model+7,"S2Pro")) {
+      strcpy (model+7," S2Pro");
+      height = 2144;
+      width  = 2880;
+      flip = 6;
+    } else
+      maximum = 0x3e00;
+    if (is_raw == 2 && shot_select)
+      maximum = 0x2f00;
+    top_margin = (raw_height - height)/2;
+    left_margin = (raw_width - width )/2;
+    if (is_raw == 2)
+      data_offset += (shot_select > 0) * ( fuji_layout ?
+		(raw_width *= 2) : raw_height*raw_width*2 );
+    fuji_width = width >> !fuji_layout;
+    width = (height >> fuji_layout) + fuji_width;
+    raw_height = height;
+    height = width - 1;
+    load_raw = &CLASS fuji_load_raw;
+    if (!(fuji_width & 1)) filters = 0x49494949;
+  } else if (!strcmp(model,"RD175")) {
+    height = 986;
+    width = 1534;
+    data_offset = 513;
+    filters = 0x61616161;
+    load_raw = &CLASS minolta_rd175_load_raw;
+  } else if (!strcmp(model,"KD-400Z")) {
+    height = 1712;
+    width  = 2312;
+    raw_width = 2336;
+    goto konica_400z;
+  } else if (!strcmp(model,"KD-510Z")) {
+    goto konica_510z;
+  } else if (!strcasecmp(make,"MINOLTA")) {
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xfff;
+    if (!strncmp(model,"DiMAGE A",8)) {
+      if (!strcmp(model,"DiMAGE A200"))
+	filters = 0x49494949;
+      load_raw = &CLASS packed_12_load_raw;
+    } else if (!strncmp(model,"ALPHA",5) ||
+	       !strncmp(model,"DYNAX",5) ||
+	       !strncmp(model,"MAXXUM",6)) {
+      sprintf (model+20, "DYNAX %-10s", model+6+(model[0]=='M'));
+      adobe_coeff (make, model+20);
+      load_raw = &CLASS packed_12_load_raw;
+    } else if (!strncmp(model,"DiMAGE G",8)) {
+      if (model[8] == '4') {
+	height = 1716;
+	width  = 2304;
+      } else if (model[8] == '5') {
+konica_510z:
+	height = 1956;
+	width  = 2607;
+	raw_width = 2624;
+      } else if (model[8] == '6') {
+	height = 2136;
+	width  = 2848;
+      }
+      data_offset += 14;
+      filters = 0x61616161;
+konica_400z:
+      load_raw = &CLASS unpacked_load_raw;
+      maximum = 0x3df;
+      order = 0x4d4d;
+    }
+  } else if (!strcmp(model,"*ist DS")) {
+    height -= 2;
+  } else if (!strcmp(model,"K20D")) {
+    filters = 0x16161616;
+  } else if (!strcmp(model,"Optio S")) {
+    if (fsize == 3178560) {
+      height = 1540;
+      width  = 2064;
+      load_raw = &CLASS eight_bit_load_raw;
+      cam_mul[0] *= 4;
+      cam_mul[2] *= 4;
+      pre_mul[0] = 1.391;
+      pre_mul[2] = 1.188;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+    } else {
+      height = 1544;
+      width  = 2068;
+      raw_width = 3136;
+      load_raw = &CLASS packed_12_load_raw;
+      maximum = 0xf7c;
+      pre_mul[0] = 1.137;
+      pre_mul[2] = 1.453;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+    }
+  } else if (fsize == 6114240) {
+    height = 1737;
+    width  = 2324;
+    raw_width = 3520;
+    load_raw = &CLASS packed_12_load_raw;
+    maximum = 0xf7a;
+    pre_mul[0] = 1.980;
+    pre_mul[2] = 1.570;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"Optio 750Z")) {
+    height = 2302;
+    width  = 3072;
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 30;
+  } else if (!strcmp(model,"S85")) {
+    height = 2448;
+    width  = 3264;
+    raw_width = fsize/height/2;
+    order = 0x4d4d;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xffff;
+  } else if (!strcmp(model,"STV680 VGA")) {
+    height = 484;
+    width  = 644;
+    load_raw = &CLASS eight_bit_load_raw;
+    flip = 2;
+    filters = 0x16161616;
+    black = 16;
+    pre_mul[0] = 1.097;
+    pre_mul[2] = 1.128;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"KAI-0340")) {
+    height = 477;
+    width  = 640;
+    order = 0x4949;
+    data_offset = 3840;
+    load_raw = &CLASS unpacked_load_raw;
+    pre_mul[0] = 1.561;
+    pre_mul[2] = 2.454;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"N95")) {
+    height = raw_height - (top_margin = 2);
+  } else if (!strcmp(model,"531C")) {
+    height = 1200;
+    width  = 1600;
+    load_raw = &CLASS unpacked_load_raw;
+    filters = 0x49494949;
+    pre_mul[1] = 1.218;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"F-080C")) {
+    height = 768;
+    width  = 1024;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"F-145C")) {
+    height = 1040;
+    width  = 1392;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"F-201C")) {
+    height = 1200;
+    width  = 1600;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"F-510C")) {
+    height = 1958;
+    width  = 2588;
+    load_raw = fsize < 7500000 ?
+	&CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+    maximum = 0xfff0;
+  } else if (!strcmp(model,"F-810C")) {
+    height = 2469;
+    width  = 3272;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xfff0;
+  } else if (!strcmp(model,"XCD-SX910CR")) {
+    height = 1024;
+    width  = 1375;
+    raw_width = 1376;
+    filters = 0x49494949;
+    maximum = 0x3ff;
+    load_raw = fsize < 2000000 ?
+	&CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+  } else if (!strcmp(model,"2010")) {
+    height = 1207;
+    width  = 1608;
+    order = 0x4949;
+    filters = 0x16161616;
+    data_offset = 3212;
+    maximum = 0x3ff;
+    load_raw = &CLASS unpacked_load_raw;
+  } else if (!strcmp(model,"A782")) {
+    height = 3000;
+    width  = 2208;
+    filters = 0x61616161;
+    load_raw = fsize < 10000000 ?
+	&CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+    maximum = 0xffc0;
+  } else if (!strcmp(model,"3320AF")) {
+    height = 1536;
+    raw_width = width = 2048;
+    filters = 0x61616161;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0x3ff;
+    pre_mul[0] = 1.717;
+    pre_mul[2] = 1.138;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+    fseek (ifp, 0x300000, SEEK_SET);
+    if ((order = guess_byte_order(0x10000)) == 0x4d4d) {
+      height -= (top_margin = 16);
+      width -= (left_margin = 28);
+      maximum = 0xf5c0;
+      strcpy (make, "ISG");
+      model[0] = 0;
+    }
+  } else if (!strcmp(make,"Hasselblad")) {
+    if (load_raw == &CLASS lossless_jpeg_load_raw)
+      load_raw = &CLASS hasselblad_load_raw;
+    if (raw_width == 7262) {
+      height = 5444;
+      width  = 7248;
+      top_margin  = 4;
+      left_margin = 7;
+      filters = 0x61616161;
+    } else if (raw_width == 4090) {
+      strcpy (model, "V96C");
+      height -= (top_margin = 6);
+      width -= (left_margin = 3) + 7;
+      filters = 0x61616161;
+    }
+  } else if (!strcmp(make,"Sinar")) {
+    if (!memcmp(head,"8BPS",4)) {
+      fseek (ifp, 14, SEEK_SET);
+      height = get4();
+      width  = get4();
+      filters = 0x61616161;
+      data_offset = 68;
+    }
+    if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+    maximum = 0x3fff;
+  } else if (!strcmp(make,"Leaf")) {
+    maximum = 0x3fff;
+    fseek (ifp, data_offset, SEEK_SET);
+    if (ljpeg_start (&jh, 1) && jh.bits == 15)
+      maximum = 0x1fff;
+    if (tiff_samples > 1) filters = 0;
+    if (tiff_samples > 1 || tile_length < raw_height)
+      load_raw = &CLASS leaf_hdr_load_raw;
+    if ((width | height) == 2048) {
+      if (tiff_samples == 1) {
+	filters = 1;
+	strcpy (cdesc, "RBTG");
+	strcpy (model, "CatchLight");
+	top_margin =  8; left_margin = 18; height = 2032; width = 2016;
+      } else {
+	strcpy (model, "DCB2");
+	top_margin = 10; left_margin = 16; height = 2028; width = 2022;
+      }
+    } else if (width+height == 3144+2060) {
+      if (!model[0]) strcpy (model, "Cantare");
+      if (width > height) {
+	 top_margin = 6; left_margin = 32; height = 2048;  width = 3072;
+	filters = 0x61616161;
+      } else {
+	left_margin = 6;  top_margin = 32;  width = 2048; height = 3072;
+	filters = 0x16161616;
+      }
+      if (!cam_mul[0] || model[0] == 'V') filters = 0;
+      else is_raw = tiff_samples;
+    } else if (width == 2116) {
+      strcpy (model, "Valeo 6");
+      height -= 2 * (top_margin = 30);
+      width -= 2 * (left_margin = 55);
+      filters = 0x49494949;
+    } else if (width == 3171) {
+      strcpy (model, "Valeo 6");
+      height -= 2 * (top_margin = 24);
+      width -= 2 * (left_margin = 24);
+      filters = 0x16161616;
+    }
+  } else if (!strcmp(make,"LEICA") || !strcmp(make,"Panasonic")) {
+    maximum = 0xfff0;
+    if ((fsize-data_offset) / (width*8/7) == height)
+      load_raw = &CLASS panasonic_load_raw;
+    if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+    switch (width) {
+      case 2568:
+	adobe_coeff ("Panasonic","DMC-LC1");  break;
+      case 3130:
+	left_margin = -14;
+      case 3170:
+	left_margin += 18;
+	width = 3096;
+	if (height > 2326) {
+	  height = 2326;
+	  top_margin = 13;
+	  filters = 0x49494949;
+	}
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ8");  break;
+      case 3213:
+	width -= 27;
+      case 3177:
+	width -= 10;
+	filters = 0x49494949;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-L1");  break;
+      case 3304:
+	width -= 17;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ30");  break;
+      case 3330:
+	width += 43;
+	left_margin = -6;
+	maximum = 0xf7f0;
+      case 3370:
+	width -= 82;
+	left_margin += 15;
+	if (height > 2480)
+	    height = 2480 - (top_margin = 10);
+	filters = 0x49494949;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ18");  break;
+      case 3690:
+	height -= 2;
+	left_margin = -14;
+	maximum = 0xf7f0;
+      case 3770:
+	width = 3672;
+	if (--height == 2798 && (height = 2760))
+	  top_margin = 15;
+	else filters = 0x49494949;
+	left_margin += 17;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ50");  break;
+      case 3710:
+	width = 3682;
+	filters = 0x49494949;
+	adobe_coeff ("Panasonic","DMC-L10");  break;
+      case 3724:
+	width -= 14;
+	if (height == 2450) height -= 2;
+      case 3836:
+	width -= 42;
+lx3:	filters = 0x16161616;
+	if (make[0] != 'P')
+	  adobe_coeff ("Panasonic","DMC-LX3");
+	break;
+      case 3880:
+	width -= 22;
+	left_margin = 6;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-LX1");  break;
+      case 4060:
+	if (!strcmp(model,"DMC-GH1")) goto gh1;
+	width = 3982;
+	if (height == 2250) goto lx3;
+	width = 4018;
+	filters = 0x49494949;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-G1");  break;
+      case 4172:
+      case 4396:
+gh1:	width -= 28;
+	filters = 0x49494949;
+	adobe_coeff ("Panasonic","DMC-GH1");  break;
+      case 4290:
+	height += 38;
+	left_margin = -14;
+	filters = 0x49494949;
+      case 4330:
+	width = 4248;
+	if ((height -= 39) == 2400)
+	  top_margin = 15;
+	left_margin += 17;
+	adobe_coeff ("Panasonic","DMC-LX2");  break;
+      case 4508:
+	height -= 6;
+	width = 4429;
+	filters = 0x16161616;
+	adobe_coeff ("Panasonic","DMC-FX150");  break;
+    }
+  } else if (!strcmp(model,"C770UZ")) {
+    height = 1718;
+    width  = 2304;
+    filters = 0x16161616;
+    load_raw = &CLASS packed_12_load_raw;
+    load_flags = 30;
+  } else if (!strcmp(make,"OLYMPUS")) {
+    height += height & 1;
+    filters = exif_cfa;
+    if (width == 4100) width -= 4;
+    if (load_raw == &CLASS olympus_e410_load_raw) {
+      black >>= 4;
+    } else if (!strcmp(model,"E-10") ||
+	      !strncmp(model,"E-20",4)) {
+      black <<= 2;
+    } else if (!strcmp(model,"E-300") ||
+	       !strcmp(model,"E-500")) {
+      width -= 20;
+      if (load_raw == &CLASS unpacked_load_raw) {
+	maximum = 0xfc30;
+	black = 0;
+      }
+    } else if (!strcmp(model,"E-330")) {
+      width -= 30;
+      if (load_raw == &CLASS unpacked_load_raw)
+	maximum = 0xf790;
+    } else if (!strcmp(model,"SP550UZ")) {
+      thumb_length = fsize - (thumb_offset = 0xa39800);
+      thumb_height = 480;
+      thumb_width  = 640;
+    }
+  } else if (!strcmp(model,"N Digital")) {
+    height = 2047;
+    width  = 3072;
+    filters = 0x61616161;
+    data_offset = 0x1a00;
+    load_raw = &CLASS packed_12_load_raw;
+  } else if (!strcmp(model,"DSC-F828")) {
+    width = 3288;
+    left_margin = 5;
+    data_offset = 862144;
+    load_raw = &CLASS sony_load_raw;
+    filters = 0x9c9c9c9c;
+    colors = 4;
+    strcpy (cdesc, "RGBE");
+  } else if (!strcmp(model,"DSC-V3")) {
+    width = 3109;
+    left_margin = 59;
+    data_offset = 787392;
+    load_raw = &CLASS sony_load_raw;
+  } else if (!strcmp(make,"SONY") && raw_width == 3984) {
+    adobe_coeff ("SONY","DSC-R1");
+    width = 3925;
+    order = 0x4d4d;
+  } else if (!strcmp(model,"DSLR-A100")) {
+    height--;
+  } else if (!strcmp(model,"DSLR-A350")) {
+    height -= 4;
+  } else if (!strcmp(model,"PIXL")) {
+    height -= top_margin = 4;
+    width -= left_margin = 32;
+    gamma_curve (0, 7, 1, 255);
+  } else if (!strcmp(model,"C603v")) {
+    height = 480;
+    width  = 640;
+    goto c603v;
+  } else if (!strcmp(model,"C603y")) {
+    height = 2134;
+    width  = 2848;
+c603v:
+    filters = 0;
+    load_raw = &CLASS kodak_yrgb_load_raw;
+    gamma_curve (0, 3.875, 1, 255);
+  } else if (!strcmp(model,"C603")) {
+    raw_height = height = 2152;
+    raw_width  = width  = 2864;
+    goto c603;
+  } else if (!strcmp(model,"C330")) {
+    height = 1744;
+    width  = 2336;
+    raw_height = 1779;
+    raw_width  = 2338;
+    top_margin = 33;
+    left_margin = 1;
+c603:
+    order = 0x4949;
+    if ((data_offset = fsize - raw_height*raw_width)) {
+      fseek (ifp, 168, SEEK_SET);
+      read_shorts (curve, 256);
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    } else gamma_curve (0, 3.875, 1, 255);
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"EASYSHARE Z1015 IS")) {
+    height = 2742;
+    width  = 3664;
+    data_offset = 0x15000;
+    load_raw = &CLASS packed_12_load_raw;
+  } else if (!strcasecmp(make,"KODAK")) {
+    if (filters == UINT_MAX) filters = 0x61616161;
+    if (!strncmp(model,"NC2000",6)) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"EOSDCS3B")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"EOSDCS1")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"DCS420")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strncmp(model,"DCS460 ",7)) {
+      model[6] = 0;
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"DCS460A")) {
+      width -= 4;
+      left_margin = 2;
+      colors = 1;
+      filters = 0;
+    } else if (!strcmp(model,"DCS660M")) {
+      black = 214;
+      colors = 1;
+      filters = 0;
+    } else if (!strcmp(model,"DCS760M")) {
+      colors = 1;
+      filters = 0;
+    }
+    if (!strcmp(model+4,"20X"))
+      strcpy (cdesc, "MYCY");
+    if (strstr(model,"DC25")) {
+      strcpy (model, "DC25");
+      data_offset = 15424;
+    }
+    if (!strncmp(model,"DC2",3)) {
+      height = 242;
+      if (fsize < 100000) {
+	raw_width = 256; width = 249;
+	pixel_aspect = (4.0*height) / (3.0*width);
+      } else {
+	raw_width = 512; width = 501;
+	pixel_aspect = (493.0*height) / (373.0*width);
+      }
+      data_offset += raw_width + 1;
+      colors = 4;
+      filters = 0x8d8d8d8d;
+      simple_coeff(1);
+      pre_mul[1] = 1.179;
+      pre_mul[2] = 1.209;
+      pre_mul[3] = 1.036;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+      load_raw = &CLASS eight_bit_load_raw;
+    } else if (!strcmp(model,"40")) {
+      strcpy (model, "DC40");
+      height = 512;
+      width  = 768;
+      data_offset = 1152;
+      load_raw = &CLASS kodak_radc_load_raw;
+    } else if (strstr(model,"DC50")) {
+      strcpy (model, "DC50");
+      height = 512;
+      width  = 768;
+      data_offset = 19712;
+      load_raw = &CLASS kodak_radc_load_raw;
+    } else if (strstr(model,"DC120")) {
+      strcpy (model, "DC120");
+      height = 976;
+      width  = 848;
+      pixel_aspect = height/0.75/width;
+      load_raw = tiff_compress == 7 ?
+	&CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw;
+    } else if (!strcmp(model,"DCS200")) {
+      thumb_height = 128;
+      thumb_width  = 192;
+      thumb_offset = 6144;
+      thumb_misc   = 360;
+      write_thumb = &CLASS layer_thumb;
+      height = 1024;
+      width  = 1536;
+      data_offset = 79872;
+      load_raw = &CLASS eight_bit_load_raw;
+      black = 17;
+    }
+  } else if (!strcmp(model,"Fotoman Pixtura")) {
+    height = 512;
+    width  = 768;
+    data_offset = 3632;
+    load_raw = &CLASS kodak_radc_load_raw;
+    filters = 0x61616161;
+    simple_coeff(2);
+  } else if (!strcmp(model,"QuickTake 100")) {
+    fseek (ifp, 544, SEEK_SET);
+    height = get2();
+    width  = get2();
+    data_offset = (get4(),get2()) == 30 ? 738:736;
+    if (height > width) {
+      SWAP(height,width);
+      fseek (ifp, data_offset-6, SEEK_SET);
+      flip = ~get2() & 3 ? 5:6;
+    }
+    load_raw = &CLASS quicktake_100_load_raw;
+    filters = 0x61616161;
+  } else if (!strcmp(model,"QuickTake 150")) {
+    data_offset = 738 - head[5];
+    if (head[5]) strcpy (model+10, "200");
+    load_raw = &CLASS kodak_radc_load_raw;
+    height = 480;
+    width  = 640;
+    filters = 0x61616161;
+  } else if (!strcmp(make,"Rollei") && !load_raw) {
+    switch (raw_width) {
+      case 1316:
+	height = 1030;
+	width  = 1300;
+	top_margin  = 1;
+	left_margin = 6;
+	break;
+      case 2568:
+	height = 1960;
+	width  = 2560;
+	top_margin  = 2;
+	left_margin = 8;
+    }
+    filters = 0x16161616;
+    load_raw = &CLASS rollei_load_raw;
+    pre_mul[0] = 1.8;
+    pre_mul[2] = 1.3;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"PC-CAM 600")) {
+    height = 768;
+    data_offset = width = 1024;
+    filters = 0x49494949;
+    load_raw = &CLASS eight_bit_load_raw;
+    pre_mul[0] = 1.14;
+    pre_mul[2] = 2.73;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  }
+#if 1
+  else
+      identify2(fsize); /* Avoid MS VS 2008 bug */
+#else
+ else if (!strcmp(model,"QV-2000UX")) {
+    height = 1208;
+    width  = 1632;
+    data_offset = width * 2;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (fsize == 3217760) {
+    height = 1546;
+    width  = 2070;
+    raw_width = 2080;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"QV-4000")) {
+    height = 1700;
+    width  = 2260;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xffff;
+  } else if (!strcmp(model,"QV-5700")) {
+    height = 1924;
+    width  = 2576;
+    load_raw = &CLASS casio_qv5700_load_raw;
+  } else if (!strcmp(model,"QV-R41")) {
+    height = 1720;
+    width  = 2312;
+    raw_width = 3520;
+    left_margin = 2;
+  } else if (!strcmp(model,"QV-R51")) {
+    height = 1926;
+    width  = 2580;
+    raw_width = 3904;
+    pre_mul[0] = 1.340;
+    pre_mul[2] = 1.672;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"EX-S100")) {
+    height = 1544;
+    width  = 2058;
+    raw_width = 3136;
+    pre_mul[0] = 1.631;
+    pre_mul[2] = 1.106;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"EX-Z50")) {
+    height = 1931;
+    width  = 2570;
+    raw_width = 3904;
+    pre_mul[0] = 2.529;
+    pre_mul[2] = 1.185;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"EX-Z55")) {
+    height = 1960;
+    width  = 2570;
+    raw_width = 3904;
+    pre_mul[0] = 1.520;
+    pre_mul[2] = 1.316;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"EX-P505")) {
+    height = 1928;
+    width  = 2568;
+    raw_width = 3852;
+    maximum = 0xfff;
+    pre_mul[0] = 2.07;
+    pre_mul[2] = 1.88;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (fsize == 9313536) {	/* EX-P600 or QV-R61 */
+    height = 2142;
+    width  = 2844;
+    raw_width = 4288;
+    pre_mul[0] = 1.797;
+    pre_mul[2] = 1.219;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"EX-P700")) {
+    height = 2318;
+    width  = 3082;
+    raw_width = 4672;
+    pre_mul[0] = 1.758;
+    pre_mul[2] = 1.504;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  }
+#endif
+  if (!model[0])
+    sprintf (model, "%dx%d", width, height);
+  if (filters == UINT_MAX) filters = 0x94949494;
+  if (raw_color) adobe_coeff (make, model);
+  if (load_raw == &CLASS kodak_radc_load_raw)
+    if (raw_color) adobe_coeff ("Apple","Quicktake");
+  if (thumb_offset && !thumb_height) {
+    fseek (ifp, thumb_offset, SEEK_SET);
+    if (ljpeg_start (&jh, 1)) {
+      thumb_width  = jh.wide;
+      thumb_height = jh.high;
+    }
+  }
+dng_skip:
+  if (!load_raw || height < 22) is_raw = 0;
+#ifdef NO_JPEG
+  if (load_raw == &CLASS kodak_jpeg_load_raw) {
+#ifdef DCRAW_VERBOSE
+    fprintf (stderr,_("%s: You must link dcraw with libjpeg!!\n"), ifname);
+#endif
+    is_raw = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+    imgdata.process_warnings |= LIBRAW_WARN_NO_JPEGLIB;
+#endif
+  }
+#endif
+  if (!cdesc[0])
+    strcpy (cdesc, colors == 3 ? "RGB":"GMCY");
+  if (!raw_height) raw_height = height;
+  if (!raw_width ) raw_width  = width;
+  if (filters && colors == 3)
+    for (i=0; i < 32; i+=4) {
+      if ((filters >> i & 15) == 9)
+	filters |= 2 << i;
+      if ((filters >> i & 15) == 6)
+	filters |= 8 << i;
+    }
+notraw:
+  if (flip == -1) flip = tiff_flip;
+  if (flip == -1) flip = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY,1,2);
+#endif
+}
+
+void CLASS identify2(unsigned fsize)
+{
+ if (!strcmp(model,"QV-2000UX")) {
+    height = 1208;
+    width  = 1632;
+    data_offset = width * 2;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (fsize == 3217760) {
+    height = 1546;
+    width  = 2070;
+    raw_width = 2080;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"QV-4000")) {
+    height = 1700;
+    width  = 2260;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xffff;
+  } else if (!strcmp(model,"QV-5700")) {
+    height = 1924;
+    width  = 2576;
+    load_raw = &CLASS casio_qv5700_load_raw;
+  } else if (!strcmp(model,"QV-R41")) {
+    height = 1720;
+    width  = 2312;
+    raw_width = 3520;
+    left_margin = 2;
+  } else if (!strcmp(model,"QV-R51")) {
+    height = 1926;
+    width  = 2580;
+    raw_width = 3904;
+    pre_mul[0] = 1.340;
+    pre_mul[2] = 1.672;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"EX-S100")) {
+    height = 1544;
+    width  = 2058;
+    raw_width = 3136;
+    pre_mul[0] = 1.631;
+    pre_mul[2] = 1.106;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"EX-Z50")) {
+    height = 1931;
+    width  = 2570;
+    raw_width = 3904;
+    pre_mul[0] = 2.529;
+    pre_mul[2] = 1.185;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"EX-Z55")) {
+    height = 1960;
+    width  = 2570;
+    raw_width = 3904;
+    pre_mul[0] = 1.520;
+    pre_mul[2] = 1.316;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"EX-P505")) {
+    height = 1928;
+    width  = 2568;
+    raw_width = 3852;
+    maximum = 0xfff;
+    pre_mul[0] = 2.07;
+    pre_mul[2] = 1.88;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (fsize == 9313536) {	/* EX-P600 or QV-R61 */
+    height = 2142;
+    width  = 2844;
+    raw_width = 4288;
+    pre_mul[0] = 1.797;
+    pre_mul[2] = 1.219;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  } else if (!strcmp(model,"EX-P700")) {
+    height = 2318;
+    width  = 3082;
+    raw_width = 4672;
+    pre_mul[0] = 1.758;
+    pre_mul[2] = 1.504;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+  }
+}
+
+void CLASS convert_to_rgb()
+{
+  int row, col, c, i, j, k;
+  ushort *img;
+  float out[3], out_cam[3][4];
+  double num, inverse[3][3];
+  static const double xyzd50_srgb[3][3] =
+  { { 0.436083, 0.385083, 0.143055 },
+    { 0.222507, 0.716888, 0.060608 },
+    { 0.013930, 0.097097, 0.714022 } };
+  static const double rgb_rgb[3][3] =
+  { { 1,0,0 }, { 0,1,0 }, { 0,0,1 } };
+  static const double adobe_rgb[3][3] =
+  { { 0.715146, 0.284856, 0.000000 },
+    { 0.000000, 1.000000, 0.000000 },
+    { 0.000000, 0.041166, 0.958839 } };
+  static const double wide_rgb[3][3] =
+  { { 0.593087, 0.404710, 0.002206 },
+    { 0.095413, 0.843149, 0.061439 },
+    { 0.011621, 0.069091, 0.919288 } };
+  static const double prophoto_rgb[3][3] =
+  { { 0.529317, 0.330092, 0.140588 },
+    { 0.098368, 0.873465, 0.028169 },
+    { 0.016879, 0.117663, 0.865457 } };
+  static const double (*out_rgb[])[3] =
+  { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb };
+  static const char *name[] =
+  { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" };
+  static const unsigned phead[] =
+  { 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0,
+    0x61637370, 0, 0, 0x6e6f6e65, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d };
+  unsigned pbody[] =
+  { 10, 0x63707274, 0, 36,	/* cprt */
+	0x64657363, 0, 40,	/* desc */
+	0x77747074, 0, 20,	/* wtpt */
+	0x626b7074, 0, 20,	/* bkpt */
+	0x72545243, 0, 14,	/* rTRC */
+	0x67545243, 0, 14,	/* gTRC */
+	0x62545243, 0, 14,	/* bTRC */
+	0x7258595a, 0, 20,	/* rXYZ */
+	0x6758595a, 0, 20,	/* gXYZ */
+	0x6258595a, 0, 20 };	/* bXYZ */
+  static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc };
+  unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 };
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB,0,2);
+#endif
+  gamma_curve (gamm[0], gamm[1], 0, 0);
+  memcpy (out_cam, rgb_cam, sizeof out_cam);
+  raw_color |= colors == 1 || document_mode ||
+		output_color < 1 || output_color > 5;
+  if (!raw_color) {
+    oprof = (unsigned *) calloc (phead[0], 1);
+    merror (oprof, "convert_to_rgb()");
+    memcpy (oprof, phead, sizeof phead);
+    if (output_color == 5) oprof[4] = oprof[5];
+    oprof[0] = 132 + 12*pbody[0];
+    for (i=0; i < pbody[0]; i++) {
+      oprof[oprof[0]/4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874;
+      pbody[i*3+2] = oprof[0];
+      oprof[0] += (pbody[i*3+3] + 3) & -4;
+    }
+    memcpy (oprof+32, pbody, sizeof pbody);
+    oprof[pbody[5]/4+2] = strlen(name[output_color-1]) + 1;
+    memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite);
+    pcurve[3] = (short)(256/gamm[5]+0.5) << 16;
+    for (i=4; i < 7; i++)
+      memcpy ((char *)oprof+pbody[i*3+2], pcurve, sizeof pcurve);
+    pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3);
+    for (i=0; i < 3; i++)
+      for (j=0; j < 3; j++) {
+	for (num = k=0; k < 3; k++)
+	  num += xyzd50_srgb[i][k] * inverse[j][k];
+        oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5;
+      }
+    for (i=0; i < phead[0]/4; i++)
+      oprof[i] = htonl(oprof[i]);
+    strcpy ((char *)oprof+pbody[2]+8, "auto-generated by dcraw");
+    strcpy ((char *)oprof+pbody[5]+12, name[output_color-1]);
+    for (i=0; i < 3; i++)
+      for (j=0; j < colors; j++)
+	for (out_cam[i][j] = k=0; k < 3; k++)
+	  out_cam[i][j] += out_rgb[output_color-1][i][k] * rgb_cam[k][j];
+  }
+#ifdef DCRAW_VERBOSE
+  if (verbose)
+    fprintf (stderr, raw_color ? _("Building histograms...\n") :
+	_("Converting to %s colorspace...\n"), name[output_color-1]);
+
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+  memset(histogram,0,sizeof(int)*LIBRAW_HISTOGRAM_SIZE*4);
+#else
+  memset (histogram, 0, sizeof histogram);
+#endif
+  for (img=image[0], row=0; row < height; row++)
+    for (col=0; col < width; col++, img+=4) {
+      if (!raw_color) {
+	out[0] = out[1] = out[2] = 0;
+	FORCC {
+	  out[0] += out_cam[0][c] * img[c];
+	  out[1] += out_cam[1][c] * img[c];
+	  out[2] += out_cam[2][c] * img[c];
+	}
+	FORC3 img[c] = CLIP((int) out[c]);
+      }
+      else if (document_mode)
+	img[0] = img[FC(row,col)];
+      FORCC histogram[c][img[c] >> 3]++;
+    }
+  if (colors == 4 && output_color) colors = 3;
+  if (document_mode && filters) colors = 1;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB,1,2);
+#endif
+}
+
+void CLASS fuji_rotate()
+{
+  int i, row, col;
+  double step;
+  float r, c, fr, fc;
+  unsigned ur, uc;
+  ushort wide, high, (*img)[4], (*pix)[4];
+
+  if (!fuji_width) return;
+#ifdef DCRAW_VERBOSE
+  if (verbose)
+    fprintf (stderr,_("Rotating image 45 degrees...\n"));
+#endif
+  fuji_width = (fuji_width - 1 + shrink) >> shrink;
+  step = sqrt(0.5);
+  wide = fuji_width / step;
+  high = (height - fuji_width) / step;
+  img = (ushort (*)[4]) calloc (wide*high, sizeof *img);
+  merror (img, "fuji_rotate()");
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE,0,2);
+#endif
+
+  for (row=0; row < high; row++)
+    for (col=0; col < wide; col++) {
+      ur = r = fuji_width + (row-col)*step;
+      uc = c = (row+col)*step;
+      if (ur > height-2 || uc > width-2) continue;
+      fr = r - ur;
+      fc = c - uc;
+      pix = image + ur*width + uc;
+      for (i=0; i < colors; i++)
+	img[row*wide+col][i] =
+	  (pix[    0][i]*(1-fc) + pix[      1][i]*fc) * (1-fr) +
+	  (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr;
+    }
+  free (image);
+  width  = wide;
+  height = high;
+  image  = img;
+  fuji_width = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE,1,2);
+#endif
+}
+
+void CLASS stretch()
+{
+  ushort newdim, (*img)[4], *pix0, *pix1;
+  int row, col, c;
+  double rc, frac;
+
+  if (pixel_aspect == 1) return;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH,0,2);
+#endif
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Stretching the image...\n"));
+#endif
+  if (pixel_aspect < 1) {
+    newdim = height / pixel_aspect + 0.5;
+    img = (ushort (*)[4]) calloc (width*newdim, sizeof *img);
+    merror (img, "stretch()");
+    for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) {
+      frac = rc - (c = rc);
+      pix0 = pix1 = image[c*width];
+      if (c+1 < height) pix1 += width*4;
+      for (col=0; col < width; col++, pix0+=4, pix1+=4)
+	FORCC img[row*width+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
+    }
+    height = newdim;
+  } else {
+    newdim = width * pixel_aspect + 0.5;
+    img = (ushort (*)[4]) calloc (height*newdim, sizeof *img);
+    merror (img, "stretch()");
+    for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) {
+      frac = rc - (c = rc);
+      pix0 = pix1 = image[c];
+      if (c+1 < width) pix1 += 4;
+      for (row=0; row < height; row++, pix0+=width*4, pix1+=width*4)
+	FORCC img[row*newdim+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
+    }
+    width = newdim;
+  }
+  free (image);
+  image = img;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH,1,2);
+#endif
+}
+
+int CLASS flip_index (int row, int col)
+{
+  if (flip & 4) SWAP(row,col);
+  if (flip & 2) row = iheight - 1 - row;
+  if (flip & 1) col = iwidth  - 1 - col;
+  return row * iwidth + col;
+}
+
+void CLASS tiff_set (ushort *ntag,
+	ushort tag, ushort type, int count, int val)
+{
+  struct tiff_tag *tt;
+  int c;
+
+  tt = (struct tiff_tag *)(ntag+1) + (*ntag)++;
+  tt->tag = tag;
+  tt->type = type;
+  tt->count = count;
+  if (type < 3 && count <= 4)
+    FORC(4) tt->val.c[c] = val >> (c << 3);
+  else if (type == 3 && count <= 2)
+    FORC(2) tt->val.s[c] = val >> (c << 4);
+  else tt->val.i = val;
+}
+
+#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
+
+void CLASS tiff_head (struct tiff_hdr *th, int full)
+{
+  int c, psize=0;
+  struct tm *t;
+
+  memset (th, 0, sizeof *th);
+  th->t_order = htonl(0x4d4d4949) >> 16;
+  th->magic = 42;
+  th->ifd = 10;
+  if (full) {
+    tiff_set (&th->ntag, 254, 4, 1, 0);
+    tiff_set (&th->ntag, 256, 4, 1, width);
+    tiff_set (&th->ntag, 257, 4, 1, height);
+    tiff_set (&th->ntag, 258, 3, colors, output_bps);
+    if (colors > 2)
+      th->tag[th->ntag-1].val.i = TOFF(th->bps);
+    FORC4 th->bps[c] = output_bps;
+    tiff_set (&th->ntag, 259, 3, 1, 1);
+    tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1));
+  }
+  tiff_set (&th->ntag, 270, 2, 512, TOFF(th->t_desc));
+  tiff_set (&th->ntag, 271, 2, 64, TOFF(th->t_make));
+  tiff_set (&th->ntag, 272, 2, 64, TOFF(th->t_model));
+  if (full) {
+    if (oprof) psize = ntohl(oprof[0]);
+    tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize);
+    tiff_set (&th->ntag, 277, 3, 1, colors);
+    tiff_set (&th->ntag, 278, 4, 1, height);
+    tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8);
+  } else
+    tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0');
+  tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0]));
+  tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2]));
+  tiff_set (&th->ntag, 284, 3, 1, 1);
+  tiff_set (&th->ntag, 296, 3, 1, 2);
+  tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft));
+  tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date));
+  tiff_set (&th->ntag, 315, 2, 64, TOFF(th->t_artist));
+  tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif));
+  if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th);
+  tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
+  tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
+  tiff_set (&th->nexif, 34855, 3, 1, iso_speed);
+  tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
+  if (gpsdata[1]) {
+    tiff_set (&th->ntag, 34853, 4, 1, TOFF(th->ngps));
+    tiff_set (&th->ngps,  0, 1,  4, 0x202);
+    tiff_set (&th->ngps,  1, 2,  2, gpsdata[29]);
+    tiff_set (&th->ngps,  2, 5,  3, TOFF(th->gps[0]));
+    tiff_set (&th->ngps,  3, 2,  2, gpsdata[30]);
+    tiff_set (&th->ngps,  4, 5,  3, TOFF(th->gps[6]));
+    tiff_set (&th->ngps,  5, 1,  1, gpsdata[31]);
+    tiff_set (&th->ngps,  6, 5,  1, TOFF(th->gps[18]));
+    tiff_set (&th->ngps,  7, 5,  3, TOFF(th->gps[12]));
+    tiff_set (&th->ngps, 18, 2, 12, TOFF(th->gps[20]));
+    tiff_set (&th->ngps, 29, 2, 12, TOFF(th->gps[23]));
+    memcpy (th->gps, gpsdata, sizeof th->gps);
+  }
+  th->rat[0] = th->rat[2] = 300;
+  th->rat[1] = th->rat[3] = 1;
+  FORC(6) th->rat[4+c] = 1000000;
+  th->rat[4] *= shutter;
+  th->rat[6] *= aperture;
+  th->rat[8] *= focal_len;
+  strncpy (th->t_desc, desc, 512);
+  strncpy (th->t_make, make, 64);
+  strncpy (th->t_model, model, 64);
+  strcpy (th->soft, "dcraw v"VERSION);
+  t = gmtime (&timestamp);
+  sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d",
+      t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
+  strncpy (th->t_artist, artist, 64);
+}
+
+void CLASS jpeg_thumb_writer (FILE *tfp,char *t_humb,int t_humb_length)
+{
+  ushort exif[5];
+  struct tiff_hdr th;
+  fputc (0xff, tfp);
+  fputc (0xd8, tfp);
+  if (strcmp (t_humb+6, "Exif")) {
+    memcpy (exif, "\xff\xe1  Exif\0\0", 10);
+    exif[1] = htons (8 + sizeof th);
+    fwrite (exif, 1, sizeof exif, tfp);
+    tiff_head (&th, 0);
+    fwrite (&th, 1, sizeof th, tfp);
+  }
+  fwrite (t_humb+2, 1, t_humb_length-2, tfp);
+}
+
+
+void CLASS jpeg_thumb()
+{
+  char *thumb;
+  ushort exif[5];
+  struct tiff_hdr th;
+
+  thumb = (char *) malloc (thumb_length);
+  merror (thumb, "jpeg_thumb()");
+  fread (thumb, 1, thumb_length, ifp);
+#if 0
+  fputc (0xff, ofp);
+  fputc (0xd8, ofp);
+  if (strcmp (thumb+6, "Exif")) {
+    memcpy (exif, "\xff\xe1  Exif\0\0", 10);
+    exif[1] = htons (8 + sizeof th);
+    fwrite (exif, 1, sizeof exif, ofp);
+    tiff_head (&th, 0);
+    fwrite (&th, 1, sizeof th, ofp);
+  }
+  fwrite (thumb+2, 1, thumb_length-2, ofp);
+#else
+  jpeg_thumb_writer(ofp,thumb,thumb_length);
+#endif
+  free (thumb);
+}
+
+void CLASS write_ppm_tiff()
+{
+  struct tiff_hdr th;
+  uchar *ppm;
+  ushort *ppm2;
+  int c, row, col, soff, rstep, cstep;
+  int perc, val, total, t_white=0x2000;
+
+  perc = width * height * 0.01;		/* 99th percentile white level */
+  if (fuji_width) perc /= 2;
+  if (!((highlight & ~2) || no_auto_bright))
+    for (t_white=c=0; c < colors; c++) {
+      for (val=0x2000, total=0; --val > 32; )
+	if ((total += histogram[c][val]) > perc) break;
+      if (t_white < val) t_white = val;
+    }
+  gamma_curve (gamm[0], gamm[1], 2, (t_white << 3)/bright);
+  iheight = height;
+  iwidth  = width;
+  if (flip & 4) SWAP(height,width);
+  ppm = (uchar *) calloc (width, colors*output_bps/8);
+  ppm2 = (ushort *) ppm;
+  merror (ppm, "write_ppm_tiff()");
+  if (output_tiff) {
+    tiff_head (&th, 1);
+    fwrite (&th, sizeof th, 1, ofp);
+    if (oprof)
+      fwrite (oprof, ntohl(oprof[0]), 1, ofp);
+  } else if (colors > 3)
+    fprintf (ofp,
+      "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
+	width, height, colors, (1 << output_bps)-1, cdesc);
+  else
+    fprintf (ofp, "P%d\n%d %d\n%d\n",
+	colors/2+5, width, height, (1 << output_bps)-1);
+
+  soff  = flip_index (0, 0);
+  cstep = flip_index (0, 1) - soff;
+  rstep = flip_index (1, 0) - flip_index (0, width);
+  for (row=0; row < height; row++, soff += rstep) {
+    for (col=0; col < width; col++, soff += cstep)
+      if (output_bps == 8)
+	   FORCC ppm [col*colors+c] = curve[image[soff][c]] >> 8;
+      else FORCC ppm2[col*colors+c] = curve[image[soff][c]];
+    if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa)
+        swab ((char*)ppm2, (char*)ppm2, width*colors*2);
+    fwrite (ppm, colors*output_bps/8, width, ofp);
+  }
+  free (ppm);
+}
diff --git a/libfspotraw/LibRaw/internal/dcraw_fileio.cpp b/libfspotraw/LibRaw/internal/dcraw_fileio.cpp
new file mode 100644
index 0000000..fa4a335
--- /dev/null
+++ b/libfspotraw/LibRaw/internal/dcraw_fileio.cpp
@@ -0,0 +1,211 @@
+/* 
+   GENERATED FILE, DO NOT EDIT
+   Generated from dcraw/dcraw.c at Mon Jun  8 13:54:39 2009
+   Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
+   for copyright information.
+*/
+
+#define CLASS LibRaw::
+#include "libraw/libraw_types.h"
+#define LIBRAW_LIBRARY_BUILD
+#include "libraw/libraw.h"
+#include "internal/defines.h"
+#include "internal/var_defines.h"
+
+/*
+   Seach from the current directory up to the root looking for
+   a ".badpixels" file, and fix those pixels now.
+ */
+void CLASS bad_pixels (const char *cfname)
+{
+  FILE *fp=0;
+  char *fname, *cp, line[128];
+  int len, time, row, col, r, c, rad, tot, n, fixed=0;
+
+  if (!filters) return;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS,0,2);
+#endif
+  if (cfname)
+    fp = fopen (cfname, "r");
+  if (!fp) 
+      {
+#ifdef LIBRAW_LIBRARY_BUILD
+          imgdata.process_warnings |= LIBRAW_WARN_NO_BADPIXELMAP;
+#endif
+          return;
+      }
+  while (fgets (line, 128, fp)) {
+    cp = strchr (line, '#');
+    if (cp) *cp = 0;
+    if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue;
+    if ((unsigned) col >= width || (unsigned) row >= height) continue;
+    if (time > timestamp) continue;
+    for (tot=n=0, rad=1; rad < 3 && n==0; rad++)
+      for (r = row-rad; r <= row+rad; r++)
+	for (c = col-rad; c <= col+rad; c++)
+	  if ((unsigned) r < height && (unsigned) c < width &&
+		(r != row || c != col) && fc(r,c) == fc(row,col)) {
+	    tot += BAYER2(r,c);
+	    n++;
+	  }
+    BAYER2(row,col) = tot/n;
+#ifdef DCRAW_VERBOSE
+    if (verbose) {
+      if (!fixed++)
+	fprintf (stderr,_("Fixed dead pixels at:"));
+      fprintf (stderr, " %d,%d", col, row);
+    }
+#endif
+  }
+#ifdef DCRAW_VERBOSE
+  if (fixed) fputc ('\n', stderr);
+#endif
+  fclose (fp);
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS,1,2);
+#endif
+}
+
+void CLASS subtract (const char *fname)
+{
+  FILE *fp;
+  int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col;
+  ushort *pixel;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME,0,2);
+#endif
+
+  if (!(fp = fopen (fname, "rb"))) {
+#ifdef DCRAW_VERBOSE
+    perror (fname); 
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+    imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_FILE;
+#endif
+    return;
+  }
+  if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1;
+  while (!error && nd < 3 && (c = fgetc(fp)) != EOF) {
+    if (c == '#')  comment = 1;
+    if (c == '\n') comment = 0;
+    if (comment) continue;
+    if (isdigit(c)) number = 1;
+    if (number) {
+      if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0';
+      else if (isspace(c)) {
+	number = 0;  nd++;
+      } else error = 1;
+    }
+  }
+  if (error || nd < 3) {
+    fprintf (stderr,_("%s is not a valid PGM file!\n"), fname);
+    fclose (fp);  return;
+  } else if (dim[0] != width || dim[1] != height || dim[2] != 65535) {
+#ifdef DCRAW_VERBOSE
+      fprintf (stderr,_("%s has the wrong dimensions!\n"), fname);
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+      imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_DIM;
+#endif
+    fclose (fp);  return;
+  }
+  pixel = (ushort *) calloc (width, sizeof *pixel);
+  merror (pixel, "subtract()");
+  for (row=0; row < height; row++) {
+    fread (pixel, 2, width, fp);
+    for (col=0; col < width; col++)
+      BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0);
+  }
+  free (pixel);
+  black = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME,1,2);
+#endif
+}
+
+#ifndef NO_LCMS
+void CLASS apply_profile (const char *input, const char *output)
+{
+  char *prof;
+  cmsHPROFILE hInProfile=0, hOutProfile=0;
+  cmsHTRANSFORM hTransform;
+  FILE *fp;
+  unsigned size;
+
+  cmsErrorAction (LCMS_ERROR_SHOW);
+  if (strcmp (input, "embed"))
+    hInProfile = cmsOpenProfileFromFile (input, "r");
+  else if (profile_length) {
+#ifndef LIBRAW_LIBRARY_BUILD
+    prof = (char *) malloc (profile_length);
+    merror (prof, "apply_profile()");
+    fseek (ifp, profile_offset, SEEK_SET);
+    fread (prof, 1, profile_length, ifp);
+    hInProfile = cmsOpenProfileFromMem (prof, profile_length);
+    free (prof);
+#else
+    hInProfile = cmsOpenProfileFromMem (imgdata.color.profile, profile_length);
+#endif
+  } else
+      {
+#ifdef LIBRAW_LIBRARY_BUILD
+          imgdata.process_warnings |= LIBRAW_WARN_NO_EMBEDDED_PROFILE;
+#endif
+#ifdef DCRAW_VERBOSE
+          fprintf (stderr,_("%s has no embedded profile.\n"), ifname);
+#endif
+      }
+  if (!hInProfile)
+      {
+#ifdef LIBRAW_LIBRARY_BUILD
+          imgdata.process_warnings |= LIBRAW_WARN_NO_INPUT_PROFILE;
+#endif
+          return;
+      }
+  if (!output)
+    hOutProfile = cmsCreate_sRGBProfile();
+  else if ((fp = fopen (output, "rb"))) {
+    fread (&size, 4, 1, fp);
+    fseek (fp, 0, SEEK_SET);
+    oprof = (unsigned *) malloc (size = ntohl(size));
+    merror (oprof, "apply_profile()");
+    fread (oprof, 1, size, fp);
+    fclose (fp);
+    if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) {
+      free (oprof);
+      oprof = 0;
+    }
+#ifdef DCRAW_VERBOSE
+  } else
+    fprintf (stderr,_("Cannot open file %s!\n"), output);
+#else
+}
+#endif
+  if (!hOutProfile)
+      {
+#ifdef LIBRAW_LIBRARY_BUILD
+          imgdata.process_warnings |= LIBRAW_WARN_BAD_OUTPUT_PROFILE;
+#endif
+          goto quit;
+      }
+#ifdef DCRAW_VERBOSE
+  if (verbose)
+    fprintf (stderr,_("Applying color profile...\n"));
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE,0,2);
+#endif
+  hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16,
+	hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0);
+  cmsDoTransform (hTransform, image, image, width*height);
+  raw_color = 1;		/* Don't use rgb_cam with a profile */
+  cmsDeleteTransform (hTransform);
+  cmsCloseProfile (hOutProfile);
+quit:
+  cmsCloseProfile (hInProfile);
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE,1,2);
+#endif
+}
+#endif
diff --git a/libfspotraw/LibRaw/internal/defines.h b/libfspotraw/LibRaw/internal/defines.h
new file mode 100644
index 0000000..768bbeb
--- /dev/null
+++ b/libfspotraw/LibRaw/internal/defines.h
@@ -0,0 +1,131 @@
+/* 
+   GENERATED FILE, DO NOT EDIT
+   Generated from dcraw/dcraw.c at Mon Jun  8 13:24:08 2009
+   Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
+   for copyright information.
+*/
+
+#define NO_JPEG
+#define VERSION "8.94"
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#define _USE_MATH_DEFINES
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+/*
+   NO_JPEG disables decoding of compressed Kodak DC120 files.
+   NO_LCMS disables the "-p" option.
+ */
+#ifndef NO_JPEG
+#include <jpeglib.h>
+#endif
+#ifndef NO_LCMS
+#include <lcms.h>
+#endif
+#ifdef LOCALEDIR
+#include <libintl.h>
+#define _(String) gettext(String)
+#else
+#define _(String) (String)
+#endif
+#ifdef __CYGWIN__
+#include <io.h>
+#endif
+#ifdef WIN32
+#include <sys/utime.h>
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+#define snprintf _snprintf
+#define strcasecmp _stricmp
+#define strncasecmp strnicmp
+typedef __int64 INT64;
+typedef unsigned __int64 UINT64;
+#else
+#include <unistd.h>
+#include <utime.h>
+#include <netinet/in.h>
+typedef long long INT64;
+typedef unsigned long long UINT64;
+#endif
+
+#ifdef LJPEG_DECODE
+#error Please compile dcraw.c by itself.
+#error Do not link it with ljpeg_decode.
+#endif
+
+#ifndef LONG_BIT
+#define LONG_BIT (8 * sizeof (long))
+#endif
+#define FORC(cnt) for (c=0; c < cnt; c++)
+#define FORC3 FORC(3)
+#define FORC4 FORC(4)
+#define FORCC FORC(colors)
+
+#define SQR(x) ((x)*(x))
+#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define LIM(x,min,max) MAX(min,MIN(x,max))
+#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
+#define CLIP(x) LIM(x,0,65535)
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+
+/*
+   In order to inline this calculation, I make the risky
+   assumption that all filter patterns can be described
+   by a repeating pattern of eight rows and two columns
+
+   Do not use the FC or BAYER macros with the Leaf CatchLight,
+   because its pattern is 16x16, not 2x8.
+
+   Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2
+
+	PowerShot 600	PowerShot A50	PowerShot Pro70	Pro90 & G1
+	0xe1e4e1e4:	0x1b4e4b1e:	0x1e4b4e1b:	0xb4b4b4b4:
+
+	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5
+	0 G M G M G M	0 C Y C Y C Y	0 Y C Y C Y C	0 G M G M G M
+	1 C Y C Y C Y	1 M G M G M G	1 M G M G M G	1 Y C Y C Y C
+	2 M G M G M G	2 Y C Y C Y C	2 C Y C Y C Y
+	3 C Y C Y C Y	3 G M G M G M	3 G M G M G M
+			4 C Y C Y C Y	4 Y C Y C Y C
+	PowerShot A5	5 G M G M G M	5 G M G M G M
+	0x1e4e1e4e:	6 Y C Y C Y C	6 C Y C Y C Y
+			7 M G M G M G	7 M G M G M G
+	  0 1 2 3 4 5
+	0 C Y C Y C Y
+	1 G M G M G M
+	2 C Y C Y C Y
+	3 M G M G M G
+
+   All RGB cameras use one of these Bayer grids:
+
+	0x16161616:	0x61616161:	0x49494949:	0x94949494:
+
+	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5
+	0 B G B G B G	0 G R G R G R	0 G B G B G B	0 R G R G R G
+	1 G R G R G R	1 B G B G B G	1 R G R G R G	1 G B G B G B
+	2 B G B G B G	2 G R G R G R	2 G B G B G B	2 R G R G R G
+	3 G R G R G R	3 B G B G B G	3 R G R G R G	3 G B G B G B
+ */
+
+#define BAYER(row,col) \
+	image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)]
+
+#define BAYER2(row,col) \
+	image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)]
diff --git a/libfspotraw/LibRaw/internal/foveon.cpp b/libfspotraw/LibRaw/internal/foveon.cpp
new file mode 100644
index 0000000..12abda9
--- /dev/null
+++ b/libfspotraw/LibRaw/internal/foveon.cpp
@@ -0,0 +1,812 @@
+/* 
+   GENERATED FILE, DO NOT EDIT
+   Generated from dcraw/dcraw.c at Mon Jun  8 13:24:08 2009
+   Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
+   for copyright information.
+*/
+
+#define CLASS LibRaw::
+#include "libraw/libraw_types.h"
+#define LIBRAW_IO_REDEFINED
+#define LIBRAW_LIBRARY_BUILD
+#include "libraw/libraw.h"
+#include "internal/defines.h"
+#define SRC_USES_SHRINK
+#define SRC_USES_BLACK
+#define SRC_USES_CURVE
+#include "internal/var_defines.h"
+#define sget4(s) sget4((uchar *)s)
+
+/* RESTRICTED code starts here */
+
+void CLASS foveon_decoder (unsigned size, unsigned code)
+{
+#ifndef LIBRAW_NOTHREADS
+#define huff tls->foveon_decoder_huff
+#else
+  static unsigned huff[1024];
+#endif
+  struct decode *cur;
+  int i, len;
+
+  if (!code) {
+    for (i=0; i < size; i++)
+      huff[i] = get4();
+    init_decoder();
+  }
+  cur = free_decode++;
+  if (free_decode > first_decode+2048) {
+#ifdef LIBRAW_LIBRARY_BUILD
+      throw LIBRAW_EXCEPTION_DECODE_RAW;
+#else
+    fprintf (stderr,_("%s: decoder table overflow\n"), ifname);
+    longjmp (failure, 2);
+#endif
+  }
+  if (code)
+    for (i=0; i < size; i++)
+      if (huff[i] == code) {
+	cur->leaf = i;
+	return;
+      }
+  if ((len = code >> 27) > 26) return;
+  code = (len+1) << 27 | (code & 0x3ffffff) << 1;
+
+  cur->branch[0] = free_decode;
+  foveon_decoder (size, code);
+  cur->branch[1] = free_decode;
+  foveon_decoder (size, code+1);
+#ifndef LIBRAW_NOTHREADS
+#undef huff
+#endif
+}
+
+void CLASS foveon_thumb()
+{
+  unsigned bwide, row, col, bitbuf=0, bit=1, c, i;
+  char *buf;
+  struct decode *dindex;
+  short pred[3];
+
+  bwide = get4();
+  fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+  if (bwide > 0) {
+    if (bwide < thumb_width*3) return;
+    buf = (char *) malloc (bwide);
+    merror (buf, "foveon_thumb()");
+    for (row=0; row < thumb_height; row++) {
+      fread  (buf, 1, bwide, ifp);
+      fwrite (buf, 3, thumb_width, ofp);
+    }
+    free (buf);
+    return;
+  }
+  foveon_decoder (256, 0);
+
+  for (row=0; row < thumb_height; row++) {
+    memset (pred, 0, sizeof pred);
+    if (!bit) get4();
+    for (bit=col=0; col < thumb_width; col++)
+      FORC3 {
+	for (dindex=first_decode; dindex->branch[0]; ) {
+	  if ((bit = (bit-1) & 31) == 31)
+	    for (i=0; i < 4; i++)
+	      bitbuf = (bitbuf << 8) + fgetc(ifp);
+	  dindex = dindex->branch[bitbuf >> bit & 1];
+	}
+	pred[c] += dindex->leaf;
+	fputc (pred[c], ofp);
+      }
+  }
+}
+
+void CLASS foveon_load_camf()
+{
+  unsigned key, i, val;
+
+  fseek (ifp, meta_offset, SEEK_SET);
+  key = get4();
+  fread (meta_data, 1, meta_length, ifp);
+  for (i=0; i < meta_length; i++) {
+    key = (key * 1597 + 51749) % 244944;
+    val = key * (INT64) 301593171 >> 24;
+    meta_data[i] ^= ((((key << 8) - val) >> 1) + val) >> 17;
+  }
+}
+
+void CLASS foveon_load_raw()
+{
+  struct decode *dindex;
+  short diff[1024];
+  unsigned bitbuf=0;
+  int pred[3], fixed, row, col, bit=-1, c, i;
+
+  fixed = get4();
+  read_shorts ((ushort *) diff, 1024);
+  if (!fixed) foveon_decoder (1024, 0);
+
+  for (row=0; row < height; row++) {
+    memset (pred, 0, sizeof pred);
+    if (!bit && !fixed && atoi(model+2) < 14) get4();
+    for (col=bit=0; col < width; col++) {
+      if (fixed) {
+	bitbuf = get4();
+	FORC3 pred[2-c] += diff[bitbuf >> c*10 & 0x3ff];
+      }
+      else FORC3 {
+	for (dindex=first_decode; dindex->branch[0]; ) {
+	  if ((bit = (bit-1) & 31) == 31)
+	    for (i=0; i < 4; i++)
+	      bitbuf = (bitbuf << 8) + fgetc(ifp);
+	  dindex = dindex->branch[bitbuf >> bit & 1];
+	}
+	pred[c] += diff[dindex->leaf];
+	if (pred[c] >> 16 && ~pred[c] >> 16) derror();
+      }
+      FORC3 image[row*width+col][c] = pred[c];
+    }
+  }
+  if (document_mode)
+    for (i=0; i < height*width*4; i++)
+      if ((short) image[0][i] < 0) image[0][i] = 0;
+  foveon_load_camf();
+}
+
+const char * CLASS foveon_camf_param (const char *block, const char *param)
+{
+  unsigned idx, num;
+  char *pos, *cp, *dp;
+
+  for (idx=0; idx < meta_length; idx += sget4(pos+8)) {
+    pos = meta_data + idx;
+    if (strncmp (pos, "CMb", 3)) break;
+    if (pos[3] != 'P') continue;
+    if (strcmp (block, pos+sget4(pos+12))) continue;
+    cp = pos + sget4(pos+16);
+    num = sget4(cp);
+    dp = pos + sget4(cp+4);
+    while (num--) {
+      cp += 8;
+      if (!strcmp (param, dp+sget4(cp)))
+	return dp+sget4(cp+4);
+    }
+  }
+  return 0;
+}
+
+void * CLASS foveon_camf_matrix (unsigned dim[3], const char *name)
+{
+  unsigned i, idx, type, ndim, size, *mat;
+  char *pos, *cp, *dp;
+  double dsize;
+
+  for (idx=0; idx < meta_length; idx += sget4(pos+8)) {
+    pos = meta_data + idx;
+    if (strncmp (pos, "CMb", 3)) break;
+    if (pos[3] != 'M') continue;
+    if (strcmp (name, pos+sget4(pos+12))) continue;
+    dim[0] = dim[1] = dim[2] = 1;
+    cp = pos + sget4(pos+16);
+    type = sget4(cp);
+    if ((ndim = sget4(cp+4)) > 3) break;
+    dp = pos + sget4(cp+8);
+    for (i=ndim; i--; ) {
+      cp += 12;
+      dim[i] = sget4(cp);
+    }
+    if ((dsize = (double) dim[0]*dim[1]*dim[2]) > meta_length/4) break;
+    mat = (unsigned *) malloc ((size = dsize) * 4);
+    merror (mat, "foveon_camf_matrix()");
+    for (i=0; i < size; i++)
+      if (type && type != 6)
+	mat[i] = sget4(dp + i*4);
+      else
+	mat[i] = sget4(dp + i*2) & 0xffff;
+    return mat;
+  }
+#ifdef LIBRAW_LIBRARY_BUILD
+  imgdata.process_warnings |= LIBRAW_WARN_FOVEON_NOMATRIX;
+#endif
+#ifdef DCRAW_VERBOSE
+  fprintf (stderr,_("%s: \"%s\" matrix not found!\n"), ifname, name);
+#endif
+  return 0;
+}
+
+int CLASS foveon_fixed (void *ptr, int size, const char *name)
+{
+  void *dp;
+  unsigned dim[3];
+
+  dp = foveon_camf_matrix (dim, name);
+  if (!dp) return 0;
+  memcpy (ptr, dp, size*4);
+  free (dp);
+  return 1;
+}
+
+float CLASS foveon_avg (short *pix, int range[2], float cfilt)
+{
+  int i;
+  float val, min=FLT_MAX, max=-FLT_MAX, sum=0;
+
+  for (i=range[0]; i <= range[1]; i++) {
+    sum += val = pix[i*4] + (pix[i*4]-pix[(i-1)*4]) * cfilt;
+    if (min > val) min = val;
+    if (max < val) max = val;
+  }
+  if (range[1] - range[0] == 1) return sum/2;
+  return (sum - min - max) / (range[1] - range[0] - 1);
+}
+
+short * CLASS foveon_make_curve (double max, double mul, double filt)
+{
+  short *curve;
+  unsigned i, size;
+  double x;
+
+  if (!filt) filt = 0.8;
+  size = 4*M_PI*max / filt;
+  if (size == UINT_MAX) size--;
+  curve = (short *) calloc (size+1, sizeof *curve);
+  merror (curve, "foveon_make_curve()");
+  curve[0] = size;
+  for (i=0; i < size; i++) {
+    x = i*filt/max/4;
+    curve[i+1] = (cos(x)+1)/2 * tanh(i*filt/mul) * mul + 0.5;
+  }
+  return curve;
+}
+
+void CLASS foveon_make_curves
+	(short **curvep, float dq[3], float div[3], float filt)
+{
+  double mul[3], max=0;
+  int c;
+
+  FORC3 mul[c] = dq[c]/div[c];
+  FORC3 if (max < mul[c]) max = mul[c];
+  FORC3 curvep[c] = foveon_make_curve (max, mul[c], filt);
+}
+
+int CLASS foveon_apply_curve (short *curve, int i)
+{
+  if (abs(i) >= curve[0]) return 0;
+  return i < 0 ? -curve[1-i] : curve[1+i];
+}
+
+#ifdef image
+#undef image
+#endif
+#define image ((short(*)[4]) imgdata.image)
+
+void CLASS foveon_interpolate()
+{
+  static const short hood[] = { -1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1 };
+  short *pix, prev[3], *curve[8], (*shrink)[3];
+  float cfilt=0, ddft[3][3][2], ppm[3][3][3];
+  float cam_xyz[3][3], correct[3][3], last[3][3], trans[3][3];
+  float chroma_dq[3], color_dq[3], diag[3][3], div[3];
+  float (*black)[3], (*sgain)[3], (*sgrow)[3];
+  float fsum[3], val, frow, num;
+  int row, col, c, i, j, diff, sgx, irow, sum, min, max, limit;
+  int dscr[2][2], dstb[4], (*smrow[7])[3], total[4], ipix[3];
+  int work[3][3], smlast, smred, smred_p=0, dev[3];
+  int satlev[3], keep[4], active[4];
+  unsigned dim[3], *badpix;
+  double dsum=0, trsum[3];
+  char str[128];
+  const char* cp;
+
+
+#ifdef DCRAW_VERBOSE
+  if (verbose)
+    fprintf(stderr,_("Foveon interpolation...\n"));
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE,0,9);
+#endif  
+
+  foveon_fixed (dscr, 4, "DarkShieldColRange");
+  foveon_fixed (ppm[0][0], 27, "PostPolyMatrix");
+  foveon_fixed (satlev, 3, "SaturationLevel");
+  foveon_fixed (keep, 4, "KeepImageArea");
+  foveon_fixed (active, 4, "ActiveImageArea");
+  foveon_fixed (chroma_dq, 3, "ChromaDQ");
+  foveon_fixed (color_dq, 3,
+	foveon_camf_param ("IncludeBlocks", "ColorDQ") ?
+		"ColorDQ" : "ColorDQCamRGB");
+  if (foveon_camf_param ("IncludeBlocks", "ColumnFilter"))
+  		 foveon_fixed (&cfilt, 1, "ColumnFilter");
+
+  memset (ddft, 0, sizeof ddft);
+  if (!foveon_camf_param ("IncludeBlocks", "DarkDrift")
+	 || !foveon_fixed (ddft[1][0], 12, "DarkDrift"))
+    for (i=0; i < 2; i++) {
+      foveon_fixed (dstb, 4, i ? "DarkShieldBottom":"DarkShieldTop");
+      for (row = dstb[1]; row <= dstb[3]; row++)
+	for (col = dstb[0]; col <= dstb[2]; col++)
+	  FORC3 ddft[i+1][c][1] += (short) image[row*width+col][c];
+      FORC3 ddft[i+1][c][1] /= (dstb[3]-dstb[1]+1) * (dstb[2]-dstb[0]+1);
+    }
+
+  if (!(cp = foveon_camf_param ("WhiteBalanceIlluminants", model2)))
+  { 
+#ifdef DCRAW_VERBOSE
+      fprintf (stderr,_("%s: Invalid white balance \"%s\"\n"), ifname, model2);
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+      imgdata.process_warnings |= LIBRAW_WARN_FOVEON_INVALIDWB;
+#endif
+      return; 
+  }
+  foveon_fixed (cam_xyz, 9, cp);
+  foveon_fixed (correct, 9,
+	foveon_camf_param ("WhiteBalanceCorrections", model2));
+  memset (last, 0, sizeof last);
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      FORC3 last[i][j] += correct[i][c] * cam_xyz[c][j];
+
+  #define LAST(x,y) last[(i+x)%3][(c+y)%3]
+  for (i=0; i < 3; i++)
+    FORC3 diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1);
+  #undef LAST
+  FORC3 div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583;
+  sprintf (str, "%sRGBNeutral", model2);
+  if (foveon_camf_param ("IncludeBlocks", str))
+    foveon_fixed (div, 3, str);
+  num = 0;
+  FORC3 if (num < div[c]) num = div[c];
+  FORC3 div[c] /= num;
+
+  memset (trans, 0, sizeof trans);
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      FORC3 trans[i][j] += rgb_cam[i][c] * last[c][j] * div[j];
+  FORC3 trsum[c] = trans[c][0] + trans[c][1] + trans[c][2];
+  dsum = (6*trsum[0] + 11*trsum[1] + 3*trsum[2]) / 20;
+  for (i=0; i < 3; i++)
+    FORC3 last[i][c] = trans[i][c] * dsum / trsum[i];
+  memset (trans, 0, sizeof trans);
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      FORC3 trans[i][j] += (i==c ? 32 : -1) * last[c][j] / 30;
+
+  foveon_make_curves (curve, color_dq, div, cfilt);
+  FORC3 chroma_dq[c] /= 3;
+  foveon_make_curves (curve+3, chroma_dq, div, cfilt);
+  FORC3 dsum += chroma_dq[c] / div[c];
+  curve[6] = foveon_make_curve (dsum, dsum, cfilt);
+  curve[7] = foveon_make_curve (dsum*2, dsum*2, cfilt);
+
+  sgain = (float (*)[3]) foveon_camf_matrix (dim, "SpatialGain");
+  if (!sgain) return;
+  sgrow = (float (*)[3]) calloc (dim[1], sizeof *sgrow);
+  sgx = (width + dim[1]-2) / (dim[1]-1);
+
+  black = (float (*)[3]) calloc (height, sizeof *black);
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE,1,9);
+#endif
+  for (row=0; row < height; row++) {
+    for (i=0; i < 6; i++)
+      ddft[0][0][i] = ddft[1][0][i] +
+	row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
+    FORC3 black[row][c] =
+ 	( foveon_avg (image[row*width]+c, dscr[0], cfilt) +
+	  foveon_avg (image[row*width]+c, dscr[1], cfilt) * 3
+	  - ddft[0][c][0] ) / 4 - ddft[0][c][1];
+  }
+  memcpy (black, black+8, sizeof *black*8);
+  memcpy (black+height-11, black+height-22, 11*sizeof *black);
+  memcpy (last, black, sizeof last);
+
+  for (row=1; row < height-1; row++) {
+    FORC3 if (last[1][c] > last[0][c]) {
+	if (last[1][c] > last[2][c])
+	  black[row][c] = (last[0][c] > last[2][c]) ? last[0][c]:last[2][c];
+      } else
+	if (last[1][c] < last[2][c])
+	  black[row][c] = (last[0][c] < last[2][c]) ? last[0][c]:last[2][c];
+    memmove (last, last+1, 2*sizeof last[0]);
+    memcpy (last[2], black[row+1], sizeof last[2]);
+  }
+  FORC3 black[row][c] = (last[0][c] + last[1][c])/2;
+  FORC3 black[0][c] = (black[1][c] + black[3][c])/2;
+
+  val = 1 - exp(-1/24.0);
+  memcpy (fsum, black, sizeof fsum);
+  for (row=1; row < height; row++)
+    FORC3 fsum[c] += black[row][c] =
+	(black[row][c] - black[row-1][c])*val + black[row-1][c];
+  memcpy (last[0], black[height-1], sizeof last[0]);
+  FORC3 fsum[c] /= height;
+  for (row = height; row--; )
+    FORC3 last[0][c] = black[row][c] =
+	(black[row][c] - fsum[c] - last[0][c])*val + last[0][c];
+
+  memset (total, 0, sizeof total);
+  for (row=2; row < height; row+=4)
+    for (col=2; col < width; col+=4) {
+      FORC3 total[c] += (short) image[row*width+col][c];
+      total[3]++;
+    }
+  for (row=0; row < height; row++)
+    FORC3 black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0);
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE,2,9);
+#endif
+  for (row=0; row < height; row++) {
+    for (i=0; i < 6; i++)
+      ddft[0][0][i] = ddft[1][0][i] +
+	row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
+    pix = image[row*width];
+    memcpy (prev, pix, sizeof prev);
+    frow = row / (height-1.0) * (dim[2]-1);
+    if ((irow = frow) == dim[2]-1) irow--;
+    frow -= irow;
+    for (i=0; i < dim[1]; i++)
+      FORC3 sgrow[i][c] = sgain[ irow   *dim[1]+i][c] * (1-frow) +
+			  sgain[(irow+1)*dim[1]+i][c] *    frow;
+    for (col=0; col < width; col++) {
+      FORC3 {
+	diff = pix[c] - prev[c];
+	prev[c] = pix[c];
+	ipix[c] = pix[c] + floor ((diff + (diff*diff >> 14)) * cfilt
+		- ddft[0][c][1] - ddft[0][c][0] * ((float) col/width - 0.5)
+		- black[row][c] );
+      }
+      FORC3 {
+	work[0][c] = ipix[c] * ipix[c] >> 14;
+	work[2][c] = ipix[c] * work[0][c] >> 14;
+	work[1][2-c] = ipix[(c+1) % 3] * ipix[(c+2) % 3] >> 14;
+      }
+      FORC3 {
+	for (val=i=0; i < 3; i++)
+	  for (  j=0; j < 3; j++)
+	    val += ppm[c][i][j] * work[i][j];
+	ipix[c] = floor ((ipix[c] + floor(val)) *
+		( sgrow[col/sgx  ][c] * (sgx - col%sgx) +
+		  sgrow[col/sgx+1][c] * (col%sgx) ) / sgx / div[c]);
+	if (ipix[c] > 32000) ipix[c] = 32000;
+	pix[c] = ipix[c];
+      }
+      pix += 4;
+    }
+  }
+  free (black);
+  free (sgrow);
+  free (sgain);
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE,3,9);
+#endif
+  if ((badpix = (unsigned int *) foveon_camf_matrix (dim, "BadPixels"))) {
+    for (i=0; i < dim[0]; i++) {
+      col = (badpix[i] >> 8 & 0xfff) - keep[0];
+      row = (badpix[i] >> 20       ) - keep[1];
+      if ((unsigned)(row-1) > height-3 || (unsigned)(col-1) > width-3)
+	continue;
+      memset (fsum, 0, sizeof fsum);
+      for (sum=j=0; j < 8; j++)
+	if (badpix[i] & (1 << j)) {
+	  FORC3 fsum[c] += (short)
+		image[(row+hood[j*2])*width+col+hood[j*2+1]][c];
+	  sum++;
+	}
+      if (sum) FORC3 image[row*width+col][c] = fsum[c]/sum;
+    }
+    free (badpix);
+  }
+
+  /* Array for 5x5 Gaussian averaging of red values */
+  smrow[6] = (int (*)[3]) calloc (width*5, sizeof **smrow);
+  merror (smrow[6], "foveon_interpolate()");
+  for (i=0; i < 5; i++)
+    smrow[i] = smrow[6] + i*width;
+
+  /* Sharpen the reds against these Gaussian averages */
+  for (smlast=-1, row=2; row < height-2; row++) {
+    while (smlast < row+2) {
+      for (i=0; i < 6; i++)
+	smrow[(i+5) % 6] = smrow[i];
+      pix = image[++smlast*width+2];
+      for (col=2; col < width-2; col++) {
+	smrow[4][col][0] =
+	  (pix[0]*6 + (pix[-4]+pix[4])*4 + pix[-8]+pix[8] + 8) >> 4;
+	pix += 4;
+      }
+    }
+    pix = image[row*width+2];
+    for (col=2; col < width-2; col++) {
+      smred = ( 6 *  smrow[2][col][0]
+	      + 4 * (smrow[1][col][0] + smrow[3][col][0])
+	      +      smrow[0][col][0] + smrow[4][col][0] + 8 ) >> 4;
+      if (col == 2)
+	smred_p = smred;
+      i = pix[0] + ((pix[0] - ((smred*7 + smred_p) >> 3)) >> 3);
+      if (i > 32000) i = 32000;
+      pix[0] = i;
+      smred_p = smred;
+      pix += 4;
+    }
+  }
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE,4,9);
+#endif
+  /* Adjust the brighter pixels for better linearity */
+  min = 0xffff;
+  FORC3 {
+    i = satlev[c] / div[c];
+    if (min > i) min = i;
+  }
+  limit = min * 9 >> 4;
+  for (pix=image[0]; pix < image[height*width]; pix+=4) {
+    if (pix[0] <= limit || pix[1] <= limit || pix[2] <= limit)
+      continue;
+    min = max = pix[0];
+    for (c=1; c < 3; c++) {
+      if (min > pix[c]) min = pix[c];
+      if (max < pix[c]) max = pix[c];
+    }
+    if (min >= limit*2) {
+      pix[0] = pix[1] = pix[2] = max;
+    } else {
+      i = 0x4000 - ((min - limit) << 14) / limit;
+      i = 0x4000 - (i*i >> 14);
+      i = i*i >> 14;
+      FORC3 pix[c] += (max - pix[c]) * i >> 14;
+    }
+  }
+/*
+   Because photons that miss one detector often hit another,
+   the sum R+G+B is much less noisy than the individual colors.
+   So smooth the hues without smoothing the total.
+ */
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE,5,9);
+#endif
+  for (smlast=-1, row=2; row < height-2; row++) {
+    while (smlast < row+2) {
+      for (i=0; i < 6; i++)
+	smrow[(i+5) % 6] = smrow[i];
+      pix = image[++smlast*width+2];
+      for (col=2; col < width-2; col++) {
+	FORC3 smrow[4][col][c] = (pix[c-4]+2*pix[c]+pix[c+4]+2) >> 2;
+	pix += 4;
+      }
+    }
+    pix = image[row*width+2];
+    for (col=2; col < width-2; col++) {
+      FORC3 dev[c] = -foveon_apply_curve (curve[7], pix[c] -
+	((smrow[1][col][c] + 2*smrow[2][col][c] + smrow[3][col][c]) >> 2));
+      sum = (dev[0] + dev[1] + dev[2]) >> 3;
+      FORC3 pix[c] += dev[c] - sum;
+      pix += 4;
+    }
+  }
+  for (smlast=-1, row=2; row < height-2; row++) {
+    while (smlast < row+2) {
+      for (i=0; i < 6; i++)
+	smrow[(i+5) % 6] = smrow[i];
+      pix = image[++smlast*width+2];
+      for (col=2; col < width-2; col++) {
+	FORC3 smrow[4][col][c] =
+		(pix[c-8]+pix[c-4]+pix[c]+pix[c+4]+pix[c+8]+2) >> 2;
+	pix += 4;
+      }
+    }
+    pix = image[row*width+2];
+    for (col=2; col < width-2; col++) {
+      for (total[3]=375, sum=60, c=0; c < 3; c++) {
+	for (total[c]=i=0; i < 5; i++)
+	  total[c] += smrow[i][col][c];
+	total[3] += total[c];
+	sum += pix[c];
+      }
+      if (sum < 0) sum = 0;
+      j = total[3] > 375 ? (sum << 16) / total[3] : sum * 174;
+      FORC3 pix[c] += foveon_apply_curve (curve[6],
+		((j*total[c] + 0x8000) >> 16) - pix[c]);
+      pix += 4;
+    }
+  }
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE,6,9);
+#endif
+  /* Transform the image to a different colorspace */
+  for (pix=image[0]; pix < image[height*width]; pix+=4) {
+    FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]);
+    sum = (pix[0]+pix[1]+pix[1]+pix[2]) >> 2;
+    FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]-sum);
+    FORC3 {
+      for (dsum=i=0; i < 3; i++)
+	dsum += trans[c][i] * pix[i];
+      if (dsum < 0)  dsum = 0;
+      if (dsum > 24000) dsum = 24000;
+      ipix[c] = dsum + 0.5;
+    }
+    FORC3 pix[c] = ipix[c];
+  }
+
+  /* Smooth the image bottom-to-top and save at 1/4 scale */
+  shrink = (short (*)[3]) calloc ((width/4) * (height/4), sizeof *shrink);
+  merror (shrink, "foveon_interpolate()");
+  for (row = height/4; row--; )
+    for (col=0; col < width/4; col++) {
+      ipix[0] = ipix[1] = ipix[2] = 0;
+      for (i=0; i < 4; i++)
+	for (j=0; j < 4; j++)
+	  FORC3 ipix[c] += image[(row*4+i)*width+col*4+j][c];
+      FORC3
+	if (row+2 > height/4)
+	  shrink[row*(width/4)+col][c] = ipix[c] >> 4;
+	else
+	  shrink[row*(width/4)+col][c] =
+	    (shrink[(row+1)*(width/4)+col][c]*1840 + ipix[c]*141 + 2048) >> 12;
+    }
+  /* From the 1/4-scale image, smooth right-to-left */
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE,7,9);
+#endif
+  for (row=0; row < (height & ~3); row++) {
+    ipix[0] = ipix[1] = ipix[2] = 0;
+    if ((row & 3) == 0)
+      for (col = width & ~3 ; col--; )
+	FORC3 smrow[0][col][c] = ipix[c] =
+	  (shrink[(row/4)*(width/4)+col/4][c]*1485 + ipix[c]*6707 + 4096) >> 13;
+
+  /* Then smooth left-to-right */
+    ipix[0] = ipix[1] = ipix[2] = 0;
+    for (col=0; col < (width & ~3); col++)
+      FORC3 smrow[1][col][c] = ipix[c] =
+	(smrow[0][col][c]*1485 + ipix[c]*6707 + 4096) >> 13;
+
+  /* Smooth top-to-bottom */
+    if (row == 0)
+      memcpy (smrow[2], smrow[1], sizeof **smrow * width);
+    else
+      for (col=0; col < (width & ~3); col++)
+	FORC3 smrow[2][col][c] =
+	  (smrow[2][col][c]*6707 + smrow[1][col][c]*1485 + 4096) >> 13;
+
+  /* Adjust the chroma toward the smooth values */
+    for (col=0; col < (width & ~3); col++) {
+      for (i=j=30, c=0; c < 3; c++) {
+	i += smrow[2][col][c];
+	j += image[row*width+col][c];
+      }
+      j = (j << 16) / i;
+      for (sum=c=0; c < 3; c++) {
+	ipix[c] = foveon_apply_curve (curve[c+3],
+	  ((smrow[2][col][c] * j + 0x8000) >> 16) - image[row*width+col][c]);
+	sum += ipix[c];
+      }
+      sum >>= 3;
+      FORC3 {
+	i = image[row*width+col][c] + ipix[c] - sum;
+	if (i < 0) i = 0;
+	image[row*width+col][c] = i;
+      }
+    }
+  }
+  free (shrink);
+  free (smrow[6]);
+  for (i=0; i < 8; i++)
+    free (curve[i]);
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE,8,9);
+#endif
+
+  /* Trim off the black border */
+  active[1] -= keep[1];
+  active[3] -= 2;
+  i = active[2] - active[0];
+  for (row=0; row < active[3]-active[1]; row++)
+    memcpy (image[row*i], image[(row+active[1])*width+active[0]],
+	 i * sizeof *image);
+  width = i;
+  height = row;
+}
+#undef image
+
+/* RESTRICTED code ends here */
+char * CLASS foveon_gets (int offset, char *str, int len)
+{
+  int i;
+  fseek (ifp, offset, SEEK_SET);
+  for (i=0; i < len-1; i++)
+    if ((str[i] = get2()) == 0) break;
+  str[i] = 0;
+  return str;
+}
+
+void CLASS parse_foveon()
+{
+  int entries, img=0, off, len, tag, save, i, wide, high, pent, poff[256][2];
+  char name[64], value[64];
+
+  order = 0x4949;			/* Little-endian */
+  fseek (ifp, 36, SEEK_SET);
+  flip = get4();
+  fseek (ifp, -4, SEEK_END);
+  fseek (ifp, get4(), SEEK_SET);
+  if (get4() != 0x64434553) return;	/* SECd */
+  entries = (get4(),get4());
+  while (entries--) {
+    off = get4();
+    len = get4();
+    tag = get4();
+    save = ftell(ifp);
+    fseek (ifp, off, SEEK_SET);
+    if (get4() != (0x20434553 | (tag << 24))) return;
+    switch (tag) {
+      case 0x47414d49:			/* IMAG */
+      case 0x32414d49:			/* IMA2 */
+	fseek (ifp, 12, SEEK_CUR);
+	wide = get4();
+	high = get4();
+	if (wide > raw_width && high > raw_height) {
+	  raw_width  = wide;
+	  raw_height = high;
+	  data_offset = off+24;
+	}
+	fseek (ifp, off+28, SEEK_SET);
+	if (fgetc(ifp) == 0xff && fgetc(ifp) == 0xd8
+		&& thumb_length < len-28) {
+	  thumb_offset = off+28;
+	  thumb_length = len-28;
+	  write_thumb = &CLASS jpeg_thumb;
+	}
+	if (++img == 2 && !thumb_length) {
+	  thumb_offset = off+24;
+	  thumb_width = wide;
+	  thumb_height = high;
+	  write_thumb = &CLASS foveon_thumb;
+	}
+	break;
+      case 0x464d4143:			/* CAMF */
+	meta_offset = off+24;
+	meta_length = len-28;
+	if (meta_length > 0x20000)
+	    meta_length = 0x20000;
+	break;
+      case 0x504f5250:			/* PROP */
+	pent = (get4(),get4());
+	fseek (ifp, 12, SEEK_CUR);
+	off += pent*8 + 24;
+	if ((unsigned) pent > 256) pent=256;
+	for (i=0; i < pent*2; i++)
+	  poff[0][i] = off + get4()*2;
+	for (i=0; i < pent; i++) {
+	  foveon_gets (poff[i][0], name, 64);
+	  foveon_gets (poff[i][1], value, 64);
+	  if (!strcmp (name, "ISO"))
+	    iso_speed = atoi(value);
+	  if (!strcmp (name, "CAMMANUF"))
+	    strcpy (make, value);
+	  if (!strcmp (name, "CAMMODEL"))
+	    strcpy (model, value);
+	  if (!strcmp (name, "WB_DESC"))
+	    strcpy (model2, value);
+	  if (!strcmp (name, "TIME"))
+	    timestamp = atoi(value);
+	  if (!strcmp (name, "EXPTIME"))
+	    shutter = atoi(value) / 1000000.0;
+	  if (!strcmp (name, "APERTURE"))
+	    aperture = atof(value);
+	  if (!strcmp (name, "FLENGTH"))
+	    focal_len = atof(value);
+	}
+#ifdef LOCALTIME
+	timestamp = mktime (gmtime (&timestamp));
+#endif
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  is_foveon = 1;
+}
diff --git a/libfspotraw/LibRaw/internal/libraw_internal_funcs.h b/libfspotraw/LibRaw/internal/libraw_internal_funcs.h
new file mode 100644
index 0000000..867f3ed
--- /dev/null
+++ b/libfspotraw/LibRaw/internal/libraw_internal_funcs.h
@@ -0,0 +1,197 @@
+/* -*- C++ -*-
+ * File: libraw_internal_funcs.h
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  14, 2008
+ *
+ * LibRaw internal data structures (not visible outside)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _LIBRAW_INTERNAL_FUNCS_H
+#define _LIBRAW_INTERNAL_FUNCS_H
+
+#ifndef LIBRAW_LIBRARY_BUILD
+#error "This file should be used only for libraw library build"
+#else
+// inline functions
+    ushort      sget2 (uchar *s);
+    ushort      get2();
+    unsigned    sget4 (uchar *s);
+    unsigned    getint (int type);
+    float       int_to_float (int i);
+    double      getreal (int type);
+    void        read_shorts (ushort *pixel, int count);
+
+// Canon P&S cameras
+    void        canon_600_fixed_wb (int temp);
+    int         canon_600_color (int ratio[2], int mar);
+    void        canon_600_auto_wb();
+    void        canon_600_coeff();
+    void        canon_600_load_raw();
+    int         canon_s2is();
+    void        canon_a5_load_raw();
+    void        parse_ciff (int offset, int length);
+    void        ciff_block_1030();
+
+// LJPEG decoder
+    unsigned    getbits (int nbits);
+    void        init_decoder();
+    uchar *     make_decoder (const uchar *source, int level);
+    int         ljpeg_start (struct jhead *jh, int info_only);
+    int         ljpeg_diff (struct decode *dindex);
+    ushort *    ljpeg_row (int jrow, struct jhead *jh);
+
+// Canon DSLRs
+    void        crw_init_tables (unsigned table);
+    int         canon_has_lowbits();
+    void        canon_compressed_load_raw();
+    void        lossless_jpeg_load_raw();
+    void        canon_sraw_load_raw();
+void        canon_black(double *, int nblack);
+// Adobe DNG
+    void        adobe_copy_pixel (int row, int col, ushort **rp);
+    void        adobe_dng_load_raw_lj();
+    void        adobe_dng_load_raw_nc();
+
+// Pentax
+    void        pentax_k10_load_raw();
+    void        pentax_tree();
+
+// Nikon (and Minolta Z2)
+    void        nikon_compressed_load_raw();
+    void        nikon_load_raw();
+    int         nikon_is_compressed();
+    int         nikon_e995();
+    int         nikon_e2100();
+    void        nikon_3700();
+    int         minolta_z2();
+    void        nikon_e900_load_raw();
+    void        nikon_e2100_load_raw();
+
+// Fuji
+    void        fuji_load_raw();
+    void        parse_fuji (int offset);
+
+
+
+
+// Rollei
+    void        rollei_load_raw();
+    void        parse_rollei();
+
+// MF backs
+    int         bayer (unsigned row, unsigned col);
+    void        phase_one_flat_field (int is_float, int nc);
+    void        phase_one_correct();
+    void        phase_one_load_raw();
+    unsigned    ph1_bits (int nbits);
+    void        phase_one_load_raw_c();
+    void        hasselblad_load_raw();
+    void        leaf_hdr_load_raw();
+    void        sinar_4shot_load_raw();
+    void        imacon_full_load_raw();
+    void        packed_12_load_raw();
+    void        unpacked_load_raw();
+    void        parse_sinar_ia();
+    void        parse_phase_one (int base);
+
+// Misc P&S cameras
+    void        nokia_load_raw();
+    unsigned    pana_bits (int nbits);
+    void        panasonic_load_raw();
+    void        olympus_e410_load_raw();
+    void        olympus_cseries_load_raw();
+    void        minolta_rd175_load_raw();
+    void        casio_qv5700_load_raw();
+    void        quicktake_100_load_raw();
+    const int*  make_decoder_int (const int *source, int level);
+    int         radc_token (int tree);
+    void        kodak_radc_load_raw();
+    void        kodak_jpeg_load_raw();
+    void        kodak_dc120_load_raw();
+    void        eight_bit_load_raw();
+    void        smal_decode_segment (unsigned seg[2][2], int holes);
+    void        smal_v6_load_raw();
+    int         median4 (int *p);
+    void        fill_holes (int holes);
+    void        smal_v9_load_raw();
+    void        parse_riff();
+    void        parse_cine();
+    void        parse_smal (int offset, int fsize);
+    int         parse_jpeg (int offset);
+
+// Kodak
+    void        kodak_262_load_raw();
+    int         kodak_65000_decode (short *out, int bsize);
+    void        kodak_65000_load_raw();
+    void        kodak_rgb_load_raw();
+    void        kodak_yrgb_load_raw();
+
+// It's a Sony (and K&M)
+    void        sony_decrypt (unsigned *data, int len, int start, int key);
+    void        sony_load_raw();
+    void        sony_arw_load_raw();
+    void        sony_arw2_load_raw();
+    void        parse_minolta (int base);
+
+// Foveon/Sigma
+    void        foveon_load_camf();
+    void        foveon_load_raw();
+    const char* foveon_camf_param (const char *block, const char *param);
+    void *      foveon_camf_matrix (unsigned dim[3], const char *name);
+    int         foveon_fixed (void *ptr, int size, const char *name);
+    float       foveon_avg (short *pix, int range[2], float cfilt);
+    short *     foveon_make_curve (double max, double mul, double filt);
+    void        foveon_make_curves(short **curvep, float dq[3], float div[3], float filt);
+    int         foveon_apply_curve (short *curve, int i);
+    void        foveon_interpolate();
+    char *      foveon_gets (int offset, char *str, int len);
+    void        parse_foveon();
+
+// CAM/RGB
+    void        pseudoinverse (double (*in)[3], double (*out)[3], int size);
+    void        cam_xyz_coeff (double cam_xyz[4][3]);
+    void        adobe_coeff (const char *, const char *);
+    void        simple_coeff (int index);
+
+
+// Tiff/Exif parsers
+    void        tiff_get (unsigned base,unsigned *tag, unsigned *type, unsigned *len, unsigned *save);
+    void        parse_thumb_note (int base, unsigned toff, unsigned tlen);
+    void        parse_makernote (int base, int uptag);
+    void        parse_exif (int base);
+    void        linear_table (unsigned len);
+    void        parse_kodak_ifd (int base);
+    int         parse_tiff_ifd (int base);
+    void        parse_tiff (int base);
+    void        parse_gps (int base);
+    void        romm_coeff (float romm_cam[3][3]);
+    void        parse_mos (int offset);
+    void        get_timestamp (int reversed);
+
+// External JPEGs, what cameras uses it ?
+    void        parse_external_jpeg();
+
+// The identify
+    short       guess_byte_order (int words);
+
+// Tiff writer
+    void        tiff_set (ushort *ntag, ushort tag, ushort type, int count, int val);
+    void        tiff_head (struct tiff_hdr *th, int full);
+#endif
+
+#endif
diff --git a/libfspotraw/LibRaw/internal/var_defines.h b/libfspotraw/LibRaw/internal/var_defines.h
new file mode 100644
index 0000000..238583a
--- /dev/null
+++ b/libfspotraw/LibRaw/internal/var_defines.h
@@ -0,0 +1,182 @@
+/* -*- C++ -*-
+ * File: var_defines.h
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8, 2008
+ *
+ * LibRaw redefinitions of dcraw internal variables
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef VAR_DEFINES_H
+#define VAR_DEFINES_H
+
+// imgdata.idata
+#define make            (imgdata.idata.make)
+#define model           (imgdata.idata.model)
+#define is_raw          (imgdata.idata.raw_count)
+#define dng_version     (imgdata.idata.dng_version)
+#define is_foveon       (imgdata.idata.is_foveon)
+#define colors          (imgdata.idata.colors)
+#define cdesc           (imgdata.idata.cdesc)
+#define filters         (imgdata.idata.filters)
+
+//imgdata image
+#define image           (imgdata.image)
+
+// imgdata.sizes
+#define raw_height      (imgdata.sizes.raw_height)
+#define raw_width       (imgdata.sizes.raw_width)
+#define height          (imgdata.sizes.height)
+#define width           (imgdata.sizes.width)
+#define top_margin      (imgdata.sizes.top_margin)
+#define left_margin     (imgdata.sizes.left_margin)
+#define bottom_margin   (imgdata.sizes.bottom_margin)
+#define right_margin    (imgdata.sizes.right_margin)
+#define iheight         (imgdata.sizes.iheight)
+#define iwidth          (imgdata.sizes.iwidth)
+#define pixel_aspect    (imgdata.sizes.pixel_aspect)
+#define flip            (imgdata.sizes.flip)
+
+//imgdata.color
+#define white           (imgdata.color.white)
+#define cam_mul         (imgdata.color.cam_mul)
+#define pre_mul         (imgdata.color.pre_mul)
+#define cmatrix         (imgdata.color.cmatrix)
+#define rgb_cam         (imgdata.color.rgb_cam)
+#ifndef SRC_USES_CURVE
+#define curve           (imgdata.color.curve)
+#endif
+#ifndef SRC_USES_BLACK
+#define black           (imgdata.color.black)
+#endif
+#define maximum         (imgdata.color.maximum)
+#define profile_length  (imgdata.color.profile_length)
+#define color_flags     (imgdata.color.color_flags)
+#define ph1             (imgdata.color.phase_one_data)
+#define flash_used      (imgdata.color.flash_used)
+#define canon_ev        (imgdata.color.canon_ev)
+#define model2          (imgdata.color.model2)
+
+//imgdata.thumbnail
+
+#define thumb_width     (imgdata.thumbnail.twidth)
+#define thumb_height    (imgdata.thumbnail.theight)
+#define thumb_length    (imgdata.thumbnail.tlength)
+
+
+//imgdata.others
+#define iso_speed       (imgdata.other.iso_speed)
+#define shutter         (imgdata.other.shutter)
+#define aperture        (imgdata.other.aperture)
+#define focal_len       (imgdata.other.focal_len)
+#define timestamp       (imgdata.other.timestamp)
+#define shot_order      (imgdata.other.shot_order)
+#define gpsdata         (imgdata.other.gpsdata)
+#define desc            (imgdata.other.desc)
+#define artist          (imgdata.other.artist)
+
+//imgdata.output
+#define greybox         (imgdata.params.greybox)
+#define aber            (imgdata.params.aber)
+#define gamm            (imgdata.params.gamm)
+#define user_mul        (imgdata.params.user_mul)
+#define shot_select     (imgdata.params.shot_select)
+#define bright          (imgdata.params.bright)
+#define threshold       (imgdata.params.threshold)
+#define half_size       (imgdata.params.half_size)
+#define four_color_rgb  (imgdata.params.four_color_rgb)
+#define document_mode   (imgdata.params.document_mode)
+#define highlight       (imgdata.params.highlight)
+//#define verbose         (imgdata.params.verbose)
+#define use_auto_wb     (imgdata.params.use_auto_wb)
+#define use_camera_wb   (imgdata.params.use_camera_wb)
+#define use_camera_matrix (imgdata.params.use_camera_matrix)
+#define output_color    (imgdata.params.output_color)
+#define output_bps      (imgdata.params.output_bps)
+#define gamma_16bit      (imgdata.params.gamma_16bit)
+#define output_tiff     (imgdata.params.output_tiff)
+#define med_passes      (imgdata.params.med_passes)
+#define no_auto_bright  (imgdata.params.no_auto_bright)
+#define use_fuji_rotate (imgdata.params.use_fuji_rotate)
+#define filtering_mode (imgdata.params.filtering_mode)
+
+//rgb_constants
+#define xyz_rgb         (rgb_constants.xyz_rgb)
+#define d65_white       (rgb_constants.d65_white)
+
+//libraw_internal_data.internal_data
+#define meta_data       (libraw_internal_data.internal_data.meta_data)
+#define ifp             libraw_internal_data.internal_data.input
+#define ifname          ((char*)libraw_internal_data.internal_data.input->fname())
+#define ofp             libraw_internal_data.internal_data.output
+#define profile_offset  (libraw_internal_data.internal_data.profile_offset)
+#define thumb_offset    (libraw_internal_data.internal_data.toffset)
+
+//libraw_internal_data.internal_output_params
+#define mix_green       (libraw_internal_data.internal_output_params.mix_green)
+#define raw_color       (libraw_internal_data.internal_output_params.raw_color)
+#define use_gamma       (libraw_internal_data.internal_output_params.use_gamma)
+#define zero_is_bad     (libraw_internal_data.internal_output_params.zero_is_bad)
+#ifndef SRC_USES_SHRINK
+#define shrink          (libraw_internal_data.internal_output_params.shrink)
+#endif
+#define fuji_width      (libraw_internal_data.internal_output_params.fuji_width)
+
+
+//libraw_internal_data.output_data
+#define histogram       (libraw_internal_data.output_data.histogram)
+#define oprof           (libraw_internal_data.output_data.oprof)
+
+//libraw_internal_data.identify_data
+#define exif_cfa        (libraw_internal_data.identify_data.olympus_exif_cfa)
+#define unique_id       (libraw_internal_data.identify_data.unique_id)
+#define tiff_nifds      (libraw_internal_data.identify_data.tiff_nifds)
+#define tiff_flip       (libraw_internal_data.identify_data.tiff_flip)
+
+//libraw_internal_data.unpacker_data
+#define order           (libraw_internal_data.unpacker_data.order)
+#define data_error      (libraw_internal_data.unpacker_data.data_error)
+#define cr2_slice       (libraw_internal_data.unpacker_data.cr2_slice)
+#define sraw_mul        (libraw_internal_data.unpacker_data.sraw_mul)
+#define kodak_cbpp      (libraw_internal_data.unpacker_data.kodak_cbpp)
+#define strip_offset    (libraw_internal_data.unpacker_data.strip_offset)
+#define data_offset     (libraw_internal_data.unpacker_data.data_offset)
+#define meta_offset     (libraw_internal_data.unpacker_data.meta_offset)
+#define meta_length     (libraw_internal_data.unpacker_data.meta_length)
+#define thumb_misc      (libraw_internal_data.unpacker_data.thumb_misc)
+#define fuji_layout     (libraw_internal_data.unpacker_data.fuji_layout)
+#define tiff_samples    (libraw_internal_data.unpacker_data.tiff_samples)
+#define tiff_bps        (libraw_internal_data.unpacker_data.tiff_bps)
+#define tiff_compress   (libraw_internal_data.unpacker_data.tiff_compress)
+#define zero_after_ff   (libraw_internal_data.unpacker_data.zero_after_ff)
+#define tile_width      (libraw_internal_data.unpacker_data.tile_width)
+#define tile_length     (libraw_internal_data.unpacker_data.tile_length)
+#define load_flags      (libraw_internal_data.unpacker_data.load_flags)
+
+#ifdef LIBRAW_IO_REDEFINED
+#define fread(ptr,size,n,stream) stream->read(ptr,size,n)
+#define fseek(stream,o,w)	 stream->seek(o,w)
+#define fseeko(stream,o,w)	 stream->seek(o,w)
+#define ftell(stream)		 stream->tell()
+#define ftello(stream)		 stream->tell()
+#define getc(stream)		 stream->get_char()
+#define fgetc(stream)		 stream->get_char()
+#define fgets(str,n,stream)	 stream->gets(str,n)
+#define fscanf(stream,fmt,ptr)	 stream->scanf_one(fmt,ptr)
+#endif
+
+#endif
diff --git a/libfspotraw/LibRaw/lib/Makefile b/libfspotraw/LibRaw/lib/Makefile
new file mode 100644
index 0000000..a49e511
--- /dev/null
+++ b/libfspotraw/LibRaw/lib/Makefile
@@ -0,0 +1,3 @@
+all: 
+	@(cd ..; make library)
+	@echo Done
diff --git a/libfspotraw/LibRaw/libraw/libraw.h b/libfspotraw/LibRaw/libraw/libraw.h
new file mode 100644
index 0000000..1a758c9
--- /dev/null
+++ b/libfspotraw/LibRaw/libraw/libraw.h
@@ -0,0 +1,219 @@
+/* -*- C++ -*-
+ * File: libraw.h
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8, 2008 
+ *
+ * LibRaw C++ interface
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _LIBRAW_CLASS_H
+#define _LIBRAW_CLASS_H
+
+#include <limits.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#include "libraw_datastream.h"
+#include "libraw_types.h"
+#include "libraw_const.h"
+#include "libraw_internal.h"
+#include "libraw_alloc.h"
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+DllDef    const char          *libraw_strerror(int errorcode);
+DllDef    const char          *libraw_strprogress(enum LibRaw_progress);
+    /* LibRaw C API */
+DllDef    libraw_data_t       *libraw_init(unsigned int flags);
+DllDef    int                 libraw_open_file(libraw_data_t*, const char *);
+DllDef    int                 libraw_open_buffer(libraw_data_t*, void * buffer, size_t size);
+DllDef    int                 libraw_unpack(libraw_data_t*);
+DllDef    int                 libraw_unpack_thumb(libraw_data_t*);
+DllDef    void                libraw_recycle(libraw_data_t*);
+DllDef    void                libraw_close(libraw_data_t*);
+    /* version helpers */
+DllDef    const char*               libraw_version();
+DllDef    int                 libraw_versionNumber();
+    /* Camera list */
+DllDef    const char**        libraw_cameraList();
+DllDef    int                 libraw_cameraCount();
+
+DllDef    void                libraw_set_memerror_handler(libraw_data_t*, memory_callback cb, void *datap);
+DllDef    void                libraw_set_dataerror_handler(libraw_data_t*,data_callback func,void *datap);
+DllDef    void                libraw_set_progress_handler(libraw_data_t*,progress_callback cb,void *datap);
+DllDef    int                 libraw_add_masked_borders_to_bitmap(libraw_data_t* lr);
+DllDef    const char *        libraw_unpack_function_name(libraw_data_t* lr);
+DllDef    int                 libraw_rotate_fuji_raw(libraw_data_t* lr);
+
+    /* DCRAW compatibility */
+DllDef    int                 libraw_adjust_sizes_info_only(libraw_data_t*);
+DllDef    int                 libraw_dcraw_document_mode_processing(libraw_data_t*);
+DllDef    int                 libraw_dcraw_ppm_tiff_writer(libraw_data_t* lr,const char *filename);
+DllDef    int                 libraw_dcraw_thumb_writer(libraw_data_t* lr,const char *fname);
+DllDef    int                 libraw_dcraw_process(libraw_data_t* lr);
+DllDef    libraw_processed_image_t* dcraw_make_mem_image(libraw_data_t* lr, int *errc);
+DllDef    libraw_processed_image_t* dcraw_make_mem_thumb(libraw_data_t* lr, int *errc);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+
+class DllDef LibRaw
+{
+  public:
+    libraw_data_t imgdata;
+    int verbose;
+
+    LibRaw(unsigned int flags = LIBRAW_OPTIONS_NONE);
+    
+    libraw_output_params_t*     output_params_ptr() { return &imgdata.params;}
+    int                         open_file(const char *fname);
+    int                         open_buffer(void *buffer, size_t size);
+    int                         open_datastream(LibRaw_abstract_datastream *);
+    int                         unpack(void);
+    int                         unpack_thumb(void);
+
+    int                         adjust_sizes_info_only(void);
+    void                        set_memerror_handler( memory_callback cb,void *data) {callbacks.memcb_data = data; callbacks.mem_cb = cb; }
+    void                        set_dataerror_handler(data_callback func, void *data) { callbacks.datacb_data = data; callbacks.data_cb = func;}
+    void                        set_progress_handler(progress_callback pcb, void *data) { callbacks.progresscb_data = data; callbacks.progress_cb = pcb;}
+
+    /* helpers */
+    static const char*          version() { return LIBRAW_VERSION_STR;}
+    static int                  versionNumber() { return LIBRAW_VERSION; }
+    static const char**         cameraList();
+    static int                  cameraCount();
+    static const char*          strprogress(enum LibRaw_progress);
+    static const char*          strerror(int p) { return libraw_strerror(p);}
+    /* dcraw emulation */
+    int                         dcraw_document_mode_processing();
+    int                         dcraw_ppm_tiff_writer(const char *filename);
+    int                         dcraw_thumb_writer(const char *fname);
+    int                         dcraw_process(void);
+    /* memory writers */
+    libraw_processed_image_t*   dcraw_make_mem_image(int *errcode=NULL);  
+    libraw_processed_image_t*   dcraw_make_mem_thumb(int *errcode=NULL);  
+
+    /* free all internal data structures */
+    void         recycle(); 
+    ~LibRaw(void) { recycle(); delete tls; }
+
+    int FC(int row,int col) { return (imgdata.idata.filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3);}
+    int         fc (int row, int col);
+    int add_masked_borders_to_bitmap();
+    
+    const char *unpack_function_name();
+    int         rotate_fuji_raw();
+
+  private:
+    void*        malloc(size_t t);
+    void*        calloc(size_t n,size_t t);
+    void        free(void *p);
+    void        merror (void *ptr, const char *where);
+    void        derror();
+
+    LibRaw_TLS  *tls;
+    libraw_internal_data_t libraw_internal_data;
+    decode      first_decode[2048], *second_decode, *free_decode;
+    tiff_ifd_t  tiff_ifd[10];
+    libraw_memmgr memmgr;
+    libraw_callbacks_t callbacks;
+
+    LibRaw_constants rgb_constants;
+    void        (LibRaw:: *write_thumb)(), 
+                (LibRaw:: *write_fun)();
+    void        (LibRaw:: *load_raw)(),
+                (LibRaw:: *thumb_load_raw)();
+
+    void        kodak_thumb_loader();
+    void        write_thumb_ppm_tiff(FILE *); 
+    void        foveon_thumb_loader (void);
+
+    
+    void init_masked_ptrs();
+    ushort *get_masked_pointer(int row, int col); 
+    
+    int         own_filtering_supported(){ return 0;}
+    void        identify();
+    void        identify2(unsigned);
+    void        write_ppm_tiff ();
+    void        convert_to_rgb();
+    void        kodak_ycbcr_load_raw();
+    void        remove_zeroes();
+#ifndef NO_LCMS
+    void	apply_profile(const char*,const char*);
+#endif
+    void        pre_interpolate();
+    void        border_interpolate (int border);
+    void        lin_interpolate();
+    void        vng_interpolate();
+    void        ppg_interpolate();
+    void        ahd_interpolate();
+
+    void        bad_pixels(const char*);
+    void        subtract(const char*);
+    void        hat_transform (float *temp, float *base, int st, int size, int sc);
+    void        wavelet_denoise();
+    void        scale_colors();
+    void        median_filter ();
+    void        blend_highlights();
+    void        recover_highlights();
+
+    void        fuji_rotate();
+    void        stretch();
+
+    void        foveon_thumb ();
+    void        jpeg_thumb_writer (FILE *tfp,char *thumb,int thumb_length);
+    void        jpeg_thumb ();
+    void        ppm_thumb ();
+    void        layer_thumb ();
+    void        rollei_thumb ();
+    void        kodak_thumb_load_raw();
+
+    void        foveon_decoder (unsigned size, unsigned code);
+    unsigned    get4();
+
+    int         flip_index (int row, int col);
+    void        gamma_curve (double pwr, double ts, int mode, int imax);
+
+
+#ifdef LIBRAW_LIBRARY_BUILD 
+#include "internal/libraw_internal_funcs.h"
+#endif
+
+};
+
+#ifdef LIBRAW_LIBRARY_BUILD 
+#define RUN_CALLBACK(stage,iter,expect)  if(callbacks.progress_cb) { \
+        int rr = (*callbacks.progress_cb)(callbacks.progresscb_data,stage,iter,expect); \
+        if(rr!=0) throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; \
+    }
+#endif
+
+
+#endif /* __cplusplus */
+
+
+#endif /* _LIBRAW_CLASS_H */
diff --git a/libfspotraw/LibRaw/libraw/libraw_alloc.h b/libfspotraw/LibRaw/libraw/libraw_alloc.h
new file mode 100644
index 0000000..506db3d
--- /dev/null
+++ b/libfspotraw/LibRaw/libraw/libraw_alloc.h
@@ -0,0 +1,97 @@
+/* -*- C++ -*-
+ * File: libraw_alloc.h
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  22, 2008 
+ *
+ * LibRaw C++ interface
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __LIBRAW_ALLOC_H
+#define __LIBRAW_ALLOC_H
+
+#include <stdlib.h>
+#include <string.h>
+#ifdef WIN32
+#define bzero(p,sz) memset(p,0,sz)
+#endif
+
+#ifdef __cplusplus
+
+#define MSIZE 32
+
+class libraw_memmgr
+{
+  public:
+    libraw_memmgr()
+        {
+            bzero(mems,sizeof(mems));
+            calloc_cnt=0;
+        }
+    void *malloc(size_t sz)
+        {
+            void *ptr = ::malloc(sz);
+            mem_ptr(ptr);
+            return ptr;
+        }
+    void *calloc(size_t n, size_t sz)
+        {
+            void *ptr =  ::calloc(n,sz);
+            mem_ptr(ptr);
+            return ptr;
+        }
+    void  free(void *ptr)
+    {
+        ::free(ptr);
+        forget_ptr(ptr);
+    }
+    void cleanup(void)
+    {
+        for(int i = 0; i< MSIZE; i++)
+            if(mems[i])
+                {
+                    free(mems[i]);
+                    mems[i] = NULL;
+                }
+    }
+
+  private:
+    void *mems[MSIZE];
+    int calloc_cnt;
+    void mem_ptr(void *ptr)
+    {
+        if(ptr)
+            for(int i=0;i < MSIZE; i++)
+                if(!mems[i])
+                    {
+                        mems[i] = ptr;
+                        break;
+                    }
+    }
+    void forget_ptr(void *ptr)
+    {
+        if(ptr)
+            for(int i=0;i < MSIZE; i++)
+                if(mems[i] == ptr)
+                    mems[i] = NULL;
+    }
+
+};
+
+#endif /* C++ */
+
+#endif
diff --git a/libfspotraw/LibRaw/libraw/libraw_const.h b/libfspotraw/LibRaw/libraw/libraw_const.h
new file mode 100644
index 0000000..e78d586
--- /dev/null
+++ b/libfspotraw/LibRaw/libraw/libraw_const.h
@@ -0,0 +1,160 @@
+/* -*- C++ -*-
+ * File: libraw_const.h
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw error codes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _LIBRAW_ERRORS_H
+#define _LIBRAW_ERRORS_H
+
+enum LibRaw_constructor_flags
+{
+    LIBRAW_OPTIONS_NONE         =0,
+    LIBRAW_OPIONS_NO_MEMERR_CALLBACK=1,
+    LIBRAW_OPIONS_NO_DATAERR_CALLBACK=1<<1
+};
+
+enum LibRaw_warnings
+{
+    LIBRAW_WARN_NONE            =0,
+    LIBRAW_WARN_FOVEON_NOMATRIX =1,
+    LIBRAW_WARN_FOVEON_INVALIDWB =1<<1,
+    LIBRAW_WARN_BAD_CAMERA_WB   =1<<2,
+    LIBRAW_WARN_NO_METADATA     =1<<3,
+    LIBRAW_WARN_NO_JPEGLIB     = 1<<4,
+    LIBRAW_WARN_NO_EMBEDDED_PROFILE = 1<<5,
+    LIBRAW_WARN_NO_INPUT_PROFILE = 1<<6,
+    LIBRAW_WARN_BAD_OUTPUT_PROFILE= 1<<7,
+    LIBRAW_WARN_NO_BADPIXELMAP=1<<8,
+    LIBRAW_WARN_BAD_DARKFRAME_FILE=1<<9,
+    LIBRAW_WARN_BAD_DARKFRAME_DIM=1<<10
+};
+
+enum LibRaw_exceptions
+{
+    LIBRAW_EXCEPTION_NONE       =0,
+    LIBRAW_EXCEPTION_ALLOC      =1,
+    LIBRAW_EXCEPTION_DECODE_RAW =2,
+    LIBRAW_EXCEPTION_DECODE_JPEG=3,
+    LIBRAW_EXCEPTION_IO_EOF     =4,
+    LIBRAW_EXCEPTION_IO_CORRUPT =5,
+    LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK=6
+};
+
+
+enum LibRaw_colorstate
+{
+    LIBRAW_COLORSTATE_UNKNOWN   =0,
+    LIBRAW_COLORSTATE_INIT      =1,
+    LIBRAW_COLORSTATE_CONST     =2,
+    LIBRAW_COLORSTATE_LOADED    =3,
+    LIBRAW_COLORSTATE_CALCULATED=4,
+    LIBRAW_COLORSTATE_RESERVED1 =5,
+    LIBRAW_COLORSTATE_RESERVED2 =6,
+    LIBRAW_COLORSTATE_RESERVED3 =7
+};
+
+enum LibRaw_filtering
+{
+    LIBRAW_FILTERING_DEFAULT            =0,
+    LIBRAW_FILTERING_NOZEROES           =1,  
+    LIBRAW_FILTERING_NOBLACKS           =2, 
+    LIBRAW_FILTERING_NORAWCURVE         =4,
+    LIBRAW_FILTERING_NONE               =7,
+    LIBRAW_FILTERING_LIBRAWOWN          =(8 | LIBRAW_FILTERING_NONE),
+    LIBRAW_FILTERING_AUTOMATIC_BIT      =16,
+    LIBRAW_FILTERING_AUTOMATIC          = (LIBRAW_FILTERING_LIBRAWOWN | LIBRAW_FILTERING_AUTOMATIC_BIT)
+};
+
+
+enum LibRaw_progress
+{
+    LIBRAW_PROGRESS_START               = 0,
+    LIBRAW_PROGRESS_OPEN                = 1,
+    LIBRAW_PROGRESS_IDENTIFY            = 1<<1,
+    LIBRAW_PROGRESS_SIZE_ADJUST         = 1<<2,
+    LIBRAW_PROGRESS_LOAD_RAW            = 1<<3,
+    LIBRAW_PROGRESS_REMOVE_ZEROES       = 1<<4,
+    LIBRAW_PROGRESS_BAD_PIXELS          = 1<<5,
+    LIBRAW_PROGRESS_DARK_FRAME          = 1<<6,
+    LIBRAW_PROGRESS_FOVEON_INTERPOLATE  = 1<<7,
+    LIBRAW_PROGRESS_SCALE_COLORS        = 1<<8,
+    LIBRAW_PROGRESS_PRE_INTERPOLATE     = 1<<9,
+    LIBRAW_PROGRESS_INTERPOLATE         = 1<<10,
+    LIBRAW_PROGRESS_MIX_GREEN           = 1<<11,
+    LIBRAW_PROGRESS_MEDIAN_FILTER       = 1<<12,
+    LIBRAW_PROGRESS_HIGHLIGHTS          = 1<<13,
+    LIBRAW_PROGRESS_FUJI_ROTATE         = 1<<14,
+    LIBRAW_PROGRESS_FLIP                = 1<<15,
+    LIBRAW_PROGRESS_APPLY_PROFILE       = 1<<16,
+    LIBRAW_PROGRESS_CONVERT_RGB         = 1<<17,
+    LIBRAW_PROGRESS_STRETCH             = 1<<18,
+/* reserved */
+    LIBRAW_PROGRESS_STAGE19             = 1<<19,
+    LIBRAW_PROGRESS_STAGE20             = 1<<20,
+    LIBRAW_PROGRESS_STAGE21             = 1<<21,
+    LIBRAW_PROGRESS_STAGE22             = 1<<22,
+    LIBRAW_PROGRESS_STAGE23             = 1<<23,
+    LIBRAW_PROGRESS_STAGE24             = 1<<24,
+    LIBRAW_PROGRESS_STAGE25             = 1<<25,
+    LIBRAW_PROGRESS_STAGE26             = 1<<26,
+    LIBRAW_PROGRESS_STAGE27             = 1<<27,
+
+    LIBRAW_PROGRESS_THUMB_LOAD          = 1<<28,
+    LIBRAW_PROGRESS_TRESERVED1          = 1<<29,
+    LIBRAW_PROGRESS_TRESERVED2          = 1<<30,
+    LIBRAW_PROGRESS_TRESERVED3          = 1<<31
+};
+#define LIBRAW_PROGRESS_THUMB_MASK 0x0fffffff
+
+enum LibRaw_errors
+{
+    LIBRAW_SUCCESS = 0,
+    LIBRAW_UNSPECIFIED_ERROR=-1,
+    LIBRAW_FILE_UNSUPPORTED = -2,
+    LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE=-3,
+    LIBRAW_OUT_OF_ORDER_CALL=-4,
+    LIBRAW_NO_THUMBNAIL=-5,
+    LIBRAW_UNSUPPORTED_THUMBNAIL=-6,
+    LIBRAW_CANNOT_ADDMASK=-7,
+    LIBRAW_UNSUFFICIENT_MEMORY=-100007,
+    LIBRAW_DATA_ERROR=-100008,
+    LIBRAW_IO_ERROR=-100009,
+    LIBRAW_CANCELLED_BY_CALLBACK=-100010
+};
+
+#define LIBRAW_FATAL_ERROR(ec) ((ec)<-100000)
+
+enum LibRaw_thumbnail_formats
+{
+    LIBRAW_THUMBNAIL_UNKNOWN=0,
+    LIBRAW_THUMBNAIL_JPEG=1,
+    LIBRAW_THUMBNAIL_BITMAP=2,
+    LIBRAW_THUMBNAIL_LAYER=4,
+    LIBRAW_THUMBNAIL_ROLLEI=5
+};
+
+enum LibRaw_image_formats
+{
+    LIBRAW_IMAGE_BITMAP=1,
+    LIBRAW_IMAGE_JPEG=2
+};
+
+#endif
diff --git a/libfspotraw/LibRaw/libraw/libraw_datastream.h b/libfspotraw/LibRaw/libraw/libraw_datastream.h
new file mode 100644
index 0000000..6616077
--- /dev/null
+++ b/libfspotraw/LibRaw/libraw/libraw_datastream.h
@@ -0,0 +1,301 @@
+/* -*- C -*-
+ * File: libraw_datastream.h
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sun Jan 18 13:07:35 2009
+ *
+ * LibRaw Data stream interface
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __LIBRAW_DATASTREAM_H
+#define __LIBRAW_DATASTREAM_H
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+
+#ifndef __cplusplus
+
+struct LibRaw_abstract_datastream;
+
+#else /* __cplusplus */
+
+#include "libraw_const.h"
+
+class LibRaw_buffer_datastream;
+
+class LibRaw_abstract_datastream
+{
+  public:
+    LibRaw_abstract_datastream(){substream=0;};
+    virtual             ~LibRaw_abstract_datastream(void){if(substream) delete substream;}
+    virtual int         valid(){return 0;}
+    virtual int         read(void *,size_t, size_t ){ return -1;}
+    virtual int         seek(off_t , int ){return -1;}
+    virtual int         tell(){return -1;}
+    virtual int         get_char(){return -1;}
+    virtual char*       gets(char *, int){ return NULL;}
+    virtual int         scanf_one(const char *, void *){return -1;}
+    virtual int         eof(){return -1;}
+
+    virtual const char* fname(){ return NULL;};
+    virtual int         subfile_open(const char*){ return EINVAL;}
+    virtual void        subfile_close(){}
+    virtual int		tempbuffer_open(void*, size_t);
+    virtual void	tempbuffer_close()
+    {
+        if(substream) delete substream;
+        substream = NULL;
+    }
+
+  protected:
+    LibRaw_abstract_datastream *substream;
+};
+
+
+class LibRaw_file_datastream : public LibRaw_abstract_datastream
+{
+  public:
+    LibRaw_file_datastream(const char *fname) 
+        { 
+            if(fname)
+                {filename = fname; f = fopen(fname,"rb");}
+            else 
+                {filename=0;f=0;}
+            sav=0;
+        }
+
+    virtual ~LibRaw_file_datastream() {if(f)fclose(f); if(sav)fclose(sav);}
+
+    virtual int valid() { return f?1:0;}
+
+#define CHK() do {if(!f) throw LIBRAW_EXCEPTION_IO_EOF;}while(0)
+    virtual int read(void * ptr,size_t size, size_t nmemb) 
+    { 
+        CHK(); 
+        return substream?substream->read(ptr,size,nmemb):int(fread(ptr,size,nmemb,f));
+    }
+    virtual int eof() 
+    { 
+        CHK(); 
+        return substream?substream->eof():feof(f);
+    }
+    virtual int seek(off_t o, int whence) 
+    { 
+        CHK(); 
+        return substream?substream->seek(o,whence):fseek(f,o,whence);
+    }
+    virtual int tell() 
+    { 
+        CHK(); 
+        return substream?substream->tell():ftell(f);
+    }
+    virtual int get_char() 
+    { 
+        CHK(); 
+        return substream?substream->get_char():fgetc(f);
+    }
+    virtual char* gets(char *str, int sz) 
+    { 
+        CHK(); 
+        return substream?substream->gets(str,sz):fgets(str,sz,f);
+    }
+    virtual int scanf_one(const char *fmt, void*val) 
+    { 
+        CHK(); 
+        return substream?substream->scanf_one(fmt,val):fscanf(f,fmt,val);
+    }
+
+    virtual const char *fname() { return filename; }
+
+    virtual int subfile_open(const char *fn)
+    {
+        if(sav) return EBUSY;
+        sav = f;
+        f = fopen(fn,"rb");
+        if(!f)
+            {
+                f = sav;
+                sav = NULL;
+                return ENOENT;
+            }
+        else
+            return 0;
+    }
+    virtual void subfile_close()
+    {
+        if(!sav) return;
+        fclose(f);
+        f = sav;
+        sav = 0;
+    }
+
+  private:
+    FILE *f,*sav;
+    const char *filename;
+};
+#undef CHK
+
+class LibRaw_buffer_datastream : public LibRaw_abstract_datastream
+{
+  public:
+    LibRaw_buffer_datastream(void *buffer, size_t bsize)
+        {
+            buf = (unsigned char*)buffer; streampos = 0; streamsize = bsize;
+        }
+    virtual ~LibRaw_buffer_datastream(){}
+    virtual int valid() { return buf?1:0;}
+    virtual int read(void * ptr,size_t sz, size_t nmemb) 
+    { 
+        if(substream) return substream->read(ptr,sz,nmemb);
+        size_t to_read = sz*nmemb;
+        if(to_read > streamsize - streampos)
+            to_read = streamsize-streampos;
+        if(to_read<1) 
+            return 0;
+        memmove(ptr,buf+streampos,to_read);
+        streampos+=to_read;
+        return int((to_read+sz-1)/sz);
+    }
+
+    virtual int eof() 
+    { 
+        if(substream) return substream->eof();
+        return streampos >= streamsize;
+    }
+
+    virtual int seek(off_t o, int whence) 
+    { 
+        if(substream) return substream->seek(o,whence);
+        switch(whence)
+            {
+            case SEEK_SET:
+                if(o<0)
+                    streampos = 0;
+                else if (size_t(o) > streamsize)
+                    streampos = streamsize;
+                else
+                    streampos = size_t(o);
+                return 0;
+            case SEEK_CUR:
+                if(o<0)
+                    {
+                        if(size_t(-o) >= streampos)
+                            streampos = 0;
+                        else
+                            streampos += o;
+                    }
+                else if (o>0)
+                    {
+                        if(o+streampos> streamsize)
+                            streampos = streamsize;
+                        else
+                            streampos += o;
+                    }
+                return 0;
+            case SEEK_END:
+                if(o>0)
+                    streampos = streamsize;
+                else if ( size_t(-o) > streamsize)
+                    streampos = 0;
+                else
+                    streampos = streamsize+o;
+                return 0;
+            default:
+                return 0;
+            }
+    }
+    
+    virtual int tell() 
+    { 
+        if(substream) return substream->tell();
+        return int(streampos);
+    }
+
+    virtual int get_char() 
+    { 
+        if(substream) return substream->get_char();
+        if(streampos>=streamsize)
+            return -1;
+        return buf[streampos++];
+    }
+    virtual char* gets(char *s, int sz) 
+    { 
+        if (substream) return substream->gets(s,sz);
+        unsigned char *psrc,*pdest,*str;
+        str = (unsigned char *)s;
+        psrc = buf+streampos;
+        pdest = str;
+        while ( (size_t(psrc - buf) < streamsize)
+               &&
+                ((pdest-str)<sz)
+		)
+	  {
+                *pdest = *psrc;
+                if(*psrc == '\n')
+                    break;
+                psrc++;
+                pdest++;
+            }
+        if(size_t(psrc-buf) < streamsize)
+            psrc++;
+        if((pdest-str)<sz)
+            *(++pdest)=0;
+        streampos = psrc - buf;
+        return s;
+    }
+    virtual int scanf_one(const char *fmt, void* val) 
+    { 
+        if(substream) return substream->scanf_one(fmt,val);
+        int scanf_res;
+        if(streampos>streamsize) return 0;
+        scanf_res = sscanf((char*)(buf+streampos),fmt,val);
+        if(scanf_res>0)
+            {
+                int xcnt=0;
+                while(streampos<streamsize)
+                    {
+                        streampos++;
+                        xcnt++;
+                        if(buf[streampos] == 0
+                           || buf[streampos]==' '
+                           || buf[streampos]=='\t'
+                           || buf[streampos]=='\n'
+                           || xcnt>24)
+                            break;
+                    }
+            }
+        return scanf_res;
+    }
+  private:
+    unsigned char *buf;
+    size_t   streampos,streamsize;
+};
+
+inline int LibRaw_abstract_datastream::tempbuffer_open(void  *buf, size_t size)
+{
+    if(substream) return EBUSY;
+    substream = new LibRaw_buffer_datastream(buf,size);
+    return substream?0:EINVAL;
+}
+
+
+#endif
+
+#endif
+
diff --git a/libfspotraw/LibRaw/libraw/libraw_internal.h b/libfspotraw/LibRaw/libraw/libraw_internal.h
new file mode 100644
index 0000000..6c1365f
--- /dev/null
+++ b/libfspotraw/LibRaw/libraw/libraw_internal.h
@@ -0,0 +1,237 @@
+/* -*- C++ -*-
+ * File: libraw_internal.h
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw internal data structures (not visible outside)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _LIBRAW_INTERNAL_TYPES_H
+#define _LIBRAW_INTERNAL_TYPES_H
+
+#include <stdio.h>
+#ifdef __cplusplus
+
+
+#ifndef CLASS
+#define CLASS LibRaw::
+#endif
+
+#else
+#ifndef CLASS
+#define CLASS
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include "libraw_datastream.h"
+
+class LibRaw_TLS
+{
+public:
+    struct 
+    {
+         unsigned bitbuf;
+         int vbits, reset;
+    }getbits;
+    struct 
+    {
+         UINT64 bitbuf;
+         int vbits;
+
+    }ph1_bits;
+    int make_decoder_leaf;
+    struct
+    {
+        struct decode *dstart[18], *dindex;
+        const int *s;
+    }radc_token;
+    struct
+    {
+         unsigned pad[128], p;
+    }sony_decrypt;
+    unsigned foveon_decoder_huff[1024];
+    uchar jpeg_buffer[4096];
+    struct
+    {
+        uchar buf[0x4000];
+        int vbits, padding;
+    }pana_bits;
+
+    void init() 
+        { 
+            getbits.bitbuf = 0; getbits.vbits = getbits.reset = 0;
+            ph1_bits.bitbuf = 0; ph1_bits.vbits = 0;
+            pana_bits.vbits = 0;
+        }
+};
+
+
+class LibRaw_constants
+{
+  public:
+    static const float d65_white[3];
+    static const double xyz_rgb[3][3];
+};
+#endif /* __cplusplus */
+
+#ifdef WIN32
+typedef long off_t;
+#endif
+
+typedef struct
+{
+#ifndef __cplusplus
+    struct
+#endif
+    LibRaw_abstract_datastream *input;
+    FILE        *output;
+    int         input_internal;
+    char        *meta_data;
+    off_t       profile_offset;
+    off_t       toffset;
+
+} internal_data_t;
+
+typedef struct
+{
+    unsigned    mix_green;
+    unsigned    raw_color;
+    unsigned    zero_is_bad;
+    ushort      shrink;
+    ushort      fuji_width;
+    ushort      fwidth,fheight;
+} internal_output_params_t;
+
+#define LIBRAW_HISTOGRAM_SIZE 0x2000
+typedef struct
+{
+    int         (*histogram)[LIBRAW_HISTOGRAM_SIZE];
+    unsigned    *oprof;
+} output_data_t;
+
+typedef struct
+{
+    unsigned olympus_exif_cfa;
+    unsigned     unique_id;
+    unsigned tiff_nifds;
+    int  tiff_flip;
+}identify_data_t;
+
+typedef struct
+{
+    short       order; 
+    ushort      sraw_mul[4],cr2_slice[3];
+    unsigned    kodak_cbpp;
+    off_t       strip_offset, data_offset;
+    off_t       meta_offset;
+    unsigned     meta_length;
+    unsigned    thumb_misc;
+    unsigned    fuji_layout;
+    unsigned    tiff_samples;
+    unsigned    tiff_bps;
+    unsigned    tiff_compress;
+    unsigned    zero_after_ff;
+    unsigned    tile_width, tile_length,load_flags;
+    unsigned    data_error;
+}unpacker_data_t;
+
+
+
+typedef struct
+{
+    internal_data_t internal_data;
+    internal_output_params_t internal_output_params;    
+    output_data_t output_data;
+    identify_data_t identify_data;
+    unpacker_data_t unpacker_data;
+} libraw_internal_data_t;
+
+
+struct decode 
+{
+    struct decode *branch[2];
+    int leaf;
+};
+
+struct tiff_ifd_t 
+{
+    int t_width, t_height, bps, comp, phint, offset, t_flip, samples, bytes;
+};
+
+
+struct jhead {
+  int bits, high, wide, clrs, sraw, psv, restart, vpred[6];
+  struct decode *huff[6];
+  ushort *row;
+};
+struct tiff_tag {
+  ushort tag, type;
+  int count;
+  union { char c[4]; short s[2]; int i; } val;
+};
+
+struct tiff_hdr {
+  ushort t_order, magic;
+  int ifd;
+  ushort pad, ntag;
+  struct tiff_tag tag[23];
+  int nextifd;
+  ushort pad2, nexif;
+  struct tiff_tag exif[4];
+  ushort pad3, ngps;
+  struct tiff_tag gpst[10];
+  short bps[4];
+  int rat[10];
+  unsigned gps[26];
+  char t_desc[512], t_make[64], t_model[64], soft[32], date[20], t_artist[64];
+};
+
+
+
+#ifdef DEBUG_STAGE_CHECKS
+#define CHECK_ORDER_HIGH(expected_stage) \
+    do { if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= expected_stage) {fprintf(stderr,"CHECK_HIGH: check %d >=  %d\n",imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK,expected_stage);return LIBRAW_OUT_OF_ORDER_CALL;} } while(0)
+
+#define CHECK_ORDER_LOW(expected_stage) \
+    do { printf("Checking LOW %d/%d : %d\n",imgdata.progress_flags,expected_stage,imgdata.progress_flags<expected_stage); if( (imgdata.progress_flags&LIBRAW_PROGRESS_THUMB_MASK) < expected_stage ) { printf("failed!\n"); return LIBRAW_OUT_OF_ORDER_CALL;} } while(0)
+#define CHECK_ORDER_BIT(expected_stage) \
+    do { if(imgdata.progress_flags & expected_stage) return LIBRAW_OUT_OF_ORDER_CALL; } while(0)
+
+#define SET_PROC_FLAG(stage) do {imgdata.progress_flags |= stage; fprintf(stderr,"SET_FLAG: %d\n",stage); } while (0)
+
+#else
+
+#define CHECK_ORDER_HIGH(expected_stage) \
+    do { if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= expected_stage) \
+            {return LIBRAW_OUT_OF_ORDER_CALL;} } while(0)
+
+#define CHECK_ORDER_LOW(expected_stage) \
+    do { if((imgdata.progress_flags&LIBRAW_PROGRESS_THUMB_MASK) < expected_stage) \
+            return LIBRAW_OUT_OF_ORDER_CALL; } while(0)
+
+#define CHECK_ORDER_BIT(expected_stage) \
+    do { if(imgdata.progress_flags & expected_stage) return LIBRAW_OUT_OF_ORDER_CALL; } while(0)
+
+#define SET_PROC_FLAG(stage) do {imgdata.progress_flags |= stage;} while (0)
+
+#endif
+
+#endif
diff --git a/libfspotraw/LibRaw/libraw/libraw_types.h b/libfspotraw/LibRaw/libraw/libraw_types.h
new file mode 100644
index 0000000..8289b00
--- /dev/null
+++ b/libfspotraw/LibRaw/libraw/libraw_types.h
@@ -0,0 +1,277 @@
+/* -*- C++ -*-
+ * File: libraw_types.h
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw C data structures
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _LIBRAW_TYPES_H
+#define _LIBRAW_TYPES_H
+
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+#include <stdio.h>
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef USE_LCMS
+#define NO_LCMS
+#endif
+
+#include "libraw_const.h"
+#include "libraw_version.h"
+
+typedef long long INT64;
+typedef unsigned long long UINT64;
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+
+#ifdef WIN32
+#ifdef LIBRAW_NODLL
+# define DllDef
+#else
+# ifdef LIBRAW_BUILDLIB
+#    define DllDef   __declspec( dllexport )
+# else
+#    define DllDef   __declspec( dllimport )
+# endif
+#endif
+#else
+#  define DllDef
+#endif
+
+
+
+typedef void (* memory_callback)(void * data, const char *file, const char *where);
+
+DllDef void default_memory_callback(void *data,const char *file, const char *where);
+
+typedef void (*data_callback)(void *data,const char *file, const int offset);
+
+DllDef void default_data_callback(void *data,const char *file, const int offset);
+
+typedef int (* progress_callback) (void *data,enum LibRaw_progress stage, int iteration,int expected);
+
+typedef struct
+{
+    memory_callback mem_cb;
+    void*  memcb_data;
+
+    data_callback data_cb;
+    void*       datacb_data;
+
+    progress_callback progress_cb;
+    void *progresscb_data;
+} libraw_callbacks_t;
+
+
+typedef struct
+{
+    enum LibRaw_image_formats type; 
+    ushort      height,
+                width,
+                colors,
+                bits;
+#ifdef _OPENMP
+#pragma omp firstprivate(colors,height,width)
+#endif
+    unsigned int  data_size; 
+    unsigned char data[1]; 
+}libraw_processed_image_t;
+
+
+typedef struct
+{
+    char        make[64];
+    char        model[64];
+
+    unsigned    raw_count;
+    unsigned    dng_version;
+    unsigned    is_foveon;
+    int         colors;
+
+    unsigned    filters; 
+    char        cdesc[5];
+
+}libraw_iparams_t;
+
+typedef struct
+{
+    ushort      raw_height, 
+                raw_width, 
+                height, 
+                width, 
+                top_margin, 
+                left_margin;
+    ushort      iheight,
+                iwidth;
+#ifdef _OPENMP
+#pragma omp firstprivate(iheight,iwidth)
+#endif
+    double      pixel_aspect;
+    int         flip;
+
+    ushort      right_margin,bottom_margin; 
+
+} libraw_image_sizes_t;
+
+struct ph1_t
+{
+    int format, key_off, t_black, black_off, split_col, tag_21a;
+    float tag_210;
+};
+
+
+typedef struct
+{
+    unsigned curve_state        : 3;
+    unsigned rgb_cam_state      : 3;
+    unsigned cmatrix_state      : 3;
+    unsigned pre_mul_state      : 3;
+    unsigned cam_mul_state      : 3;
+    unsigned filler             : 17;
+} color_data_state_t;
+
+typedef struct
+{
+    color_data_state_t   color_flags;
+    ushort      white[8][8];  
+    float       cam_mul[4]; 
+    float       pre_mul[4]; 
+    float       cmatrix[3][4]; 
+    float       rgb_cam[3][4]; 
+    float       cam_xyz[4][3]; 
+    ushort      curve[0x10000]; 
+    unsigned    black;
+    unsigned    maximum;
+    struct ph1_t       phase_one_data;
+    float       flash_used; 
+    float       canon_ev; 
+    char        model2[64];
+    void        *profile;
+    unsigned    profile_length;
+}libraw_colordata_t;
+
+typedef struct
+{
+    enum LibRaw_thumbnail_formats tformat;
+    ushort      twidth, 
+                theight;
+    unsigned    tlength;
+    int         tcolors;
+    
+    char       *thumb;
+}libraw_thumbnail_t;
+
+typedef struct
+{
+    float       iso_speed; 
+    float       shutter;
+    float       aperture;
+    float       focal_len;
+    time_t      timestamp; 
+    unsigned    shot_order;
+    unsigned    gpsdata[32];
+    char        desc[512],
+                artist[64];
+} libraw_imgother_t;
+
+typedef struct
+{
+    unsigned    greybox[4];     /* -A  x1 y1 x2 y2 */
+    double      aber[4];        /* -C */
+    double      gamm[6];        /* -g */
+    float       user_mul[4];    /* -r mul0 mul1 mul2 mul3 */
+    unsigned    shot_select;    /* -s */
+    float       bright;         /* -b */
+    float       threshold;      /*  -n */
+#ifdef _OPENMP
+#pragma omp firstprivate(threshold)
+#endif
+    int         half_size;      /* -h */
+    int         four_color_rgb; /* -f */
+    int         document_mode;  /* -d/-D */
+    int         highlight;      /* -H */
+    int         use_auto_wb;    /* -a */
+    int         use_camera_wb;  /* -w */
+    int         use_camera_matrix; /* +M/-M */
+    int         output_color;   /* -o */
+    char        *output_profile; /* -o */
+    char        *camera_profile; /* -p */
+    char        *bad_pixels;    /* -P */
+    char        *dark_frame;    /* -K */
+    int         output_bps;     /* -4 */
+    int         output_tiff;    /* -T */
+    int         user_flip;      /* -t */
+    int         user_qual;      /* -q */
+    int         user_black;     /* -k */
+    int         user_sat;       /* -S */
+
+    int         med_passes;     /* -m */
+    float       auto_bright_thr; 
+    int         no_auto_bright; /* -W */
+    int         use_fuji_rotate;/* -j */
+    enum LibRaw_filtering    filtering_mode; 
+}libraw_output_params_t;
+
+typedef struct
+{
+    ushort  *buffer; 
+    ushort  *tl;     
+    ushort  *top;    
+    ushort  *tr;    
+    ushort  *left;  
+    ushort  *right; 
+    ushort  *bl;     
+    ushort  *bottom; 
+    ushort  *br;     
+    ushort  (*ph1_black)[2]; 
+}libraw_masked_t;
+
+typedef struct
+{
+    unsigned int                progress_flags;
+    unsigned int                process_warnings;
+    libraw_iparams_t            idata;
+    libraw_image_sizes_t        sizes;
+    libraw_colordata_t          color;
+    libraw_imgother_t           other;
+    libraw_thumbnail_t          thumbnail;
+    libraw_masked_t             masked_pixels;
+    ushort                      (*image)[4] ;
+#ifdef _OPENMP
+#pragma omp shared(image)
+#endif
+    libraw_output_params_t     params;
+    void                *parent_class;      
+} libraw_data_t;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libfspotraw/LibRaw/libraw/libraw_version.h b/libfspotraw/LibRaw/libraw/libraw_version.h
new file mode 100644
index 0000000..d3a9c16
--- /dev/null
+++ b/libfspotraw/LibRaw/libraw/libraw_version.h
@@ -0,0 +1,47 @@
+/* -*- C++ -*-
+ * File: libraw_version.h
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Mon Sept  8, 2008 
+ *
+ * LibRaw C++ interface
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __VERSION_H
+#define __VERSION_H
+
+#define LIBRAW_MAJOR_VERSION  0
+#define LIBRAW_MINOR_VERSION  8
+#define LIBRAW_PATCH_VERSION  0
+#define LIBRAW_VERSION_TAIL   Beta3
+
+#define _LIBRAW_VERSION_MAKE(a,b,c,d) #a"."#b"."#c"-"#d
+#define LIBRAW_VERSION_MAKE(a,b,c,d) _LIBRAW_VERSION_MAKE(a,b,c,d)
+
+#define LIBRAW_VERSION_STR LIBRAW_VERSION_MAKE(LIBRAW_MAJOR_VERSION,LIBRAW_MINOR_VERSION,LIBRAW_PATCH_VERSION,LIBRAW_VERSION_TAIL)
+
+#define LIBRAW_MAKE_VERSION(major,minor,patch) \
+    (((major) << 16) | ((minor) << 8) | (patch))
+
+#define LIBRAW_VERSION \
+    LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION,LIBRAW_MINOR_VERSION,LIBRAW_PATCH_VERSION)
+
+#define LIBRAW_CHECK_VERSION(major,minor,patch) \
+    ( LibRaw::versionNumber() >= LIBRAW_MAKE_VERSION(major,minor,patch) )
+
+
+#endif
diff --git a/libfspotraw/LibRaw/object/.keep_me b/libfspotraw/LibRaw/object/.keep_me
new file mode 100644
index 0000000..e69de29
diff --git a/libfspotraw/LibRaw/samples/4channels.cpp b/libfspotraw/LibRaw/samples/4channels.cpp
new file mode 100644
index 0000000..08f6542
--- /dev/null
+++ b/libfspotraw/LibRaw/samples/4channels.cpp
@@ -0,0 +1,190 @@
+/* -*- C++ -*-
+ * File: 4channels.cpp
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Mon Feb 09, 2009
+ *
+ * LibRaw sample
+ * Generates 4 TIFF file from RAW data, one file per channel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#ifndef WIN32
+#include <netinet/in.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include "libraw/libraw.h"
+
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
+
+int main(int ac, char *av[])
+{
+    int  i, ret;
+    int autoscale=0,filtering_mode=LIBRAW_FILTERING_DEFAULT,black_subtraction=1, use_gamma=0;
+    char outfn[1024]; 
+
+    LibRaw RawProcessor;
+    if(ac<2) 
+        {
+          usage:
+            printf(
+                "4channeld - LibRaw %s sample. %d cameras supported\n"
+                "Usage: %s [-s N] [-g] [-A] [-B] [-N] raw-files....\n"
+                "\t-s N - select Nth image in file (default=0)\n"
+                "\t-g - use gamma correction with gamma 2.2 (not precise,use for visual inspection only)\n"
+                "\t-A - autoscaling (by integer factor)\n"
+                "\t-B - no black subtraction\n"
+                "\t-N - no raw curve\n"
+                ,LibRaw::version(),
+                LibRaw::cameraCount(),
+                av[0]);
+            return 0;
+        }
+    
+#define P1 RawProcessor.imgdata.idata
+#define S RawProcessor.imgdata.sizes
+#define C RawProcessor.imgdata.color
+#define T RawProcessor.imgdata.thumbnail
+#define P2 RawProcessor.imgdata.other
+#define OUT RawProcessor.imgdata.params
+
+    OUT.document_mode=2;
+    OUT.output_bps=16;
+    OUT.output_tiff=1;
+    OUT.user_flip=0;
+    OUT.no_auto_bright = 1;
+    OUT.half_size=1;
+    OUT.filtering_mode= LIBRAW_FILTERING_AUTOMATIC;
+
+    for (i=1;i<ac;i++)
+        {
+            if(av[i][0]=='-')
+                {
+                    if(av[i][1]=='s' && av[i][2]==0)
+                        {
+                            i++;
+                            OUT.shot_select=atoi(av[i]);
+                        }
+                    else if(av[i][1]=='g' && av[i][2]==0)
+                        use_gamma = 1;
+                    else if(av[i][1]=='A' && av[i][2]==0)
+                        autoscale=1;
+                    else if(av[i][1]=='B' && av[i][2]==0)
+                        {
+                            filtering_mode |= (LIBRAW_FILTERING_NOZEROES | LIBRAW_FILTERING_NOBLACKS);
+                            black_subtraction=0;
+                        }
+                    else if(av[i][1]=='N' && av[i][2]==0)
+                        filtering_mode |= LIBRAW_FILTERING_NORAWCURVE;
+                    else
+                        goto usage;
+                    continue;
+                }
+            if(!use_gamma)
+                OUT.gamm[0] = OUT.gamm[1] = 1;
+                
+            if(filtering_mode)
+                OUT.filtering_mode = (LibRaw_filtering) filtering_mode;
+            int c;
+            printf("Processing file %s\n",av[i]);
+            if( (ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
+                {
+                    fprintf(stderr,"Cannot open %s: %s\n",av[i],libraw_strerror(ret));
+                    continue; // no recycle b/c open file will recycle itself
+                }
+            if(P1.is_foveon)
+                {
+                    printf("Cannot process foveon image %s\n",av[i]);
+                    continue ;
+                }
+            if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS)
+                {
+                    fprintf(stderr,"Cannot unpack %s: %s\n",av[i],libraw_strerror(ret));
+                    continue;
+                }
+            if(black_subtraction && C.black>0)
+                {
+                    for(int j=0; j<S.iheight*S.iwidth; j++)
+                        for(int c = 0; c< 4; c++)
+                            if(RawProcessor.imgdata.image[j][c]>C.black)
+                                RawProcessor.imgdata.image[j][c]-=C.black;
+                            else
+                                RawProcessor.imgdata.image[j][c]=0;
+                }
+
+            if(autoscale)
+                {
+                    unsigned max=0,scale;
+                    for(int j=0; j<S.iheight*S.iwidth; j++)
+                        for(int c = 0; c< 4; c++)
+                            if(max < RawProcessor.imgdata.image[j][c])
+                                max = RawProcessor.imgdata.image[j][c]; 
+                    if (max >0 && max< 1<<15)
+                        {
+                            scale = (1<<16)/max;
+                            printf("Scaling with multiplier=%d (max=%d)\n",scale,max);
+                            for(int j=0; j<S.iheight*S.iwidth; j++)
+                                for(c=0;c<4;c++)
+                                    RawProcessor.imgdata.image[j][c] *= scale;
+                        }
+		   printf("Black level (scaled)=%d\n",C.black*scale);
+                }
+		else
+		   printf("Black level (unscaled)=%d\n",C.black);
+
+
+            // hack to make dcraw tiff writer happy
+	    int isrgb=(P1.colors==4?0:1);
+            P1.colors = 1;
+            S.width = S.iwidth;
+            S.height = S.iheight;
+
+            for (int layer=0;layer<4;layer++)
+                {
+                    if(layer>0)
+                        {
+                            for (int rc = 0; rc < S.iheight*S.iwidth; rc++)
+                                RawProcessor.imgdata.image[rc][0] = RawProcessor.imgdata.image[rc][layer];
+                        }
+		    char lname[8];
+		    if(isrgb)
+		      {
+			snprintf(lname,7,"%c",((char*)("RGBG"))[layer]);
+			if(layer==3)
+			  strcat(lname,"2");
+		      }
+		    else
+		      snprintf(lname,7,"%c",((char*)("GCMY"))[layer]);
+
+                    if(OUT.shot_select)
+                        snprintf(outfn,sizeof(outfn),"%s-%d.%s.tiff",av[i],OUT.shot_select,lname);
+                    else
+                        snprintf(outfn,sizeof(outfn),"%s.%s.tiff",av[i],lname);
+                    
+                    printf("Writing file %s\n",outfn);
+                    if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
+                        fprintf(stderr,"Cannot write %s: %s\n",outfn,libraw_strerror(ret));
+                }
+
+        }
+    return 0;
+}
diff --git a/libfspotraw/LibRaw/samples/Makefile b/libfspotraw/LibRaw/samples/Makefile
new file mode 100644
index 0000000..be880e8
--- /dev/null
+++ b/libfspotraw/LibRaw/samples/Makefile
@@ -0,0 +1,2 @@
+all: 
+	(cd ..; make all_samples)
diff --git a/libfspotraw/LibRaw/samples/README-samples.rus b/libfspotraw/LibRaw/samples/README-samples.rus
new file mode 100644
index 0000000..9a775c9
--- /dev/null
+++ b/libfspotraw/LibRaw/samples/README-samples.rus
@@ -0,0 +1,3 @@
+
+See ../doc/Samples-LibRaw-rus.html and ../doc/Samples-LibRaw-eng.html
+
diff --git a/libfspotraw/LibRaw/samples/dcraw_emu.cpp b/libfspotraw/LibRaw/samples/dcraw_emu.cpp
new file mode 100644
index 0000000..7321767
--- /dev/null
+++ b/libfspotraw/LibRaw/samples/dcraw_emu.cpp
@@ -0,0 +1,282 @@
+/* -*- C++ -*-
+ * File: dcraw_emu.cpp
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sun Mar 23,   2008
+ *
+ * LibRaw simple C++ API sample: almost complete dcraw emulator
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <ctype.h>
+#ifndef WIN32
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#endif
+
+#include "libraw/libraw.h"
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
+
+
+void usage(const char *prog)
+{
+    printf("dcraw_emu: almost complete dcraw emulator\n");
+    printf("Usage:  %s [OPTION]... [FILE]...\n", prog);
+    printf(
+"-v        Verbose: print progress messages (repeated -v will add verbosity)\n"
+"-w        Use camera white balance, if possible\n"
+"-a        Average the whole image for white balance\n"
+"-A <x y w h> Average a grey box for white balance\n"
+"-r <r g b g> Set custom white balance\n"
+"+M/-M     Use/don't use an embedded color matrix\n"
+"-C <r b>  Correct chromatic aberration\n"
+"-P <file> Fix the dead pixels listed in this file\n"
+"-K <file> Subtract dark frame (16-bit raw PGM)\n"
+"-k <num>  Set the darkness level\n"
+"-S <num>  Set the saturation level\n"
+"-n <num>  Set threshold for wavelet denoising\n"
+"-H [0-9]  Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)\n"
+"-t [0-7]  Flip image (0=none, 3=180, 5=90CCW, 6=90CW)\n"
+"-o [0-5]  Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)\n"
+#ifndef NO_LCMS
+"-o file   Output ICC profile\n"
+"-p file   Camera input profile (use \'embed\' for embedded profile)\n"
+#endif
+"-j        Don't stretch or rotate raw pixels\n"
+"-W        Don't automatically brighten the image\n"
+"-b <num>  Adjust brightness (default = 1.0)\n"
+"-q [0-3]  Set the interpolation quality\n"
+"-h        Half-size color image (twice as fast as \"-q 0\")\n"
+"-f        Interpolate RGGB as four colors\n"
+"-m <num>  Apply a 3x3 median filter to R-G and B-G\n"
+"-s [0..N-1] Select one raw image from input file\n"
+"-4        Linear 16-bit, same as \"-6 -W -g 1 1\""
+"-6        Write 16-bit linear instead of 8-bit with gamma\n"
+"-g pow ts Set gamma curve to gamma pow and toe slope ts (default = 2.222 4.5)\n"
+"-T        Write TIFF instead of PPM\n"
+#ifndef WIN32
+"-B        Use mmap()-ed buffer instead of plain FILE I/O\n"
+#endif
+        );
+    exit(1);
+}
+
+static int verbosity=0;
+
+int cnt=0;
+int my_progress_callback(void *d,enum LibRaw_progress p,int iteration, int expected)
+{
+    char *passed  = (char*)(d?d:"default string"); // data passed to callback at set_callback stage
+
+    if(verbosity>2) // verbosity set by repeat -v switches
+        {
+            printf("CB: %s  pass %d of %d (data passed=%s)\n",libraw_strprogress(p),iteration,expected,passed);
+        }
+    else if (iteration == 0) // 1st iteration of each step
+        printf("Starting %s (expecting %d iterations)\n", libraw_strprogress(p),expected);
+    else if (iteration == expected-1)
+        printf("%s finished\n",libraw_strprogress(p));
+
+///    if(++cnt>10) return 1; // emulate user termination on 10-th callback call
+
+    return 0; // always return 0 to continue processing
+}
+
+
+int main(int argc, char *argv[])
+{
+    if(argc==1) usage(argv[0]);
+
+    LibRaw RawProcessor;
+    int i,arg,c,ret;
+    char opm,opt,*cp,*sp;
+    int use_mmap=0, msize;
+    void *iobuffer;
+
+#define OUT RawProcessor.imgdata.params
+    
+  argv[argc] = (char*)"";
+  for (arg=1; (((opm = argv[arg][0]) - 2) | 2) == '+'; ) 
+      {
+          opt = argv[arg++][1];
+          if ((cp = strchr (sp=(char*)"nbrkStqmHACgU", opt)))
+              for (i=0; i < "11411111142"[cp-sp]-'0'; i++)
+                  if (!isdigit(argv[arg+i][0])) 
+                      {
+                          fprintf (stderr,"Non-numeric argument to \"-%c\"\n", opt);
+                          return 1;
+                      }
+          switch (opt) 
+              {
+              case 'v':  verbosity++;  break;
+                  
+              case 'U':  OUT.auto_bright_thr   = atof(argv[arg++]);  break;
+              case 'n':  OUT.threshold   = atof(argv[arg++]);  break;
+              case 'b':  OUT.bright      = atof(argv[arg++]);  break;
+              case 'P':  OUT.bad_pixels  = argv[arg++];        break;
+              case 'K':  OUT.dark_frame  = argv[arg++];        break;
+              case 'r':
+                  for(c=0;c<4;c++) 
+                      OUT.user_mul[c] = atof(argv[arg++]);  
+                  break;
+              case 'C':  
+                  OUT.aber[0] = 1 / atof(argv[arg++]);
+                  OUT.aber[2] = 1 / atof(argv[arg++]);  
+                  break;
+              case 'g':  
+                  OUT.gamm[0] = 1 / atof(argv[arg++]);
+                  OUT.gamm[1] =     atof(argv[arg++]);  
+                  break;
+              case 'k':  OUT.user_black  = atoi(argv[arg++]);  break;
+              case 'S':  OUT.user_sat    = atoi(argv[arg++]);  break;
+              case 't':  OUT.user_flip   = atoi(argv[arg++]);  break;
+              case 'q':  OUT.user_qual   = atoi(argv[arg++]);  break;
+              case 'm':  OUT.med_passes  = atoi(argv[arg++]);  break;
+              case 'H':  OUT.highlight   = atoi(argv[arg++]);  break;
+              case 's':  OUT.shot_select = abs(atoi(argv[arg++])); break;
+              case 'o':  
+                  if(isdigit(argv[arg+1][0]) && !isdigit(argv[arg+1][1]))
+                          OUT.output_color = atoi(argv[arg++]);
+#ifndef NO_LCMS
+                   else
+                         OUT.output_profile = argv[arg++];
+                  break;
+              case 'p':  OUT.camera_profile = argv[arg++];
+#endif
+                  break;
+              case 'h':  OUT.half_size         = 1;		
+                  // no break:  "-h" implies "-f" 
+              case 'f':  
+                  OUT.four_color_rgb    = 1;  
+                  break;
+              case 'A':  for(c=0; c<4;c++) OUT.greybox[c]  = atoi(argv[arg++]);
+              case 'a':  OUT.use_auto_wb       = 1;  break;
+              case 'w':  OUT.use_camera_wb     = 1;  break;
+              case 'M':  OUT.use_camera_matrix = (opm == '+');  break;
+              case 'j':  OUT.use_fuji_rotate   = 0;  break;
+              case 'W':  OUT.no_auto_bright    = 1;  break;
+              case 'T':  OUT.output_tiff       = 1;  break;
+              case '4':  OUT.gamm[0] = OUT.gamm[1] =  OUT.no_auto_bright    = 1; /* no break here! */
+              case '6':  OUT.output_bps = 16;  break;
+#ifndef WIN32
+              case 'B':  use_mmap              = 1;  break;
+#endif
+              default:
+                  fprintf (stderr,"Unknown option \"-%c\".\n", opt);
+                  return 1;
+              }
+      }
+  putenv ((char*)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
+  OUT.filtering_mode = LIBRAW_FILTERING_AUTOMATIC;
+#define P1 RawProcessor.imgdata.idata
+#define S RawProcessor.imgdata.sizes
+#define C RawProcessor.imgdata.color
+#define T RawProcessor.imgdata.thumbnail
+#define P2 RawProcessor.imgdata.other
+
+  if(verbosity>1)
+          RawProcessor.set_progress_handler(my_progress_callback,(void*)"Sample data passed");
+#ifdef _OPENMP
+  if(verbosity)
+          printf ("Using %d threads\n", omp_get_max_threads());
+#endif
+
+  for ( ; arg < argc; arg++)
+        {
+            char outfn[1024];
+
+            if(verbosity) printf("Processing file %s\n",argv[arg]);
+#ifndef WIN32
+            if(use_mmap)
+                {
+                    int file = open(argv[arg],O_RDONLY);
+                    struct stat st;
+                    if(file<0)
+                        {
+                            fprintf(stderr,"Cannot open %s: %s\n",argv[arg],strerror(errno));
+                            continue;
+                        }
+                    if(fstat(file,&st))
+                        {
+                            fprintf(stderr,"Cannot stat %s: %s\n",argv[arg],strerror(errno));
+                            close(file);
+                            continue;
+                        }
+                    int pgsz = getpagesize();
+                    msize = ((st.st_size+pgsz-1)/pgsz)*pgsz;
+                    iobuffer = mmap(NULL,msize,PROT_READ,MAP_PRIVATE,file,0);
+                    if(!iobuffer)
+                        {
+                            fprintf(stderr,"Cannot mmap %s: %s\n",argv[arg],strerror(errno));
+                            close(file);
+                            continue;
+                        }
+                    close(file);
+                    if( (ret = RawProcessor.open_buffer(iobuffer,st.st_size) != LIBRAW_SUCCESS))
+                        {
+                            fprintf(stderr,"Cannot open_buffer %s: %s\n",argv[arg],libraw_strerror(ret));
+                            continue; // no recycle b/c open file will recycle itself
+                        }
+
+                }
+            else
+#endif
+                {
+                    if( (ret = RawProcessor.open_file(argv[arg])) != LIBRAW_SUCCESS)
+                        {
+                            fprintf(stderr,"Cannot open %s: %s\n",argv[arg],libraw_strerror(ret));
+                            continue; // no recycle b/c open_file will recycle itself
+                        }
+                }
+            if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS)
+                {
+                    fprintf(stderr,"Cannot unpack %s: %s\n",argv[arg],libraw_strerror(ret));
+                    continue;
+                }
+            if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_process()))
+                {
+                    fprintf(stderr,"Cannot do postpocessing on %s: %s\n",argv[arg],libraw_strerror(ret));
+                    if(LIBRAW_FATAL_ERROR(ret))
+                        continue; 
+                }
+            snprintf(outfn,sizeof(outfn),
+                     "%s.%s",
+                     argv[arg], OUT.output_tiff ? "tiff" : (P1.colors>1?"ppm":"pgm"));
+
+            if(verbosity) printf("Writing file %s\n",outfn);
+
+            if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
+                fprintf(stderr,"Cannot write %s: %s\n",outfn,libraw_strerror(ret));
+
+#ifndef WIN32
+            if(use_mmap && iobuffer)
+                {
+                    munmap(iobuffer,msize);
+                    iobuffer=0;
+                }
+#endif
+            
+            RawProcessor.recycle(); // just for show this call
+        }
+    return 0;
+}
diff --git a/libfspotraw/LibRaw/samples/dcraw_half.c b/libfspotraw/LibRaw/samples/dcraw_half.c
new file mode 100644
index 0000000..76f32c6
--- /dev/null
+++ b/libfspotraw/LibRaw/samples/dcraw_half.c
@@ -0,0 +1,83 @@
+/* -*- C++ -*-
+ * File: dcraw_half.c
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw  C API sample:  emulates "dcraw  -h"
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "libraw/libraw.h"
+
+
+#define HANDLE_FATAL_ERROR(ret)\
+    if(ret)\
+        {\
+            fprintf(stderr,"%s: libraw  %s\n",av[i],libraw_strerror(ret));\
+            if(LIBRAW_FATAL_ERROR(ret))\
+                exit(1);               \
+        }\
+
+#define HANDLE_ALL_ERRORS(ret)\
+    if(ret)\
+        {\
+            fprintf(stderr,"%s: libraw  %s\n",av[i],libraw_strerror(ret));\
+            continue;                                                   \
+        }\
+
+
+int main(int ac, char *av[])
+{
+    int i;
+    libraw_data_t *iprc = libraw_init(0);
+    
+    if(!iprc)
+        {
+            fprintf(stderr,"Cannot create libraw handle\n");
+            exit(1);
+        }
+
+    iprc->params.half_size = 1; /* dcraw -h */
+	
+    for (i=1;i<ac;i++)
+        {
+            char outfn[1024];
+			int ret = libraw_open_file(iprc,av[i]);
+            HANDLE_ALL_ERRORS(ret);
+            
+            printf("Processing %s (%s %s)\n",av[i],iprc->idata.make,iprc->idata.model);
+
+            ret = libraw_unpack(iprc);
+            HANDLE_ALL_ERRORS(ret);
+
+            ret = libraw_dcraw_process(iprc);
+            HANDLE_ALL_ERRORS(ret);
+            
+            strcpy(outfn,av[i]);
+            strcat(outfn,".ppm");
+            printf("Writing to %s\n",outfn);
+
+            ret = libraw_dcraw_ppm_tiff_writer(iprc,outfn);
+            HANDLE_FATAL_ERROR(ret);
+        }
+    libraw_close(iprc);
+    return 0;
+}
diff --git a/libfspotraw/LibRaw/samples/half_mt.c b/libfspotraw/LibRaw/samples/half_mt.c
new file mode 100644
index 0000000..05afe6f
--- /dev/null
+++ b/libfspotraw/LibRaw/samples/half_mt.c
@@ -0,0 +1,173 @@
+/* -*- C++ -*-
+ * File: halt_mt.c
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw  C API mutithreaded sample: emulates call to "dcraw  -h [-w] [-a] [-v]"
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <pthread.h>
+
+#include "libraw/libraw.h"
+
+#define HANDLE_ERRORS(ret) do {                                 \
+    if(ret)                                                     \
+        {                                                       \
+            fprintf(stderr,"%s: %s\n",fn,libraw_strerror(ret)); \
+            if(LIBRAW_FATAL_ERROR(ret))                         \
+                {                                               \
+                    libraw_close(iprc);                         \
+                    return NULL ;                               \
+                }                                               \
+        }                                                       \
+    }while(0)
+
+
+int verbose=0,use_camera_wb=0,use_auto_wb=0,tiff_mode=0;
+
+pthread_mutex_t qm;
+char **queue=NULL;
+size_t qsize=0,qptr=0;
+
+char *get_next_file()
+{
+    char *ret;
+    if(!queue) return NULL;
+    if(qptr>=qsize) return NULL;
+    pthread_mutex_lock(&qm);
+    ret = queue[qptr++];
+    pthread_mutex_unlock(&qm);
+    return ret;
+}
+
+
+void * process_files(void *q)
+{
+    int ret;
+    int count=0;
+    char outfn[1024], *fn;
+    libraw_data_t *iprc = libraw_init(0);
+
+    if(!iprc)
+        {
+            fprintf(stderr,"Cannot create libraw handle\n");
+            return NULL ;
+        }
+
+    while((fn = get_next_file()))
+        {
+
+            iprc->params.half_size = 1; /* dcraw -h */
+            iprc->params.use_camera_wb = use_camera_wb;
+            iprc->params.use_auto_wb = use_auto_wb;
+            iprc->params.output_tiff = tiff_mode;
+            
+            ret = libraw_open_file(iprc,fn);
+            if(verbose) fprintf(stderr,"%s: %s/%s\n",fn,iprc->idata.make,iprc->idata.model);
+            HANDLE_ERRORS(ret);
+
+            ret = libraw_unpack(iprc);
+            HANDLE_ERRORS(ret);
+            
+            ret = libraw_dcraw_process(iprc);
+            HANDLE_ERRORS(ret);
+            
+            snprintf(outfn,1023,"%s.ppm",fn);
+
+            if(verbose) fprintf(stderr,"Writing file %s\n",outfn);
+            ret = libraw_dcraw_ppm_tiff_writer(iprc,outfn);
+            HANDLE_ERRORS(ret);
+            count++;
+        }
+    libraw_close(iprc);
+    return NULL;
+}
+
+void usage(const char*p)
+{
+    printf("%s: Multi-threaded LibRaw sample app. Emulates dcraw -h [-w] [-a]\n",p);
+    printf(
+        "Options:\n"
+        "-J n  - set parrallel job coun (default 2)\n"
+        "-v    - verbose\n"
+        "-w    - use camera white balance\n"
+        "-a    - average image for white balance\n");
+    exit(1);
+}
+
+int show_files(void *q)
+{
+    char *p;
+    int cnt = 0;
+    while((p = get_next_file()))
+        {
+            printf("%s\n",p);
+            cnt++;
+        }
+    return cnt;
+
+}
+
+int main(int ac, char *av[])
+{
+    int i, max_threads = 2;
+    pthread_t *threads;
+    if(ac<2)
+        usage(av[0]);
+
+    queue = calloc(ac-1,sizeof(queue[0]));
+
+    for (i=1;i<ac;i++)
+        {
+            if(av[i][0]=='-')
+                {
+                    if(av[i][1]=='w') use_camera_wb = 1;
+                    if(av[i][1]=='a') use_auto_wb = 1;
+                    if(av[i][1]=='v') verbose = 1;
+                    if(av[i][1]=='T') tiff_mode = 1;
+                    if(av[i][1]=='J')
+                        {
+                            max_threads=atoi(av[++i]);
+                            if(max_threads<1)
+                                {
+                                    fprintf(stderr,"Job count should be at least 1\n");
+                                    exit(1);
+                                }
+                        }
+                }
+            else
+                queue[qsize++] = av[i];
+        }
+    pthread_mutex_init(&qm,NULL);
+    threads = calloc(max_threads,sizeof(threads[0]));
+    for(i=0;i<max_threads;i++)
+        pthread_create(&threads[i],NULL,process_files,NULL);
+    for(i=0;i<max_threads;i++)
+        {
+            int *iptr;
+            if(threads[i])
+                {
+                    pthread_join(threads[i],(void*)&iptr);
+                }
+        }
+            
+    return 0;
+}
diff --git a/libfspotraw/LibRaw/samples/half_mt_win32.c b/libfspotraw/LibRaw/samples/half_mt_win32.c
new file mode 100644
index 0000000..d10e014
--- /dev/null
+++ b/libfspotraw/LibRaw/samples/half_mt_win32.c
@@ -0,0 +1,212 @@
+/* -*- C++ -*-
+ * File: halt_mt_win32.c
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw  C API mutithreaded sample:  emulates call to "dcraw  -h [-w] [-a] [-v]"
+ * Win32 version
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <windows.h>
+#include "libraw/libraw.h"
+
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
+
+
+#define HANDLE_ERRORS(ret) do {                                 \
+    if(ret)                                                     \
+        {                                                       \
+            fprintf(stderr,"%s: %s\n",fn,libraw_strerror(ret)); \
+            if(LIBRAW_FATAL_ERROR(ret))                         \
+                {                                               \
+                    libraw_close(iprc);                         \
+                    return -1;                                   \
+                }                                               \
+        }                                                       \
+    }while(0)
+
+
+// global settings
+int verbose=0,use_camera_wb=0,use_auto_wb=0,tiff_mode=0;
+
+// global file queue
+HANDLE qmutex;
+char **queue=NULL;
+size_t qsize=0,qptr=0;
+
+char *get_next_file()
+{
+    char *ret;
+	DWORD dwWaitResult;
+    if(!queue) return NULL;
+    if(qptr>=qsize) return NULL;
+
+	dwWaitResult = WaitForSingleObject( 
+            qmutex,    // handle to mutex
+            INFINITE);  // no time-out interval
+	switch (dwWaitResult) 
+        {
+            // The thread got ownership of the mutex
+            case WAIT_OBJECT_0:     
+				ret = queue[qptr++];
+				ReleaseMutex(qmutex);
+				break;
+			case WAIT_ABANDONED: 
+                return NULL; // cannot obtain the lock
+	};
+    return ret;
+}
+
+
+// thread routine
+int process_files(void *q)
+{
+    int ret;
+    int count=0;
+    char outfn[1024], *fn;
+    libraw_data_t *iprc = libraw_init(0);
+
+    if(!iprc)
+        {
+            fprintf(stderr,"Cannot create libraw handle\n");
+            return -1;
+        }
+
+    while((fn = get_next_file()))
+        {
+
+            iprc->params.half_size = 1; /* dcraw -h */
+            iprc->params.use_camera_wb = use_camera_wb;
+            iprc->params.use_auto_wb = use_auto_wb;
+            iprc->params.output_tiff = tiff_mode;
+            
+            ret = libraw_open_file(iprc,fn);
+            if(verbose) fprintf(stderr,"%s: %s/%s\n",fn,iprc->idata.make,iprc->idata.model);
+            HANDLE_ERRORS(ret);
+
+            ret = libraw_unpack(iprc);
+            HANDLE_ERRORS(ret);
+            
+            ret = libraw_dcraw_process(iprc);
+            HANDLE_ERRORS(ret);
+            
+            snprintf(outfn,1023,"%s.%s",fn,tiff_mode?"tif":"ppm");
+
+            if(verbose) fprintf(stderr,"Writing file %s\n",outfn);
+            ret = libraw_dcraw_ppm_tiff_writer(iprc,outfn);
+            HANDLE_ERRORS(ret);
+            count++;
+        }
+    libraw_close(iprc);
+	printf("Processed %d files\n",count);
+    return 0;
+}
+
+void usage(const char*p)
+{
+    printf(
+        "Options:\n"
+        "-J n  - set parrallel job coun (default 2)\n"
+        "-v    - verbose\n"
+        "-w    - use camera white balance\n"
+        "-T    - output TIFF instead of PPM\n"
+        "-a    - average image for white balance\n");
+    exit(1);
+}
+
+int show_files(void *q)
+{
+    char *p;
+    int cnt = 0;
+    while(p = get_next_file())
+        {
+            printf("%s\n",p);
+            cnt++;
+        }
+    return cnt;
+
+}
+
+int main(int ac, char *av[])
+{
+    int i,max_threads = 2;
+    HANDLE *threads;
+	DWORD   ThreadID;
+
+    if(ac<2)
+        usage(av[0]);
+
+    queue = calloc(ac-1,sizeof(queue[0]));
+
+    for (i=1;i<ac;i++)
+        {
+            if(av[i][0]=='-')
+                {
+                    if(av[i][1]=='w') use_camera_wb = 1;
+                    if(av[i][1]=='a') use_auto_wb = 1;
+                    if(av[i][1]=='v') verbose = 1;
+                    if(av[i][1]=='T') tiff_mode = 1;
+                    if(av[i][1]=='J')
+                        {
+                            max_threads=atoi(av[++i]);
+                            if(max_threads<1)
+                                {
+                                    fprintf(stderr,"Job count should be at least 1\n");
+                                    exit(1);
+                                }
+                        }
+                }
+            else
+                queue[qsize++] = av[i];
+        }
+    qmutex = CreateMutex(NULL,FALSE,NULL);	
+    threads = calloc(max_threads,sizeof(threads[0]));
+    for(i=0;i<max_threads;i++)
+	{
+
+		if (NULL == (threads[i] = CreateThread( 
+                     NULL,       // default security attributes
+                     0,          // default stack size
+                     (LPTHREAD_START_ROUTINE) process_files, 
+                     NULL,       // no thread function arguments
+                     0,          // default creation flags
+                     &ThreadID) // receive thread identifier
+					 )
+			)
+        {
+            printf("CreateThread error: %d\n", GetLastError());
+            return 1;
+        }
+	}
+        
+	WaitForMultipleObjects(max_threads, threads, TRUE, INFINITE);
+
+    // Close thread and mutex handles
+
+    for( i=0; i < max_threads; i++ )
+        CloseHandle(threads[i]);
+
+    CloseHandle(qmutex);
+           
+    return 0;
+}
diff --git a/libfspotraw/LibRaw/samples/mem_image.cpp b/libfspotraw/LibRaw/samples/mem_image.cpp
new file mode 100644
index 0000000..4ade460
--- /dev/null
+++ b/libfspotraw/LibRaw/samples/mem_image.cpp
@@ -0,0 +1,199 @@
+/* -*- C++ -*-
+ * File: mem_image.cpp
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw mem_image/mem_thumb API test. Results should be same (bitwise) to dcraw [-4] [-6] [-e]
+ * Testing note: for ppm-thumbnails you should use dcraw -w -e for thumbnail extraction
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "libraw/libraw.h"
+
+#ifdef WIN32
+#define snprintf _snprintf
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+#else
+#include <netinet/in.h>
+#endif
+
+
+// no error reporting, only params check
+void write_ppm(libraw_processed_image_t *img, const char *basename)
+{
+    if(!img) return;
+    // type SHOULD be LIBRAW_IMAGE_BITMAP, but we'll check
+    if(img->type != LIBRAW_IMAGE_BITMAP) return;
+    // only 3-color images supported...
+    if(img->colors != 3) return;
+
+    char fn[1024];
+    snprintf(fn,1024,"%s.ppm",basename);
+    FILE *f = fopen(fn,"wb");
+    if(!f) return;
+    fprintf (f, "P6\n%d %d\n%d\n", img->width, img->height, (1 << img->bits)-1);
+/*
+  NOTE:
+  data in img->data is not converted to network byte order.
+  So, we should swap values on some architectures for dcraw compatibility
+  (unfortunately, xv cannot display 16-bit PPMs with network byte order data
+*/
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+    if (img->bits == 16 && htons(0x55aa) != 0x55aa)
+        for(unsigned i=0; i< img->data_size; i+=2)
+            SWAP(img->data[i],img->data[i+1]);
+#undef SWAP
+
+    fwrite(img->data,img->data_size,1,f);
+    fclose(f);
+}
+
+void write_thumb(libraw_processed_image_t *img, const char *basename)
+{
+    if(!img) return;
+
+    if(img->type == LIBRAW_IMAGE_BITMAP)
+        {
+            char fnt[1024];
+            snprintf(fnt,1024,"%s.thumb",basename);
+            write_ppm(img,fnt);
+        }
+    else if (img->type == LIBRAW_IMAGE_JPEG)
+        {
+            char fn[1024];
+            snprintf(fn,1024,"%s.thumb.jpg",basename);
+            FILE *f = fopen(fn,"wb");
+            if(!f) return;
+            fwrite(img->data,img->data_size,1,f);
+            fclose(f);
+        }
+}
+
+
+
+int main(int ac, char *av[])
+{
+    int  i, ret, output_thumbs=0;
+
+    // don't use fixed size buffers in real apps!
+
+    LibRaw RawProcessor;
+    
+    if(ac<2) 
+        {
+            printf(
+                "mem_image - LibRaw sample, to illustrate work for memory buffers. Emulates dcraw [-4] [-1] [-e]\n"
+                "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n"
+                "\t-6 - output 16-bit PPM\n"
+                "\t-4 - linear 16-bit data\n"
+                "\t-e - extract thumbnails (same as dcraw -e in separate run)\n",
+                av[0]);
+            return 0;
+        }
+
+    putenv ((char*)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
+    
+#define P1 RawProcessor.imgdata.idata
+#define S RawProcessor.imgdata.sizes
+#define C RawProcessor.imgdata.color
+#define T RawProcessor.imgdata.thumbnail
+#define P2 RawProcessor.imgdata.other
+#define OUT RawProcessor.imgdata.params
+
+
+    for (i=1;i<ac;i++)
+        {
+            if(av[i][0]=='-')
+                {
+                    if(av[i][1]=='6' && av[i][2]==0)
+                        OUT.output_bps = 16;
+                    if(av[i][1]=='4' && av[i][2]==0)
+                        {
+                            OUT.output_bps = 16;
+                            OUT.gamm[0] = OUT.gamm[1] =  OUT.no_auto_bright    = 1;
+                        }
+                    if(av[i][1]=='e' && av[i][2]==0)
+                        output_thumbs++;
+                    continue;
+                }
+            printf("Processing %s\n",av[i]);
+            if( (ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
+                {
+                    fprintf(stderr,"Cannot open %s: %s\n",av[i],libraw_strerror(ret));
+                    continue; // no recycle b/c open file will recycle itself
+                }
+            
+            if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS)
+                {
+                    fprintf(stderr,"Cannot unpack %s: %s\n",av[i],libraw_strerror(ret));
+                    continue;
+                }
+
+            // we should call dcraw_process before thumbnail extraction because for
+            // some cameras (i.e. Kodak ones) white balance for thumbnal should be set
+            // from main image settings
+
+
+            ret = RawProcessor.dcraw_process();
+                
+            if(LIBRAW_SUCCESS !=ret)
+                {
+                    fprintf(stderr,"Cannot do postpocessing on %s: %s\n",
+                            av[i],libraw_strerror(ret));
+                    if(LIBRAW_FATAL_ERROR(ret))
+                        continue; 
+                }
+            libraw_processed_image_t *image = RawProcessor.dcraw_make_mem_image(&ret);
+            if(image)
+                {
+                    write_ppm(image,av[i]);
+                    free(image);
+                }
+            else
+                fprintf(stderr,"Cannot unpack %s to memory buffer: %s\n" , av[i],libraw_strerror(ret));
+
+            if(output_thumbs)
+                {
+
+                    if( (ret = RawProcessor.unpack_thumb() ) != LIBRAW_SUCCESS)
+                        {
+                            fprintf(stderr,"Cannot unpack_thumb %s: %s\n",av[i],libraw_strerror(ret));
+                            if(LIBRAW_FATAL_ERROR(ret))
+                                continue; // skip to next file
+                        }
+                    else
+                        {
+                            libraw_processed_image_t *thumb = RawProcessor.dcraw_make_mem_thumb(&ret);
+                            if(thumb)
+                                {
+                                    write_thumb(thumb,av[i]);
+                                    free(thumb);
+                                }
+                            else
+                                fprintf(stderr,"Cannot unpack thumbnail of %s to memory buffer: %s\n" , av[i],libraw_strerror(ret));
+                        }
+
+                }
+                    
+            RawProcessor.recycle(); // just for show this call
+        }
+    return 0;
+}
diff --git a/libfspotraw/LibRaw/samples/raw-identify.cpp b/libfspotraw/LibRaw/samples/raw-identify.cpp
new file mode 100644
index 0000000..124f40c
--- /dev/null
+++ b/libfspotraw/LibRaw/samples/raw-identify.cpp
@@ -0,0 +1,147 @@
+/* -*- C++ -*-
+ * File: identify.cpp
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw C++ demo: emulates dcraw -i [-v]
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#include "libraw/libraw.h"
+
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
+
+
+int main(int ac, char *av[])
+{
+    int verbose = 0, ret,print_unpack=0,print_frame=0;
+    LibRaw MyCoolRawProcessor;
+
+    for (int i=1;i<ac;i++) {
+        if(av[i][0]=='-')
+            {
+                if(av[i][1]=='v' && av[i][2]==0) verbose++;
+                if(av[i][1]=='u' && av[i][2]==0) print_unpack++;
+                if(av[i][1]=='f' && av[i][2]==0) print_frame++;
+                continue;
+            }
+        if( (ret = MyCoolRawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
+            {
+                printf("Cannot decode %s: %s\n",av[i],libraw_strerror(ret));
+                continue; // no recycle, open_file will recycle
+            }
+        if(verbose) {
+
+#define P1 MyCoolRawProcessor.imgdata.idata
+#define P2 MyCoolRawProcessor.imgdata.other
+
+#define S MyCoolRawProcessor.imgdata.sizes
+#define O MyCoolRawProcessor.imgdata.params
+#define C MyCoolRawProcessor.imgdata.color
+#define T MyCoolRawProcessor.imgdata.thumbnail
+
+
+            if( (ret =  MyCoolRawProcessor.adjust_sizes_info_only()))
+            {
+                printf("Cannot decode %s: %s\n",av[i],libraw_strerror(ret));
+                continue; // no recycle, open_file will recycle
+            }
+            
+            printf ("\nFilename: %s\n", av[i]);
+            printf ("Timestamp: %s", ctime(&(P2.timestamp)));
+            printf ("Camera: %s %s\n", P1.make, P1.model);
+            if (P2.artist[0])
+                printf ("Owner: %s\n", P2.artist);
+            if (P1.dng_version) {
+                printf ("DNG Version: ");
+                for (int i=24; i >= 0; i -= 8)
+                    printf ("%d%c", P1.dng_version >> i & 255, i ? '.':'\n');
+            }
+            printf ("ISO speed: %d\n", (int) P2.iso_speed);
+            printf ("Shutter: ");
+            if (P2.shutter > 0 && P2.shutter < 1)
+                P2.shutter = (printf ("1/"), 1 / P2.shutter);
+            printf ("%0.1f sec\n", P2.shutter);
+            printf ("Aperture: f/%0.1f\n", P2.aperture);
+            printf ("Focal length: %0.1f mm\n", P2.focal_len);
+            if(C.profile)
+                printf ("Embedded ICC profile: yes, %d bytes\n", C.profile_length);
+            else
+                printf ("Embedded ICC profile: no\n");
+                
+            printf ("Number of raw images: %d\n", P1.raw_count);
+            if (S.pixel_aspect != 1)
+                printf ("Pixel Aspect Ratio: %0.6f\n", S.pixel_aspect);
+            if (T.tlength)
+                printf ("Thumb size:  %4d x %d\n", T.twidth, T.theight);
+            printf ("Full size:   %4d x %d\n", S.raw_width, S.raw_height);
+            
+            printf ("Image size:  %4d x %d\n", S.width, S.height);
+            printf ("Output size: %4d x %d\n", S.iwidth, S.iheight);
+            printf ("Raw colors: %d", P1.colors);
+            if (P1.filters) 
+                {
+                    printf ("\nFilter pattern: ");
+                    if (!P1.cdesc[3]) P1.cdesc[3] = 'G';
+                    for (int i=0; i < 16; i++)
+                        putchar (P1.cdesc[MyCoolRawProcessor.fc(i >> 1,i & 1)]);
+                }
+            printf ("\nDaylight multipliers:");
+            for(int c=0;c<P1.colors;c++) printf (" %f", C.pre_mul[c]);
+            if (C.cam_mul[0] > 0) 
+                {
+                    printf ("\nCamera multipliers:");
+                    for(int c=0;c<4;c++) printf (" %f", C.cam_mul[c]);
+                }
+            const char *csl[] = {"U","I","CO","L","CA"};
+            printf("\nColor sources /Legend: (U)nknown, (I)nit, (CO)nstant, (L)oaded, (CA)lculated/:\n");
+            printf("\tcurve=%s; rgb_cam=%s; cmatrix=%s, pre_mul=%s, cam_mul=%s",
+                   csl[C.color_flags.curve_state],csl[C.color_flags.rgb_cam_state],
+                   csl[C.color_flags.cmatrix_state],csl[C.color_flags.pre_mul_state],
+                   csl[C.color_flags.cam_mul_state]);
+            putchar ('\n');
+            printf("Cam->XYZ matrix:\n");
+            for(int i=0; i< 4; i++)
+                printf("%6.4f\t%6.4f\t%6.4f\n",C.cam_xyz[i][0],C.cam_xyz[i][1],C.cam_xyz[i][2]);
+        }
+        else 
+            {
+                if(print_unpack)
+                    {
+                        char frame[32]="";
+                        if(print_frame)
+                            snprintf(frame,32,"%dx%dx%dx%d",S.left_margin,S.top_margin,S.right_margin,S.bottom_margin);
+                        printf ("%s\t%s\t%s\t%s/%s\n", 
+                                av[i],
+                                MyCoolRawProcessor.unpack_function_name(),
+                                frame,
+                                P1.make, P1.model);
+                    }
+                else
+                    printf ("%s is a %s %s image.\n", av[i],P1.make, P1.model);
+            }
+        MyCoolRawProcessor.recycle();
+    }// endfor
+    return 0;
+}
diff --git a/libfspotraw/LibRaw/samples/simple_dcraw.cpp b/libfspotraw/LibRaw/samples/simple_dcraw.cpp
new file mode 100644
index 0000000..6f69b31
--- /dev/null
+++ b/libfspotraw/LibRaw/samples/simple_dcraw.cpp
@@ -0,0 +1,213 @@
+/* -*- C++ -*-
+ * File: simple_dcraw.cpp
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw simple C++ API:  emulates call to "dcraw  [-D]  [-T] [-v] [-e] [-4]"
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#endif
+
+#include "libraw/libraw.h"
+
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
+
+int my_progress_callback(void *unused_data,enum LibRaw_progress state,int iter, int expected)
+{
+    if(iter==0)
+        printf("CB: state=%x, expected %d iterations\n",state,expected);
+    return 0;
+}
+
+
+int main(int ac, char *av[])
+{
+    int  i, ret, verbose=0, output_thumbs=0,use_mmap=0,msize;
+    void *file_buffer;
+
+    // don't use fixed size buffers in real apps!
+    char outfn[1024],thumbfn[1024]; 
+
+    LibRaw RawProcessor;
+    if(ac<2) 
+        {
+            printf(
+                "simple_dcraw - LibRaw %s sample. Emulates dcraw [-D] [-T] [-v] [-e] [-B]\n"
+                " %d cameras supported\n"
+                "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n"
+                "\t-D - document mode emulation\n"
+                "\t-4 - 16-bit mode\n"
+                "\t-v - verbose output\n"
+                "\t-T - output TIFF files instead of .pgm/ppm\n"
+#ifndef WIN32
+                "\t-B - use mmap()-ed I/O (Unix only)\n"
+#endif
+                "\t-e - extract thumbnails (same as dcraw -e in separate run)\n",LibRaw::version(),
+                LibRaw::cameraCount(),
+                av[0]);
+            return 0;
+        }
+    
+    putenv ((char*)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
+
+#define P1 RawProcessor.imgdata.idata
+#define S RawProcessor.imgdata.sizes
+#define C RawProcessor.imgdata.color
+#define T RawProcessor.imgdata.thumbnail
+#define P2 RawProcessor.imgdata.other
+#define OUT RawProcessor.imgdata.params
+
+
+    for (i=1;i<ac;i++)
+        {
+            if(av[i][0]=='-')
+                {
+                    if(av[i][1]=='T' && av[i][2]==0)
+                        OUT.output_tiff=1;
+                    if(av[i][1]=='v' && av[i][2]==0)
+                        verbose++;
+                    if(av[i][1]=='e' && av[i][2]==0)
+                        output_thumbs++;
+                    if(av[i][1]=='D' && av[i][2]==0)
+                        OUT.document_mode=2;
+                    if(av[i][1]=='B' && av[i][2]==0)
+                        use_mmap=1;
+                    if(av[i][1]=='4' && av[i][2]==0)
+                        OUT.output_bps=16;
+                    if(av[i][1]=='C' && av[i][2]==0)
+                        RawProcessor.set_progress_handler(my_progress_callback,NULL);
+                    continue;
+                }
+
+            if(verbose) printf("Processing file %s\n",av[i]);
+
+#ifndef WIN32
+            if(use_mmap)
+                {
+                    int file = open(av[i],O_RDONLY);
+                    struct stat st;
+                    if(file<0)
+                        {
+                            fprintf(stderr,"Cannot open %s: %s\n",av[i],strerror(errno));
+                            continue;
+                        }
+                    if(fstat(file,&st))
+                        {
+                            fprintf(stderr,"Cannot stat %s: %s\n",av[i],strerror(errno));
+                            close(file);
+                            continue;
+                        }
+                    int pgsz = getpagesize();
+                    msize = ((st.st_size+pgsz-1)/pgsz)*pgsz;
+                    file_buffer = mmap(NULL,msize,PROT_READ,MAP_PRIVATE,file,0);
+                    if(!file_buffer)
+                        {
+                            fprintf(stderr,"Cannot mmap %s: %s\n",av[i],strerror(errno));
+                            close(file);
+                            continue;
+                        }
+                    close(file);
+                    if( (ret = RawProcessor.open_buffer(file_buffer,st.st_size) != LIBRAW_SUCCESS))
+                        {
+                            fprintf(stderr,"Cannot open_buffer %s: %s\n",av[i],libraw_strerror(ret));
+                            continue; // no recycle b/c open file will recycle itself
+                        }
+                }
+            else
+#endif
+                {
+                    if( (ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
+                        {
+                            fprintf(stderr,"Cannot open_file %s: %s\n",av[i],libraw_strerror(ret));
+                            continue; // no recycle b/c open file will recycle itself
+                        }
+                }
+
+            if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS)
+                {
+                    fprintf(stderr,"Cannot unpack %s: %s\n",av[i],libraw_strerror(ret));
+                    continue;
+                }
+
+            // thumbnail unpacking and output in the middle of main
+            // image processing - for test purposes!
+            if(output_thumbs)
+                {
+                    if( (ret = RawProcessor.unpack_thumb() ) != LIBRAW_SUCCESS)
+                        {
+                            fprintf(stderr,"Cannot unpack_thumb %s: %s\n",av[i],libraw_strerror(ret));
+                            if(LIBRAW_FATAL_ERROR(ret))
+                                continue; // skip to next file
+                        }
+                    else
+                        {
+                            snprintf(thumbfn,sizeof(thumbfn),"%s.%s",
+                                     av[i],T.tformat == LIBRAW_THUMBNAIL_JPEG ? "thumb.jpg" : "thumb.ppm");
+
+                            if(verbose) printf("Writing thumbnail file %s\n",thumbfn);
+                            if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_thumb_writer(thumbfn)))
+                                {
+                                    fprintf(stderr,"Cannot write %s: %s\n",thumbfn,libraw_strerror(ret));
+                                    if(LIBRAW_FATAL_ERROR(ret))
+                                        continue; 
+                                }
+                        }
+                }
+            
+            if(OUT.document_mode)
+                ret = RawProcessor.dcraw_document_mode_processing();
+            else
+                ret = RawProcessor.dcraw_process();
+                
+            if(LIBRAW_SUCCESS !=ret)
+                {
+                    fprintf(stderr,"Cannot do postpocessing on %s: %s\n",
+                            av[i],libraw_strerror(ret));
+                    if(LIBRAW_FATAL_ERROR(ret))
+                        continue; 
+                }
+            snprintf(outfn,sizeof(outfn),
+                     "%s.%s",
+                     av[i], OUT.output_tiff ? "tiff" : (P1.colors>1?"ppm":"pgm"));
+
+            if(verbose) printf("Writing file %s\n",outfn);
+
+            if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
+                fprintf(stderr,"Cannot write %s: %s\n",outfn,libraw_strerror(ret));
+
+#ifndef WIN32            
+            if(use_mmap && file_buffer)
+                {
+                    munmap(file_buffer,msize);
+                    file_buffer=0;
+                }
+#endif
+            RawProcessor.recycle(); // just for show this call
+        }
+    return 0;
+}
diff --git a/libfspotraw/LibRaw/samples/unprocessed_raw.cpp b/libfspotraw/LibRaw/samples/unprocessed_raw.cpp
new file mode 100644
index 0000000..8dc7ceb
--- /dev/null
+++ b/libfspotraw/LibRaw/samples/unprocessed_raw.cpp
@@ -0,0 +1,158 @@
+/* -*- C++ -*-
+ * File: unprocessed_raw.cpp
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Fri Jan 02, 2009
+ *
+ * LibRaw sample
+ * Generates unprocessed raw image: with masked pixels and without black subtraction
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#ifndef WIN32
+#include <netinet/in.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include "libraw/libraw.h"
+
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
+
+int main(int ac, char *av[])
+{
+    int  i, ret;
+    int verbose=1,autoscale=0,use_gamma=0;
+    char outfn[1024]; 
+
+    LibRaw RawProcessor;
+    if(ac<2) 
+        {
+          usage:
+            printf(
+                "unprocessed_raw - LibRaw %s sample. %d cameras supported\n"
+                "Usage: %s [-q] [-A] [-g] [-s N] [-N] raw-files....\n"
+                "\t-q - be quiet\n"
+                "\t-s N - select Nth image in file (default=0)\n"
+                "\t-g - use gamma correction with gamma 2.2 (not precise,use for visual inspection only)\n"
+                "\t-A - autoscaling (by integer factor)\n"
+                "\t-N - no raw curve\n"
+                ,LibRaw::version(),
+                LibRaw::cameraCount(),
+                av[0]);
+            return 0;
+        }
+    
+#define P1 RawProcessor.imgdata.idata
+#define S RawProcessor.imgdata.sizes
+#define C RawProcessor.imgdata.color
+#define T RawProcessor.imgdata.thumbnail
+#define P2 RawProcessor.imgdata.other
+#define OUT RawProcessor.imgdata.params
+
+    OUT.document_mode=2;
+    OUT.output_bps=16;
+    OUT.output_tiff=1;
+    OUT.user_flip=0;
+    OUT.no_auto_bright = 1;
+    OUT.filtering_mode=(LibRaw_filtering)( LIBRAW_FILTERING_NOBLACKS|LIBRAW_FILTERING_NOZEROES);
+    for (i=1;i<ac;i++)
+        {
+            if(av[i][0]=='-')
+                {
+                    if(av[i][1]=='q' && av[i][2]==0)
+                        verbose=0;
+                    else if(av[i][1]=='A' && av[i][2]==0)
+                        autoscale=1;
+                    else if(av[i][1]=='g' && av[i][2]==0)
+                        use_gamma = 1;
+                    else if(av[i][1]=='N' && av[i][2]==0)
+                        OUT.filtering_mode=LIBRAW_FILTERING_NONE;
+                    else if(av[i][1]=='s' && av[i][2]==0)
+                        {
+                            i++;
+                            OUT.shot_select=atoi(av[i]);
+                        }
+                    else
+                        goto usage;
+                    continue;
+                }
+            int c;
+            if(!use_gamma)
+                OUT.gamm[0] = OUT.gamm[1] = 1;
+            if(verbose) printf("Processing file %s\n",av[i]);
+            if( (ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
+                {
+                    fprintf(stderr,"Cannot open %s: %s\n",av[i],libraw_strerror(ret));
+                    continue; // no recycle b/c open file will recycle itself
+                }
+            if(verbose)
+                {
+                    printf("Image size: %dx%d\nRaw size: %dx%d\n",S.width,S.height,S.raw_width,S.raw_height);
+                    printf("Margins: top=%d, left=%d, right=%d, bottom=%d\n",
+                           S.top_margin,S.left_margin,S.right_margin,S.bottom_margin);
+                }
+
+            if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS)
+                {
+                    fprintf(stderr,"Cannot unpack %s: %s\n",av[i],libraw_strerror(ret));
+                    continue;
+                }
+            if(verbose)
+                printf("Unpacked....\n");
+
+            if( (ret = RawProcessor.add_masked_borders_to_bitmap() ) != LIBRAW_SUCCESS)
+                {
+                    fprintf(stderr,"Cannot add mask data to bitmap %s\n",av[i]);
+                }
+            for(int r=0;r<S.iheight;r++)
+                for(c=0;c<S.iwidth;c++)
+                    RawProcessor.imgdata.image[r*S.iwidth+c][0] 
+                        = RawProcessor.imgdata.image[r*S.iwidth+c][RawProcessor.FC(r,c)];
+
+            P1.colors=1;
+            if(autoscale)
+                {
+                    unsigned max=0,scale;
+                    for(int j=0; j<S.iheight*S.iwidth; j++)
+                        if(max < RawProcessor.imgdata.image[j][0])
+                            max = RawProcessor.imgdata.image[j][0]; 
+                    if (max >0 && max< 1<<15)
+                        {
+                            scale = (1<<16)/max;
+                            if(verbose)
+                                printf("Scaling with multiplier=%d (max=%d)\n",scale,max);
+                            
+                            for(int j=0; j<S.iheight*S.iwidth; j++)
+                                RawProcessor.imgdata.image[j][0] *= scale;
+                        }
+                }
+            
+            if(OUT.shot_select)
+                snprintf(outfn,sizeof(outfn),"%s-%d.tiff",av[i],OUT.shot_select);
+            else
+                snprintf(outfn,sizeof(outfn),"%s.tiff",av[i]);
+
+            if(verbose) printf("Writing file %s\n",outfn);
+            if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
+                fprintf(stderr,"Cannot write %s: %s\n",outfn,libraw_strerror(ret));
+        }
+    return 0;
+}
diff --git a/libfspotraw/LibRaw/src/Makefile b/libfspotraw/LibRaw/src/Makefile
new file mode 100644
index 0000000..a54d1a4
--- /dev/null
+++ b/libfspotraw/LibRaw/src/Makefile
@@ -0,0 +1,2 @@
+all: 
+	(cd ..; make library)
diff --git a/libfspotraw/LibRaw/src/libraw_c_api.cpp b/libfspotraw/LibRaw/src/libraw_c_api.cpp
new file mode 100644
index 0000000..c482888
--- /dev/null
+++ b/libfspotraw/LibRaw/src/libraw_c_api.cpp
@@ -0,0 +1,143 @@
+/* -*- C++ -*-
+ * File: libraw_c_api.cpp
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw C interface 
+ */
+#include <errno.h>
+#include "libraw/libraw.h"
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+
+    libraw_data_t *libraw_init(unsigned int flags)
+    {
+        LibRaw *ret = new LibRaw(flags);
+        return &(ret->imgdata);
+    }
+
+    const char*   libraw_version() { return LibRaw::version();}
+    const char*   libraw_strprogress(enum LibRaw_progress p) { return LibRaw::strprogress(p);}
+    int     libraw_versionNumber() { return LibRaw::versionNumber();}
+    const char**  libraw_cameraList() { return LibRaw::cameraList();}
+    int   libraw_cameraCount() { return LibRaw::cameraCount(); }
+    const char* libraw_unpack_function_name(libraw_data_t* lr)
+    {
+        if(!lr) return "NULL parameter passed";
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->unpack_function_name();
+    }
+    int libraw_rotate_fuji_raw(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->rotate_fuji_raw();
+    }
+
+    int libraw_add_masked_borders_to_bitmap(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->add_masked_borders_to_bitmap();
+    }
+
+    int libraw_open_file(libraw_data_t* lr, const char *file)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->open_file(file);
+    }
+    int libraw_open_buffer(libraw_data_t* lr, void *buffer, size_t size)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->open_buffer(buffer,size);
+    }
+    int libraw_unpack(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->unpack();
+    }
+    int libraw_unpack_thumb(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->unpack_thumb();
+    }
+    void libraw_recycle(libraw_data_t* lr)
+    {
+        if(!lr) return;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        ip->recycle();
+    }
+    void libraw_close(libraw_data_t* lr)
+    {
+        if(!lr) return;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        delete ip;
+    }
+
+    void  libraw_set_memerror_handler(libraw_data_t* lr, memory_callback cb,void *data)
+    {
+        if(!lr) return;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        ip->set_memerror_handler(cb,data);
+
+    }
+    void libraw_set_dataerror_handler(libraw_data_t* lr,data_callback func,void *data)
+    {
+        if(!lr) return;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        ip->set_dataerror_handler(func,data);
+
+    }
+    void  libraw_set_progress_handler(libraw_data_t* lr, progress_callback cb,void *data)
+    {
+        if(!lr) return;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        ip->set_progress_handler(cb,data);
+
+    }
+
+    // DCRAW
+    int  libraw_adjust_sizes_info_only(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->adjust_sizes_info_only();
+    }
+
+    int  libraw_dcraw_document_mode_processing(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->dcraw_document_mode_processing();
+
+    }
+    int  libraw_dcraw_ppm_tiff_writer(libraw_data_t* lr,const char *filename)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->dcraw_ppm_tiff_writer(filename);
+    }
+    int  libraw_dcraw_thumb_writer(libraw_data_t* lr,const char *fname)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->dcraw_thumb_writer(fname);
+
+    }
+    int libraw_dcraw_process(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->dcraw_process();
+    }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libfspotraw/LibRaw/src/libraw_cxx.cpp b/libfspotraw/LibRaw/src/libraw_cxx.cpp
new file mode 100644
index 0000000..de77245
--- /dev/null
+++ b/libfspotraw/LibRaw/src/libraw_cxx.cpp
@@ -0,0 +1,1970 @@
+/* -*- C++ -*-
+ * File: libraw_cxx.cpp
+ * Copyright 2008-2009 LibRaw LLC (info libraw org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw C++ interface (implementation)
+ */
+
+#include <errno.h>
+#include <float.h>
+#include <math.h>
+#ifndef WIN32
+#include <netinet/in.h>
+#else
+#include <winsock2.h>
+#endif
+#define LIBRAW_LIBRARY_BUILD
+#include "libraw/libraw.h"
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+    void default_memory_callback(void *,const char *file,const char *where)
+    {
+        fprintf (stderr,"%s: Out of memory in %s\n", file?file:"unknown file", where);
+    }
+
+    void default_data_callback(void*,const char *file, const int offset)
+    {
+        if(offset < 0)
+            fprintf (stderr,"%s: Unexpected end of file\n", file?file:"unknown file");
+        else
+            fprintf (stderr,"%s: data corrupted at %d\n",file?file:"unknown file",offset); 
+    }
+    const char *libraw_strerror(int e)
+    {
+        enum LibRaw_errors errorcode = (LibRaw_errors)e;
+        switch(errorcode)
+            {
+            case        LIBRAW_SUCCESS:
+                return "No error";
+            case        LIBRAW_UNSPECIFIED_ERROR:
+                return "Unspecified error";
+            case        LIBRAW_FILE_UNSUPPORTED:
+                return "Unsupported file format or not RAW file";
+            case        LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE:
+                return "Request for nonexisting image number";
+            case        LIBRAW_OUT_OF_ORDER_CALL:
+                return "Out of order call of libraw function";
+            case    LIBRAW_NO_THUMBNAIL:
+                return "No thumbnail in file";
+            case    LIBRAW_UNSUPPORTED_THUMBNAIL:
+                return "Unsupported thumbnail format";
+            case LIBRAW_CANNOT_ADDMASK:
+                return "Cannot add masked pixels to resized image";
+            case    LIBRAW_UNSUFFICIENT_MEMORY:
+                return "Unsufficient memory";
+            case    LIBRAW_DATA_ERROR:
+                return "Corrupted data or unexpected EOF";
+            case    LIBRAW_IO_ERROR:
+                return "Input/output error";
+            case LIBRAW_CANCELLED_BY_CALLBACK:
+                return "Cancelled by user callback";
+            default:
+                return "Unknown error code";
+        }
+    }
+
+#ifdef __cplusplus
+}
+#endif
+
+
+const double LibRaw_constants::xyz_rgb[3][3] = 
+{
+    { 0.412453, 0.357580, 0.180423 },
+    { 0.212671, 0.715160, 0.072169 },
+    { 0.019334, 0.119193, 0.950227 } 
+};
+
+const float LibRaw_constants::d65_white[3] =  { 0.950456, 1, 1.088754 };
+
+#define P1 imgdata.idata
+#define S imgdata.sizes
+#define O imgdata.params
+#define C imgdata.color
+#define M imgdata.masked_pixels
+#define T imgdata.thumbnail
+#define IO libraw_internal_data.internal_output_params
+#define ID libraw_internal_data.internal_data
+
+#define EXCEPTION_HANDLER(e) do{                        \
+        fprintf(stderr,"Exception %d caught\n",e);      \
+        switch(e)                                       \
+            {                                           \
+            case LIBRAW_EXCEPTION_ALLOC:                \
+                recycle();                              \
+                return LIBRAW_UNSUFFICIENT_MEMORY;      \
+            case LIBRAW_EXCEPTION_DECODE_RAW:           \
+            case LIBRAW_EXCEPTION_DECODE_JPEG:          \
+                recycle();                              \
+                return LIBRAW_DATA_ERROR;               \
+            case LIBRAW_EXCEPTION_IO_EOF:               \
+            case LIBRAW_EXCEPTION_IO_CORRUPT:           \
+                recycle();                              \
+                return LIBRAW_IO_ERROR;                 \
+            case LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK:\
+                recycle();                              \
+                return LIBRAW_CANCELLED_BY_CALLBACK;    \
+            default:                                    \
+                return LIBRAW_UNSPECIFIED_ERROR;        \
+            } \
+    }while(0)
+
+void LibRaw::derror()
+{
+    if (!libraw_internal_data.unpacker_data.data_error && libraw_internal_data.internal_data.input) 
+        {
+            if (libraw_internal_data.internal_data.input->eof())
+                {
+                    if(callbacks.data_cb)(*callbacks.data_cb)(callbacks.datacb_data,
+                                                              libraw_internal_data.internal_data.input->fname(),-1);
+                    throw LIBRAW_EXCEPTION_IO_EOF;
+                }
+            else
+                {
+                    if(callbacks.data_cb)(*callbacks.data_cb)(callbacks.datacb_data,
+                                                              libraw_internal_data.internal_data.input->fname(),
+                                                              libraw_internal_data.internal_data.input->tell());
+                    throw LIBRAW_EXCEPTION_IO_CORRUPT;
+                }
+        }
+    libraw_internal_data.unpacker_data.data_error = 1;
+}
+LibRaw:: LibRaw(unsigned int flags)
+{
+    double aber[4] = {1,1,1,1};
+    double gamm[6] = { 0.45,4.5,0,0,0,0 };
+    unsigned greybox[4] =  { 0, 0, UINT_MAX, UINT_MAX };
+#ifdef DCRAW_VERBOSE
+    verbose = 1;
+#else
+    verbose = 0;
+#endif
+    bzero(&imgdata,sizeof(imgdata));
+    bzero(&libraw_internal_data,sizeof(libraw_internal_data));
+    bzero(&callbacks,sizeof(callbacks));
+    callbacks.mem_cb = (flags & LIBRAW_OPIONS_NO_MEMERR_CALLBACK) ? NULL:  &default_memory_callback;
+    callbacks.data_cb = (flags & LIBRAW_OPIONS_NO_DATAERR_CALLBACK)? NULL : &default_data_callback;
+    memmove(&imgdata.params.aber,&aber,sizeof(aber));
+    memmove(&imgdata.params.gamm,&gamm,sizeof(gamm));
+    memmove(&imgdata.params.greybox,&greybox,sizeof(greybox));
+    
+    imgdata.params.bright=1;
+    imgdata.params.use_camera_matrix=-1;
+    imgdata.params.user_flip=-1;
+    imgdata.params.user_black=-1;
+    imgdata.params.user_sat=-1;
+    imgdata.params.user_qual=-1;
+    imgdata.params.output_color=1;
+    imgdata.params.output_bps=8;
+    imgdata.params.use_fuji_rotate=1;
+    imgdata.params.auto_bright_thr = 0.01;
+    imgdata.parent_class = this;
+    imgdata.progress_flags = 0;
+    tls = new LibRaw_TLS;
+    tls->init();
+}
+
+
+void* LibRaw:: malloc(size_t t)
+{
+    void *p = memmgr.malloc(t);
+    return p;
+}
+void* LibRaw::       calloc(size_t n,size_t t)
+{
+    void *p = memmgr.calloc(n,t);
+    return p;
+}
+void  LibRaw::      free(void *p)
+{
+    memmgr.free(p);
+}
+
+
+int LibRaw:: fc (int row, int col)
+{
+    static const char filter[16][16] =
+        { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
+          { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
+          { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
+          { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
+          { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
+          { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
+          { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
+          { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
+          { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
+          { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
+          { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
+          { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
+          { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
+          { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
+          { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
+          { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
+    
+    if (imgdata.idata.filters != 1) return FC(row,col);
+    return filter[(row+imgdata.sizes.top_margin) & 15][(col+imgdata.sizes.left_margin) & 15];
+}
+
+void LibRaw:: recycle() 
+{
+    if(libraw_internal_data.internal_data.input && libraw_internal_data.internal_data.input_internal) 
+        { 
+            delete libraw_internal_data.internal_data.input; 
+            libraw_internal_data.internal_data.input = NULL;
+        }
+    libraw_internal_data.internal_data.input_internal = 0;
+#define FREE(a) do { if(a) { free(a); a = NULL;} }while(0)
+            
+    FREE(imgdata.image); 
+    FREE(imgdata.thumbnail.thumb);
+    FREE(libraw_internal_data.internal_data.meta_data);
+    FREE(libraw_internal_data.output_data.histogram);
+    FREE(libraw_internal_data.output_data.oprof);
+    FREE(imgdata.color.profile);
+    FREE(imgdata.masked_pixels.buffer);
+    FREE(imgdata.masked_pixels.ph1_black);
+#undef FREE
+#define ZERO(a) bzero(&a,sizeof(a))
+    ZERO(imgdata.masked_pixels);
+    ZERO(imgdata.sizes);
+    ZERO(libraw_internal_data.internal_output_params);
+#undef ZERO
+    memmgr.cleanup();
+    imgdata.thumbnail.tformat = LIBRAW_THUMBNAIL_UNKNOWN;
+    imgdata.progress_flags = 0;
+    
+    tls->init();
+}
+
+const char * LibRaw::unpack_function_name()
+{
+    if(!load_raw) return "Function not set";
+
+    // sorted names order
+    if (load_raw == &LibRaw::adobe_dng_load_raw_lj)     return "adobe_dng_load_raw_lj()";
+    if (load_raw == &LibRaw::adobe_dng_load_raw_nc)     return "adobe_dng_load_raw_nc()";
+    if (load_raw == &LibRaw::canon_600_load_raw)        return "canon_600_load_raw()";
+
+    if (load_raw == &LibRaw::canon_a5_load_raw)         return "canon_a5_load_raw()";
+    if (load_raw == &LibRaw::canon_compressed_load_raw) return "canon_compressed_load_raw()";
+    if (load_raw == &LibRaw::canon_sraw_load_raw)       return "canon_sraw_load_raw()";
+
+    if (load_raw == &LibRaw::casio_qv5700_load_raw )    return "casio_qv5700_load_raw()";
+    if (load_raw == &LibRaw::eight_bit_load_raw )       return "eight_bit_load_raw()";
+    if (load_raw == &LibRaw::foveon_load_raw )          return "foveon_load_raw()";
+    if (load_raw == &LibRaw::fuji_load_raw )            return "fuji_load_raw()";
+    // 10
+    if (load_raw == &LibRaw::hasselblad_load_raw )      return "hasselblad_load_raw()";
+    if (load_raw == &LibRaw::imacon_full_load_raw )     return "imacon_full_load_raw()";
+    if (load_raw == &LibRaw::kodak_262_load_raw )       return "kodak_262_load_raw()";
+
+    if (load_raw == &LibRaw::kodak_65000_load_raw )     return "kodak_65000_load_raw()";
+    if (load_raw == &LibRaw::kodak_dc120_load_raw )     return "kodak_dc120_load_raw()";
+    if (load_raw == &LibRaw::kodak_jpeg_load_raw )      return "kodak_jpeg_load_raw()";
+
+    if (load_raw == &LibRaw::kodak_radc_load_raw )      return "kodak_radc_load_raw()";
+    if (load_raw == &LibRaw::kodak_rgb_load_raw )       return "kodak_rgb_load_raw()";
+    if (load_raw == &LibRaw::kodak_yrgb_load_raw )      return "kodak_yrgb_load_raw()";
+    if (load_raw == &LibRaw::kodak_ycbcr_load_raw )     return "kodak_ycbcr_load_raw()";
+    // 20
+    if (load_raw == &LibRaw::leaf_hdr_load_raw )        return "leaf_hdr_load_raw()";
+    if (load_raw == &LibRaw::lossless_jpeg_load_raw)    return "lossless_jpeg_load_raw()";
+    if (load_raw == &LibRaw::minolta_rd175_load_raw )   return "minolta_rd175_load_raw()";
+
+    if (load_raw == &LibRaw::nikon_compressed_load_raw) return "nikon_compressed_load_raw()";
+    if (load_raw == &LibRaw::nikon_e900_load_raw )      return "nikon_e900_load_raw()";
+    if (load_raw == &LibRaw::nokia_load_raw )           return "nokia_load_raw()";
+
+    if (load_raw == &LibRaw::olympus_e410_load_raw )    return "olympus_e410_load_raw()";
+    if (load_raw == &LibRaw::packed_12_load_raw )       return "packed_12_load_raw()";
+    if (load_raw == &LibRaw::panasonic_load_raw )       return "panasonic_load_raw()";
+    // 30
+    if (load_raw == &LibRaw::pentax_k10_load_raw )      return "pentax_k10_load_raw()";
+    if (load_raw == &LibRaw::phase_one_load_raw )       return "phase_one_load_raw()";
+    if (load_raw == &LibRaw::phase_one_load_raw_c )     return "phase_one_load_raw_c()";
+
+    if (load_raw == &LibRaw::quicktake_100_load_raw )   return "quicktake_100_load_raw()";
+    if (load_raw == &LibRaw::rollei_load_raw )          return "rollei_load_raw()";
+    if (load_raw == &LibRaw::sinar_4shot_load_raw )     return "sinar_4shot_load_raw()";
+
+    if (load_raw == &LibRaw::smal_v6_load_raw )         return "smal_v6_load_raw()";
+    if (load_raw == &LibRaw::smal_v9_load_raw )         return "smal_v9_load_raw()";
+    if (load_raw == &LibRaw::sony_load_raw )            return "sony_load_raw()";
+    if (load_raw == &LibRaw::sony_arw_load_raw )        return "sony_arw_load_raw()";
+    // 40
+    if (load_raw == &LibRaw::sony_arw2_load_raw )       return "sony_arw2_load_raw()";
+    if (load_raw == &LibRaw::unpacked_load_raw )        return "unpacked_load_raw()";
+    // 42 total
+        
+    return "Unknown unpack function";
+}
+
+
+void LibRaw:: merror (void *ptr, const char *where)
+{
+    if (ptr) return;
+    if(callbacks.mem_cb)(*callbacks.mem_cb)(callbacks.memcb_data,
+                                            libraw_internal_data.internal_data.input
+                                            ?libraw_internal_data.internal_data.input->fname()
+                                            :NULL,
+                                            where);
+    throw LIBRAW_EXCEPTION_ALLOC;
+}
+
+ushort * LibRaw::get_masked_pointer(int row, int col) 
+{ 
+    if(row<0 || col < 0) return NULL;
+    if(!M.buffer) return NULL; 
+    if(row < S.top_margin)
+        {
+            // top band
+            if(col < S.left_margin)
+                {
+                    return &(M.tl[row*S.left_margin+col]);
+                }
+            else if (col < S.left_margin + S.width)
+                {
+                    int icol = col - S.left_margin;
+                    return &(M.top[row*S.width+icol]);
+                }
+            else if (col < S.raw_width)
+                {
+                    int icol = col - S.left_margin - S.width;
+                    return &(M.tr[row*S.right_margin+icol]);
+                }
+            else
+                return NULL; // out of bounds
+        }
+    else if (row < S.top_margin + S.height)
+        {
+            //normal image height
+            int irow = row - S.top_margin;
+            if(col < S.left_margin)
+                {
+                    return &M.left[irow*S.left_margin + col];
+                }
+            else if (col < S.left_margin + S.width)
+                {
+                    // central image
+                    return NULL;
+                }
+            else if (col < S.raw_width)
+                {
+                    int icol = col - S.left_margin - S.width;
+                    return &M.right[irow*S.right_margin+icol];
+                }
+            else
+                return NULL; // out of bounds
+        }
+    else if (row < S.raw_height)
+        {
+            int irow = row - S.top_margin - S.height;
+            // bottom band
+            if(col < S.left_margin)
+                {
+                    return &M.bl[irow*S.left_margin+col];
+                }
+            else if (col < S.left_margin + S.width)
+                {
+                    int icol = col - S.left_margin;
+                    return &M.bottom[irow*S.width + icol];
+                }
+            else if (col < S.raw_width)
+                {
+                    int icol = col - S.left_margin - S.width;
+                    return &M.br[irow*S.right_margin + icol];
+                }
+            else
+                return NULL; // out of bounds
+        }
+    else
+        {
+            // out of bounds
+            return NULL;
+        }
+    // fallback
+    return NULL;
+}
+
+void LibRaw:: init_masked_ptrs()
+{
+    if(!M.buffer) return;
+    
+    // top band
+    M.tl = M.buffer;
+    M.top = M.tl +(S.top_margin*S.left_margin);
+    M.tr =  M.top + (S.top_margin*S.width);
+    
+    // left-right
+    M.left = M.tr + (S.top_margin * S.right_margin);
+    M.right = M.left + (S.left_margin * S.height);
+
+    // bottom band
+    M.bl = M.right + (S.right_margin * S.height);
+    M.bottom = M.bl + (S.left_margin * S.bottom_margin);
+    M.br = M.bottom + (S.width * S.bottom_margin);
+
+}
+
+int LibRaw::add_masked_borders_to_bitmap()
+{
+    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+
+    if(S.width != S.iwidth || S.height!=S.iheight)
+        return LIBRAW_CANNOT_ADDMASK;
+
+    if(P1.is_foveon || !P1.filters)
+        return LIBRAW_CANNOT_ADDMASK;
+        
+    if(!imgdata.image)
+        return LIBRAW_OUT_OF_ORDER_CALL;
+
+    if(S.raw_width < S.width || S.raw_height < S.height)
+        return LIBRAW_SUCCESS; // nothing to do or already called
+
+    if(S.width == S.raw_width && S.height == S.raw_height)
+        return LIBRAW_SUCCESS; // nothing to do or already called
+
+    ushort (*newimage)[4];
+
+    newimage = (ushort (*)[4]) calloc (S.raw_height*S.raw_width, sizeof (*newimage));
+    merror (newimage, "add_masked_borders_to_bitmap()");
+
+    int r,c;
+    // top rows
+    for (r=0; r<S.top_margin;r++)
+        for(c=0;c<S.raw_width;c++)
+            {
+                ushort *p = get_masked_pointer(r,c);
+                if(p)
+                    newimage[r*S.raw_width+c][FC(r,c)] = *p;
+            }
+    // middle rows
+    for (r=S.top_margin; r<S.top_margin+S.height;r++)
+        {
+            int row = r-S.top_margin;
+            for(c=0;c<S.left_margin;c++)
+                {
+                    ushort *p = get_masked_pointer(r,c);
+                    if(p)
+                        newimage[r*S.raw_width+c][FC(r,c)] =  *p;
+                }
+            for(c=S.left_margin; c<S.left_margin+S.iwidth;c++)
+                {
+                    int col = c - S.left_margin;
+                    newimage[r*S.raw_width+c][FC(r,c)] = imgdata.image[row*S.iwidth+col][FC(row,col)];
+                }
+            for(c=S.left_margin+S.iwidth;c<S.raw_width;c++)
+                {
+                    ushort *p = get_masked_pointer(r,c);
+                    if(p)
+                        newimage[r*S.raw_width+c][FC(r,c)] =  *p;
+                }
+        }
+    // bottom rows
+    for (r=S.top_margin+S.height; r<S.raw_height;r++)
+        for(c=0;c<S.raw_width;c++)
+            {
+                ushort *p = get_masked_pointer(r,c);
+                if(p)
+                    newimage[r*S.raw_width+c][FC(r,c)] = *p;
+            }
+    free(imgdata.image);
+    imgdata.image=newimage;
+    S.iwidth = S.width = S.raw_width;
+    S.iheight = S.height = S.raw_height;
+    return LIBRAW_SUCCESS;
+}
+
+int LibRaw::open_file(const char *fname)
+{
+    // this stream will close on recycle()
+    LibRaw_file_datastream *stream = new LibRaw_file_datastream(fname);
+    if(!stream->valid())
+        {
+            delete stream;
+            return LIBRAW_IO_ERROR;
+        }
+    ID.input_internal = 0; // preserve from deletion on error
+    int ret = open_datastream(stream);
+    if (ret == LIBRAW_SUCCESS)
+        {
+            ID.input_internal =1 ; // flag to delete datastream on recycle
+        }
+    else
+        {
+            delete stream;
+            ID.input_internal = 0;
+        }
+    return ret;
+}
+
+int LibRaw::open_buffer(void *buffer, size_t size)
+{
+    // this stream will close on recycle()
+    if(!buffer  || buffer==(void*)-1)
+        return LIBRAW_IO_ERROR;
+
+    LibRaw_buffer_datastream *stream = new LibRaw_buffer_datastream(buffer,size);
+    if(!stream->valid())
+        {
+            delete stream;
+            return LIBRAW_IO_ERROR;
+        }
+    ID.input_internal = 0; // preserve from deletion on error
+    int ret = open_datastream(stream);
+    if (ret == LIBRAW_SUCCESS)
+        {
+            ID.input_internal =1 ; // flag to delete datastream on recycle
+        }
+    else
+        {
+            delete stream;
+            ID.input_internal = 0;
+        }
+    return ret;
+}
+
+
+int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)
+{
+
+    if(!stream)
+        return ENOENT;
+    if(!stream->valid())
+        return LIBRAW_IO_ERROR;
+    recycle();
+
+    try {
+        ID.input = stream;
+        SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN);
+
+        if (O.use_camera_matrix < 0)
+            O.use_camera_matrix = O.use_camera_wb;
+
+        identify();
+
+        if(IO.fuji_width)
+            {
+                IO.fwidth = S.width;
+                IO.fheight = S.height;
+                S.iwidth = S.width = IO.fuji_width << !libraw_internal_data.unpacker_data.fuji_layout;
+                S.iheight = S.height = S.raw_height;
+                S.raw_height += 2*S.top_margin;
+            }
+
+        int saved_raw_width = S.raw_width;
+        int saved_width = S.width;
+        // from packed_12_load_raw
+        if ((load_raw == &LibRaw:: packed_12_load_raw) && (S.raw_width * 2 >= S.width * 3))
+            {	
+                // raw_width is in bytes!
+                S.raw_width = S.raw_width * 2 / 3;	
+            }
+        else if (S.pixel_aspect < 0.95 || S.pixel_aspect > 1.05)
+            {
+                S.width*=S.pixel_aspect;
+            }
+
+        if(S.raw_width>S.width + S.left_margin)
+            S.right_margin = S.raw_width - S.width - S.left_margin;
+
+        if(S.raw_height > S.height + S.top_margin)
+            S.bottom_margin = S.raw_height - S.height - S.top_margin;
+
+        S.raw_width = saved_raw_width;
+        S.width = saved_width;
+
+        if(C.profile_length)
+            {
+                if(C.profile) free(C.profile);
+                C.profile = malloc(C.profile_length);
+                merror(C.profile,"LibRaw::open_file()");
+                ID.input->seek(ID.profile_offset,SEEK_SET);
+                ID.input->read(C.profile,C.profile_length,1);
+            }
+        
+        SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY);
+    }
+    catch ( LibRaw_exceptions err) {
+        EXCEPTION_HANDLER(err);
+    }
+
+    if(P1.raw_count < 1) 
+        return LIBRAW_FILE_UNSUPPORTED;
+
+    if (O.user_flip >= 0)
+        S.flip = O.user_flip;
+    
+    switch ((S.flip+3600) % 360) 
+        {
+        case 270:  S.flip = 5;  break;
+        case 180:  S.flip = 3;  break;
+        case  90:  S.flip = 6;  break;
+        }
+    
+    write_fun = &LibRaw::write_ppm_tiff;
+    
+    if (load_raw == &LibRaw::kodak_ycbcr_load_raw) 
+        {
+            S.height += S.height & 1;
+            S.width  += S.width  & 1;
+        }
+
+    IO.shrink = P1.filters && (O.half_size || O.threshold || O.aber[0] != 1 || O.aber[2] != 1);
+    S.iheight = (S.height + IO.shrink) >> IO.shrink;
+    S.iwidth  = (S.width  + IO.shrink) >> IO.shrink;
+    
+    SET_PROC_FLAG(LIBRAW_PROGRESS_SIZE_ADJUST);
+
+
+    return LIBRAW_SUCCESS;
+}
+
+int LibRaw::unpack(void)
+{
+    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_LOAD_RAW);
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
+    try {
+
+        RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW,0,2);
+        if (O.shot_select >= P1.raw_count)
+            return LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE;
+        
+        if(!load_raw)
+            return LIBRAW_UNSPECIFIED_ERROR;
+        
+        if (O.use_camera_matrix && C.cmatrix[0][0] > 0.25) 
+            {
+                memcpy (C.rgb_cam, C.cmatrix, sizeof (C.cmatrix));
+                IO.raw_color = 0;
+            }
+        // already allocated ?
+        if(imgdata.image) free(imgdata.image);
+        
+        imgdata.image = (ushort (*)[4]) calloc (S.iheight*S.iwidth, sizeof (*imgdata.image));
+        merror (imgdata.image, "unpack()");
+
+
+        if(S.top_margin || S.left_margin || S.right_margin || S.bottom_margin)
+            {
+                unsigned sz = S.raw_height*(S.left_margin+S.right_margin) 
+                    + S.width*(S.top_margin+S.bottom_margin);
+                imgdata.masked_pixels.buffer = (ushort*) calloc(sz, sizeof(ushort)); 
+                merror (imgdata.masked_pixels.buffer, "unpack()");
+                init_masked_ptrs();
+            }
+        if (libraw_internal_data.unpacker_data.meta_length) 
+            {
+                libraw_internal_data.internal_data.meta_data = 
+                    (char *) malloc (libraw_internal_data.unpacker_data.meta_length);
+                merror (libraw_internal_data.internal_data.meta_data, "LibRaw::unpack()");
+            }
+        ID.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET);
+        // foveon_load_raw produces different data for document_mode, we'll
+        // deal with it in dcraw_document_mode_processing
+        int save_document_mode = O.document_mode;
+        O.document_mode = 0;
+
+        if(!own_filtering_supported() && (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT))
+            O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC_BIT; // turn on black and zeroes filtering
+        
+        (this->*load_raw)();
+        
+        O.document_mode = save_document_mode;
+
+        if (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT)
+            O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC; // restore automated mode
+        
+        SET_PROC_FLAG(LIBRAW_PROGRESS_LOAD_RAW);
+        RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW,1,2);
+        
+        return 0;
+    }
+    catch ( LibRaw_exceptions err) {
+        EXCEPTION_HANDLER(err);
+    }
+}
+
+int LibRaw::dcraw_document_mode_processing(void)
+{
+    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+
+    try {
+
+        if(IO.fwidth) 
+            rotate_fuji_raw();
+
+        if(!own_filtering_supported() && (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT))
+            O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC_BIT; // turn on black and zeroes filtering
+
+        O.document_mode = 2;
+        if(P1.is_foveon)
+            {
+                // filter image data for foveon document mode
+                short *iptr = (short *)imgdata.image;
+                for (int i=0; i < S.height*S.width*4; i++)
+                    {
+                        if ((short) iptr[i] < 0) 
+                            iptr[i] = 0;
+                    }
+                SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE);
+            }
+
+        O.use_fuji_rotate = 0;
+        if (!(O.filtering_mode & LIBRAW_FILTERING_NOZEROES) && IO.zero_is_bad)
+            {
+                remove_zeroes();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES);
+            }
+        if(O.bad_pixels) 
+            {
+                bad_pixels(O.bad_pixels);
+                SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS);
+            }
+        if (O.dark_frame)
+            {
+                subtract (O.dark_frame);
+                SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME);
+            }
+        if(O.filtering_mode & LIBRAW_FILTERING_NOBLACKS)
+            C.black=0;
+
+        if (O.user_black >= 0) 
+            C.black = O.user_black;
+
+        if (O.user_sat > 0) 
+            C.maximum = O.user_sat;
+
+        pre_interpolate();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+        if (libraw_internal_data.internal_output_params.mix_green)
+            {
+                int i;
+                for (P1.colors=3, i=0; i < S.height*S.width; i++)
+                    imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1;
+            }
+        SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN);
+
+        if (!P1.is_foveon && P1.colors == 3) 
+            median_filter();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER);
+
+        if (!P1.is_foveon && O.highlight == 2) 
+            blend_highlights();
+
+        if (!P1.is_foveon && O.highlight > 2) 
+            recover_highlights();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
+
+        if (O.use_fuji_rotate) 
+            fuji_rotate();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
+#ifndef NO_LCMS
+	if(O.camera_profile)
+            {
+                apply_profile(O.camera_profile,O.output_profile);
+                SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE);
+            }
+#endif
+        if(!libraw_internal_data.output_data.histogram)
+            {
+                libraw_internal_data.output_data.histogram = (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
+                merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_document_mode_processing()");
+            }
+        convert_to_rgb();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB);
+
+        if (O.use_fuji_rotate)
+            stretch();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH);
+
+        if (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT)
+            O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC; // restore automated mode
+
+        return 0;
+    }
+    catch ( LibRaw_exceptions err) {
+        EXCEPTION_HANDLER(err);
+    }
+
+}
+
+#if 1
+#define FORC(cnt) for (c=0; c < cnt; c++)
+#define FORCC FORC(ret->colors)
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+
+libraw_processed_image_t * LibRaw::dcraw_make_mem_thumb(int *errcode)
+{
+    if(!T.thumb)
+        {
+            if ( !ID.toffset) 
+                {
+                    if(errcode) *errcode= LIBRAW_NO_THUMBNAIL;
+                }
+            else
+                {
+                    if(errcode) *errcode= LIBRAW_OUT_OF_ORDER_CALL;
+                }
+            return NULL;
+        }
+
+    if (T.tformat == LIBRAW_THUMBNAIL_BITMAP)
+        {
+            libraw_processed_image_t * ret = 
+                (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t)+T.tlength);
+
+            if(!ret)
+                {
+                    if(errcode) *errcode= ENOMEM;
+                    return NULL;
+                }
+
+            bzero(ret,sizeof(libraw_processed_image_t));
+            ret->type   = LIBRAW_IMAGE_BITMAP;
+            ret->height = T.theight;
+            ret->width  = T.twidth;
+            ret->colors = 3; 
+            ret->bits   = 8;
+            ret->data_size = T.tlength;
+            memmove(ret->data,T.thumb,T.tlength);
+            if(errcode) *errcode= 0;
+            return ret;
+        }
+    else if (T.tformat == LIBRAW_THUMBNAIL_JPEG)
+        {
+            ushort exif[5];
+            int mk_exif = 0;
+            if(strcmp(T.thumb+6,"Exif")) mk_exif = 1;
+            
+            int dsize = T.tlength + mk_exif * (sizeof(exif)+sizeof(tiff_hdr));
+
+            libraw_processed_image_t * ret = 
+                (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t)+dsize);
+
+            if(!ret)
+                {
+                    if(errcode) *errcode= ENOMEM;
+                    return NULL;
+                }
+
+            bzero(ret,sizeof(libraw_processed_image_t));
+
+            ret->type = LIBRAW_IMAGE_JPEG;
+            ret->data_size = dsize;
+            
+            ret->data[0] = 0xff;
+            ret->data[1] = 0xd8;
+            if(mk_exif)
+                {
+                    struct tiff_hdr th;
+                    memcpy (exif, "\xff\xe1  Exif\0\0", 10);
+                    exif[1] = htons (8 + sizeof th);
+                    memmove(ret->data+2,exif,sizeof(exif));
+                    tiff_head (&th, 0);
+                    memmove(ret->data+(2+sizeof(exif)),&th,sizeof(th));
+                    memmove(ret->data+(2+sizeof(exif)+sizeof(th)),T.thumb+2,T.tlength-2);
+                }
+            else
+                {
+                    memmove(ret->data+2,T.thumb+2,T.tlength-2);
+                }
+            if(errcode) *errcode= 0;
+            return ret;
+            
+        }
+    else
+        {
+            if(errcode) *errcode= LIBRAW_UNSUPPORTED_THUMBNAIL;
+            return NULL;
+
+        }
+}
+
+
+
+libraw_processed_image_t *LibRaw::dcraw_make_mem_image(int *errcode)
+{
+    if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) < LIBRAW_PROGRESS_PRE_INTERPOLATE)
+            {
+                if(errcode) *errcode= LIBRAW_OUT_OF_ORDER_CALL;
+                return NULL;
+            }
+
+    if(libraw_internal_data.output_data.histogram)
+        {
+            int perc, val, total, t_white=0x2000,c;
+
+            perc = S.width * S.height * 0.01;		/* 99th percentile white level */
+            if (IO.fuji_width) perc /= 2;
+            if (!((O.highlight & ~2) || O.no_auto_bright))
+                for (t_white=c=0; c < P1.colors; c++) {
+                    for (val=0x2000, total=0; --val > 32; )
+                        if ((total += libraw_internal_data.output_data.histogram[c][val]) > perc) break;
+                    if (t_white < val) t_white = val;
+                }
+            gamma_curve (O.gamm[0], O.gamm[1], 2, (t_white << 3)/O.bright);
+        }
+
+    unsigned ds = S.height * S.width * (O.output_bps/8) * P1.colors;
+    libraw_processed_image_t *ret = (libraw_processed_image_t*)::malloc(sizeof(libraw_processed_image_t)+ds);
+    if(!ret)
+        {
+                if(errcode) *errcode= ENOMEM;
+                return NULL;
+        }
+    bzero(ret,sizeof(libraw_processed_image_t));
+    // metadata init
+
+    int s_iheight = S.iheight;
+    int s_iwidth = S.iwidth;
+    int s_width = S.width;
+    int s_hwight = S.height;
+
+    S.iheight = S.height;
+    S.iwidth  = S.width;
+
+
+    if (S.flip & 4) SWAP(S.height,S.width);
+
+
+    ret->type   = LIBRAW_IMAGE_BITMAP;
+    ret->height = S.height;
+    ret->width  = S.width;
+    ret->colors = P1.colors;
+    ret->bits   = O.output_bps;
+
+    ret->data_size = ds;
+
+    // Cut'n'paste from write_tiff_ppm, should be generalized later
+    uchar *bufp = ret->data;
+    uchar *ppm;
+    ushort *ppm2;
+    int c, row, col, soff, rstep, cstep;
+
+
+    soff  = flip_index (0, 0);
+    cstep = flip_index (0, 1) - soff;
+    rstep = flip_index (1, 0) - flip_index (0, S.width);
+
+
+    for (row=0; row < ret->height; row++, soff += rstep) 
+        {
+            ppm2 = (ushort*) (ppm = bufp);
+            for (col=0; col < ret->width; col++, soff += cstep)
+                if (ret->bits == 8)
+                    FORCC ppm [col*ret->colors+c] = imgdata.color.curve[imgdata.image[soff][c]]>>8;
+                else
+                    FORCC ppm2[col*ret->colors+c] =     imgdata.color.curve[imgdata.image[soff][c]];
+            bufp+=ret->colors*(ret->bits/8)*ret->width;
+        }
+    if(errcode) *errcode= 0;
+
+    S.iheight = s_iheight;
+    S.iwidth = s_iwidth;
+    S.width = s_width;
+    S.height = s_hwight;
+
+    return ret;
+}
+
+#undef FORC
+#undef FORCC
+#undef SWAP
+#endif
+
+
+int LibRaw::dcraw_ppm_tiff_writer(const char *filename)
+{
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+
+    if(!imgdata.image) 
+        return LIBRAW_OUT_OF_ORDER_CALL;
+
+    if(!filename) 
+        return ENOENT;
+    FILE *f = fopen(filename,"wb");
+
+    if(!f) 
+        return errno;
+        
+    try {
+        if(!libraw_internal_data.output_data.histogram)
+            {
+                libraw_internal_data.output_data.histogram = 
+                    (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
+                merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_ppm_tiff_writer()");
+            }
+        libraw_internal_data.internal_data.output = f;
+        write_ppm_tiff();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP);
+        libraw_internal_data.internal_data.output = NULL;
+        fclose(f);
+        return 0;
+    }
+    catch ( LibRaw_exceptions err) {
+        fclose(f);
+        EXCEPTION_HANDLER(err);
+    }
+}
+
+void LibRaw::kodak_thumb_loader()
+{
+    // some kodak cameras
+    ushort s_height = S.height, s_width = S.width,s_iwidth = S.iwidth,s_iheight=S.iheight;
+    int s_colors = P1.colors;
+    unsigned s_filters = P1.filters;
+    ushort (*s_image)[4] = imgdata.image;
+
+    
+    S.height = T.theight;
+    S.width  = T.twidth;
+    P1.filters = 0;
+
+    if (thumb_load_raw == &CLASS kodak_ycbcr_load_raw) 
+        {
+            S.height += S.height & 1;
+            S.width  += S.width  & 1;
+        }
+    
+    imgdata.image = (ushort (*)[4]) calloc (S.iheight*S.iwidth, sizeof (*imgdata.image));
+    merror (imgdata.image, "LibRaw::kodak_thumb_loader()");
+
+    ID.input->seek(ID.toffset, SEEK_SET);
+    // read kodak thumbnail into T.image[]
+    (this->*thumb_load_raw)();
+
+    // copy-n-paste from image pipe
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define LIM(x,min,max) MAX(min,MIN(x,max))
+#define CLIP(x) LIM(x,0,65535)
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+
+    // from scale_colors
+    {
+        double   dmax;
+        float scale_mul[4];
+        int c,val;
+        for (dmax=DBL_MAX, c=0; c < 3; c++) 
+                if (dmax > C.pre_mul[c])
+                    dmax = C.pre_mul[c];
+
+        for( c=0; c< 3; c++)
+                scale_mul[c] = (C.pre_mul[c] / dmax) * 65535.0 / C.maximum;
+        scale_mul[3] = scale_mul[1];
+
+        size_t size = S.height * S.width;
+        for (unsigned i=0; i < size*4 ; i++) 
+            {
+                val = imgdata.image[0][i];
+                if(!val) continue;
+                val *= scale_mul[i & 3];
+                imgdata.image[0][i] = CLIP(val);
+            }
+    }
+
+    // from convert_to_rgb
+    ushort *img;
+    int row,col;
+    
+    int  (*t_hist)[LIBRAW_HISTOGRAM_SIZE] =  (int (*)[LIBRAW_HISTOGRAM_SIZE]) calloc(sizeof(*t_hist),4);
+    merror (t_hist, "LibRaw::kodak_thumb_loader()");
+    
+    float out[3], 
+        out_cam[3][4] = 
+        {
+            {2.81761312, -1.98369181, 0.166078627, 0}, 
+            {-0.111855984, 1.73688626, -0.625030339, 0}, 
+            {-0.0379119813, -0.891268849, 1.92918086, 0}
+        };
+
+    for (img=imgdata.image[0], row=0; row < S.height; row++)
+        for (col=0; col < S.width; col++, img+=4)
+            {
+                out[0] = out[1] = out[2] = 0;
+                for(int c=0;c<3;c++) 
+                    {
+                        out[0] += out_cam[0][c] * img[c];
+                        out[1] += out_cam[1][c] * img[c];
+                        out[2] += out_cam[2][c] * img[c];
+                    }
+                for(int c=0; c<3; c++)
+                    img[c] = CLIP((int) out[c]);
+                for(int c=0; c<P1.colors;c++)
+                    t_hist[c][img[c] >> 3]++;
+                    
+            }
+
+    // from gamma_lut
+    int  (*save_hist)[LIBRAW_HISTOGRAM_SIZE] = libraw_internal_data.output_data.histogram;
+    libraw_internal_data.output_data.histogram = t_hist;
+
+    // make curve output curve!
+    ushort (*t_curve) = (ushort*) calloc(sizeof(C.curve),1);
+    merror (t_curve, "LibRaw::kodak_thumb_loader()");
+    memmove(t_curve,C.curve,sizeof(C.curve));
+    memset(C.curve,0,sizeof(C.curve));
+        {
+            int perc, val, total, t_white=0x2000,c;
+
+            perc = S.width * S.height * 0.01;		/* 99th percentile white level */
+            if (IO.fuji_width) perc /= 2;
+            if (!((O.highlight & ~2) || O.no_auto_bright))
+                for (t_white=c=0; c < P1.colors; c++) {
+                    for (val=0x2000, total=0; --val > 32; )
+                        if ((total += libraw_internal_data.output_data.histogram[c][val]) > perc) break;
+                    if (t_white < val) t_white = val;
+                }
+            gamma_curve (O.gamm[0], O.gamm[1], 2, (t_white << 3)/O.bright);
+        }
+    
+    libraw_internal_data.output_data.histogram = save_hist;
+    free(t_hist);
+    
+    // from write_ppm_tiff - copy pixels into bitmap
+    
+    S.iheight = S.height;
+    S.iwidth  = S.width;
+    if (S.flip & 4) SWAP(S.height,S.width);
+
+    if(T.thumb) free(T.thumb);
+    T.thumb = (char*) calloc (S.width * S.height, P1.colors);
+    merror (T.thumb, "LibRaw::kodak_thumb_loader()");
+    T.tlength = S.width * S.height * P1.colors;
+
+    // from write_tiff_ppm
+    {
+        int soff  = flip_index (0, 0);
+        int cstep = flip_index (0, 1) - soff;
+        int rstep = flip_index (1, 0) - flip_index (0, S.width);
+        
+        for (int row=0; row < S.height; row++, soff += rstep) 
+            {
+                char *ppm = T.thumb + row*S.width*P1.colors;
+                for (int col=0; col < S.width; col++, soff += cstep)
+                    for(int c = 0; c < P1.colors; c++)
+                        ppm [col*P1.colors+c] = imgdata.color.curve[imgdata.image[soff][c]]>>8;
+            }
+    }
+
+    memmove(C.curve,t_curve,sizeof(C.curve));
+    free(t_curve);
+
+    // restore variables
+    free(imgdata.image);
+    imgdata.image  = s_image;
+    
+    T.twidth = S.width;
+    S.width = s_width;
+
+    S.iwidth = s_iwidth;
+    S.iheight = s_iheight;
+
+    T.theight = S.height;
+    S.height = s_height;
+
+    T.tcolors = P1.colors;
+    P1.colors = s_colors;
+
+    P1.filters = s_filters;
+}
+#undef MIN
+#undef MAX
+#undef LIM
+#undef CLIP
+#undef SWAP
+
+
+void LibRaw::foveon_thumb_loader (void)
+{
+    unsigned bwide, row, col, bitbuf=0, bit=1, c, i;
+    struct decode *dindex;
+    short pred[3];
+    
+    if(T.thumb) free(T.thumb);
+    T.thumb = NULL;
+    
+    bwide = get4();
+    if (bwide > 0) 
+        {
+            if (bwide < (unsigned)T.twidth*3) return;
+            T.thumb = (char*)malloc(3*T.twidth * T.theight);
+            merror (T.thumb, "foveon_thumb()");
+            char *buf = (char*)malloc(bwide); 
+            merror (buf, "foveon_thumb()");
+            for (row=0; row < T.theight; row++) 
+                {
+                    ID.input->read(buf, 1, bwide);
+                    memmove(T.thumb+(row*T.twidth*3),buf,T.twidth*3);
+                }
+            free(buf);
+            T.tlength = 3*T.twidth * T.theight;
+            T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+            return;
+        }
+    else 
+        {
+            foveon_decoder (256, 0);
+            T.thumb = (char*)malloc(3*T.twidth * T.theight);
+            char *bufp = T.thumb;
+            merror (T.thumb, "foveon_thumb()");
+            for (row=0; row < T.theight; row++) 
+                {
+                    memset (pred, 0, sizeof pred);
+                    if (!bit) get4();
+                    for (bit=col=0; col < T.twidth; col++)
+                        for(c=0;c<3;c++) 
+                            {
+                                for (dindex=first_decode; dindex->branch[0]; ) 
+                                    {
+                                        if ((bit = (bit-1) & 31) == 31)
+                                            for (i=0; i < 4; i++)
+                                                bitbuf = (bitbuf << 8) + ID.input->get_char();
+                                        dindex = dindex->branch[bitbuf >> bit & 1];
+                                    }
+                                pred[c] += dindex->leaf;
+                                (*bufp++)=pred[c];
+                            }
+                }
+            T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+            T.tlength = 3*T.twidth * T.theight;
+        }
+    return;
+}
+
+
+// Äîñòàåò thumbnail èç ôàéëà, ñòàâèò thumb_format â ñîîòâåòñòâèè ñ ôîðìàòîì
+int LibRaw::unpack_thumb(void)
+{
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
+    CHECK_ORDER_BIT(LIBRAW_PROGRESS_THUMB_LOAD);
+
+    try {
+        if ( !ID.toffset) 
+            {
+                return LIBRAW_NO_THUMBNAIL;
+            } 
+        else if (thumb_load_raw) 
+            {
+                kodak_thumb_loader();
+                T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+                SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+                return 0;
+            } 
+        else 
+            {
+                ID.input->seek(ID.toffset, SEEK_SET);
+                if ( write_thumb == &LibRaw::jpeg_thumb)
+                    {
+                        if(T.thumb) free(T.thumb);
+                        T.thumb = (char *) malloc (T.tlength);
+                        merror (T.thumb, "jpeg_thumb()");
+                        ID.input->read (T.thumb, 1, T.tlength);
+                        T.tcolors = 3;
+                        T.tformat = LIBRAW_THUMBNAIL_JPEG;
+                        SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+                        return 0;
+                    }
+                else if (write_thumb == &LibRaw::ppm_thumb)
+                    {
+                        T.tlength = T.twidth * T.theight*3;
+                        if(T.thumb) free(T.thumb);
+
+                        T.thumb = (char *) malloc (T.tlength);
+                        merror (T.thumb, "ppm_thumb()");
+
+                        ID.input->read(T.thumb, 1, T.tlength);
+
+                        T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+                        SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+                        return 0;
+
+                    }
+                else if (write_thumb == &LibRaw::foveon_thumb)
+                    {
+                        foveon_thumb_loader();
+                        // may return with error, so format is set in
+                        // foveon thumb loader itself
+                        SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+                        return 0;
+                    }
+                // else if -- all other write_thumb cases!
+                else
+                    {
+                        return LIBRAW_UNSUPPORTED_THUMBNAIL;
+                    }
+            }
+        // last resort
+        return LIBRAW_UNSUPPORTED_THUMBNAIL;
+    }
+    catch ( LibRaw_exceptions err) {
+        EXCEPTION_HANDLER(err);
+    }
+
+}
+
+int LibRaw::dcraw_thumb_writer(const char *fname)
+{
+//    CHECK_ORDER_LOW(LIBRAW_PROGRESS_THUMB_LOAD);
+
+    if(!fname) 
+        return ENOENT;
+        
+    FILE *tfp = fopen(fname,"wb");
+    
+    if(!tfp) 
+        return errno;
+
+    if(!T.thumb)
+	{
+		fclose(tfp);
+        	return LIBRAW_OUT_OF_ORDER_CALL;
+	}
+
+    try {
+        switch (T.tformat)
+            {
+            case LIBRAW_THUMBNAIL_JPEG:
+                jpeg_thumb_writer (tfp,T.thumb,T.tlength);
+                break;
+            case LIBRAW_THUMBNAIL_BITMAP:
+                fprintf (tfp, "P6\n%d %d\n255\n", T.twidth, T.theight);
+                fwrite (T.thumb, 1, T.tlength, tfp);
+                break;
+            default:
+                fclose(tfp);
+                return LIBRAW_UNSUPPORTED_THUMBNAIL;
+           }
+        fclose(tfp);
+        return 0;
+    }
+    catch ( LibRaw_exceptions err) {
+        fclose(tfp);
+        EXCEPTION_HANDLER(err);
+    }
+}
+
+int LibRaw::adjust_sizes_info_only(void)
+{
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
+    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_FUJI_ROTATE);
+    if (O.use_fuji_rotate)
+        {
+            if (IO.fuji_width) 
+                {
+                    // restore saved values
+                    if(IO.fheight)
+                        {
+                            S.height = IO.fheight;
+                            S.width = IO.fwidth;
+                            S.iheight = (S.height + IO.shrink) >> IO.shrink;
+                            S.iwidth  = (S.width  + IO.shrink) >> IO.shrink;
+                            S.raw_height -= 2*S.top_margin;
+                            IO.fheight = IO.fwidth = 0; // prevent repeated calls
+                        }
+                    // dcraw code
+                    IO.fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink;
+                    S.iwidth = (ushort)(IO.fuji_width / sqrt(0.5));
+                    S.iheight = (ushort)( (S.iheight - IO.fuji_width) / sqrt(0.5));
+                } 
+            else 
+                {
+                    if (S.pixel_aspect < 1) S.iheight = (ushort)( S.iheight / S.pixel_aspect + 0.5);
+                    if (S.pixel_aspect > 1) S.iwidth  = (ushort) (S.iwidth  * S.pixel_aspect + 0.5);
+                }
+        }
+    SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
+    if (S.flip & 4)
+        {
+            unsigned short t = S.iheight;
+            S.iheight=S.iwidth;
+            S.iwidth = t;
+            SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP);
+        }
+    return 0;
+}
+
+int LibRaw::rotate_fuji_raw(void)
+{
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+
+    if(!IO.fwidth) return LIBRAW_SUCCESS;
+    int row,col,r,c;
+    ushort (*newimage)[4];
+    ushort fiwidth,fiheight;
+
+    fiheight = (IO.fheight + IO.shrink) >> IO.shrink;
+    fiwidth = (IO.fwidth + IO.shrink) >> IO.shrink;
+    
+    newimage = (ushort (*)[4]) calloc (fiheight*fiwidth, sizeof (*newimage));
+    merror(newimage,"rotate_fuji_raw()");
+    for(row=0;row<S.height;row++)
+        {
+            for(col=0;col<S.width;col++)
+                {
+
+                    if (libraw_internal_data.unpacker_data.fuji_layout) {
+                        r = IO.fuji_width - 1 - col + (row >> 1);
+                        c = col + ((row+1) >> 1);
+                    } else {
+                        r = IO.fuji_width - 1 + row - (col >> 1);
+                        c = row + ((col+1) >> 1);
+                    }
+                    newimage[((r) >> IO.shrink)*fiwidth + ((c) >> IO.shrink)][FC(r,c)] = 
+                        imgdata.image[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][FC(r,c)];
+                }
+        }
+    // restore fuji sizes!
+    S.height = IO.fheight;
+    S.width = IO.fwidth;
+    S.iheight = (S.height + IO.shrink) >> IO.shrink;
+    S.iwidth  = (S.width  + IO.shrink) >> IO.shrink;
+    S.raw_height -= 2*S.top_margin;
+    IO.fheight = IO.fwidth = 0; // prevent repeated calls
+
+    free(imgdata.image);
+    imgdata.image = newimage;
+    return LIBRAW_SUCCESS;
+    
+}
+
+
+int LibRaw::dcraw_process(void)
+{
+    int quality,i;
+
+
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+    try {
+
+        if(IO.fwidth) 
+            rotate_fuji_raw();
+
+
+        if(!own_filtering_supported() && (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT))
+            O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC_BIT; // turn on black and zeroes filtering
+
+        if(O.half_size) 
+            O.four_color_rgb = 1;
+
+        if (!(O.filtering_mode & LIBRAW_FILTERING_NOZEROES) && IO.zero_is_bad) 
+            {
+                remove_zeroes();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES);
+            }
+        if(O.bad_pixels) 
+            {
+                bad_pixels(O.bad_pixels);
+                SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS);
+            }
+        if (O.dark_frame)
+            {
+                subtract (O.dark_frame);
+                SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME);
+            }
+
+        quality = 2 + !IO.fuji_width;
+
+        if(O.filtering_mode & LIBRAW_FILTERING_NOBLACKS)
+            C.black=0;
+
+        if (O.user_qual >= 0) quality = O.user_qual;
+        if (O.user_black >= 0) C.black = O.user_black;
+        if (O.user_sat > 0) C.maximum = O.user_sat;
+
+        if (P1.is_foveon && !O.document_mode) 
+            {
+                foveon_interpolate();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE);
+            }
+
+        if (!P1.is_foveon && O.document_mode < 2)
+            {
+                scale_colors();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_SCALE_COLORS);
+            }
+
+        pre_interpolate();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+        if (P1.filters && !O.document_mode) 
+            {
+                if (quality == 0)
+                    lin_interpolate();
+                else if (quality == 1 || P1.colors > 3)
+                    vng_interpolate();
+                else if (quality == 2)
+                    ppg_interpolate();
+                else 
+                    ahd_interpolate();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_INTERPOLATE);
+            }
+        if (IO.mix_green)
+            {
+                for (P1.colors=3, i=0; i < S.height * S.width; i++)
+                    imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1;
+                SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN);
+            }
+
+        if(!P1.is_foveon)
+            {
+                if (P1.colors == 3) 
+                    {
+                        median_filter();
+                        SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER);
+                    }
+            
+                if (O.highlight == 2) 
+                    {
+                        blend_highlights();
+                        SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
+                    }
+            
+                if (O.highlight > 2) 
+                    {
+                        recover_highlights();
+                        SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
+                    }
+            }
+        if (O.use_fuji_rotate) 
+            {
+                fuji_rotate();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
+            }
+    
+        if(!libraw_internal_data.output_data.histogram)
+            {
+                libraw_internal_data.output_data.histogram = (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
+                merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_process()");
+            }
+#ifndef NO_LCMS
+	if(O.camera_profile)
+            {
+                apply_profile(O.camera_profile,O.output_profile);
+                SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE);
+            }
+#endif
+
+        convert_to_rgb();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB);
+
+        if (O.use_fuji_rotate) 
+            {
+                stretch();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH);
+            }
+        if (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT)
+            O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC; // restore automated mode
+        return 0;
+    }
+    catch ( LibRaw_exceptions err) {
+        EXCEPTION_HANDLER(err);
+    }
+}
+
+// Supported cameras:
+static const char  *static_camera_list[] = 
+{
+"Adobe Digital Negative (DNG)",
+"Apple QuickTake 100",
+"Apple QuickTake 150",
+"Apple QuickTake 200",
+"AVT F-080C",
+"AVT F-145C",
+"AVT F-201C",
+"AVT F-510C",
+"AVT F-810C",
+"Canon PowerShot 600",
+"Canon PowerShot A5",
+"Canon PowerShot A5 Zoom",
+"Canon PowerShot A50",
+"Canon PowerShot A460 (CHDK hack)",
+"Canon PowerShot A530 (CHDK hack)",
+"Canon PowerShot A570 (CHDK hack)",
+"Canon PowerShot A590 (CHDK hack)",
+"Canon PowerShot A610 (CHDK hack)",
+"Canon PowerShot A620 (CHDK hack)",
+"Canon PowerShot A630 (CHDK hack)",
+"Canon PowerShot A640 (CHDK hack)",
+"Canon PowerShot A650 (CHDK hack)",
+"Canon PowerShot A710 IS (CHDK hack)",
+"Canon PowerShot A720 IS (CHDK hack)",
+"Canon PowerShot Pro70",
+"Canon PowerShot Pro90 IS",
+"Canon PowerShot Pro1",
+"Canon PowerShot G1",
+"Canon PowerShot G2",
+"Canon PowerShot G3",
+"Canon PowerShot G5",
+"Canon PowerShot G6",
+"Canon PowerShot G7 (CHDK hack)",
+"Canon PowerShot G9",
+"Canon PowerShot G10",
+"Canon PowerShot S2 IS (CHDK hack)",
+"Canon PowerShot S3 IS (CHDK hack)",
+"Canon PowerShot S5 IS (CHDK hack)",
+"Canon PowerShot SD300 (CHDK hack)",
+"Canon PowerShot S30",
+"Canon PowerShot S40",
+"Canon PowerShot S45",
+"Canon PowerShot S50",
+"Canon PowerShot S60",
+"Canon PowerShot S70",
+"Canon PowerShot SX1 IS",
+"Canon PowerShot SX110 IS (CHDK hack)",
+"Canon EOS D30",
+"Canon EOS D60",
+"Canon EOS 5D",
+"Canon EOS 5D Mark II",
+"Canon EOS 10D",
+"Canon EOS 20D",
+"Canon EOS 30D",
+"Canon EOS 40D",
+"Canon EOS 50D",
+"Canon EOS 300D / Digital Rebel / Kiss Digital",
+"Canon EOS 350D / Digital Rebel XT / Kiss Digital N",
+"Canon EOS 400D / Digital Rebel XTi / Kiss Digital X",
+"Canon EOS 450D / Digital Rebel XSi / Kiss Digital X2",
+"Canon EOS 500D / Digital Rebel T1i / Kiss Digital X3",
+"Canon EOS 1000D / Digital Rebel XS / Kiss Digital F",
+"Canon EOS D2000C",
+"Canon EOS-1D",
+"Canon EOS-1DS",
+"Canon EOS-1D Mark II",
+"Canon EOS-1D Mark III",
+"Canon EOS-1D Mark II N",
+"Canon EOS-1Ds Mark II",
+"Canon EOS-1Ds Mark III",
+"Casio QV-2000UX",
+"Casio QV-3000EX",
+"Casio QV-3500EX",
+"Casio QV-4000",
+"Casio QV-5700",
+"Casio QV-R41",
+"Casio QV-R51",
+"Casio QV-R61",
+"Casio EX-S100",
+"Casio EX-Z4",
+"Casio EX-Z50",
+"Casio EX-Z55",
+"Casio Exlim Pro 505",
+"Casio Exlim Pro 600",
+"Casio Exlim Pro 700",
+"Contax N Digital",
+"Creative PC-CAM 600",
+"Epson R-D1",
+"Foculus 531C",
+"Fuji FinePix E550",
+"Fuji FinePix E900",
+"Fuji FinePix F700",
+"Fuji FinePix F710",
+"Fuji FinePix F800",
+"Fuji FinePix F810",
+"Fuji FinePix S2Pro",
+"Fuji FinePix S3Pro",
+"Fuji FinePix S5Pro",
+"Fuji FinePix S20Pro",
+"Fuji FinePix S100FS",
+"Fuji FinePix S5000",
+"Fuji FinePix S5100/S5500",
+"Fuji FinePix S5200/S5600",
+"Fuji FinePix S6000fd",
+"Fuji FinePix S7000",
+"Fuji FinePix S9000/S9500",
+"Fuji FinePix S9100/S9600",
+"Fuji IS-1",
+"Hasselblad CFV",
+"Hasselblad H3D",
+"Hasselblad V96C",
+"Imacon Ixpress 16-megapixel",
+"Imacon Ixpress 22-megapixel",
+"Imacon Ixpress 39-megapixel",
+"ISG 2020x1520",
+"Kodak DC20 (see Oliver Hartman's page)",
+"Kodak DC25 (see Jun-ichiro Itoh's page)",
+"Kodak DC40",
+"Kodak DC50",
+"Kodak DC120 (also try kdc2tiff)",
+"Kodak DCS200",
+"Kodak DCS315C",
+"Kodak DCS330C",
+"Kodak DCS420",
+"Kodak DCS460",
+"Kodak DCS460A",
+"Kodak DCS520C",
+"Kodak DCS560C",
+"Kodak DCS620C",
+"Kodak DCS620X",
+"Kodak DCS660C",
+"Kodak DCS660M",
+"Kodak DCS720X",
+"Kodak DCS760C",
+"Kodak DCS760M",
+"Kodak EOSDCS1",
+"Kodak EOSDCS3B",
+"Kodak NC2000F",
+"Kodak ProBack",
+"Kodak PB645C",
+"Kodak PB645H",
+"Kodak PB645M",
+"Kodak DCS Pro 14n",
+"Kodak DCS Pro 14nx",
+"Kodak DCS Pro SLR/c",
+"Kodak DCS Pro SLR/n",
+"Kodak C330",
+"Kodak C603",
+"Kodak P850",
+"Kodak P880",
+"Kodak Z1015",
+"Kodak KAI-0340",
+"Konica KD-400Z",
+"Konica KD-510Z",
+"Leaf AFi 7",
+"Leaf Aptus 17",
+"Leaf Aptus 22",
+"Leaf Aptus 54S",
+"Leaf Aptus 65",
+"Leaf Aptus 75",
+"Leaf Aptus 75S",
+"Leaf Cantare",
+"Leaf CatchLight",
+"Leaf CMost",
+"Leaf DCB2",
+"Leaf Valeo 6",
+"Leaf Valeo 11",
+"Leaf Valeo 17",
+"Leaf Valeo 22",
+"Leaf Volare",
+"Leica Digilux 2",
+"Leica Digilux 3",
+"Leica D-LUX2",
+"Leica D-LUX3",
+"Leica D-LUX4",
+"Leica V-LUX1",
+"Logitech Fotoman Pixtura",
+"Mamiya ZD",
+"Micron 2010",
+"Minolta RD175",
+"Minolta DiMAGE 5",
+"Minolta DiMAGE 7",
+"Minolta DiMAGE 7i",
+"Minolta DiMAGE 7Hi",
+"Minolta DiMAGE A1",
+"Minolta DiMAGE A2",
+"Minolta DiMAGE A200",
+"Minolta DiMAGE G400",
+"Minolta DiMAGE G500",
+"Minolta DiMAGE G530",
+"Minolta DiMAGE G600",
+"Minolta DiMAGE Z2",
+"Minolta Alpha/Dynax/Maxxum 5D",
+"Minolta Alpha/Dynax/Maxxum 7D",
+"Motorola PIXL",
+"Nikon D1",
+"Nikon D1H",
+"Nikon D1X",
+"Nikon D2H",
+"Nikon D2Hs",
+"Nikon D2X",
+"Nikon D2Xs",
+"Nikon D3",
+"Nikon D3X",
+"Nikon D40",
+"Nikon D40X",
+"Nikon D50",
+"Nikon D60",
+"Nikon D70",
+"Nikon D70s",
+"Nikon D80",
+"Nikon D90",
+"Nikon D100",
+"Nikon D200",
+"Nikon D300",
+"Nikon D700",
+"Nikon E700 (\"DIAG RAW\" hack)",
+"Nikon E800 (\"DIAG RAW\" hack)",
+"Nikon E880 (\"DIAG RAW\" hack)",
+"Nikon E900 (\"DIAG RAW\" hack)",
+"Nikon E950 (\"DIAG RAW\" hack)",
+"Nikon E990 (\"DIAG RAW\" hack)",
+"Nikon E995 (\"DIAG RAW\" hack)",
+"Nikon E2100 (\"DIAG RAW\" hack)",
+"Nikon E2500 (\"DIAG RAW\" hack)",
+"Nikon E3200 (\"DIAG RAW\" hack)",
+"Nikon E3700 (\"DIAG RAW\" hack)",
+"Nikon E4300 (\"DIAG RAW\" hack)",
+"Nikon E4500 (\"DIAG RAW\" hack)",
+"Nikon E5000",
+"Nikon E5400",
+"Nikon E5700",
+"Nikon E8400",
+"Nikon E8700",
+"Nikon E8800",
+"Nikon Coolpix P6000",
+"Nikon Coolpix S6 (\"DIAG RAW\" hack)",
+"Nokia N95",
+"Olympus C3030Z",
+"Olympus C5050Z",
+"Olympus C5060WZ",
+"Olympus C7070WZ",
+"Olympus C70Z,C7000Z",
+"Olympus C740UZ",
+"Olympus C770UZ",
+"Olympus C8080WZ",
+"Olympus E-1",
+"Olympus E-3",
+"Olympus E-10",
+"Olympus E-20",
+"Olympus E-30",
+"Olympus E-300",
+"Olympus E-330",
+"Olympus E-400",
+"Olympus E-410",
+"Olympus E-420",
+"Olympus E-500",
+"Olympus E-510",
+"Olympus E-520",
+"Olympus SP310",
+"Olympus SP320",
+"Olympus SP350",
+"Olympus SP500UZ",
+"Olympus SP510UZ",
+"Olympus SP550UZ",
+"Olympus SP560UZ",
+"Olympus SP570UZ",
+"Panasonic DMC-FZ8",
+"Panasonic DMC-FZ18",
+"Panasonic DMC-FZ28",
+"Panasonic DMC-FZ30",
+"Panasonic DMC-FZ50",
+"Panasonic DMC-FX150",
+"Panasonic DMC-G1",
+"Panasonic DMC-GH1",
+"Panasonic DMC-L1",
+"Panasonic DMC-L10",
+"Panasonic DMC-LC1",
+"Panasonic DMC-LX1",
+"Panasonic DMC-LX2",
+"Panasonic DMC-LX3",
+"Pentax *ist D",
+"Pentax *ist DL",
+"Pentax *ist DL2",
+"Pentax *ist DS",
+"Pentax *ist DS2",
+"Pentax K10D",
+"Pentax K20D",
+"Pentax K100D",
+"Pentax K100D Super",
+"Pentax K200D",
+"Pentax K2000/K-m",
+"Pentax Optio S",
+"Pentax Optio S4",
+"Pentax Optio 33WR",
+"Pentax Optio 750Z",
+"Phase One LightPhase",
+"Phase One H 10",
+"Phase One H 20",
+"Phase One H 25",
+"Phase One P 20",
+"Phase One P 25",
+"Phase One P 30",
+"Phase One P 45",
+"Pixelink A782",
+"Polaroid x530",
+"Rollei d530flex",
+"RoverShot 3320af",
+"Samsung GX-1S",
+"Samsung GX-10",
+"Samsung S85 (hacked)",
+"Sarnoff 4096x5440",
+"Sigma SD9",
+"Sigma SD10",
+"Sigma SD14",
+"Sinar 3072x2048",
+"Sinar 4080x4080",
+"Sinar 4080x5440",
+"Sinar STI format",
+"SMaL Ultra-Pocket 3",
+"SMaL Ultra-Pocket 4",
+"SMaL Ultra-Pocket 5",
+"Sony DSC-F828",
+"Sony DSC-R1",
+"Sony DSC-V3",
+"Sony DSLR-A100",
+"Sony DSLR-A200",
+"Sony DSLR-A300",
+"Sony DSLR-A350",
+"Sony DSLR-A700",
+"Sony DSLR-A900",
+"Sony XCD-SX910CR",
+"STV680 VGA",
+   NULL
+};
+
+const char** LibRaw::cameraList() { return static_camera_list;}
+int LibRaw::cameraCount() { return (sizeof(static_camera_list)/sizeof(static_camera_list[0]))-1; }
+
+
+const char * LibRaw::strprogress(enum LibRaw_progress p)
+{
+    switch(p)
+        {
+        case LIBRAW_PROGRESS_START:
+            return "Starting";
+        case LIBRAW_PROGRESS_OPEN :
+            return "Opening file";
+        case LIBRAW_PROGRESS_IDENTIFY :
+            return "Reading metadata";
+        case LIBRAW_PROGRESS_SIZE_ADJUST:
+            return "Adjusting size";
+        case LIBRAW_PROGRESS_LOAD_RAW:
+            return "Reading RAW data";
+        case LIBRAW_PROGRESS_REMOVE_ZEROES:
+            return "Clearing zero values";
+        case LIBRAW_PROGRESS_BAD_PIXELS :
+            return "Removing dead pixels";
+        case LIBRAW_PROGRESS_DARK_FRAME:
+            return "Subtracting dark frame data";
+        case LIBRAW_PROGRESS_FOVEON_INTERPOLATE:
+            return "Interpolating Foveon sensor data";
+        case LIBRAW_PROGRESS_SCALE_COLORS:
+            return "Scaling colors";
+        case LIBRAW_PROGRESS_PRE_INTERPOLATE:
+            return "Pre-interpolating";
+        case LIBRAW_PROGRESS_INTERPOLATE:
+            return "Interpolating";
+        case LIBRAW_PROGRESS_MIX_GREEN :
+            return "Mixing green channels";
+        case LIBRAW_PROGRESS_MEDIAN_FILTER   :
+            return "Median filter";
+        case LIBRAW_PROGRESS_HIGHLIGHTS:
+            return "Highlight recovery";
+        case LIBRAW_PROGRESS_FUJI_ROTATE :
+            return "Rotating Fuji diagonal data";
+        case LIBRAW_PROGRESS_FLIP :
+            return "Flipping image";
+        case LIBRAW_PROGRESS_APPLY_PROFILE:
+            return "ICC conversion";
+        case LIBRAW_PROGRESS_CONVERT_RGB:
+            return "Converting to RGB";
+        case LIBRAW_PROGRESS_STRETCH:
+            return "Stretching image";
+        case LIBRAW_PROGRESS_THUMB_LOAD:
+            return "Loading thumbnail";
+        default:
+            return "Some strange things";
+        }
+}
diff --git a/libfspotraw/Makefile.am b/libfspotraw/Makefile.am
new file mode 100644
index 0000000..9b5e968
--- /dev/null
+++ b/libfspotraw/Makefile.am
@@ -0,0 +1,38 @@
+include $(top_srcdir)/Makefile.include
+
+LIBRAW = LibRaw-0.8.0-Beta3
+INCLUDES = -I $(top_srcdir) -I LibRaw $(F_CFLAGS)
+
+CFLAGS = -g -O4
+CXXFLAGS = -g -O4
+
+fspotlibdir = $(libdir)/f-spot
+fspotlib_LTLIBRARIES = libfspotraw.la
+libfspotraw_files = \
+	LibRaw/libraw/libraw_const.h 					\
+	LibRaw/libraw/libraw.h 							\
+	LibRaw/libraw/libraw_version.h 					\
+	LibRaw/libraw/libraw_types.h 					\
+	LibRaw/libraw/libraw_internal.h 				\
+	LibRaw/libraw/libraw_alloc.h 					\
+	LibRaw/libraw/libraw_datastream.h 				\
+	LibRaw/internal/var_defines.h 					\
+	LibRaw/internal/libraw_internal_funcs.h 		\
+	LibRaw/internal/dcraw_fileio.cpp 				\
+	LibRaw/internal/defines.h 						\
+	LibRaw/internal/foveon.cpp 						\
+	LibRaw/internal/dcraw_common.cpp 				\
+	LibRaw/dcraw/dcraw.c 							\
+	LibRaw/src/libraw_c_api.cpp 					\
+	LibRaw/src/libraw_cxx.cpp 						\
+	fspot-librawloader.cpp 							\
+	fspot-librawloader.h
+
+libfspotraw_la_SOURCES = \
+	$(libfspotraw_files)
+
+extract: $(LIBRAW).tar.gz
+	rm -rf LibRaw
+	tar xvpzf $(LIBRAW).tar.gz
+	mv $(LIBRAW) LibRaw
+	git add LibRaw
diff --git a/libfspotraw/fspot-librawloader.cpp b/libfspotraw/fspot-librawloader.cpp
new file mode 100644
index 0000000..533877f
--- /dev/null
+++ b/libfspotraw/fspot-librawloader.cpp
@@ -0,0 +1,211 @@
+//
+// fspot-librawloader.cpp
+//
+// Author(s)
+//	Ruben Vermeersch  <ruben savanne be>
+//
+// This is free software. See COPYING for details
+//
+
+#include "fspot-librawloader.h"
+
+#include <libraw/libraw.h>
+
+G_DEFINE_TYPE (FSpotLibrawLoader, fspot_librawloader, G_TYPE_OBJECT);
+
+static void
+fspot_librawloader_set_property (GObject	  *object,
+								 guint		   property_id,
+								 const GValue *value,
+								 GParamSpec   *pspec);
+static void
+fspot_librawloader_get_property (GObject	  *object,
+								 guint		   property_id,
+								 GValue		  *value,
+								 GParamSpec   *pspec);
+static void fspot_librawloader_dispose (GObject *object);
+static void fspot_librawloader_finalize (GObject *object);
+
+static void open_if_needed (FSpotLibrawLoader *self);
+
+#define FSPOT_LIBRAWLOADER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), FSPOT_TYPE_LIBRAWLOADER, FSpotLibrawLoaderPriv))
+
+struct _FSpotLibrawLoaderPriv
+{
+	LibRaw *raw_proc;
+	gchar *filename;
+	double progress;
+
+	gboolean opened;
+};
+
+static void
+fspot_librawloader_class_init (FSpotLibrawLoaderClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GParamSpec *pspec;
+
+	gobject_class->set_property = fspot_librawloader_set_property;
+	gobject_class->get_property = fspot_librawloader_get_property;
+	gobject_class->dispose      = fspot_librawloader_dispose;
+	gobject_class->finalize     = fspot_librawloader_finalize;
+
+	pspec = g_param_spec_string ("filename",
+								 "The full path of the RAW files.",
+								 "Set filename",
+								 "",
+							     (GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	g_object_class_install_property (gobject_class,
+									 PROP_FILENAME,
+									 pspec);
+
+	pspec = g_param_spec_double ("progress",
+								 "The progress of loading the full size.",
+								 "Loading progress",
+								 0.0,
+								 1.0,
+								 0.0,
+								 G_PARAM_READABLE);
+	g_object_class_install_property (gobject_class,
+									 PROP_PROGRESS,
+									 pspec);
+
+	g_type_class_add_private (klass, sizeof (FSpotLibrawLoaderPriv));
+}
+
+static void
+fspot_librawloader_init (FSpotLibrawLoader *self)
+{
+	self->priv = FSPOT_LIBRAWLOADER_GET_PRIVATE (self);
+
+	self->priv->raw_proc = new LibRaw;
+	self->priv->opened = false;
+	self->priv->progress = 0;
+}
+
+static void
+fspot_librawloader_set_property (GObject	  *object,
+								 guint		   property_id,
+								 const GValue *value,
+								 GParamSpec   *pspec)
+{
+	FSpotLibrawLoader *self = FSPOT_LIBRAWLOADER (object);
+
+	switch (property_id)
+	{
+		case PROP_FILENAME:
+			g_free (self->priv->filename);
+			self->priv->filename = g_value_dup_string (value);
+			break;
+
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
+static void
+fspot_librawloader_get_property (GObject	  *object,
+								 guint		   property_id,
+								 GValue		  *value,
+								 GParamSpec   *pspec)
+{
+	FSpotLibrawLoader *self = FSPOT_LIBRAWLOADER (object);
+
+	switch (property_id)
+	{
+		case PROP_FILENAME:
+			g_value_set_string (value, self->priv->filename);
+			break;
+
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
+static void
+fspot_librawloader_dispose (GObject *object)
+{
+	FSpotLibrawLoader *self = FSPOT_LIBRAWLOADER (object);
+
+	self->priv->raw_proc->recycle ();
+
+	G_OBJECT_CLASS (fspot_librawloader_parent_class)->dispose (object);
+}
+
+static void
+fspot_librawloader_finalize (GObject *object)
+{
+	FSpotLibrawLoader *self = FSPOT_LIBRAWLOADER (object);
+
+	delete self->priv->raw_proc;
+	g_free (self->priv->filename);
+
+	G_OBJECT_CLASS (fspot_librawloader_parent_class)->finalize (object);
+}
+
+GdkPixbuf *
+fspot_librawloader_load_thumbnail (FSpotLibrawLoader *self)
+{
+	int result;
+	libraw_processed_image_t *image = NULL;
+	GdkPixbufLoader *loader = NULL;
+	GdkPixbuf *pixbuf = NULL;
+	GError *error = NULL;
+
+	open_if_needed (self);
+
+	self->priv->raw_proc->unpack_thumb ();
+	image = self->priv->raw_proc->dcraw_make_mem_thumb (&result);
+	g_assert (result == 0 && image != NULL);
+	g_assert (image->type == LIBRAW_IMAGE_JPEG);
+
+	loader = gdk_pixbuf_loader_new ();
+	gdk_pixbuf_loader_write (loader, image->data, image->data_size, NULL);
+	gdk_pixbuf_loader_close (loader, &error);
+	g_assert (error == NULL);
+
+	pixbuf = gdk_pixbuf_copy (gdk_pixbuf_loader_get_pixbuf (loader));
+
+	return pixbuf;
+}
+
+GdkPixbuf *
+fspot_librawloader_load_full (FSpotLibrawLoader *self)
+{
+	int result;
+	libraw_processed_image_t *image = NULL;
+	GdkPixbuf *pixbuf = NULL;
+
+	open_if_needed (self);
+
+	self->priv->raw_proc->unpack ();
+	self->priv->raw_proc->dcraw_process ();
+	image = self->priv->raw_proc->dcraw_make_mem_image (&result);
+	g_assert (result == 0 && image != NULL);
+	g_assert (image->type == LIBRAW_IMAGE_BITMAP);
+
+	pixbuf = gdk_pixbuf_new_from_data (image->data,
+									   GDK_COLORSPACE_RGB,
+									   false,
+									   image->bits,
+									   image->width,
+									   image->height,
+									   image->width * 3, /* rowstride */
+									   (GdkPixbufDestroyNotify) g_free,
+									   NULL);
+
+	return pixbuf;
+}
+
+static void
+open_if_needed (FSpotLibrawLoader *self)
+{
+	if (!self->priv->opened) {
+		int result = self->priv->raw_proc->open_file (self->priv->filename);
+		g_assert (result == 0);
+
+		self->priv->opened = true;
+	}
+}
diff --git a/libfspotraw/fspot-librawloader.h b/libfspotraw/fspot-librawloader.h
new file mode 100644
index 0000000..c3611bd
--- /dev/null
+++ b/libfspotraw/fspot-librawloader.h
@@ -0,0 +1,56 @@
+//
+// fspot-librawloader.h
+//
+// Author(s)
+//	Ruben Vermeersch  <ruben savanne be>
+//
+// This is free software. See COPYING for details
+//
+
+#ifndef __FSPOT_LIBRAWLOADER_H__
+#define __FSPOT_LIBRAWLOADER_H__
+
+#include <glib-object.h>
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define FSPOT_TYPE_LIBRAWLOADER				(fspot_librawloader_get_type ())
+#define FSPOT_LIBRAWLOADER(obj)				(G_TYPE_CHECK_INSTANCE_CAST ((obj), FSPOT_TYPE_LIBRAWLOADER, FSpotLibrawLoader))
+#define FSPOT_IS_LIBRAWLOADER(obj)			(G_TYPE_CHECK_INSTANCE_TYPE ((obj), FSPOT_TYPE_LIBRAWLOADER))
+#define FSPOT_LIBRAWLOADER_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass), FSPOT_TYPE_LIBRAWLOADER, FSpotLibrawLoaderClass))
+#define FSPOT_IS_LIBRAWLOADER_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), FSPOT_TYPE_LIBRAWLOADER))
+#define FSPOT_LIBRAWLOADER_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), FSPOT_TYPE_LIBRAWLOADER, FSpotLibrawLoaderClass))
+
+enum {
+	PROP_0,
+
+	PROP_FILENAME,
+	PROP_PROGRESS
+};
+
+typedef struct _FSpotLibrawLoader		FSpotLibrawLoader;
+typedef struct _FSpotLibrawLoaderClass	FSpotLibrawLoaderClass;
+typedef struct _FSpotLibrawLoaderPriv	FSpotLibrawLoaderPriv;
+
+struct _FSpotLibrawLoader
+{
+	GObject parent_instance;
+
+	/*< private >*/
+	FSpotLibrawLoaderPriv *priv;
+};
+
+struct _FSpotLibrawLoaderClass
+{
+	GObjectClass parent_class;
+
+};
+
+GType fspot_librawloader_get_type (void);
+GdkPixbuf * fspot_librawloader_load_thumbnail (FSpotLibrawLoader *self);
+GdkPixbuf * fspot_librawloader_load_full (FSpotLibrawLoader *self);
+
+G_END_DECLS
+
+#endif /* __FSPOT_LIBRAWLOADER_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]