Raspbian Package Auto-Building

Build log for exactimage (0.9.2-1) on armhf

exactimage0.9.2-1armhf → 2017-06-27 05:56:01

sbuild (Debian sbuild) 0.71.0 (24 Aug 2016) on bm-wb-03

+==============================================================================+
| exactimage 0.9.2-1 (armhf)                   Tue, 27 Jun 2017 05:18:27 +0000 |
+==============================================================================+

Package: exactimage
Version: 0.9.2-1
Source Version: 0.9.2-1
Distribution: buster-staging
Machine Architecture: armhf
Host Architecture: armhf
Build Architecture: armhf

I: NOTICE: Log filtering will replace 'var/lib/schroot/mount/buster-staging-armhf-sbuild-4e03235f-f5e2-4eec-b3f8-fbb0aafce692' with '<<CHROOT>>'

+------------------------------------------------------------------------------+
| Update chroot                                                                |
+------------------------------------------------------------------------------+

Get:1 http://172.17.0.1/private buster-staging InRelease [11.3 kB]
Get:2 http://172.17.0.1/private buster-staging/main Sources [9988 kB]
Get:3 http://172.17.0.1/private buster-staging/main armhf Packages [11.9 MB]
Fetched 21.9 MB in 24s (902 kB/s)
Reading package lists...
W: No sandbox user '_apt' on the system, can not drop privileges

+------------------------------------------------------------------------------+
| Fetch source files                                                           |
+------------------------------------------------------------------------------+


Check APT
---------

Checking available source versions...

Download source files with APT
------------------------------

Reading package lists...
NOTICE: 'exactimage' packaging is maintained in the 'Git' version control system at:
https://anonscm.debian.org/git/collab-maint/exactimage.git
Please use:
git clone https://anonscm.debian.org/git/collab-maint/exactimage.git
to retrieve the latest (possibly unreleased) updates to the package.
Need to get 343 kB of source archives.
Get:1 http://172.17.0.1/private buster-staging/main exactimage 0.9.2-1 (dsc) [2386 B]
Get:2 http://172.17.0.1/private buster-staging/main exactimage 0.9.2-1 (tar) [313 kB]
Get:3 http://172.17.0.1/private buster-staging/main exactimage 0.9.2-1 (diff) [27.6 kB]
Fetched 343 kB in 0s (3870 kB/s)
Download complete and in download only mode
I: NOTICE: Log filtering will replace 'build/exactimage-jTybz2/exactimage-0.9.2' with '<<PKGBUILDDIR>>'
I: NOTICE: Log filtering will replace 'build/exactimage-jTybz2' with '<<BUILDDIR>>'

+------------------------------------------------------------------------------+
| Install build-essential                                                      |
+------------------------------------------------------------------------------+


Setup apt archive
-----------------

Merged Build-Depends: build-essential, fakeroot
Filtered Build-Depends: build-essential, fakeroot
dpkg-deb: building package 'sbuild-build-depends-core-dummy' in '/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive/sbuild-build-depends-core-dummy.deb'.
dpkg-scanpackages: warning: Packages in archive but missing from override file:
dpkg-scanpackages: warning:   sbuild-build-depends-core-dummy
dpkg-scanpackages: info: Wrote 1 entries to output Packages file.
gpg: keybox '/<<BUILDDIR>>/resolver-KzgeuJ/gpg/pubring.kbx' created
gpg: /<<BUILDDIR>>/resolver-KzgeuJ/gpg/trustdb.gpg: trustdb created
gpg: key 35506D9A48F77B2E: public key "Sbuild Signer (Sbuild Build Dependency Archive Key) <buildd-tools-devel@lists.alioth.debian.org>" imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg: key 35506D9A48F77B2E: "Sbuild Signer (Sbuild Build Dependency Archive Key) <buildd-tools-devel@lists.alioth.debian.org>" not changed
gpg: key 35506D9A48F77B2E: secret key imported
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
gpg: using "Sbuild Signer" as default secret key for signing
Ign:1 copy:/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive ./ InRelease
Get:2 copy:/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive ./ Release [957 B]
Get:3 copy:/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive ./ Release.gpg [370 B]
Get:4 copy:/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive ./ Sources [349 B]
Get:5 copy:/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive ./ Packages [434 B]
Fetched 2110 B in 0s (3116 B/s)
Reading package lists...
W: No sandbox user '_apt' on the system, can not drop privileges
Reading package lists...

Install core build dependencies (apt-based resolver)
----------------------------------------------------

Installing build dependencies
Reading package lists...
Building dependency tree...
The following NEW packages will be installed:
  sbuild-build-depends-core-dummy
0 upgraded, 1 newly installed, 0 to remove and 24 not upgraded.
Need to get 770 B of archives.
After this operation, 0 B of additional disk space will be used.
Get:1 copy:/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive ./ sbuild-build-depends-core-dummy 0.invalid.0 [770 B]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 770 B in 0s (0 B/s)
Selecting previously unselected package sbuild-build-depends-core-dummy.
(Reading database ... 12654 files and directories currently installed.)
Preparing to unpack .../sbuild-build-depends-core-dummy_0.invalid.0_armhf.deb ...
Unpacking sbuild-build-depends-core-dummy (0.invalid.0) ...
Setting up sbuild-build-depends-core-dummy (0.invalid.0) ...
W: No sandbox user '_apt' on the system, can not drop privileges

+------------------------------------------------------------------------------+
| Check architectures                                                          |
+------------------------------------------------------------------------------+

Arch check ok (armhf included in any)

+------------------------------------------------------------------------------+
| Install package build dependencies                                           |
+------------------------------------------------------------------------------+


Setup apt archive
-----------------

Merged Build-Depends: debhelper (>= 9.20151219), dh-python, docbook-xml, docbook-xsl, dpkg-dev (>= 1.16.1.1), libagg-dev, libevas-dev, libexpat-dev, libfreetype6-dev, libgif-dev, libjpeg-dev, libopenexr-dev, libperl-dev, libpng-dev, libtiff5-dev, libx11-dev, libxml2-utils, libxrender-dev, perl, pkg-config, python-all-dev (>= 2.6.6-3~), swig, xsltproc
Filtered Build-Depends: debhelper (>= 9.20151219), dh-python, docbook-xml, docbook-xsl, dpkg-dev (>= 1.16.1.1), libagg-dev, libevas-dev, libexpat-dev, libfreetype6-dev, libgif-dev, libjpeg-dev, libopenexr-dev, libperl-dev, libpng-dev, libtiff5-dev, libx11-dev, libxml2-utils, libxrender-dev, perl, pkg-config, python-all-dev (>= 2.6.6-3~), swig, xsltproc
dpkg-deb: building package 'sbuild-build-depends-exactimage-dummy' in '/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive/sbuild-build-depends-exactimage-dummy.deb'.
dpkg-scanpackages: warning: Packages in archive but missing from override file:
dpkg-scanpackages: warning:   sbuild-build-depends-core-dummy sbuild-build-depends-exactimage-dummy
dpkg-scanpackages: info: Wrote 2 entries to output Packages file.
gpg: using "Sbuild Signer" as default secret key for signing
Ign:1 copy:/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive ./ InRelease
Get:2 copy:/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive ./ Release [963 B]
Get:3 copy:/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive ./ Release.gpg [370 B]
Get:4 copy:/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive ./ Sources [634 B]
Get:5 copy:/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive ./ Packages [718 B]
Fetched 2685 B in 0s (3610 B/s)
Reading package lists...
W: No sandbox user '_apt' on the system, can not drop privileges
Reading package lists...

Install exactimage build dependencies (apt-based resolver)
----------------------------------------------------------

Installing build dependencies
Reading package lists...
Building dependency tree...
Reading state information...
The following additional packages will be installed:
  autoconf automake autopoint autotools-dev bsdmainutils debhelper
  dh-autoreconf dh-python dh-strip-nondeterminism docbook-xml docbook-xsl file
  fontconfig fontconfig-config fonts-dejavu-core gettext gettext-base
  groff-base intltool-debian libagg-dev libarchive-zip-perl libavahi-client3
  libavahi-common-data libavahi-common3 libbsd0 libcairo2 libcroco3 libcups2
  libcupsimage2 libdatrie1 libeet-dev libeet1 libeina-dev libeina1 libevas-dev
  libevas-loaders libevas1 libexpat1 libexpat1-dev libffi6
  libfile-stripnondeterminism-perl libfontconfig1 libfontconfig1-dev
  libfreetype6 libfreetype6-dev libfribidi-dev libfribidi0 libgdk-pixbuf2.0-0
  libgdk-pixbuf2.0-common libgif-dev libgif7 libglib2.0-0 libgmp-dev
  libgmpxx4ldbl libgnutls-dane0 libgnutls-openssl27 libgnutls28-dev
  libgnutls30 libgnutlsxx28 libgraphite2-3 libgs9 libgs9-common
  libgssapi-krb5-2 libharfbuzz0b libhogweed4 libicu57 libidn11-dev libijs-0.35
  libilmbase-dev libilmbase12 libjbig-dev libjbig0 libjbig2dec0 libjpeg-dev
  libjpeg62-turbo libjpeg62-turbo-dev libk5crypto3 libkeyutils1 libkrb5-3
  libkrb5support0 liblcms2-2 liblzma-dev libmagic-mgc libmagic1 libmpdec2
  libnettle6 libopenexr-dev libopenexr22 libopenjp2-7 libp11-kit-dev
  libp11-kit0 libpango-1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0 libpaper1
  libperl-dev libperl5.24 libpipeline1 libpixman-1-0 libpng-dev libpng12-0
  libpng16-16 libpthread-stubs0-dev libpython-all-dev libpython-dev
  libpython-stdlib libpython2.7 libpython2.7-dev libpython2.7-minimal
  libpython2.7-stdlib libpython3-stdlib libpython3.5-minimal
  libpython3.5-stdlib libraw15 librsvg2-2 libsigsegv2 libspectre1 libssl1.1
  libtasn1-6 libtasn1-6-dev libthai-data libthai0 libtiff5 libtiff5-dev
  libtiffxx5 libtimedate-perl libtool libunbound2 libunistring0 libx11-6
  libx11-data libx11-dev libxau-dev libxau6 libxcb-render0 libxcb-shm0 libxcb1
  libxcb1-dev libxdmcp-dev libxdmcp6 libxext6 libxml2 libxml2-utils
  libxrender-dev libxrender1 libxslt1.1 m4 man-db mime-support nettle-dev perl
  perl-base perl-modules-5.24 pkg-config po-debconf poppler-data python
  python-all python-all-dev python-dev python-minimal python2.7 python2.7-dev
  python2.7-minimal python3 python3-minimal python3.5 python3.5-minimal
  sgml-base sgml-data shared-mime-info swig swig3.0 ucf x11proto-core-dev
  x11proto-input-dev x11proto-kb-dev x11proto-render-dev xml-core
  xorg-sgml-doctools xsltproc xtrans-dev zlib1g-dev
Suggested packages:
  autoconf-archive gnu-standards autoconf-doc wamerican | wordlist whois
  vacation dh-make docbook docbook-dsssl docbook-defguide dbtoepub
  docbook-xsl-doc-html | docbook-xsl-doc-pdf | docbook-xsl-doc-text
  | docbook-xsl-doc docbook-xsl-saxon fop libsaxon-java libxalan2-java
  libxslthl-java xalan gettext-doc libasprintf-dev libgettextpo-dev groff
  cups-common efl-doc gmp-doc libgmp10-doc libmpfr-dev dns-root-data
  gnutls-doc gnutls-bin krb5-doc krb5-user liblcms2-utils liblzma-doc
  librsvg2-bin libtool-doc gfortran | fortran95-compiler gcj-jdk libxcb-doc
  m4-doc less www-browser perl-doc libterm-readline-gnu-perl
  | libterm-readline-perl-perl libmail-box-perl poppler-utils ghostscript
  fonts-japanese-mincho | fonts-ipafont-mincho fonts-japanese-gothic
  | fonts-ipafont-gothic fonts-arphic-ukai fonts-arphic-uming fonts-nanum
  python-doc python-tk python2.7-doc binfmt-support python3-doc python3-tk
  python3-venv python3.5-venv python3.5-doc sgml-base-doc perlsgml w3-recs
  opensp swig-doc swig-examples swig3.0-examples swig3.0-doc
Recommended packages:
  curl | wget | lynx-cur libcupsfilters1 efl-doc libglib2.0-data xdg-user-dirs
  fonts-droid-fallback krb5-locales libpaper-utils libpng-tools
  librsvg2-common libtasn1-doc libltdl-dev libx11-doc netbase rename
  libmail-sendmail-perl
The following NEW packages will be installed:
  autoconf automake autopoint autotools-dev bsdmainutils debhelper
  dh-autoreconf dh-python dh-strip-nondeterminism docbook-xml docbook-xsl file
  fontconfig fontconfig-config fonts-dejavu-core gettext gettext-base
  groff-base intltool-debian libagg-dev libarchive-zip-perl libavahi-client3
  libavahi-common-data libavahi-common3 libbsd0 libcairo2 libcroco3 libcups2
  libcupsimage2 libdatrie1 libeet-dev libeet1 libeina-dev libeina1 libevas-dev
  libevas-loaders libevas1 libexpat1 libexpat1-dev libffi6
  libfile-stripnondeterminism-perl libfontconfig1 libfontconfig1-dev
  libfreetype6 libfreetype6-dev libfribidi-dev libfribidi0 libgdk-pixbuf2.0-0
  libgdk-pixbuf2.0-common libgif-dev libgif7 libglib2.0-0 libgmp-dev
  libgmpxx4ldbl libgnutls-dane0 libgnutls-openssl27 libgnutls28-dev
  libgnutls30 libgnutlsxx28 libgraphite2-3 libgs9 libgs9-common
  libgssapi-krb5-2 libharfbuzz0b libhogweed4 libicu57 libidn11-dev libijs-0.35
  libilmbase-dev libilmbase12 libjbig-dev libjbig0 libjbig2dec0 libjpeg-dev
  libjpeg62-turbo libjpeg62-turbo-dev libk5crypto3 libkeyutils1 libkrb5-3
  libkrb5support0 liblcms2-2 liblzma-dev libmagic-mgc libmagic1 libmpdec2
  libnettle6 libopenexr-dev libopenexr22 libopenjp2-7 libp11-kit-dev
  libp11-kit0 libpango-1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0 libpaper1
  libperl-dev libpipeline1 libpixman-1-0 libpng-dev libpng12-0
  libpthread-stubs0-dev libpython-all-dev libpython-dev libpython-stdlib
  libpython2.7 libpython2.7-dev libpython2.7-minimal libpython2.7-stdlib
  libpython3-stdlib libpython3.5-minimal libpython3.5-stdlib libraw15
  librsvg2-2 libsigsegv2 libspectre1 libssl1.1 libtasn1-6 libtasn1-6-dev
  libthai-data libthai0 libtiff5 libtiff5-dev libtiffxx5 libtimedate-perl
  libtool libunbound2 libunistring0 libx11-6 libx11-data libx11-dev libxau-dev
  libxau6 libxcb-render0 libxcb-shm0 libxcb1 libxcb1-dev libxdmcp-dev
  libxdmcp6 libxext6 libxml2 libxml2-utils libxrender-dev libxrender1
  libxslt1.1 m4 man-db mime-support nettle-dev pkg-config po-debconf
  poppler-data python python-all python-all-dev python-dev python-minimal
  python2.7 python2.7-dev python2.7-minimal python3 python3-minimal python3.5
  python3.5-minimal sbuild-build-depends-exactimage-dummy sgml-base sgml-data
  shared-mime-info swig swig3.0 ucf x11proto-core-dev x11proto-input-dev
  x11proto-kb-dev x11proto-render-dev xml-core xorg-sgml-doctools xsltproc
  xtrans-dev zlib1g-dev
The following packages will be upgraded:
  libperl5.24 libpng16-16 perl perl-base perl-modules-5.24
5 upgraded, 179 newly installed, 0 to remove and 19 not upgraded.
Need to get 108 MB of archives.
After this operation, 297 MB of additional disk space will be used.
Get:1 copy:/<<BUILDDIR>>/resolver-KzgeuJ/apt_archive ./ sbuild-build-depends-exactimage-dummy 0.invalid.0 [920 B]
Get:2 http://172.17.0.1/private buster-staging/main armhf libperl5.24 armhf 5.24.1-4 [2830 kB]
Get:3 http://172.17.0.1/private buster-staging/main armhf perl armhf 5.24.1-4 [218 kB]
Get:4 http://172.17.0.1/private buster-staging/main armhf perl-base armhf 5.24.1-4 [1196 kB]
Get:5 http://172.17.0.1/private buster-staging/main armhf perl-modules-5.24 all 5.24.1-4 [2722 kB]
Get:6 http://172.17.0.1/private buster-staging/main armhf groff-base armhf 1.22.3-9 [1005 kB]
Get:7 http://172.17.0.1/private buster-staging/main armhf libbsd0 armhf 0.8.3-1 [89.0 kB]
Get:8 http://172.17.0.1/private buster-staging/main armhf bsdmainutils armhf 9.0.12+nmu1 [178 kB]
Get:9 http://172.17.0.1/private buster-staging/main armhf libpipeline1 armhf 1.4.1-2 [23.7 kB]
Get:10 http://172.17.0.1/private buster-staging/main armhf man-db armhf 2.7.6.1-2 [1014 kB]
Get:11 http://172.17.0.1/private buster-staging/main armhf libexpat1 armhf 2.2.1-1 [65.2 kB]
Get:12 http://172.17.0.1/private buster-staging/main armhf libpng16-16 armhf 1.6.29-3 [264 kB]
Get:13 http://172.17.0.1/private buster-staging/main armhf libfreetype6 armhf 2.6.3-3.2 [384 kB]
Get:14 http://172.17.0.1/private buster-staging/main armhf ucf all 3.0036 [70.2 kB]
Get:15 http://172.17.0.1/private buster-staging/main armhf fonts-dejavu-core all 2.37-1 [1068 kB]
Get:16 http://172.17.0.1/private buster-staging/main armhf fontconfig-config all 2.11.0-6.7 [271 kB]
Get:17 http://172.17.0.1/private buster-staging/main armhf libfontconfig1 armhf 2.11.0-6.7 [313 kB]
Get:18 http://172.17.0.1/private buster-staging/main armhf fontconfig armhf 2.11.0-6.7 [402 kB]
Get:19 http://172.17.0.1/private buster-staging/main armhf libjbig0 armhf 2.1-3.1 [27.5 kB]
Get:20 http://172.17.0.1/private buster-staging/main armhf libilmbase12 armhf 2.2.0-12 [65.2 kB]
Get:21 http://172.17.0.1/private buster-staging/main armhf libilmbase-dev armhf 2.2.0-12 [76.7 kB]
Get:22 http://172.17.0.1/private buster-staging/main armhf libopenexr22 armhf 2.2.0-11 [543 kB]
Get:23 http://172.17.0.1/private buster-staging/main armhf libopenexr-dev armhf 2.2.0-11 [681 kB]
Get:24 http://172.17.0.1/private buster-staging/main armhf libxau6 armhf 1:1.0.8-1 [19.9 kB]
Get:25 http://172.17.0.1/private buster-staging/main armhf libxdmcp6 armhf 1:1.1.2-3 [25.0 kB]
Get:26 http://172.17.0.1/private buster-staging/main armhf libxcb1 armhf 1.12-1 [129 kB]
Get:27 http://172.17.0.1/private buster-staging/main armhf libx11-data all 2:1.6.4-3 [290 kB]
Get:28 http://172.17.0.1/private buster-staging/main armhf libx11-6 armhf 2:1.6.4-3 [683 kB]
Get:29 http://172.17.0.1/private buster-staging/main armhf libxext6 armhf 2:1.3.3-1 [48.1 kB]
Get:30 http://172.17.0.1/private buster-staging/main armhf poppler-data all 0.4.7-8 [1451 kB]
Get:31 http://172.17.0.1/private buster-staging/main armhf libpython2.7-minimal armhf 2.7.13-2 [389 kB]
Get:32 http://172.17.0.1/private buster-staging/main armhf python2.7-minimal armhf 2.7.13-2 [1178 kB]
Get:33 http://172.17.0.1/private buster-staging/main armhf python-minimal armhf 2.7.13-2 [40.5 kB]
Get:34 http://172.17.0.1/private buster-staging/main armhf mime-support all 3.60 [36.7 kB]
Get:35 http://172.17.0.1/private buster-staging/main armhf libffi6 armhf 3.2.1-6 [18.7 kB]
Get:36 http://172.17.0.1/private buster-staging/main armhf libssl1.1 armhf 1.1.0f-3 [1105 kB]
Get:37 http://172.17.0.1/private buster-staging/main armhf libpython2.7-stdlib armhf 2.7.13-2 [1827 kB]
Get:38 http://172.17.0.1/private buster-staging/main armhf python2.7 armhf 2.7.13-2 [285 kB]
Get:39 http://172.17.0.1/private buster-staging/main armhf libpython-stdlib armhf 2.7.13-2 [20.0 kB]
Get:40 http://172.17.0.1/private buster-staging/main armhf python armhf 2.7.13-2 [154 kB]
Get:41 http://172.17.0.1/private buster-staging/main armhf libpython3.5-minimal armhf 3.5.3-3 [570 kB]
Get:42 http://172.17.0.1/private buster-staging/main armhf python3.5-minimal armhf 3.5.3-3 [1447 kB]
Get:43 http://172.17.0.1/private buster-staging/main armhf python3-minimal armhf 3.5.3-1 [35.3 kB]
Get:44 http://172.17.0.1/private buster-staging/main armhf libmpdec2 armhf 2.4.2-1 [67.5 kB]
Get:45 http://172.17.0.1/private buster-staging/main armhf libpython3.5-stdlib armhf 3.5.3-3 [2091 kB]
Get:46 http://172.17.0.1/private buster-staging/main armhf python3.5 armhf 3.5.3-3 [237 kB]
Get:47 http://172.17.0.1/private buster-staging/main armhf libpython3-stdlib armhf 3.5.3-1 [18.6 kB]
Get:48 http://172.17.0.1/private buster-staging/main armhf dh-python all 2.20170125 [86.8 kB]
Get:49 http://172.17.0.1/private buster-staging/main armhf python3 armhf 3.5.3-1 [21.6 kB]
Get:50 http://172.17.0.1/private buster-staging/main armhf sgml-base all 1.29 [14.8 kB]
Get:51 http://172.17.0.1/private buster-staging/main armhf libmagic-mgc armhf 1:5.30-1 [222 kB]
Get:52 http://172.17.0.1/private buster-staging/main armhf libmagic1 armhf 1:5.30-1 [105 kB]
Get:53 http://172.17.0.1/private buster-staging/main armhf file armhf 1:5.30-1 [63.4 kB]
Get:54 http://172.17.0.1/private buster-staging/main armhf gettext-base armhf 0.19.8.1-2 [116 kB]
Get:55 http://172.17.0.1/private buster-staging/main armhf libnettle6 armhf 3.3-1 [204 kB]
Get:56 http://172.17.0.1/private buster-staging/main armhf libhogweed4 armhf 3.3-1 [126 kB]
Get:57 http://172.17.0.1/private buster-staging/main armhf libp11-kit0 armhf 0.23.3-5 [94.6 kB]
Get:58 http://172.17.0.1/private buster-staging/main armhf libtasn1-6 armhf 4.12-2 [46.0 kB]
Get:59 http://172.17.0.1/private buster-staging/main armhf libgnutls30 armhf 3.5.8-6 [822 kB]
Get:60 http://172.17.0.1/private buster-staging/main armhf libgnutls-openssl27 armhf 3.5.8-6 [182 kB]
Get:61 http://172.17.0.1/private buster-staging/main armhf libkeyutils1 armhf 1.5.9-9 [11.9 kB]
Get:62 http://172.17.0.1/private buster-staging/main armhf libkrb5support0 armhf 1.15-1 [57.9 kB]
Get:63 http://172.17.0.1/private buster-staging/main armhf libk5crypto3 armhf 1.15-1 [115 kB]
Get:64 http://172.17.0.1/private buster-staging/main armhf libkrb5-3 armhf 1.15-1 [262 kB]
Get:65 http://172.17.0.1/private buster-staging/main armhf libgssapi-krb5-2 armhf 1.15-1 [132 kB]
Get:66 http://172.17.0.1/private buster-staging/main armhf libicu57 armhf 57.1-6 [7427 kB]
Get:67 http://172.17.0.1/private buster-staging/main armhf libxml2 armhf 2.9.4+dfsg1-2.2 [806 kB]
Get:68 http://172.17.0.1/private buster-staging/main armhf libsigsegv2 armhf 2.10-5 [28.4 kB]
Get:69 http://172.17.0.1/private buster-staging/main armhf m4 armhf 1.4.18-1 [185 kB]
Get:70 http://172.17.0.1/private buster-staging/main armhf autoconf all 2.69-10 [338 kB]
Get:71 http://172.17.0.1/private buster-staging/main armhf autotools-dev all 20161112.1 [73.4 kB]
Get:72 http://172.17.0.1/private buster-staging/main armhf automake all 1:1.15-6 [733 kB]
Get:73 http://172.17.0.1/private buster-staging/main armhf autopoint all 0.19.8.1-2 [433 kB]
Get:74 http://172.17.0.1/private buster-staging/main armhf libtool all 2.4.6-2 [545 kB]
Get:75 http://172.17.0.1/private buster-staging/main armhf dh-autoreconf all 14 [15.9 kB]
Get:76 http://172.17.0.1/private buster-staging/main armhf libarchive-zip-perl all 1.59-1 [95.5 kB]
Get:77 http://172.17.0.1/private buster-staging/main armhf libfile-stripnondeterminism-perl all 0.034-1 [16.4 kB]
Get:78 http://172.17.0.1/private buster-staging/main armhf libtimedate-perl all 2.3000-2 [42.2 kB]
Get:79 http://172.17.0.1/private buster-staging/main armhf dh-strip-nondeterminism all 0.034-1 [10.5 kB]
Get:80 http://172.17.0.1/private buster-staging/main armhf libglib2.0-0 armhf 2.50.3-2 [2527 kB]
Get:81 http://172.17.0.1/private buster-staging/main armhf libcroco3 armhf 0.6.11-3 [131 kB]
Get:82 http://172.17.0.1/private buster-staging/main armhf libunistring0 armhf 0.9.6+really0.9.3-0.1 [252 kB]
Get:83 http://172.17.0.1/private buster-staging/main armhf gettext armhf 0.19.8.1-2 [1434 kB]
Get:84 http://172.17.0.1/private buster-staging/main armhf intltool-debian all 0.35.0+20060710.4 [26.3 kB]
Get:85 http://172.17.0.1/private buster-staging/main armhf po-debconf all 1.0.20 [247 kB]
Get:86 http://172.17.0.1/private buster-staging/main armhf debhelper all 10.2.5 [961 kB]
Get:87 http://172.17.0.1/private buster-staging/main armhf xml-core all 0.17 [23.2 kB]
Get:88 http://172.17.0.1/private buster-staging/main armhf sgml-data all 2.0.10 [181 kB]
Get:89 http://172.17.0.1/private buster-staging/main armhf docbook-xml all 4.5-8 [84.7 kB]
Get:90 http://172.17.0.1/private buster-staging/main armhf docbook-xsl all 1.79.1+dfsg-2 [1249 kB]
Get:91 http://172.17.0.1/private buster-staging/main armhf libagg-dev armhf 2.5+dfsg1-12 [270 kB]
Get:92 http://172.17.0.1/private buster-staging/main armhf libavahi-common-data armhf 0.6.32-2 [118 kB]
Get:93 http://172.17.0.1/private buster-staging/main armhf libavahi-common3 armhf 0.6.32-2 [48.6 kB]
Get:94 http://172.17.0.1/private buster-staging/main armhf libavahi-client3 armhf 0.6.32-2 [51.3 kB]
Get:95 http://172.17.0.1/private buster-staging/main armhf libpixman-1-0 armhf 0.34.0-1 [451 kB]
Get:96 http://172.17.0.1/private buster-staging/main armhf libxcb-render0 armhf 1.12-1 [104 kB]
Get:97 http://172.17.0.1/private buster-staging/main armhf libxcb-shm0 armhf 1.12-1 [95.9 kB]
Get:98 http://172.17.0.1/private buster-staging/main armhf libxrender1 armhf 1:0.9.10-1 [29.9 kB]
Get:99 http://172.17.0.1/private buster-staging/main armhf libcairo2 armhf 1.14.8-1 [688 kB]
Get:100 http://172.17.0.1/private buster-staging/main armhf libcups2 armhf 2.2.3-2+rpi1 [277 kB]
Get:101 http://172.17.0.1/private buster-staging/main armhf libcupsimage2 armhf 2.2.3-2+rpi1 [122 kB]
Get:102 http://172.17.0.1/private buster-staging/main armhf libdatrie1 armhf 0.2.10-4 [32.8 kB]
Get:103 http://172.17.0.1/private buster-staging/main armhf libeina1 armhf 1.8.6-2.5 [157 kB]
Get:104 http://172.17.0.1/private buster-staging/main armhf libjpeg62-turbo armhf 1:1.5.1-2 [109 kB]
Get:105 http://172.17.0.1/private buster-staging/main armhf libeet1 armhf 1.8.6-2.5 [67.6 kB]
Get:106 http://172.17.0.1/private buster-staging/main armhf pkg-config armhf 0.29-4 [59.2 kB]
Get:107 http://172.17.0.1/private buster-staging/main armhf libeina-dev armhf 1.8.6-2.5 [148 kB]
Get:108 http://172.17.0.1/private buster-staging/main armhf libjpeg62-turbo-dev armhf 1:1.5.1-2 [181 kB]
Get:109 http://172.17.0.1/private buster-staging/main armhf libjpeg-dev all 1:1.5.1-2 [56.1 kB]
Get:110 http://172.17.0.1/private buster-staging/main armhf libgnutlsxx28 armhf 3.5.8-6 [11.7 kB]
Get:111 http://172.17.0.1/private buster-staging/main armhf libunbound2 armhf 1.6.0-3 [326 kB]
Get:112 http://172.17.0.1/private buster-staging/main armhf libgnutls-dane0 armhf 3.5.8-6 [182 kB]
Get:113 http://172.17.0.1/private buster-staging/main armhf libgmpxx4ldbl armhf 2:6.1.2+dfsg-1 [21.5 kB]
Get:114 http://172.17.0.1/private buster-staging/main armhf libgmp-dev armhf 2:6.1.2+dfsg-1 [563 kB]
Get:115 http://172.17.0.1/private buster-staging/main armhf nettle-dev armhf 3.3-1 [1048 kB]
Get:116 http://172.17.0.1/private buster-staging/main armhf zlib1g-dev armhf 1:1.2.8.dfsg-5 [198 kB]
Get:117 http://172.17.0.1/private buster-staging/main armhf libtasn1-6-dev armhf 4.12-2 [96.3 kB]
Get:118 http://172.17.0.1/private buster-staging/main armhf libp11-kit-dev armhf 0.23.3-5 [64.3 kB]
Get:119 http://172.17.0.1/private buster-staging/main armhf libidn11-dev armhf 1.33-1 [590 kB]
Get:120 http://172.17.0.1/private buster-staging/main armhf libgnutls28-dev armhf 3.5.8-6 [787 kB]
Get:121 http://172.17.0.1/private buster-staging/main armhf libeet-dev armhf 1.8.6-2.5 [50.5 kB]
Get:122 http://172.17.0.1/private buster-staging/main armhf libfribidi0 armhf 0.19.7-1 [44.2 kB]
Get:123 http://172.17.0.1/private buster-staging/main armhf libgif7 armhf 5.1.4-0.4 [40.8 kB]
Get:124 http://172.17.0.1/private buster-staging/main armhf libpng12-0 armhf 1.2.54-6 [160 kB]
Get:125 http://172.17.0.1/private buster-staging/main armhf libtiff5 armhf 4.0.8-2 [218 kB]
Get:126 http://172.17.0.1/private buster-staging/main armhf shared-mime-info armhf 1.8-1 [727 kB]
Get:127 http://172.17.0.1/private buster-staging/main armhf libgdk-pixbuf2.0-common all 2.36.5-2 [310 kB]
Get:128 http://172.17.0.1/private buster-staging/main armhf libgdk-pixbuf2.0-0 armhf 2.36.5-2 [152 kB]
Get:129 http://172.17.0.1/private buster-staging/main armhf liblcms2-2 armhf 2.8-4 [118 kB]
Get:130 http://172.17.0.1/private buster-staging/main armhf libraw15 armhf 0.17.2-6 [242 kB]
Get:131 http://172.17.0.1/private buster-staging/main armhf libthai-data all 0.1.26-1 [166 kB]
Get:132 http://172.17.0.1/private buster-staging/main armhf libthai0 armhf 0.1.26-1 [49.3 kB]
Get:133 http://172.17.0.1/private buster-staging/main armhf libpango-1.0-0 armhf 1.40.5-1 [305 kB]
Get:134 http://172.17.0.1/private buster-staging/main armhf libgraphite2-3 armhf 1.3.10-2 [71.8 kB]
Get:135 http://172.17.0.1/private buster-staging/main armhf libharfbuzz0b armhf 1.4.2-1 [640 kB]
Get:136 http://172.17.0.1/private buster-staging/main armhf libpangoft2-1.0-0 armhf 1.40.5-1 [201 kB]
Get:137 http://172.17.0.1/private buster-staging/main armhf libpangocairo-1.0-0 armhf 1.40.5-1 [190 kB]
Get:138 http://172.17.0.1/private buster-staging/main armhf librsvg2-2 armhf 2.40.16-1 [266 kB]
Get:139 http://172.17.0.1/private buster-staging/main armhf libijs-0.35 armhf 0.35-12 [16.0 kB]
Get:140 http://172.17.0.1/private buster-staging/main armhf libjbig2dec0 armhf 0.13-4.1 [52.6 kB]
Get:141 http://172.17.0.1/private buster-staging/main armhf libopenjp2-7 armhf 2.1.2-1.1 [108 kB]
Get:142 http://172.17.0.1/private buster-staging/main armhf libpaper1 armhf 1.1.24+nmu5 [20.8 kB]
Get:143 http://172.17.0.1/private buster-staging/main armhf libgs9-common all 9.21~dfsg-1 [5164 kB]
Get:144 http://172.17.0.1/private buster-staging/main armhf libgs9 armhf 9.21~dfsg-1 [1807 kB]
Get:145 http://172.17.0.1/private buster-staging/main armhf libspectre1 armhf 0.2.8-1 [43.6 kB]
Get:146 http://172.17.0.1/private buster-staging/main armhf libevas-loaders armhf 1.8.1-2+b2 [18.8 kB]
Get:147 http://172.17.0.1/private buster-staging/main armhf libevas1 armhf 1.8.6-2.5 [398 kB]
Get:148 http://172.17.0.1/private buster-staging/main armhf xorg-sgml-doctools all 1:1.11-1 [21.9 kB]
Get:149 http://172.17.0.1/private buster-staging/main armhf x11proto-core-dev all 7.0.31-1 [728 kB]
Get:150 http://172.17.0.1/private buster-staging/main armhf libxau-dev armhf 1:1.0.8-1 [23.0 kB]
Get:151 http://172.17.0.1/private buster-staging/main armhf libxdmcp-dev armhf 1:1.1.2-3 [40.9 kB]
Get:152 http://172.17.0.1/private buster-staging/main armhf x11proto-input-dev all 2.3.2-1 [158 kB]
Get:153 http://172.17.0.1/private buster-staging/main armhf x11proto-kb-dev all 1.0.7-1 [233 kB]
Get:154 http://172.17.0.1/private buster-staging/main armhf xtrans-dev all 1.3.5-1 [100 kB]
Get:155 http://172.17.0.1/private buster-staging/main armhf libpthread-stubs0-dev armhf 0.3-4 [4042 B]
Get:156 http://172.17.0.1/private buster-staging/main armhf libxcb1-dev armhf 1.12-1 [165 kB]
Get:157 http://172.17.0.1/private buster-staging/main armhf libx11-dev armhf 2:1.6.4-3 [753 kB]
Get:158 http://172.17.0.1/private buster-staging/main armhf libpng-dev armhf 1.6.29-3 [232 kB]
Get:159 http://172.17.0.1/private buster-staging/main armhf libfreetype6-dev armhf 2.6.3-3.2 [5757 kB]
Get:160 http://172.17.0.1/private buster-staging/main armhf libexpat1-dev armhf 2.2.1-1 [122 kB]
Get:161 http://172.17.0.1/private buster-staging/main armhf libfontconfig1-dev armhf 2.11.0-6.7 [877 kB]
Get:162 http://172.17.0.1/private buster-staging/main armhf libfribidi-dev armhf 0.19.7-1 [64.4 kB]
Get:163 http://172.17.0.1/private buster-staging/main armhf libevas-dev armhf 1.8.6-2.5 [147 kB]
Get:164 http://172.17.0.1/private buster-staging/main armhf libgif-dev armhf 5.1.4-0.4 [43.0 kB]
Get:165 http://172.17.0.1/private buster-staging/main armhf libjbig-dev armhf 2.1-3.1 [27.6 kB]
Get:166 http://172.17.0.1/private buster-staging/main armhf liblzma-dev armhf 5.2.2-1.2 [284 kB]
Get:167 http://172.17.0.1/private buster-staging/main armhf libperl-dev armhf 5.24.1-4 [2494 kB]
Get:168 http://172.17.0.1/private buster-staging/main armhf libpython2.7 armhf 2.7.13-2 [916 kB]
Get:169 http://172.17.0.1/private buster-staging/main armhf libpython2.7-dev armhf 2.7.13-2 [27.6 MB]
Get:170 http://172.17.0.1/private buster-staging/main armhf libpython-dev armhf 2.7.13-2 [20.0 kB]
Get:171 http://172.17.0.1/private buster-staging/main armhf libpython-all-dev armhf 2.7.13-2 [958 B]
Get:172 http://172.17.0.1/private buster-staging/main armhf libtiffxx5 armhf 4.0.8-2 [95.1 kB]
Get:173 http://172.17.0.1/private buster-staging/main armhf libtiff5-dev armhf 4.0.8-2 [330 kB]
Get:174 http://172.17.0.1/private buster-staging/main armhf libxml2-utils armhf 2.9.4+dfsg1-2.2 [100 kB]
Get:175 http://172.17.0.1/private buster-staging/main armhf x11proto-render-dev all 2:0.11.1-2 [20.8 kB]
Get:176 http://172.17.0.1/private buster-staging/main armhf libxrender-dev armhf 1:0.9.10-1 [37.7 kB]
Get:177 http://172.17.0.1/private buster-staging/main armhf libxslt1.1 armhf 1.1.29-2.1 [214 kB]
Get:178 http://172.17.0.1/private buster-staging/main armhf python-all armhf 2.7.13-2 [940 B]
Get:179 http://172.17.0.1/private buster-staging/main armhf python2.7-dev armhf 2.7.13-2 [276 kB]
Get:180 http://172.17.0.1/private buster-staging/main armhf python-dev armhf 2.7.13-2 [1130 B]
Get:181 http://172.17.0.1/private buster-staging/main armhf python-all-dev armhf 2.7.13-2 [962 B]
Get:182 http://172.17.0.1/private buster-staging/main armhf swig3.0 armhf 3.0.10-1.1 [1205 kB]
Get:183 http://172.17.0.1/private buster-staging/main armhf swig armhf 3.0.10-1.1 [305 kB]
Get:184 http://172.17.0.1/private buster-staging/main armhf xsltproc armhf 1.1.29-2.1 [120 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 108 MB in 16s (6380 kB/s)
(Reading database ... 12654 files and directories currently installed.)
Preparing to unpack .../libperl5.24_5.24.1-4_armhf.deb ...
Unpacking libperl5.24:armhf (5.24.1-4) over (5.24.1-3) ...
Preparing to unpack .../perl_5.24.1-4_armhf.deb ...
Unpacking perl (5.24.1-4) over (5.24.1-3) ...
Preparing to unpack .../perl-base_5.24.1-4_armhf.deb ...
Unpacking perl-base (5.24.1-4) over (5.24.1-3) ...
Setting up perl-base (5.24.1-4) ...
(Reading database ... 12654 files and directories currently installed.)
Preparing to unpack .../00-perl-modules-5.24_5.24.1-4_all.deb ...
Unpacking perl-modules-5.24 (5.24.1-4) over (5.24.1-3) ...
Selecting previously unselected package groff-base.
Preparing to unpack .../01-groff-base_1.22.3-9_armhf.deb ...
Unpacking groff-base (1.22.3-9) ...
Selecting previously unselected package libbsd0:armhf.
Preparing to unpack .../02-libbsd0_0.8.3-1_armhf.deb ...
Unpacking libbsd0:armhf (0.8.3-1) ...
Selecting previously unselected package bsdmainutils.
Preparing to unpack .../03-bsdmainutils_9.0.12+nmu1_armhf.deb ...
Unpacking bsdmainutils (9.0.12+nmu1) ...
Selecting previously unselected package libpipeline1:armhf.
Preparing to unpack .../04-libpipeline1_1.4.1-2_armhf.deb ...
Unpacking libpipeline1:armhf (1.4.1-2) ...
Selecting previously unselected package man-db.
Preparing to unpack .../05-man-db_2.7.6.1-2_armhf.deb ...
Unpacking man-db (2.7.6.1-2) ...
Selecting previously unselected package libexpat1:armhf.
Preparing to unpack .../06-libexpat1_2.2.1-1_armhf.deb ...
Unpacking libexpat1:armhf (2.2.1-1) ...
Preparing to unpack .../07-libpng16-16_1.6.29-3_armhf.deb ...
Unpacking libpng16-16:armhf (1.6.29-3) over (1.6.28-1) ...
Selecting previously unselected package libfreetype6:armhf.
Preparing to unpack .../08-libfreetype6_2.6.3-3.2_armhf.deb ...
Unpacking libfreetype6:armhf (2.6.3-3.2) ...
Selecting previously unselected package ucf.
Preparing to unpack .../09-ucf_3.0036_all.deb ...
Moving old data out of the way
Unpacking ucf (3.0036) ...
Selecting previously unselected package fonts-dejavu-core.
Preparing to unpack .../10-fonts-dejavu-core_2.37-1_all.deb ...
Unpacking fonts-dejavu-core (2.37-1) ...
Selecting previously unselected package fontconfig-config.
Preparing to unpack .../11-fontconfig-config_2.11.0-6.7_all.deb ...
Unpacking fontconfig-config (2.11.0-6.7) ...
Selecting previously unselected package libfontconfig1:armhf.
Preparing to unpack .../12-libfontconfig1_2.11.0-6.7_armhf.deb ...
Unpacking libfontconfig1:armhf (2.11.0-6.7) ...
Selecting previously unselected package fontconfig.
Preparing to unpack .../13-fontconfig_2.11.0-6.7_armhf.deb ...
Unpacking fontconfig (2.11.0-6.7) ...
Selecting previously unselected package libjbig0:armhf.
Preparing to unpack .../14-libjbig0_2.1-3.1_armhf.deb ...
Unpacking libjbig0:armhf (2.1-3.1) ...
Selecting previously unselected package libilmbase12:armhf.
Preparing to unpack .../15-libilmbase12_2.2.0-12_armhf.deb ...
Unpacking libilmbase12:armhf (2.2.0-12) ...
Selecting previously unselected package libilmbase-dev.
Preparing to unpack .../16-libilmbase-dev_2.2.0-12_armhf.deb ...
Unpacking libilmbase-dev (2.2.0-12) ...
Selecting previously unselected package libopenexr22:armhf.
Preparing to unpack .../17-libopenexr22_2.2.0-11_armhf.deb ...
Unpacking libopenexr22:armhf (2.2.0-11) ...
Selecting previously unselected package libopenexr-dev.
Preparing to unpack .../18-libopenexr-dev_2.2.0-11_armhf.deb ...
Unpacking libopenexr-dev (2.2.0-11) ...
Selecting previously unselected package libxau6:armhf.
Preparing to unpack .../19-libxau6_1%3a1.0.8-1_armhf.deb ...
Unpacking libxau6:armhf (1:1.0.8-1) ...
Selecting previously unselected package libxdmcp6:armhf.
Preparing to unpack .../20-libxdmcp6_1%3a1.1.2-3_armhf.deb ...
Unpacking libxdmcp6:armhf (1:1.1.2-3) ...
Selecting previously unselected package libxcb1:armhf.
Preparing to unpack .../21-libxcb1_1.12-1_armhf.deb ...
Unpacking libxcb1:armhf (1.12-1) ...
Selecting previously unselected package libx11-data.
Preparing to unpack .../22-libx11-data_2%3a1.6.4-3_all.deb ...
Unpacking libx11-data (2:1.6.4-3) ...
Selecting previously unselected package libx11-6:armhf.
Preparing to unpack .../23-libx11-6_2%3a1.6.4-3_armhf.deb ...
Unpacking libx11-6:armhf (2:1.6.4-3) ...
Selecting previously unselected package libxext6:armhf.
Preparing to unpack .../24-libxext6_2%3a1.3.3-1_armhf.deb ...
Unpacking libxext6:armhf (2:1.3.3-1) ...
Selecting previously unselected package poppler-data.
Preparing to unpack .../25-poppler-data_0.4.7-8_all.deb ...
Unpacking poppler-data (0.4.7-8) ...
Selecting previously unselected package libpython2.7-minimal:armhf.
Preparing to unpack .../26-libpython2.7-minimal_2.7.13-2_armhf.deb ...
Unpacking libpython2.7-minimal:armhf (2.7.13-2) ...
Selecting previously unselected package python2.7-minimal.
Preparing to unpack .../27-python2.7-minimal_2.7.13-2_armhf.deb ...
Unpacking python2.7-minimal (2.7.13-2) ...
Selecting previously unselected package python-minimal.
Preparing to unpack .../28-python-minimal_2.7.13-2_armhf.deb ...
Unpacking python-minimal (2.7.13-2) ...
Selecting previously unselected package mime-support.
Preparing to unpack .../29-mime-support_3.60_all.deb ...
Unpacking mime-support (3.60) ...
Selecting previously unselected package libffi6:armhf.
Preparing to unpack .../30-libffi6_3.2.1-6_armhf.deb ...
Unpacking libffi6:armhf (3.2.1-6) ...
Selecting previously unselected package libssl1.1:armhf.
Preparing to unpack .../31-libssl1.1_1.1.0f-3_armhf.deb ...
Unpacking libssl1.1:armhf (1.1.0f-3) ...
Selecting previously unselected package libpython2.7-stdlib:armhf.
Preparing to unpack .../32-libpython2.7-stdlib_2.7.13-2_armhf.deb ...
Unpacking libpython2.7-stdlib:armhf (2.7.13-2) ...
Selecting previously unselected package python2.7.
Preparing to unpack .../33-python2.7_2.7.13-2_armhf.deb ...
Unpacking python2.7 (2.7.13-2) ...
Selecting previously unselected package libpython-stdlib:armhf.
Preparing to unpack .../34-libpython-stdlib_2.7.13-2_armhf.deb ...
Unpacking libpython-stdlib:armhf (2.7.13-2) ...
Setting up libpython2.7-minimal:armhf (2.7.13-2) ...
Setting up python2.7-minimal (2.7.13-2) ...
Setting up python-minimal (2.7.13-2) ...
Selecting previously unselected package python.
(Reading database ... 15193 files and directories currently installed.)
Preparing to unpack .../0-python_2.7.13-2_armhf.deb ...
Unpacking python (2.7.13-2) ...
Selecting previously unselected package libpython3.5-minimal:armhf.
Preparing to unpack .../1-libpython3.5-minimal_3.5.3-3_armhf.deb ...
Unpacking libpython3.5-minimal:armhf (3.5.3-3) ...
Selecting previously unselected package python3.5-minimal.
Preparing to unpack .../2-python3.5-minimal_3.5.3-3_armhf.deb ...
Unpacking python3.5-minimal (3.5.3-3) ...
Selecting previously unselected package python3-minimal.
Preparing to unpack .../3-python3-minimal_3.5.3-1_armhf.deb ...
Unpacking python3-minimal (3.5.3-1) ...
Selecting previously unselected package libmpdec2:armhf.
Preparing to unpack .../4-libmpdec2_2.4.2-1_armhf.deb ...
Unpacking libmpdec2:armhf (2.4.2-1) ...
Selecting previously unselected package libpython3.5-stdlib:armhf.
Preparing to unpack .../5-libpython3.5-stdlib_3.5.3-3_armhf.deb ...
Unpacking libpython3.5-stdlib:armhf (3.5.3-3) ...
Selecting previously unselected package python3.5.
Preparing to unpack .../6-python3.5_3.5.3-3_armhf.deb ...
Unpacking python3.5 (3.5.3-3) ...
Selecting previously unselected package libpython3-stdlib:armhf.
Preparing to unpack .../7-libpython3-stdlib_3.5.3-1_armhf.deb ...
Unpacking libpython3-stdlib:armhf (3.5.3-1) ...
Selecting previously unselected package dh-python.
Preparing to unpack .../8-dh-python_2.20170125_all.deb ...
Unpacking dh-python (2.20170125) ...
Setting up libssl1.1:armhf (1.1.0f-3) ...
Setting up libpython3.5-minimal:armhf (3.5.3-3) ...
Setting up libexpat1:armhf (2.2.1-1) ...
Setting up python3.5-minimal (3.5.3-3) ...
Setting up python3-minimal (3.5.3-1) ...
Selecting previously unselected package python3.
(Reading database ... 16169 files and directories currently installed.)
Preparing to unpack .../000-python3_3.5.3-1_armhf.deb ...
Unpacking python3 (3.5.3-1) ...
Selecting previously unselected package sgml-base.
Preparing to unpack .../001-sgml-base_1.29_all.deb ...
Unpacking sgml-base (1.29) ...
Selecting previously unselected package libmagic-mgc.
Preparing to unpack .../002-libmagic-mgc_1%3a5.30-1_armhf.deb ...
Unpacking libmagic-mgc (1:5.30-1) ...
Selecting previously unselected package libmagic1:armhf.
Preparing to unpack .../003-libmagic1_1%3a5.30-1_armhf.deb ...
Unpacking libmagic1:armhf (1:5.30-1) ...
Selecting previously unselected package file.
Preparing to unpack .../004-file_1%3a5.30-1_armhf.deb ...
Unpacking file (1:5.30-1) ...
Selecting previously unselected package gettext-base.
Preparing to unpack .../005-gettext-base_0.19.8.1-2_armhf.deb ...
Unpacking gettext-base (0.19.8.1-2) ...
Selecting previously unselected package libnettle6:armhf.
Preparing to unpack .../006-libnettle6_3.3-1_armhf.deb ...
Unpacking libnettle6:armhf (3.3-1) ...
Selecting previously unselected package libhogweed4:armhf.
Preparing to unpack .../007-libhogweed4_3.3-1_armhf.deb ...
Unpacking libhogweed4:armhf (3.3-1) ...
Selecting previously unselected package libp11-kit0:armhf.
Preparing to unpack .../008-libp11-kit0_0.23.3-5_armhf.deb ...
Unpacking libp11-kit0:armhf (0.23.3-5) ...
Selecting previously unselected package libtasn1-6:armhf.
Preparing to unpack .../009-libtasn1-6_4.12-2_armhf.deb ...
Unpacking libtasn1-6:armhf (4.12-2) ...
Selecting previously unselected package libgnutls30:armhf.
Preparing to unpack .../010-libgnutls30_3.5.8-6_armhf.deb ...
Unpacking libgnutls30:armhf (3.5.8-6) ...
Selecting previously unselected package libgnutls-openssl27:armhf.
Preparing to unpack .../011-libgnutls-openssl27_3.5.8-6_armhf.deb ...
Unpacking libgnutls-openssl27:armhf (3.5.8-6) ...
Selecting previously unselected package libkeyutils1:armhf.
Preparing to unpack .../012-libkeyutils1_1.5.9-9_armhf.deb ...
Unpacking libkeyutils1:armhf (1.5.9-9) ...
Selecting previously unselected package libkrb5support0:armhf.
Preparing to unpack .../013-libkrb5support0_1.15-1_armhf.deb ...
Unpacking libkrb5support0:armhf (1.15-1) ...
Selecting previously unselected package libk5crypto3:armhf.
Preparing to unpack .../014-libk5crypto3_1.15-1_armhf.deb ...
Unpacking libk5crypto3:armhf (1.15-1) ...
Selecting previously unselected package libkrb5-3:armhf.
Preparing to unpack .../015-libkrb5-3_1.15-1_armhf.deb ...
Unpacking libkrb5-3:armhf (1.15-1) ...
Selecting previously unselected package libgssapi-krb5-2:armhf.
Preparing to unpack .../016-libgssapi-krb5-2_1.15-1_armhf.deb ...
Unpacking libgssapi-krb5-2:armhf (1.15-1) ...
Selecting previously unselected package libicu57:armhf.
Preparing to unpack .../017-libicu57_57.1-6_armhf.deb ...
Unpacking libicu57:armhf (57.1-6) ...
Selecting previously unselected package libxml2:armhf.
Preparing to unpack .../018-libxml2_2.9.4+dfsg1-2.2_armhf.deb ...
Unpacking libxml2:armhf (2.9.4+dfsg1-2.2) ...
Selecting previously unselected package libsigsegv2:armhf.
Preparing to unpack .../019-libsigsegv2_2.10-5_armhf.deb ...
Unpacking libsigsegv2:armhf (2.10-5) ...
Selecting previously unselected package m4.
Preparing to unpack .../020-m4_1.4.18-1_armhf.deb ...
Unpacking m4 (1.4.18-1) ...
Selecting previously unselected package autoconf.
Preparing to unpack .../021-autoconf_2.69-10_all.deb ...
Unpacking autoconf (2.69-10) ...
Selecting previously unselected package autotools-dev.
Preparing to unpack .../022-autotools-dev_20161112.1_all.deb ...
Unpacking autotools-dev (20161112.1) ...
Selecting previously unselected package automake.
Preparing to unpack .../023-automake_1%3a1.15-6_all.deb ...
Unpacking automake (1:1.15-6) ...
Selecting previously unselected package autopoint.
Preparing to unpack .../024-autopoint_0.19.8.1-2_all.deb ...
Unpacking autopoint (0.19.8.1-2) ...
Selecting previously unselected package libtool.
Preparing to unpack .../025-libtool_2.4.6-2_all.deb ...
Unpacking libtool (2.4.6-2) ...
Selecting previously unselected package dh-autoreconf.
Preparing to unpack .../026-dh-autoreconf_14_all.deb ...
Unpacking dh-autoreconf (14) ...
Selecting previously unselected package libarchive-zip-perl.
Preparing to unpack .../027-libarchive-zip-perl_1.59-1_all.deb ...
Unpacking libarchive-zip-perl (1.59-1) ...
Selecting previously unselected package libfile-stripnondeterminism-perl.
Preparing to unpack .../028-libfile-stripnondeterminism-perl_0.034-1_all.deb ...
Unpacking libfile-stripnondeterminism-perl (0.034-1) ...
Selecting previously unselected package libtimedate-perl.
Preparing to unpack .../029-libtimedate-perl_2.3000-2_all.deb ...
Unpacking libtimedate-perl (2.3000-2) ...
Selecting previously unselected package dh-strip-nondeterminism.
Preparing to unpack .../030-dh-strip-nondeterminism_0.034-1_all.deb ...
Unpacking dh-strip-nondeterminism (0.034-1) ...
Selecting previously unselected package libglib2.0-0:armhf.
Preparing to unpack .../031-libglib2.0-0_2.50.3-2_armhf.deb ...
Unpacking libglib2.0-0:armhf (2.50.3-2) ...
Selecting previously unselected package libcroco3:armhf.
Preparing to unpack .../032-libcroco3_0.6.11-3_armhf.deb ...
Unpacking libcroco3:armhf (0.6.11-3) ...
Selecting previously unselected package libunistring0:armhf.
Preparing to unpack .../033-libunistring0_0.9.6+really0.9.3-0.1_armhf.deb ...
Unpacking libunistring0:armhf (0.9.6+really0.9.3-0.1) ...
Selecting previously unselected package gettext.
Preparing to unpack .../034-gettext_0.19.8.1-2_armhf.deb ...
Unpacking gettext (0.19.8.1-2) ...
Selecting previously unselected package intltool-debian.
Preparing to unpack .../035-intltool-debian_0.35.0+20060710.4_all.deb ...
Unpacking intltool-debian (0.35.0+20060710.4) ...
Selecting previously unselected package po-debconf.
Preparing to unpack .../036-po-debconf_1.0.20_all.deb ...
Unpacking po-debconf (1.0.20) ...
Selecting previously unselected package debhelper.
Preparing to unpack .../037-debhelper_10.2.5_all.deb ...
Unpacking debhelper (10.2.5) ...
Selecting previously unselected package xml-core.
Preparing to unpack .../038-xml-core_0.17_all.deb ...
Unpacking xml-core (0.17) ...
Selecting previously unselected package sgml-data.
Preparing to unpack .../039-sgml-data_2.0.10_all.deb ...
Unpacking sgml-data (2.0.10) ...
Selecting previously unselected package docbook-xml.
Preparing to unpack .../040-docbook-xml_4.5-8_all.deb ...
Unpacking docbook-xml (4.5-8) ...
Selecting previously unselected package docbook-xsl.
Preparing to unpack .../041-docbook-xsl_1.79.1+dfsg-2_all.deb ...
Unpacking docbook-xsl (1.79.1+dfsg-2) ...
Selecting previously unselected package libagg-dev.
Preparing to unpack .../042-libagg-dev_2.5+dfsg1-12_armhf.deb ...
Unpacking libagg-dev (2.5+dfsg1-12) ...
Selecting previously unselected package libavahi-common-data:armhf.
Preparing to unpack .../043-libavahi-common-data_0.6.32-2_armhf.deb ...
Unpacking libavahi-common-data:armhf (0.6.32-2) ...
Selecting previously unselected package libavahi-common3:armhf.
Preparing to unpack .../044-libavahi-common3_0.6.32-2_armhf.deb ...
Unpacking libavahi-common3:armhf (0.6.32-2) ...
Selecting previously unselected package libavahi-client3:armhf.
Preparing to unpack .../045-libavahi-client3_0.6.32-2_armhf.deb ...
Unpacking libavahi-client3:armhf (0.6.32-2) ...
Selecting previously unselected package libpixman-1-0:armhf.
Preparing to unpack .../046-libpixman-1-0_0.34.0-1_armhf.deb ...
Unpacking libpixman-1-0:armhf (0.34.0-1) ...
Selecting previously unselected package libxcb-render0:armhf.
Preparing to unpack .../047-libxcb-render0_1.12-1_armhf.deb ...
Unpacking libxcb-render0:armhf (1.12-1) ...
Selecting previously unselected package libxcb-shm0:armhf.
Preparing to unpack .../048-libxcb-shm0_1.12-1_armhf.deb ...
Unpacking libxcb-shm0:armhf (1.12-1) ...
Selecting previously unselected package libxrender1:armhf.
Preparing to unpack .../049-libxrender1_1%3a0.9.10-1_armhf.deb ...
Unpacking libxrender1:armhf (1:0.9.10-1) ...
Selecting previously unselected package libcairo2:armhf.
Preparing to unpack .../050-libcairo2_1.14.8-1_armhf.deb ...
Unpacking libcairo2:armhf (1.14.8-1) ...
Selecting previously unselected package libcups2:armhf.
Preparing to unpack .../051-libcups2_2.2.3-2+rpi1_armhf.deb ...
Unpacking libcups2:armhf (2.2.3-2+rpi1) ...
Selecting previously unselected package libcupsimage2:armhf.
Preparing to unpack .../052-libcupsimage2_2.2.3-2+rpi1_armhf.deb ...
Unpacking libcupsimage2:armhf (2.2.3-2+rpi1) ...
Selecting previously unselected package libdatrie1:armhf.
Preparing to unpack .../053-libdatrie1_0.2.10-4_armhf.deb ...
Unpacking libdatrie1:armhf (0.2.10-4) ...
Selecting previously unselected package libeina1:armhf.
Preparing to unpack .../054-libeina1_1.8.6-2.5_armhf.deb ...
Unpacking libeina1:armhf (1.8.6-2.5) ...
Selecting previously unselected package libjpeg62-turbo:armhf.
Preparing to unpack .../055-libjpeg62-turbo_1%3a1.5.1-2_armhf.deb ...
Unpacking libjpeg62-turbo:armhf (1:1.5.1-2) ...
Selecting previously unselected package libeet1:armhf.
Preparing to unpack .../056-libeet1_1.8.6-2.5_armhf.deb ...
Unpacking libeet1:armhf (1.8.6-2.5) ...
Selecting previously unselected package pkg-config.
Preparing to unpack .../057-pkg-config_0.29-4_armhf.deb ...
Unpacking pkg-config (0.29-4) ...
Selecting previously unselected package libeina-dev.
Preparing to unpack .../058-libeina-dev_1.8.6-2.5_armhf.deb ...
Unpacking libeina-dev (1.8.6-2.5) ...
Selecting previously unselected package libjpeg62-turbo-dev:armhf.
Preparing to unpack .../059-libjpeg62-turbo-dev_1%3a1.5.1-2_armhf.deb ...
Unpacking libjpeg62-turbo-dev:armhf (1:1.5.1-2) ...
Selecting previously unselected package libjpeg-dev.
Preparing to unpack .../060-libjpeg-dev_1%3a1.5.1-2_all.deb ...
Unpacking libjpeg-dev (1:1.5.1-2) ...
Selecting previously unselected package libgnutlsxx28:armhf.
Preparing to unpack .../061-libgnutlsxx28_3.5.8-6_armhf.deb ...
Unpacking libgnutlsxx28:armhf (3.5.8-6) ...
Selecting previously unselected package libunbound2:armhf.
Preparing to unpack .../062-libunbound2_1.6.0-3_armhf.deb ...
Unpacking libunbound2:armhf (1.6.0-3) ...
Selecting previously unselected package libgnutls-dane0:armhf.
Preparing to unpack .../063-libgnutls-dane0_3.5.8-6_armhf.deb ...
Unpacking libgnutls-dane0:armhf (3.5.8-6) ...
Selecting previously unselected package libgmpxx4ldbl:armhf.
Preparing to unpack .../064-libgmpxx4ldbl_2%3a6.1.2+dfsg-1_armhf.deb ...
Unpacking libgmpxx4ldbl:armhf (2:6.1.2+dfsg-1) ...
Selecting previously unselected package libgmp-dev:armhf.
Preparing to unpack .../065-libgmp-dev_2%3a6.1.2+dfsg-1_armhf.deb ...
Unpacking libgmp-dev:armhf (2:6.1.2+dfsg-1) ...
Selecting previously unselected package nettle-dev.
Preparing to unpack .../066-nettle-dev_3.3-1_armhf.deb ...
Unpacking nettle-dev (3.3-1) ...
Selecting previously unselected package zlib1g-dev:armhf.
Preparing to unpack .../067-zlib1g-dev_1%3a1.2.8.dfsg-5_armhf.deb ...
Unpacking zlib1g-dev:armhf (1:1.2.8.dfsg-5) ...
Selecting previously unselected package libtasn1-6-dev:armhf.
Preparing to unpack .../068-libtasn1-6-dev_4.12-2_armhf.deb ...
Unpacking libtasn1-6-dev:armhf (4.12-2) ...
Selecting previously unselected package libp11-kit-dev:armhf.
Preparing to unpack .../069-libp11-kit-dev_0.23.3-5_armhf.deb ...
Unpacking libp11-kit-dev:armhf (0.23.3-5) ...
Selecting previously unselected package libidn11-dev.
Preparing to unpack .../070-libidn11-dev_1.33-1_armhf.deb ...
Unpacking libidn11-dev (1.33-1) ...
Selecting previously unselected package libgnutls28-dev:armhf.
Preparing to unpack .../071-libgnutls28-dev_3.5.8-6_armhf.deb ...
Unpacking libgnutls28-dev:armhf (3.5.8-6) ...
Selecting previously unselected package libeet-dev.
Preparing to unpack .../072-libeet-dev_1.8.6-2.5_armhf.deb ...
Unpacking libeet-dev (1.8.6-2.5) ...
Selecting previously unselected package libfribidi0:armhf.
Preparing to unpack .../073-libfribidi0_0.19.7-1_armhf.deb ...
Unpacking libfribidi0:armhf (0.19.7-1) ...
Selecting previously unselected package libgif7:armhf.
Preparing to unpack .../074-libgif7_5.1.4-0.4_armhf.deb ...
Unpacking libgif7:armhf (5.1.4-0.4) ...
Selecting previously unselected package libpng12-0:armhf.
Preparing to unpack .../075-libpng12-0_1.2.54-6_armhf.deb ...
Unpacking libpng12-0:armhf (1.2.54-6) ...
Selecting previously unselected package libtiff5:armhf.
Preparing to unpack .../076-libtiff5_4.0.8-2_armhf.deb ...
Unpacking libtiff5:armhf (4.0.8-2) ...
Selecting previously unselected package shared-mime-info.
Preparing to unpack .../077-shared-mime-info_1.8-1_armhf.deb ...
Unpacking shared-mime-info (1.8-1) ...
Selecting previously unselected package libgdk-pixbuf2.0-common.
Preparing to unpack .../078-libgdk-pixbuf2.0-common_2.36.5-2_all.deb ...
Unpacking libgdk-pixbuf2.0-common (2.36.5-2) ...
Selecting previously unselected package libgdk-pixbuf2.0-0:armhf.
Preparing to unpack .../079-libgdk-pixbuf2.0-0_2.36.5-2_armhf.deb ...
Unpacking libgdk-pixbuf2.0-0:armhf (2.36.5-2) ...
Selecting previously unselected package liblcms2-2:armhf.
Preparing to unpack .../080-liblcms2-2_2.8-4_armhf.deb ...
Unpacking liblcms2-2:armhf (2.8-4) ...
Selecting previously unselected package libraw15:armhf.
Preparing to unpack .../081-libraw15_0.17.2-6_armhf.deb ...
Unpacking libraw15:armhf (0.17.2-6) ...
Selecting previously unselected package libthai-data.
Preparing to unpack .../082-libthai-data_0.1.26-1_all.deb ...
Unpacking libthai-data (0.1.26-1) ...
Selecting previously unselected package libthai0:armhf.
Preparing to unpack .../083-libthai0_0.1.26-1_armhf.deb ...
Unpacking libthai0:armhf (0.1.26-1) ...
Selecting previously unselected package libpango-1.0-0:armhf.
Preparing to unpack .../084-libpango-1.0-0_1.40.5-1_armhf.deb ...
Unpacking libpango-1.0-0:armhf (1.40.5-1) ...
Selecting previously unselected package libgraphite2-3:armhf.
Preparing to unpack .../085-libgraphite2-3_1.3.10-2_armhf.deb ...
Unpacking libgraphite2-3:armhf (1.3.10-2) ...
Selecting previously unselected package libharfbuzz0b:armhf.
Preparing to unpack .../086-libharfbuzz0b_1.4.2-1_armhf.deb ...
Unpacking libharfbuzz0b:armhf (1.4.2-1) ...
Selecting previously unselected package libpangoft2-1.0-0:armhf.
Preparing to unpack .../087-libpangoft2-1.0-0_1.40.5-1_armhf.deb ...
Unpacking libpangoft2-1.0-0:armhf (1.40.5-1) ...
Selecting previously unselected package libpangocairo-1.0-0:armhf.
Preparing to unpack .../088-libpangocairo-1.0-0_1.40.5-1_armhf.deb ...
Unpacking libpangocairo-1.0-0:armhf (1.40.5-1) ...
Selecting previously unselected package librsvg2-2:armhf.
Preparing to unpack .../089-librsvg2-2_2.40.16-1_armhf.deb ...
Unpacking librsvg2-2:armhf (2.40.16-1) ...
Selecting previously unselected package libijs-0.35:armhf.
Preparing to unpack .../090-libijs-0.35_0.35-12_armhf.deb ...
Unpacking libijs-0.35:armhf (0.35-12) ...
Selecting previously unselected package libjbig2dec0:armhf.
Preparing to unpack .../091-libjbig2dec0_0.13-4.1_armhf.deb ...
Unpacking libjbig2dec0:armhf (0.13-4.1) ...
Selecting previously unselected package libopenjp2-7:armhf.
Preparing to unpack .../092-libopenjp2-7_2.1.2-1.1_armhf.deb ...
Unpacking libopenjp2-7:armhf (2.1.2-1.1) ...
Selecting previously unselected package libpaper1:armhf.
Preparing to unpack .../093-libpaper1_1.1.24+nmu5_armhf.deb ...
Unpacking libpaper1:armhf (1.1.24+nmu5) ...
Selecting previously unselected package libgs9-common.
Preparing to unpack .../094-libgs9-common_9.21~dfsg-1_all.deb ...
Unpacking libgs9-common (9.21~dfsg-1) ...
Selecting previously unselected package libgs9:armhf.
Preparing to unpack .../095-libgs9_9.21~dfsg-1_armhf.deb ...
Unpacking libgs9:armhf (9.21~dfsg-1) ...
Selecting previously unselected package libspectre1:armhf.
Preparing to unpack .../096-libspectre1_0.2.8-1_armhf.deb ...
Unpacking libspectre1:armhf (0.2.8-1) ...
Selecting previously unselected package libevas-loaders:armhf.
Preparing to unpack .../097-libevas-loaders_1.8.1-2+b2_armhf.deb ...
Unpacking libevas-loaders:armhf (1.8.1-2+b2) ...
Selecting previously unselected package libevas1:armhf.
Preparing to unpack .../098-libevas1_1.8.6-2.5_armhf.deb ...
Unpacking libevas1:armhf (1.8.6-2.5) ...
Selecting previously unselected package xorg-sgml-doctools.
Preparing to unpack .../099-xorg-sgml-doctools_1%3a1.11-1_all.deb ...
Unpacking xorg-sgml-doctools (1:1.11-1) ...
Selecting previously unselected package x11proto-core-dev.
Preparing to unpack .../100-x11proto-core-dev_7.0.31-1_all.deb ...
Unpacking x11proto-core-dev (7.0.31-1) ...
Selecting previously unselected package libxau-dev:armhf.
Preparing to unpack .../101-libxau-dev_1%3a1.0.8-1_armhf.deb ...
Unpacking libxau-dev:armhf (1:1.0.8-1) ...
Selecting previously unselected package libxdmcp-dev:armhf.
Preparing to unpack .../102-libxdmcp-dev_1%3a1.1.2-3_armhf.deb ...
Unpacking libxdmcp-dev:armhf (1:1.1.2-3) ...
Selecting previously unselected package x11proto-input-dev.
Preparing to unpack .../103-x11proto-input-dev_2.3.2-1_all.deb ...
Unpacking x11proto-input-dev (2.3.2-1) ...
Selecting previously unselected package x11proto-kb-dev.
Preparing to unpack .../104-x11proto-kb-dev_1.0.7-1_all.deb ...
Unpacking x11proto-kb-dev (1.0.7-1) ...
Selecting previously unselected package xtrans-dev.
Preparing to unpack .../105-xtrans-dev_1.3.5-1_all.deb ...
Unpacking xtrans-dev (1.3.5-1) ...
Selecting previously unselected package libpthread-stubs0-dev:armhf.
Preparing to unpack .../106-libpthread-stubs0-dev_0.3-4_armhf.deb ...
Unpacking libpthread-stubs0-dev:armhf (0.3-4) ...
Selecting previously unselected package libxcb1-dev:armhf.
Preparing to unpack .../107-libxcb1-dev_1.12-1_armhf.deb ...
Unpacking libxcb1-dev:armhf (1.12-1) ...
Selecting previously unselected package libx11-dev:armhf.
Preparing to unpack .../108-libx11-dev_2%3a1.6.4-3_armhf.deb ...
Unpacking libx11-dev:armhf (2:1.6.4-3) ...
Selecting previously unselected package libpng-dev:armhf.
Preparing to unpack .../109-libpng-dev_1.6.29-3_armhf.deb ...
Unpacking libpng-dev:armhf (1.6.29-3) ...
Selecting previously unselected package libfreetype6-dev.
Preparing to unpack .../110-libfreetype6-dev_2.6.3-3.2_armhf.deb ...
Unpacking libfreetype6-dev (2.6.3-3.2) ...
Selecting previously unselected package libexpat1-dev:armhf.
Preparing to unpack .../111-libexpat1-dev_2.2.1-1_armhf.deb ...
Unpacking libexpat1-dev:armhf (2.2.1-1) ...
Selecting previously unselected package libfontconfig1-dev:armhf.
Preparing to unpack .../112-libfontconfig1-dev_2.11.0-6.7_armhf.deb ...
Unpacking libfontconfig1-dev:armhf (2.11.0-6.7) ...
Selecting previously unselected package libfribidi-dev.
Preparing to unpack .../113-libfribidi-dev_0.19.7-1_armhf.deb ...
Unpacking libfribidi-dev (0.19.7-1) ...
Selecting previously unselected package libevas-dev.
Preparing to unpack .../114-libevas-dev_1.8.6-2.5_armhf.deb ...
Unpacking libevas-dev (1.8.6-2.5) ...
Selecting previously unselected package libgif-dev.
Preparing to unpack .../115-libgif-dev_5.1.4-0.4_armhf.deb ...
Unpacking libgif-dev (5.1.4-0.4) ...
Selecting previously unselected package libjbig-dev:armhf.
Preparing to unpack .../116-libjbig-dev_2.1-3.1_armhf.deb ...
Unpacking libjbig-dev:armhf (2.1-3.1) ...
Selecting previously unselected package liblzma-dev:armhf.
Preparing to unpack .../117-liblzma-dev_5.2.2-1.2_armhf.deb ...
Unpacking liblzma-dev:armhf (5.2.2-1.2) ...
Selecting previously unselected package libperl-dev.
Preparing to unpack .../118-libperl-dev_5.24.1-4_armhf.deb ...
Unpacking libperl-dev (5.24.1-4) ...
Selecting previously unselected package libpython2.7:armhf.
Preparing to unpack .../119-libpython2.7_2.7.13-2_armhf.deb ...
Unpacking libpython2.7:armhf (2.7.13-2) ...
Selecting previously unselected package libpython2.7-dev:armhf.
Preparing to unpack .../120-libpython2.7-dev_2.7.13-2_armhf.deb ...
Unpacking libpython2.7-dev:armhf (2.7.13-2) ...
Selecting previously unselected package libpython-dev:armhf.
Preparing to unpack .../121-libpython-dev_2.7.13-2_armhf.deb ...
Unpacking libpython-dev:armhf (2.7.13-2) ...
Selecting previously unselected package libpython-all-dev:armhf.
Preparing to unpack .../122-libpython-all-dev_2.7.13-2_armhf.deb ...
Unpacking libpython-all-dev:armhf (2.7.13-2) ...
Selecting previously unselected package libtiffxx5:armhf.
Preparing to unpack .../123-libtiffxx5_4.0.8-2_armhf.deb ...
Unpacking libtiffxx5:armhf (4.0.8-2) ...
Selecting previously unselected package libtiff5-dev:armhf.
Preparing to unpack .../124-libtiff5-dev_4.0.8-2_armhf.deb ...
Unpacking libtiff5-dev:armhf (4.0.8-2) ...
Selecting previously unselected package libxml2-utils.
Preparing to unpack .../125-libxml2-utils_2.9.4+dfsg1-2.2_armhf.deb ...
Unpacking libxml2-utils (2.9.4+dfsg1-2.2) ...
Selecting previously unselected package x11proto-render-dev.
Preparing to unpack .../126-x11proto-render-dev_2%3a0.11.1-2_all.deb ...
Unpacking x11proto-render-dev (2:0.11.1-2) ...
Selecting previously unselected package libxrender-dev:armhf.
Preparing to unpack .../127-libxrender-dev_1%3a0.9.10-1_armhf.deb ...
Unpacking libxrender-dev:armhf (1:0.9.10-1) ...
Selecting previously unselected package libxslt1.1:armhf.
Preparing to unpack .../128-libxslt1.1_1.1.29-2.1_armhf.deb ...
Unpacking libxslt1.1:armhf (1.1.29-2.1) ...
Selecting previously unselected package python-all.
Preparing to unpack .../129-python-all_2.7.13-2_armhf.deb ...
Unpacking python-all (2.7.13-2) ...
Selecting previously unselected package python2.7-dev.
Preparing to unpack .../130-python2.7-dev_2.7.13-2_armhf.deb ...
Unpacking python2.7-dev (2.7.13-2) ...
Selecting previously unselected package python-dev.
Preparing to unpack .../131-python-dev_2.7.13-2_armhf.deb ...
Unpacking python-dev (2.7.13-2) ...
Selecting previously unselected package python-all-dev.
Preparing to unpack .../132-python-all-dev_2.7.13-2_armhf.deb ...
Unpacking python-all-dev (2.7.13-2) ...
Selecting previously unselected package swig3.0.
Preparing to unpack .../133-swig3.0_3.0.10-1.1_armhf.deb ...
Unpacking swig3.0 (3.0.10-1.1) ...
Selecting previously unselected package swig.
Preparing to unpack .../134-swig_3.0.10-1.1_armhf.deb ...
Unpacking swig (3.0.10-1.1) ...
Selecting previously unselected package xsltproc.
Preparing to unpack .../135-xsltproc_1.1.29-2.1_armhf.deb ...
Unpacking xsltproc (1.1.29-2.1) ...
Selecting previously unselected package sbuild-build-depends-exactimage-dummy.
Preparing to unpack .../136-sbuild-build-depends-exactimage-dummy_0.invalid.0_armhf.deb ...
Unpacking sbuild-build-depends-exactimage-dummy (0.invalid.0) ...
Setting up libgs9-common (9.21~dfsg-1) ...
Setting up perl-modules-5.24 (5.24.1-4) ...
Setting up libperl5.24:armhf (5.24.1-4) ...
Setting up libnettle6:armhf (3.3-1) ...
Setting up libopenjp2-7:armhf (2.1.2-1.1) ...
Setting up libjpeg62-turbo:armhf (1:1.5.1-2) ...
Setting up swig3.0 (3.0.10-1.1) ...
Setting up mime-support (3.60) ...
Setting up libpng16-16:armhf (1.6.29-3) ...
Setting up liblcms2-2:armhf (2.8-4) ...
Setting up libjbig0:armhf (2.1-3.1) ...
Setting up libsigsegv2:armhf (2.10-5) ...
Setting up libpthread-stubs0-dev:armhf (0.3-4) ...
Setting up fonts-dejavu-core (2.37-1) ...
Setting up poppler-data (0.4.7-8) ...
Setting up groff-base (1.22.3-9) ...
Setting up xorg-sgml-doctools (1:1.11-1) ...
Setting up libagg-dev (2.5+dfsg1-12) ...
Setting up libgdk-pixbuf2.0-common (2.36.5-2) ...
Setting up libdatrie1:armhf (0.2.10-4) ...
Setting up libtiff5:armhf (4.0.8-2) ...
Setting up gettext-base (0.19.8.1-2) ...
Setting up libgif7:armhf (5.1.4-0.4) ...
Setting up libpipeline1:armhf (1.4.1-2) ...
Setting up x11proto-kb-dev (1.0.7-1) ...
Setting up m4 (1.4.18-1) ...
Setting up sgml-base (1.29) ...
Setting up libicu57:armhf (57.1-6) ...
Setting up libeina1:armhf (1.8.6-2.5) ...
Setting up libbsd0:armhf (0.8.3-1) ...
Setting up libpng12-0:armhf (1.2.54-6) ...
Setting up ucf (3.0036) ...
Setting up libxml2:armhf (2.9.4+dfsg1-2.2) ...
Setting up libfreetype6:armhf (2.6.3-3.2) ...
Setting up libtasn1-6:armhf (4.12-2) ...
Setting up libmagic-mgc (1:5.30-1) ...
Setting up libmagic1:armhf (1:5.30-1) ...
Setting up libhogweed4:armhf (3.3-1) ...
Setting up libgraphite2-3:armhf (1.3.10-2) ...
Setting up libjbig-dev:armhf (2.1-3.1) ...
Setting up libxslt1.1:armhf (1.1.29-2.1) ...
Setting up perl (5.24.1-4) ...
Setting up libilmbase12:armhf (2.2.0-12) ...
Setting up libjbig2dec0:armhf (0.13-4.1) ...
Setting up libpixman-1-0:armhf (0.34.0-1) ...
Setting up xtrans-dev (1.3.5-1) ...
Processing triggers for libc-bin (2.24-11+deb9u1) ...
Setting up autotools-dev (20161112.1) ...
Setting up libunistring0:armhf (0.9.6+really0.9.3-0.1) ...
Setting up libijs-0.35:armhf (0.35-12) ...
Setting up libtiffxx5:armhf (4.0.8-2) ...
Setting up libfribidi0:armhf (0.19.7-1) ...
Setting up libexpat1-dev:armhf (2.2.1-1) ...
Setting up libffi6:armhf (3.2.1-6) ...
Setting up libthai-data (0.1.26-1) ...
Setting up libjpeg62-turbo-dev:armhf (1:1.5.1-2) ...
Setting up liblzma-dev:armhf (5.2.2-1.2) ...
Setting up libxdmcp6:armhf (1:1.1.2-3) ...
Setting up xml-core (0.17) ...
Setting up libkeyutils1:armhf (1.5.9-9) ...
Setting up bsdmainutils (9.0.12+nmu1) ...
update-alternatives: using /usr/bin/bsd-write to provide /usr/bin/write (write) in auto mode
update-alternatives: using /usr/bin/bsd-from to provide /usr/bin/from (from) in auto mode
Setting up libgmpxx4ldbl:armhf (2:6.1.2+dfsg-1) ...
Setting up libx11-data (2:1.6.4-3) ...
Setting up libpython2.7-stdlib:armhf (2.7.13-2) ...
Setting up libxau6:armhf (1:1.0.8-1) ...
Setting up autopoint (0.19.8.1-2) ...
Setting up libmpdec2:armhf (2.4.2-1) ...
Setting up libavahi-common-data:armhf (0.6.32-2) ...
Setting up zlib1g-dev:armhf (1:1.2.8.dfsg-5) ...
Setting up libgmp-dev:armhf (2:6.1.2+dfsg-1) ...
Setting up libraw15:armhf (0.17.2-6) ...
Setting up libpaper1:armhf (1.1.24+nmu5) ...

Creating config file /etc/papersize with new version
Setting up libunbound2:armhf (1.6.0-3) ...
Setting up swig (3.0.10-1.1) ...
Setting up fontconfig-config (2.11.0-6.7) ...
Setting up libperl-dev (5.24.1-4) ...
Setting up libarchive-zip-perl (1.59-1) ...
Setting up x11proto-core-dev (7.0.31-1) ...
Setting up libilmbase-dev (2.2.0-12) ...
Setting up libtimedate-perl (2.3000-2) ...
Setting up libgif-dev (5.1.4-0.4) ...
Setting up libglib2.0-0:armhf (2.50.3-2) ...
No schema files found: doing nothing.
Setting up libpython3.5-stdlib:armhf (3.5.3-3) ...
Setting up libtiff5-dev:armhf (4.0.8-2) ...
Setting up libxml2-utils (2.9.4+dfsg1-2.2) ...
Setting up python2.7 (2.7.13-2) ...
Setting up libtasn1-6-dev:armhf (4.12-2) ...
Setting up libharfbuzz0b:armhf (1.4.2-1) ...
Setting up libxau-dev:armhf (1:1.0.8-1) ...
Setting up xsltproc (1.1.29-2.1) ...
Setting up autoconf (2.69-10) ...
Setting up libthai0:armhf (0.1.26-1) ...
Setting up libopenexr22:armhf (2.2.0-11) ...
Setting up file (1:5.30-1) ...
Setting up libkrb5support0:armhf (1.15-1) ...
Setting up libcroco3:armhf (0.6.11-3) ...
Setting up libpython-stdlib:armhf (2.7.13-2) ...
Setting up pkg-config (0.29-4) ...
Setting up libxdmcp-dev:armhf (1:1.1.2-3) ...
Setting up libjpeg-dev (1:1.5.1-2) ...
Setting up libfribidi-dev (0.19.7-1) ...
Setting up libp11-kit0:armhf (0.23.3-5) ...
Setting up libpython2.7:armhf (2.7.13-2) ...
Setting up automake (1:1.15-6) ...
update-alternatives: using /usr/bin/automake-1.15 to provide /usr/bin/automake (automake) in auto mode
Setting up libopenexr-dev (2.2.0-11) ...
Setting up man-db (2.7.6.1-2) ...
Not building database; man-db/auto-update is not 'true'.
Setting up shared-mime-info (1.8-1) ...
Setting up nettle-dev (3.3-1) ...
Setting up libpython2.7-dev:armhf (2.7.13-2) ...
Setting up libavahi-common3:armhf (0.6.32-2) ...
Setting up libpng-dev:armhf (1.6.29-3) ...
Setting up x11proto-render-dev (2:0.11.1-2) ...
Setting up python2.7-dev (2.7.13-2) ...
Setting up libxcb1:armhf (1.12-1) ...
Setting up x11proto-input-dev (2.3.2-1) ...
Setting up python (2.7.13-2) ...
Setting up libidn11-dev (1.33-1) ...
Setting up libfile-stripnondeterminism-perl (0.034-1) ...
Setting up libeina-dev (1.8.6-2.5) ...
Setting up libtool (2.4.6-2) ...
Setting up python3.5 (3.5.3-3) ...
Setting up libpython3-stdlib:armhf (3.5.3-1) ...
Setting up libpython-dev:armhf (2.7.13-2) ...
Setting up libfontconfig1:armhf (2.11.0-6.7) ...
Setting up libk5crypto3:armhf (1.15-1) ...
Setting up libxcb-render0:armhf (1.12-1) ...
Setting up gettext (0.19.8.1-2) ...
Setting up python-dev (2.7.13-2) ...
Setting up libgnutls30:armhf (3.5.8-6) ...
Setting up libx11-6:armhf (2:1.6.4-3) ...
Setting up libpython-all-dev:armhf (2.7.13-2) ...
Setting up libp11-kit-dev:armhf (0.23.3-5) ...
Setting up libeet1:armhf (1.8.6-2.5) ...
Setting up intltool-debian (0.35.0+20060710.4) ...
Setting up libgnutlsxx28:armhf (3.5.8-6) ...
Setting up libfreetype6-dev (2.6.3-3.2) ...
Setting up libgnutls-dane0:armhf (3.5.8-6) ...
Setting up libgnutls-openssl27:armhf (3.5.8-6) ...
Setting up libxcb-shm0:armhf (1.12-1) ...
Setting up libxrender1:armhf (1:0.9.10-1) ...
Setting up libxcb1-dev:armhf (1.12-1) ...
Setting up libavahi-client3:armhf (0.6.32-2) ...
Setting up libkrb5-3:armhf (1.15-1) ...
Setting up libx11-dev:armhf (2:1.6.4-3) ...
Setting up python-all (2.7.13-2) ...
Setting up fontconfig (2.11.0-6.7) ...
Regenerating fonts cache... done.
Setting up libfontconfig1-dev:armhf (2.11.0-6.7) ...
Setting up libxext6:armhf (2:1.3.3-1) ...
Setting up po-debconf (1.0.20) ...
Setting up libgdk-pixbuf2.0-0:armhf (2.36.5-2) ...
Setting up libxrender-dev:armhf (1:0.9.10-1) ...
Setting up libgnutls28-dev:armhf (3.5.8-6) ...
Setting up libgssapi-krb5-2:armhf (1.15-1) ...
Setting up python-all-dev (2.7.13-2) ...
Setting up libpango-1.0-0:armhf (1.40.5-1) ...
Setting up libcups2:armhf (2.2.3-2+rpi1) ...
Setting up libcairo2:armhf (1.14.8-1) ...
Setting up libeet-dev (1.8.6-2.5) ...
Setting up libpangoft2-1.0-0:armhf (1.40.5-1) ...
Setting up libcupsimage2:armhf (2.2.3-2+rpi1) ...
Setting up libgs9:armhf (9.21~dfsg-1) ...
Setting up libspectre1:armhf (0.2.8-1) ...
Setting up libpangocairo-1.0-0:armhf (1.40.5-1) ...
Setting up librsvg2-2:armhf (2.40.16-1) ...
Setting up libevas-loaders:armhf (1.8.1-2+b2) ...
Setting up libevas1:armhf (1.8.6-2.5) ...
Setting up libevas-dev (1.8.6-2.5) ...
Processing triggers for sgml-base (1.29) ...
Setting up sgml-data (2.0.10) ...
Setting up docbook-xsl (1.79.1+dfsg-2) ...
Processing triggers for sgml-base (1.29) ...
Setting up docbook-xml (4.5-8) ...
Processing triggers for sgml-base (1.29) ...
Setting up dh-python (2.20170125) ...
Setting up dh-autoreconf (14) ...
Setting up python3 (3.5.3-1) ...
Setting up debhelper (10.2.5) ...
Setting up dh-strip-nondeterminism (0.034-1) ...
Setting up sbuild-build-depends-exactimage-dummy (0.invalid.0) ...
Processing triggers for libc-bin (2.24-11+deb9u1) ...
W: No sandbox user '_apt' on the system, can not drop privileges

+------------------------------------------------------------------------------+
| Build environment                                                            |
+------------------------------------------------------------------------------+

Kernel: Linux 4.9.0-0.bpo.2-armmp armhf (armv7l)
Toolchain package versions: binutils_2.28-5 dpkg-dev_1.18.24 g++-6_6.3.0-18+rpi1 gcc-6_6.3.0-18+rpi1 libc6-dev_2.24-11+deb9u1 libstdc++-6-dev_6.3.0-18+rpi1 libstdc++6_6.3.0-18+rpi1 linux-libc-dev_3.18.5-1~exp1+rpi19+stretch
Package versions: adduser_3.115 apt_1.4.6 autoconf_2.69-10 automake_1:1.15-6 autopoint_0.19.8.1-2 autotools-dev_20161112.1 base-files_9.9+rpi1 base-passwd_3.5.43 bash_4.4-5 binutils_2.28-5 bsdmainutils_9.0.12+nmu1 bsdutils_1:2.29.2-1 build-essential_12.3 bzip2_1.0.6-8.1 coreutils_8.26-3 cpio_2.11+dfsg-6 cpp_4:6.3.0-4 cpp-6_6.3.0-18+rpi1 dash_0.5.8-2.4 debconf_1.5.61 debhelper_10.2.5 debianutils_4.8.1.1 dh-autoreconf_14 dh-python_2.20170125 dh-strip-nondeterminism_0.034-1 diffutils_1:3.5-3 dmsetup_2:1.02.137-2 docbook-xml_4.5-8 docbook-xsl_1.79.1+dfsg-2 dpkg_1.18.24 dpkg-dev_1.18.24 e2fslibs_1.43.4-2 e2fsprogs_1.43.4-2 fakeroot_1.21-3.1 file_1:5.30-1 findutils_4.6.0+git+20161106-2 fontconfig_2.11.0-6.7 fontconfig-config_2.11.0-6.7 fonts-dejavu-core_2.37-1 g++_4:6.3.0-4 g++-6_6.3.0-18+rpi1 gcc_4:6.3.0-4 gcc-4.6-base_4.6.4-5+rpi1 gcc-4.7-base_4.7.3-11+rpi1 gcc-4.8-base_4.8.5-4 gcc-4.9-base_4.9.3-14 gcc-5-base_5.4.1-4 gcc-6_6.3.0-18+rpi1 gcc-6-base_6.3.0-18+rpi1 gettext_0.19.8.1-2 gettext-base_0.19.8.1-2 gnupg_2.1.18-6 gnupg-agent_2.1.18-6 gpgv_2.1.18-6 grep_2.27-2 groff-base_1.22.3-9 gzip_1.6-5 hostname_3.18 init-system-helpers_1.48 initramfs-tools_0.130 initramfs-tools-core_0.130 intltool-debian_0.35.0+20060710.4 klibc-utils_2.0.4-9+rpi1 kmod_23-2 libacl1_2.2.52-3 libagg-dev_2.5+dfsg1-12 libapparmor1_2.11.0-3 libapt-pkg5.0_1.4.6 libarchive-zip-perl_1.59-1 libasan3_6.3.0-18+rpi1 libassuan0_2.4.3-2 libatomic1_6.3.0-18+rpi1 libattr1_1:2.4.47-2 libaudit-common_1:2.6.7-2 libaudit1_1:2.6.7-2 libavahi-client3_0.6.32-2 libavahi-common-data_0.6.32-2 libavahi-common3_0.6.32-2 libblkid1_2.29.2-1 libbsd0_0.8.3-1 libbz2-1.0_1.0.6-8.1 libc-bin_2.24-11+deb9u1 libc-dev-bin_2.24-11+deb9u1 libc6_2.24-11+deb9u1 libc6-dev_2.24-11+deb9u1 libcairo2_1.14.8-1 libcap-ng0_0.7.7-3 libcap2_1:2.25-1 libcc1-0_6.3.0-18+rpi1 libcomerr2_1.43.4-2 libcroco3_0.6.11-3 libcryptsetup4_2:1.7.3-4 libcups2_2.2.3-2+rpi1 libcupsimage2_2.2.3-2+rpi1 libdatrie1_0.2.10-4 libdb5.3_5.3.28-12 libdbus-1-3_1.10.18-1 libdebconfclient0_0.227 libdevmapper1.02.1_2:1.02.137-2 libdpkg-perl_1.18.24 libdrm2_2.4.74-1 libeet-dev_1.8.6-2.5 libeet1_1.8.6-2.5 libeina-dev_1.8.6-2.5 libeina1_1.8.6-2.5 libevas-dev_1.8.6-2.5 libevas-loaders_1.8.1-2+b2 libevas1_1.8.6-2.5 libexpat1_2.2.1-1 libexpat1-dev_2.2.1-1 libfakeroot_1.21-3.1 libfdisk1_2.29.2-1 libffi6_3.2.1-6 libfile-stripnondeterminism-perl_0.034-1 libfontconfig1_2.11.0-6.7 libfontconfig1-dev_2.11.0-6.7 libfreetype6_2.6.3-3.2 libfreetype6-dev_2.6.3-3.2 libfribidi-dev_0.19.7-1 libfribidi0_0.19.7-1 libgcc-6-dev_6.3.0-18+rpi1 libgcc1_1:6.3.0-18+rpi1 libgcrypt20_1.7.6-2 libgdbm3_1.8.3-14 libgdk-pixbuf2.0-0_2.36.5-2 libgdk-pixbuf2.0-common_2.36.5-2 libgif-dev_5.1.4-0.4 libgif7_5.1.4-0.4 libglib2.0-0_2.50.3-2 libgmp-dev_2:6.1.2+dfsg-1 libgmp10_2:6.1.2+dfsg-1 libgmpxx4ldbl_2:6.1.2+dfsg-1 libgnutls-dane0_3.5.8-6 libgnutls-openssl27_3.5.8-6 libgnutls28-dev_3.5.8-6 libgnutls30_3.5.8-6 libgnutlsxx28_3.5.8-6 libgomp1_6.3.0-18+rpi1 libgpg-error0_1.26-2 libgraphite2-3_1.3.10-2 libgs9_9.21~dfsg-1 libgs9-common_9.21~dfsg-1 libgssapi-krb5-2_1.15-1 libharfbuzz0b_1.4.2-1 libhogweed4_3.3-1 libicu57_57.1-6 libidn11_1.33-1 libidn11-dev_1.33-1 libijs-0.35_0.35-12 libilmbase-dev_2.2.0-12 libilmbase12_2.2.0-12 libip4tc0_1.6.0+snapshot20161117-6 libisl15_0.18-1 libjbig-dev_2.1-3.1 libjbig0_2.1-3.1 libjbig2dec0_0.13-4.1 libjpeg-dev_1:1.5.1-2 libjpeg62-turbo_1:1.5.1-2 libjpeg62-turbo-dev_1:1.5.1-2 libk5crypto3_1.15-1 libkeyutils1_1.5.9-9 libklibc_2.0.4-9+rpi1 libkmod2_23-2 libkrb5-3_1.15-1 libkrb5support0_1.15-1 libksba8_1.3.5-2 liblcms2-2_2.8-4 liblocale-gettext-perl_1.07-3+b1 liblz4-1_0.0~r131-2 liblzma-dev_5.2.2-1.2 liblzma5_5.2.2-1.2 libmagic-mgc_1:5.30-1 libmagic1_1:5.30-1 libmount1_2.29.2-1 libmpc3_1.0.3-1 libmpdec2_2.4.2-1 libmpfr4_3.1.5-1 libncurses5_6.0+20161126-1 libncursesw5_6.0+20161126-1 libnettle6_3.3-1 libnih-dbus1_1.0.3-8 libnih1_1.0.3-8 libnpth0_1.3-1 libopenexr-dev_2.2.0-11 libopenexr22_2.2.0-11 libopenjp2-7_2.1.2-1.1 libp11-kit-dev_0.23.3-5 libp11-kit0_0.23.3-5 libpam-modules_1.1.8-3.6 libpam-modules-bin_1.1.8-3.6 libpam-runtime_1.1.8-3.6 libpam0g_1.1.8-3.6 libpango-1.0-0_1.40.5-1 libpangocairo-1.0-0_1.40.5-1 libpangoft2-1.0-0_1.40.5-1 libpaper1_1.1.24+nmu5 libpcre3_2:8.39-3 libperl-dev_5.24.1-4 libperl5.24_5.24.1-4 libpipeline1_1.4.1-2 libpixman-1-0_0.34.0-1 libplymouth4_0.9.2-4 libpng-dev_1.6.29-3 libpng12-0_1.2.54-6 libpng16-16_1.6.29-3 libprocps6_2:3.3.12-3 libpthread-stubs0-dev_0.3-4 libpython-all-dev_2.7.13-2 libpython-dev_2.7.13-2 libpython-stdlib_2.7.13-2 libpython2.7_2.7.13-2 libpython2.7-dev_2.7.13-2 libpython2.7-minimal_2.7.13-2 libpython2.7-stdlib_2.7.13-2 libpython3-stdlib_3.5.3-1 libpython3.5-minimal_3.5.3-3 libpython3.5-stdlib_3.5.3-3 libraw15_0.17.2-6 libreadline7_7.0-3 librsvg2-2_2.40.16-1 libseccomp2_2.3.1-2.1 libselinux1_2.6-3 libsemanage-common_2.6-2 libsemanage1_2.6-2 libsepol1_2.6-2 libsigsegv2_2.10-5 libsmartcols1_2.29.2-1 libspectre1_0.2.8-1 libsqlite3-0_3.16.2-5 libss2_1.43.4-2 libssl1.1_1.1.0f-3 libstdc++-6-dev_6.3.0-18+rpi1 libstdc++6_6.3.0-18+rpi1 libsystemd0_232-25 libtasn1-6_4.12-2 libtasn1-6-dev_4.12-2 libtext-charwidth-perl_0.04-7+b7 libtext-iconv-perl_1.7-5+b8 libtext-wrapi18n-perl_0.06-7.1 libthai-data_0.1.26-1 libthai0_0.1.26-1 libtiff5_4.0.8-2 libtiff5-dev_4.0.8-2 libtiffxx5_4.0.8-2 libtimedate-perl_2.3000-2 libtinfo5_6.0+20161126-1 libtool_2.4.6-2 libubsan0_6.3.0-18+rpi1 libudev1_232-25 libunbound2_1.6.0-3 libunistring0_0.9.6+really0.9.3-0.1 libustr-1.0-1_1.0.4-6 libuuid1_2.29.2-1 libx11-6_2:1.6.4-3 libx11-data_2:1.6.4-3 libx11-dev_2:1.6.4-3 libxau-dev_1:1.0.8-1 libxau6_1:1.0.8-1 libxcb-render0_1.12-1 libxcb-shm0_1.12-1 libxcb1_1.12-1 libxcb1-dev_1.12-1 libxdmcp-dev_1:1.1.2-3 libxdmcp6_1:1.1.2-3 libxext6_2:1.3.3-1 libxml2_2.9.4+dfsg1-2.2 libxml2-utils_2.9.4+dfsg1-2.2 libxrender-dev_1:0.9.10-1 libxrender1_1:0.9.10-1 libxslt1.1_1.1.29-2.1 linux-base_4.5 linux-libc-dev_3.18.5-1~exp1+rpi19+stretch login_1:4.4-4.1 lsb-base_9.20161125+rpi1 m4_1.4.18-1 make_4.1-9.1 makedev_2.3.1-93 man-db_2.7.6.1-2 mawk_1.3.3-17 mime-support_3.60 mount_2.29.2-1 mountall_2.54 multiarch-support_2.24-11+deb9u1 ncurses-base_6.0+20161126-1 ncurses-bin_6.0+20161126-1 nettle-dev_3.3-1 passwd_1:4.4-4.1 patch_2.7.5-1 perl_5.24.1-4 perl-base_5.24.1-4 perl-modules-5.24_5.24.1-4 pinentry-curses_1.0.0-2 pkg-config_0.29-4 plymouth_0.9.2-4 po-debconf_1.0.20 poppler-data_0.4.7-8 procps_2:3.3.12-3 python_2.7.13-2 python-all_2.7.13-2 python-all-dev_2.7.13-2 python-dev_2.7.13-2 python-minimal_2.7.13-2 python2.7_2.7.13-2 python2.7-dev_2.7.13-2 python2.7-minimal_2.7.13-2 python3_3.5.3-1 python3-minimal_3.5.3-1 python3.5_3.5.3-3 python3.5-minimal_3.5.3-3 raspbian-archive-keyring_20120528.2 readline-common_7.0-3 sbuild-build-depends-core-dummy_0.invalid.0 sbuild-build-depends-exactimage-dummy_0.invalid.0 sed_4.4-1 sensible-utils_0.0.9 sgml-base_1.29 sgml-data_2.0.10 shared-mime-info_1.8-1 swig_3.0.10-1.1 swig3.0_3.0.10-1.1 systemd_232-25 sysvinit-utils_2.88dsf-59.9 tar_1.29b-1.1 tzdata_2017b-1 ucf_3.0036 udev_232-25 util-linux_2.29.2-1 x11proto-core-dev_7.0.31-1 x11proto-input-dev_2.3.2-1 x11proto-kb-dev_1.0.7-1 x11proto-render-dev_2:0.11.1-2 xml-core_0.17 xorg-sgml-doctools_1:1.11-1 xsltproc_1.1.29-2.1 xtrans-dev_1.3.5-1 xz-utils_5.2.2-1.2 zlib1g_1:1.2.8.dfsg-5 zlib1g-dev_1:1.2.8.dfsg-5

+------------------------------------------------------------------------------+
| Build                                                                        |
+------------------------------------------------------------------------------+


Unpack source
-------------

gpgv: unknown type of key resource 'trustedkeys.kbx'
gpgv: keyblock resource '/sbuild-nonexistent/.gnupg/trustedkeys.kbx': General error
gpgv: Signature made Thu Jun 22 07:51:46 2017 UTC
gpgv:                using RSA key 175D2B87612573DCE332E0025D870A07C1267B46
gpgv: Can't check signature: No public key
dpkg-source: warning: failed to verify signature on ./exactimage_0.9.2-1.dsc
dpkg-source: info: extracting exactimage in /<<PKGBUILDDIR>>
dpkg-source: info: unpacking exactimage_0.9.2.orig.tar.bz2
dpkg-source: info: unpacking exactimage_0.9.2-1.debian.tar.xz
dpkg-source: info: applying Respect-CFLAGS-from-the-environment.patch
dpkg-source: info: applying Use-PIC-version-of-static-AGG-library.patch
dpkg-source: info: applying Disable-dead-code-that-is-causing-compilation-errors.patch
dpkg-source: info: applying Remove-dead-timer-code-which-causes-FTBFS.patch
dpkg-source: info: applying Enforce-simple-verbose-build-for-blhc.patch
dpkg-source: info: applying Avoid-infinite-loops-generated-by-GCC-4.8-caused-by-.patch
dpkg-source: info: applying Disable-unused-Evas-Helper-function-to-avoid-FTBFS.patch
dpkg-source: info: applying Install-module-to-perl-vendor-path.patch
dpkg-source: info: applying Fix-buffer-overflow-when-decoding-code128-code_set_c.patch
dpkg-source: info: applying Drop-date-to-make-build-reproducible.patch
dpkg-source: info: applying giflib5.patch
dpkg-source: info: applying Fix-FTBFS-when-building-with-swig-3.0.7.patch
dpkg-source: info: applying Build-as-C-98-code-to-avoid-errors-when-compiling-as-C-11.patch
dpkg-source: info: applying Fix-typo-s-optinally-optionally.patch
dpkg-source: info: applying Don-t-compile-dynamic-shared-objects-as-PIE.patch
dpkg-source: info: applying Fix-CVE-2015-8366-Index-overflow-in-smal_decode_segment.patch
dpkg-source: info: applying Fix-typo-s-sufficently-sufficiently.patch
dpkg-source: info: applying Remove-obsolete-path-reorientation-code-fixes-nonzero-fil.patch

Check disc space
----------------

Sufficient free space for build

User Environment
----------------

APT_CONFIG=/var/lib/sbuild/apt.conf
DEB_BUILD_OPTIONS=parallel=4
HOME=/sbuild-nonexistent
LC_ALL=POSIX
LOGNAME=root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
SCHROOT_ALIAS_NAME=buster-staging-armhf-sbuild
SCHROOT_CHROOT_NAME=buster-staging-armhf-sbuild
SCHROOT_COMMAND=env
SCHROOT_GID=109
SCHROOT_GROUP=buildd
SCHROOT_SESSION_ID=buster-staging-armhf-sbuild-4e03235f-f5e2-4eec-b3f8-fbb0aafce692
SCHROOT_UID=104
SCHROOT_USER=buildd
SHELL=/bin/sh
TERM=xterm
USER=buildd

dpkg-buildpackage
-----------------

dpkg-buildpackage: info: source package exactimage
dpkg-buildpackage: info: source version 0.9.2-1
dpkg-buildpackage: info: source distribution unstable
 dpkg-source --before-build exactimage-0.9.2
dpkg-buildpackage: info: host architecture armhf
 fakeroot debian/rules clean
dh clean --parallel --list-missing --with=python2
   dh_testdir -O--parallel -O--list-missing
   debian/rules override_dh_auto_clean
make[1]: Entering directory '/<<PKGBUILDDIR>>'
touch config.make
dh_auto_clean -- X_SYSTEM=Linux Q=
	make -j4 clean X_SYSTEM=Linux Q=
make[2]: Entering directory '/<<PKGBUILDDIR>>'
rm -rf ./objdir
make[2]: Leaving directory '/<<PKGBUILDDIR>>'
make[1]: Leaving directory '/<<PKGBUILDDIR>>'
   dh_clean -O--parallel -O--list-missing
 debian/rules build-arch
dh build-arch --parallel --list-missing --with=python2
   dh_testdir -a -O--parallel -O--list-missing
   dh_update_autotools_config -a -O--parallel -O--list-missing
   debian/rules override_dh_auto_configure
make[1]: Entering directory '/<<PKGBUILDDIR>>'
./configure --prefix=/usr --includedir=/usr/include --mandir=/usr/share/man --infodir=/usr/share/info --sysconfdir=/etc --libdir=/usr/lib --libexecdir=/usr/lib --with-ruby=no --with-php=no
checking whether the C++ compiler works ... yes
checking for C++ STL support ... yes
checking for C++ templates ... yes
checking for C++ template specialization ... yes
checking for C++ partial template specialization ... yes
checking whether C++ supports templates ... yes
checking for header iostream ... found
checking for header string ... found
checking for header iostream ... found
checking for header sstream ... found
checking for header fstream ... found
checking for package x11 (atleast 11.0) ... yes (11.0)
checking for package libagg (atleast 2.3) ... yes (2.5.0)
checking for package freetype2 (atleast 9.5.0) ... yes (18.3.12)
checking for package evas (atleast 0.9.9) ... yes (1.8.6)
checking for header Evas_Engine_GL_X11.h ... found
checking for package libjpeg  ... yes
checking for package libtiff  ... yes
checking for package libpng (atleast 1.2) ... yes (1.6.29)
checking for package libgif  ... yes
checking for package jasper  ... no
checking for package expat  ... yes
checking for package OpenEXR (atleast 1.2.0) ... yes (2.2.0)
checking for package lcms (atleast 1.10) ... no
checking for package bardecode  ... no
For optional, proprietary barcode recognition, place it in 'external/'.

checking for package swig (atleast 1.3.32) ... yes (3.0.10)
checking for package lua (atleast 5.1) ... no
checking for package perl (atleast 5.8.0) ... yes (5.24.1)
checking for package php (atleast 5.2.0) ... disabled
checking for package python (atleast 2.5.0) ... yes (2.7.13)
checking for package ruby (atleast 1.8.5) ... disabled
make[1]: Leaving directory '/<<PKGBUILDDIR>>'
   debian/rules override_dh_auto_build
make[1]: Entering directory '/<<PKGBUILDDIR>>'
mkdir -p objdir/api/python/
touch objdir/api/python/_ExactImage.so # prevent from being built this time
dh_auto_build -- all X_SYSTEM=Linux Q=
	make -j4 all X_SYSTEM=Linux Q=
make[2]: Entering directory '/<<PKGBUILDDIR>>'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/Colorspace.d' -o 'objdir/image/Colorspace.o' 'image/Colorspace.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/ContourMatching.d' -o 'objdir/image/ContourMatching.o' 'image/ContourMatching.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/ContourUtility.d' -o 'objdir/image/ContourUtility.o' 'image/ContourUtility.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/Contours.d' -o 'objdir/image/Contours.o' 'image/Contours.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/DistanceMatrix.d' -o 'objdir/image/DistanceMatrix.o' 'image/DistanceMatrix.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/FG-Matrix.d' -o 'objdir/image/FG-Matrix.o' 'image/FG-Matrix.cc'
In file included from /usr/include/c++/6/vector:69:0,
                 from image/Contours.hh:23,
                 from image/ContourUtility.hh:1,
                 from image/ContourMatching.hh:1,
                 from image/ContourMatching.cc:5:
/usr/include/c++/6/bits/vector.tcc: In member function 'void std::vector<_Tp, _Alloc>::_M_fill_insert(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = LogoRepresentation::ImageContourData; _Alloc = std::allocator<LogoRepresentation::ImageContourData>]':
/usr/include/c++/6/bits/vector.tcc:449:5: note: parameter passing for argument of type 'std::vector<LogoRepresentation::ImageContourData>::iterator {aka __gnu_cxx::__normal_iterator<LogoRepresentation::ImageContourData*, std::vector<LogoRepresentation::ImageContourData> >}' will change in GCC 7.1
     vector<_Tp, _Alloc>::
     ^~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/bits/vector.tcc:449:5: note: parameter passing for argument of type 'std::vector<LogoRepresentation::ImageContourData>::iterator {aka __gnu_cxx::__normal_iterator<LogoRepresentation::ImageContourData*, std::vector<LogoRepresentation::ImageContourData> >}' will change in GCC 7.1
In file included from /usr/include/c++/6/vector:64:0,
                 from image/Contours.hh:23,
                 from image/ContourUtility.hh:1,
                 from image/ContourMatching.hh:1,
                 from image/ContourMatching.cc:5:
/usr/include/c++/6/bits/stl_vector.h: In member function 'double LogoRepresentation::Score(Contours*)':
/usr/include/c++/6/bits/stl_vector.h:1074:9: note: parameter passing for argument of type 'std::vector<LogoRepresentation::ImageContourData>::iterator {aka __gnu_cxx::__normal_iterator<LogoRepresentation::ImageContourData*, std::vector<LogoRepresentation::ImageContourData> >}' will change in GCC 7.1
       { _M_fill_insert(__position, __n, __x); }
         ^~~~~~~~~~~~~~
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/GaussianBlur.d' -o 'objdir/image/GaussianBlur.o' 'image/GaussianBlur.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/Image.d' -o 'objdir/image/Image.o' 'image/Image.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/Image2.d' -o 'objdir/image/Image2.o' 'image/Image2.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/Matrix.d' -o 'objdir/image/Matrix.o' 'image/Matrix.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/agg.d' -o 'objdir/image/agg.o' 'image/agg.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/canvas.d' -o 'objdir/image/canvas.o' 'image/canvas.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/crop.d' -o 'objdir/image/crop.o' 'image/crop.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/empty-page.d' -o 'objdir/image/empty-page.o' 'image/empty-page.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/floyd-steinberg.d' -o 'objdir/image/floyd-steinberg.o' 'image/floyd-steinberg.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/hocr.d' -o 'objdir/image/hocr.o' 'image/hocr.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/low-level.d' -o 'objdir/image/low-level.o' 'image/low-level.cc'
In file included from /usr/include/c++/6/vector:69:0,
                 from image/hocr.cc:28:
/usr/include/c++/6/bits/vector.tcc: In member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, const _Tp&) [with _Tp = Span; _Alloc = std::allocator<Span>]':
/usr/include/c++/6/bits/vector.tcc:326:5: note: parameter passing for argument of type 'std::vector<Span>::iterator {aka __gnu_cxx::__normal_iterator<Span*, std::vector<Span> >}' will change in GCC 7.1
     vector<_Tp, _Alloc>::
     ^~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/6/vector:64:0,
                 from image/hocr.cc:28:
/usr/include/c++/6/bits/stl_vector.h: In function 'void elementText(const string&)':
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<Span*, std::vector<Span> >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/optimize2bw.d' -o 'objdir/image/optimize2bw.o' 'image/optimize2bw.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/riemersma.d' -o 'objdir/image/riemersma.o' 'image/riemersma.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/rotate.d' -o 'objdir/image/rotate.o' 'image/rotate.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/scale.d' -o 'objdir/image/scale.o' 'image/scale.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/segmentation.d' -o 'objdir/image/segmentation.o' 'image/segmentation.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/image/vectorial.d' -o 'objdir/image/vectorial.o' 'image/vectorial.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/Codecs.d' -o 'objdir/codecs/Codecs.o' 'codecs/Codecs.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/agg_svg_parser.d' -o 'objdir/codecs/agg_svg_parser.o' 'codecs/agg_svg_parser.cc'
In file included from /usr/include/c++/6/vector:69:0,
                 from image/vectorial.hh:24,
                 from image/vectorial.cc:23:
/usr/include/c++/6/bits/vector.tcc: In member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, const _Tp&) [with _Tp = double; _Alloc = std::allocator<double>]':
/usr/include/c++/6/bits/vector.tcc:326:5: note: parameter passing for argument of type 'std::vector<double>::iterator {aka __gnu_cxx::__normal_iterator<double*, std::vector<double> >}' will change in GCC 7.1
     vector<_Tp, _Alloc>::
     ^~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/6/vector:64:0,
                 from image/vectorial.hh:24,
                 from image/vectorial.cc:23:
/usr/include/c++/6/bits/stl_vector.h: In member function 'void Path::setLineDash(double, const double*, int)':
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double> >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/agg_svg_path_renderer.d' -o 'objdir/codecs/agg_svg_path_renderer.o' 'codecs/agg_svg_path_renderer.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/agg_svg_path_tokenizer.d' -o 'objdir/codecs/agg_svg_path_tokenizer.o' 'codecs/agg_svg_path_tokenizer.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/bmp.d' -o 'objdir/codecs/bmp.o' 'codecs/bmp.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/dcraw.d' -o 'objdir/codecs/dcraw.o' 'codecs/dcraw.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/eps.d' -o 'objdir/codecs/eps.o' 'codecs/eps.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/gif.d' -o 'objdir/codecs/gif.o' 'codecs/gif.cc'
In file included from codecs/dcraw.cc:137:0:
codecs/dcraw.h: In function 'void dcraw::samsung3_load_raw()':
codecs/dcraw.h:2786:24: warning: iteration 2 invokes undefined behavior [-Waggressive-loop-optimizations]
     FORC(6) lent[0][c] = row < 2 ? 7:4;
             ~~~~~~~~~~~^~~~~~~~~~~~~~~
codecs/dcraw.h:178:31: note: within this loop
 #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=a+b; b=a-b; a=a-b; }
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /*
 ~~                             
    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 RAW(row,col) \
 ~~~~~~~~~~~~~~~~~~~~~~         
  raw_image[(row)*raw_width+(col)]
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 #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)][fcol(row,col)]
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 int CLASS fcol (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 filter[(row+top_margin)&15][(col+left_margin)&15];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (filters == 9) return xtrans[(row+6) % 6][(col+6) % 6];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   return FC(row,col);
   ~~~~~~~~~~~~~~~~~~~          
 }
 ~                              
 
                                
 #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
 ~~~~~~~~~~~~~~~~~~~~~~~~       
 char *my_strcasestr (char *haystack, const char *needle)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   char *c;
   ~~~~~~~~                     
   for (c = haystack; *c; c++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     if (!strncasecmp(c, needle, strlen(needle)))
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       return c;
       ~~~~~~~~~                
   return 0;
   ~~~~~~~~~                    
 }
 ~                              
 #define strcasestr my_strcasestr
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #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++;
   ~~~~~~~~~~~~~                
 }
 ~                              
 
                                
 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 cubic_spline (const int *x_, const int *y_, const int len)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   float **A, *b, *c, *d, *x, *y;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int i, j;
   ~~~~~~~~~                    
 
                                
   A = (float **) calloc (((2*len + 4)*sizeof **A + sizeof *A), 2*len);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (!A) return;
   ~~~~~~~~~~~~~~~              
   A[0] = (float *) (A + 2*len);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (i = 1; i < 2*len; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     A[i] = A[0] + 2*len*i;
     ~~~~~~~~~~~~~~~~~~~~~~     
   y = len + (x = i + (d = i + (c = i + (b = A[0] + i*i))));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (i = 0; i < len; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     x[i] = x_[i] / 65535.0;
     ~~~~~~~~~~~~~~~~~~~~~~~    
     y[i] = y_[i] / 65535.0;
     ~~~~~~~~~~~~~~~~~~~~~~~    
   }
   ~                            
   for (i = len-1; i > 0; i--) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     b[i] = (y[i] - y[i-1]) / (x[i] - x[i-1]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     d[i-1] = x[i] - x[i-1];
     ~~~~~~~~~~~~~~~~~~~~~~~    
   }
   ~                            
   for (i = 1; i < len-1; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     A[i][i] = 2 * (d[i-1] + d[i]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (i > 1) {
     ~~~~~~~~~~~~               
       A[i][i-1] = d[i-1];
       ~~~~~~~~~~~~~~~~~~~      
       A[i-1][i] = d[i-1];
       ~~~~~~~~~~~~~~~~~~~      
     }
     ~                          
     A[i][len-1] = 6 * (b[i+1] - b[i]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for(i = 1; i < len-2; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     float v = A[i+1][i] / A[i][i];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for(j = 1; j <= len-1; j++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       A[i+1][j] -= v * A[i][j];
       ~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for(i = len-2; i > 0; i--) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     float acc = 0;
     ~~~~~~~~~~~~~~             
     for(j = i; j <= len-2; j++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       acc += A[i][j]*c[j];
       ~~~~~~~~~~~~~~~~~~~~     
     c[i] = (A[i][len-1] - acc) / A[i][i];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for (i = 0; i < 0x10000; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     float x_out = (float)(i / 65535.0);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     float y_out = 0;
     ~~~~~~~~~~~~~~~~           
     for (j = 0; j < len-1; j++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (x[j] <= x_out && x_out <= x[j+1]) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  float v = x_out - x[j];
  ~~~~~~~~~~~~~~~~~~~~~~~       
  y_out = y[j] +
  ~~~~~~~~~~~~~~                
    ((y[j+1] - y[j]) / d[j] - (2 * d[j] * c[j] + c[j+1] * d[j])/6) * v
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + (c[j] * 0.5) * v*v + ((c[j+1] - c[j]) / (6 * d[j])) * v*v*v;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
     curve[i] = y_out < 0.0 ? 0 : (y_out >= 1.0 ? 65535 :
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   (ushort)(y_out * 65535.0 + 0.5));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   free (A);
   ~~~~~~~~~                    
 }
 ~                              
 
                                
 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 *pix;
   ~~~~~~~~~~~~                 
   int irow, row;
   ~~~~~~~~~~~~~~               
 
                                
   for (irow=row=0; irow < height; irow++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (data, 1, 1120, ifp) < 1120) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     pix = raw_image + row*raw_width;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (dp=data; 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    );
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     if ((row+=2) > height) row = 1;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS canon_600_correct()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   int row, col, val;
   ~~~~~~~~~~~~~~~~~~           
   static const short mul[4][2] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   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;
   ~~~~~~~~~~                   
 }
 ~                              
 
                                
 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;
   ~~~~~~~~~                    
 }
 ~                              
 
                                
 unsigned CLASS getbithuff (int nbits, ushort *huff)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   static unsigned bitbuf=0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   static int vbits=0, reset=0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   unsigned c;
   ~~~~~~~~~~~                  
 
                                
   if (nbits > 25) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   if (nbits < 0)
   ~~~~~~~~~~~~~~               
     return bitbuf = vbits = reset = 0;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (nbits == 0 || vbits < 0) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   while (!reset && vbits < nbits && (c = fgetc(ifp)) != EOF &&
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     !(reset = zero_after_ff && c == 0xff && fgetc(ifp))) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     bitbuf = (bitbuf << 8) + (uchar) c;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     vbits += 8;
     ~~~~~~~~~~~                
   }
   ~                            
   c = bitbuf << (32-vbits) >> (32-nbits);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (huff) {
   ~~~~~~~~~~~                  
     vbits -= huff[c] >> 8;
     ~~~~~~~~~~~~~~~~~~~~~~     
     c = (uchar) huff[c];
     ~~~~~~~~~~~~~~~~~~~~       
   } else
   ~~~~~~                       
     vbits -= nbits;
     ~~~~~~~~~~~~~~~            
   if (vbits < 0) derror();
   ~~~~~~~~~~~~~~~~~~~~~~~~     
   return c;
   ~~~~~~~~~                    
 }
 ~                              
 
                                
 #define getbits(n) getbithuff(n,0)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #define gethuff(h) getbithuff(*h,h+1)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /*
 ~~                             
    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
  ~~~~~~~~~~~~~                 
  */
  ~~                            
 ushort * CLASS make_decoder_ref (const uchar **source)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int max, len, h, i, j;
   ~~~~~~~~~~~~~~~~~~~~~~       
   const uchar *count;
   ~~~~~~~~~~~~~~~~~~~          
   ushort *huff;
   ~~~~~~~~~~~~~                
 
                                
   count = (*source += 16) - 17;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (max=16; max && !count[max]; max--);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff = (ushort *) calloc (1 + (1 << max), sizeof *huff);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (huff, "make_decoder()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff[0] = max;
   ~~~~~~~~~~~~~~               
   for (h=len=1; len <= max; len++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (i=0; i < count[len]; i++, ++*source)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (j=0; j < 1 << (max-len); j++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (h <= 1 << max)
  ~~~~~~~~~~~~~~~~~~            
    huff[h++] = len << 8 | **source;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   return huff;
   ~~~~~~~~~~~~                 
 }
 ~                              
 
                                
 ushort * CLASS make_decoder (const uchar *source)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   return make_decoder_ref (&source);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS crw_init_tables (unsigned table, ushort *huff[2])
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   huff[0] = make_decoder ( first_tree[table]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff[1] = make_decoder (second_tree[table]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 /*
 ~~                             
    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_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~    
 {
 ~                              
   ushort *pixel, *prow, *huff[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int nblocks, lowbits, i, c, row, r, save, val;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   crw_init_tables (tiff_compress, huff);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     pixel = raw_image + row*raw_width;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     nblocks = MIN (8, raw_height-row) * raw_width >> 6;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (block=0; block < nblocks; block++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       memset (diffbuf, 0, sizeof diffbuf);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i=0; i < 64; i++ ) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  leaf = gethuff(huff[i > 0]);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  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);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   FORC(2) free (huff[c]);
   ~~~~~~~~~~~~~~~~~~~~~~~      
 }
 ~                              
 
                                
 /*
 ~~                             
    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];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort *huff[6], *free[4], *row;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 };
 ~~                             
 
                                
 int CLASS ljpeg_start (struct jhead *jh, int info_only)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c, tag;
   ~~~~~~~~~~~                  
   ushort len;
   ~~~~~~~~~~~                  
   uchar data[0x10000];
   ~~~~~~~~~~~~~~~~~~~~         
   const uchar *dp;
   ~~~~~~~~~~~~~~~~             
 
                                
   memset (jh, 0, sizeof *jh);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   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 && (c = *dp++) < 4; )
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    jh->free[c] = jh->huff[c] = make_decoder_ref (&dp);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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->clrs > 6 || !jh->huff[0]) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC(5) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
 }
 ~                              
 
                                
 void CLASS ljpeg_end (struct jhead *jh)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c;
   ~~~~~~                       
   FORC4 if (jh->free[c]) free (jh->free[c]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   free (jh->row);
   ~~~~~~~~~~~~~~~              
 }
 ~                              
 
                                
 int CLASS ljpeg_diff (ushort *huff)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int len, diff;
   ~~~~~~~~~~~~~~               
 
                                
   if(!huff)
   ~~~~~~~~~                    
     longjmp (failure, 2);
     ~~~~~~~~~~~~~~~~~~~~~      
 
                                
   len = gethuff(huff);
   ~~~~~~~~~~~~~~~~~~~~         
   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) {
     ~~~~~~~~~~~                
       fseek (ifp, -2, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   struct jhead jh;
   ~~~~~~~~~~~~~~~~             
   ushort *rp;
   ~~~~~~~~~~~                  
 
                                
   if (!ljpeg_start (&jh, 0)) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jwide = jh.wide * jh.clrs;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
 
                                
   if(jh.wide<1 || jh.high<1 || jh.clrs<1 || jh.bits <1)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     longjmp (failure, 2);
     ~~~~~~~~~~~~~~~~~~~~~      
 
                                
   for (jrow=0; jrow < jh.high; jrow++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     rp = ljpeg_row (jrow, &jh);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (load_flags & 1)
     ~~~~~~~~~~~~~~~~~~~        
       row = jrow & 1 ? height-1-jrow/2 : jrow/2;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (jcol=0; jcol < jwide; jcol++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       val = curve[*rp++];
       ~~~~~~~~~~~~~~~~~~~      
       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(row>raw_height)
       ~~~~~~~~~~~~~~~~~~       
  longjmp (failure, 3);
  ~~~~~~~~~~~~~~~~~~~~~         
       if ((unsigned) row < raw_height) RAW(row,col) = val;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (++col >= raw_width)
       ~~~~~~~~~~~~~~~~~~~~~~~  
  col = (row++,0);
  ~~~~~~~~~~~~~~~~              
     }
     ~                          
   }
   ~                            
   ljpeg_end (&jh);
   ~~~~~~~~~~~~~~~~             
 }
 ~                              
 
                                
 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) || jh.clrs < 4) 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 >= 0x80000281 || (unique_id == 0x80000218 && ver > 1000006))
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     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 == 0x80000218 ||
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  unique_id == 0x80000250 ||
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  unique_id == 0x80000261 ||
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  unique_id == 0x80000281 ||
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  unique_id == 0x80000287) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
       rp[1] = (rp[1] << 2) + hue;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       rp[2] = (rp[2] << 2) + hue;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pix[0] = rp[0] + ((   50*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);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else {
     ~~~~~~~~                   
       if (unique_id < 0x80000218) rp[0] -= 512;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pix[0] = rp[0] + rp[2];
       ~~~~~~~~~~~~~~~~~~~~~~~  
       pix[2] = rp[0] + rp[1];
       ~~~~~~~~~~~~~~~~~~~~~~~  
       pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   ljpeg_end (&jh);
   ~~~~~~~~~~~~~~~~             
   maximum = 0x3fff;
   ~~~~~~~~~~~~~~~~~            
 }
 ~                              
 
                                
 void CLASS adobe_copy_pixel (unsigned row, unsigned col, ushort **rp)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c;
   ~~~~~~                       
 
                                
   if (is_raw == 2 && shot_select) (*rp)++;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (raw_image) {
   ~~~~~~~~~~~~~~~~             
     if (row < raw_height && col < raw_width)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[**rp];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     *rp += is_raw;
     ~~~~~~~~~~~~~~             
   } else {
   ~~~~~~~~                     
     if (row < height && col < width)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC(tiff_samples)
       ~~~~~~~~~~~~~~~~~~       
  image[row*width+col][c] = curve[(*rp)[c]];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     *rp += tiff_samples;
     ~~~~~~~~~~~~~~~~~~~~       
   }
   ~                            
   if (is_raw == 2 && shot_select) (*rp)--;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS lossless_dng_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   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);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     ljpeg_end (&jh);
     ~~~~~~~~~~~~~~~~           
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS packed_dng_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   ushort *pixel, *rp;
   ~~~~~~~~~~~~~~~~~~~          
   int row, col;
   ~~~~~~~~~~~~~                
 
                                
   pixel = (ushort *) calloc (raw_width, tiff_samples*sizeof *pixel);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (pixel, "packed_dng_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
 {
 ~                              
   ushort bit[2][15], huff[4097];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int dep, row, col, diff, c, i;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   fseek (ifp, meta_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   dep = (get2() + 12) & 15;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   fseek (ifp, 12, SEEK_CUR);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
   FORC(dep) bit[0][c] = get2();
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC(dep) bit[1][c] = fgetc(ifp);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC(dep)
   ~~~~~~~~~                    
     for (i=bit[0][c]; i <= ((bit[0][c]+(4096 >> bit[1][c])-1) & 4095); )
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       huff[++i] = bit[1][c] << 8 | c;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff[0] = 12;
   ~~~~~~~~~~~~~                
   fseek (ifp, data_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       diff = ljpeg_diff (huff);
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else    hpred[col & 1] += diff;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = hpred[col & 1];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (hpred[col & 1] >> tiff_bps) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 void CLASS nikon_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 } };
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort *huff, ver0, ver1, vpred[2][2], hpred[2], csize;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int i, min, max, step=0, tree=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) tree = 2;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   if (tiff_bps == 14) tree += 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--;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff = make_decoder (nikon_tree[tree]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fseek (ifp, data_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (min=row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (split && row == split) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       free (huff);
       ~~~~~~~~~~~~             
       huff = make_decoder (nikon_tree[tree+1]);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       max += (min = 16) << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~  
     }
     ~                          
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       i = gethuff(huff);
       ~~~~~~~~~~~~~~~~~~       
       len = i & 15;
       ~~~~~~~~~~~~~            
       shl = i >> 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();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[LIM((short)hpred[col & 1],0,0x3fff)];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   free (huff);
   ~~~~~~~~~~~~                 
 }
 ~                              
 
                                
 void CLASS nikon_yuv_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int row, col, yuv[4], rgb[3], b, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   UINT64 bitbuf=0;
   ~~~~~~~~~~~~~~~~             
 
                                
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (!(b = col & 1)) {
       ~~~~~~~~~~~~~~~~~~~~~    
  bitbuf = 0;
  ~~~~~~~~~~~                   
  FORC(6) bitbuf |= (UINT64) fgetc(ifp) << c*8;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC(4) yuv[c] = (bitbuf >> c*12 & 0xfff) - (c >> 1 << 11);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
       rgb[0] = yuv[b] + 1.370705*yuv[3];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       rgb[1] = yuv[b] - 0.337633*yuv[2] - 0.698001*yuv[3];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       rgb[2] = yuv[b] + 1.732446*yuv[2];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,0xfff)] / cam_mul[c];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 /*
 ~~                             
    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;
   ~~~~~~~~~~~~~~~              
 }
 ~                              
 
                                
 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 ppm16_thumb()
 ~~~~~~~~~~~~~~~~~~~~~~~~       
 {
 ~                              
   int i;
   ~~~~~~                       
   char *thumb;
   ~~~~~~~~~~~~                 
   thumb_length = thumb_width*thumb_height*3;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   thumb = (char *) calloc (thumb_length, 2);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (thumb, "ppm16_thumb()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   read_shorts ((ushort *) thumb, thumb_length);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (i=0; i < thumb_length; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     thumb[i] = ((ushort *) thumb)[i] >> 8;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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, 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)
     ~~~~~~~~~~~~~~~~~~~~~~~    
       raw_image[todo[i]] = (todo[i+1] & 0x3ff);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   maximum = 0x3ff;
   ~~~~~~~~~~~~~~~~             
 }
 ~                              
 
                                
 int CLASS raw (unsigned row, unsigned col)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   return (row < raw_height && col < raw_width) ? RAW(row,col) : 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS phase_one_flat_field (int is_float, int nc)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   ushort head[8];
   ~~~~~~~~~~~~~~~              
   unsigned wide, high, y, x, c, rend, cend, row, col;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   float *mrow, num, mult[4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
 
                                
   read_shorts (head, 8);
   ~~~~~~~~~~~~~~~~~~~~~~       
   if (head[2] * head[3] * head[4] * head[5] == 0) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   wide = head[2] / head[4] + (head[2] % head[4] != 0);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   high = head[3] / head[5] + (head[3] % head[5] != 0);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   mrow = (float *) calloc (nc*wide, sizeof *mrow);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (mrow, "phase_one_flat_field()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (y=0; y < high; 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] + y*head[5];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (row = rend-head[5];
     ~~~~~~~~~~~~~~~~~~~~~~~~   
   row < raw_height && row < rend &&
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   row < head[1]+head[3]-head[5]; 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] + x*head[4];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  for (col = cend-head[4];
  ~~~~~~~~~~~~~~~~~~~~~~~~      
       col < raw_width &&
       ~~~~~~~~~~~~~~~~~~       
       col < cend && col < head[0]+head[2]-head[4]; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    c = nc > 2 ? FC(row-top_margin,col-left_margin) : 0;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (!(c & 1)) {
    ~~~~~~~~~~~~~~~             
      c = RAW(row,col) * mult[c];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~
      RAW(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];
   ~~~~~~~~~~~~~~~~             
   int qmult_applied = 0, qlin_applied = 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   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 < raw_height; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col = (tag & 1)*ph1.split_col; col < raw_width; col++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    RAW(row,col) = curve[RAW(row,col)];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else if (tag == 0x400) {   /* Sensor defects */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       while ((len -= 8) >= 0) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  col  = get2();
  ~~~~~~~~~~~~~~                
  row  = get2();
  ~~~~~~~~~~~~~~                
  type = get2(); get2();
  ~~~~~~~~~~~~~~~~~~~~~~        
  if (col >= raw_width) continue;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (type == 131 || type == 137)  /* Bad column */
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (row=0; row < raw_height; row++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (FC(row-top_margin,col-left_margin) == 1) {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        for (sum=i=0; i < 4; i++)
        ~~~~~~~~~~~~~~~~~~~~~~~~~
   sum += val[i] = raw (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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        }
        ~                       
        RAW(row,col) = (sum - val[max])/3.0 + 0.5;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      } else {
      ~~~~~~~~                  
        for (sum=0, i=8; i < 12; i++)
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   sum += raw (row+dir[i][0], col+dir[i][1]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        RAW(row,col) = 0.5 + sum * 0.0732233 +
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   (raw(row,col-2) + raw(row,col+2)) * 0.3535534;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      }
      ~                         
  else if (type == 129) {   /* Bad pixel */
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (row >= raw_height) continue;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    j = (FC(row-top_margin,col-left_margin) != 1) * 4;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (sum=0, i=j; i < j+8; i++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      sum += raw (row+dir[i][0], col+dir[i][1]);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    RAW(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;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
       }
       ~                        
     } else if (tag == 0x41f && !qlin_applied) { /* Quadrant linearization */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       ushort lc[2][2][16], ref[16];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       int qr, qc;
       ~~~~~~~~~~~              
       for (qr = 0; qr < 2; qr++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (qc = 0; qc < 2; qc++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
    for (i = 0; i < 16; i++)
    ~~~~~~~~~~~~~~~~~~~~~~~~    
      lc[qr][qc][i] = (ushort)get4();
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i = 0; i < 16; i++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  int v = 0;
  ~~~~~~~~~~                    
  for (qr = 0; qr < 2; qr++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
    for (qc = 0; qc < 2; qc++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
      v += lc[qr][qc][i];
      ~~~~~~~~~~~~~~~~~~~       
  ref[i] = (v + 2) >> 2;
  ~~~~~~~~~~~~~~~~~~~~~~        
       }
       ~                        
       for (qr = 0; qr < 2; qr++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (qc = 0; qc < 2; qc++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    int cx[18], cf[18];
    ~~~~~~~~~~~~~~~~~~~         
    for (i = 0; i < 16; i++) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
      cx[1+i] = lc[qr][qc][i];
      ~~~~~~~~~~~~~~~~~~~~~~~~  
      cf[1+i] = ref[i];
      ~~~~~~~~~~~~~~~~~         
    }
    ~                           
    cx[0] = cf[0] = 0;
    ~~~~~~~~~~~~~~~~~~          
    cx[17] = cf[17] = ((unsigned int)ref[15] * 65535) / lc[qr][qc][15];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    cubic_spline(cx, cf, 18);
    ~~~~~~~~~~~~~~~~~~~~~~~~~   
 
                                
    for (row = (qr ? ph1.split_row : 0);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         row < (qr ? raw_height : ph1.split_row); row++)
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (col = (qc ? ph1.split_col : 0);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    col < (qc ? raw_width : ph1.split_col); col++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        RAW(row,col) = curve[RAW(row,col)];
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       }
       ~                        
       qlin_applied = 1;
       ~~~~~~~~~~~~~~~~~        
     } else if (tag == 0x41e && !qmult_applied) { /* Quadrant multipliers */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       float qmult[2][2] = { { 1, 1 }, { 1, 1 } };
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       get4(); get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       qmult[0][0] = 1.0 + getreal(11);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       get4(); get4(); get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       qmult[0][1] = 1.0 + getreal(11);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~  
       qmult[1][0] = 1.0 + getreal(11);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~  
       qmult[1][1] = 1.0 + getreal(11);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (row=0; row < raw_height; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col=0; col < raw_width; col++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    i = qmult[row >= ph1.split_row][col >= ph1.split_col] * RAW(row,col);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    RAW(row,col) = LIM(i,0,65535);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       qmult_applied = 1;
       ~~~~~~~~~~~~~~~~~~       
     } else if (tag == 0x431 && !qmult_applied) { /* Quadrant combined */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       ushort lc[2][2][7], ref[7];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       int qr, qc;
       ~~~~~~~~~~~              
       for (i = 0; i < 7; i++)
       ~~~~~~~~~~~~~~~~~~~~~~~  
  ref[i] = (ushort)get4();
  ~~~~~~~~~~~~~~~~~~~~~~~~      
       for (qr = 0; qr < 2; qr++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (qc = 0; qc < 2; qc++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
    for (i = 0; i < 7; i++)
    ~~~~~~~~~~~~~~~~~~~~~~~     
      lc[qr][qc][i] = (ushort)get4();
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (qr = 0; qr < 2; qr++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (qc = 0; qc < 2; qc++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    int cx[9], cf[9];
    ~~~~~~~~~~~~~~~~~           
    for (i = 0; i < 7; i++) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~   
      cx[1+i] = ref[i];
      ~~~~~~~~~~~~~~~~~         
      cf[1+i] = ((unsigned int)ref[i] * lc[qr][qc][i]) / 10000;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    }
    ~                           
    cx[0] = cf[0] = 0;
    ~~~~~~~~~~~~~~~~~~          
    cx[8] = cf[8] = 65535;
    ~~~~~~~~~~~~~~~~~~~~~~      
    cubic_spline(cx, cf, 9);
    ~~~~~~~~~~~~~~~~~~~~~~~~    
    for (row = (qr ? ph1.split_row : 0);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         row < (qr ? raw_height : ph1.split_row); row++)
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (col = (qc ? ph1.split_col : 0);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    col < (qc ? raw_width : ph1.split_col); col++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        RAW(row,col) = curve[RAW(row,col)];
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         }
         ~                      
       }
       ~                        
       qmult_applied = 1;
       ~~~~~~~~~~~~~~~~~~       
       qlin_applied = 1;
       ~~~~~~~~~~~~~~~~~        
     }
     ~                          
     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 < raw_height; row++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < raw_width; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cfrac = (float) col * head[3] / raw_width;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cfrac -= cip = cfrac;
  ~~~~~~~~~~~~~~~~~~~~~         
  num = RAW(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 + num) * 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = LIM(i,0,65535);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     free (yval[0]);
     ~~~~~~~~~~~~~~~            
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS phase_one_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int a, b, i;
   ~~~~~~~~~~~~                 
   ushort akey, bkey, mask;
   ~~~~~~~~~~~~~~~~~~~~~~~~     
 
                                
   fseek (ifp, ph1.key_off, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   akey = get2();
   ~~~~~~~~~~~~~~               
   bkey = get2();
   ~~~~~~~~~~~~~~               
   mask = ph1.format == 1 ? 0x5555:0x1354;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fseek (ifp, data_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   read_shorts (raw_image, raw_width*raw_height);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (ph1.format)
   ~~~~~~~~~~~~~~~              
     for (i=0; i < raw_width*raw_height; i+=2) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       a = raw_image[i+0] ^ akey;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       b = raw_image[i+1] ^ bkey;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       raw_image[i+0] = (a & mask) | (b & ~mask);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       raw_image[i+1] = (b & mask) | (a & ~mask);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 unsigned CLASS ph1_bithuff (int nbits, ushort *huff)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   static UINT64 bitbuf=0;
   ~~~~~~~~~~~~~~~~~~~~~~~      
   static int vbits=0;
   ~~~~~~~~~~~~~~~~~~~          
   unsigned c;
   ~~~~~~~~~~~                  
 
                                
   if (nbits == -1)
   ~~~~~~~~~~~~~~~~             
     return bitbuf = vbits = 0;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   if (nbits == 0) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   if (vbits < nbits) {
   ~~~~~~~~~~~~~~~~~~~~         
     bitbuf = bitbuf << 32 | get4();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     vbits += 32;
     ~~~~~~~~~~~~               
   }
   ~                            
   c = bitbuf << (64-vbits) >> (64-nbits);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (huff) {
   ~~~~~~~~~~~                  
     vbits -= huff[c] >> 8;
     ~~~~~~~~~~~~~~~~~~~~~~     
     return (uchar) huff[c];
     ~~~~~~~~~~~~~~~~~~~~~~~    
   }
   ~                            
   vbits -= nbits;
   ~~~~~~~~~~~~~~~              
   return c;
   ~~~~~~~~~                    
 }
 ~                              
 #define ph1_bits(n) ph1_bithuff(n,0)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #define ph1_huff(h) ph1_bithuff(*h,h+1)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 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 (*cblack)[2], (*rblack)[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   pixel = (ushort *) calloc (raw_width*3 + 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();
     ~~~~~~~~~~~~~~~~~~~~~      
   cblack = (short (*)[2]) (offset + raw_height);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fseek (ifp, ph1.black_col, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (ph1.black_col)
   ~~~~~~~~~~~~~~~~~~           
     read_shorts ((ushort *) cblack[0], raw_height*2);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   rblack = cblack + raw_height;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fseek (ifp, ph1.black_row, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (ph1.black_row)
   ~~~~~~~~~~~~~~~~~~           
     read_shorts ((ushort *) rblack[0], raw_width*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]];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       i = (pixel[col] << 2) - ph1.black
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  + cblack[row][col >= ph1.split_col]
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  + rblack[col][row >= ph1.split_row];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (i > 0) RAW(row,col) = i;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   free (pixel);
   ~~~~~~~~~~~~~                
   maximum = 0xfffc - ph1.black;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS hasselblad_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   struct jhead jh;
   ~~~~~~~~~~~~~~~~             
   int shot, row, col, *back[5], len[2], diff[12], pred, sh, f, s, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   unsigned upix, urow, ucol;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
   ushort *ip;
   ~~~~~~~~~~~                  
 
                                
   if (!ljpeg_start (&jh, 0)) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   order = 0x4949;
   ~~~~~~~~~~~~~~~              
   ph1_bits(-1);
   ~~~~~~~~~~~~~                
   back[4] = (int *) calloc (raw_width, 3*sizeof **back);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (back[4], "hasselblad_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC3 back[c] = back[4] + c*raw_width;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cblack[6] >>= sh = tiff_samples > 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   shot = LIM(shot_select, 1, tiff_samples) - 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC4 back[(c+3) & 3] = back[c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col+=2) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (s=0; s < tiff_samples*2; s+=2) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC(2) len[c] = ph1_huff(jh.huff[0]);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC(2) {
  ~~~~~~~~~                     
    diff[s+c] = ph1_bits(len[c]);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if ((diff[s+c] & (1 << (len[c]-1))) == 0)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      diff[s+c] -= (1 << len[c]) - 1;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (diff[s+c] == 65535) diff[s+c] = -32768;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       }
       ~                        
       for (s=col; s < col+2; s++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pred = 0x8000 + load_flags;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  if (col) pred = back[2][s-2];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  if (col && row > 1) switch (jh.psv) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    case 11: pred += back[0][s]/2 - back[0][s-2]/2;  break;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
  f = (row & 1)*3 ^ ((col+s) & 1);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC (tiff_samples) {
  ~~~~~~~~~~~~~~~~~~~~~         
    pred += diff[(s & 1)*tiff_samples+c];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    upix = pred >> sh & 0xffff;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    if (raw_image && c == shot)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
      RAW(row,s) = upix;
      ~~~~~~~~~~~~~~~~~~        
    if (image) {
    ~~~~~~~~~~~~                
      urow = row-top_margin  + (c & 1);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      ucol = col-left_margin - ((c >> 1) & 1);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      ip = &image[urow*width+ucol][f];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (urow < height && ucol < width)
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        *ip = c < 4 ? upix : (*ip + upix) >> 1;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    }
    ~                           
  }
  ~                             
  back[2][s] = pred;
  ~~~~~~~~~~~~~~~~~~            
       }
       ~                        
     }
     ~                          
   }
   ~                            
   free (back[4]);
   ~~~~~~~~~~~~~~~              
   ljpeg_end (&jh);
   ~~~~~~~~~~~~~~~~             
   if (image) mix_green = 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
 }
 ~                              
 
                                
 void CLASS leaf_hdr_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   ushort *pixel=0;
   ~~~~~~~~~~~~~~~~             
   unsigned tile=0, r, c, row, col;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (!filters) {
   ~~~~~~~~~~~~~~~              
     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(), SEEK_SET);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
       if (filters && c != shot_select) continue;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (filters) pixel = raw_image + r*raw_width;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       read_shorts (pixel, raw_width);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (!filters && (row = r - top_margin) < height)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col=0; col < width; col++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    image[row*width+col][c] = pixel[col+left_margin];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   if (!filters) {
   ~~~~~~~~~~~~~~~              
     maximum = 0xffff;
     ~~~~~~~~~~~~~~~~~          
     raw_color = 1;
     ~~~~~~~~~~~~~~             
     free (pixel);
     ~~~~~~~~~~~~~              
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS unpacked_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   int row, col, bits=0;
   ~~~~~~~~~~~~~~~~~~~~~        
 
                                
   while (1 << ++bits < maximum);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   read_shorts (raw_image, raw_width*raw_height);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((RAW(row,col) >>= load_flags) >> bits
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  && (unsigned) (row-top_margin) < height
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  && (unsigned) (col-left_margin) < width) derror();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS sinar_4shot_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   ushort *pixel;
   ~~~~~~~~~~~~~~               
   unsigned shot, row, col, r, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (raw_image) {
   ~~~~~~~~~~~~~~~~             
     shot = LIM (shot_select, 1, 4) - 1;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, data_offset + shot*4, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, get4(), SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     unpacked_load_raw();
     ~~~~~~~~~~~~~~~~~~~~       
     return;
     ~~~~~~~                    
   }
   ~                            
   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][(row & 1)*3 ^ (~col & 1)] = pixel[col];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
   }
   ~                            
   free (pixel);
   ~~~~~~~~~~~~~                
   mix_green = 1;
   ~~~~~~~~~~~~~~               
 }
 ~                              
 
                                
 void CLASS imacon_full_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int row, col;
   ~~~~~~~~~~~~~                
 
                                
   if (!image) return;
   ~~~~~~~~~~~~~~~~~~~          
   for (row=0; row < height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       read_shorts (image[row*width+col], 3);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS packed_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
 {
 ~                              
   int vbits=0, bwide, rbits, bite, half, irow, row, col, val, i;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   UINT64 bitbuf=0;
   ~~~~~~~~~~~~~~~~             
 
                                
   bwide = raw_width * tiff_bps / 8;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   bwide += bwide & load_flags >> 7;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   rbits = bwide * 8 - raw_width * tiff_bps;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (load_flags & 1) bwide = bwide * 16 / 15;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   bite = 8 + (load_flags & 24);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   half = (raw_height+1) >> 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   for (irow=0; irow < raw_height; irow++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     row = irow;
     ~~~~~~~~~~~                
     if (load_flags & 2 &&
     ~~~~~~~~~~~~~~~~~~~~~      
  (row = irow % half * 2 + irow / half) == 1 &&
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  load_flags & 4) {
  ~~~~~~~~~~~~~~~~~             
       if (vbits=0, tiff_compress)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  fseek (ifp, data_offset - (-half*bwide & -2048), SEEK_SET);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else {
       ~~~~~~                   
  fseek (ifp, 0, SEEK_END);
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  fseek (ifp, ftell(ifp) >> 3 << 2, SEEK_SET);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (vbits -= tiff_bps; vbits < 0; vbits += bite) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  bitbuf <<= bite;
  ~~~~~~~~~~~~~~~~              
  for (i=0; i < bite; i+=8)
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
    bitbuf |= (unsigned) (fgetc(ifp) << i);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
       val = bitbuf << (64-tiff_bps-vbits) >> (64-tiff_bps);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col ^ (load_flags >> 6 & 1)) = val;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (load_flags & 1 && (col % 10) == 9 && fgetc(ifp) &&
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  row < height+top_margin && col < width+left_margin) derror();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     vbits -= rbits;
     ~~~~~~~~~~~~~~~            
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS nokia_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~    
 {
 ~                              
   uchar  *data,  *dp;
   ~~~~~~~~~~~~~~~~~~~          
   int rev, dwide, row, col, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   double sum[]={0,0};
   ~~~~~~~~~~~~~~~~~~~          
 
                                
   rev = 3 * (order == 0x4949);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   dwide = (raw_width * 5 + 1) / 4;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   data = (uchar *) malloc (dwide*2);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (data, "nokia_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (data+dwide, 1, dwide, ifp) < dwide) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC(dwide) data[c] = data[dwide+(c ^ rev)];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (dp=data, col=0; col < raw_width; dp+=5, col+=4)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 RAW(row,col+c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   free (data);
   ~~~~~~~~~~~~                 
   maximum = 0x3ff;
   ~~~~~~~~~~~~~~~~             
   if (strcmp(make,"OmniVision")) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   row = raw_height/2;
   ~~~~~~~~~~~~~~~~~~~          
   FORC(width-1) {
   ~~~~~~~~~~~~~~~              
     sum[ c & 1] += SQR(RAW(row,c)-RAW(row+1,c+1));
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     sum[~c & 1] += SQR(RAW(row+1,c)-RAW(row,c+1));
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   if (sum[1] > sum[0]) filters = 0x4b4b4b4b;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS canon_rmf_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int row, col, bits, orow, ocol, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width-2; col+=3) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       bits = get4();
       ~~~~~~~~~~~~~~           
       FORC3 {
       ~~~~~~~                  
  orow = row;
  ~~~~~~~~~~~                   
  if ((ocol = col+c-4) < 0) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
    ocol += raw_width;
    ~~~~~~~~~~~~~~~~~~          
    if ((orow -= 2) < 0)
    ~~~~~~~~~~~~~~~~~~~~        
      orow += raw_height;
      ~~~~~~~~~~~~~~~~~~~       
  }
  ~                             
  RAW(orow,ocol) = curve[bits >> (10*c+2) & 0x3ff];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
   maximum = curve[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 ((RAW(row,col) = pred[col & 1]) > 4098 && col < width) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 void CLASS olympus_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
 {
 ~                              
   ushort huff[4096];
   ~~~~~~~~~~~~~~~~~~           
   int row, col, nbits, sign, low, high, i, c, w, n, nw;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int acarry[2][3], *carry, pred, diff;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   huff[n=0] = 0xc0c;
   ~~~~~~~~~~~~~~~~~~           
   for (i=12; i--; )
   ~~~~~~~~~~~~~~~~~            
     FORC(2048 >> i) huff[++n] = (i+1) << 8 | i;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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++);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       low = (sign = getbits(3)) & 3;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       sign = sign << 29 >> 31;
       ~~~~~~~~~~~~~~~~~~~~~~~~ 
       if ((high = getbithuff(12,huff)) == 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 = RAW(row,col-2);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else if (col < 2) pred = RAW(row-2,col);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else {
       ~~~~~~                   
  w  = RAW(row,col-2);
  ~~~~~~~~~~~~~~~~~~~~          
  n  = RAW(row-2,col);
  ~~~~~~~~~~~~~~~~~~~~          
  nw = RAW(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 ((RAW(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) RAW(row,col) = (col+1) & 2 ?
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,1)    = pixel[1]   << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,1533) = pixel[765] << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else
     ~~~~~~                     
       for (col=row & 1; col < 1534; col+=2)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = pixel[col/2] << 1;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   maximum = 0xff << 1;
   ~~~~~~~~~~~~~~~~~~~~         
 }
 ~                              
 
                                
 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++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[pixel[row+2][col+2]];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   maximum = 0x3ff;
   ~~~~~~~~~~~~~~~~             
 }
 ~                              
 
                                
 #define radc_token(tree) ((signed char) getbithuff(8,huff[tree]))
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 #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)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 #define ARRAY_SIZE(_array) (sizeof(_array) / sizeof((_array)[0]))
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 void CLASS kodak_radc_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   static const char src[] = {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     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
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   };
   ~~                           
   ushort huff[19][256];
   ~~~~~~~~~~~~~~~~~~~~~        
   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;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (s=i=0; i < sizeof src; i+=2)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC(256 >> src[i])
     ~~~~~~~~~~~~~~~~~~~        
       huff[0][s++] = src[i] << 8 | (uchar) src[i+1];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   s = kodak_cbpp == 243 ? 2 : 3;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC(256) huff[18][c] = (8-s) << 8 | c >> s << s | 1 << (s-1);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (c=0; c < ARRAY_SIZE(buf); c++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (y=0; y < ARRAY_SIZE(buf[0]); y++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (x=0; y < ARRAY_SIZE(buf[0][0]); x++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         buf[c][y][x] = 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] = (uchar) radc_token(18) * 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) RAW(row+y*2+c-1,x*2+2-c) = val;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      else   RAW(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 = (RAW(y,x)-2048)*2 + (RAW(y,r)+RAW(y,s))/2;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (val < 0) val = 0;
    ~~~~~~~~~~~~~~~~~~~~~       
    RAW(y,x) = val;
    ~~~~~~~~~~~~~~~             
  }
  ~                             
   }
   ~                            
   for (i=0; i < height*width; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     raw_image[i] = curve[raw_image[i]];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   maximum = 0x3fff;
   ~~~~~~~~~~~~~~~~~            
 }
 ~                              
 
                                
 #undef FORYX
 ~~~~~~~~~~~~                   
 #undef PREDICTOR
 ~~~~~~~~~~~~~~~~               
 
                                
 #ifdef NO_JPEG
 ~~~~~~~~~~~~~~                 
 void CLASS kodak_jpeg_load_raw() {}
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 void CLASS lossy_dng_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) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row+0,col+0) = pixel[col+0][1] << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row+1,col+1) = pixel[col+1][1] << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   jpeg_finish_decompress (&cinfo);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jpeg_destroy_decompress (&cinfo);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   maximum = 0xff << 1;
   ~~~~~~~~~~~~~~~~~~~~         
 }
 ~                              
 
                                
 void CLASS gamma_curve (double pwr, double ts, int mode, int imax);
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 void CLASS lossy_dng_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   struct jpeg_decompress_struct cinfo;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   struct jpeg_error_mgr jerr;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   JSAMPARRAY buf;
   ~~~~~~~~~~~~~~~              
   JSAMPLE (*pixel)[3];
   ~~~~~~~~~~~~~~~~~~~~         
   unsigned sorder=order, ntags, opcode, deg, i, j, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   unsigned save=data_offset-4, trow=0, tcol=0, row, col;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort cur[3][256];
   ~~~~~~~~~~~~~~~~~~~          
   double coeff[9], tot;
   ~~~~~~~~~~~~~~~~~~~~~        
 
                                
   if (meta_offset) {
   ~~~~~~~~~~~~~~~~~~           
     fseek (ifp, meta_offset, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     order = 0x4d4d;
     ~~~~~~~~~~~~~~~            
     ntags = get4();
     ~~~~~~~~~~~~~~~            
     while (ntags--) {
     ~~~~~~~~~~~~~~~~~          
       opcode = get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (opcode != 8)
       ~~~~~~~~~~~~~~~~         
       { fseek (ifp, get4(), SEEK_CUR); continue; }
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, 20, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((c = get4()) > 2) break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, 12, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((deg = get4()) > 8) break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i=0; i <= deg && i < 9; i++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  coeff[i] = getreal(12);
  ~~~~~~~~~~~~~~~~~~~~~~~       
       for (i=0; i < 256; i++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  for (tot=j=0; j <= deg; j++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    tot += coeff[j] * pow(i/255.0, j);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cur[c][i] = tot*0xffff;
  ~~~~~~~~~~~~~~~~~~~~~~~       
       }
       ~                        
     }
     ~                          
     order = sorder;
     ~~~~~~~~~~~~~~~            
   } else {
   ~~~~~~~~                     
     gamma_curve (1/2.4, 12.92, 1, 255);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC3 memcpy (cur[c], curve, sizeof cur[0]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   cinfo.err = jpeg_std_error (&jerr);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jpeg_create_decompress (&cinfo);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   while (trow < raw_height) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     fseek (ifp, save+=4, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tile_length < INT_MAX)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
       fseek (ifp, get4(), SEEK_SET);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     jpeg_stdio_src (&cinfo, ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     jpeg_read_header (&cinfo, TRUE);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     jpeg_start_decompress (&cinfo);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     buf = (*cinfo.mem->alloc_sarray)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width*3, 1);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     while (cinfo.output_scanline < cinfo.output_height &&
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  (row = trow + cinfo.output_scanline) < height) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       jpeg_read_scanlines (&cinfo, buf, 1);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pixel = (JSAMPLE (*)[3]) buf[0];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < cinfo.output_width && tcol+col < width; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC3 image[row*width+tcol+col][c] = cur[c][pixel[col][c]];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
     jpeg_abort_decompress (&cinfo);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if ((tcol += tile_width) >= raw_width)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       trow += tile_length + (tcol = 0);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   jpeg_destroy_decompress (&cinfo);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   maximum = 0xffff;
   ~~~~~~~~~~~~~~~~~            
 }
 ~                              
 #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++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = (ushort) pixel[(col + shift) % 848];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   maximum = 0xff;
   ~~~~~~~~~~~~~~~              
 }
 ~                              
 
                                
 void CLASS eight_bit_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   uchar *pixel;
   ~~~~~~~~~~~~~                
   unsigned row, col;
   ~~~~~~~~~~~~~~~~~~           
 
                                
   pixel = (uchar *) calloc (raw_width, sizeof *pixel);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (pixel, "eight_bit_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[pixel[col]];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   free (pixel);
   ~~~~~~~~~~~~~                
   maximum = curve[0xff];
   ~~~~~~~~~~~~~~~~~~~~~~       
 }
 ~                              
 
                                
 void CLASS kodak_c330_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   uchar *pixel;
   ~~~~~~~~~~~~~                
   int row, col, y, cb, cr, rgb[3], c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   pixel = (uchar *) calloc (raw_width, 2*sizeof *pixel);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (pixel, "kodak_c330_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (pixel, raw_width, 2, ifp) < 2) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (load_flags && (row & 31) == 31)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, raw_width*32, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       y  = pixel[col*2];
       ~~~~~~~~~~~~~~~~~~       
       cb = pixel[(col*2 & -4) | 1] - 128;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       cr = pixel[(col*2 & -4) | 3] - 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_c603_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   uchar *pixel;
   ~~~~~~~~~~~~~                
   int row, col, y, cb, cr, rgb[3], c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (pixel, "kodak_c603_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (~row & 1)
     ~~~~~~~~~~~~~              
       if (fread (pixel, raw_width, 3, ifp) < 3) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < 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 } };
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort *huff[2];
   ~~~~~~~~~~~~~~~~             
   uchar *pixel;
   ~~~~~~~~~~~~~                
   int *strip, ns, c, row, col, chess, pi=0, pi1, pi2, pred, val;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   FORC(2) huff[c] = make_decoder (kodak_tree[c]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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;
   ~~~~~~~~~~~~~~~              
   FORC(ns) strip[c] = 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 (huff[chess]);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (val >> 8) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~  
       val = curve[pixel[pi++]];
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = val;
       ~~~~~~~~~~~~~~~~~~~      
     }
     ~                          
   }
   ~                            
   free (pixel);
   ~~~~~~~~~~~~~                
   FORC(2) free (huff[c]);
   ~~~~~~~~~~~~~~~~~~~~~~~      
 }
 ~                              
 
                                
 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 ((RAW(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;
   ~~~~~~~~~~~                  
 
                                
   if (!image) return;
   ~~~~~~~~~~~~~~~~~~~          
   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-- && p++)
   ~~~~~~~~~~~~~~~~~~~~         
     *data++ ^= pad[(p-1) & 127] = pad[p & 127] ^ pad[(p+64) & 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);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     pixel = raw_image + row*raw_width;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (pixel, 2, raw_width, ifp) < raw_width) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((pixel[col] = ntohs(pixel[col])) >> 14) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   maximum = 0x3ff0;
   ~~~~~~~~~~~~~~~~~            
 }
 ~                              
 
                                
 void CLASS sony_arw_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   ushort huff[32770];
   ~~~~~~~~~~~~~~~~~~~          
   static const ushort tab[18] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   { 0xf11,0xf10,0xe0f,0xd0e,0xc0d,0xb0c,0xa0b,0x90a,0x809,
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     0x708,0x607,0x506,0x405,0x304,0x303,0x300,0x202,0x201 };
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int i, c, n, col, row, sum=0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   huff[0] = 15;
   ~~~~~~~~~~~~~                
   for (n=i=0; i < 18; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~     
     FORC(32768 >> (tab[i] >> 8)) huff[++n] = tab[i];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (col = raw_width; col--; )
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (row=0; row < raw_height+1; row+=2) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (row == raw_height) row = 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((sum += ljpeg_diff(huff)) >> 12) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (row < height) RAW(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+1);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (data, "sony_arw2_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fread (data, 1, raw_width, ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (dp=data, col=0; col < raw_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)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = curve[pix[i] << 1] >> 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       col -= col & 1 ? 1:31;
       ~~~~~~~~~~~~~~~~~~~~~~   
     }
     ~                          
   }
   ~                            
   free (data);
   ~~~~~~~~~~~~                 
 }
 ~                              
 
                                
 void CLASS samsung_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
 {
 ~                              
   int row, col, c, i, dir, op[4], len[4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   order = 0x4949;
   ~~~~~~~~~~~~~~~              
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, strip_offset+row*4, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, data_offset+get4(), SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     ph1_bits(-1);
     ~~~~~~~~~~~~~              
     FORC4 len[c] = row < 2 ? 7:4;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col+=16) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       dir = ph1_bits(1);
       ~~~~~~~~~~~~~~~~~~       
       FORC4 op[c] = ph1_bits(2);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 switch (op[c]) {
       ~~~~~~~~~~~~~~~~~~~~~~   
  case 3: len[c] = ph1_bits(4); break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  case 2: len[c]--;  break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  case 1: len[c]++;
  ~~~~~~~~~~~~~~~~~             
       }
       ~                        
       for (c=0; c < 16; c+=2) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  i = len[((c & 1) << 1) | (c >> 3)];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         RAW(row,col+c) = ((signed) ph1_bits(i) << (32-i) >> (32-i)) +
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    (dir ? RAW(row+(~c | -2),col+c) : col ? RAW(row,col+(c | -2)) : 128);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (c == 14) c = -1;
  ~~~~~~~~~~~~~~~~~~~~          
       }
       ~                        
     }
     ~                          
   }
   ~                            
   for (row=0; row < raw_height-1; row+=2)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width-1; col+=2)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       SWAP (RAW(row,col+1), RAW(row+1,col));
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS samsung2_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   static const ushort tab[14] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   { 0x304,0x307,0x206,0x205,0x403,0x600,0x709,
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     0x80a,0x90b,0xa0c,0xa0d,0x501,0x408,0x402 };
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort huff[1026], vpred[2][2] = {{0,0},{0,0}}, hpred[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int i, c, n, row, col, diff;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 
                                
   huff[0] = 10;
   ~~~~~~~~~~~~~                
   for (n=i=0; i < 14; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~     
     FORC(1024 >> (tab[i] >> 8)) huff[++n] = tab[i];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       diff = ljpeg_diff (huff);
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else    hpred[col & 1] += diff;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = hpred[col & 1];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (hpred[col & 1] >> tiff_bps) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 void CLASS samsung3_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   int opt, init, mag, pmode, row, tab, col, pred, diff, i, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort lent[3][2], len[4], *prow[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   order = 0x4949;
   ~~~~~~~~~~~~~~~              
   fseek (ifp, 9, SEEK_CUR);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   opt = fgetc(ifp);
   ~~~~~~~~~~~~~~~~~            
   init = (get2(),get2());
   ~~~~~~~~~~~~~~~~~~~~~~~      
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, (data_offset-ftell(ifp)) & 15, SEEK_CUR);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     ph1_bits(-1);
     ~~~~~~~~~~~~~              
     mag = 0; pmode = 7;
     ~~~~~~~~~~~~~~~~~~~        
     FORC(6) lent[0][c] = row < 2 ? 7:4;
     ~~~~~~                     
codecs/dcraw.h:2786:5: note: in expansion of macro 'FORC'
     FORC(6) lent[0][c] = row < 2 ? 7:4;
     ^~~~
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/jpeg.d' -o 'objdir/codecs/jpeg.o' 'codecs/jpeg.cc'
codecs/dcraw.h: In function 'void dcraw::identify()':
codecs/dcraw.h:8758:29: warning: iteration 6 invokes undefined behavior [-Waggressive-loop-optimizations]
       FORC(36) xtrans[0][c] =
                ~~~~~~~~~~~~~^
  xtrans_abs[(c/6+top_margin) % 6][(c+left_margin) % 6];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
codecs/dcraw.h:178:31: note: within this loop
 #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=a+b; b=a-b; a=a-b; }
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /*
 ~~                             
    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 RAW(row,col) \
 ~~~~~~~~~~~~~~~~~~~~~~         
  raw_image[(row)*raw_width+(col)]
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 #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)][fcol(row,col)]
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 int CLASS fcol (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 filter[(row+top_margin)&15][(col+left_margin)&15];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (filters == 9) return xtrans[(row+6) % 6][(col+6) % 6];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   return FC(row,col);
   ~~~~~~~~~~~~~~~~~~~          
 }
 ~                              
 
                                
 #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
 ~~~~~~~~~~~~~~~~~~~~~~~~       
 char *my_strcasestr (char *haystack, const char *needle)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   char *c;
   ~~~~~~~~                     
   for (c = haystack; *c; c++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     if (!strncasecmp(c, needle, strlen(needle)))
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       return c;
       ~~~~~~~~~                
   return 0;
   ~~~~~~~~~                    
 }
 ~                              
 #define strcasestr my_strcasestr
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #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++;
   ~~~~~~~~~~~~~                
 }
 ~                              
 
                                
 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 cubic_spline (const int *x_, const int *y_, const int len)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   float **A, *b, *c, *d, *x, *y;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int i, j;
   ~~~~~~~~~                    
 
                                
   A = (float **) calloc (((2*len + 4)*sizeof **A + sizeof *A), 2*len);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (!A) return;
   ~~~~~~~~~~~~~~~              
   A[0] = (float *) (A + 2*len);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (i = 1; i < 2*len; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     A[i] = A[0] + 2*len*i;
     ~~~~~~~~~~~~~~~~~~~~~~     
   y = len + (x = i + (d = i + (c = i + (b = A[0] + i*i))));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (i = 0; i < len; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     x[i] = x_[i] / 65535.0;
     ~~~~~~~~~~~~~~~~~~~~~~~    
     y[i] = y_[i] / 65535.0;
     ~~~~~~~~~~~~~~~~~~~~~~~    
   }
   ~                            
   for (i = len-1; i > 0; i--) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     b[i] = (y[i] - y[i-1]) / (x[i] - x[i-1]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     d[i-1] = x[i] - x[i-1];
     ~~~~~~~~~~~~~~~~~~~~~~~    
   }
   ~                            
   for (i = 1; i < len-1; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     A[i][i] = 2 * (d[i-1] + d[i]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (i > 1) {
     ~~~~~~~~~~~~               
       A[i][i-1] = d[i-1];
       ~~~~~~~~~~~~~~~~~~~      
       A[i-1][i] = d[i-1];
       ~~~~~~~~~~~~~~~~~~~      
     }
     ~                          
     A[i][len-1] = 6 * (b[i+1] - b[i]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for(i = 1; i < len-2; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     float v = A[i+1][i] / A[i][i];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for(j = 1; j <= len-1; j++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       A[i+1][j] -= v * A[i][j];
       ~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for(i = len-2; i > 0; i--) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     float acc = 0;
     ~~~~~~~~~~~~~~             
     for(j = i; j <= len-2; j++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       acc += A[i][j]*c[j];
       ~~~~~~~~~~~~~~~~~~~~     
     c[i] = (A[i][len-1] - acc) / A[i][i];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for (i = 0; i < 0x10000; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     float x_out = (float)(i / 65535.0);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     float y_out = 0;
     ~~~~~~~~~~~~~~~~           
     for (j = 0; j < len-1; j++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (x[j] <= x_out && x_out <= x[j+1]) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  float v = x_out - x[j];
  ~~~~~~~~~~~~~~~~~~~~~~~       
  y_out = y[j] +
  ~~~~~~~~~~~~~~                
    ((y[j+1] - y[j]) / d[j] - (2 * d[j] * c[j] + c[j+1] * d[j])/6) * v
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + (c[j] * 0.5) * v*v + ((c[j+1] - c[j]) / (6 * d[j])) * v*v*v;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
     curve[i] = y_out < 0.0 ? 0 : (y_out >= 1.0 ? 65535 :
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   (ushort)(y_out * 65535.0 + 0.5));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   free (A);
   ~~~~~~~~~                    
 }
 ~                              
 
                                
 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 *pix;
   ~~~~~~~~~~~~                 
   int irow, row;
   ~~~~~~~~~~~~~~               
 
                                
   for (irow=row=0; irow < height; irow++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (data, 1, 1120, ifp) < 1120) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     pix = raw_image + row*raw_width;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (dp=data; 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    );
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     if ((row+=2) > height) row = 1;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS canon_600_correct()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   int row, col, val;
   ~~~~~~~~~~~~~~~~~~           
   static const short mul[4][2] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   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;
   ~~~~~~~~~~                   
 }
 ~                              
 
                                
 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;
   ~~~~~~~~~                    
 }
 ~                              
 
                                
 unsigned CLASS getbithuff (int nbits, ushort *huff)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   static unsigned bitbuf=0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   static int vbits=0, reset=0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   unsigned c;
   ~~~~~~~~~~~                  
 
                                
   if (nbits > 25) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   if (nbits < 0)
   ~~~~~~~~~~~~~~               
     return bitbuf = vbits = reset = 0;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (nbits == 0 || vbits < 0) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   while (!reset && vbits < nbits && (c = fgetc(ifp)) != EOF &&
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     !(reset = zero_after_ff && c == 0xff && fgetc(ifp))) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     bitbuf = (bitbuf << 8) + (uchar) c;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     vbits += 8;
     ~~~~~~~~~~~                
   }
   ~                            
   c = bitbuf << (32-vbits) >> (32-nbits);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (huff) {
   ~~~~~~~~~~~                  
     vbits -= huff[c] >> 8;
     ~~~~~~~~~~~~~~~~~~~~~~     
     c = (uchar) huff[c];
     ~~~~~~~~~~~~~~~~~~~~       
   } else
   ~~~~~~                       
     vbits -= nbits;
     ~~~~~~~~~~~~~~~            
   if (vbits < 0) derror();
   ~~~~~~~~~~~~~~~~~~~~~~~~     
   return c;
   ~~~~~~~~~                    
 }
 ~                              
 
                                
 #define getbits(n) getbithuff(n,0)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #define gethuff(h) getbithuff(*h,h+1)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /*
 ~~                             
    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
  ~~~~~~~~~~~~~                 
  */
  ~~                            
 ushort * CLASS make_decoder_ref (const uchar **source)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int max, len, h, i, j;
   ~~~~~~~~~~~~~~~~~~~~~~       
   const uchar *count;
   ~~~~~~~~~~~~~~~~~~~          
   ushort *huff;
   ~~~~~~~~~~~~~                
 
                                
   count = (*source += 16) - 17;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (max=16; max && !count[max]; max--);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff = (ushort *) calloc (1 + (1 << max), sizeof *huff);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (huff, "make_decoder()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff[0] = max;
   ~~~~~~~~~~~~~~               
   for (h=len=1; len <= max; len++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (i=0; i < count[len]; i++, ++*source)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (j=0; j < 1 << (max-len); j++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (h <= 1 << max)
  ~~~~~~~~~~~~~~~~~~            
    huff[h++] = len << 8 | **source;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   return huff;
   ~~~~~~~~~~~~                 
 }
 ~                              
 
                                
 ushort * CLASS make_decoder (const uchar *source)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   return make_decoder_ref (&source);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS crw_init_tables (unsigned table, ushort *huff[2])
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   huff[0] = make_decoder ( first_tree[table]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff[1] = make_decoder (second_tree[table]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 /*
 ~~                             
    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_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~    
 {
 ~                              
   ushort *pixel, *prow, *huff[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int nblocks, lowbits, i, c, row, r, save, val;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   crw_init_tables (tiff_compress, huff);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     pixel = raw_image + row*raw_width;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     nblocks = MIN (8, raw_height-row) * raw_width >> 6;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (block=0; block < nblocks; block++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       memset (diffbuf, 0, sizeof diffbuf);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i=0; i < 64; i++ ) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  leaf = gethuff(huff[i > 0]);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  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);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   FORC(2) free (huff[c]);
   ~~~~~~~~~~~~~~~~~~~~~~~      
 }
 ~                              
 
                                
 /*
 ~~                             
    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];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort *huff[6], *free[4], *row;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 };
 ~~                             
 
                                
 int CLASS ljpeg_start (struct jhead *jh, int info_only)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c, tag;
   ~~~~~~~~~~~                  
   ushort len;
   ~~~~~~~~~~~                  
   uchar data[0x10000];
   ~~~~~~~~~~~~~~~~~~~~         
   const uchar *dp;
   ~~~~~~~~~~~~~~~~             
 
                                
   memset (jh, 0, sizeof *jh);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   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 && (c = *dp++) < 4; )
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    jh->free[c] = jh->huff[c] = make_decoder_ref (&dp);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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->clrs > 6 || !jh->huff[0]) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC(5) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
 }
 ~                              
 
                                
 void CLASS ljpeg_end (struct jhead *jh)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c;
   ~~~~~~                       
   FORC4 if (jh->free[c]) free (jh->free[c]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   free (jh->row);
   ~~~~~~~~~~~~~~~              
 }
 ~                              
 
                                
 int CLASS ljpeg_diff (ushort *huff)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int len, diff;
   ~~~~~~~~~~~~~~               
 
                                
   if(!huff)
   ~~~~~~~~~                    
     longjmp (failure, 2);
     ~~~~~~~~~~~~~~~~~~~~~      
 
                                
   len = gethuff(huff);
   ~~~~~~~~~~~~~~~~~~~~         
   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) {
     ~~~~~~~~~~~                
       fseek (ifp, -2, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   struct jhead jh;
   ~~~~~~~~~~~~~~~~             
   ushort *rp;
   ~~~~~~~~~~~                  
 
                                
   if (!ljpeg_start (&jh, 0)) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jwide = jh.wide * jh.clrs;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
 
                                
   if(jh.wide<1 || jh.high<1 || jh.clrs<1 || jh.bits <1)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     longjmp (failure, 2);
     ~~~~~~~~~~~~~~~~~~~~~      
 
                                
   for (jrow=0; jrow < jh.high; jrow++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     rp = ljpeg_row (jrow, &jh);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (load_flags & 1)
     ~~~~~~~~~~~~~~~~~~~        
       row = jrow & 1 ? height-1-jrow/2 : jrow/2;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (jcol=0; jcol < jwide; jcol++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       val = curve[*rp++];
       ~~~~~~~~~~~~~~~~~~~      
       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(row>raw_height)
       ~~~~~~~~~~~~~~~~~~       
  longjmp (failure, 3);
  ~~~~~~~~~~~~~~~~~~~~~         
       if ((unsigned) row < raw_height) RAW(row,col) = val;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (++col >= raw_width)
       ~~~~~~~~~~~~~~~~~~~~~~~  
  col = (row++,0);
  ~~~~~~~~~~~~~~~~              
     }
     ~                          
   }
   ~                            
   ljpeg_end (&jh);
   ~~~~~~~~~~~~~~~~             
 }
 ~                              
 
                                
 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) || jh.clrs < 4) 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 >= 0x80000281 || (unique_id == 0x80000218 && ver > 1000006))
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     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 == 0x80000218 ||
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  unique_id == 0x80000250 ||
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  unique_id == 0x80000261 ||
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  unique_id == 0x80000281 ||
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  unique_id == 0x80000287) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
       rp[1] = (rp[1] << 2) + hue;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       rp[2] = (rp[2] << 2) + hue;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pix[0] = rp[0] + ((   50*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);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else {
     ~~~~~~~~                   
       if (unique_id < 0x80000218) rp[0] -= 512;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pix[0] = rp[0] + rp[2];
       ~~~~~~~~~~~~~~~~~~~~~~~  
       pix[2] = rp[0] + rp[1];
       ~~~~~~~~~~~~~~~~~~~~~~~  
       pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   ljpeg_end (&jh);
   ~~~~~~~~~~~~~~~~             
   maximum = 0x3fff;
   ~~~~~~~~~~~~~~~~~            
 }
 ~                              
 
                                
 void CLASS adobe_copy_pixel (unsigned row, unsigned col, ushort **rp)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c;
   ~~~~~~                       
 
                                
   if (is_raw == 2 && shot_select) (*rp)++;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (raw_image) {
   ~~~~~~~~~~~~~~~~             
     if (row < raw_height && col < raw_width)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[**rp];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     *rp += is_raw;
     ~~~~~~~~~~~~~~             
   } else {
   ~~~~~~~~                     
     if (row < height && col < width)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC(tiff_samples)
       ~~~~~~~~~~~~~~~~~~       
  image[row*width+col][c] = curve[(*rp)[c]];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     *rp += tiff_samples;
     ~~~~~~~~~~~~~~~~~~~~       
   }
   ~                            
   if (is_raw == 2 && shot_select) (*rp)--;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS lossless_dng_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   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);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     ljpeg_end (&jh);
     ~~~~~~~~~~~~~~~~           
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS packed_dng_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   ushort *pixel, *rp;
   ~~~~~~~~~~~~~~~~~~~          
   int row, col;
   ~~~~~~~~~~~~~                
 
                                
   pixel = (ushort *) calloc (raw_width, tiff_samples*sizeof *pixel);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (pixel, "packed_dng_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
 {
 ~                              
   ushort bit[2][15], huff[4097];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int dep, row, col, diff, c, i;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   fseek (ifp, meta_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   dep = (get2() + 12) & 15;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   fseek (ifp, 12, SEEK_CUR);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
   FORC(dep) bit[0][c] = get2();
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC(dep) bit[1][c] = fgetc(ifp);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC(dep)
   ~~~~~~~~~                    
     for (i=bit[0][c]; i <= ((bit[0][c]+(4096 >> bit[1][c])-1) & 4095); )
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       huff[++i] = bit[1][c] << 8 | c;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff[0] = 12;
   ~~~~~~~~~~~~~                
   fseek (ifp, data_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       diff = ljpeg_diff (huff);
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else    hpred[col & 1] += diff;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = hpred[col & 1];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (hpred[col & 1] >> tiff_bps) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 void CLASS nikon_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 } };
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort *huff, ver0, ver1, vpred[2][2], hpred[2], csize;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int i, min, max, step=0, tree=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) tree = 2;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   if (tiff_bps == 14) tree += 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--;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff = make_decoder (nikon_tree[tree]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fseek (ifp, data_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (min=row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (split && row == split) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       free (huff);
       ~~~~~~~~~~~~             
       huff = make_decoder (nikon_tree[tree+1]);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       max += (min = 16) << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~  
     }
     ~                          
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       i = gethuff(huff);
       ~~~~~~~~~~~~~~~~~~       
       len = i & 15;
       ~~~~~~~~~~~~~            
       shl = i >> 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();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[LIM((short)hpred[col & 1],0,0x3fff)];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   free (huff);
   ~~~~~~~~~~~~                 
 }
 ~                              
 
                                
 void CLASS nikon_yuv_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int row, col, yuv[4], rgb[3], b, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   UINT64 bitbuf=0;
   ~~~~~~~~~~~~~~~~             
 
                                
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (!(b = col & 1)) {
       ~~~~~~~~~~~~~~~~~~~~~    
  bitbuf = 0;
  ~~~~~~~~~~~                   
  FORC(6) bitbuf |= (UINT64) fgetc(ifp) << c*8;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC(4) yuv[c] = (bitbuf >> c*12 & 0xfff) - (c >> 1 << 11);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
       rgb[0] = yuv[b] + 1.370705*yuv[3];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       rgb[1] = yuv[b] - 0.337633*yuv[2] - 0.698001*yuv[3];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       rgb[2] = yuv[b] + 1.732446*yuv[2];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,0xfff)] / cam_mul[c];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 /*
 ~~                             
    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;
   ~~~~~~~~~~~~~~~              
 }
 ~                              
 
                                
 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 ppm16_thumb()
 ~~~~~~~~~~~~~~~~~~~~~~~~       
 {
 ~                              
   int i;
   ~~~~~~                       
   char *thumb;
   ~~~~~~~~~~~~                 
   thumb_length = thumb_width*thumb_height*3;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   thumb = (char *) calloc (thumb_length, 2);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (thumb, "ppm16_thumb()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   read_shorts ((ushort *) thumb, thumb_length);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (i=0; i < thumb_length; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     thumb[i] = ((ushort *) thumb)[i] >> 8;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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, 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)
     ~~~~~~~~~~~~~~~~~~~~~~~    
       raw_image[todo[i]] = (todo[i+1] & 0x3ff);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   maximum = 0x3ff;
   ~~~~~~~~~~~~~~~~             
 }
 ~                              
 
                                
 int CLASS raw (unsigned row, unsigned col)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   return (row < raw_height && col < raw_width) ? RAW(row,col) : 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS phase_one_flat_field (int is_float, int nc)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   ushort head[8];
   ~~~~~~~~~~~~~~~              
   unsigned wide, high, y, x, c, rend, cend, row, col;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   float *mrow, num, mult[4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
 
                                
   read_shorts (head, 8);
   ~~~~~~~~~~~~~~~~~~~~~~       
   if (head[2] * head[3] * head[4] * head[5] == 0) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   wide = head[2] / head[4] + (head[2] % head[4] != 0);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   high = head[3] / head[5] + (head[3] % head[5] != 0);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   mrow = (float *) calloc (nc*wide, sizeof *mrow);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (mrow, "phase_one_flat_field()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (y=0; y < high; 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] + y*head[5];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (row = rend-head[5];
     ~~~~~~~~~~~~~~~~~~~~~~~~   
   row < raw_height && row < rend &&
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   row < head[1]+head[3]-head[5]; 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] + x*head[4];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  for (col = cend-head[4];
  ~~~~~~~~~~~~~~~~~~~~~~~~      
       col < raw_width &&
       ~~~~~~~~~~~~~~~~~~       
       col < cend && col < head[0]+head[2]-head[4]; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    c = nc > 2 ? FC(row-top_margin,col-left_margin) : 0;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (!(c & 1)) {
    ~~~~~~~~~~~~~~~             
      c = RAW(row,col) * mult[c];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~
      RAW(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];
   ~~~~~~~~~~~~~~~~             
   int qmult_applied = 0, qlin_applied = 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   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 < raw_height; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col = (tag & 1)*ph1.split_col; col < raw_width; col++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    RAW(row,col) = curve[RAW(row,col)];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else if (tag == 0x400) {   /* Sensor defects */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       while ((len -= 8) >= 0) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  col  = get2();
  ~~~~~~~~~~~~~~                
  row  = get2();
  ~~~~~~~~~~~~~~                
  type = get2(); get2();
  ~~~~~~~~~~~~~~~~~~~~~~        
  if (col >= raw_width) continue;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (type == 131 || type == 137)  /* Bad column */
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (row=0; row < raw_height; row++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (FC(row-top_margin,col-left_margin) == 1) {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        for (sum=i=0; i < 4; i++)
        ~~~~~~~~~~~~~~~~~~~~~~~~~
   sum += val[i] = raw (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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        }
        ~                       
        RAW(row,col) = (sum - val[max])/3.0 + 0.5;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      } else {
      ~~~~~~~~                  
        for (sum=0, i=8; i < 12; i++)
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   sum += raw (row+dir[i][0], col+dir[i][1]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        RAW(row,col) = 0.5 + sum * 0.0732233 +
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   (raw(row,col-2) + raw(row,col+2)) * 0.3535534;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      }
      ~                         
  else if (type == 129) {   /* Bad pixel */
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (row >= raw_height) continue;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    j = (FC(row-top_margin,col-left_margin) != 1) * 4;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (sum=0, i=j; i < j+8; i++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      sum += raw (row+dir[i][0], col+dir[i][1]);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    RAW(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;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
       }
       ~                        
     } else if (tag == 0x41f && !qlin_applied) { /* Quadrant linearization */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       ushort lc[2][2][16], ref[16];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       int qr, qc;
       ~~~~~~~~~~~              
       for (qr = 0; qr < 2; qr++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (qc = 0; qc < 2; qc++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
    for (i = 0; i < 16; i++)
    ~~~~~~~~~~~~~~~~~~~~~~~~    
      lc[qr][qc][i] = (ushort)get4();
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i = 0; i < 16; i++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  int v = 0;
  ~~~~~~~~~~                    
  for (qr = 0; qr < 2; qr++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
    for (qc = 0; qc < 2; qc++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
      v += lc[qr][qc][i];
      ~~~~~~~~~~~~~~~~~~~       
  ref[i] = (v + 2) >> 2;
  ~~~~~~~~~~~~~~~~~~~~~~        
       }
       ~                        
       for (qr = 0; qr < 2; qr++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (qc = 0; qc < 2; qc++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    int cx[18], cf[18];
    ~~~~~~~~~~~~~~~~~~~         
    for (i = 0; i < 16; i++) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
      cx[1+i] = lc[qr][qc][i];
      ~~~~~~~~~~~~~~~~~~~~~~~~  
      cf[1+i] = ref[i];
      ~~~~~~~~~~~~~~~~~         
    }
    ~                           
    cx[0] = cf[0] = 0;
    ~~~~~~~~~~~~~~~~~~          
    cx[17] = cf[17] = ((unsigned int)ref[15] * 65535) / lc[qr][qc][15];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    cubic_spline(cx, cf, 18);
    ~~~~~~~~~~~~~~~~~~~~~~~~~   
 
                                
    for (row = (qr ? ph1.split_row : 0);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         row < (qr ? raw_height : ph1.split_row); row++)
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (col = (qc ? ph1.split_col : 0);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    col < (qc ? raw_width : ph1.split_col); col++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        RAW(row,col) = curve[RAW(row,col)];
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       }
       ~                        
       qlin_applied = 1;
       ~~~~~~~~~~~~~~~~~        
     } else if (tag == 0x41e && !qmult_applied) { /* Quadrant multipliers */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       float qmult[2][2] = { { 1, 1 }, { 1, 1 } };
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       get4(); get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       qmult[0][0] = 1.0 + getreal(11);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       get4(); get4(); get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       qmult[0][1] = 1.0 + getreal(11);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~  
       qmult[1][0] = 1.0 + getreal(11);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~  
       qmult[1][1] = 1.0 + getreal(11);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (row=0; row < raw_height; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col=0; col < raw_width; col++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    i = qmult[row >= ph1.split_row][col >= ph1.split_col] * RAW(row,col);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    RAW(row,col) = LIM(i,0,65535);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       qmult_applied = 1;
       ~~~~~~~~~~~~~~~~~~       
     } else if (tag == 0x431 && !qmult_applied) { /* Quadrant combined */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       ushort lc[2][2][7], ref[7];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       int qr, qc;
       ~~~~~~~~~~~              
       for (i = 0; i < 7; i++)
       ~~~~~~~~~~~~~~~~~~~~~~~  
  ref[i] = (ushort)get4();
  ~~~~~~~~~~~~~~~~~~~~~~~~      
       for (qr = 0; qr < 2; qr++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (qc = 0; qc < 2; qc++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
    for (i = 0; i < 7; i++)
    ~~~~~~~~~~~~~~~~~~~~~~~     
      lc[qr][qc][i] = (ushort)get4();
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (qr = 0; qr < 2; qr++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (qc = 0; qc < 2; qc++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    int cx[9], cf[9];
    ~~~~~~~~~~~~~~~~~           
    for (i = 0; i < 7; i++) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~   
      cx[1+i] = ref[i];
      ~~~~~~~~~~~~~~~~~         
      cf[1+i] = ((unsigned int)ref[i] * lc[qr][qc][i]) / 10000;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    }
    ~                           
    cx[0] = cf[0] = 0;
    ~~~~~~~~~~~~~~~~~~          
    cx[8] = cf[8] = 65535;
    ~~~~~~~~~~~~~~~~~~~~~~      
    cubic_spline(cx, cf, 9);
    ~~~~~~~~~~~~~~~~~~~~~~~~    
    for (row = (qr ? ph1.split_row : 0);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         row < (qr ? raw_height : ph1.split_row); row++)
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (col = (qc ? ph1.split_col : 0);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    col < (qc ? raw_width : ph1.split_col); col++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        RAW(row,col) = curve[RAW(row,col)];
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         }
         ~                      
       }
       ~                        
       qmult_applied = 1;
       ~~~~~~~~~~~~~~~~~~       
       qlin_applied = 1;
       ~~~~~~~~~~~~~~~~~        
     }
     ~                          
     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 < raw_height; row++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < raw_width; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cfrac = (float) col * head[3] / raw_width;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cfrac -= cip = cfrac;
  ~~~~~~~~~~~~~~~~~~~~~         
  num = RAW(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 + num) * 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = LIM(i,0,65535);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     free (yval[0]);
     ~~~~~~~~~~~~~~~            
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS phase_one_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int a, b, i;
   ~~~~~~~~~~~~                 
   ushort akey, bkey, mask;
   ~~~~~~~~~~~~~~~~~~~~~~~~     
 
                                
   fseek (ifp, ph1.key_off, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   akey = get2();
   ~~~~~~~~~~~~~~               
   bkey = get2();
   ~~~~~~~~~~~~~~               
   mask = ph1.format == 1 ? 0x5555:0x1354;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fseek (ifp, data_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   read_shorts (raw_image, raw_width*raw_height);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (ph1.format)
   ~~~~~~~~~~~~~~~              
     for (i=0; i < raw_width*raw_height; i+=2) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       a = raw_image[i+0] ^ akey;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       b = raw_image[i+1] ^ bkey;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       raw_image[i+0] = (a & mask) | (b & ~mask);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       raw_image[i+1] = (b & mask) | (a & ~mask);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 unsigned CLASS ph1_bithuff (int nbits, ushort *huff)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   static UINT64 bitbuf=0;
   ~~~~~~~~~~~~~~~~~~~~~~~      
   static int vbits=0;
   ~~~~~~~~~~~~~~~~~~~          
   unsigned c;
   ~~~~~~~~~~~                  
 
                                
   if (nbits == -1)
   ~~~~~~~~~~~~~~~~             
     return bitbuf = vbits = 0;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   if (nbits == 0) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   if (vbits < nbits) {
   ~~~~~~~~~~~~~~~~~~~~         
     bitbuf = bitbuf << 32 | get4();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     vbits += 32;
     ~~~~~~~~~~~~               
   }
   ~                            
   c = bitbuf << (64-vbits) >> (64-nbits);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (huff) {
   ~~~~~~~~~~~                  
     vbits -= huff[c] >> 8;
     ~~~~~~~~~~~~~~~~~~~~~~     
     return (uchar) huff[c];
     ~~~~~~~~~~~~~~~~~~~~~~~    
   }
   ~                            
   vbits -= nbits;
   ~~~~~~~~~~~~~~~              
   return c;
   ~~~~~~~~~                    
 }
 ~                              
 #define ph1_bits(n) ph1_bithuff(n,0)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #define ph1_huff(h) ph1_bithuff(*h,h+1)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 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 (*cblack)[2], (*rblack)[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   pixel = (ushort *) calloc (raw_width*3 + 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();
     ~~~~~~~~~~~~~~~~~~~~~      
   cblack = (short (*)[2]) (offset + raw_height);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fseek (ifp, ph1.black_col, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (ph1.black_col)
   ~~~~~~~~~~~~~~~~~~           
     read_shorts ((ushort *) cblack[0], raw_height*2);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   rblack = cblack + raw_height;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fseek (ifp, ph1.black_row, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (ph1.black_row)
   ~~~~~~~~~~~~~~~~~~           
     read_shorts ((ushort *) rblack[0], raw_width*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]];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       i = (pixel[col] << 2) - ph1.black
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  + cblack[row][col >= ph1.split_col]
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  + rblack[col][row >= ph1.split_row];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (i > 0) RAW(row,col) = i;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   free (pixel);
   ~~~~~~~~~~~~~                
   maximum = 0xfffc - ph1.black;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS hasselblad_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   struct jhead jh;
   ~~~~~~~~~~~~~~~~             
   int shot, row, col, *back[5], len[2], diff[12], pred, sh, f, s, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   unsigned upix, urow, ucol;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
   ushort *ip;
   ~~~~~~~~~~~                  
 
                                
   if (!ljpeg_start (&jh, 0)) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   order = 0x4949;
   ~~~~~~~~~~~~~~~              
   ph1_bits(-1);
   ~~~~~~~~~~~~~                
   back[4] = (int *) calloc (raw_width, 3*sizeof **back);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (back[4], "hasselblad_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC3 back[c] = back[4] + c*raw_width;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cblack[6] >>= sh = tiff_samples > 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   shot = LIM(shot_select, 1, tiff_samples) - 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC4 back[(c+3) & 3] = back[c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col+=2) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (s=0; s < tiff_samples*2; s+=2) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC(2) len[c] = ph1_huff(jh.huff[0]);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC(2) {
  ~~~~~~~~~                     
    diff[s+c] = ph1_bits(len[c]);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if ((diff[s+c] & (1 << (len[c]-1))) == 0)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      diff[s+c] -= (1 << len[c]) - 1;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (diff[s+c] == 65535) diff[s+c] = -32768;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       }
       ~                        
       for (s=col; s < col+2; s++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pred = 0x8000 + load_flags;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  if (col) pred = back[2][s-2];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  if (col && row > 1) switch (jh.psv) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    case 11: pred += back[0][s]/2 - back[0][s-2]/2;  break;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
  f = (row & 1)*3 ^ ((col+s) & 1);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC (tiff_samples) {
  ~~~~~~~~~~~~~~~~~~~~~         
    pred += diff[(s & 1)*tiff_samples+c];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    upix = pred >> sh & 0xffff;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    if (raw_image && c == shot)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
      RAW(row,s) = upix;
      ~~~~~~~~~~~~~~~~~~        
    if (image) {
    ~~~~~~~~~~~~                
      urow = row-top_margin  + (c & 1);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      ucol = col-left_margin - ((c >> 1) & 1);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      ip = &image[urow*width+ucol][f];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (urow < height && ucol < width)
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        *ip = c < 4 ? upix : (*ip + upix) >> 1;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    }
    ~                           
  }
  ~                             
  back[2][s] = pred;
  ~~~~~~~~~~~~~~~~~~            
       }
       ~                        
     }
     ~                          
   }
   ~                            
   free (back[4]);
   ~~~~~~~~~~~~~~~              
   ljpeg_end (&jh);
   ~~~~~~~~~~~~~~~~             
   if (image) mix_green = 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
 }
 ~                              
 
                                
 void CLASS leaf_hdr_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   ushort *pixel=0;
   ~~~~~~~~~~~~~~~~             
   unsigned tile=0, r, c, row, col;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (!filters) {
   ~~~~~~~~~~~~~~~              
     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(), SEEK_SET);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
       if (filters && c != shot_select) continue;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (filters) pixel = raw_image + r*raw_width;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       read_shorts (pixel, raw_width);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (!filters && (row = r - top_margin) < height)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col=0; col < width; col++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    image[row*width+col][c] = pixel[col+left_margin];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   if (!filters) {
   ~~~~~~~~~~~~~~~              
     maximum = 0xffff;
     ~~~~~~~~~~~~~~~~~          
     raw_color = 1;
     ~~~~~~~~~~~~~~             
     free (pixel);
     ~~~~~~~~~~~~~              
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS unpacked_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   int row, col, bits=0;
   ~~~~~~~~~~~~~~~~~~~~~        
 
                                
   while (1 << ++bits < maximum);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   read_shorts (raw_image, raw_width*raw_height);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((RAW(row,col) >>= load_flags) >> bits
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  && (unsigned) (row-top_margin) < height
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  && (unsigned) (col-left_margin) < width) derror();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS sinar_4shot_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   ushort *pixel;
   ~~~~~~~~~~~~~~               
   unsigned shot, row, col, r, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (raw_image) {
   ~~~~~~~~~~~~~~~~             
     shot = LIM (shot_select, 1, 4) - 1;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, data_offset + shot*4, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, get4(), SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     unpacked_load_raw();
     ~~~~~~~~~~~~~~~~~~~~       
     return;
     ~~~~~~~                    
   }
   ~                            
   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][(row & 1)*3 ^ (~col & 1)] = pixel[col];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
   }
   ~                            
   free (pixel);
   ~~~~~~~~~~~~~                
   mix_green = 1;
   ~~~~~~~~~~~~~~               
 }
 ~                              
 
                                
 void CLASS imacon_full_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int row, col;
   ~~~~~~~~~~~~~                
 
                                
   if (!image) return;
   ~~~~~~~~~~~~~~~~~~~          
   for (row=0; row < height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       read_shorts (image[row*width+col], 3);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS packed_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
 {
 ~                              
   int vbits=0, bwide, rbits, bite, half, irow, row, col, val, i;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   UINT64 bitbuf=0;
   ~~~~~~~~~~~~~~~~             
 
                                
   bwide = raw_width * tiff_bps / 8;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   bwide += bwide & load_flags >> 7;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   rbits = bwide * 8 - raw_width * tiff_bps;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (load_flags & 1) bwide = bwide * 16 / 15;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   bite = 8 + (load_flags & 24);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   half = (raw_height+1) >> 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   for (irow=0; irow < raw_height; irow++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     row = irow;
     ~~~~~~~~~~~                
     if (load_flags & 2 &&
     ~~~~~~~~~~~~~~~~~~~~~      
  (row = irow % half * 2 + irow / half) == 1 &&
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  load_flags & 4) {
  ~~~~~~~~~~~~~~~~~             
       if (vbits=0, tiff_compress)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  fseek (ifp, data_offset - (-half*bwide & -2048), SEEK_SET);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else {
       ~~~~~~                   
  fseek (ifp, 0, SEEK_END);
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  fseek (ifp, ftell(ifp) >> 3 << 2, SEEK_SET);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (vbits -= tiff_bps; vbits < 0; vbits += bite) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  bitbuf <<= bite;
  ~~~~~~~~~~~~~~~~              
  for (i=0; i < bite; i+=8)
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
    bitbuf |= (unsigned) (fgetc(ifp) << i);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
       val = bitbuf << (64-tiff_bps-vbits) >> (64-tiff_bps);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col ^ (load_flags >> 6 & 1)) = val;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (load_flags & 1 && (col % 10) == 9 && fgetc(ifp) &&
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  row < height+top_margin && col < width+left_margin) derror();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     vbits -= rbits;
     ~~~~~~~~~~~~~~~            
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS nokia_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~    
 {
 ~                              
   uchar  *data,  *dp;
   ~~~~~~~~~~~~~~~~~~~          
   int rev, dwide, row, col, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   double sum[]={0,0};
   ~~~~~~~~~~~~~~~~~~~          
 
                                
   rev = 3 * (order == 0x4949);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   dwide = (raw_width * 5 + 1) / 4;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   data = (uchar *) malloc (dwide*2);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (data, "nokia_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (data+dwide, 1, dwide, ifp) < dwide) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC(dwide) data[c] = data[dwide+(c ^ rev)];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (dp=data, col=0; col < raw_width; dp+=5, col+=4)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 RAW(row,col+c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   free (data);
   ~~~~~~~~~~~~                 
   maximum = 0x3ff;
   ~~~~~~~~~~~~~~~~             
   if (strcmp(make,"OmniVision")) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   row = raw_height/2;
   ~~~~~~~~~~~~~~~~~~~          
   FORC(width-1) {
   ~~~~~~~~~~~~~~~              
     sum[ c & 1] += SQR(RAW(row,c)-RAW(row+1,c+1));
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     sum[~c & 1] += SQR(RAW(row+1,c)-RAW(row,c+1));
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   if (sum[1] > sum[0]) filters = 0x4b4b4b4b;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS canon_rmf_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int row, col, bits, orow, ocol, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width-2; col+=3) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       bits = get4();
       ~~~~~~~~~~~~~~           
       FORC3 {
       ~~~~~~~                  
  orow = row;
  ~~~~~~~~~~~                   
  if ((ocol = col+c-4) < 0) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
    ocol += raw_width;
    ~~~~~~~~~~~~~~~~~~          
    if ((orow -= 2) < 0)
    ~~~~~~~~~~~~~~~~~~~~        
      orow += raw_height;
      ~~~~~~~~~~~~~~~~~~~       
  }
  ~                             
  RAW(orow,ocol) = curve[bits >> (10*c+2) & 0x3ff];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
   maximum = curve[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 ((RAW(row,col) = pred[col & 1]) > 4098 && col < width) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 void CLASS olympus_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
 {
 ~                              
   ushort huff[4096];
   ~~~~~~~~~~~~~~~~~~           
   int row, col, nbits, sign, low, high, i, c, w, n, nw;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int acarry[2][3], *carry, pred, diff;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   huff[n=0] = 0xc0c;
   ~~~~~~~~~~~~~~~~~~           
   for (i=12; i--; )
   ~~~~~~~~~~~~~~~~~            
     FORC(2048 >> i) huff[++n] = (i+1) << 8 | i;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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++);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       low = (sign = getbits(3)) & 3;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       sign = sign << 29 >> 31;
       ~~~~~~~~~~~~~~~~~~~~~~~~ 
       if ((high = getbithuff(12,huff)) == 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 = RAW(row,col-2);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else if (col < 2) pred = RAW(row-2,col);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else {
       ~~~~~~                   
  w  = RAW(row,col-2);
  ~~~~~~~~~~~~~~~~~~~~          
  n  = RAW(row-2,col);
  ~~~~~~~~~~~~~~~~~~~~          
  nw = RAW(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 ((RAW(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) RAW(row,col) = (col+1) & 2 ?
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,1)    = pixel[1]   << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,1533) = pixel[765] << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else
     ~~~~~~                     
       for (col=row & 1; col < 1534; col+=2)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = pixel[col/2] << 1;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   maximum = 0xff << 1;
   ~~~~~~~~~~~~~~~~~~~~         
 }
 ~                              
 
                                
 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++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[pixel[row+2][col+2]];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   maximum = 0x3ff;
   ~~~~~~~~~~~~~~~~             
 }
 ~                              
 
                                
 #define radc_token(tree) ((signed char) getbithuff(8,huff[tree]))
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 #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)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 #define ARRAY_SIZE(_array) (sizeof(_array) / sizeof((_array)[0]))
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 void CLASS kodak_radc_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   static const char src[] = {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     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
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   };
   ~~                           
   ushort huff[19][256];
   ~~~~~~~~~~~~~~~~~~~~~        
   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;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (s=i=0; i < sizeof src; i+=2)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC(256 >> src[i])
     ~~~~~~~~~~~~~~~~~~~        
       huff[0][s++] = src[i] << 8 | (uchar) src[i+1];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   s = kodak_cbpp == 243 ? 2 : 3;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC(256) huff[18][c] = (8-s) << 8 | c >> s << s | 1 << (s-1);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (c=0; c < ARRAY_SIZE(buf); c++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (y=0; y < ARRAY_SIZE(buf[0]); y++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (x=0; y < ARRAY_SIZE(buf[0][0]); x++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         buf[c][y][x] = 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] = (uchar) radc_token(18) * 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) RAW(row+y*2+c-1,x*2+2-c) = val;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      else   RAW(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 = (RAW(y,x)-2048)*2 + (RAW(y,r)+RAW(y,s))/2;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (val < 0) val = 0;
    ~~~~~~~~~~~~~~~~~~~~~       
    RAW(y,x) = val;
    ~~~~~~~~~~~~~~~             
  }
  ~                             
   }
   ~                            
   for (i=0; i < height*width; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     raw_image[i] = curve[raw_image[i]];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   maximum = 0x3fff;
   ~~~~~~~~~~~~~~~~~            
 }
 ~                              
 
                                
 #undef FORYX
 ~~~~~~~~~~~~                   
 #undef PREDICTOR
 ~~~~~~~~~~~~~~~~               
 
                                
 #ifdef NO_JPEG
 ~~~~~~~~~~~~~~                 
 void CLASS kodak_jpeg_load_raw() {}
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 void CLASS lossy_dng_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) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row+0,col+0) = pixel[col+0][1] << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row+1,col+1) = pixel[col+1][1] << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   jpeg_finish_decompress (&cinfo);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jpeg_destroy_decompress (&cinfo);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   maximum = 0xff << 1;
   ~~~~~~~~~~~~~~~~~~~~         
 }
 ~                              
 
                                
 void CLASS gamma_curve (double pwr, double ts, int mode, int imax);
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 void CLASS lossy_dng_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   struct jpeg_decompress_struct cinfo;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   struct jpeg_error_mgr jerr;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   JSAMPARRAY buf;
   ~~~~~~~~~~~~~~~              
   JSAMPLE (*pixel)[3];
   ~~~~~~~~~~~~~~~~~~~~         
   unsigned sorder=order, ntags, opcode, deg, i, j, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   unsigned save=data_offset-4, trow=0, tcol=0, row, col;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort cur[3][256];
   ~~~~~~~~~~~~~~~~~~~          
   double coeff[9], tot;
   ~~~~~~~~~~~~~~~~~~~~~        
 
                                
   if (meta_offset) {
   ~~~~~~~~~~~~~~~~~~           
     fseek (ifp, meta_offset, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     order = 0x4d4d;
     ~~~~~~~~~~~~~~~            
     ntags = get4();
     ~~~~~~~~~~~~~~~            
     while (ntags--) {
     ~~~~~~~~~~~~~~~~~          
       opcode = get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (opcode != 8)
       ~~~~~~~~~~~~~~~~         
       { fseek (ifp, get4(), SEEK_CUR); continue; }
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, 20, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((c = get4()) > 2) break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, 12, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((deg = get4()) > 8) break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i=0; i <= deg && i < 9; i++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  coeff[i] = getreal(12);
  ~~~~~~~~~~~~~~~~~~~~~~~       
       for (i=0; i < 256; i++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  for (tot=j=0; j <= deg; j++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    tot += coeff[j] * pow(i/255.0, j);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cur[c][i] = tot*0xffff;
  ~~~~~~~~~~~~~~~~~~~~~~~       
       }
       ~                        
     }
     ~                          
     order = sorder;
     ~~~~~~~~~~~~~~~            
   } else {
   ~~~~~~~~                     
     gamma_curve (1/2.4, 12.92, 1, 255);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC3 memcpy (cur[c], curve, sizeof cur[0]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   cinfo.err = jpeg_std_error (&jerr);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jpeg_create_decompress (&cinfo);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   while (trow < raw_height) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     fseek (ifp, save+=4, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tile_length < INT_MAX)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
       fseek (ifp, get4(), SEEK_SET);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     jpeg_stdio_src (&cinfo, ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     jpeg_read_header (&cinfo, TRUE);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     jpeg_start_decompress (&cinfo);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     buf = (*cinfo.mem->alloc_sarray)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width*3, 1);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     while (cinfo.output_scanline < cinfo.output_height &&
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  (row = trow + cinfo.output_scanline) < height) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       jpeg_read_scanlines (&cinfo, buf, 1);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pixel = (JSAMPLE (*)[3]) buf[0];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < cinfo.output_width && tcol+col < width; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC3 image[row*width+tcol+col][c] = cur[c][pixel[col][c]];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
     jpeg_abort_decompress (&cinfo);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if ((tcol += tile_width) >= raw_width)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       trow += tile_length + (tcol = 0);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   jpeg_destroy_decompress (&cinfo);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   maximum = 0xffff;
   ~~~~~~~~~~~~~~~~~            
 }
 ~                              
 #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++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = (ushort) pixel[(col + shift) % 848];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   maximum = 0xff;
   ~~~~~~~~~~~~~~~              
 }
 ~                              
 
                                
 void CLASS eight_bit_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   uchar *pixel;
   ~~~~~~~~~~~~~                
   unsigned row, col;
   ~~~~~~~~~~~~~~~~~~           
 
                                
   pixel = (uchar *) calloc (raw_width, sizeof *pixel);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (pixel, "eight_bit_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[pixel[col]];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   free (pixel);
   ~~~~~~~~~~~~~                
   maximum = curve[0xff];
   ~~~~~~~~~~~~~~~~~~~~~~       
 }
 ~                              
 
                                
 void CLASS kodak_c330_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   uchar *pixel;
   ~~~~~~~~~~~~~                
   int row, col, y, cb, cr, rgb[3], c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   pixel = (uchar *) calloc (raw_width, 2*sizeof *pixel);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (pixel, "kodak_c330_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (pixel, raw_width, 2, ifp) < 2) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (load_flags && (row & 31) == 31)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, raw_width*32, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       y  = pixel[col*2];
       ~~~~~~~~~~~~~~~~~~       
       cb = pixel[(col*2 & -4) | 1] - 128;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       cr = pixel[(col*2 & -4) | 3] - 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_c603_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   uchar *pixel;
   ~~~~~~~~~~~~~                
   int row, col, y, cb, cr, rgb[3], c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (pixel, "kodak_c603_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (~row & 1)
     ~~~~~~~~~~~~~              
       if (fread (pixel, raw_width, 3, ifp) < 3) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < 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 } };
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort *huff[2];
   ~~~~~~~~~~~~~~~~             
   uchar *pixel;
   ~~~~~~~~~~~~~                
   int *strip, ns, c, row, col, chess, pi=0, pi1, pi2, pred, val;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   FORC(2) huff[c] = make_decoder (kodak_tree[c]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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;
   ~~~~~~~~~~~~~~~              
   FORC(ns) strip[c] = 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 (huff[chess]);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (val >> 8) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~  
       val = curve[pixel[pi++]];
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = val;
       ~~~~~~~~~~~~~~~~~~~      
     }
     ~                          
   }
   ~                            
   free (pixel);
   ~~~~~~~~~~~~~                
   FORC(2) free (huff[c]);
   ~~~~~~~~~~~~~~~~~~~~~~~      
 }
 ~                              
 
                                
 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 ((RAW(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;
   ~~~~~~~~~~~                  
 
                                
   if (!image) return;
   ~~~~~~~~~~~~~~~~~~~          
   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-- && p++)
   ~~~~~~~~~~~~~~~~~~~~         
     *data++ ^= pad[(p-1) & 127] = pad[p & 127] ^ pad[(p+64) & 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);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     pixel = raw_image + row*raw_width;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (pixel, 2, raw_width, ifp) < raw_width) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((pixel[col] = ntohs(pixel[col])) >> 14) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   maximum = 0x3ff0;
   ~~~~~~~~~~~~~~~~~            
 }
 ~                              
 
                                
 void CLASS sony_arw_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   ushort huff[32770];
   ~~~~~~~~~~~~~~~~~~~          
   static const ushort tab[18] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   { 0xf11,0xf10,0xe0f,0xd0e,0xc0d,0xb0c,0xa0b,0x90a,0x809,
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     0x708,0x607,0x506,0x405,0x304,0x303,0x300,0x202,0x201 };
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int i, c, n, col, row, sum=0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   huff[0] = 15;
   ~~~~~~~~~~~~~                
   for (n=i=0; i < 18; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~     
     FORC(32768 >> (tab[i] >> 8)) huff[++n] = tab[i];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (col = raw_width; col--; )
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (row=0; row < raw_height+1; row+=2) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (row == raw_height) row = 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((sum += ljpeg_diff(huff)) >> 12) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (row < height) RAW(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+1);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (data, "sony_arw2_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fread (data, 1, raw_width, ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (dp=data, col=0; col < raw_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)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = curve[pix[i] << 1] >> 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       col -= col & 1 ? 1:31;
       ~~~~~~~~~~~~~~~~~~~~~~   
     }
     ~                          
   }
   ~                            
   free (data);
   ~~~~~~~~~~~~                 
 }
 ~                              
 
                                
 void CLASS samsung_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
 {
 ~                              
   int row, col, c, i, dir, op[4], len[4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   order = 0x4949;
   ~~~~~~~~~~~~~~~              
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, strip_offset+row*4, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, data_offset+get4(), SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     ph1_bits(-1);
     ~~~~~~~~~~~~~              
     FORC4 len[c] = row < 2 ? 7:4;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col+=16) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       dir = ph1_bits(1);
       ~~~~~~~~~~~~~~~~~~       
       FORC4 op[c] = ph1_bits(2);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 switch (op[c]) {
       ~~~~~~~~~~~~~~~~~~~~~~   
  case 3: len[c] = ph1_bits(4); break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  case 2: len[c]--;  break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  case 1: len[c]++;
  ~~~~~~~~~~~~~~~~~             
       }
       ~                        
       for (c=0; c < 16; c+=2) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  i = len[((c & 1) << 1) | (c >> 3)];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         RAW(row,col+c) = ((signed) ph1_bits(i) << (32-i) >> (32-i)) +
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    (dir ? RAW(row+(~c | -2),col+c) : col ? RAW(row,col+(c | -2)) : 128);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (c == 14) c = -1;
  ~~~~~~~~~~~~~~~~~~~~          
       }
       ~                        
     }
     ~                          
   }
   ~                            
   for (row=0; row < raw_height-1; row+=2)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width-1; col+=2)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       SWAP (RAW(row,col+1), RAW(row+1,col));
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS samsung2_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   static const ushort tab[14] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   { 0x304,0x307,0x206,0x205,0x403,0x600,0x709,
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     0x80a,0x90b,0xa0c,0xa0d,0x501,0x408,0x402 };
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort huff[1026], vpred[2][2] = {{0,0},{0,0}}, hpred[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int i, c, n, row, col, diff;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 
                                
   huff[0] = 10;
   ~~~~~~~~~~~~~                
   for (n=i=0; i < 14; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~     
     FORC(1024 >> (tab[i] >> 8)) huff[++n] = tab[i];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       diff = ljpeg_diff (huff);
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else    hpred[col & 1] += diff;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = hpred[col & 1];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (hpred[col & 1] >> tiff_bps) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 void CLASS samsung3_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   int opt, init, mag, pmode, row, tab, col, pred, diff, i, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort lent[3][2], len[4], *prow[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   order = 0x4949;
   ~~~~~~~~~~~~~~~              
   fseek (ifp, 9, SEEK_CUR);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   opt = fgetc(ifp);
   ~~~~~~~~~~~~~~~~~            
   init = (get2(),get2());
   ~~~~~~~~~~~~~~~~~~~~~~~      
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, (data_offset-ftell(ifp)) & 15, SEEK_CUR);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     ph1_bits(-1);
     ~~~~~~~~~~~~~              
     mag = 0; pmode = 7;
     ~~~~~~~~~~~~~~~~~~~        
     FORC(6) lent[0][c] = row < 2 ? 7:4;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     prow[ row & 1] = &RAW(row-1,1-((row & 1) << 1)); // green
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     prow[~row & 1] = &RAW(row-2,0);   // red and blue
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (tab=0; tab+15 < raw_width; tab+=16) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (~opt & 4 && !(tab & 63)) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  i = ph1_bits(2);
  ~~~~~~~~~~~~~~~~              
  mag = i < 3 ? mag-'2'+"204"[i] : ph1_bits(12);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
       if (opt & 2)
       ~~~~~~~~~~~~             
  pmode = 7 - 4*ph1_bits(1);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
       else if (!ph1_bits(1))
       ~~~~~~~~~~~~~~~~~~~~~~   
  pmode = ph1_bits(3);
  ~~~~~~~~~~~~~~~~~~~~          
       if (opt & 1 || !ph1_bits(1)) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC4 len[c] = ph1_bits(2);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  FORC4 {
  ~~~~~~~                       
    i = ((row & 1) << 1 | (c & 1)) % 3;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    len[c] = len[c] < 3 ? lent[i][0]-'1'+"120"[len[c]] : ph1_bits(4);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    lent[i][0] = lent[i][1];
    ~~~~~~~~~~~~~~~~~~~~~~~~    
    lent[i][1] = len[c];
    ~~~~~~~~~~~~~~~~~~~~        
  }
  ~                             
       }
       ~                        
       FORC(16) {
       ~~~~~~~~~~               
  col = tab + (((c & 7) << 1)^(c >> 3)^(row & 1));
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pred = (pmode == 7 || row < 2)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       ? (tab ? RAW(row,tab-2+(col & 1)) : init)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       : (prow[col & 1][col-'4'+"0224468"[pmode]] +
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   prow[col & 1][col-'4'+"0244668"[pmode]] + 1) >> 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  diff = ph1_bits (i = len[c >> 2]);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (diff >> (i-1)) diff -= 1 << i;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  diff = diff * (mag*2+1) + mag;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = pred + diff;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
       }
       ~                        
     }
     ~                          
   }
   ~                            
 }
 ~                              
 
                                
 #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 pix, s, count, bin, next, i, sym[3];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   uchar diff, pred[]={0,0};
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   ushort data=0, range=0;
   ~~~~~~~~~~~~~~~~~~~~~~~      
 
                                
   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;
       ~~~~~~~~~                
     if(pix>=raw_width*raw_height)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         return;
         ~~~~~~~                
     raw_image[pix] = pred[pix & 1] += diff;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!(pix & 1) && HOLE(pix / raw_width)) 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] = RAW(row-1,col-1);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       val[1] = RAW(row-1,col+1);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       val[2] = RAW(row+1,col-1);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       val[3] = RAW(row+1,col+1);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = median4(val);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     for (col=2; col < width-2; col+=4)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (HOLE(row-2) || HOLE(row+2))
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = (RAW(row,col-2) + RAW(row,col+2)) >> 1;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else {
       ~~~~~~                   
  val[0] = RAW(row,col-2);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  val[1] = RAW(row,col+2);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  val[2] = RAW(row-2,col);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  val[3] = RAW(row+2,col);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  RAW(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 redcine_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
 {
 ~                              
 #ifndef NO_JASPER
 ~~~~~~~~~~~~~~~~~              
   int c, row, col;
   ~~~~~~~~~~~~~~~~             
   jas_stream_t *in;
   ~~~~~~~~~~~~~~~~~            
   jas_image_t *jimg;
   ~~~~~~~~~~~~~~~~~~           
   jas_matrix_t *jmat;
   ~~~~~~~~~~~~~~~~~~~          
   jas_seqent_t *data;
   ~~~~~~~~~~~~~~~~~~~          
   ushort *img, *pix;
   ~~~~~~~~~~~~~~~~~~           
 
                                
   jas_init();
   ~~~~~~~~~~~                  
   in = jas_stream_fopen (ifname, "rb");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jas_stream_seek (in, data_offset+20, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jimg = jas_image_decode (in, -1, 0);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (!jimg) longjmp (failure, 3);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jmat = jas_matrix_create (height/2, width/2);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (jmat, "redcine_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   img = (ushort *) calloc ((height+2), (width+2)*2);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (img, "redcine_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC4 {
   ~~~~~~~                      
     jas_image_readcmpt (jimg, c, 0, 0, width/2, height/2, jmat);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     data = jas_matrix_getref (jmat, 0, 0);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (row = c >> 1; row < height; row+=2)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col = c & 1; col < width; col+=2)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  img[(row+1)*(width+2)+col+1] = data[(row/2)*(width/2)+col/2];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for (col=1; col <= width; col++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     img[col] = img[2*(width+2)+col];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     img[(height+1)*(width+2)+col] = img[(height-1)*(width+2)+col];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for (row=0; row < height+2; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     img[row*(width+2)] = img[row*(width+2)+2];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     img[(row+1)*(width+2)-1] = img[(row+1)*(width+2)-3];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for (row=1; row <= height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     pix = img + row*(width+2) + (col = 1 + (FC(row,1) & 1));
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (   ; col <= width; col+=2, pix+=2) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       c = (((pix[0] - 0x800) << 3) +
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pix[-(width+2)] + pix[width+2] + pix[-1] + pix[1]) >> 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pix[0] = LIM(c,0,4095);
       ~~~~~~~~~~~~~~~~~~~~~~~  
     }
     ~                          
   }
   ~                            
   for (row=0; row < height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[img[(row+1)*(width+2)+col+1]];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   free (img);
   ~~~~~~~~~~~                  
   jas_matrix_destroy (jmat);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
   jas_image_destroy (jimg);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   jas_stream_close (in);
   ~~~~~~~~~~~~~~~~~~~~~~       
 #endif
 ~~~~~~                         
 }
 ~                              
 
                                
 /* 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();
       ~~~~~~~~~~~~~~~~~        
     memset (first_decode, 0, sizeof first_decode);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     free_decode = first_decode;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   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_sd_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   struct decode *dindex;
   ~~~~~~~~~~~~~~~~~~~~~~       
   short diff[1024];
   ~~~~~~~~~~~~~~~~~            
   unsigned bitbuf=0;
   ~~~~~~~~~~~~~~~~~~           
   int pred[3], row, col, bit=-1, c, i;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   read_shorts ((ushort *) diff, 1024);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (!load_flags) foveon_decoder (1024, 0);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   for (row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     memset (pred, 0, sizeof pred);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!bit && !load_flags && atoi(model+2) < 14) get4();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=bit=0; col < width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (load_flags) {
       ~~~~~~~~~~~~~~~~~        
  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];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS foveon_huff (ushort *huff)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int i, j, clen, code;
   ~~~~~~~~~~~~~~~~~~~~~        
 
                                
   huff[0] = 8;
   ~~~~~~~~~~~~                 
   for (i=0; i < 13; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~     
     clen = getc(ifp);
     ~~~~~~~~~~~~~~~~~          
     code = getc(ifp);
     ~~~~~~~~~~~~~~~~~          
     for (j=0; j < 256 >> clen; )
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       huff[code+ ++j] = clen << 8 | i;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   get2();
   ~~~~~~~                      
 }
 ~                              
 
                                
 void CLASS foveon_dp_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   unsigned c, roff[4], row, col, diff;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort huff[512], vpred[2][2], hpred[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   fseek (ifp, 8, SEEK_CUR);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   foveon_huff (huff);
   ~~~~~~~~~~~~~~~~~~~          
   roff[0] = 48;
   ~~~~~~~~~~~~~                
   FORC3 roff[c+1] = -(-(roff[c] + get4()) & -16);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC3 {
   ~~~~~~~                      
     fseek (ifp, data_offset+roff[c], SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     getbits(-1);
     ~~~~~~~~~~~~               
     vpred[0][0] = vpred[0][1] = vpred[1][0] = vpred[1][1] = 512;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (row=0; row < height; row++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < width; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  diff = ljpeg_diff(huff);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  else hpred[col & 1] += diff;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  image[row*width+col][c] = hpred[col & 1];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS foveon_load_camf()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
 {
 ~                              
   unsigned type, wide, high, i, j, row, col, diff;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort huff[258], vpred[2][2] = {{512,512},{512,512}}, hpred[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   fseek (ifp, meta_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   type = get4();  get4();  get4();
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   wide = get4();
   ~~~~~~~~~~~~~~               
   high = get4();
   ~~~~~~~~~~~~~~               
   if (type == 2) {
   ~~~~~~~~~~~~~~~~             
     fread (meta_data, 1, meta_length, ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (i=0; i < meta_length; i++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       high = (high * 1597 + 51749) % 244944;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       wide = high * (INT64) 301593171 >> 24;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       meta_data[i] ^= ((((high << 8) - wide) >> 1) + wide) >> 17;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   } else if (type == 4) {
   ~~~~~~~~~~~~~~~~~~~~~~~      
     free (meta_data);
     ~~~~~~~~~~~~~~~~~          
     meta_data = (char *) malloc (meta_length = wide*high*3/2);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     merror (meta_data, "foveon_load_camf()");
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     foveon_huff (huff);
     ~~~~~~~~~~~~~~~~~~~        
     get4();
     ~~~~~~~                    
     getbits(-1);
     ~~~~~~~~~~~~               
     for (j=row=0; row < high; row++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < wide; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  diff = ljpeg_diff(huff);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  else         hpred[col & 1] += diff;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (col & 1) {
  ~~~~~~~~~~~~~~                
    meta_data[j++] = hpred[0] >> 4;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    meta_data[j++] = hpred[0] << 4 | hpred[1] >> 8;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    meta_data[j++] = hpred[1];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
  }
  ~                             
       }
       ~                        
     }
     ~                          
   } else
   ~~~~~~                       
     fprintf (stderr,_("%s has unknown CAMF type %d.\n"), ifname, type);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 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];
   ~~~~~~~~~~~~~~~~             
 
                                
   if (!name) return 0;
   ~~~~~~~~~~~~~~~~~~~~         
   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_load_camf();
   ~~~~~~~~~~~~~~~~~~~          
   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 (c=0; c < ARRAY_SIZE(ddft[0]); c++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i=0; i < ARRAY_SIZE(ddft[0][0]); i++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         ddft[0][c][i] = ddft[1][c][i] +
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           row / (height-1.0) * (ddft[2][c][i] - ddft[1][c][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 (c=0; c < ARRAY_SIZE(ddft[0]); c++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i=0; i < ARRAY_SIZE(ddft[0][0]); i++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         ddft[0][c][i] = ddft[1][c][i] +
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           row / (height-1.0) * (ddft[2][c][i] - ddft[1][c][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 ((height/4), (width/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 */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 void CLASS crop_masked_pixels()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int row, col;
   ~~~~~~~~~~~~~                
   unsigned r, c, m, mblack[8], zero, val;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (load_raw == &CLASS phase_one_load_raw ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       load_raw == &CLASS phase_one_load_raw_c)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     phase_one_correct();
     ~~~~~~~~~~~~~~~~~~~~       
   if (fuji_width) {
   ~~~~~~~~~~~~~~~~~            
     for (row=0; row < raw_height-top_margin*2; row++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < fuji_width << !fuji_layout; 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);
    ~~~~~~~~~~~~~~~~~~~~~~~~~   
  }
  ~                             
  if (r < height && c < width)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    BAYER(r,c) = RAW(row+top_margin,col+left_margin);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
   } else {
   ~~~~~~~~                     
     for (row=0; row < height; row++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < width; col++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  BAYER2(row,col) = RAW(row+top_margin,col+left_margin);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   if (mask[0][3] > 0) goto mask_set;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (load_raw == &CLASS canon_load_raw ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       load_raw == &CLASS lossless_jpeg_load_raw) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[0][1] = mask[1][1] += 2;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[0][3] -= 2;
     ~~~~~~~~~~~~~~~~           
     goto sides;
     ~~~~~~~~~~~                
   }
   ~                            
   if (load_raw == &CLASS canon_600_load_raw ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       load_raw == &CLASS sony_load_raw ||
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      (load_raw == &CLASS eight_bit_load_raw && strncmp(model,"DC2",3)) ||
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       load_raw == &CLASS kodak_262_load_raw ||
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      (load_raw == &CLASS packed_load_raw && (load_flags & 32))) {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 sides:
 ~~~~~~                         
     mask[0][0] = mask[1][0] = top_margin;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[0][2] = mask[1][2] = top_margin+height;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[0][3] += left_margin;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     mask[1][1] += left_margin+width;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[1][3] += raw_width;
     ~~~~~~~~~~~~~~~~~~~~~~~~   
   }
   ~                            
   if (load_raw == &CLASS nokia_load_raw) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[0][2] = top_margin;
     ~~~~~~~~~~~~~~~~~~~~~~~~   
     mask[0][3] = width;
     ~~~~~~~~~~~~~~~~~~~        
   }
   ~                            
 mask_set:
 ~~~~~~~~~                      
   memset (mblack, 0, sizeof mblack);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (zero=m=0; m < 8; m++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
     for (row=MAX(mask[m][0],0); row < MIN(mask[m][2],raw_height); row++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=MAX(mask[m][1],0); col < MIN(mask[m][3],raw_width); col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  c = FC(row-top_margin,col-left_margin);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  mblack[c] += val = RAW(row,col);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  mblack[4+c]++;
  ~~~~~~~~~~~~~~                
  zero += !val;
  ~~~~~~~~~~~~~                 
       }
       ~                        
   if (load_raw == &CLASS canon_600_load_raw && width < raw_width) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     black = (mblack[0]+mblack[1]+mblack[2]+mblack[3]) /
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      (mblack[4]+mblack[5]+mblack[6]+mblack[7]) - 4;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     canon_600_correct();
     ~~~~~~~~~~~~~~~~~~~~       
   } else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7]) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC4 cblack[c] = mblack[c] / mblack[4+c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     cblack[4] = cblack[5] = cblack[6] = 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;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
 }
 ~                              
 
                                
 /*
 ~~                             
    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) && fcol(r,c) == fcol(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);
   ~~~~~~~~~~~~~                
   fclose (fp);
   ~~~~~~~~~~~~                 
   memset (cblack, 0, sizeof cblack);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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 (float rgb_cam[3][4], 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 (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], balance[4], num;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int c, i, j, k, sq, row, col, pass, 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] += BAYER2(row,col);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  BAYER2(row,col) = black + (BAYER2(row,col)-black)/2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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 (pass=0; pass < 2; pass++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (raw_color = 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 (rgb_cam, cam_xyz);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORCC balance[c] = pre_mul[c] * gmb_cam[20][c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (sq=0; sq < NSQ; sq++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
       FORCC gmb_cam[sq][c] *= balance[c];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   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, blk[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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;
   ~~~~~~~~~~~~~~~~             
   FORC4 cblack[c] <<= 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];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       blk[row] = cblack[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] - blk[~row & 1]*4 )
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        * mul[row & 1] + (window[1][col] + blk[row & 1]) * 0.5;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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 = fcol(y,x);
   ~~~~~~~~~~~~~~               
   val = BAYER2(y,x);
   ~~~~~~~~~~~~~~~~~~           
        } else
        ~~~~~~                  
   val = image[y*width+x][c];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
        if (val > maximum-25) goto skip_block;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if ((val -= cblack[c]) < 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] - cblack[c]) > 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[1] == 0) pre_mul[1] = 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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);
     ~~~~~~~~~~~~~~~~~~~~~      
   }
   ~                            
   if (filters > 1000 && (cblack[4]+1)/2 == 1 && (cblack[5]+1)/2 == 1) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC4 cblack[FC(c/2,c%2)] +=
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cblack[6 + c/2 % cblack[4] * cblack[5] + c%2 % cblack[5]];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     cblack[4] = cblack[5] = 0;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   }
   ~                            
   size = iheight*iwidth;
   ~~~~~~~~~~~~~~~~~~~~~~       
   for (i=0; i < size*4; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     if (!(val = image[0][i])) continue;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (cblack[4] && cblack[5])
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       val -= cblack[6 + i/4 / iwidth % cblack[4] * cblack[5] +
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    i/4 % iwidth % cblack[5]];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
     val -= cblack[i & 3];
     ~~~~~~~~~~~~~~~~~~~~~      
     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;
       ~~~~~~~~~~~~~~~~         
       if (filters == 9) {
       ~~~~~~~~~~~~~~~~~~~      
  for (row=0; row < 3; row++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
    for (col=1; col < 4; col++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
      if (!(image[row*width+col][0] | image[row*width+col][2]))
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        goto break2;  break2:
        ~~~~~~~~~~~~~~~~~~~~~   
  for ( ; row < height; row+=3)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    for (col=(col-1)%3+1; col < width-1; col+=3) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      img = image + row*width+col;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (c=0; c < 3; c+=2)
      ~~~~~~~~~~~~~~~~~~~~~~    
        img[0][c] = (img[-1][c] + img[1][c]) >> 1;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    }
    ~                           
       }
       ~                        
     } 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 = fcol(row,col);
    ~~~~~~~~~~~~~~~~~~          
    img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       free (image);
       ~~~~~~~~~~~~~            
       image = img;
       ~~~~~~~~~~~~             
       shrink = 0;
       ~~~~~~~~~~~              
     }
     ~                          
   }
   ~                            
   if (filters > 1000 && colors == 3) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mix_green = four_color_rgb ^ half_size;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (four_color_rgb | half_size) 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 = fcol(y,x);
      ~~~~~~~~~~~~~~            
      sum[f] += image[y*width+x][f];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      sum[f+4]++;
      ~~~~~~~~~~~               
    }
    ~                           
       f = fcol(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], size=16, *ip, sum[4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int f, c, i, x, y, row, col, shift, color;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort *pix;
   ~~~~~~~~~~~~                 
 
                                
   if (verbose) fprintf (stderr,_("Bilinear interpolation...\n"));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (filters == 9) size = 6;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   border_interpolate(1);
   ~~~~~~~~~~~~~~~~~~~~~~       
   for (row=0; row < size; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < size; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       ip = code[row][col]+1;
       ~~~~~~~~~~~~~~~~~~~~~~   
       f = fcol(row,col);
       ~~~~~~~~~~~~~~~~~~       
       memset (sum, 0, sizeof sum);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (y=-1; y <= 1; y++)
       ~~~~~~~~~~~~~~~~~~~~~~~  
  for (x=-1; x <= 1; x++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
    shift = (y==0) + (x==0);
    ~~~~~~~~~~~~~~~~~~~~~~~~    
    color = fcol(row+y,col+x);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
    if (color == f) continue;
    ~~~~~~~~~~~~~~~~~~~~~~~~~   
    *ip++ = (width*y + x)*4 + color;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    *ip++ = shift;
    ~~~~~~~~~~~~~~              
    *ip++ = color;
    ~~~~~~~~~~~~~~              
    sum[color] += 1 << shift;
    ~~~~~~~~~~~~~~~~~~~~~~~~~   
  }
  ~                             
       code[row][col][0] = (ip - code[row][col]) / 3;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORCC
       ~~~~~                    
  if (c != f) {
  ~~~~~~~~~~~~~                 
    *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 % size][col % size];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       memset (sum, 0, sizeof sum);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i=*ip++; 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/pages/labsite/1999/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=8, pcol=2, *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 = 16;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (filters == 9) prow = pcol =  6;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ip = (int *) calloc (prow*pcol, 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 = fcol(row+y1,col+x1);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  if (fcol(row+y2,col+x2) != color) continue;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  diag = (fcol(row,col+1) == color && fcol(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 = fcol(row,col);
  ~~~~~~~~~~~~~~~~~~~~~~        
  if (fcol(row+y,col+x) != color && fcol(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 = fcol(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);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 void CLASS cielab (ushort rgb[3], short lab[3])
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c, i, j, k;
   ~~~~~~~~~~~~~~~              
   float r, xyz[3];
   ~~~~~~~~~~~~~~~~             
   static float cbrt[0x10000], xyz_cam[3][4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (!rgb) {
   ~~~~~~~~~~~                  
     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];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     return;
     ~~~~~~~                    
   }
   ~                            
   xyz[0] = xyz[1] = xyz[2] = 0.5;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORCC {
   ~~~~~~~                      
     xyz[0] += xyz_cam[0][c] * rgb[c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     xyz[1] += xyz_cam[1][c] * rgb[c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     xyz[2] += xyz_cam[2][c] * rgb[c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   xyz[0] = cbrt[CLIP((int) xyz[0])];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   xyz[1] = cbrt[CLIP((int) xyz[1])];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   xyz[2] = cbrt[CLIP((int) xyz[2])];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   lab[0] = 64 * (116 * xyz[1] - 16);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   lab[1] = 64 * 500 * (xyz[0] - xyz[1]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   lab[2] = 64 * 200 * (xyz[1] - xyz[2]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 #define TS 512  /* Tile Size */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #define fcol(row,col) xtrans[(row+6) % 6][(col+6) % 6]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /*
 ~~                             
    Frank Markesteijn's algorithm for Fuji X-Trans sensors
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
  ~~                            
 void CLASS xtrans_interpolate (int passes)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c, d, f, g, h, i, v, ng, row, col, top, left, mrow, mcol;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int val, ndir, pass, hm[8], avg[4], color[3][8];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   static const short orth[12] = { 1,0,0,1,-1,0,0,-1,1,0,0,1 },
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  patt[2][16] = { { 0,1,0,-1,2,0,-1,0,1,1,1,-1,0,0,0,0 },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    { 0,1,0,-2,1,0,-2,0,1,1,-2,-2,1,-1,-1,1 } },
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  dir[4] = { 1,TS,TS+1,TS-1 };
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   short allhex[3][3][2][8], *hex;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort min, max, sgrow, sgcol;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    short (*lab)    [TS][3], (*lix)[3];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    float (*drv)[TS][TS], diff[6], tr;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    char (*homo)[TS][TS], *buffer;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (verbose)
   ~~~~~~~~~~~~                 
     fprintf (stderr,_("%d-pass X-Trans interpolation...\n"), passes);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   cielab (0,0);
   ~~~~~~~~~~~~~                
   ndir = 4 << (passes > 1);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   buffer = (char *) malloc (TS*TS*(ndir*11+6));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (buffer, "xtrans_interpolate()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   rgb  = (ushort(*)[TS][TS][3]) buffer;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   lab  = (short (*)    [TS][3])(buffer + TS*TS*(ndir*6));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drv  = (float (*)[TS][TS])   (buffer + TS*TS*(ndir*6+6));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   homo = (char  (*)[TS][TS])   (buffer + TS*TS*(ndir*10+6));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /* Map a green hexagon around each non-green pixel and vice versa: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < 3; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     for (col=0; col < 3; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (ng=d=0; d < 10; d+=2) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  g = fcol(row,col) == 1;
  ~~~~~~~~~~~~~~~~~~~~~~~       
  if (fcol(row+orth[d],col+orth[d+2]) == 1) ng=0; else ng++;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (ng == 4) { sgrow = row; sgcol = col; }
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (ng == g+1) FORC(8) {
  ~~~~~~~~~~~~~~~~~~~~~~~~      
    v = orth[d  ]*patt[g][c*2] + orth[d+1]*patt[g][c*2+1];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    h = orth[d+2]*patt[g][c*2] + orth[d+3]*patt[g][c*2+1];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    allhex[row][col][0][c^(g*2 & d)] = h + v*width;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    allhex[row][col][1][c^(g*2 & d)] = h + v*TS;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       }
       ~                        
 
                                
 /* Set green1 and green3 to the minimum and maximum allowed values: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=2; row < height-2; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (min=~(max=0), col=2; col < width-2; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (fcol(row,col) == 1 && (min=~(max=0))) continue;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pix = image + row*width + col;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       hex = allhex[row % 3][col % 3][0];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (!max) FORC(6) {
       ~~~~~~~~~~~~~~~~~~~      
  val = pix[hex[c]][1];
  ~~~~~~~~~~~~~~~~~~~~~         
  if (min > val) min = val;
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  if (max < val) max = val;
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
       }
       ~                        
       pix[0][1] = min;
       ~~~~~~~~~~~~~~~~         
       pix[0][3] = max;
       ~~~~~~~~~~~~~~~~         
       switch ((row-sgrow) % 3) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  case 1: if (row < height-3) { row++; col--; } break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  case 2: if ((min=~(max=0)) && (col+=2) < width-3 && row > 2) row--;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
 
                                
   for (top=3; top < height-19; top += TS-16)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (left=3; left < width-19; left += TS-16) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       mrow = MIN (top+TS, height-3);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       mcol = MIN (left+TS, width-3);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (row=top; row < mrow; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col=left; col < mcol; col++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    memcpy (rgb[0][row-top][col-left], image[row*width+col], 6);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 memcpy (rgb[c+1], rgb[0], sizeof *rgb);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /* Interpolate green horizontally, vertically, and along both diagonals: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (row=top; row < mrow; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col=left; col < mcol; col++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if ((f = fcol(row,col)) == 1) continue;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    pix = image + row*width + col;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    hex = allhex[row % 3][col % 3][0];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    color[1][0] = 174 * (pix[  hex[1]][1] + pix[  hex[0]][1]) -
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     46 * (pix[2*hex[1]][1] + pix[2*hex[0]][1]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    color[1][1] = 223 *  pix[  hex[3]][1] + pix[  hex[2]][1] * 33 +
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     92 * (pix[      0 ][f] - pix[ -hex[2]][f]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    FORC(2) color[1][2+c] =
    ~~~~~~~~~~~~~~~~~~~~~~~     
   164 * pix[hex[4+c]][1] + 92 * pix[-2*hex[4+c]][1] + 33 *
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   (2*pix[0][f] - pix[3*hex[4+c]][f] - pix[-3*hex[4+c]][f]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    FORC4 rgb[c^!((row-sgrow) % 3)][row-top][col-left][1] =
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   LIM(color[1][c] >> 8,pix[0][1],pix[0][3]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
 
                                
       for (pass=0; pass < passes; pass++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (pass == 1)
  ~~~~~~~~~~~~~~                
    memcpy (rgb+=4, buffer, 4*sizeof *rgb);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /* Recalculate green from interpolated values of closer pixels: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (pass) {
  ~~~~~~~~~~~                   
    for (row=top+2; row < mrow-2; row++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (col=left+2; col < mcol-2; col++) {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if ((f = fcol(row,col)) == 1) continue;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        pix = image + row*width + col;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        hex = allhex[row % 3][col % 3][1];
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        for (d=3; d < 6; d++) {
        ~~~~~~~~~~~~~~~~~~~~~~~ 
   rix = &rgb[(d-2)^!((row-sgrow) % 3)][row-top][col-left];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   val = rix[-2*hex[d]][1] + 2*rix[hex[d]][1]
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       - rix[-2*hex[d]][f] - 2*rix[hex[d]][f] + 3*rix[0][f];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   rix[0][1] = LIM(val/3,pix[0][1],pix[0][3]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        }
        ~                       
      }
      ~                         
  }
  ~                             
 
                                
 /* Interpolate red and blue values for solitary green pixels: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (row=(top-sgrow+4)/3*3+sgrow; row < mrow-2; row+=3)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (col=(left-sgcol+4)/3*3+sgcol; col < mcol-2; col+=3) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      rix = &rgb[0][row-top][col-left];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      h = fcol(row,col+1);
      ~~~~~~~~~~~~~~~~~~~~      
      memset (diff, 0, sizeof diff);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (i=1, d=0; d < 6; d++, i^=TS^1, h^=2) {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        for (c=0; c < 2; c++, h^=2) {
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   g = 2*rix[0][1] - rix[i<<c][1] - rix[-i<<c][1];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   color[h][d] = g + rix[i<<c][h] + rix[-i<<c][h];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (d > 1)
   ~~~~~~~~~~                   
     diff[d] += SQR (rix[i<<c][1] - rix[-i<<c][1]
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     - rix[i<<c][h] + rix[-i<<c][h]) + SQR(g);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        }
        ~                       
        if (d > 1 && (d & 1))
        ~~~~~~~~~~~~~~~~~~~~~   
   if (diff[d-1] < diff[d])
   ~~~~~~~~~~~~~~~~~~~~~~~~     
     FORC(2) color[c*2][d] = color[c*2][d-1];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if (d < 2 || (d & 1)) {
        ~~~~~~~~~~~~~~~~~~~~~~~ 
   FORC(2) rix[0][c*2] = CLIP(color[c*2][d]/2);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   rix += TS*TS;
   ~~~~~~~~~~~~~                
        }
        ~                       
      }
      ~                         
    }
    ~                           
 
                                
 /* Interpolate red for blue pixels and vice versa:  */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (row=top+3; row < mrow-3; row++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (col=left+3; col < mcol-3; col++) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if ((f = 2-fcol(row,col)) == 1) continue;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      rix = &rgb[0][row-top][col-left];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      c = (row-sgrow) % 3 ? TS:1;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~
      h = 3 * (c ^ TS ^ 1);
      ~~~~~~~~~~~~~~~~~~~~~     
      for (d=0; d < 4; d++, rix += TS*TS) {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        i = d > 1 || ((d ^ c) & 1) ||
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ((ABS(rix[0][1]-rix[c][1])+ABS(rix[0][1]-rix[-c][1])) <
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2*(ABS(rix[0][1]-rix[h][1])+ABS(rix[0][1]-rix[-h][1]))) ? c:h;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        rix[0][f] = CLIP((rix[i][f] + rix[-i][f] +
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     2*rix[0][1] - rix[i][1] - rix[-i][1])/2);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      }
      ~                         
    }
    ~                           
 
                                
 /* Fill in red and blue for 2x2 blocks of green:  */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (row=top+2; row < mrow-2; row++) if ((row-sgrow) % 3)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (col=left+2; col < mcol-2; col++) if ((col-sgcol) % 3) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      rix = &rgb[0][row-top][col-left];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      hex = allhex[row % 3][col % 3][1];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (d=0; d < ndir; d+=2, rix += TS*TS)
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if (hex[d] + hex[d+1]) {
        ~~~~~~~~~~~~~~~~~~~~~~~~
   g = 3*rix[0][1] - 2*rix[hex[d]][1] - rix[hex[d+1]][1];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (c=0; c < 4; c+=2) rix[0][c] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    CLIP((g + 2*rix[hex[d]][c] + rix[hex[d+1]][c])/3);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        } else {
        ~~~~~~~~                
   g = 2*rix[0][1] - rix[hex[d]][1] - rix[hex[d+1]][1];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (c=0; c < 4; c+=2) rix[0][c] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    CLIP((g + rix[hex[d]][c] + rix[hex[d+1]][c])/2);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        }
        ~                       
    }
    ~                           
       }
       ~                        
       rgb = (ushort(*)[TS][TS][3]) buffer;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       mrow -= top;
       ~~~~~~~~~~~~             
       mcol -= left;
       ~~~~~~~~~~~~~            
 
                                
 /* Convert to CIELab and differentiate in all directions: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (d=0; d < ndir; d++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (row=2; row < mrow-2; row++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (col=2; col < mcol-2; col++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      cielab (rgb[d][row][col], lab[row][col]);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (f=dir[d & 3],row=3; row < mrow-3; row++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (col=3; col < mcol-3; col++) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      lix = &lab[row][col];
      ~~~~~~~~~~~~~~~~~~~~~     
      g = 2*lix[0][0] - lix[f][0] - lix[-f][0];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      drv[d][row][col] = SQR(g)
      ~~~~~~~~~~~~~~~~~~~~~~~~~ 
        + SQR((2*lix[0][1] - lix[f][1] - lix[-f][1] + g*500/232))
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + SQR((2*lix[0][2] - lix[f][2] - lix[-f][2] - g*500/580));
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    }
    ~                           
       }
       ~                        
 
                                
 /* Build homogeneity maps from the derivatives:   */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       memset(homo, 0, ndir*TS*TS);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (row=4; row < mrow-4; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col=4; col < mcol-4; col++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (tr=FLT_MAX, d=0; d < ndir; d++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (tr > drv[d][row][col])
      ~~~~~~~~~~~~~~~~~~~~~~~~~~
   tr = drv[d][row][col];
   ~~~~~~~~~~~~~~~~~~~~~~       
    tr *= 8;
    ~~~~~~~~                    
    for (d=0; d < ndir; d++)
    ~~~~~~~~~~~~~~~~~~~~~~~~    
      for (v=-1; v <= 1; v++)
      ~~~~~~~~~~~~~~~~~~~~~~~   
        for (h=-1; h <= 1; h++)
        ~~~~~~~~~~~~~~~~~~~~~~~ 
   if (drv[d][row+v][col+h] <= tr)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     homo[d][row][col]++;
     ~~~~~~~~~~~~~~~~~~~~       
  }
  ~                             
 
                                
 /* Average the most homogenous pixels for the final result: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (height-top < TS+4) mrow = height-top+2;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (width-left < TS+4) mcol = width-left+2;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (row = MIN(top,8); row < mrow-8; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col = MIN(left,8); col < mcol-8; col++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (d=0; d < ndir; d++)
    ~~~~~~~~~~~~~~~~~~~~~~~~    
      for (hm[d]=0, v=-2; v <= 2; v++)
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        for (h=-2; h <= 2; h++)
        ~~~~~~~~~~~~~~~~~~~~~~~ 
   hm[d] += homo[d][row+v][col+h];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (d=0; d < ndir-4; d++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
      if (hm[d] < hm[d+4]) hm[d  ] = 0; else
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (hm[d] > hm[d+4]) hm[d+4] = 0;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (max=hm[0],d=1; d < ndir; d++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (max < hm[d]) max = hm[d];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    max -= max >> 3;
    ~~~~~~~~~~~~~~~~            
    memset (avg, 0, sizeof avg);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (d=0; d < ndir; d++)
    ~~~~~~~~~~~~~~~~~~~~~~~~    
      if (hm[d] >= max) {
      ~~~~~~~~~~~~~~~~~~~       
        FORC3 avg[c] += rgb[d][row][col][c];
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        avg[3]++;
        ~~~~~~~~~               
      }
      ~                         
    FORC3 image[(row+top)*width+col+left][c] = avg[c]/avg[3];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
     }
     ~                          
   free(buffer);
   ~~~~~~~~~~~~~                
   border_interpolate(8);
   ~~~~~~~~~~~~~~~~~~~~~~       
 }
 ~                              
 #undef fcol
 ~~~~~~~~~~~                    
 
                                
 /*
 ~~                             
    Adaptive Homogeneity-Directed interpolation is based on
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
  ~~                            
 void CLASS ahd_interpolate()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
 {
 ~                              
   int i, j, top, left, row, col, tr, tc, c, d, val, hm[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   static const int dir[4] = { -1, 1, -TS, TS };
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    short (*lab)[TS][TS][3], (*lix)[3];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    char (*homo)[TS][TS], *buffer;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   cielab (0,0);
   ~~~~~~~~~~~~~                
   border_interpolate(5);
   ~~~~~~~~~~~~~~~~~~~~~~       
   buffer = (char *) malloc (26*TS*TS);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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];
      ~~~~~~~~~~~~~~~~~~~~~~    
      cielab (rix[0],lix[0]);
      ~~~~~~~~~~~~~~~~~~~~~~~   
    }
    ~                           
 /*  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 * ("11124811248484"[*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 morder, 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.
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
  ~~                            
   if (!strcmp(make,"Nokia")) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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") ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
              !strcmp (buf,"PENTAX ")) {
              ~~~~~~~~~~~~~~~~~~~~~~~~~~
     base = ftell(ifp)-10;
     ~~~~~~~~~~~~~~~~~~~~~      
     fseek (ifp, -2, SEEK_CUR);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     order = get2();
     ~~~~~~~~~~~~~~~            
     if (buf[0] == 'O') get2();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   } else if (!strncmp (buf,"SONY",4) ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       !strcmp  (buf,"Panasonic")) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     goto nf;
     ~~~~~~~~                   
   } else if (!strncmp (buf,"FUJIFILM",8)) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     base = ftell(ifp)-10;
     ~~~~~~~~~~~~~~~~~~~~~      
 nf: 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);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!strncmp(make,"SAMSUNG",7))
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       base = ftell(ifp);
       ~~~~~~~~~~~~~~~~~~       
   }
   ~                            
   entries = get2();
   ~~~~~~~~~~~~~~~~~            
   if (entries > 1000) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   morder = order;
   ~~~~~~~~~~~~~~~              
   while (entries--) {
   ~~~~~~~~~~~~~~~~~~~          
     order = morder;
     ~~~~~~~~~~~~~~~            
     tiff_get (base, &tag, &type, &len, &save);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     tag |= uptag << 16;
     ~~~~~~~~~~~~~~~~~~~        
     if (tag == 2 && strstr(make,"NIKON") && !iso_speed)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       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 == 4 || tag == 0x114) && !strncmp(make,"KONICA",6)) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, tag == 4 ? 140:160, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       switch (get2()) {
       ~~~~~~~~~~~~~~~~~        
  case 72:  flip = 0;  break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  case 76:  flip = 6;  break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  case 82:  flip = 5;  break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
       }
       ~                        
     }
     ~                          
     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)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 cam_mul[(c << 1 | c >> 1) & 3] = getreal(type);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0xd && type == 7 && get2() == 0xaaaa) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (c=i=2; (ushort) c != 0xbbbb && i < len; i++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  c = c << 8 | fgetc(ifp);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
       while ((i+=4) < len-5)
       ~~~~~~~~~~~~~~~~~~~~~~   
  if (get4() == 257 && (i=len) && (c = (get4(),fgetc(ifp))) < 3)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    flip = "065"[c]-'0';
    ~~~~~~~~~~~~~~~~~~~~        
     }
     ~                          
     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 && type == 7) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (len == 2560) {
       ~~~~~~~~~~~~~~~~~~       
  fseek (ifp, 1248, SEEK_CUR);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  goto get2_256;
  ~~~~~~~~~~~~~~                
       }
       ~                        
       fread (buf, 1, 10, ifp);
       ~~~~~~~~~~~~~~~~~~~~~~~~ 
       if (!strncmp(buf,"NRW ",4)) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  fseek (ifp, strcmp(buf+4,"0100") ? 46:1546, SEEK_CUR);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cam_mul[0] = get4() << 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  cam_mul[1] = get4() + get4();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  cam_mul[2] = get4() << 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
       }
       ~                        
     }
     ~                          
     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 == 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 == 0x3d && type == 3 && len == 4)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 cblack[c ^ c >> 1] = get2() >> (14-tiff_ifd[2].bps);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     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 == 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 == 0xa1 && type == 7) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       order = 0x4949;
       ~~~~~~~~~~~~~~~          
       fseek (ifp, 140, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 cam_mul[c] = get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     if (tag == 0xa4 && type == 3) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, wbi*48, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 cam_mul[c] = get2();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     if (tag == 0xa7 && (unsigned) (ver97-200) < 17) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       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;:;55"[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)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 cblack[c ^ c >> 1] = get2();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0x201 && len == 4)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       goto get2_rggb;
       ~~~~~~~~~~~~~~~          
     if (tag == 0x220 && type == 7)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       meta_offset = ftell(ifp);
       ~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0x401 && type == 4 && len == 4)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 cblack[c ^ c >> 1] = get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0xe01) {  /* Nikon Capture Note */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       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);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
     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)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 cblack[c ^ c >> 1] = get2();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     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 || type == 13))
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, get4()+base, SEEK_SET);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0x2020)
     ~~~~~~~~~~~~~~~~~~         
       parse_thumb_note (base, 257, 258);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0x2040)
     ~~~~~~~~~~~~~~~~~~         
       parse_makernote (base, 0x2040);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0xb028) {
     ~~~~~~~~~~~~~~~~~~~~       
       fseek (ifp, get4()+base, 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();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       i = len >> 3 == 164 || len == 1506 ? 112:22;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, i, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 sraw_mul[c ^ (c >> 1)] = get2();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     if (tag == 0x4021 && get4() && get4())
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 cam_mul[c] = 1024;
       ~~~~~~~~~~~~~~~~~~~~~~~~ 
     if (tag == 0xa021)
     ~~~~~~~~~~~~~~~~~~         
       FORC4 cam_mul[c ^ (c >> 1)] = get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0xa028)
     ~~~~~~~~~~~~~~~~~~         
       FORC4 cam_mul[c ^ (c >> 1)] -= get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0xb001)
     ~~~~~~~~~~~~~~~~~~         
       unique_id = 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;
   ~~~~~~~~~~~~~~               
   t.tm_isdst = -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) && tiff_nifds < 3;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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",
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     "Aptus-II 7","","","Aptus-II 6","","","Aptus-II 10","Aptus-II 5",
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     "","","","","Aptus-II 10R","Aptus-II 8","","Aptus-II 12","","AFi-II 12" };
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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 (c=0; c < ARRAY_SIZE(romm_cam); c++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (i=0; i < ARRAY_SIZE(romm_cam[0]); i++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    romm_cam[c][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];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     if (!strcmp(data,"Rows_data"))
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       load_flags = get4();
       ~~~~~~~~~~~~~~~~~~~~     
     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]={1,1,1}, num;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
   static const int wbtag[] = { 64037,64040,64039,64041,-1,-1,64042 };
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   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 == 2120 + wbi && wbi >= 0)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 cam_mul[c] = 2048.0 / getreal(type);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/openexr.d' -o 'objdir/codecs/openexr.o' 'codecs/openexr.cc'
 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);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 64013) wbi = fgetc(ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if ((unsigned) wbi < 7 && tag == wbtag[wbi])
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 cam_mul[c] = get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 64019) width = getint(type);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 64020) height = (getint(type)+1) & -2;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, save, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS parse_minolta (int base);
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 int CLASS parse_tiff (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 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 5:   width  = get2();  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 6:   height = get2();  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 7:   width += get2();  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 9:   if ((i = get2())) filters = i;  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       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 28: case 29: case 30:
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  cblack[tag-28] = get2();
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  cblack[3] = cblack[1];
  ~~~~~~~~~~~~~~~~~~~~~~        
  break;
  ~~~~~~                        
       case 36: case 37: case 38:
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  cam_mul[tag-36] = 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 61440:   /* Fuji HS10 table */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  fseek (ifp, get4()+base, SEEK_SET);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  parse_tiff_ifd (base);
  ~~~~~~~~~~~~~~~~~~~~~~        
  break;
  ~~~~~~                        
       case 2: case 256: case 61441: /* ImageWidth */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].width = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 3: case 257: case 61442: /* ImageHeight */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].height = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 258:    /* BitsPerSample */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 61443:
       ~~~~~~~~~~~              
  tiff_ifd[ifd].samples = len & 7;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].bps = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 61446:
       ~~~~~~~~~~~              
  raw_height = 0;
  ~~~~~~~~~~~~~~~               
  if (tiff_ifd[ifd].bps > 12) break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  load_raw = &CLASS packed_load_raw;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  load_flags = get4() ? 24:80;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  break;
  ~~~~~~                        
       case 259:    /* Compression */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].comp = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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:    /* JpegIFOffset */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 61447:
       ~~~~~~~~~~~              
  tiff_ifd[ifd].offset = get4()+base;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (!tiff_ifd[ifd].bps && tiff_ifd[ifd].offset > 0) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (ljpeg_start (&jh, 1)) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
      tiff_ifd[ifd].comp    = 6;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~
      tiff_ifd[ifd].width   = jh.wide;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      tiff_ifd[ifd].height  = jh.high;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      tiff_ifd[ifd].bps     = jh.bits;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      tiff_ifd[ifd].samples = jh.clrs;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (!(jh.sraw || (jh.clrs & 1)))
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        tiff_ifd[ifd].width *= jh.clrs;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      i = order;
      ~~~~~~~~~~                
      parse_tiff (tiff_ifd[ifd].offset + 12);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      order = i;
      ~~~~~~~~~~                
    }
    ~                           
  }
  ~                             
  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:
       ~~~~~~~~~                
       case 61448:
       ~~~~~~~~~~~              
  tiff_ifd[ifd].bytes = get4();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  break;
  ~~~~~~                        
       case 61454:
       ~~~~~~~~~~~              
  FORC3 cam_mul[(4-c) % 3] = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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 */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].tile_width = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 323:    /* TileLength */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].tile_length = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 324:    /* TileOffsets */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (len == 1)
  ~~~~~~~~~~~~~                 
    tiff_ifd[ifd].tile_width = tiff_ifd[ifd].tile_length = 0;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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;
    ~~~~~~~~~~~~~~              
  }
  ~                             
  if(len > 1000) len=1000; /* 1000 SubIFDs is enough */
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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] = get2();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  i = (cam_mul[1] == 1024 && cam_mul[2] == 1024) << 1;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SWAP (cam_mul[i],cam_mul[i+1])
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 33405:   /* Model2 */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  fgets (model2, 64, ifp);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  break;
  ~~~~~~                        
       case 33421:   /* CFARepeatPatternDim */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (get2() == 6 && get2() == 6)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    filters = 9;
    ~~~~~~~~~~~~                
  break;
  ~~~~~~                        
       case 33422:   /* CFAPattern */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (filters == 9) {
  ~~~~~~~~~~~~~~~~~~~           
    FORC(36) xtrans[0][c] = fgetc(ifp) & 3;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    break;
    ~~~~~~                      
  }
  ~                             
       case 64777:   /* Kodak P-series */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if ((plen=len) > 16) plen = 16;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  fread (cfa_pat, 1, plen, ifp);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (colors=cfa=i=0; i < plen && colors < 4; 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:
       ~~~~~~~~~~~              
       case 65024:
       ~~~~~~~~~~~              
  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 40976:
       ~~~~~~~~~~~              
  strip_offset = get4();
  ~~~~~~~~~~~~~~~~~~~~~~        
  switch (tiff_ifd[ifd].comp) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    case 32770: load_raw = &CLASS samsung_load_raw;   break;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    case 32772: load_raw = &CLASS samsung2_load_raw;  break;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    case 32773: load_raw = &CLASS samsung3_load_raw;  break;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
  break;
  ~~~~~~                        
       case 46275:   /* Imacon tags */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  strcpy (make, "Imacon");
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  data_offset = ftell(ifp);
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  ima_len = len;
  ~~~~~~~~~~~~~~                
  break;
  ~~~~~~                        
       case 46279:
       ~~~~~~~~~~~              
  if (!ima_len) break;
  ~~~~~~~~~~~~~~~~~~~~          
  fseek (ifp, 38, SEEK_CUR);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
       case 46274:
       ~~~~~~~~~~~              
  fseek (ifp, 40, 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);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    raw_width = width;
    ~~~~~~~~~~~~~~~~~~          
    raw_height = height;
    ~~~~~~~~~~~~~~~~~~~~        
    left_margin = top_margin = 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 (filters == 9) break;
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  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]];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  filters -= !filters;
  ~~~~~~~~~~~~~~~~~~~~          
  break;
  ~~~~~~                        
       case 50711:   /* CFALayout */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (get2() == 2) {
  ~~~~~~~~~~~~~~~~~~            
    fuji_width = 1;
    ~~~~~~~~~~~~~~~             
    filters = 0x49494949;
    ~~~~~~~~~~~~~~~~~~~~~       
  }
  ~                             
  break;
  ~~~~~~                        
       case 291:
       ~~~~~~~~~                
       case 50712:   /* LinearizationTable */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  linear_table (len);
  ~~~~~~~~~~~~~~~~~~~           
  break;
  ~~~~~~                        
       case 50713:   /* BlackLevelRepeatDim */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cblack[4] = get2();
  ~~~~~~~~~~~~~~~~~~~           
  cblack[5] = get2();
  ~~~~~~~~~~~~~~~~~~~           
  if (cblack[4] * cblack[5] > sizeof cblack / sizeof *cblack - 6)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      cblack[4] = cblack[5] = 1;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 61450:
       ~~~~~~~~~~~              
  cblack[4] = cblack[5] = MIN(sqrt(len),64);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 50714:   /* BlackLevel */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (!(cblack[4] * cblack[5]))
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    cblack[4] = cblack[5] = 1;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
  FORC (cblack[4] * cblack[5])
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    cblack[6+c] = getreal(type);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  black = 0;
  ~~~~~~~~~~                    
  break;
  ~~~~~~                        
       case 50715:   /* BlackLevelDeltaH */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 50716:   /* BlackLevelDeltaV */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (num=i=0; i < len && i < 65536; i++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    num += getreal(type);
    ~~~~~~~~~~~~~~~~~~~~~       
  black += num/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);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       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 50830:   /* MaskedAreas */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         for (i=0; i < len && i < 32; i++)
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    mask[0][i] = getint(type);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
  black = 0;
  ~~~~~~~~~~                    
  break;
  ~~~~~~                        
       case 51009:   /* OpcodeList2 */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  meta_offset = ftell(ifp);
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  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_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 (cmatrix, 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;
   ~~~~~~~~~                    
 }
 ~                              
 
                                
 int CLASS parse_tiff (int base)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int doff;
   ~~~~~~~~~                    
 
                                
   fseek (ifp, base, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   order = get2();
   ~~~~~~~~~~~~~~~              
   if (order != 0x4949 && order != 0x4d4d) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   get2();
   ~~~~~~~                      
   while ((doff = get4())) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
     fseek (ifp, doff+base, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (parse_tiff_ifd (base)) break;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   return 1;
   ~~~~~~~~~                    
 }
 ~                              
 
                                
 void CLASS apply_tiff()
 ~~~~~~~~~~~~~~~~~~~~~~~        
 {
 ~                              
   int max_samp=0, raw=-1, thm=-1, i;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   struct jhead jh;
   ~~~~~~~~~~~~~~~~             
 
                                
   thumb_misc = 16;
   ~~~~~~~~~~~~~~~~             
   if (thumb_offset) {
   ~~~~~~~~~~~~~~~~~~~          
     fseek (ifp, thumb_offset, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (ljpeg_start (&jh, 1)) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if((unsigned)jh.bits<17 && (unsigned)jh.wide < 0x10000 && (unsigned)jh.high < 0x10000)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         {
         ~                      
           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) &&
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  unsigned(tiff_ifd[i].width | tiff_ifd[i].height) < 0x10000 &&
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  (unsigned)tiff_ifd[i].bps < 33 && (unsigned)tiff_ifd[i].samples < 13 &&
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       tile_width    = tiff_ifd[i].tile_width;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       tile_length   = tiff_ifd[i].tile_length;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       raw = i;
       ~~~~~~~~                 
     }
     ~                          
   }
   ~                            
   if (!tile_width ) tile_width  = INT_MAX;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (!tile_length) tile_length = INT_MAX;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (i=tiff_nifds; i--; )
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
     if (tiff_ifd[i].flip) tiff_flip = tiff_ifd[i].flip;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (raw >= 0 && !load_raw)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
     switch (tiff_compress) {
     ~~~~~~~~~~~~~~~~~~~~~~~~   
       case 32767:
       ~~~~~~~~~~~              
  if (tiff_ifd[raw].bytes == raw_width*raw_height) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    tiff_bps = 12;
    ~~~~~~~~~~~~~~              
    load_raw = &CLASS sony_arw2_load_raw;   break;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
  if (tiff_ifd[raw].bytes*8 != raw_width*raw_height*tiff_bps) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    raw_height += 8;
    ~~~~~~~~~~~~~~~~            
    load_raw = &CLASS sony_arw_load_raw;   break;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
  load_flags = 79;
  ~~~~~~~~~~~~~~~~              
       case 32769:
       ~~~~~~~~~~~              
  load_flags++;
  ~~~~~~~~~~~~~                 
       case 32770:
       ~~~~~~~~~~~              
       case 32773: goto slr;
       ~~~~~~~~~~~~~~~~~~~~~    
       case 0:  case 1:
       ~~~~~~~~~~~~~~~~         
  if (!strncmp(make,"OLYMPUS",7) &&
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   tiff_ifd[raw].bytes*2 == raw_width*raw_height*3)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    load_flags = 24;
    ~~~~~~~~~~~~~~~~            
  if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    load_flags = 81;
    ~~~~~~~~~~~~~~~~            
    tiff_bps = 12;
    ~~~~~~~~~~~~~~              
  } slr:
  ~~~~~~                        
  switch (tiff_bps) {
  ~~~~~~~~~~~~~~~~~~~           
    case  8: load_raw = &CLASS eight_bit_load_raw; break;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    case 12: if (tiff_ifd[raw].phint == 2)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        load_flags = 6;
        ~~~~~~~~~~~~~~~         
      load_raw = &CLASS packed_load_raw;  break;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    case 14: load_flags = 0;
    ~~~~~~~~~~~~~~~~~~~~~~~~    
    case 16: load_raw = &CLASS unpacked_load_raw;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (!strncmp(make,"OLYMPUS",7) &&
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    tiff_ifd[raw].bytes*7 > raw_width*raw_height)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        load_raw = &CLASS olympus_load_raw;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
  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 34713:
       ~~~~~~~~~~~              
  if ((raw_width+9)/10*16*raw_height == tiff_ifd[raw].bytes) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    load_raw = &CLASS packed_load_raw;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    load_flags = 1;
    ~~~~~~~~~~~~~~~             
  } else if (raw_width*raw_height*3 == tiff_ifd[raw].bytes*2) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    load_raw = &CLASS packed_load_raw;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (model[0] == 'N') load_flags = 80;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  } else if (raw_width*raw_height*3 == tiff_ifd[raw].bytes) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    load_raw = &CLASS nikon_yuv_load_raw;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    gamma_curve (1/2.4, 12.92, 1, 4095);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    memset (cblack, 0, sizeof cblack);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    filters = 0;
    ~~~~~~~~~~~~                
  } else if (raw_width*raw_height*2 == tiff_ifd[raw].bytes) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    load_raw = &CLASS unpacked_load_raw;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    load_flags = 4;
    ~~~~~~~~~~~~~~~             
    order = 0x4d4d;
    ~~~~~~~~~~~~~~~             
  } else
  ~~~~~~                        
    load_raw = &CLASS nikon_load_raw;   break;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 65535:
       ~~~~~~~~~~~              
  load_raw = &CLASS pentax_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: case 34892: break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       default: is_raw = 0;
       ~~~~~~~~~~~~~~~~~~~~     
     }
     ~                          
   if (!dng_version)
   ~~~~~~~~~~~~~~~~~            
     if ( (tiff_samples == 3 && tiff_ifd[raw].bytes && tiff_bps != 14 &&
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    (tiff_compress & -16) != 32768)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       || (tiff_bps == 8 && !strcasestr(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].bps>0 && tiff_ifd[i].bps < 33 &&
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         unsigned(tiff_ifd[i].width | tiff_ifd[i].height) < 0x10000 &&
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[i].width * tiff_ifd[i].height / (SQR(tiff_ifd[i].bps)+1) >
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        thumb_width *       thumb_height / (SQR(thumb_misc)+1)
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  && tiff_ifd[i].comp != 34892) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       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)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
    write_thumb = &CLASS ppm_thumb;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  else if (!strcmp(make,"Imacon"))
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    write_thumb = &CLASS ppm16_thumb;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  else
  ~~~~                          
    thumb_load_raw = &CLASS kodak_thumb_load_raw;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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 depth)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   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 | depth) > 127) 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, depth+1); /* 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) {
     ~~~~~~~~~~~~~~~~~~~~~      
       width = get4();
       ~~~~~~~~~~~~~~~          
       height = get4();
       ~~~~~~~~~~~~~~~~         
       pixel_aspect = int_to_float(get4());
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       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 (c=0; c < ARRAY_SIZE(romm_cam); c++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (i=0; i < ARRAY_SIZE(romm_cam[0]); i++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      romm_cam[c][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;  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 0x223:  ph1.black_col = data+base;  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 0x224:  ph1.split_row = data;  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 0x225:  ph1.black_row = 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;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fuji_width = !(fgetc(ifp) & 8);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else if (tag == 0x131) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
       filters = 9;
       ~~~~~~~~~~~~             
       FORC(36) xtrans_abs[0][35-c] = fgetc(ifp) & 3;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else if (tag == 0x2ff0) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 cam_mul[c ^ 1] = get2();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else if (tag == 0xc000) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       c = order;
       ~~~~~~~~~~               
       order = 0x4949;
       ~~~~~~~~~~~~~~~          
       if ((tag = get4()) > 10000) tag = get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       width = tag;
       ~~~~~~~~~~~~             
       height = get4();
       ~~~~~~~~~~~~~~~~         
       order = c;
       ~~~~~~~~~~               
     }
     ~                          
     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, 0);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (parse_tiff (save+6)) apply_tiff();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     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 && !feof(ifp))
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       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_qt (int end)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
 {
 ~                              
   unsigned save, size;
   ~~~~~~~~~~~~~~~~~~~~         
   char tag[4];
   ~~~~~~~~~~~~                 
 
                                
   order = 0x4d4d;
   ~~~~~~~~~~~~~~~              
   while (ftell(ifp)+7 < end) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     save = ftell(ifp);
     ~~~~~~~~~~~~~~~~~~         
     if ((size = get4()) < 8) return;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fread (tag, 4, 1, ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~    
     if (!memcmp(tag,"moov",4) ||
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  !memcmp(tag,"udta",4) ||
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  !memcmp(tag,"CNTH",4))
  ~~~~~~~~~~~~~~~~~~~~~~        
       parse_qt (save+size);
       ~~~~~~~~~~~~~~~~~~~~~    
     if (!memcmp(tag,"CNDA",4))
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
       parse_jpeg (ftell(ifp));
       ~~~~~~~~~~~~~~~~~~~~~~~~ 
     fseek (ifp, save+size, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
 }
 ~                              
 
                                
 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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS parse_redcine()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~     
 {
 ~                              
   unsigned i, len, rdvo;
   ~~~~~~~~~~~~~~~~~~~~~~       
 
                                
   order = 0x4d4d;
   ~~~~~~~~~~~~~~~              
   is_raw = 0;
   ~~~~~~~~~~~                  
   fseek (ifp, 52, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
   width  = get4();
   ~~~~~~~~~~~~~~~~             
   height = get4();
   ~~~~~~~~~~~~~~~~             
   fseek (ifp, 0, SEEK_END);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   fseek (ifp, -(i = ftello(ifp) & 511), SEEK_CUR);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (get4() != i || get4() != 0x52454f42) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fprintf (stderr,_("%s: Tail is missing, parsing from head...\n"), ifname);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, 0, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
     while ((len = get4()) != EOF) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (get4() == 0x52454456)
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  if (is_raw++ == shot_select)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    data_offset = ftello(ifp) - 8;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, len-8, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   } else {
   ~~~~~~~~                     
     rdvo = get4();
     ~~~~~~~~~~~~~~             
     fseek (ifp, 12, SEEK_CUR);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     is_raw = get4();
     ~~~~~~~~~~~~~~~~           
     fseeko (ifp, rdvo+8 + shot_select*4, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     data_offset = get4();
     ~~~~~~~~~~~~~~~~~~~~~      
   }
   ~                            
 }
 ~                              
 
                                
 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, 8, SEEK_CUR);
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  pent = get4();
  ~~~~~~~~~~~~~~                
  wide = get4();
  ~~~~~~~~~~~~~~                
  high = get4();
  ~~~~~~~~~~~~~~                
  if (wide > raw_width && high > raw_height) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    switch (pent) {
    ~~~~~~~~~~~~~~~             
      case  5:  load_flags = 1;
      ~~~~~~~~~~~~~~~~~~~~~~~~~ 
      case  6:  load_raw = &CLASS foveon_sd_load_raw;  break;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      case 30:  load_raw = &CLASS foveon_dp_load_raw;  break;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      default:  load_raw = 0;
      ~~~~~~~~~~~~~~~~~~~~~~~   
    }
    ~                           
    raw_width  = wide;
    ~~~~~~~~~~~~~~~~~~          
    raw_height = high;
    ~~~~~~~~~~~~~~~~~~          
    data_offset = off+28;
    ~~~~~~~~~~~~~~~~~~~~~       
    is_foveon = 1;
    ~~~~~~~~~~~~~~              
  }
  ~                             
  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+8;
  ~~~~~~~~~~~~~~~~~~~~          
  meta_length = len-28;
  ~~~~~~~~~~~~~~~~~~~~~         
  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);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
 }
 ~                              
 
                                
 /*
 ~~                             
    All matrices are from Adobe DNG Converter unless otherwise noted.
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
  ~~                            
 void CLASS adobe_coeff (const char *make, const char *model)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   static const struct {
   ~~~~~~~~~~~~~~~~~~~~~        
     const char *prefix;
     ~~~~~~~~~~~~~~~~~~~        
     short black, maximum, trans[12];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   } table[] = {
   ~~~~~~~~~~~~~                
     { "AgfaPhoto DC-833m", 0, 0, /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 III", 0, 0x3c80,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6722,-635,-963,-4287,12460,2028,-908,2162,5668 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 6D", 0, 0x3c82,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS 7D Mark II", 0, 0x3510,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7268,-1082,-969,-4186,11839,2663,-825,2029,5839 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS 7D", 0, 0x3510,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6844,-996,-856,-3876,11761,2396,-593,1772,6198 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 60D", 0, 0x2ff7,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6719,-994,-925,-4408,12426,2211,-887,2129,6051 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS 70D", 0, 0x3bc7,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS 100D", 0, 0x350f,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 500D", 0, 0x3479,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 4763,712,-646,-6821,14399,2640,-1921,3276,6561 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS 550D", 0, 0x3dd7,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6941,-1164,-857,-3825,11597,2534,-416,1540,6039 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS 600D", 0, 0x3510,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6461,-907,-882,-4300,12184,2378,-819,1944,5931 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS 650D", 0, 0x354d,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS 700D", 0, 0x3c00,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS 1000D", 0, 0xe43,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS 1100D", 0, 0x3510,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6444,-904,-893,-4563,12308,2535,-903,2016,6728 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS 1200D", 0, 0x37c2,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6461,-907,-882,-4300,12184,2378,-819,1944,5931 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS M", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 IV", 0, 0x3bb0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6014,-220,-795,-4109,12014,2361,-561,1824,5787 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS-1D Mark III", 0, 0x3bb0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS-1D Mark II N", 0, 0xe80,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 C", 0, 0x3c4e,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6847,-614,-1014,-4669,12737,2139,-1197,2488,6846 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS-1D X", 0, 0x3c4e,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6847,-614,-1014,-4669,12737,2139,-1197,2488,6846 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS-1D", 0, 0xe20,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon EOS C500", 853, 0,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 17851,-10604,922,-7425,16662,763,-3660,3636,22278 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot A530", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 0 } }, /* don't want the A5 matrix */
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 G11", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 12177,-4817,-1069,-1612,9864,2049,-98,850,4471 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot G12", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 13244,-5501,-1248,-1508,9858,1935,-270,1083,4366 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot G15", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7474,-2301,-567,-4056,11456,2975,-222,716,4181 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot G16", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8020,-2687,-682,-3704,11879,2052,-965,1921,5556 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot G1 X", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7378,-1255,-1043,-4088,12251,2048,-876,1946,5805 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 G7 X", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 S90", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 12374,-5016,-1049,-1677,9902,2078,-83,852,4683 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot S95", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 13440,-5896,-1279,-1236,9598,1931,-180,1001,4651 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot S100", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7968,-2565,-636,-2873,10697,2513,180,667,4211 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot S110", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8039,-2643,-654,-3783,11230,2930,-206,690,4194 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot S120", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6961,-1685,-695,-4625,12945,1836,-1114,2152,5518 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot SX1 IS", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6578,-259,-502,-5974,13030,3309,-308,1058,4970 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot SX50 HS", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 12432,-4753,-1247,-2110,10691,1629,-412,1623,4926 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot SX60 HS", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 13161,-5451,-1344,-1989,10654,1531,-47,1271,4955 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot A3300", 0, 0, /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10826,-3654,-1023,-3215,11310,1906,0,999,4960 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot A470", 0, 0, /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 12513,-4407,-1242,-2680,10276,2405,-878,2215,4734 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 SX110 IS", 0, 0, /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Canon PowerShot SX220", 0, 0, /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 13898,-5076,-1447,-1405,10109,1297,-244,1860,3687 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Casio EX-S20", 0, 0,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11634,-3924,-1128,-4968,12954,2015,-1588,2648,7206 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Casio EX-Z750", 0, 0,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10819,-3873,-1099,-4903,13730,1175,-1755,3751,4632 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Casio EX-Z10", 128, 0xfff, /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 9790,-3338,-603,-2321,10222,2099,-344,1273,4799 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 E550", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm E900", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm F5", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm F6", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm F77", 0, 0xfe9,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm F7", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm F8", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S100FS", 514, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 12297,-4882,-1202,-2106,10691,1623,-88,1312,4790 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S20Pro", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S20", 512, 0x3fff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11401,-4498,-1312,-5088,12751,2613,-838,1568,5941 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S2Pro", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S3Pro", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S5Pro", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S5000", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S5100", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S5500", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S5200", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S5600", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S6", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S7000", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S9000", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S9500", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S9100", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm S9600", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm SL1000", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 11705,-4262,-1107,-2282,10791,1709,-555,1713,4945 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm HS10 HS11", 0, 0xf68,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 12440,-3954,-1183,-1123,9674,1708,-83,1614,4086 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm HS2", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm HS3", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm HS50EXR", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 12085,-4727,-953,-3257,11489,2002,-511,2046,4592 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm F900EXR", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 12085,-4727,-953,-3257,11489,2002,-511,2046,4592 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X100S", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X100T", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X100", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 12161,-4457,-1069,-5034,12874,2400,-795,1724,6904 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X10", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X20", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 11768,-4971,-1133,-4904,12927,2183,-480,1723,4605 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X30", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 12328,-5256,-1144,-4469,12927,1675,-87,1291,4351 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X-Pro1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X-A1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 11086,-4555,-839,-3512,11310,2517,-815,1341,5940 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X-E1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X-E2", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X-M1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X-S1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm X-T1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm XF1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Fujifilm XQ1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 9252,-2704,-1064,-5893,14265,1717,-1101,2341,4349 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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", 178, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Kodak DCS560C", 177, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Kodak DCS620C", 177, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Kodak DCS620X", 176, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 13095,-6231,154,12221,-21,-2137,895,4602,2258 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Kodak DCS660C", 173, 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 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Kodak EasyShare Z980", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11313,-3559,-1101,-3893,11891,2257,-1214,2398,4908 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Kodak EasyShare Z981", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 12729,-4717,-1188,-1367,9187,2582,274,860,4411 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Kodak EasyShare Z990", 0, 0xfed,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11749,-4048,-1309,-1867,10572,1489,-138,1449,4522 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Kodak EASYSHARE Z1015", 0, 0xef1,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11265,-4286,-992,-4694,12343,2647,-1090,1523,5447 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 D200", 0, 0xfbc,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 D3000", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D3100", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 7911,-2167,-813,-5327,13150,2408,-1288,2483,7968 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D3200", 0, 0xfb9,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 7013,-1408,-635,-5268,12902,2640,-1470,2801,7379 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D3300", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 D3S", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~       
  { 8828,-2406,-694,-4874,12603,2541,-660,1509,7587 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D3", 0, 0,
     ~~~~~~~~~~~~~~~~~~~        
  { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 D4S", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~       
  { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D4", 0, 0,
     ~~~~~~~~~~~~~~~~~~~        
  { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon Df", 0, 0,
     ~~~~~~~~~~~~~~~~~~~        
  { 8598,-2848,-857,-5618,13606,2195,-1002,1773,7137 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D5000", 0, 0xf00,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 7309,-1403,-519,-8474,16008,2622,-2433,2826,8064 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D5100", 0, 0x3de6,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D5200", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D5300", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D5500", 0, 0,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 5765,-2176,184,-3736,9072,4664,-1028,2213,9259 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D50", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~       
  { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D600", 0, 0x3e07,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D610", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D60", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~       
  { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D7000", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D7100", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D750", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 9020,-2890,-715,-4535,12436,2348,-934,1919,7086 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 D810", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 9369,-3195,-791,-4488,12430,2301,-893,1796,6872 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon D800", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 7866,-2108,-555,-4869,12483,2681,-1176,2069,7501 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 E700", 0, 0x3dd,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon E800", 0, 0x3dd,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 E3200", 0, 0,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 9846,-2085,-1019,-3278,11109,2170,-774,2134,5745 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 A", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon COOLPIX P330", 200, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon COOLPIX P340", 200, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon COOLPIX P6000", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon COOLPIX P7000", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11432,-3679,-1111,-3169,11239,2202,-791,1380,4455 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon COOLPIX P7100", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11053,-4269,-1024,-1976,10182,2088,-526,1263,4469 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon COOLPIX P7700", 200, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon COOLPIX P7800", 200, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon 1 V3", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 5958,-1559,-571,-4021,11453,2939,-634,1548,5087 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon 1 J4", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 5958,-1559,-571,-4021,11453,2939,-634,1548,5087 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon 1 S2", 200, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 6612,-1342,-618,-3338,11055,2623,-174,1792,5075 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon 1 V2", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon 1 J3", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon 1 AW1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 6588,-1305,-693,-3277,10987,2634,-355,2016,5106 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Nikon 1 ", 0, 0,  /* J1, J2, S1, V1 */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8994,-2667,-865,-4594,12324,2552,-699,1786,6260 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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, 0xffc,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-20", 0, 0xffc,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 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, 0xfbc,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 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, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 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-450", 0, 0xfd2,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8745,-2425,-1095,-7594,15613,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 E-5", 0, 0xeec,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 11200,-3783,-1325,-4576,12593,2206,-695,1742,7504 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-600", 0, 0xfaf,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-620", 0, 0xfaf,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-P1", 0, 0xffd,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-P2", 0, 0xffd,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-P3", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-P5", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-PL1s", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 11409,-3872,-1393,-4572,12757,2003,-709,1810,7415 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-PL1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 11408,-4289,-1215,-4286,12385,2118,-387,1467,7787 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-PL2", 0, 0xcf3,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 15030,-5552,-1806,-3987,12387,1767,-592,1670,7023 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-PL3", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-PL5", 0, 0xfcb,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-PL6", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-PL7", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-PM1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-PM2", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-M10", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-M1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 7687,-1984,-606,-4327,11928,2721,-1381,2339,6452 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-M5MarkII", 0, 0, /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6617,-2589,139,-2917,8499,4419,-884,1913,6829 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus E-M5", 0, 0xfe1,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus STYLUS1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 8360,-2420,-880,-3928,12353,1739,-1381,2416,5173 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus XZ-10", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus XZ-1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 10901,-4095,-1074,-1141,9208,2293,-62,1417,5158 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Olympus XZ-2", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "OmniVision", 0, 0,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Pentax K-x", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 8843,-2837,-625,-5025,12644,2668,-411,1234,7410 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Pentax K-r", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 9895,-3077,-850,-5304,13035,2521,-883,1768,6936 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Pentax K-3", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 7415,-2052,-721,-5186,12788,2682,-1446,2157,6773 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Pentax K-5 II", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 8170,-2725,-639,-4440,12017,2744,-771,1465,6599 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Pentax K-5", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 8713,-2833,-743,-4342,11900,2772,-722,1543,6247 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Pentax K-7", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~      
  { 9142,-2947,-678,-8648,16967,1663,-2224,2898,8615 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Pentax K-S1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 8512,-3211,-787,-4167,11966,2487,-638,1288,6054 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Pentax 645D", 0, 0x3e00,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10646,-3593,-1158,-3329,11699,1831,-667,2874,6287 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-CM1", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8770,-3194,-820,-2871,11281,1803,-513,1552,4434 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-FZ8", 0, 0xf7f,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 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, 0xf96,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-FZ30", 0, 0xf94,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-FZ3", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 9938,-2780,-890,-4604,12393,2480,-1117,2304,4620 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-FZ4", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 13639,-5535,-1371,-1698,9633,2430,316,1152,4108 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-FZ50", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-FZ7", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11532,-4324,-1066,-2375,10847,1749,-564,1699,4351 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica V-LUX1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 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, 0xf7f,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica DIGILUX 3", 0, 0xf7f,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-LC1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica DIGILUX 2", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-LX100", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica D-LUX (Typ 109)", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-LF1", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 9379,-3267,-816,-3227,11560,1881,-926,1928,5340 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica C (Typ 112)", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 9379,-3267,-816,-3227,11560,1881,-926,1928,5340 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-LX1", 0, 0xf7f,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica D-LUX2", 0, 0xf7f,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-LX2", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica D-LUX3", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-LX3", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica D-LUX 4", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-LX5", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica D-LUX 5", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-LX7", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica D-LUX 6", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-FZ1000", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica V-LUX (Typ 114)", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-FZ100", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica V-LUX 2", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-FZ150", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica V-LUX 3", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-FZ200", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8112,-2563,-740,-3730,11784,2197,-941,2075,4933 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Leica V-LUX 4", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8112,-2563,-740,-3730,11784,2197,-941,2075,4933 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-FX150", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-G10", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-G1", 15, 0xf94,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-G2", 15, 0xf3c,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-G3", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-G5", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7798,-2562,-740,-3879,11584,2613,-1055,2248,5434 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-G6", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8294,-2891,-651,-3869,11590,2595,-1183,2267,5352 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GF1", 15, 0xf92,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GF2", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GF3", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 9051,-2468,-1204,-5212,13276,2121,-1197,2510,6890 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GF5", 15, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8228,-2945,-660,-3938,11792,2430,-1094,2278,5793 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GF6", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8130,-2801,-946,-3520,11289,2552,-1314,2511,5791 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GF7", 15, 0, /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6086,-2691,-18,-4207,9767,4441,-1486,2640,7441 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GH1", 15, 0xf92,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6299,-1466,-532,-6535,13852,2969,-2331,3112,5984 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GH2", 15, 0xf95,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GH3", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6559,-1752,-491,-3672,11407,2586,-962,1875,5130 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GH4", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7122,-2108,-512,-3155,11201,2231,-541,1423,5045 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GM1", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6770,-1895,-744,-5232,13145,2303,-1664,2691,5703 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GM5", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8238,-3244,-679,-3921,11814,2384,-836,2022,5852 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GX1", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-GX7", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-TZ6", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Panasonic DMC-ZS4", 15, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Phase One H 20", 0, 0,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 1313,1855,-109,-6715,15908,808,-327,1840,6020 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Phase One H 25", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "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 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Phase One P40", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Phase One P65", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Red One", 704, 0xffff,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 21014,-7891,-2613,-3056,12201,856,-2203,5125,8042 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung EX1", 0, 0x3e00,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8898,-2498,-994,-3144,11328,2066,-760,1381,4576 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung EX2F", 0, 0x7ff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10648,-3897,-1055,-2022,10573,1668,-492,1611,4742 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung EK-GN120", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung NX mini", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 5222,-1196,-550,-6540,14649,2009,-1666,2819,5657 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung NX3000", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 8060,-2933,-761,-4504,12890,1762,-630,1489,5227 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung NX30", 0, 0, /* NX30, NX300, NX300M */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung NX2000", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung NX2", 0, 0xfff, /* NX20, NX200, NX210 */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung NX1000", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung NX1100", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 6933,-2268,-753,-4921,13387,1647,-803,1641,6096 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung NX11", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung NX10", 0, 0, /* also NX100 */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung NX5", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~     
  { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung NX1", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 10686,-4042,-1052,-3595,13238,276,-464,1259,5931 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung WB2000", 0, 0xfff,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 12093,-3557,-1155,-1000,9534,1733,-22,1787,4576 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung GX-1", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung GX20", 0, 0, /* copied from Pentax K20D */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Samsung S85", 0, 0,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 11885,-3968,-1473,-4214,12299,1916,-835,1655,5549 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sinar", 0, 0,   /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSC-F828", 0, 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 DSC-RX100M", 200, 0, /* M2 and M3 */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSC-RX100", 200, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 8651,-2754,-1057,-3464,12207,1373,-568,1398,4434 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSC-RX10", 200, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 6679,-1825,-745,-5047,13256,1953,-1580,2422,5183 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSC-RX1", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A100", 0, 0xfeb,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A290", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A2", 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-A330", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 9847,-3091,-929,-8485,16346,2225,-714,595,7103 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A350", 0, 0xffc,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A380", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A390", 0, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A450", 128, 0xfeb,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A580", 128, 0xfeb,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A500", 128, 0xfeb,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6046,-1127,-278,-5574,13076,2786,-691,1419,7625 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A5", 128, 0xfeb,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A700", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A850", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 5413,-1162,-365,-5665,13098,2866,-608,1179,8440 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony DSLR-A900", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony ILCA-77M2", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 5991,-1732,-443,-4100,11989,2381,-704,1467,5992 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony ILCE-7M2", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony ILCE-7S", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 5838,-1430,-246,-3497,11477,2297,-748,1885,5778 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony ILCE-7R", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 4913,-541,-202,-6130,13513,2906,-1564,2151,7183 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony ILCE-7", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony ILCE", 128, 0, /* 3000, 5000, 5100, 6000, and QX1 */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony NEX-5N", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony NEX-5R", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony NEX-5T", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony NEX-3N", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~   
  { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony NEX-3", 138, 0,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6907,-1256,-645,-4940,12621,2320,-1710,2581,6230 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony NEX-5", 116, 0,  /* DJC */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6807,-1350,-342,-4216,11649,2567,-1089,2001,6420 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony NEX-3", 128, 0,  /* Adobe */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony NEX-5", 128, 0,  /* Adobe */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony NEX-6", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony NEX-7", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~    
  { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony NEX", 128, 0, /* NEX-C3, NEX-F3 */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony SLT-A33", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 6069,-1221,-366,-5221,12779,2734,-1024,2066,6834 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony SLT-A35", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 5986,-1618,-415,-4557,11820,3120,-681,1404,6971 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony SLT-A37", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony SLT-A55", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony SLT-A57", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony SLT-A58", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony SLT-A65", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony SLT-A77", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { "Sony SLT-A99", 128, 0,
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
  { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   };
   ~~                           
   double cam_xyz[4][3];
   ~~~~~~~~~~~~~~~~~~~~~        
   char name[130];
   ~~~~~~~~~~~~~~~              
   int i, j, c;
   ~~~~~~~~~~~~                 
 
                                
   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;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (table[i].trans[0]) {
       ~~~~~~~~~~~~~~~~~~~~~~~~ 
  for (raw_color = c=0; c < ARRAY_SIZE(cam_xyz); c++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (j=0; j < ARRAY_SIZE(cam_xyz[0]); j++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      cam_xyz[c][j] = table[i].trans[c * ARRAY_SIZE(cam_xyz[0]) + j] / 10000.0;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
  cam_xyz_coeff (rgb_cam, 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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 float CLASS find_green (int bps, int bite, int off0, int off1)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   UINT64 bitbuf=0;
   ~~~~~~~~~~~~~~~~             
   int vbits, col, i, c;
   ~~~~~~~~~~~~~~~~~~~~~        
   ushort img[2][2064];
   ~~~~~~~~~~~~~~~~~~~~         
   double sum[]={0,0};
   ~~~~~~~~~~~~~~~~~~~          
 
                                
   FORC(2) {
   ~~~~~~~~~                    
     fseek (ifp, c ? off1:off0, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (vbits=col=0; col < width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (vbits -= bps; vbits < 0; vbits += bite) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  bitbuf <<= bite;
  ~~~~~~~~~~~~~~~~              
  for (i=0; i < bite; i+=8)
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
    bitbuf |= (unsigned) (fgetc(ifp) << i);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
       img[c][col] = bitbuf << (64-bps-vbits) >> (64-bps);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   FORC(width-1) {
   ~~~~~~~~~~~~~~~              
     sum[ c & 1] += ABS(img[0][c]-img[1][c+1]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     sum[~c & 1] += ABS(img[1][c]-img[0][c+1]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   return 100 * log(sum[0]/sum[1]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 /*
 ~~                             
    Identify which camera created this file, and set global variables
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    accordingly.
    ~~~~~~~~~~~~                
  */
  ~~                            
 void CLASS identify()
 ~~~~~~~~~~~~~~~~~~~~~          
 {
 ~                              
   static const short pana[][6] = {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3130, 1743,  4,  0, -6,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3130, 2055,  4,  0, -6,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3130, 2319,  4,  0, -6,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3170, 2103, 18,  0,-42, 20 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3170, 2367, 18, 13,-42,-21 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3177, 2367,  0,  0, -1,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3304, 2458,  0,  0, -1,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3330, 2463,  9,  0, -5,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3330, 2479,  9,  0,-17,  4 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3370, 1899, 15,  0,-44, 20 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3370, 2235, 15,  0,-44, 20 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3370, 2511, 15, 10,-44,-21 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3690, 2751,  3,  0, -8, -3 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3710, 2751,  0,  0, -3,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3724, 2450,  0,  0,  0, -2 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3770, 2487, 17,  0,-44, 19 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3770, 2799, 17, 15,-44,-19 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3880, 2170,  6,  0, -6,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4060, 3018,  0,  0,  0, -2 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4290, 2391,  3,  0, -8, -1 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4330, 2439, 17, 15,-44,-19 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4508, 2962,  0,  0, -3, -4 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4508, 3330,  0,  0, -3, -6 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   };
   ~~                           
   static const ushort canon[][11] = {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 1944, 1416,   0,  0, 48,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 2144, 1560,   4,  8, 52,  2, 0, 0, 0, 25 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 2224, 1456,  48,  6,  0,  2 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 2376, 1728,  12,  6, 52,  2 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 2672, 1968,  12,  6, 44,  2 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3152, 2068,  64, 12,  0,  0, 16 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3160, 2344,  44, 12,  4,  4 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3344, 2484,   4,  6, 52,  6 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3516, 2328,  42, 14,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3596, 2360,  74, 12,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3744, 2784,  52, 12,  8, 12 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3944, 2622,  30, 18,  6,  2 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3948, 2622,  42, 18,  0,  2 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 3984, 2622,  76, 20,  0,  2, 14 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4104, 3048,  48, 12, 24, 12 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4116, 2178,   4,  2,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4152, 2772, 192, 12,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4160, 3124, 104, 11,  8, 65 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4176, 3062,  96, 17,  8,  0, 0, 16, 0, 7, 0x49 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4192, 3062,  96, 17, 24,  0, 0, 16, 0, 0, 0x49 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4312, 2876,  22, 18,  0,  2 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4352, 2874,  62, 18,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4476, 2954,  90, 34,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4480, 3348,  12, 10, 36, 12, 0, 0, 0, 18, 0x49 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4480, 3366,  80, 50,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4496, 3366,  80, 50, 12,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4768, 3516,  96, 16,  0,  0, 0, 16 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4832, 3204,  62, 26,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 4832, 3228,  62, 51,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 5108, 3349,  98, 13,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 5120, 3318, 142, 45, 62,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 5280, 3528,  72, 52,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 5344, 3516, 142, 51,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 5344, 3584, 126,100,  0,  2 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 5360, 3516, 158, 51,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 5568, 3708,  72, 38,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 5632, 3710,  96, 17,  0,  0, 0, 16, 0, 0, 0x49 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 5712, 3774,  62, 20, 10,  2 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 5792, 3804, 158, 51,  0,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 5920, 3950, 122, 80,  2,  0 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   };
   ~~                           
   static const struct {
   ~~~~~~~~~~~~~~~~~~~~~        
     ushort id;
     ~~~~~~~~~~                 
     char model[20];
     ~~~~~~~~~~~~~~~            
   } unique[] = {
   ~~~~~~~~~~~~~~               
     { 0x168, "EOS 10D" },    { 0x001, "EOS-1D" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x175, "EOS 20D" },    { 0x174, "EOS-1D Mark II" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x234, "EOS 30D" },    { 0x232, "EOS-1D Mark II N" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x190, "EOS 40D" },    { 0x169, "EOS-1D Mark III" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x261, "EOS 50D" },    { 0x281, "EOS-1D Mark IV" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x287, "EOS 60D" },    { 0x167, "EOS-1DS" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x325, "EOS 70D" },
     ~~~~~~~~~~~~~~~~~~~~~      
     { 0x170, "EOS 300D" },   { 0x188, "EOS-1Ds Mark II" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x176, "EOS 450D" },   { 0x215, "EOS-1Ds Mark III" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x189, "EOS 350D" },   { 0x324, "EOS-1D C" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x236, "EOS 400D" },   { 0x269, "EOS-1D X" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x252, "EOS 500D" },   { 0x213, "EOS 5D" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x270, "EOS 550D" },   { 0x218, "EOS 5D Mark II" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x286, "EOS 600D" },   { 0x285, "EOS 5D Mark III" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x301, "EOS 650D" },   { 0x302, "EOS 6D" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x326, "EOS 700D" },   { 0x250, "EOS 7D" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x254, "EOS 1000D" },
     ~~~~~~~~~~~~~~~~~~~~~~~    
     { 0x288, "EOS 1100D" },
     ~~~~~~~~~~~~~~~~~~~~~~~    
     { 0x327, "EOS 1200D" },
     ~~~~~~~~~~~~~~~~~~~~~~~    
     { 0x346, "EOS 100D" },
     ~~~~~~~~~~~~~~~~~~~~~~     
   }, sonique[] = {
   ~~~~~~~~~~~~~~~~             
     { 0x002, "DSC-R1" },     { 0x100, "DSLR-A100" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x101, "DSLR-A900" },  { 0x102, "DSLR-A700" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x103, "DSLR-A200" },  { 0x104, "DSLR-A350" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x105, "DSLR-A300" },  { 0x108, "DSLR-A330" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x109, "DSLR-A230" },  { 0x10a, "DSLR-A290" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x10d, "DSLR-A850" },  { 0x111, "DSLR-A550" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x112, "DSLR-A500" },  { 0x113, "DSLR-A450" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x116, "NEX-5" },      { 0x117, "NEX-3" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x118, "SLT-A33" },    { 0x119, "SLT-A55V" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x11a, "DSLR-A560" },  { 0x11b, "DSLR-A580" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x11c, "NEX-C3" },     { 0x11d, "SLT-A35" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x11e, "SLT-A65V" },   { 0x11f, "SLT-A77V" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x120, "NEX-5N" },     { 0x121, "NEX-7" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x123, "SLT-A37" },    { 0x124, "SLT-A57" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x125, "NEX-F3" },     { 0x126, "SLT-A99V" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x127, "NEX-6" },      { 0x128, "NEX-5R" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x129, "DSC-RX100" },  { 0x12a, "DSC-RX1" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x12e, "ILCE-3000" },  { 0x12f, "SLT-A58" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x131, "NEX-3N" },     { 0x132, "ILCE-7" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x133, "NEX-5T" },     { 0x134, "DSC-RX100M2" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x135, "DSC-RX10" },   { 0x136, "DSC-RX1R" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x137, "ILCE-7R" },    { 0x138, "ILCE-6000" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x139, "ILCE-5000" },  { 0x13d, "DSC-RX100M3" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x13e, "ILCE-7S" },    { 0x13f, "ILCA-77M2" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x153, "ILCE-5100" },  { 0x154, "ILCE-7M2" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 0x15a, "ILCE-QX1" },
     ~~~~~~~~~~~~~~~~~~~~~~     
   };
   ~~                           
   static const struct {
   ~~~~~~~~~~~~~~~~~~~~~        
     unsigned fsize;
     ~~~~~~~~~~~~~~~            
     ushort rw, rh;
     ~~~~~~~~~~~~~~             
     uchar lm, tm, rm, bm, lf, cf, max, flags;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     char make[10], model[20];
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
     ushort offset;
     ~~~~~~~~~~~~~~             
   } table[] = {
   ~~~~~~~~~~~~~                
     {   786432,1024, 768, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-080C" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  1447680,1392,1040, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-145C" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  1920000,1600,1200, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-201C" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  5067304,2588,1958, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-510C" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  5067316,2588,1958, 0, 0, 0, 0, 0,0x94,0,0,"AVT","F-510C",12 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 10134608,2588,1958, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-510C" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 10134620,2588,1958, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-510C",12 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 16157136,3272,2469, 0, 0, 0, 0, 9,0x94,0,0,"AVT","F-810C" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 15980544,3264,2448, 0, 0, 0, 0, 8,0x61,0,1,"AgfaPhoto","DC-833m" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  9631728,2532,1902, 0, 0, 0, 0,96,0x61,0,0,"Alcatel","5035D" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  2868726,1384,1036, 0, 0, 0, 0,64,0x49,0,8,"Baumer","TXG14",1078 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  5298000,2400,1766,12,12,44, 2,40,0x94,0,2,"Canon","PowerShot SD300" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  6553440,2664,1968, 4, 4,44, 4,40,0x94,0,2,"Canon","PowerShot A460" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  6573120,2672,1968,12, 8,44, 0,40,0x94,0,2,"Canon","PowerShot A610" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  6653280,2672,1992,10, 6,42, 2,40,0x94,0,2,"Canon","PowerShot A530" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  7710960,2888,2136,44, 8, 4, 0,40,0x94,0,2,"Canon","PowerShot S3 IS" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  9219600,3152,2340,36,12, 4, 0,40,0x94,0,2,"Canon","PowerShot A620" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  9243240,3152,2346,12, 7,44,13,40,0x49,0,2,"Canon","PowerShot A470" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 10341600,3336,2480, 6, 5,32, 3,40,0x94,0,2,"Canon","PowerShot A720 IS" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 10383120,3344,2484,12, 6,44, 6,40,0x94,0,2,"Canon","PowerShot A630" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 12945240,3736,2772,12, 6,52, 6,40,0x94,0,2,"Canon","PowerShot A640" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 15636240,4104,3048,48,12,24,12,40,0x94,0,2,"Canon","PowerShot A650" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 15467760,3720,2772, 6,12,30, 0,40,0x94,0,2,"Canon","PowerShot SX110 IS" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 15534576,3728,2778,12, 9,44, 9,40,0x94,0,2,"Canon","PowerShot SX120 IS" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 18653760,4080,3048,24,12,24,12,40,0x94,0,2,"Canon","PowerShot SX20 IS" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 19131120,4168,3060,92,16, 4, 1,40,0x94,0,2,"Canon","PowerShot SX220 HS" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 21936096,4464,3276,25,10,73,12,40,0x16,0,2,"Canon","PowerShot SX30 IS" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 24724224,4704,3504, 8,16,56, 8,40,0x94,0,2,"Canon","PowerShot A3300 IS" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  1976352,1632,1211, 0, 2, 0, 1, 0,0x94,0,1,"Casio","QV-2000UX" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  3217760,2080,1547, 0, 0,10, 1, 0,0x94,0,1,"Casio","QV-3*00EX" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  6218368,2585,1924, 0, 0, 9, 0, 0,0x94,0,1,"Casio","QV-5700" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  7816704,2867,2181, 0, 0,34,36, 0,0x16,0,1,"Casio","EX-Z60" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  2937856,1621,1208, 0, 0, 1, 0, 0,0x94,7,13,"Casio","EX-S20" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  4948608,2090,1578, 0, 0,32,34, 0,0x94,7,1,"Casio","EX-S100" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  6054400,2346,1720, 2, 0,32, 0, 0,0x94,7,1,"Casio","QV-R41" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  7426656,2568,1928, 0, 0, 0, 0, 0,0x94,0,1,"Casio","EX-P505" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  7530816,2602,1929, 0, 0,22, 0, 0,0x94,7,1,"Casio","QV-R51" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  7542528,2602,1932, 0, 0,32, 0, 0,0x94,7,1,"Casio","EX-Z50" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  7562048,2602,1937, 0, 0,25, 0, 0,0x16,7,1,"Casio","EX-Z500" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  7753344,2602,1986, 0, 0,32,26, 0,0x94,7,1,"Casio","EX-Z55" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  9313536,2858,2172, 0, 0,14,30, 0,0x94,7,1,"Casio","EX-P600" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 10834368,3114,2319, 0, 0,27, 0, 0,0x94,0,1,"Casio","EX-Z750" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 10843712,3114,2321, 0, 0,25, 0, 0,0x94,0,1,"Casio","EX-Z75" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 10979200,3114,2350, 0, 0,32,32, 0,0x94,7,1,"Casio","EX-P700" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 12310144,3285,2498, 0, 0, 6,30, 0,0x94,0,1,"Casio","EX-Z850" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 12489984,3328,2502, 0, 0,47,35, 0,0x94,0,1,"Casio","EX-Z8" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 15499264,3754,2752, 0, 0,82, 0, 0,0x94,0,1,"Casio","EX-Z1050" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 18702336,4096,3044, 0, 0,24, 0,80,0x94,7,1,"Casio","EX-ZR100" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  7684000,2260,1700, 0, 0, 0, 0,13,0x94,0,1,"Casio","QV-4000" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {   787456,1024, 769, 0, 1, 0, 0, 0,0x49,0,0,"Creative","PC-CAM 600" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 28829184,4384,3288, 0, 0, 0, 0,36,0x61,0,0,"DJI" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 15151104,4608,3288, 0, 0, 0, 0, 0,0x94,0,0,"Matrix" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  3840000,1600,1200, 0, 0, 0, 0,65,0x49,0,0,"Foculus","531C" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {   307200, 640, 480, 0, 0, 0, 0, 0,0x94,0,0,"Generic" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {    62464, 256, 244, 1, 1, 6, 1, 0,0x8d,0,0,"Kodak","DC20" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {   124928, 512, 244, 1, 1,10, 1, 0,0x8d,0,0,"Kodak","DC20" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  1652736,1536,1076, 0,52, 0, 0, 0,0x61,0,0,"Kodak","DCS200" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  4159302,2338,1779, 1,33, 1, 2, 0,0x94,0,0,"Kodak","C330" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  4162462,2338,1779, 1,33, 1, 2, 0,0x94,0,0,"Kodak","C330",3160 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  2247168,1232, 912, 0, 0,16, 0, 0,0x00,0,0,"Kodak","C330" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  3370752,1232, 912, 0, 0,16, 0, 0,0x00,0,0,"Kodak","C330" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  6163328,2864,2152, 0, 0, 0, 0, 0,0x94,0,0,"Kodak","C603" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  6166488,2864,2152, 0, 0, 0, 0, 0,0x94,0,0,"Kodak","C603",3160 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {   460800, 640, 480, 0, 0, 0, 0, 0,0x00,0,0,"Kodak","C603" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  9116448,2848,2134, 0, 0, 0, 0, 0,0x00,0,0,"Kodak","C603" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 12241200,4040,3030, 2, 0, 0,13, 0,0x49,0,0,"Kodak","12MP" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 12272756,4040,3030, 2, 0, 0,13, 0,0x49,0,0,"Kodak","12MP",31556 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 18000000,4000,3000, 0, 0, 0, 0, 0,0x00,0,0,"Kodak","12MP" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {   614400, 640, 480, 0, 3, 0, 0,64,0x94,0,0,"Kodak","KAI-0340" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 15360000,3200,2400, 0, 0, 0, 0,96,0x16,0,0,"Lenovo","A820" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  3884928,1608,1207, 0, 0, 0, 0,96,0x16,0,0,"Micron","2010",3212 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  1138688,1534, 986, 0, 0, 0, 0, 0,0x61,0,0,"Minolta","RD175",513 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  1581060,1305, 969, 0, 0,18, 6, 6,0x1e,4,1,"Nikon","E900" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  2465792,1638,1204, 0, 0,22, 1, 6,0x4b,5,1,"Nikon","E950" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  2940928,1616,1213, 0, 0, 0, 7,30,0x94,0,1,"Nikon","E2100" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  4771840,2064,1541, 0, 0, 0, 1, 6,0xe1,0,1,"Nikon","E990" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  4775936,2064,1542, 0, 0, 0, 0,30,0x94,0,1,"Nikon","E3700" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  5865472,2288,1709, 0, 0, 0, 1, 6,0xb4,0,1,"Nikon","E4500" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  5869568,2288,1710, 0, 0, 0, 0, 6,0x16,0,1,"Nikon","E4300" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  7438336,2576,1925, 0, 0, 0, 1, 6,0xb4,0,1,"Nikon","E5000" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  8998912,2832,2118, 0, 0, 0, 0,30,0x94,7,1,"Nikon","COOLPIX S6" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  5939200,2304,1718, 0, 0, 0, 0,30,0x16,0,0,"Olympus","C770UZ" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  3178560,2064,1540, 0, 0, 0, 0, 0,0x94,0,1,"Pentax","Optio S" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  4841984,2090,1544, 0, 0,22, 0, 0,0x94,7,1,"Pentax","Optio S" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  6114240,2346,1737, 0, 0,22, 0, 0,0x94,7,1,"Pentax","Optio S4" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 10702848,3072,2322, 0, 0, 0,21,30,0x94,0,1,"Pentax","Optio 750Z" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 13248000,2208,3000, 0, 0, 0, 0,13,0x61,0,0,"Pixelink","A782" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  6291456,2048,1536, 0, 0, 0, 0,96,0x61,0,0,"RoverShot","3320AF" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {   311696, 644, 484, 0, 0, 0, 0, 0,0x16,0,8,"ST Micro","STV680 VGA" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 16098048,3288,2448, 0, 0,24, 0, 9,0x94,0,1,"Samsung","S85" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 16215552,3312,2448, 0, 0,48, 0, 9,0x94,0,1,"Samsung","S85" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 20487168,3648,2808, 0, 0, 0, 0,13,0x94,5,1,"Samsung","WB550" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 24000000,4000,3000, 0, 0, 0, 0,13,0x94,5,1,"Samsung","WB550" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 12582980,3072,2048, 0, 0, 0, 0,33,0x61,0,0,"Sinar","",68 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 33292868,4080,4080, 0, 0, 0, 0,33,0x61,0,0,"Sinar","",68 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { 44390468,4080,5440, 0, 0, 0, 0,33,0x61,0,0,"Sinar","",68 },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  1409024,1376,1024, 0, 0, 1, 0, 0,0x49,0,0,"Sony","XCD-SX910CR" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {  2818048,1376,1024, 0, 0, 1, 0,97,0x49,0,0,"Sony","XCD-SX910CR" },
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   };
   ~~                           
   static const char *corp[] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     { "AgfaPhoto", "Canon", "Casio", "Epson", "Fujifilm",
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       "Mamiya", "Minolta", "Motorola", "Kodak", "Konica", "Leica",
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       "Nikon", "Nokia", "Olympus", "Pentax", "Phase One", "Ricoh",
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       "Samsung", "Sigma", "Sinar", "Sony" };
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   char head[32], *cp;
   ~~~~~~~~~~~~~~~~~~~          
   int hlen, flen, fsize, zero_fsize=1, i, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   struct jhead jh;
   ~~~~~~~~~~~~~~~~             
 
                                
   tiff_flip = flip = filters = UINT_MAX; /* 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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   tiff_nifds = 0;
   ~~~~~~~~~~~~~~~              
   memset (tiff_ifd, 0, sizeof tiff_ifd);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   memset (gpsdata, 0, sizeof gpsdata);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   memset (cblack, 0, sizeof cblack);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   memset (white, 0, sizeof white);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   memset (mask, 0, sizeof mask);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   thumb_offset = thumb_length = thumb_width = thumb_height = 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   load_raw = thumb_load_raw = 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   write_thumb = &CLASS jpeg_thumb;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   data_offset = meta_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 = 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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;
   ~~~~~~~~~~~                  
   for (i=0; i < 0x10000; i++) curve[i] = i;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   order = get2();
   ~~~~~~~~~~~~~~~              
   hlen = get4();
   ~~~~~~~~~~~~~~               
   fseek (ifp, 0, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   fread (head, 1, 32, ifp);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   fseek (ifp, 0, SEEK_END);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   flen = 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)) apply_tiff();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   } else if (order == 0x4949 || order == 0x4d4d) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!memcmp (head+6,"HEAPCCDR",8)) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       data_offset = hlen;
       ~~~~~~~~~~~~~~~~~~~      
       parse_ciff (hlen, flen-hlen, 0);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       load_raw = &CLASS canon_load_raw;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else if (parse_tiff(0)) apply_tiff();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   } 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");
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     load_raw = &CLASS quicktake_100_load_raw;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   } else if (!strcmp (head, "qktn")) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     strcpy (make, "Apple");
     ~~~~~~~~~~~~~~~~~~~~~~~    
     strcpy (model,"QuickTake 150");
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     load_raw = &CLASS kodak_radc_load_raw;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   } 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);
  ~~~~~~~~~~~~~~~               
     }
     ~                          
     load_raw = &CLASS unpacked_load_raw;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, 100+28*(shot_select > 0), SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     parse_tiff (data_offset = get4());
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     parse_tiff (thumb_offset+12);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     apply_tiff();
     ~~~~~~~~~~~~~              
   } else if (!memcmp (head,"RIFF",4)) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, 0, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
     parse_riff();
     ~~~~~~~~~~~~~              
   } else if (!memcmp (head+4,"ftypqt   ",9)) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, 0, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
     parse_qt (fsize);
     ~~~~~~~~~~~~~~~~~          
     is_raw = 0;
     ~~~~~~~~~~~                
   } 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,"NOKIARAW",8)) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     strcpy (make, "NOKIA");
     ~~~~~~~~~~~~~~~~~~~~~~~    
     order = 0x4949;
     ~~~~~~~~~~~~~~~            
     fseek (ifp, 300, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     data_offset = get4();
     ~~~~~~~~~~~~~~~~~~~~~      
     i = get4();
     ~~~~~~~~~~~                
     width = get2();
     ~~~~~~~~~~~~~~~            
     height = get2();
     ~~~~~~~~~~~~~~~~           
     switch (tiff_bps = i*8 / (width * height)) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case  8: load_raw = &CLASS eight_bit_load_raw;  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 10: load_raw = &CLASS nokia_load_raw;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     raw_height = height + (top_margin = i / (width * tiff_bps/8) - height);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[0][3] = 1;
     ~~~~~~~~~~~~~~~            
     filters = 0x61616161;
     ~~~~~~~~~~~~~~~~~~~~~      
   } else if (!memcmp (head,"ARRI",4)) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     order = 0x4949;
     ~~~~~~~~~~~~~~~            
     fseek (ifp, 20, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     width = get4();
     ~~~~~~~~~~~~~~~            
     height = get4();
     ~~~~~~~~~~~~~~~~           
     strcpy (make, "ARRI");
     ~~~~~~~~~~~~~~~~~~~~~~     
     fseek (ifp, 668, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fread (model, 1, 64, ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     data_offset = 4096;
     ~~~~~~~~~~~~~~~~~~~        
     load_raw = &CLASS packed_load_raw;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     load_flags = 88;
     ~~~~~~~~~~~~~~~~           
     filters = 0x61616161;
     ~~~~~~~~~~~~~~~~~~~~~      
   } else if (!memcmp (head,"XPDS",4)) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     order = 0x4949;
     ~~~~~~~~~~~~~~~            
     fseek (ifp, 0x800, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fread (make, 1, 41, ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
     raw_height = get2();
     ~~~~~~~~~~~~~~~~~~~~       
     raw_width  = get2();
     ~~~~~~~~~~~~~~~~~~~~       
     fseek (ifp, 56, SEEK_CUR);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     fread (model, 1, 30, ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     data_offset = 0x10000;
     ~~~~~~~~~~~~~~~~~~~~~~     
     load_raw = &CLASS canon_rmf_load_raw;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     gamma_curve (0, 12.25, 1, 1023);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   } else if (!memcmp (head+4,"RED1",4)) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     strcpy (make, "Red");
     ~~~~~~~~~~~~~~~~~~~~~      
     strcpy (model,"One");
     ~~~~~~~~~~~~~~~~~~~~~      
     parse_redcine();
     ~~~~~~~~~~~~~~~~           
     load_raw = &CLASS redcine_load_raw;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     gamma_curve (1/2.4, 12.92, 1, 4095);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     filters = 0x49494949;
     ~~~~~~~~~~~~~~~~~~~~~      
   } 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 (zero_fsize=i=0; i < sizeof table / sizeof *table; i++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (fsize == table[i].fsize) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  strcpy (make,  table[i].make );
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  strcpy (model, table[i].model);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  flip = table[i].flags >> 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  zero_is_bad = table[i].flags & 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (table[i].flags & 1)
  ~~~~~~~~~~~~~~~~~~~~~~~       
    parse_external_jpeg();
    ~~~~~~~~~~~~~~~~~~~~~~      
  data_offset = table[i].offset;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  raw_width   = table[i].rw;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  raw_height  = table[i].rh;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  left_margin = table[i].lm;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
   top_margin = table[i].tm;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
  width  = raw_width - left_margin - table[i].rm;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  height = raw_height - top_margin - table[i].bm;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  filters = 0x1010101 * table[i].cf;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  colors = 4 - !((filters & filters >> 1) & 0x5555);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  load_flags = table[i].lf;
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  switch (tiff_bps = (fsize-data_offset)*8 / (raw_width*raw_height)) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    case 6:
    ~~~~~~~                     
      load_raw = &CLASS minolta_rd175_load_raw;  break;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    case 8:
    ~~~~~~~                     
      load_raw = &CLASS eight_bit_load_raw;  break;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    case 10: case 12:
    ~~~~~~~~~~~~~~~~~           
      load_flags |= 128;
      ~~~~~~~~~~~~~~~~~~        
      load_raw = &CLASS packed_load_raw;     break;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    case 16:
    ~~~~~~~~                    
      order = 0x4949 | 0x404 * (load_flags & 1);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      tiff_bps -= load_flags >> 4;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      tiff_bps -= load_flags = load_flags >> 1 & 7;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      load_raw = &CLASS unpacked_load_raw;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
  maximum = (1 << tiff_bps) - (1 << table[i].max);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
   if (zero_fsize) fsize = 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
   if (make[0] == 0) parse_smal (0, flen);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (make[0] == 0) {
   ~~~~~~~~~~~~~~~~~~~          
     parse_jpeg(0);
     ~~~~~~~~~~~~~~             
     if (!(strncmp(model,"ov",2) && strncmp(model,"RP_OV",5)) &&
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  !fseek (ifp, -6404096, SEEK_END) &&
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  fread (head, 1, 32, ifp) && !strcmp(head,"BRCMn")) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       strcpy (make, "OmniVision");
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       data_offset = ftell(ifp) + 0x8000-32;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       width = raw_width;
       ~~~~~~~~~~~~~~~~~~       
       raw_width = 2611;
       ~~~~~~~~~~~~~~~~~        
       load_raw = &CLASS nokia_load_raw;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       filters = 0x16161616;
       ~~~~~~~~~~~~~~~~~~~~~    
     } else is_raw = 0;
     ~~~~~~~~~~~~~~~~~~         
   }
   ~                            
 
                                
   for (i=0; i < sizeof corp / sizeof *corp; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (strcasestr (make, corp[i])) /* Simplify company names */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      strcpy (make, corp[i]);
      ~~~~~~~~~~~~~~~~~~~~~~~   
   if ((!strcmp(make,"Kodak") || !strcmp(make,"Leica")) &&
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ((cp = strcasestr(model," DIGITAL CAMERA")) ||
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   (cp = strstr(model,"FILE VERSION"))))
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      *cp = 0;
      ~~~~~~~~                  
   if (!strncasecmp(model,"PENTAX",6))
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     strcpy (make, "Pentax");
     ~~~~~~~~~~~~~~~~~~~~~~~~   
   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,"FinePix ",8))
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     strcpy (model, model+8);
     ~~~~~~~~~~~~~~~~~~~~~~~~   
   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 (!height) height = raw_height;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (!width)  width  = raw_width;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (height == 2624 && width == 3936) /* Pentax K10D and Samsung GX10 */
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { height  = 2616;   width  = 3896; }
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (height == 3136 && width == 4864)  /* Pentax K20D and Samsung GX20 */
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { height  = 3124;   width  = 4688; filters = 0x16161616; }
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (width == 4352 && (!strcmp(model,"K-r") || !strcmp(model,"K-x")))
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     {   width  = 4309; filters = 0x16161616; }
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (width >= 4960 && !strncmp(model,"K-5",3))
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { left_margin = 10; width  = 4950; filters = 0x16161616; }
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (width == 4736 && !strcmp(model,"K-7"))
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { height  = 3122;   width  = 4684; filters = 0x16161616; top_margin = 2; }
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (width == 6080 && !strcmp(model,"K-3"))
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { left_margin = 4;  width  = 6040; }
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (width == 7424 && !strcmp(model,"645D"))
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     { height  = 5502;   width  = 7328; filters = 0x61616161; top_margin = 29;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       left_margin = 48; }
       ~~~~~~~~~~~~~~~~~~~      
   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;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     switch (tiff_compress) {
     ~~~~~~~~~~~~~~~~~~~~~~~~   
       case 1:     load_raw = &CLASS   packed_dng_load_raw;  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 7:     load_raw = &CLASS lossless_dng_load_raw;  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 34892: load_raw = &CLASS    lossy_dng_load_raw;  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       default:    load_raw = 0;
       ~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     goto dng_skip;
     ~~~~~~~~~~~~~~             
   }
   ~                            
   if (!strcmp(make,"Canon") && !fsize && tiff_bps != 15) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!load_raw)
     ~~~~~~~~~~~~~~             
       load_raw = &CLASS lossless_jpeg_load_raw;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (i=0; i < sizeof canon / sizeof *canon; i++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (raw_width == canon[i][0] && raw_height == canon[i][1]) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  width  = raw_width - (left_margin = canon[i][2]);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  height = raw_height - (top_margin = canon[i][3]);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  width  -= canon[i][4];
  ~~~~~~~~~~~~~~~~~~~~~~        
  height -= canon[i][5];
  ~~~~~~~~~~~~~~~~~~~~~~        
  mask[0][1] =  canon[i][6];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  mask[0][3] = -canon[i][7];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  mask[1][1] =  canon[i][8];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  mask[1][3] = -canon[i][9];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  if (canon[i][10]) filters = canon[i][10] * 0x01010101;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     if ((unique_id | 0x20000) == 0x2720000) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       left_margin = 8;
       ~~~~~~~~~~~~~~~~         
       top_margin = 16;
       ~~~~~~~~~~~~~~~~         
     }
     ~                          
   }
   ~                            
   for (i=0; i < sizeof unique / sizeof *unique; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (unique_id == 0x80000000 + unique[i].id) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       adobe_coeff ("Canon", unique[i].model);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (model[4] == 'K' && strlen(model) == 8)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  strcpy (model, unique[i].model);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   for (i=0; i < sizeof sonique / sizeof *sonique; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (unique_id == sonique[i].id)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       strcpy (model, sonique[i].model);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (!strcmp(make,"Nikon")) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     if (!load_raw)
     ~~~~~~~~~~~~~~             
       load_raw = &CLASS packed_load_raw;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (model[0] == 'E')
     ~~~~~~~~~~~~~~~~~~~~       
       load_flags |= !data_offset << 2 | 2;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
 
                                
 /* Set parameters based on camera name (for non-DNG files). */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (!strcmp(model,"KAI-0340")
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  && find_green (16, 16, 3840, 5120) < 25) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     height = 480;
     ~~~~~~~~~~~~~              
     top_margin = filters = 0;
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
     strcpy (model,"C603");
     ~~~~~~~~~~~~~~~~~~~~~~     
   }
   ~                            
   if (is_foveon) {
   ~~~~~~~~~~~~~~~~             
     if (height*2 < width) pixel_aspect = 0.5;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (height   > width) pixel_aspect = 2;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     filters = 0;
     ~~~~~~~~~~~~               
     simple_coeff(0);
     ~~~~~~~~~~~~~~~~           
   } else if (!strcmp(make,"Canon") && tiff_bps == 15) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     switch (width) {
     ~~~~~~~~~~~~~~~~           
       case 3344: width -= 66;
       ~~~~~~~~~~~~~~~~~~~~~~~  
       case 3872: width -= 6;
       ~~~~~~~~~~~~~~~~~~~~~~   
     }
     ~                          
     if (height > width) SWAP(height,width);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     filters = 0;
     ~~~~~~~~~~~~               
     tiff_samples = colors = 3;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     load_raw = &CLASS canon_sraw_load_raw;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   } else if (!strcmp(model,"PowerShot 600")) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     height = 613;
     ~~~~~~~~~~~~~              
     width  = 854;
     ~~~~~~~~~~~~~              
     raw_width = 896;
     ~~~~~~~~~~~~~~~~           
     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;
     ~~~~~~~~~~~~~~~~~~~~~~~~~  
     filters = 0x1e4e1e4e;
     ~~~~~~~~~~~~~~~~~~~~~      
     goto canon_a5;
     ~~~~~~~~~~~~~~             
   } else if (!strcmp(model,"PowerShot A50")) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     height =  968;
     ~~~~~~~~~~~~~~             
     width  = 1290;
     ~~~~~~~~~~~~~~             
     raw_width = 1320;
     ~~~~~~~~~~~~~~~~~          
     filters = 0x1b4e4b1e;
     ~~~~~~~~~~~~~~~~~~~~~      
     goto canon_a5;
     ~~~~~~~~~~~~~~             
   } else if (!strcmp(model,"PowerShot Pro70")) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     height = 1024;
     ~~~~~~~~~~~~~~             
     width  = 1552;
     ~~~~~~~~~~~~~~             
     filters = 0x1e4b4e1b;
     ~~~~~~~~~~~~~~~~~~~~~      
 canon_a5:
 ~~~~~~~~~                      
     colors = 4;
     ~~~~~~~~~~~                
     tiff_bps = 10;
     ~~~~~~~~~~~~~~             
     load_raw = &CLASS packed_load_raw;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     load_flags = 40;
     ~~~~~~~~~~~~~~~~           
   } else if (!strcmp(model,"PowerShot Pro90 IS") ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       !strcmp(model,"PowerShot G1")) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     colors = 4;
     ~~~~~~~~~~~                
     filters = 0xb4b4b4b4;
     ~~~~~~~~~~~~~~~~~~~~~      
   } else if (!strcmp(model,"PowerShot A610")) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (canon_s2is()) strcpy (model+10, "S2 IS");
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   } else if (!strcmp(model,"PowerShot SX220 HS")) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[1][3] = -4;
     ~~~~~~~~~~~~~~~~           
   } else if (!strcmp(model,"EOS D2000C")) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     filters = 0x61616161;
     ~~~~~~~~~~~~~~~~~~~~~      
     black = curve[200];
     ~~~~~~~~~~~~~~~~~~~        
   } 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")  ||
       ~~~~~~~~~~~~~~~~~~~~~~~~ 
       !strcmp(model,"D3000")) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
     height -= 3;
     ~~~~~~~~~~~~               
     width  -= 4;
     ~~~~~~~~~~~~               
   } else if (!strcmp(model,"D3")   ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       !strcmp(model,"D3S")  ||
       ~~~~~~~~~~~~~~~~~~~~~~~~ 
       !strcmp(model,"D700")) {
       ~~~~~~~~~~~~~~~~~~~~~~~~ 
     width -= 4;
     ~~~~~~~~~~~                
     left_margin = 2;
     ~~~~~~~~~~~~~~~~           
   } else if (!strcmp(model,"D3100")) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     width -= 28;
     ~~~~~~~~~~~~               
     left_margin = 6;
     ~~~~~~~~~~~~~~~~           
   } else if (!strcmp(model,"D5000") ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       !strcmp(model,"D90")) {
       ~~~~~~~~~~~~~~~~~~~~~~~  
     width -= 42;
     ~~~~~~~~~~~~               
   } else if (!strcmp(model,"D5100") ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       !strcmp(model,"D7000") ||
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       !strcmp(model,"COOLPIX A")) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     width -= 44;
     ~~~~~~~~~~~~               
   } else if (!strcmp(model,"D3200") ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      !strncmp(model,"D6",2)  ||
      ~~~~~~~~~~~~~~~~~~~~~~~~~~
      !strncmp(model,"D800",4)) {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     width -= 46;
     ~~~~~~~~~~~~               
   } else if (!strcmp(model,"D4") ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       !strcmp(model,"Df")) {
       ~~~~~~~~~~~~~~~~~~~~~~   
     width -= 52;
     ~~~~~~~~~~~~               
     left_margin = 2;
     ~~~~~~~~~~~~~~~~           
   } else if (!strncmp(model,"D40",3) ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       !strncmp(model,"D50",3) ||
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       !strncmp(model,"D70",3)) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
     width--;
     ~~~~~~~~                   
   } else if (!strcmp(model,"D100")) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (load_flags)
     ~~~~~~~~~~~~~~~            
       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 (!strncmp(model,"D300",4)) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     width -= 32;
     ~~~~~~~~~~~~               
   } else if (!strncmp(model,"COOLPIX P",9) && raw_width != 4032) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     load_flags = 24;
     ~~~~~~~~~~~~~~~~           
     filters = 0x94949494;
     ~~~~~~~~~~~~~~~~~~~~~      
     if (model[9] == '7' && iso_speed >= 400)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       black = 255;
       ~~~~~~~~~~~~             
   } else if (!strncmp(model,"1 ",2)) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     height -= 2;
     ~~~~~~~~~~~~               
   } else if (fsize == 1581060) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     simple_coeff(3);
     ~~~~~~~~~~~~~~~~           
     pre_mul[0] = 1.2085;
     ~~~~~~~~~~~~~~~~~~~~       
     pre_mul[1] = 1.0943;
     ~~~~~~~~~~~~~~~~~~~~       
     pre_mul[3] = 1.1103;
     ~~~~~~~~~~~~~~~~~~~~       
   } else if (fsize == 3178560) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     cam_mul[0] *= 4;
     ~~~~~~~~~~~~~~~~           
     cam_mul[2] *= 4;
     ~~~~~~~~~~~~~~~~           
   } else if (fsize == 4771840) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     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 (fsize == 2940928) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!timestamp && !nikon_e2100())
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       strcpy (model,"E2500");
       ~~~~~~~~~~~~~~~~~~~~~~~  
     if (!strcmp(model,"E2500")) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       height -= 2;
       ~~~~~~~~~~~~             
       load_flags = 6;
       ~~~~~~~~~~~~~~~          
       colors = 4;
       ~~~~~~~~~~~              
       filters = 0x4b4b4b4b;
       ~~~~~~~~~~~~~~~~~~~~~    
     }
     ~                          
   } else if (fsize == 4775936) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!timestamp) nikon_3700();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (model[0] == 'E' && atoi(model+1) < 3700)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       filters = 0x49494949;
       ~~~~~~~~~~~~~~~~~~~~~    
     if (!strcmp(model,"Optio 33WR")) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       flip = 1;
       ~~~~~~~~~                
       filters = 0x16161616;
       ~~~~~~~~~~~~~~~~~~~~~    
     }
     ~                          
     if (make[0] == 'O') {
     ~~~~~~~~~~~~~~~~~~~~~      
       i = find_green (12, 32, 1188864, 3576832);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       c = find_green (12, 32, 2383920, 2387016);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (abs(i) < abs(c)) {
       ~~~~~~~~~~~~~~~~~~~~~~   
  SWAP(i,c);
  ~~~~~~~~~~                    
  load_flags = 24;
  ~~~~~~~~~~~~~~~~              
       }
       ~                        
       if (i < 0) filters = 0x61616161;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   } else if (fsize == 5869568) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!timestamp && minolta_z2()) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       strcpy (make, "Minolta");
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       strcpy (model,"DiMAGE Z2");
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     load_flags = 6 + 24*(make[0] == 'M');
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   } else if (fsize == 6291456) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     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,"Fujifilm")) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!strcmp(model+7,"S2Pro")) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       strcpy (model,"S2Pro");
       ~~~~~~~~~~~~~~~~~~~~~~~  
       height = 2144;
       ~~~~~~~~~~~~~~           
       width  = 2880;
       ~~~~~~~~~~~~~~           
       flip = 6;
       ~~~~~~~~~                
     } else if (load_raw != &CLASS packed_load_raw)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       maximum = (is_raw == 2 && shot_select) ? 0x2f00 : 0x3e00;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     top_margin = (raw_height - height) >> 2 << 1;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     left_margin = (raw_width - width ) >> 2 << 1;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (width == 2848 || width == 3664) filters = 0x16161616;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (width == 4032 || width == 4952) left_margin = 0;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (width == 3328 && (width -= 66)) left_margin = 34;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (width == 4936) left_margin = 4;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!strcmp(model,"HS50EXR") ||
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  !strcmp(model,"F900EXR")) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
       width += 2;
       ~~~~~~~~~~~              
       left_margin = 0;
       ~~~~~~~~~~~~~~~~         
       filters = 0x16161616;
       ~~~~~~~~~~~~~~~~~~~~~    
     }
     ~                          
     if (fuji_layout) raw_width *= is_raw;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (filters == 9)
     ~~~~~~~~~~~~~~~~~          
       FORC(36) xtrans[0][c] =
       ~~~~~~                   
codecs/dcraw.h:8758:7: note: in expansion of macro 'FORC'
       FORC(36) xtrans[0][c] =
       ^~~~
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/pcx.d' -o 'objdir/codecs/pcx.o' 'codecs/pcx.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/pdf.d' -o 'objdir/codecs/pdf.o' 'codecs/pdf.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/png.d' -o 'objdir/codecs/png.o' 'codecs/png.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/pnm.d' -o 'objdir/codecs/pnm.o' 'codecs/pnm.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/ps.d' -o 'objdir/codecs/ps.o' 'codecs/ps.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/raw.d' -o 'objdir/codecs/raw.o' 'codecs/raw.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/svg.d' -o 'objdir/codecs/svg.o' 'codecs/svg.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/tga.d' -o 'objdir/codecs/tga.o' 'codecs/tga.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/tiff.d' -o 'objdir/codecs/tiff.o' 'codecs/tiff.cc'
cc -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/transupp.d' -o 'objdir/codecs/transupp.o' 'codecs/transupp.c'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/codecs/xpm.d' -o 'objdir/codecs/xpm.o' 'codecs/xpm.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/bardecode/Scanner.d' -o 'objdir/bardecode/Scanner.o' 'bardecode/Scanner.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/utility/ArgumentList.d' -o 'objdir/utility/ArgumentList.o' 'utility/ArgumentList.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/utility/File.d' -o 'objdir/utility/File.o' 'utility/File.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/optimize2bw.d' -o 'objdir/frontends/optimize2bw.o' 'frontends/optimize2bw.cc'
codecs/dcraw.h: In function 'int dcraw::parse_tiff_ifd(int)':
codecs/dcraw.h:5854:26: warning: iteration 6 invokes undefined behavior [-Waggressive-loop-optimizations]
    FORC(36) xtrans[0][c] = fgetc(ifp) & 3;
             ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
codecs/dcraw.h:178:31: note: within this loop
 #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=a+b; b=a-b; a=a-b; }
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /*
 ~~                             
    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 RAW(row,col) \
 ~~~~~~~~~~~~~~~~~~~~~~         
  raw_image[(row)*raw_width+(col)]
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 #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)][fcol(row,col)]
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 int CLASS fcol (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 filter[(row+top_margin)&15][(col+left_margin)&15];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (filters == 9) return xtrans[(row+6) % 6][(col+6) % 6];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   return FC(row,col);
   ~~~~~~~~~~~~~~~~~~~          
 }
 ~                              
 
                                
 #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
 ~~~~~~~~~~~~~~~~~~~~~~~~       
 char *my_strcasestr (char *haystack, const char *needle)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   char *c;
   ~~~~~~~~                     
   for (c = haystack; *c; c++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     if (!strncasecmp(c, needle, strlen(needle)))
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       return c;
       ~~~~~~~~~                
   return 0;
   ~~~~~~~~~                    
 }
 ~                              
 #define strcasestr my_strcasestr
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #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++;
   ~~~~~~~~~~~~~                
 }
 ~                              
 
                                
 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 cubic_spline (const int *x_, const int *y_, const int len)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   float **A, *b, *c, *d, *x, *y;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int i, j;
   ~~~~~~~~~                    
 
                                
   A = (float **) calloc (((2*len + 4)*sizeof **A + sizeof *A), 2*len);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (!A) return;
   ~~~~~~~~~~~~~~~              
   A[0] = (float *) (A + 2*len);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (i = 1; i < 2*len; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     A[i] = A[0] + 2*len*i;
     ~~~~~~~~~~~~~~~~~~~~~~     
   y = len + (x = i + (d = i + (c = i + (b = A[0] + i*i))));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (i = 0; i < len; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     x[i] = x_[i] / 65535.0;
     ~~~~~~~~~~~~~~~~~~~~~~~    
     y[i] = y_[i] / 65535.0;
     ~~~~~~~~~~~~~~~~~~~~~~~    
   }
   ~                            
   for (i = len-1; i > 0; i--) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     b[i] = (y[i] - y[i-1]) / (x[i] - x[i-1]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     d[i-1] = x[i] - x[i-1];
     ~~~~~~~~~~~~~~~~~~~~~~~    
   }
   ~                            
   for (i = 1; i < len-1; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     A[i][i] = 2 * (d[i-1] + d[i]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (i > 1) {
     ~~~~~~~~~~~~               
       A[i][i-1] = d[i-1];
       ~~~~~~~~~~~~~~~~~~~      
       A[i-1][i] = d[i-1];
       ~~~~~~~~~~~~~~~~~~~      
     }
     ~                          
     A[i][len-1] = 6 * (b[i+1] - b[i]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for(i = 1; i < len-2; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     float v = A[i+1][i] / A[i][i];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for(j = 1; j <= len-1; j++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       A[i+1][j] -= v * A[i][j];
       ~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for(i = len-2; i > 0; i--) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     float acc = 0;
     ~~~~~~~~~~~~~~             
     for(j = i; j <= len-2; j++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       acc += A[i][j]*c[j];
       ~~~~~~~~~~~~~~~~~~~~     
     c[i] = (A[i][len-1] - acc) / A[i][i];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for (i = 0; i < 0x10000; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     float x_out = (float)(i / 65535.0);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     float y_out = 0;
     ~~~~~~~~~~~~~~~~           
     for (j = 0; j < len-1; j++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (x[j] <= x_out && x_out <= x[j+1]) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  float v = x_out - x[j];
  ~~~~~~~~~~~~~~~~~~~~~~~       
  y_out = y[j] +
  ~~~~~~~~~~~~~~                
    ((y[j+1] - y[j]) / d[j] - (2 * d[j] * c[j] + c[j+1] * d[j])/6) * v
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + (c[j] * 0.5) * v*v + ((c[j+1] - c[j]) / (6 * d[j])) * v*v*v;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
     curve[i] = y_out < 0.0 ? 0 : (y_out >= 1.0 ? 65535 :
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   (ushort)(y_out * 65535.0 + 0.5));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   free (A);
   ~~~~~~~~~                    
 }
 ~                              
 
                                
 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 *pix;
   ~~~~~~~~~~~~                 
   int irow, row;
   ~~~~~~~~~~~~~~               
 
                                
   for (irow=row=0; irow < height; irow++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (data, 1, 1120, ifp) < 1120) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     pix = raw_image + row*raw_width;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (dp=data; 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    );
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     if ((row+=2) > height) row = 1;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS canon_600_correct()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   int row, col, val;
   ~~~~~~~~~~~~~~~~~~           
   static const short mul[4][2] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   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;
   ~~~~~~~~~~                   
 }
 ~                              
 
                                
 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;
   ~~~~~~~~~                    
 }
 ~                              
 
                                
 unsigned CLASS getbithuff (int nbits, ushort *huff)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   static unsigned bitbuf=0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   static int vbits=0, reset=0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   unsigned c;
   ~~~~~~~~~~~                  
 
                                
   if (nbits > 25) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   if (nbits < 0)
   ~~~~~~~~~~~~~~               
     return bitbuf = vbits = reset = 0;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (nbits == 0 || vbits < 0) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   while (!reset && vbits < nbits && (c = fgetc(ifp)) != EOF &&
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     !(reset = zero_after_ff && c == 0xff && fgetc(ifp))) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     bitbuf = (bitbuf << 8) + (uchar) c;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     vbits += 8;
     ~~~~~~~~~~~                
   }
   ~                            
   c = bitbuf << (32-vbits) >> (32-nbits);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (huff) {
   ~~~~~~~~~~~                  
     vbits -= huff[c] >> 8;
     ~~~~~~~~~~~~~~~~~~~~~~     
     c = (uchar) huff[c];
     ~~~~~~~~~~~~~~~~~~~~       
   } else
   ~~~~~~                       
     vbits -= nbits;
     ~~~~~~~~~~~~~~~            
   if (vbits < 0) derror();
   ~~~~~~~~~~~~~~~~~~~~~~~~     
   return c;
   ~~~~~~~~~                    
 }
 ~                              
 
                                
 #define getbits(n) getbithuff(n,0)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #define gethuff(h) getbithuff(*h,h+1)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /*
 ~~                             
    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
  ~~~~~~~~~~~~~                 
  */
  ~~                            
 ushort * CLASS make_decoder_ref (const uchar **source)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int max, len, h, i, j;
   ~~~~~~~~~~~~~~~~~~~~~~       
   const uchar *count;
   ~~~~~~~~~~~~~~~~~~~          
   ushort *huff;
   ~~~~~~~~~~~~~                
 
                                
   count = (*source += 16) - 17;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (max=16; max && !count[max]; max--);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff = (ushort *) calloc (1 + (1 << max), sizeof *huff);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (huff, "make_decoder()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff[0] = max;
   ~~~~~~~~~~~~~~               
   for (h=len=1; len <= max; len++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (i=0; i < count[len]; i++, ++*source)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (j=0; j < 1 << (max-len); j++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (h <= 1 << max)
  ~~~~~~~~~~~~~~~~~~            
    huff[h++] = len << 8 | **source;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   return huff;
   ~~~~~~~~~~~~                 
 }
 ~                              
 
                                
 ushort * CLASS make_decoder (const uchar *source)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   return make_decoder_ref (&source);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS crw_init_tables (unsigned table, ushort *huff[2])
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   huff[0] = make_decoder ( first_tree[table]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff[1] = make_decoder (second_tree[table]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 /*
 ~~                             
    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_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~    
 {
 ~                              
   ushort *pixel, *prow, *huff[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int nblocks, lowbits, i, c, row, r, save, val;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   crw_init_tables (tiff_compress, huff);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     pixel = raw_image + row*raw_width;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     nblocks = MIN (8, raw_height-row) * raw_width >> 6;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (block=0; block < nblocks; block++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       memset (diffbuf, 0, sizeof diffbuf);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i=0; i < 64; i++ ) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  leaf = gethuff(huff[i > 0]);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  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);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   FORC(2) free (huff[c]);
   ~~~~~~~~~~~~~~~~~~~~~~~      
 }
 ~                              
 
                                
 /*
 ~~                             
    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];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort *huff[6], *free[4], *row;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 };
 ~~                             
 
                                
 int CLASS ljpeg_start (struct jhead *jh, int info_only)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c, tag;
   ~~~~~~~~~~~                  
   ushort len;
   ~~~~~~~~~~~                  
   uchar data[0x10000];
   ~~~~~~~~~~~~~~~~~~~~         
   const uchar *dp;
   ~~~~~~~~~~~~~~~~             
 
                                
   memset (jh, 0, sizeof *jh);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   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 && (c = *dp++) < 4; )
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    jh->free[c] = jh->huff[c] = make_decoder_ref (&dp);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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->clrs > 6 || !jh->huff[0]) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC(5) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
 }
 ~                              
 
                                
 void CLASS ljpeg_end (struct jhead *jh)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c;
   ~~~~~~                       
   FORC4 if (jh->free[c]) free (jh->free[c]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   free (jh->row);
   ~~~~~~~~~~~~~~~              
 }
 ~                              
 
                                
 int CLASS ljpeg_diff (ushort *huff)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int len, diff;
   ~~~~~~~~~~~~~~               
 
                                
   if(!huff)
   ~~~~~~~~~                    
     longjmp (failure, 2);
     ~~~~~~~~~~~~~~~~~~~~~      
 
                                
   len = gethuff(huff);
   ~~~~~~~~~~~~~~~~~~~~         
   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) {
     ~~~~~~~~~~~                
       fseek (ifp, -2, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   struct jhead jh;
   ~~~~~~~~~~~~~~~~             
   ushort *rp;
   ~~~~~~~~~~~                  
 
                                
   if (!ljpeg_start (&jh, 0)) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jwide = jh.wide * jh.clrs;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
 
                                
   if(jh.wide<1 || jh.high<1 || jh.clrs<1 || jh.bits <1)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     longjmp (failure, 2);
     ~~~~~~~~~~~~~~~~~~~~~      
 
                                
   for (jrow=0; jrow < jh.high; jrow++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     rp = ljpeg_row (jrow, &jh);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (load_flags & 1)
     ~~~~~~~~~~~~~~~~~~~        
       row = jrow & 1 ? height-1-jrow/2 : jrow/2;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (jcol=0; jcol < jwide; jcol++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       val = curve[*rp++];
       ~~~~~~~~~~~~~~~~~~~      
       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(row>raw_height)
       ~~~~~~~~~~~~~~~~~~       
  longjmp (failure, 3);
  ~~~~~~~~~~~~~~~~~~~~~         
       if ((unsigned) row < raw_height) RAW(row,col) = val;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (++col >= raw_width)
       ~~~~~~~~~~~~~~~~~~~~~~~  
  col = (row++,0);
  ~~~~~~~~~~~~~~~~              
     }
     ~                          
   }
   ~                            
   ljpeg_end (&jh);
   ~~~~~~~~~~~~~~~~             
 }
 ~                              
 
                                
 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) || jh.clrs < 4) 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 >= 0x80000281 || (unique_id == 0x80000218 && ver > 1000006))
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     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 == 0x80000218 ||
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  unique_id == 0x80000250 ||
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  unique_id == 0x80000261 ||
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  unique_id == 0x80000281 ||
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  unique_id == 0x80000287) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
       rp[1] = (rp[1] << 2) + hue;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       rp[2] = (rp[2] << 2) + hue;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pix[0] = rp[0] + ((   50*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);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else {
     ~~~~~~~~                   
       if (unique_id < 0x80000218) rp[0] -= 512;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pix[0] = rp[0] + rp[2];
       ~~~~~~~~~~~~~~~~~~~~~~~  
       pix[2] = rp[0] + rp[1];
       ~~~~~~~~~~~~~~~~~~~~~~~  
       pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   ljpeg_end (&jh);
   ~~~~~~~~~~~~~~~~             
   maximum = 0x3fff;
   ~~~~~~~~~~~~~~~~~            
 }
 ~                              
 
                                
 void CLASS adobe_copy_pixel (unsigned row, unsigned col, ushort **rp)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c;
   ~~~~~~                       
 
                                
   if (is_raw == 2 && shot_select) (*rp)++;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (raw_image) {
   ~~~~~~~~~~~~~~~~             
     if (row < raw_height && col < raw_width)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[**rp];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     *rp += is_raw;
     ~~~~~~~~~~~~~~             
   } else {
   ~~~~~~~~                     
     if (row < height && col < width)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC(tiff_samples)
       ~~~~~~~~~~~~~~~~~~       
  image[row*width+col][c] = curve[(*rp)[c]];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     *rp += tiff_samples;
     ~~~~~~~~~~~~~~~~~~~~       
   }
   ~                            
   if (is_raw == 2 && shot_select) (*rp)--;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS lossless_dng_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   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);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     ljpeg_end (&jh);
     ~~~~~~~~~~~~~~~~           
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS packed_dng_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   ushort *pixel, *rp;
   ~~~~~~~~~~~~~~~~~~~          
   int row, col;
   ~~~~~~~~~~~~~                
 
                                
   pixel = (ushort *) calloc (raw_width, tiff_samples*sizeof *pixel);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (pixel, "packed_dng_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
 {
 ~                              
   ushort bit[2][15], huff[4097];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int dep, row, col, diff, c, i;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   fseek (ifp, meta_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   dep = (get2() + 12) & 15;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   fseek (ifp, 12, SEEK_CUR);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
   FORC(dep) bit[0][c] = get2();
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC(dep) bit[1][c] = fgetc(ifp);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC(dep)
   ~~~~~~~~~                    
     for (i=bit[0][c]; i <= ((bit[0][c]+(4096 >> bit[1][c])-1) & 4095); )
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       huff[++i] = bit[1][c] << 8 | c;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff[0] = 12;
   ~~~~~~~~~~~~~                
   fseek (ifp, data_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       diff = ljpeg_diff (huff);
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else    hpred[col & 1] += diff;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = hpred[col & 1];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (hpred[col & 1] >> tiff_bps) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 void CLASS nikon_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 } };
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort *huff, ver0, ver1, vpred[2][2], hpred[2], csize;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int i, min, max, step=0, tree=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) tree = 2;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   if (tiff_bps == 14) tree += 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--;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   huff = make_decoder (nikon_tree[tree]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fseek (ifp, data_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (min=row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (split && row == split) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       free (huff);
       ~~~~~~~~~~~~             
       huff = make_decoder (nikon_tree[tree+1]);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       max += (min = 16) << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~  
     }
     ~                          
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       i = gethuff(huff);
       ~~~~~~~~~~~~~~~~~~       
       len = i & 15;
       ~~~~~~~~~~~~~            
       shl = i >> 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();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[LIM((short)hpred[col & 1],0,0x3fff)];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   free (huff);
   ~~~~~~~~~~~~                 
 }
 ~                              
 
                                
 void CLASS nikon_yuv_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int row, col, yuv[4], rgb[3], b, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   UINT64 bitbuf=0;
   ~~~~~~~~~~~~~~~~             
 
                                
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (!(b = col & 1)) {
       ~~~~~~~~~~~~~~~~~~~~~    
  bitbuf = 0;
  ~~~~~~~~~~~                   
  FORC(6) bitbuf |= (UINT64) fgetc(ifp) << c*8;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC(4) yuv[c] = (bitbuf >> c*12 & 0xfff) - (c >> 1 << 11);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
       rgb[0] = yuv[b] + 1.370705*yuv[3];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       rgb[1] = yuv[b] - 0.337633*yuv[2] - 0.698001*yuv[3];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       rgb[2] = yuv[b] + 1.732446*yuv[2];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,0xfff)] / cam_mul[c];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 /*
 ~~                             
    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;
   ~~~~~~~~~~~~~~~              
 }
 ~                              
 
                                
 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 ppm16_thumb()
 ~~~~~~~~~~~~~~~~~~~~~~~~       
 {
 ~                              
   int i;
   ~~~~~~                       
   char *thumb;
   ~~~~~~~~~~~~                 
   thumb_length = thumb_width*thumb_height*3;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   thumb = (char *) calloc (thumb_length, 2);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (thumb, "ppm16_thumb()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   read_shorts ((ushort *) thumb, thumb_length);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (i=0; i < thumb_length; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     thumb[i] = ((ushort *) thumb)[i] >> 8;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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, 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)
     ~~~~~~~~~~~~~~~~~~~~~~~    
       raw_image[todo[i]] = (todo[i+1] & 0x3ff);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   maximum = 0x3ff;
   ~~~~~~~~~~~~~~~~             
 }
 ~                              
 
                                
 int CLASS raw (unsigned row, unsigned col)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   return (row < raw_height && col < raw_width) ? RAW(row,col) : 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS phase_one_flat_field (int is_float, int nc)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   ushort head[8];
   ~~~~~~~~~~~~~~~              
   unsigned wide, high, y, x, c, rend, cend, row, col;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   float *mrow, num, mult[4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
 
                                
   read_shorts (head, 8);
   ~~~~~~~~~~~~~~~~~~~~~~       
   if (head[2] * head[3] * head[4] * head[5] == 0) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   wide = head[2] / head[4] + (head[2] % head[4] != 0);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   high = head[3] / head[5] + (head[3] % head[5] != 0);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   mrow = (float *) calloc (nc*wide, sizeof *mrow);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (mrow, "phase_one_flat_field()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (y=0; y < high; 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] + y*head[5];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (row = rend-head[5];
     ~~~~~~~~~~~~~~~~~~~~~~~~   
   row < raw_height && row < rend &&
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   row < head[1]+head[3]-head[5]; 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] + x*head[4];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  for (col = cend-head[4];
  ~~~~~~~~~~~~~~~~~~~~~~~~      
       col < raw_width &&
       ~~~~~~~~~~~~~~~~~~       
       col < cend && col < head[0]+head[2]-head[4]; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    c = nc > 2 ? FC(row-top_margin,col-left_margin) : 0;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (!(c & 1)) {
    ~~~~~~~~~~~~~~~             
      c = RAW(row,col) * mult[c];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~
      RAW(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];
   ~~~~~~~~~~~~~~~~             
   int qmult_applied = 0, qlin_applied = 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   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 < raw_height; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col = (tag & 1)*ph1.split_col; col < raw_width; col++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    RAW(row,col) = curve[RAW(row,col)];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else if (tag == 0x400) {   /* Sensor defects */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       while ((len -= 8) >= 0) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  col  = get2();
  ~~~~~~~~~~~~~~                
  row  = get2();
  ~~~~~~~~~~~~~~                
  type = get2(); get2();
  ~~~~~~~~~~~~~~~~~~~~~~        
  if (col >= raw_width) continue;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (type == 131 || type == 137)  /* Bad column */
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (row=0; row < raw_height; row++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (FC(row-top_margin,col-left_margin) == 1) {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        for (sum=i=0; i < 4; i++)
        ~~~~~~~~~~~~~~~~~~~~~~~~~
   sum += val[i] = raw (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;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        }
        ~                       
        RAW(row,col) = (sum - val[max])/3.0 + 0.5;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      } else {
      ~~~~~~~~                  
        for (sum=0, i=8; i < 12; i++)
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   sum += raw (row+dir[i][0], col+dir[i][1]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        RAW(row,col) = 0.5 + sum * 0.0732233 +
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   (raw(row,col-2) + raw(row,col+2)) * 0.3535534;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      }
      ~                         
  else if (type == 129) {   /* Bad pixel */
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (row >= raw_height) continue;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    j = (FC(row-top_margin,col-left_margin) != 1) * 4;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (sum=0, i=j; i < j+8; i++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      sum += raw (row+dir[i][0], col+dir[i][1]);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    RAW(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;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
       }
       ~                        
     } else if (tag == 0x41f && !qlin_applied) { /* Quadrant linearization */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       ushort lc[2][2][16], ref[16];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       int qr, qc;
       ~~~~~~~~~~~              
       for (qr = 0; qr < 2; qr++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (qc = 0; qc < 2; qc++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
    for (i = 0; i < 16; i++)
    ~~~~~~~~~~~~~~~~~~~~~~~~    
      lc[qr][qc][i] = (ushort)get4();
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i = 0; i < 16; i++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  int v = 0;
  ~~~~~~~~~~                    
  for (qr = 0; qr < 2; qr++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
    for (qc = 0; qc < 2; qc++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
      v += lc[qr][qc][i];
      ~~~~~~~~~~~~~~~~~~~       
  ref[i] = (v + 2) >> 2;
  ~~~~~~~~~~~~~~~~~~~~~~        
       }
       ~                        
       for (qr = 0; qr < 2; qr++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (qc = 0; qc < 2; qc++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    int cx[18], cf[18];
    ~~~~~~~~~~~~~~~~~~~         
    for (i = 0; i < 16; i++) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
      cx[1+i] = lc[qr][qc][i];
      ~~~~~~~~~~~~~~~~~~~~~~~~  
      cf[1+i] = ref[i];
      ~~~~~~~~~~~~~~~~~         
    }
    ~                           
    cx[0] = cf[0] = 0;
    ~~~~~~~~~~~~~~~~~~          
    cx[17] = cf[17] = ((unsigned int)ref[15] * 65535) / lc[qr][qc][15];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    cubic_spline(cx, cf, 18);
    ~~~~~~~~~~~~~~~~~~~~~~~~~   
 
                                
    for (row = (qr ? ph1.split_row : 0);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         row < (qr ? raw_height : ph1.split_row); row++)
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (col = (qc ? ph1.split_col : 0);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    col < (qc ? raw_width : ph1.split_col); col++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        RAW(row,col) = curve[RAW(row,col)];
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       }
       ~                        
       qlin_applied = 1;
       ~~~~~~~~~~~~~~~~~        
     } else if (tag == 0x41e && !qmult_applied) { /* Quadrant multipliers */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       float qmult[2][2] = { { 1, 1 }, { 1, 1 } };
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       get4(); get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       qmult[0][0] = 1.0 + getreal(11);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       get4(); get4(); get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       qmult[0][1] = 1.0 + getreal(11);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~  
       qmult[1][0] = 1.0 + getreal(11);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~  
       qmult[1][1] = 1.0 + getreal(11);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (row=0; row < raw_height; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col=0; col < raw_width; col++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    i = qmult[row >= ph1.split_row][col >= ph1.split_col] * RAW(row,col);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    RAW(row,col) = LIM(i,0,65535);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       qmult_applied = 1;
       ~~~~~~~~~~~~~~~~~~       
     } else if (tag == 0x431 && !qmult_applied) { /* Quadrant combined */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       ushort lc[2][2][7], ref[7];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       int qr, qc;
       ~~~~~~~~~~~              
       for (i = 0; i < 7; i++)
       ~~~~~~~~~~~~~~~~~~~~~~~  
  ref[i] = (ushort)get4();
  ~~~~~~~~~~~~~~~~~~~~~~~~      
       for (qr = 0; qr < 2; qr++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (qc = 0; qc < 2; qc++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
    for (i = 0; i < 7; i++)
    ~~~~~~~~~~~~~~~~~~~~~~~     
      lc[qr][qc][i] = (ushort)get4();
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (qr = 0; qr < 2; qr++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (qc = 0; qc < 2; qc++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    int cx[9], cf[9];
    ~~~~~~~~~~~~~~~~~           
    for (i = 0; i < 7; i++) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~   
      cx[1+i] = ref[i];
      ~~~~~~~~~~~~~~~~~         
      cf[1+i] = ((unsigned int)ref[i] * lc[qr][qc][i]) / 10000;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    }
    ~                           
    cx[0] = cf[0] = 0;
    ~~~~~~~~~~~~~~~~~~          
    cx[8] = cf[8] = 65535;
    ~~~~~~~~~~~~~~~~~~~~~~      
    cubic_spline(cx, cf, 9);
    ~~~~~~~~~~~~~~~~~~~~~~~~    
    for (row = (qr ? ph1.split_row : 0);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         row < (qr ? raw_height : ph1.split_row); row++)
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (col = (qc ? ph1.split_col : 0);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    col < (qc ? raw_width : ph1.split_col); col++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        RAW(row,col) = curve[RAW(row,col)];
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         }
         ~                      
       }
       ~                        
       qmult_applied = 1;
       ~~~~~~~~~~~~~~~~~~       
       qlin_applied = 1;
       ~~~~~~~~~~~~~~~~~        
     }
     ~                          
     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 < raw_height; row++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < raw_width; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cfrac = (float) col * head[3] / raw_width;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cfrac -= cip = cfrac;
  ~~~~~~~~~~~~~~~~~~~~~         
  num = RAW(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 + num) * 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = LIM(i,0,65535);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     free (yval[0]);
     ~~~~~~~~~~~~~~~            
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS phase_one_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int a, b, i;
   ~~~~~~~~~~~~                 
   ushort akey, bkey, mask;
   ~~~~~~~~~~~~~~~~~~~~~~~~     
 
                                
   fseek (ifp, ph1.key_off, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   akey = get2();
   ~~~~~~~~~~~~~~               
   bkey = get2();
   ~~~~~~~~~~~~~~               
   mask = ph1.format == 1 ? 0x5555:0x1354;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fseek (ifp, data_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   read_shorts (raw_image, raw_width*raw_height);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (ph1.format)
   ~~~~~~~~~~~~~~~              
     for (i=0; i < raw_width*raw_height; i+=2) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       a = raw_image[i+0] ^ akey;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       b = raw_image[i+1] ^ bkey;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       raw_image[i+0] = (a & mask) | (b & ~mask);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       raw_image[i+1] = (b & mask) | (a & ~mask);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 unsigned CLASS ph1_bithuff (int nbits, ushort *huff)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   static UINT64 bitbuf=0;
   ~~~~~~~~~~~~~~~~~~~~~~~      
   static int vbits=0;
   ~~~~~~~~~~~~~~~~~~~          
   unsigned c;
   ~~~~~~~~~~~                  
 
                                
   if (nbits == -1)
   ~~~~~~~~~~~~~~~~             
     return bitbuf = vbits = 0;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   if (nbits == 0) return 0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   if (vbits < nbits) {
   ~~~~~~~~~~~~~~~~~~~~         
     bitbuf = bitbuf << 32 | get4();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     vbits += 32;
     ~~~~~~~~~~~~               
   }
   ~                            
   c = bitbuf << (64-vbits) >> (64-nbits);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (huff) {
   ~~~~~~~~~~~                  
     vbits -= huff[c] >> 8;
     ~~~~~~~~~~~~~~~~~~~~~~     
     return (uchar) huff[c];
     ~~~~~~~~~~~~~~~~~~~~~~~    
   }
   ~                            
   vbits -= nbits;
   ~~~~~~~~~~~~~~~              
   return c;
   ~~~~~~~~~                    
 }
 ~                              
 #define ph1_bits(n) ph1_bithuff(n,0)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #define ph1_huff(h) ph1_bithuff(*h,h+1)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 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 (*cblack)[2], (*rblack)[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   pixel = (ushort *) calloc (raw_width*3 + 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();
     ~~~~~~~~~~~~~~~~~~~~~      
   cblack = (short (*)[2]) (offset + raw_height);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fseek (ifp, ph1.black_col, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (ph1.black_col)
   ~~~~~~~~~~~~~~~~~~           
     read_shorts ((ushort *) cblack[0], raw_height*2);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   rblack = cblack + raw_height;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fseek (ifp, ph1.black_row, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (ph1.black_row)
   ~~~~~~~~~~~~~~~~~~           
     read_shorts ((ushort *) rblack[0], raw_width*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]];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       i = (pixel[col] << 2) - ph1.black
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  + cblack[row][col >= ph1.split_col]
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  + rblack[col][row >= ph1.split_row];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (i > 0) RAW(row,col) = i;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   free (pixel);
   ~~~~~~~~~~~~~                
   maximum = 0xfffc - ph1.black;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS hasselblad_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   struct jhead jh;
   ~~~~~~~~~~~~~~~~             
   int shot, row, col, *back[5], len[2], diff[12], pred, sh, f, s, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   unsigned upix, urow, ucol;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
   ushort *ip;
   ~~~~~~~~~~~                  
 
                                
   if (!ljpeg_start (&jh, 0)) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   order = 0x4949;
   ~~~~~~~~~~~~~~~              
   ph1_bits(-1);
   ~~~~~~~~~~~~~                
   back[4] = (int *) calloc (raw_width, 3*sizeof **back);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (back[4], "hasselblad_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC3 back[c] = back[4] + c*raw_width;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cblack[6] >>= sh = tiff_samples > 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   shot = LIM(shot_select, 1, tiff_samples) - 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC4 back[(c+3) & 3] = back[c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col+=2) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (s=0; s < tiff_samples*2; s+=2) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC(2) len[c] = ph1_huff(jh.huff[0]);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC(2) {
  ~~~~~~~~~                     
    diff[s+c] = ph1_bits(len[c]);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if ((diff[s+c] & (1 << (len[c]-1))) == 0)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      diff[s+c] -= (1 << len[c]) - 1;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (diff[s+c] == 65535) diff[s+c] = -32768;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       }
       ~                        
       for (s=col; s < col+2; s++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pred = 0x8000 + load_flags;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  if (col) pred = back[2][s-2];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  if (col && row > 1) switch (jh.psv) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    case 11: pred += back[0][s]/2 - back[0][s-2]/2;  break;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
  f = (row & 1)*3 ^ ((col+s) & 1);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC (tiff_samples) {
  ~~~~~~~~~~~~~~~~~~~~~         
    pred += diff[(s & 1)*tiff_samples+c];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    upix = pred >> sh & 0xffff;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    if (raw_image && c == shot)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
      RAW(row,s) = upix;
      ~~~~~~~~~~~~~~~~~~        
    if (image) {
    ~~~~~~~~~~~~                
      urow = row-top_margin  + (c & 1);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      ucol = col-left_margin - ((c >> 1) & 1);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      ip = &image[urow*width+ucol][f];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (urow < height && ucol < width)
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        *ip = c < 4 ? upix : (*ip + upix) >> 1;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    }
    ~                           
  }
  ~                             
  back[2][s] = pred;
  ~~~~~~~~~~~~~~~~~~            
       }
       ~                        
     }
     ~                          
   }
   ~                            
   free (back[4]);
   ~~~~~~~~~~~~~~~              
   ljpeg_end (&jh);
   ~~~~~~~~~~~~~~~~             
   if (image) mix_green = 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
 }
 ~                              
 
                                
 void CLASS leaf_hdr_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   ushort *pixel=0;
   ~~~~~~~~~~~~~~~~             
   unsigned tile=0, r, c, row, col;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (!filters) {
   ~~~~~~~~~~~~~~~              
     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(), SEEK_SET);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
       if (filters && c != shot_select) continue;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (filters) pixel = raw_image + r*raw_width;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       read_shorts (pixel, raw_width);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (!filters && (row = r - top_margin) < height)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col=0; col < width; col++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    image[row*width+col][c] = pixel[col+left_margin];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   if (!filters) {
   ~~~~~~~~~~~~~~~              
     maximum = 0xffff;
     ~~~~~~~~~~~~~~~~~          
     raw_color = 1;
     ~~~~~~~~~~~~~~             
     free (pixel);
     ~~~~~~~~~~~~~              
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS unpacked_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   int row, col, bits=0;
   ~~~~~~~~~~~~~~~~~~~~~        
 
                                
   while (1 << ++bits < maximum);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   read_shorts (raw_image, raw_width*raw_height);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((RAW(row,col) >>= load_flags) >> bits
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  && (unsigned) (row-top_margin) < height
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  && (unsigned) (col-left_margin) < width) derror();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS sinar_4shot_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   ushort *pixel;
   ~~~~~~~~~~~~~~               
   unsigned shot, row, col, r, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (raw_image) {
   ~~~~~~~~~~~~~~~~             
     shot = LIM (shot_select, 1, 4) - 1;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, data_offset + shot*4, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, get4(), SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     unpacked_load_raw();
     ~~~~~~~~~~~~~~~~~~~~       
     return;
     ~~~~~~~                    
   }
   ~                            
   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][(row & 1)*3 ^ (~col & 1)] = pixel[col];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
   }
   ~                            
   free (pixel);
   ~~~~~~~~~~~~~                
   mix_green = 1;
   ~~~~~~~~~~~~~~               
 }
 ~                              
 
                                
 void CLASS imacon_full_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int row, col;
   ~~~~~~~~~~~~~                
 
                                
   if (!image) return;
   ~~~~~~~~~~~~~~~~~~~          
   for (row=0; row < height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       read_shorts (image[row*width+col], 3);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS packed_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
 {
 ~                              
   int vbits=0, bwide, rbits, bite, half, irow, row, col, val, i;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   UINT64 bitbuf=0;
   ~~~~~~~~~~~~~~~~             
 
                                
   bwide = raw_width * tiff_bps / 8;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   bwide += bwide & load_flags >> 7;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   rbits = bwide * 8 - raw_width * tiff_bps;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (load_flags & 1) bwide = bwide * 16 / 15;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   bite = 8 + (load_flags & 24);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   half = (raw_height+1) >> 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   for (irow=0; irow < raw_height; irow++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     row = irow;
     ~~~~~~~~~~~                
     if (load_flags & 2 &&
     ~~~~~~~~~~~~~~~~~~~~~      
  (row = irow % half * 2 + irow / half) == 1 &&
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  load_flags & 4) {
  ~~~~~~~~~~~~~~~~~             
       if (vbits=0, tiff_compress)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  fseek (ifp, data_offset - (-half*bwide & -2048), SEEK_SET);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else {
       ~~~~~~                   
  fseek (ifp, 0, SEEK_END);
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  fseek (ifp, ftell(ifp) >> 3 << 2, SEEK_SET);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (vbits -= tiff_bps; vbits < 0; vbits += bite) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  bitbuf <<= bite;
  ~~~~~~~~~~~~~~~~              
  for (i=0; i < bite; i+=8)
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
    bitbuf |= (unsigned) (fgetc(ifp) << i);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
       val = bitbuf << (64-tiff_bps-vbits) >> (64-tiff_bps);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col ^ (load_flags >> 6 & 1)) = val;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (load_flags & 1 && (col % 10) == 9 && fgetc(ifp) &&
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  row < height+top_margin && col < width+left_margin) derror();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     vbits -= rbits;
     ~~~~~~~~~~~~~~~            
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS nokia_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~    
 {
 ~                              
   uchar  *data,  *dp;
   ~~~~~~~~~~~~~~~~~~~          
   int rev, dwide, row, col, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   double sum[]={0,0};
   ~~~~~~~~~~~~~~~~~~~          
 
                                
   rev = 3 * (order == 0x4949);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   dwide = (raw_width * 5 + 1) / 4;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   data = (uchar *) malloc (dwide*2);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (data, "nokia_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (data+dwide, 1, dwide, ifp) < dwide) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC(dwide) data[c] = data[dwide+(c ^ rev)];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (dp=data, col=0; col < raw_width; dp+=5, col+=4)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 RAW(row,col+c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   free (data);
   ~~~~~~~~~~~~                 
   maximum = 0x3ff;
   ~~~~~~~~~~~~~~~~             
   if (strcmp(make,"OmniVision")) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   row = raw_height/2;
   ~~~~~~~~~~~~~~~~~~~          
   FORC(width-1) {
   ~~~~~~~~~~~~~~~              
     sum[ c & 1] += SQR(RAW(row,c)-RAW(row+1,c+1));
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     sum[~c & 1] += SQR(RAW(row+1,c)-RAW(row,c+1));
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   if (sum[1] > sum[0]) filters = 0x4b4b4b4b;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS canon_rmf_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int row, col, bits, orow, ocol, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width-2; col+=3) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       bits = get4();
       ~~~~~~~~~~~~~~           
       FORC3 {
       ~~~~~~~                  
  orow = row;
  ~~~~~~~~~~~                   
  if ((ocol = col+c-4) < 0) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
    ocol += raw_width;
    ~~~~~~~~~~~~~~~~~~          
    if ((orow -= 2) < 0)
    ~~~~~~~~~~~~~~~~~~~~        
      orow += raw_height;
      ~~~~~~~~~~~~~~~~~~~       
  }
  ~                             
  RAW(orow,ocol) = curve[bits >> (10*c+2) & 0x3ff];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
   maximum = curve[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 ((RAW(row,col) = pred[col & 1]) > 4098 && col < width) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 void CLASS olympus_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
 {
 ~                              
   ushort huff[4096];
   ~~~~~~~~~~~~~~~~~~           
   int row, col, nbits, sign, low, high, i, c, w, n, nw;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int acarry[2][3], *carry, pred, diff;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   huff[n=0] = 0xc0c;
   ~~~~~~~~~~~~~~~~~~           
   for (i=12; i--; )
   ~~~~~~~~~~~~~~~~~            
     FORC(2048 >> i) huff[++n] = (i+1) << 8 | i;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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++);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       low = (sign = getbits(3)) & 3;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       sign = sign << 29 >> 31;
       ~~~~~~~~~~~~~~~~~~~~~~~~ 
       if ((high = getbithuff(12,huff)) == 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 = RAW(row,col-2);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else if (col < 2) pred = RAW(row-2,col);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else {
       ~~~~~~                   
  w  = RAW(row,col-2);
  ~~~~~~~~~~~~~~~~~~~~          
  n  = RAW(row-2,col);
  ~~~~~~~~~~~~~~~~~~~~          
  nw = RAW(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 ((RAW(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) RAW(row,col) = (col+1) & 2 ?
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,1)    = pixel[1]   << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,1533) = pixel[765] << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     } else
     ~~~~~~                     
       for (col=row & 1; col < 1534; col+=2)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = pixel[col/2] << 1;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   maximum = 0xff << 1;
   ~~~~~~~~~~~~~~~~~~~~         
 }
 ~                              
 
                                
 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++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[pixel[row+2][col+2]];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   maximum = 0x3ff;
   ~~~~~~~~~~~~~~~~             
 }
 ~                              
 
                                
 #define radc_token(tree) ((signed char) getbithuff(8,huff[tree]))
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 #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)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 #define ARRAY_SIZE(_array) (sizeof(_array) / sizeof((_array)[0]))
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 void CLASS kodak_radc_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   static const char src[] = {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     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
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   };
   ~~                           
   ushort huff[19][256];
   ~~~~~~~~~~~~~~~~~~~~~        
   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;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (s=i=0; i < sizeof src; i+=2)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC(256 >> src[i])
     ~~~~~~~~~~~~~~~~~~~        
       huff[0][s++] = src[i] << 8 | (uchar) src[i+1];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   s = kodak_cbpp == 243 ? 2 : 3;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC(256) huff[18][c] = (8-s) << 8 | c >> s << s | 1 << (s-1);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (c=0; c < ARRAY_SIZE(buf); c++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (y=0; y < ARRAY_SIZE(buf[0]); y++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (x=0; y < ARRAY_SIZE(buf[0][0]); x++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         buf[c][y][x] = 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] = (uchar) radc_token(18) * 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) RAW(row+y*2+c-1,x*2+2-c) = val;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      else   RAW(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 = (RAW(y,x)-2048)*2 + (RAW(y,r)+RAW(y,s))/2;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (val < 0) val = 0;
    ~~~~~~~~~~~~~~~~~~~~~       
    RAW(y,x) = val;
    ~~~~~~~~~~~~~~~             
  }
  ~                             
   }
   ~                            
   for (i=0; i < height*width; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     raw_image[i] = curve[raw_image[i]];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   maximum = 0x3fff;
   ~~~~~~~~~~~~~~~~~            
 }
 ~                              
 
                                
 #undef FORYX
 ~~~~~~~~~~~~                   
 #undef PREDICTOR
 ~~~~~~~~~~~~~~~~               
 
                                
 #ifdef NO_JPEG
 ~~~~~~~~~~~~~~                 
 void CLASS kodak_jpeg_load_raw() {}
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 void CLASS lossy_dng_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) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row+0,col+0) = pixel[col+0][1] << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row+1,col+1) = pixel[col+1][1] << 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
   jpeg_finish_decompress (&cinfo);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jpeg_destroy_decompress (&cinfo);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   maximum = 0xff << 1;
   ~~~~~~~~~~~~~~~~~~~~         
 }
 ~                              
 
                                
 void CLASS gamma_curve (double pwr, double ts, int mode, int imax);
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 void CLASS lossy_dng_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   struct jpeg_decompress_struct cinfo;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   struct jpeg_error_mgr jerr;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   JSAMPARRAY buf;
   ~~~~~~~~~~~~~~~              
   JSAMPLE (*pixel)[3];
   ~~~~~~~~~~~~~~~~~~~~         
   unsigned sorder=order, ntags, opcode, deg, i, j, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   unsigned save=data_offset-4, trow=0, tcol=0, row, col;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort cur[3][256];
   ~~~~~~~~~~~~~~~~~~~          
   double coeff[9], tot;
   ~~~~~~~~~~~~~~~~~~~~~        
 
                                
   if (meta_offset) {
   ~~~~~~~~~~~~~~~~~~           
     fseek (ifp, meta_offset, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     order = 0x4d4d;
     ~~~~~~~~~~~~~~~            
     ntags = get4();
     ~~~~~~~~~~~~~~~            
     while (ntags--) {
     ~~~~~~~~~~~~~~~~~          
       opcode = get4(); get4(); get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (opcode != 8)
       ~~~~~~~~~~~~~~~~         
       { fseek (ifp, get4(), SEEK_CUR); continue; }
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, 20, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((c = get4()) > 2) break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, 12, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((deg = get4()) > 8) break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i=0; i <= deg && i < 9; i++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  coeff[i] = getreal(12);
  ~~~~~~~~~~~~~~~~~~~~~~~       
       for (i=0; i < 256; i++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  for (tot=j=0; j <= deg; j++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    tot += coeff[j] * pow(i/255.0, j);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cur[c][i] = tot*0xffff;
  ~~~~~~~~~~~~~~~~~~~~~~~       
       }
       ~                        
     }
     ~                          
     order = sorder;
     ~~~~~~~~~~~~~~~            
   } else {
   ~~~~~~~~                     
     gamma_curve (1/2.4, 12.92, 1, 255);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC3 memcpy (cur[c], curve, sizeof cur[0]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   cinfo.err = jpeg_std_error (&jerr);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jpeg_create_decompress (&cinfo);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   while (trow < raw_height) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     fseek (ifp, save+=4, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tile_length < INT_MAX)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
       fseek (ifp, get4(), SEEK_SET);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     jpeg_stdio_src (&cinfo, ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     jpeg_read_header (&cinfo, TRUE);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     jpeg_start_decompress (&cinfo);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     buf = (*cinfo.mem->alloc_sarray)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width*3, 1);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     while (cinfo.output_scanline < cinfo.output_height &&
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  (row = trow + cinfo.output_scanline) < height) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       jpeg_read_scanlines (&cinfo, buf, 1);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pixel = (JSAMPLE (*)[3]) buf[0];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < cinfo.output_width && tcol+col < width; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC3 image[row*width+tcol+col][c] = cur[c][pixel[col][c]];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
     jpeg_abort_decompress (&cinfo);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if ((tcol += tile_width) >= raw_width)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       trow += tile_length + (tcol = 0);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   jpeg_destroy_decompress (&cinfo);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   maximum = 0xffff;
   ~~~~~~~~~~~~~~~~~            
 }
 ~                              
 #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++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = (ushort) pixel[(col + shift) % 848];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   maximum = 0xff;
   ~~~~~~~~~~~~~~~              
 }
 ~                              
 
                                
 void CLASS eight_bit_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   uchar *pixel;
   ~~~~~~~~~~~~~                
   unsigned row, col;
   ~~~~~~~~~~~~~~~~~~           
 
                                
   pixel = (uchar *) calloc (raw_width, sizeof *pixel);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (pixel, "eight_bit_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[pixel[col]];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   free (pixel);
   ~~~~~~~~~~~~~                
   maximum = curve[0xff];
   ~~~~~~~~~~~~~~~~~~~~~~       
 }
 ~                              
 
                                
 void CLASS kodak_c330_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   uchar *pixel;
   ~~~~~~~~~~~~~                
   int row, col, y, cb, cr, rgb[3], c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   pixel = (uchar *) calloc (raw_width, 2*sizeof *pixel);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (pixel, "kodak_c330_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (pixel, raw_width, 2, ifp) < 2) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (load_flags && (row & 31) == 31)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, raw_width*32, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       y  = pixel[col*2];
       ~~~~~~~~~~~~~~~~~~       
       cb = pixel[(col*2 & -4) | 1] - 128;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       cr = pixel[(col*2 & -4) | 3] - 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_c603_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   uchar *pixel;
   ~~~~~~~~~~~~~                
   int row, col, y, cb, cr, rgb[3], c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (pixel, "kodak_c603_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (~row & 1)
     ~~~~~~~~~~~~~              
       if (fread (pixel, raw_width, 3, ifp) < 3) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < 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 } };
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort *huff[2];
   ~~~~~~~~~~~~~~~~             
   uchar *pixel;
   ~~~~~~~~~~~~~                
   int *strip, ns, c, row, col, chess, pi=0, pi1, pi2, pred, val;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   FORC(2) huff[c] = make_decoder (kodak_tree[c]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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;
   ~~~~~~~~~~~~~~~              
   FORC(ns) strip[c] = 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 (huff[chess]);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (val >> 8) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~  
       val = curve[pixel[pi++]];
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = val;
       ~~~~~~~~~~~~~~~~~~~      
     }
     ~                          
   }
   ~                            
   free (pixel);
   ~~~~~~~~~~~~~                
   FORC(2) free (huff[c]);
   ~~~~~~~~~~~~~~~~~~~~~~~      
 }
 ~                              
 
                                
 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 ((RAW(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;
   ~~~~~~~~~~~                  
 
                                
   if (!image) return;
   ~~~~~~~~~~~~~~~~~~~          
   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-- && p++)
   ~~~~~~~~~~~~~~~~~~~~         
     *data++ ^= pad[(p-1) & 127] = pad[p & 127] ^ pad[(p+64) & 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);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     pixel = raw_image + row*raw_width;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (fread (pixel, 2, raw_width, ifp) < raw_width) derror();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((pixel[col] = ntohs(pixel[col])) >> 14) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   maximum = 0x3ff0;
   ~~~~~~~~~~~~~~~~~            
 }
 ~                              
 
                                
 void CLASS sony_arw_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   ushort huff[32770];
   ~~~~~~~~~~~~~~~~~~~          
   static const ushort tab[18] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   { 0xf11,0xf10,0xe0f,0xd0e,0xc0d,0xb0c,0xa0b,0x90a,0x809,
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     0x708,0x607,0x506,0x405,0x304,0x303,0x300,0x202,0x201 };
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int i, c, n, col, row, sum=0;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   huff[0] = 15;
   ~~~~~~~~~~~~~                
   for (n=i=0; i < 18; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~     
     FORC(32768 >> (tab[i] >> 8)) huff[++n] = tab[i];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (col = raw_width; col--; )
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (row=0; row < raw_height+1; row+=2) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (row == raw_height) row = 1;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if ((sum += ljpeg_diff(huff)) >> 12) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (row < height) RAW(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+1);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (data, "sony_arw2_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fread (data, 1, raw_width, ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (dp=data, col=0; col < raw_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)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = curve[pix[i] << 1] >> 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       col -= col & 1 ? 1:31;
       ~~~~~~~~~~~~~~~~~~~~~~   
     }
     ~                          
   }
   ~                            
   free (data);
   ~~~~~~~~~~~~                 
 }
 ~                              
 
                                
 void CLASS samsung_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
 {
 ~                              
   int row, col, c, i, dir, op[4], len[4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   order = 0x4949;
   ~~~~~~~~~~~~~~~              
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, strip_offset+row*4, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, data_offset+get4(), SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     ph1_bits(-1);
     ~~~~~~~~~~~~~              
     FORC4 len[c] = row < 2 ? 7:4;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col+=16) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       dir = ph1_bits(1);
       ~~~~~~~~~~~~~~~~~~       
       FORC4 op[c] = ph1_bits(2);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 switch (op[c]) {
       ~~~~~~~~~~~~~~~~~~~~~~   
  case 3: len[c] = ph1_bits(4); break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  case 2: len[c]--;  break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  case 1: len[c]++;
  ~~~~~~~~~~~~~~~~~             
       }
       ~                        
       for (c=0; c < 16; c+=2) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~
  i = len[((c & 1) << 1) | (c >> 3)];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         RAW(row,col+c) = ((signed) ph1_bits(i) << (32-i) >> (32-i)) +
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    (dir ? RAW(row+(~c | -2),col+c) : col ? RAW(row,col+(c | -2)) : 128);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (c == 14) c = -1;
  ~~~~~~~~~~~~~~~~~~~~          
       }
       ~                        
     }
     ~                          
   }
   ~                            
   for (row=0; row < raw_height-1; row+=2)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width-1; col+=2)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       SWAP (RAW(row,col+1), RAW(row+1,col));
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 void CLASS samsung2_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   static const ushort tab[14] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   { 0x304,0x307,0x206,0x205,0x403,0x600,0x709,
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     0x80a,0x90b,0xa0c,0xa0d,0x501,0x408,0x402 };
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort huff[1026], vpred[2][2] = {{0,0},{0,0}}, hpred[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int i, c, n, row, col, diff;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 
                                
   huff[0] = 10;
   ~~~~~~~~~~~~~                
   for (n=i=0; i < 14; i++)
   ~~~~~~~~~~~~~~~~~~~~~~~~     
     FORC(1024 >> (tab[i] >> 8)) huff[++n] = tab[i];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   getbits(-1);
   ~~~~~~~~~~~~                 
   for (row=0; row < raw_height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < raw_width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       diff = ljpeg_diff (huff);
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else    hpred[col & 1] += diff;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = hpred[col & 1];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (hpred[col & 1] >> tiff_bps) derror();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 void CLASS samsung3_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 {
 ~                              
   int opt, init, mag, pmode, row, tab, col, pred, diff, i, c;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort lent[3][2], len[4], *prow[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   order = 0x4949;
   ~~~~~~~~~~~~~~~              
   fseek (ifp, 9, SEEK_CUR);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   opt = fgetc(ifp);
   ~~~~~~~~~~~~~~~~~            
   init = (get2(),get2());
   ~~~~~~~~~~~~~~~~~~~~~~~      
   for (row=0; row < raw_height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, (data_offset-ftell(ifp)) & 15, SEEK_CUR);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     ph1_bits(-1);
     ~~~~~~~~~~~~~              
     mag = 0; pmode = 7;
     ~~~~~~~~~~~~~~~~~~~        
     FORC(6) lent[0][c] = row < 2 ? 7:4;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     prow[ row & 1] = &RAW(row-1,1-((row & 1) << 1)); // green
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     prow[~row & 1] = &RAW(row-2,0);   // red and blue
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (tab=0; tab+15 < raw_width; tab+=16) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (~opt & 4 && !(tab & 63)) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  i = ph1_bits(2);
  ~~~~~~~~~~~~~~~~              
  mag = i < 3 ? mag-'2'+"204"[i] : ph1_bits(12);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
       if (opt & 2)
       ~~~~~~~~~~~~             
  pmode = 7 - 4*ph1_bits(1);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
       else if (!ph1_bits(1))
       ~~~~~~~~~~~~~~~~~~~~~~   
  pmode = ph1_bits(3);
  ~~~~~~~~~~~~~~~~~~~~          
       if (opt & 1 || !ph1_bits(1)) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FORC4 len[c] = ph1_bits(2);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  FORC4 {
  ~~~~~~~                       
    i = ((row & 1) << 1 | (c & 1)) % 3;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    len[c] = len[c] < 3 ? lent[i][0]-'1'+"120"[len[c]] : ph1_bits(4);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    lent[i][0] = lent[i][1];
    ~~~~~~~~~~~~~~~~~~~~~~~~    
    lent[i][1] = len[c];
    ~~~~~~~~~~~~~~~~~~~~        
  }
  ~                             
       }
       ~                        
       FORC(16) {
       ~~~~~~~~~~               
  col = tab + (((c & 7) << 1)^(c >> 3)^(row & 1));
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pred = (pmode == 7 || row < 2)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       ? (tab ? RAW(row,tab-2+(col & 1)) : init)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       : (prow[col & 1][col-'4'+"0224468"[pmode]] +
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   prow[col & 1][col-'4'+"0244668"[pmode]] + 1) >> 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  diff = ph1_bits (i = len[c >> 2]);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (diff >> (i-1)) diff -= 1 << i;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  diff = diff * (mag*2+1) + mag;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = pred + diff;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
       }
       ~                        
     }
     ~                          
   }
   ~                            
 }
 ~                              
 
                                
 #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 pix, s, count, bin, next, i, sym[3];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   uchar diff, pred[]={0,0};
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   ushort data=0, range=0;
   ~~~~~~~~~~~~~~~~~~~~~~~      
 
                                
   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;
       ~~~~~~~~~                
     if(pix>=raw_width*raw_height)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         return;
         ~~~~~~~                
     raw_image[pix] = pred[pix & 1] += diff;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!(pix & 1) && HOLE(pix / raw_width)) 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] = RAW(row-1,col-1);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       val[1] = RAW(row-1,col+1);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       val[2] = RAW(row+1,col-1);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       val[3] = RAW(row+1,col+1);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = median4(val);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     for (col=2; col < width-2; col+=4)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (HOLE(row-2) || HOLE(row+2))
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  RAW(row,col) = (RAW(row,col-2) + RAW(row,col+2)) >> 1;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       else {
       ~~~~~~                   
  val[0] = RAW(row,col-2);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  val[1] = RAW(row,col+2);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  val[2] = RAW(row-2,col);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  val[3] = RAW(row+2,col);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  RAW(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 redcine_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
 {
 ~                              
 #ifndef NO_JASPER
 ~~~~~~~~~~~~~~~~~              
   int c, row, col;
   ~~~~~~~~~~~~~~~~             
   jas_stream_t *in;
   ~~~~~~~~~~~~~~~~~            
   jas_image_t *jimg;
   ~~~~~~~~~~~~~~~~~~           
   jas_matrix_t *jmat;
   ~~~~~~~~~~~~~~~~~~~          
   jas_seqent_t *data;
   ~~~~~~~~~~~~~~~~~~~          
   ushort *img, *pix;
   ~~~~~~~~~~~~~~~~~~           
 
                                
   jas_init();
   ~~~~~~~~~~~                  
   in = jas_stream_fopen (ifname, "rb");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jas_stream_seek (in, data_offset+20, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jimg = jas_image_decode (in, -1, 0);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (!jimg) longjmp (failure, 3);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   jmat = jas_matrix_create (height/2, width/2);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (jmat, "redcine_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   img = (ushort *) calloc ((height+2), (width+2)*2);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (img, "redcine_load_raw()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC4 {
   ~~~~~~~                      
     jas_image_readcmpt (jimg, c, 0, 0, width/2, height/2, jmat);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     data = jas_matrix_getref (jmat, 0, 0);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (row = c >> 1; row < height; row+=2)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col = c & 1; col < width; col+=2)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  img[(row+1)*(width+2)+col+1] = data[(row/2)*(width/2)+col/2];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for (col=1; col <= width; col++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     img[col] = img[2*(width+2)+col];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     img[(height+1)*(width+2)+col] = img[(height-1)*(width+2)+col];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for (row=0; row < height+2; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     img[row*(width+2)] = img[row*(width+2)+2];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     img[(row+1)*(width+2)-1] = img[(row+1)*(width+2)-3];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   for (row=1; row <= height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     pix = img + row*(width+2) + (col = 1 + (FC(row,1) & 1));
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (   ; col <= width; col+=2, pix+=2) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       c = (((pix[0] - 0x800) << 3) +
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pix[-(width+2)] + pix[width+2] + pix[-1] + pix[1]) >> 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pix[0] = LIM(c,0,4095);
       ~~~~~~~~~~~~~~~~~~~~~~~  
     }
     ~                          
   }
   ~                            
   for (row=0; row < height; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < width; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       RAW(row,col) = curve[img[(row+1)*(width+2)+col+1]];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   free (img);
   ~~~~~~~~~~~                  
   jas_matrix_destroy (jmat);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
   jas_image_destroy (jimg);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   jas_stream_close (in);
   ~~~~~~~~~~~~~~~~~~~~~~       
 #endif
 ~~~~~~                         
 }
 ~                              
 
                                
 /* 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();
       ~~~~~~~~~~~~~~~~~        
     memset (first_decode, 0, sizeof first_decode);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     free_decode = first_decode;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   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_sd_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   struct decode *dindex;
   ~~~~~~~~~~~~~~~~~~~~~~       
   short diff[1024];
   ~~~~~~~~~~~~~~~~~            
   unsigned bitbuf=0;
   ~~~~~~~~~~~~~~~~~~           
   int pred[3], row, col, bit=-1, c, i;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   read_shorts ((ushort *) diff, 1024);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (!load_flags) foveon_decoder (1024, 0);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   for (row=0; row < height; row++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     memset (pred, 0, sizeof pred);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!bit && !load_flags && atoi(model+2) < 14) get4();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=bit=0; col < width; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (load_flags) {
       ~~~~~~~~~~~~~~~~~        
  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];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS foveon_huff (ushort *huff)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int i, j, clen, code;
   ~~~~~~~~~~~~~~~~~~~~~        
 
                                
   huff[0] = 8;
   ~~~~~~~~~~~~                 
   for (i=0; i < 13; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~     
     clen = getc(ifp);
     ~~~~~~~~~~~~~~~~~          
     code = getc(ifp);
     ~~~~~~~~~~~~~~~~~          
     for (j=0; j < 256 >> clen; )
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       huff[code+ ++j] = clen << 8 | i;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   get2();
   ~~~~~~~                      
 }
 ~                              
 
                                
 void CLASS foveon_dp_load_raw()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   unsigned c, roff[4], row, col, diff;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort huff[512], vpred[2][2], hpred[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   fseek (ifp, 8, SEEK_CUR);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   foveon_huff (huff);
   ~~~~~~~~~~~~~~~~~~~          
   roff[0] = 48;
   ~~~~~~~~~~~~~                
   FORC3 roff[c+1] = -(-(roff[c] + get4()) & -16);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORC3 {
   ~~~~~~~                      
     fseek (ifp, data_offset+roff[c], SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     getbits(-1);
     ~~~~~~~~~~~~               
     vpred[0][0] = vpred[0][1] = vpred[1][0] = vpred[1][1] = 512;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (row=0; row < height; row++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < width; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  diff = ljpeg_diff(huff);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  else hpred[col & 1] += diff;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  image[row*width+col][c] = hpred[col & 1];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS foveon_load_camf()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
 {
 ~                              
   unsigned type, wide, high, i, j, row, col, diff;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort huff[258], vpred[2][2] = {{512,512},{512,512}}, hpred[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   fseek (ifp, meta_offset, SEEK_SET);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   type = get4();  get4();  get4();
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   wide = get4();
   ~~~~~~~~~~~~~~               
   high = get4();
   ~~~~~~~~~~~~~~               
   if (type == 2) {
   ~~~~~~~~~~~~~~~~             
     fread (meta_data, 1, meta_length, ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (i=0; i < meta_length; i++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       high = (high * 1597 + 51749) % 244944;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       wide = high * (INT64) 301593171 >> 24;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       meta_data[i] ^= ((((high << 8) - wide) >> 1) + wide) >> 17;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
   } else if (type == 4) {
   ~~~~~~~~~~~~~~~~~~~~~~~      
     free (meta_data);
     ~~~~~~~~~~~~~~~~~          
     meta_data = (char *) malloc (meta_length = wide*high*3/2);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     merror (meta_data, "foveon_load_camf()");
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     foveon_huff (huff);
     ~~~~~~~~~~~~~~~~~~~        
     get4();
     ~~~~~~~                    
     getbits(-1);
     ~~~~~~~~~~~~               
     for (j=row=0; row < high; row++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < wide; col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  diff = ljpeg_diff(huff);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  else         hpred[col & 1] += diff;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (col & 1) {
  ~~~~~~~~~~~~~~                
    meta_data[j++] = hpred[0] >> 4;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    meta_data[j++] = hpred[0] << 4 | hpred[1] >> 8;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    meta_data[j++] = hpred[1];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
  }
  ~                             
       }
       ~                        
     }
     ~                          
   } else
   ~~~~~~                       
     fprintf (stderr,_("%s has unknown CAMF type %d.\n"), ifname, type);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 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];
   ~~~~~~~~~~~~~~~~             
 
                                
   if (!name) return 0;
   ~~~~~~~~~~~~~~~~~~~~         
   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_load_camf();
   ~~~~~~~~~~~~~~~~~~~          
   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 (c=0; c < ARRAY_SIZE(ddft[0]); c++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i=0; i < ARRAY_SIZE(ddft[0][0]); i++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         ddft[0][c][i] = ddft[1][c][i] +
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           row / (height-1.0) * (ddft[2][c][i] - ddft[1][c][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 (c=0; c < ARRAY_SIZE(ddft[0]); c++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i=0; i < ARRAY_SIZE(ddft[0][0]); i++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         ddft[0][c][i] = ddft[1][c][i] +
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           row / (height-1.0) * (ddft[2][c][i] - ddft[1][c][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 ((height/4), (width/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 */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 void CLASS crop_masked_pixels()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int row, col;
   ~~~~~~~~~~~~~                
   unsigned r, c, m, mblack[8], zero, val;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (load_raw == &CLASS phase_one_load_raw ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       load_raw == &CLASS phase_one_load_raw_c)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     phase_one_correct();
     ~~~~~~~~~~~~~~~~~~~~       
   if (fuji_width) {
   ~~~~~~~~~~~~~~~~~            
     for (row=0; row < raw_height-top_margin*2; row++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < fuji_width << !fuji_layout; 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);
    ~~~~~~~~~~~~~~~~~~~~~~~~~   
  }
  ~                             
  if (r < height && c < width)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    BAYER(r,c) = RAW(row+top_margin,col+left_margin);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
   } else {
   ~~~~~~~~                     
     for (row=0; row < height; row++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=0; col < width; col++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  BAYER2(row,col) = RAW(row+top_margin,col+left_margin);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   if (mask[0][3] > 0) goto mask_set;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (load_raw == &CLASS canon_load_raw ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       load_raw == &CLASS lossless_jpeg_load_raw) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[0][1] = mask[1][1] += 2;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[0][3] -= 2;
     ~~~~~~~~~~~~~~~~           
     goto sides;
     ~~~~~~~~~~~                
   }
   ~                            
   if (load_raw == &CLASS canon_600_load_raw ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       load_raw == &CLASS sony_load_raw ||
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      (load_raw == &CLASS eight_bit_load_raw && strncmp(model,"DC2",3)) ||
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       load_raw == &CLASS kodak_262_load_raw ||
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      (load_raw == &CLASS packed_load_raw && (load_flags & 32))) {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 sides:
 ~~~~~~                         
     mask[0][0] = mask[1][0] = top_margin;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[0][2] = mask[1][2] = top_margin+height;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[0][3] += left_margin;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     mask[1][1] += left_margin+width;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[1][3] += raw_width;
     ~~~~~~~~~~~~~~~~~~~~~~~~   
   }
   ~                            
   if (load_raw == &CLASS nokia_load_raw) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mask[0][2] = top_margin;
     ~~~~~~~~~~~~~~~~~~~~~~~~   
     mask[0][3] = width;
     ~~~~~~~~~~~~~~~~~~~        
   }
   ~                            
 mask_set:
 ~~~~~~~~~                      
   memset (mblack, 0, sizeof mblack);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (zero=m=0; m < 8; m++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
     for (row=MAX(mask[m][0],0); row < MIN(mask[m][2],raw_height); row++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (col=MAX(mask[m][1],0); col < MIN(mask[m][3],raw_width); col++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  c = FC(row-top_margin,col-left_margin);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  mblack[c] += val = RAW(row,col);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  mblack[4+c]++;
  ~~~~~~~~~~~~~~                
  zero += !val;
  ~~~~~~~~~~~~~                 
       }
       ~                        
   if (load_raw == &CLASS canon_600_load_raw && width < raw_width) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     black = (mblack[0]+mblack[1]+mblack[2]+mblack[3]) /
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      (mblack[4]+mblack[5]+mblack[6]+mblack[7]) - 4;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     canon_600_correct();
     ~~~~~~~~~~~~~~~~~~~~       
   } else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7]) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC4 cblack[c] = mblack[c] / mblack[4+c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     cblack[4] = cblack[5] = cblack[6] = 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;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
 }
 ~                              
 
                                
 /*
 ~~                             
    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) && fcol(r,c) == fcol(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);
   ~~~~~~~~~~~~~                
   fclose (fp);
   ~~~~~~~~~~~~                 
   memset (cblack, 0, sizeof cblack);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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 (float rgb_cam[3][4], 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 (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], balance[4], num;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int c, i, j, k, sq, row, col, pass, 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] += BAYER2(row,col);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  BAYER2(row,col) = black + (BAYER2(row,col)-black)/2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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 (pass=0; pass < 2; pass++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (raw_color = 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 (rgb_cam, cam_xyz);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORCC balance[c] = pre_mul[c] * gmb_cam[20][c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (sq=0; sq < NSQ; sq++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
       FORCC gmb_cam[sq][c] *= balance[c];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   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, blk[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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;
   ~~~~~~~~~~~~~~~~             
   FORC4 cblack[c] <<= 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];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       blk[row] = cblack[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] - blk[~row & 1]*4 )
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        * mul[row & 1] + (window[1][col] + blk[row & 1]) * 0.5;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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 = fcol(y,x);
   ~~~~~~~~~~~~~~               
   val = BAYER2(y,x);
   ~~~~~~~~~~~~~~~~~~           
        } else
        ~~~~~~                  
   val = image[y*width+x][c];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
        if (val > maximum-25) goto skip_block;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if ((val -= cblack[c]) < 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] - cblack[c]) > 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[1] == 0) pre_mul[1] = 1;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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);
     ~~~~~~~~~~~~~~~~~~~~~      
   }
   ~                            
   if (filters > 1000 && (cblack[4]+1)/2 == 1 && (cblack[5]+1)/2 == 1) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     FORC4 cblack[FC(c/2,c%2)] +=
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cblack[6 + c/2 % cblack[4] * cblack[5] + c%2 % cblack[5]];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     cblack[4] = cblack[5] = 0;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   }
   ~                            
   size = iheight*iwidth;
   ~~~~~~~~~~~~~~~~~~~~~~       
   for (i=0; i < size*4; i++) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     if (!(val = image[0][i])) continue;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (cblack[4] && cblack[5])
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       val -= cblack[6 + i/4 / iwidth % cblack[4] * cblack[5] +
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    i/4 % iwidth % cblack[5]];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
     val -= cblack[i & 3];
     ~~~~~~~~~~~~~~~~~~~~~      
     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;
       ~~~~~~~~~~~~~~~~         
       if (filters == 9) {
       ~~~~~~~~~~~~~~~~~~~      
  for (row=0; row < 3; row++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
    for (col=1; col < 4; col++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
      if (!(image[row*width+col][0] | image[row*width+col][2]))
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        goto break2;  break2:
        ~~~~~~~~~~~~~~~~~~~~~   
  for ( ; row < height; row+=3)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    for (col=(col-1)%3+1; col < width-1; col+=3) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      img = image + row*width+col;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (c=0; c < 3; c+=2)
      ~~~~~~~~~~~~~~~~~~~~~~    
        img[0][c] = (img[-1][c] + img[1][c]) >> 1;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    }
    ~                           
       }
       ~                        
     } 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 = fcol(row,col);
    ~~~~~~~~~~~~~~~~~~          
    img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       free (image);
       ~~~~~~~~~~~~~            
       image = img;
       ~~~~~~~~~~~~             
       shrink = 0;
       ~~~~~~~~~~~              
     }
     ~                          
   }
   ~                            
   if (filters > 1000 && colors == 3) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mix_green = four_color_rgb ^ half_size;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (four_color_rgb | half_size) 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 = fcol(y,x);
      ~~~~~~~~~~~~~~            
      sum[f] += image[y*width+x][f];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      sum[f+4]++;
      ~~~~~~~~~~~               
    }
    ~                           
       f = fcol(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], size=16, *ip, sum[4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int f, c, i, x, y, row, col, shift, color;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort *pix;
   ~~~~~~~~~~~~                 
 
                                
   if (verbose) fprintf (stderr,_("Bilinear interpolation...\n"));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (filters == 9) size = 6;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   border_interpolate(1);
   ~~~~~~~~~~~~~~~~~~~~~~       
   for (row=0; row < size; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (col=0; col < size; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       ip = code[row][col]+1;
       ~~~~~~~~~~~~~~~~~~~~~~   
       f = fcol(row,col);
       ~~~~~~~~~~~~~~~~~~       
       memset (sum, 0, sizeof sum);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (y=-1; y <= 1; y++)
       ~~~~~~~~~~~~~~~~~~~~~~~  
  for (x=-1; x <= 1; x++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
    shift = (y==0) + (x==0);
    ~~~~~~~~~~~~~~~~~~~~~~~~    
    color = fcol(row+y,col+x);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
    if (color == f) continue;
    ~~~~~~~~~~~~~~~~~~~~~~~~~   
    *ip++ = (width*y + x)*4 + color;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    *ip++ = shift;
    ~~~~~~~~~~~~~~              
    *ip++ = color;
    ~~~~~~~~~~~~~~              
    sum[color] += 1 << shift;
    ~~~~~~~~~~~~~~~~~~~~~~~~~   
  }
  ~                             
       code[row][col][0] = (ip - code[row][col]) / 3;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORCC
       ~~~~~                    
  if (c != f) {
  ~~~~~~~~~~~~~                 
    *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 % size][col % size];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       memset (sum, 0, sizeof sum);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (i=*ip++; 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/pages/labsite/1999/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=8, pcol=2, *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 = 16;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (filters == 9) prow = pcol =  6;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ip = (int *) calloc (prow*pcol, 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 = fcol(row+y1,col+x1);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  if (fcol(row+y2,col+x2) != color) continue;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  diag = (fcol(row,col+1) == color && fcol(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 = fcol(row,col);
  ~~~~~~~~~~~~~~~~~~~~~~        
  if (fcol(row+y,col+x) != color && fcol(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 = fcol(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);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
 }
 ~                              
 
                                
 void CLASS cielab (ushort rgb[3], short lab[3])
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c, i, j, k;
   ~~~~~~~~~~~~~~~              
   float r, xyz[3];
   ~~~~~~~~~~~~~~~~             
   static float cbrt[0x10000], xyz_cam[3][4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (!rgb) {
   ~~~~~~~~~~~                  
     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];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     return;
     ~~~~~~~                    
   }
   ~                            
   xyz[0] = xyz[1] = xyz[2] = 0.5;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   FORCC {
   ~~~~~~~                      
     xyz[0] += xyz_cam[0][c] * rgb[c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     xyz[1] += xyz_cam[1][c] * rgb[c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     xyz[2] += xyz_cam[2][c] * rgb[c];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
   xyz[0] = cbrt[CLIP((int) xyz[0])];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   xyz[1] = cbrt[CLIP((int) xyz[1])];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   xyz[2] = cbrt[CLIP((int) xyz[2])];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   lab[0] = 64 * (116 * xyz[1] - 16);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   lab[1] = 64 * 500 * (xyz[0] - xyz[1]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   lab[2] = 64 * 200 * (xyz[1] - xyz[2]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 }
 ~                              
 
                                
 #define TS 512  /* Tile Size */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #define fcol(row,col) xtrans[(row+6) % 6][(col+6) % 6]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /*
 ~~                             
    Frank Markesteijn's algorithm for Fuji X-Trans sensors
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
  ~~                            
 void CLASS xtrans_interpolate (int passes)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 {
 ~                              
   int c, d, f, g, h, i, v, ng, row, col, top, left, mrow, mcol;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   int val, ndir, pass, hm[8], avg[4], color[3][8];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   static const short orth[12] = { 1,0,0,1,-1,0,0,-1,1,0,0,1 },
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  patt[2][16] = { { 0,1,0,-1,2,0,-1,0,1,1,1,-1,0,0,0,0 },
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    { 0,1,0,-2,1,0,-2,0,1,1,-2,-2,1,-1,-1,1 } },
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  dir[4] = { 1,TS,TS+1,TS-1 };
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   short allhex[3][3][2][8], *hex;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort min, max, sgrow, sgcol;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    short (*lab)    [TS][3], (*lix)[3];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    float (*drv)[TS][TS], diff[6], tr;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    char (*homo)[TS][TS], *buffer;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (verbose)
   ~~~~~~~~~~~~                 
     fprintf (stderr,_("%d-pass X-Trans interpolation...\n"), passes);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   cielab (0,0);
   ~~~~~~~~~~~~~                
   ndir = 4 << (passes > 1);
   ~~~~~~~~~~~~~~~~~~~~~~~~~    
   buffer = (char *) malloc (TS*TS*(ndir*11+6));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   merror (buffer, "xtrans_interpolate()");
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   rgb  = (ushort(*)[TS][TS][3]) buffer;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   lab  = (short (*)    [TS][3])(buffer + TS*TS*(ndir*6));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drv  = (float (*)[TS][TS])   (buffer + TS*TS*(ndir*6+6));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   homo = (char  (*)[TS][TS])   (buffer + TS*TS*(ndir*10+6));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /* Map a green hexagon around each non-green pixel and vice versa: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=0; row < 3; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
     for (col=0; col < 3; col++)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (ng=d=0; d < 10; d+=2) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  g = fcol(row,col) == 1;
  ~~~~~~~~~~~~~~~~~~~~~~~       
  if (fcol(row+orth[d],col+orth[d+2]) == 1) ng=0; else ng++;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (ng == 4) { sgrow = row; sgcol = col; }
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (ng == g+1) FORC(8) {
  ~~~~~~~~~~~~~~~~~~~~~~~~      
    v = orth[d  ]*patt[g][c*2] + orth[d+1]*patt[g][c*2+1];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    h = orth[d+2]*patt[g][c*2] + orth[d+3]*patt[g][c*2+1];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    allhex[row][col][0][c^(g*2 & d)] = h + v*width;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    allhex[row][col][1][c^(g*2 & d)] = h + v*TS;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
       }
       ~                        
 
                                
 /* Set green1 and green3 to the minimum and maximum allowed values: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (row=2; row < height-2; row++)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (min=~(max=0), col=2; col < width-2; col++) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (fcol(row,col) == 1 && (min=~(max=0))) continue;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       pix = image + row*width + col;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       hex = allhex[row % 3][col % 3][0];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (!max) FORC(6) {
       ~~~~~~~~~~~~~~~~~~~      
  val = pix[hex[c]][1];
  ~~~~~~~~~~~~~~~~~~~~~         
  if (min > val) min = val;
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  if (max < val) max = val;
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
       }
       ~                        
       pix[0][1] = min;
       ~~~~~~~~~~~~~~~~         
       pix[0][3] = max;
       ~~~~~~~~~~~~~~~~         
       switch ((row-sgrow) % 3) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  case 1: if (row < height-3) { row++; col--; } break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  case 2: if ((min=~(max=0)) && (col+=2) < width-3 && row > 2) row--;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
 
                                
   for (top=3; top < height-19; top += TS-16)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     for (left=3; left < width-19; left += TS-16) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       mrow = MIN (top+TS, height-3);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       mcol = MIN (left+TS, width-3);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (row=top; row < mrow; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col=left; col < mcol; col++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    memcpy (rgb[0][row-top][col-left], image[row*width+col], 6);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 memcpy (rgb[c+1], rgb[0], sizeof *rgb);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /* Interpolate green horizontally, vertically, and along both diagonals: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (row=top; row < mrow; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col=left; col < mcol; col++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if ((f = fcol(row,col)) == 1) continue;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    pix = image + row*width + col;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    hex = allhex[row % 3][col % 3][0];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    color[1][0] = 174 * (pix[  hex[1]][1] + pix[  hex[0]][1]) -
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     46 * (pix[2*hex[1]][1] + pix[2*hex[0]][1]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    color[1][1] = 223 *  pix[  hex[3]][1] + pix[  hex[2]][1] * 33 +
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     92 * (pix[      0 ][f] - pix[ -hex[2]][f]);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    FORC(2) color[1][2+c] =
    ~~~~~~~~~~~~~~~~~~~~~~~     
   164 * pix[hex[4+c]][1] + 92 * pix[-2*hex[4+c]][1] + 33 *
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   (2*pix[0][f] - pix[3*hex[4+c]][f] - pix[-3*hex[4+c]][f]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    FORC4 rgb[c^!((row-sgrow) % 3)][row-top][col-left][1] =
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   LIM(color[1][c] >> 8,pix[0][1],pix[0][3]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
 
                                
       for (pass=0; pass < passes; pass++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (pass == 1)
  ~~~~~~~~~~~~~~                
    memcpy (rgb+=4, buffer, 4*sizeof *rgb);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
 /* Recalculate green from interpolated values of closer pixels: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (pass) {
  ~~~~~~~~~~~                   
    for (row=top+2; row < mrow-2; row++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (col=left+2; col < mcol-2; col++) {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if ((f = fcol(row,col)) == 1) continue;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        pix = image + row*width + col;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        hex = allhex[row % 3][col % 3][1];
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        for (d=3; d < 6; d++) {
        ~~~~~~~~~~~~~~~~~~~~~~~ 
   rix = &rgb[(d-2)^!((row-sgrow) % 3)][row-top][col-left];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   val = rix[-2*hex[d]][1] + 2*rix[hex[d]][1]
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       - rix[-2*hex[d]][f] - 2*rix[hex[d]][f] + 3*rix[0][f];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   rix[0][1] = LIM(val/3,pix[0][1],pix[0][3]);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        }
        ~                       
      }
      ~                         
  }
  ~                             
 
                                
 /* Interpolate red and blue values for solitary green pixels: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (row=(top-sgrow+4)/3*3+sgrow; row < mrow-2; row+=3)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (col=(left-sgcol+4)/3*3+sgcol; col < mcol-2; col+=3) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      rix = &rgb[0][row-top][col-left];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      h = fcol(row,col+1);
      ~~~~~~~~~~~~~~~~~~~~      
      memset (diff, 0, sizeof diff);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (i=1, d=0; d < 6; d++, i^=TS^1, h^=2) {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        for (c=0; c < 2; c++, h^=2) {
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   g = 2*rix[0][1] - rix[i<<c][1] - rix[-i<<c][1];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   color[h][d] = g + rix[i<<c][h] + rix[-i<<c][h];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if (d > 1)
   ~~~~~~~~~~                   
     diff[d] += SQR (rix[i<<c][1] - rix[-i<<c][1]
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     - rix[i<<c][h] + rix[-i<<c][h]) + SQR(g);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        }
        ~                       
        if (d > 1 && (d & 1))
        ~~~~~~~~~~~~~~~~~~~~~   
   if (diff[d-1] < diff[d])
   ~~~~~~~~~~~~~~~~~~~~~~~~     
     FORC(2) color[c*2][d] = color[c*2][d-1];
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if (d < 2 || (d & 1)) {
        ~~~~~~~~~~~~~~~~~~~~~~~ 
   FORC(2) rix[0][c*2] = CLIP(color[c*2][d]/2);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   rix += TS*TS;
   ~~~~~~~~~~~~~                
        }
        ~                       
      }
      ~                         
    }
    ~                           
 
                                
 /* Interpolate red for blue pixels and vice versa:  */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (row=top+3; row < mrow-3; row++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (col=left+3; col < mcol-3; col++) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if ((f = 2-fcol(row,col)) == 1) continue;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      rix = &rgb[0][row-top][col-left];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      c = (row-sgrow) % 3 ? TS:1;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~
      h = 3 * (c ^ TS ^ 1);
      ~~~~~~~~~~~~~~~~~~~~~     
      for (d=0; d < 4; d++, rix += TS*TS) {
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        i = d > 1 || ((d ^ c) & 1) ||
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ((ABS(rix[0][1]-rix[c][1])+ABS(rix[0][1]-rix[-c][1])) <
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2*(ABS(rix[0][1]-rix[h][1])+ABS(rix[0][1]-rix[-h][1]))) ? c:h;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        rix[0][f] = CLIP((rix[i][f] + rix[-i][f] +
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     2*rix[0][1] - rix[i][1] - rix[-i][1])/2);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      }
      ~                         
    }
    ~                           
 
                                
 /* Fill in red and blue for 2x2 blocks of green:  */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (row=top+2; row < mrow-2; row++) if ((row-sgrow) % 3)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (col=left+2; col < mcol-2; col++) if ((col-sgcol) % 3) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      rix = &rgb[0][row-top][col-left];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      hex = allhex[row % 3][col % 3][1];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      for (d=0; d < ndir; d+=2, rix += TS*TS)
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if (hex[d] + hex[d+1]) {
        ~~~~~~~~~~~~~~~~~~~~~~~~
   g = 3*rix[0][1] - 2*rix[hex[d]][1] - rix[hex[d+1]][1];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (c=0; c < 4; c+=2) rix[0][c] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    CLIP((g + 2*rix[hex[d]][c] + rix[hex[d+1]][c])/3);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        } else {
        ~~~~~~~~                
   g = 2*rix[0][1] - rix[hex[d]][1] - rix[hex[d+1]][1];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   for (c=0; c < 4; c+=2) rix[0][c] =
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    CLIP((g + rix[hex[d]][c] + rix[hex[d+1]][c])/2);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        }
        ~                       
    }
    ~                           
       }
       ~                        
       rgb = (ushort(*)[TS][TS][3]) buffer;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       mrow -= top;
       ~~~~~~~~~~~~             
       mcol -= left;
       ~~~~~~~~~~~~~            
 
                                
 /* Convert to CIELab and differentiate in all directions: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (d=0; d < ndir; d++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (row=2; row < mrow-2; row++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (col=2; col < mcol-2; col++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      cielab (rgb[d][row][col], lab[row][col]);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (f=dir[d & 3],row=3; row < mrow-3; row++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (col=3; col < mcol-3; col++) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      lix = &lab[row][col];
      ~~~~~~~~~~~~~~~~~~~~~     
      g = 2*lix[0][0] - lix[f][0] - lix[-f][0];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      drv[d][row][col] = SQR(g)
      ~~~~~~~~~~~~~~~~~~~~~~~~~ 
        + SQR((2*lix[0][1] - lix[f][1] - lix[-f][1] + g*500/232))
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + SQR((2*lix[0][2] - lix[f][2] - lix[-f][2] - g*500/580));
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    }
    ~                           
       }
       ~                        
 
                                
 /* Build homogeneity maps from the derivatives:   */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       memset(homo, 0, ndir*TS*TS);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (row=4; row < mrow-4; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col=4; col < mcol-4; col++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (tr=FLT_MAX, d=0; d < ndir; d++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (tr > drv[d][row][col])
      ~~~~~~~~~~~~~~~~~~~~~~~~~~
   tr = drv[d][row][col];
   ~~~~~~~~~~~~~~~~~~~~~~       
    tr *= 8;
    ~~~~~~~~                    
    for (d=0; d < ndir; d++)
    ~~~~~~~~~~~~~~~~~~~~~~~~    
      for (v=-1; v <= 1; v++)
      ~~~~~~~~~~~~~~~~~~~~~~~   
        for (h=-1; h <= 1; h++)
        ~~~~~~~~~~~~~~~~~~~~~~~ 
   if (drv[d][row+v][col+h] <= tr)
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     homo[d][row][col]++;
     ~~~~~~~~~~~~~~~~~~~~       
  }
  ~                             
 
                                
 /* Average the most homogenous pixels for the final result: */
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (height-top < TS+4) mrow = height-top+2;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (width-left < TS+4) mcol = width-left+2;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (row = MIN(top,8); row < mrow-8; row++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (col = MIN(left,8); col < mcol-8; col++) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (d=0; d < ndir; d++)
    ~~~~~~~~~~~~~~~~~~~~~~~~    
      for (hm[d]=0, v=-2; v <= 2; v++)
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        for (h=-2; h <= 2; h++)
        ~~~~~~~~~~~~~~~~~~~~~~~ 
   hm[d] += homo[d][row+v][col+h];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (d=0; d < ndir-4; d++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~  
      if (hm[d] < hm[d+4]) hm[d  ] = 0; else
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (hm[d] > hm[d+4]) hm[d+4] = 0;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (max=hm[0],d=1; d < ndir; d++)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (max < hm[d]) max = hm[d];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    max -= max >> 3;
    ~~~~~~~~~~~~~~~~            
    memset (avg, 0, sizeof avg);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (d=0; d < ndir; d++)
    ~~~~~~~~~~~~~~~~~~~~~~~~    
      if (hm[d] >= max) {
      ~~~~~~~~~~~~~~~~~~~       
        FORC3 avg[c] += rgb[d][row][col][c];
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        avg[3]++;
        ~~~~~~~~~               
      }
      ~                         
    FORC3 image[(row+top)*width+col+left][c] = avg[c]/avg[3];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  }
  ~                             
     }
     ~                          
   free(buffer);
   ~~~~~~~~~~~~~                
   border_interpolate(8);
   ~~~~~~~~~~~~~~~~~~~~~~       
 }
 ~                              
 #undef fcol
 ~~~~~~~~~~~                    
 
                                
 /*
 ~~                             
    Adaptive Homogeneity-Directed interpolation is based on
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
  ~~                            
 void CLASS ahd_interpolate()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
 {
 ~                              
   int i, j, top, left, row, col, tr, tc, c, d, val, hm[2];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   static const int dir[4] = { -1, 1, -TS, TS };
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4];
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    short (*lab)[TS][TS][3], (*lix)[3];
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    char (*homo)[TS][TS], *buffer;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   cielab (0,0);
   ~~~~~~~~~~~~~                
   border_interpolate(5);
   ~~~~~~~~~~~~~~~~~~~~~~       
   buffer = (char *) malloc (26*TS*TS);
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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];
      ~~~~~~~~~~~~~~~~~~~~~~    
      cielab (rix[0],lix[0]);
      ~~~~~~~~~~~~~~~~~~~~~~~   
    }
    ~                           
 /*  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 * ("11124811248484"[*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 morder, 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.
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
  ~~                            
   if (!strcmp(make,"Nokia")) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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") ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
              !strcmp (buf,"PENTAX ")) {
              ~~~~~~~~~~~~~~~~~~~~~~~~~~
     base = ftell(ifp)-10;
     ~~~~~~~~~~~~~~~~~~~~~      
     fseek (ifp, -2, SEEK_CUR);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     order = get2();
     ~~~~~~~~~~~~~~~            
     if (buf[0] == 'O') get2();
     ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   } else if (!strncmp (buf,"SONY",4) ||
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       !strcmp  (buf,"Panasonic")) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     goto nf;
     ~~~~~~~~                   
   } else if (!strncmp (buf,"FUJIFILM",8)) {
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     base = ftell(ifp)-10;
     ~~~~~~~~~~~~~~~~~~~~~      
 nf: 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);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (!strncmp(make,"SAMSUNG",7))
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       base = ftell(ifp);
       ~~~~~~~~~~~~~~~~~~       
   }
   ~                            
   entries = get2();
   ~~~~~~~~~~~~~~~~~            
   if (entries > 1000) return;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
   morder = order;
   ~~~~~~~~~~~~~~~              
   while (entries--) {
   ~~~~~~~~~~~~~~~~~~~          
     order = morder;
     ~~~~~~~~~~~~~~~            
     tiff_get (base, &tag, &type, &len, &save);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     tag |= uptag << 16;
     ~~~~~~~~~~~~~~~~~~~        
     if (tag == 2 && strstr(make,"NIKON") && !iso_speed)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       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 == 4 || tag == 0x114) && !strncmp(make,"KONICA",6)) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, tag == 4 ? 140:160, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       switch (get2()) {
       ~~~~~~~~~~~~~~~~~        
  case 72:  flip = 0;  break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  case 76:  flip = 6;  break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
  case 82:  flip = 5;  break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~   
       }
       ~                        
     }
     ~                          
     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)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 cam_mul[(c << 1 | c >> 1) & 3] = getreal(type);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0xd && type == 7 && get2() == 0xaaaa) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       for (c=i=2; (ushort) c != 0xbbbb && i < len; i++)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  c = c << 8 | fgetc(ifp);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
       while ((i+=4) < len-5)
       ~~~~~~~~~~~~~~~~~~~~~~   
  if (get4() == 257 && (i=len) && (c = (get4(),fgetc(ifp))) < 3)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    flip = "065"[c]-'0';
    ~~~~~~~~~~~~~~~~~~~~        
     }
     ~                          
     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 && type == 7) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       if (len == 2560) {
       ~~~~~~~~~~~~~~~~~~       
  fseek (ifp, 1248, SEEK_CUR);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  goto get2_256;
  ~~~~~~~~~~~~~~                
       }
       ~                        
       fread (buf, 1, 10, ifp);
       ~~~~~~~~~~~~~~~~~~~~~~~~ 
       if (!strncmp(buf,"NRW ",4)) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  fseek (ifp, strcmp(buf+4,"0100") ? 46:1546, SEEK_CUR);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cam_mul[0] = get4() << 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
  cam_mul[1] = get4() + get4();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  cam_mul[2] = get4() << 2;
  ~~~~~~~~~~~~~~~~~~~~~~~~~     
       }
       ~                        
     }
     ~                          
     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 == 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 == 0x3d && type == 3 && len == 4)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 cblack[c ^ c >> 1] = get2() >> (14-tiff_ifd[2].bps);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     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 == 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 == 0xa1 && type == 7) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       order = 0x4949;
       ~~~~~~~~~~~~~~~          
       fseek (ifp, 140, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 cam_mul[c] = get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     if (tag == 0xa4 && type == 3) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, wbi*48, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 cam_mul[c] = get2();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     if (tag == 0xa7 && (unsigned) (ver97-200) < 17) {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       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;:;55"[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)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 cblack[c ^ c >> 1] = get2();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0x201 && len == 4)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       goto get2_rggb;
       ~~~~~~~~~~~~~~~          
     if (tag == 0x220 && type == 7)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       meta_offset = ftell(ifp);
       ~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0x401 && type == 4 && len == 4)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 cblack[c ^ c >> 1] = get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0xe01) {  /* Nikon Capture Note */
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       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);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       }
       ~                        
     }
     ~                          
     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)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 cblack[c ^ c >> 1] = get2();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     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 || type == 13))
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, get4()+base, SEEK_SET);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0x2020)
     ~~~~~~~~~~~~~~~~~~         
       parse_thumb_note (base, 257, 258);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0x2040)
     ~~~~~~~~~~~~~~~~~~         
       parse_makernote (base, 0x2040);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0xb028) {
     ~~~~~~~~~~~~~~~~~~~~       
       fseek (ifp, get4()+base, 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();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       i = len >> 3 == 164 || len == 1506 ? 112:22;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       fseek (ifp, i, SEEK_CUR);
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 sraw_mul[c ^ (c >> 1)] = get2();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     if (tag == 0x4021 && get4() && get4())
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC4 cam_mul[c] = 1024;
       ~~~~~~~~~~~~~~~~~~~~~~~~ 
     if (tag == 0xa021)
     ~~~~~~~~~~~~~~~~~~         
       FORC4 cam_mul[c ^ (c >> 1)] = get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0xa028)
     ~~~~~~~~~~~~~~~~~~         
       FORC4 cam_mul[c ^ (c >> 1)] -= get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 0xb001)
     ~~~~~~~~~~~~~~~~~~         
       unique_id = 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;
   ~~~~~~~~~~~~~~               
   t.tm_isdst = -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) && tiff_nifds < 3;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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",
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     "Aptus-II 7","","","Aptus-II 6","","","Aptus-II 10","Aptus-II 5",
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     "","","","","Aptus-II 10R","Aptus-II 8","","Aptus-II 12","","AFi-II 12" };
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   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 (c=0; c < ARRAY_SIZE(romm_cam); c++) {
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (i=0; i < ARRAY_SIZE(romm_cam[0]); i++)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    romm_cam[c][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];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     }
     ~                          
     if (!strcmp(data,"Rows_data"))
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       load_flags = get4();
       ~~~~~~~~~~~~~~~~~~~~     
     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]={1,1,1}, num;
   ~~~~~~~~~~~~~~~~~~~~~~~~~~   
   static const int wbtag[] = { 64037,64040,64039,64041,-1,-1,64042 };
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
                                
   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 == 2120 + wbi && wbi >= 0)
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 cam_mul[c] = 2048.0 / getreal(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);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 64013) wbi = fgetc(ifp);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if ((unsigned) wbi < 7 && tag == wbtag[wbi])
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       FORC3 cam_mul[c] = get4();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 64019) width = getint(type);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     if (tag == 64020) height = (getint(type)+1) & -2;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     fseek (ifp, save, SEEK_SET);
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
   ~                            
 }
 ~                              
 
                                
 void CLASS parse_minolta (int base);
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 int CLASS parse_tiff (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 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 5:   width  = get2();  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 6:   height = get2();  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 7:   width += get2();  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 9:   if ((i = get2())) filters = i;  break;
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       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 28: case 29: case 30:
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  cblack[tag-28] = get2();
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  cblack[3] = cblack[1];
  ~~~~~~~~~~~~~~~~~~~~~~        
  break;
  ~~~~~~                        
       case 36: case 37: case 38:
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  cam_mul[tag-36] = 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 61440:   /* Fuji HS10 table */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  fseek (ifp, get4()+base, SEEK_SET);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  parse_tiff_ifd (base);
  ~~~~~~~~~~~~~~~~~~~~~~        
  break;
  ~~~~~~                        
       case 2: case 256: case 61441: /* ImageWidth */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].width = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 3: case 257: case 61442: /* ImageHeight */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].height = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 258:    /* BitsPerSample */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 61443:
       ~~~~~~~~~~~              
  tiff_ifd[ifd].samples = len & 7;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].bps = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 61446:
       ~~~~~~~~~~~              
  raw_height = 0;
  ~~~~~~~~~~~~~~~               
  if (tiff_ifd[ifd].bps > 12) break;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  load_raw = &CLASS packed_load_raw;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  load_flags = get4() ? 24:80;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  break;
  ~~~~~~                        
       case 259:    /* Compression */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].comp = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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:    /* JpegIFOffset */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       case 61447:
       ~~~~~~~~~~~              
  tiff_ifd[ifd].offset = get4()+base;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (!tiff_ifd[ifd].bps && tiff_ifd[ifd].offset > 0) {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET);
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (ljpeg_start (&jh, 1)) {
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
      tiff_ifd[ifd].comp    = 6;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~
      tiff_ifd[ifd].width   = jh.wide;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      tiff_ifd[ifd].height  = jh.high;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      tiff_ifd[ifd].bps     = jh.bits;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      tiff_ifd[ifd].samples = jh.clrs;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (!(jh.sraw || (jh.clrs & 1)))
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        tiff_ifd[ifd].width *= jh.clrs;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      i = order;
      ~~~~~~~~~~                
      parse_tiff (tiff_ifd[ifd].offset + 12);
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      order = i;
      ~~~~~~~~~~                
    }
    ~                           
  }
  ~                             
  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:
       ~~~~~~~~~                
       case 61448:
       ~~~~~~~~~~~              
  tiff_ifd[ifd].bytes = get4();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  break;
  ~~~~~~                        
       case 61454:
       ~~~~~~~~~~~              
  FORC3 cam_mul[(4-c) % 3] = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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 */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].tile_width = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 323:    /* TileLength */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].tile_length = getint(type);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 324:    /* TileOffsets */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (len == 1)
  ~~~~~~~~~~~~~                 
    tiff_ifd[ifd].tile_width = tiff_ifd[ifd].tile_length = 0;
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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;
    ~~~~~~~~~~~~~~              
  }
  ~                             
  if(len > 1000) len=1000; /* 1000 SubIFDs is enough */
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  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] = get2();
  ~~~~~~~~~~~~~~~~~~~~~~~~~~    
  i = (cam_mul[1] == 1024 && cam_mul[2] == 1024) << 1;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SWAP (cam_mul[i],cam_mul[i+1])
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  break;
  ~~~~~~                        
       case 33405:   /* Model2 */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~
  fgets (model2, 64, ifp);
  ~~~~~~~~~~~~~~~~~~~~~~~~      
  break;
  ~~~~~~                        
       case 33421:   /* CFARepeatPatternDim */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (get2() == 6 && get2() == 6)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    filters = 9;
    ~~~~~~~~~~~~                
  break;
  ~~~~~~                        
       case 33422:   /* CFAPattern */
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (filters == 9) {
  ~~~~~~~~~~~~~~~~~~~           
    FORC(36) xtrans[0][c] = fgetc(ifp) & 3;
    ~~~~~~                      
codecs/dcraw.h:5854:4: note: in expansion of macro 'FORC'
    FORC(36) xtrans[0][c] = fgetc(ifp) & 3;
    ^~~~
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/bardecode.d' -o 'objdir/frontends/bardecode.o' 'frontends/bardecode.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/hocr2pdf.d' -o 'objdir/frontends/hocr2pdf.o' 'frontends/hocr2pdf.cc'
In file included from /usr/include/c++/6/vector:69:0,
                 from utility/ArgumentList.hh:40,
                 from frontends/optimize2bw.cc:25:
/usr/include/c++/6/bits/vector.tcc: In member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, const _Tp&) [with _Tp = double; _Alloc = std::allocator<double>]':
/usr/include/c++/6/bits/vector.tcc:326:5: note: parameter passing for argument of type 'std::vector<double, std::allocator<double> >::iterator {aka __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >}' will change in GCC 7.1
     vector<_Tp, _Alloc>::
     ^~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/6/vector:64:0,
                 from utility/ArgumentList.hh:40,
                 from frontends/optimize2bw.cc:25:
/usr/include/c++/6/bits/stl_vector.h: In constructor 'Utility::Argument<T>::Argument(const string&, const string&, const string&, const T&, int, int, bool, bool) [with T = double]':
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h: In member function 'bool Utility::Argument<T>::Read(const string&) [with T = double]':
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/edentify.d' -o 'objdir/frontends/edentify.o' 'frontends/edentify.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/empty-page.d' -o 'objdir/frontends/empty-page.o' 'frontends/empty-page.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/e2mtiff.d' -o 'objdir/frontends/e2mtiff.o' 'frontends/e2mtiff.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/econvert.d' -o 'objdir/frontends/econvert.o' 'frontends/econvert.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/gfx/EvasHelper.d' -o 'objdir/gfx/EvasHelper.o' 'gfx/EvasHelper.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/gfx/X11Helper.d' -o 'objdir/gfx/X11Helper.o' 'gfx/X11Helper.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/edisplay/edisplay.d' -o 'objdir/edisplay/edisplay.o' 'edisplay/edisplay.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/utility/Timer.d' -o 'objdir/utility/Timer.o' 'utility/Timer.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/api/api.d' -o 'objdir/api/api.o' 'api/api.cc'
edisplay/edisplay.cc: In member function 'int Viewer::Run(bool)':
edisplay/edisplay.cc:231:20: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
   chint.res_name = "edisplay";
                    ^~~~~~~~~~
edisplay/edisplay.cc:232:21: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
   chint.res_class = "Main";
                     ^~~~~~
echo "  SWIG      objdir/api/perl/"
  SWIG      objdir/api/perl/
swig -perl -c++ -outdir objdir/api/perl/ -o 'objdir/api/perl/api-perl-wrap.cc' api/python/../api-swig.hh
echo "  SWIG      objdir/api/python/"
  SWIG      objdir/api/python/
swig -python -c++ -outdir objdir/api/python/ -o 'objdir/api/python/api-python-wrap.cc' api/python/../api-swig.hh
ld -r -o 'objdir/image/image.a' objdir/image/Colorspace.o objdir/image/ContourMatching.o objdir/image/ContourUtility.o objdir/image/Contours.o objdir/image/DistanceMatrix.o objdir/image/FG-Matrix.o objdir/image/GaussianBlur.o objdir/image/Image.o objdir/image/Image2.o objdir/image/Matrix.o objdir/image/agg.o objdir/image/canvas.o objdir/image/crop.o objdir/image/empty-page.o objdir/image/floyd-steinberg.o objdir/image/hocr.o objdir/image/low-level.o objdir/image/optimize2bw.o objdir/image/riemersma.o objdir/image/rotate.o objdir/image/scale.o objdir/image/segmentation.o objdir/image/vectorial.o
ld -r -o 'objdir/codecs/codecs.a' objdir/codecs/Codecs.o objdir/codecs/agg_svg_parser.o objdir/codecs/agg_svg_path_renderer.o objdir/codecs/agg_svg_path_tokenizer.o objdir/codecs/bmp.o objdir/codecs/dcraw.o objdir/codecs/eps.o objdir/codecs/gif.o objdir/codecs/jpeg.o objdir/codecs/openexr.o objdir/codecs/pcx.o objdir/codecs/pdf.o objdir/codecs/png.o objdir/codecs/pnm.o objdir/codecs/ps.o objdir/codecs/raw.o objdir/codecs/svg.o objdir/codecs/tga.o objdir/codecs/tiff.o objdir/codecs/transupp.o objdir/codecs/xpm.o
ld -r -o 'objdir/bardecode/bardecode.a' objdir/bardecode/Scanner.o
ld -r -o 'objdir/gfx/libgsmpgfx.a' objdir/gfx/EvasHelper.o objdir/gfx/X11Helper.o objdir/image/image.a objdir/codecs/codecs.a objdir/utility/ArgumentList.o
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/optimize2bw' objdir/frontends/optimize2bw.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/bardecode' objdir/frontends/bardecode.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/hocr2pdf' objdir/frontends/hocr2pdf.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/edentify' objdir/frontends/edentify.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/empty-page' objdir/frontends/empty-page.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/e2mtiff' objdir/frontends/e2mtiff.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
In file included from /usr/include/c++/6/vector:69:0,
                 from utility/ArgumentList.hh:40,
                 from frontends/econvert.cc:35:
/usr/include/c++/6/bits/vector.tcc: In member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, const _Tp&) [with _Tp = double; _Alloc = std::allocator<double>]':
/usr/include/c++/6/bits/vector.tcc:326:5: note: parameter passing for argument of type 'std::vector<double>::iterator {aka __gnu_cxx::__normal_iterator<double*, std::vector<double> >}' will change in GCC 7.1
     vector<_Tp, _Alloc>::
     ^~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/6/vector:64:0,
                 from utility/ArgumentList.hh:40,
                 from frontends/econvert.cc:35:
/usr/include/c++/6/bits/stl_vector.h: In member function 'bool Utility::Argument<T>::Read(const string&) [with T = double]':
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double> >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/edisplay/edisplay' objdir/edisplay/edisplay.o objdir/image/image.a objdir/codecs/codecs.a objdir/utility/ArgumentList.o objdir/gfx/X11Helper.o objdir/gfx/EvasHelper.o objdir/utility/Timer.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
/usr/include/c++/6/bits/stl_vector.h: In constructor 'Utility::Argument<T>::Argument(const string&, const string&, const string&, int, int, bool, bool) [with T = double]':
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double> >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h: In constructor 'Utility::Argument<T>::Argument(const string&, const string&, const string&, const T&, int, int, bool, bool) [with T = double]':
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double> >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double> >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
ld -r -o 'objdir/api/api.a' objdir/api/api.o
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN -I api -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fwrapv -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/lib/arm-linux-gnueabihf/perl/5.24/CORE  -shared -fPIC -o 'objdir/api/perl/ExactImage.so' objdir/bardecode/bardecode.a objdir/codecs/codecs.a objdir/api/api.a objdir/api/perl/api-perl-wrap.cc -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections -lagg_pic -laggfontfreetype_pic -lfreetype -ljpeg -ltiff -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN -I api -I/usr/include/python2.7 -I/usr/include/arm-linux-gnueabihf/python2.7  -shared -fPIC -o 'objdir/api/python/_ExactImage.so' objdir/bardecode/bardecode.a objdir/codecs/codecs.a objdir/api/api.a objdir/api/python/api-python-wrap.cc -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections -lagg_pic -laggfontfreetype_pic -lfreetype -ljpeg -ltiff -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
In file included from api/api.hh:36:0,
                 from objdir/api/perl/api-perl-wrap.cc:1620:
./config.h:27:0: warning: "STATIC" redefined
 #define STATIC
 
In file included from objdir/api/perl/api-perl-wrap.cc:763:0:
/usr/lib/arm-linux-gnueabihf/perl/5.24/CORE/perl.h:197:0: note: this is the location of the previous definition
 #define STATIC static
 
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/econvert' objdir/frontends/econvert.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
rm objdir/frontends/bardecode.o objdir/frontends/edentify.o objdir/frontends/hocr2pdf.o objdir/frontends/e2mtiff.o objdir/frontends/econvert.o objdir/frontends/empty-page.o objdir/frontends/optimize2bw.o
make[2]: Leaving directory '/<<PKGBUILDDIR>>'
set -e; \
for python in python2.7; do \
	rm -f objdir/api/python/_ExactImage.so; \
	dh_auto_build -- X_SYSTEM=Linux Q= objdir/api/python/_ExactImage.so PYTHONINCS=`$python-config --includes`; \
	mkdir -p objdir/api/$python; \
	cp objdir/api/python/*.so objdir/api/$python/; \
	cp objdir/api/python/*.py objdir/api/$python/; \
	chmod a-x objdir/api/$python/*; \
done
	make -j4 X_SYSTEM=Linux Q= objdir/api/python/_ExactImage.so PYTHONINCS=-I/usr/include/python2.7 -I/usr/include/arm-linux-gnueabihf/python2.7
make[2]: Entering directory '/<<PKGBUILDDIR>>'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN -I api -I/usr/include/python2.7  -shared -fPIC -o 'objdir/api/python/_ExactImage.so' objdir/bardecode/bardecode.a objdir/codecs/codecs.a objdir/api/api.a objdir/api/python/api-python-wrap.cc -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections -lagg_pic -laggfontfreetype_pic -lfreetype -ljpeg -ltiff -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
make[2]: Leaving directory '/<<PKGBUILDDIR>>'
/usr/bin/make X_SYSTEM=Linux Q= -C debian/manpages/
make[2]: Entering directory '/<<PKGBUILDDIR>>/debian/manpages'
xmllint --valid --noout e2mtiff.1.xml
xsltproc --param man.charmap.use.subset 0 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl e2mtiff.1.xml
Note: Writing e2mtiff.1
xmllint --valid --noout econvert.1.xml
xsltproc --param man.charmap.use.subset 0 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl econvert.1.xml
Note: Writing econvert.1
xmllint --valid --noout optimize2bw.1.xml
xsltproc --param man.charmap.use.subset 0 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl optimize2bw.1.xml
Note: Writing optimize2bw.1
xmllint --valid --noout exactimage.7.xml
xsltproc --param man.charmap.use.subset 0 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl exactimage.7.xml
Note: Writing exactimage.7
xmllint --valid --noout bardecode.1.xml
xsltproc --param man.charmap.use.subset 0 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl bardecode.1.xml
Note: Writing bardecode.1
xmllint --valid --noout hocr2pdf.1.xml
xsltproc --param man.charmap.use.subset 0 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl hocr2pdf.1.xml
Note: Writing hocr2pdf.1
xmllint --valid --noout edentify.1.xml
xsltproc --param man.charmap.use.subset 0 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl edentify.1.xml
Note: Writing edentify.1
xmllint --valid --noout edisplay.1.xml
xsltproc --param man.charmap.use.subset 0 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl edisplay.1.xml
Note: Writing edisplay.1
xmllint --valid --noout empty-page.1.xml
xsltproc --param man.charmap.use.subset 0 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl empty-page.1.xml
Note: Writing empty-page.1
make[2]: Leaving directory '/<<PKGBUILDDIR>>/debian/manpages'
make[1]: Leaving directory '/<<PKGBUILDDIR>>'
   create-stamp debian/debhelper-build-stamp
 fakeroot debian/rules binary-arch
dh binary-arch --parallel --list-missing --with=python2
   debian/rules install-arch
make[1]: Entering directory '/<<PKGBUILDDIR>>'
dh install-arch --parallel --list-missing --with=python2
   debian/rules build-arch
make[2]: Entering directory '/<<PKGBUILDDIR>>'
dh build-arch --parallel --list-missing --with=python2
   create-stamp debian/debhelper-build-stamp
make[2]: Leaving directory '/<<PKGBUILDDIR>>'
   dh_testroot -a -O--parallel -O--list-missing
   dh_prep -a -O--parallel -O--list-missing
   debian/rules override_dh_auto_install
make[2]: Entering directory '/<<PKGBUILDDIR>>'
sed -e 's,${perl_archlib},/usr/lib/arm-linux-gnueabihf/perl5/5.24,g' debian/libexactimage-perl.install.in > debian/libexactimage-perl.install
dh_auto_install -- X_SYSTEM=Linux Q= WITHPYTHON=0
	make -j4 install DESTDIR=/<<PKGBUILDDIR>>/debian/tmp AM_UPDATE_INFO_DIR=no X_SYSTEM=Linux Q= WITHPYTHON=0
make[3]: Entering directory '/<<PKGBUILDDIR>>'
for x in objdir/image/image.a; do \
  case $x in \
	*.so ) echo INSTALL DYNLIB $x; mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/lib/; install $x /<<PKGBUILDDIR>>/debian/tmp/usr/lib/ ;; \
	*.a ) ;; \
	* ) echo INSTALL EXEC   $x; mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/bin/; install $x /<<PKGBUILDDIR>>/debian/tmp/usr/bin/ ;; \
  esac ;\
done
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/optimize2bw.d' -o 'objdir/frontends/optimize2bw.o' 'frontends/optimize2bw.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/bardecode.d' -o 'objdir/frontends/bardecode.o' 'frontends/bardecode.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/hocr2pdf.d' -o 'objdir/frontends/hocr2pdf.o' 'frontends/hocr2pdf.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/edentify.d' -o 'objdir/frontends/edentify.o' 'frontends/edentify.cc'
In file included from /usr/include/c++/6/vector:69:0,
                 from utility/ArgumentList.hh:40,
                 from frontends/optimize2bw.cc:25:
/usr/include/c++/6/bits/vector.tcc: In member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, const _Tp&) [with _Tp = double; _Alloc = std::allocator<double>]':
/usr/include/c++/6/bits/vector.tcc:326:5: note: parameter passing for argument of type 'std::vector<double, std::allocator<double> >::iterator {aka __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >}' will change in GCC 7.1
     vector<_Tp, _Alloc>::
     ^~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/6/vector:64:0,
                 from utility/ArgumentList.hh:40,
                 from frontends/optimize2bw.cc:25:
/usr/include/c++/6/bits/stl_vector.h: In constructor 'Utility::Argument<T>::Argument(const string&, const string&, const string&, const T&, int, int, bool, bool) [with T = double]':
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/empty-page.d' -o 'objdir/frontends/empty-page.o' 'frontends/empty-page.cc'
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/e2mtiff.d' -o 'objdir/frontends/e2mtiff.o' 'frontends/e2mtiff.cc'
/usr/include/c++/6/bits/stl_vector.h: In member function 'bool Utility::Argument<T>::Read(const string&) [with T = double]':
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN  -c  -MMD -MP -MF 'objdir/frontends/econvert.d' -o 'objdir/frontends/econvert.o' 'frontends/econvert.cc'
for x in objdir/codecs/codecs.a; do \
  case $x in \
	*.so ) echo INSTALL DYNLIB $x; mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/lib/; install $x /<<PKGBUILDDIR>>/debian/tmp/usr/lib/ ;; \
	*.a ) ;; \
	* ) echo INSTALL EXEC   $x; mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/bin/; install $x /<<PKGBUILDDIR>>/debian/tmp/usr/bin/ ;; \
  esac ;\
done
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/optimize2bw' objdir/frontends/optimize2bw.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/hocr2pdf' objdir/frontends/hocr2pdf.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/edentify' objdir/frontends/edentify.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/empty-page' objdir/frontends/empty-page.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/e2mtiff' objdir/frontends/e2mtiff.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
for x in objdir/bardecode/bardecode.a; do \
  case $x in \
	*.so ) echo INSTALL DYNLIB $x; mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/lib/; install $x /<<PKGBUILDDIR>>/debian/tmp/usr/lib/ ;; \
	*.a ) ;; \
	* ) echo INSTALL EXEC   $x; mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/bin/; install $x /<<PKGBUILDDIR>>/debian/tmp/usr/bin/ ;; \
  esac ;\
done
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/bardecode' objdir/frontends/bardecode.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
In file included from /usr/include/c++/6/vector:69:0,
                 from utility/ArgumentList.hh:40,
                 from frontends/econvert.cc:35:
/usr/include/c++/6/bits/vector.tcc: In member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, const _Tp&) [with _Tp = double; _Alloc = std::allocator<double>]':
/usr/include/c++/6/bits/vector.tcc:326:5: note: parameter passing for argument of type 'std::vector<double>::iterator {aka __gnu_cxx::__normal_iterator<double*, std::vector<double> >}' will change in GCC 7.1
     vector<_Tp, _Alloc>::
     ^~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/6/vector:64:0,
                 from utility/ArgumentList.hh:40,
                 from frontends/econvert.cc:35:
/usr/include/c++/6/bits/stl_vector.h: In member function 'bool Utility::Argument<T>::Read(const string&) [with T = double]':
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double> >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h: In constructor 'Utility::Argument<T>::Argument(const string&, const string&, const string&, int, int, bool, bool) [with T = double]':
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double> >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h: In constructor 'Utility::Argument<T>::Argument(const string&, const string&, const string&, const T&, int, int, bool, bool) [with T = double]':
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double> >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:926:4: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<double*, std::vector<double> >' will change in GCC 7.1
    _M_insert_aux(end(), __x);
    ^~~~~~~~~~~~~
g++ -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -fopenmp -ffunction-sections -fdata-sections -fPIC -Wno-switch -Wno-switch-enum -Wno-sign-compare -std=gnu++98 -Wdate-time -D_FORTIFY_SOURCE=2 -D_FILE_OFFSET_BITS=64 -I . -I/usr/include/agg2 -I/usr/include/freetype2 -I image -I utility -I/usr/include/OpenEXR -I codecs/ -I bardecode -I utility -I utility -I/usr/X11/include -I/usr/include/efl-1 -I/usr/include/evas-1 -I/usr/include/libpng16 -I/usr/include/fribidi -I/usr/include/freetype2 -I/usr/include/efl-1 -I/usr/include/eet-1 -I/usr/include/p11-kit-1 -I/usr/include/efl-1 -I/usr/include/eo-1 -I/usr/include/efl-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina -Igfx -D WITHEVAS_COLOR_PREMUL -I . -I lib -I gfx -D WITHEVAS_X11_CONNECTION -D WITHEVAS_X11_SCREEN    -o 'objdir/frontends/econvert' objdir/frontends/econvert.o objdir/image/image.a objdir/codecs/codecs.a objdir/bardecode/bardecode.a objdir/utility/ArgumentList.o objdir/utility/File.o -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections   -lagg_pic -laggfontfreetype_pic -lfreetype  -ljpeg -ltiff  -lpng -lgif -lIlmImf -lImath -lHalf -lIex -lIexMath -lIlmThread -lpthread -lexpat -lz  -L/usr/X11/lib64 -L/usr/X11/lib -L/usr/X11R6/lib -lX11 -lXrender -levas 
for x in objdir/frontends/optimize2bw objdir/frontends/bardecode objdir/frontends/hocr2pdf objdir/frontends/edentify objdir/frontends/empty-page objdir/frontends/e2mtiff objdir/frontends/econvert; do \
  case $x in \
	*.so ) echo INSTALL DYNLIB $x; mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/lib/; install $x /<<PKGBUILDDIR>>/debian/tmp/usr/lib/ ;; \
	*.a ) ;; \
	* ) echo INSTALL EXEC   $x; mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/bin/; install $x /<<PKGBUILDDIR>>/debian/tmp/usr/bin/ ;; \
  esac ;\
done
INSTALL EXEC objdir/frontends/optimize2bw
INSTALL EXEC objdir/frontends/bardecode
INSTALL EXEC objdir/frontends/hocr2pdf
INSTALL EXEC objdir/frontends/edentify
INSTALL EXEC objdir/frontends/empty-page
INSTALL EXEC objdir/frontends/e2mtiff
INSTALL EXEC objdir/frontends/econvert
for x in objdir/gfx/libgsmpgfx.a; do \
  case $x in \
	*.so ) echo INSTALL DYNLIB $x; mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/lib/; install $x /<<PKGBUILDDIR>>/debian/tmp/usr/lib/ ;; \
	*.a ) ;; \
	* ) echo INSTALL EXEC   $x; mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/bin/; install $x /<<PKGBUILDDIR>>/debian/tmp/usr/bin/ ;; \
  esac ;\
done
for x in objdir/edisplay/edisplay; do \
  case $x in \
	*.so ) echo INSTALL DYNLIB $x; mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/lib/; install $x /<<PKGBUILDDIR>>/debian/tmp/usr/lib/ ;; \
	*.a ) ;; \
	* ) echo INSTALL EXEC   $x; mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/bin/; install $x /<<PKGBUILDDIR>>/debian/tmp/usr/bin/ ;; \
  esac ;\
done
INSTALL EXEC objdir/edisplay/edisplay
echo "INSTALL PERL module objdir/api/perl/ExactImage.so"
INSTALL PERL module objdir/api/perl/ExactImage.so
mkdir -p /<<PKGBUILDDIR>>/debian/tmp/usr/lib/arm-linux-gnueabihf/perl5/5.24
install objdir/api/perl/ExactImage.so objdir/api/perl//ExactImage.pm /<<PKGBUILDDIR>>/debian/tmp/usr/lib/arm-linux-gnueabihf/perl5/5.24
make[3]: Leaving directory '/<<PKGBUILDDIR>>'
set -e; \
for python in python2.7; do \
	PYDIR=$(${python} -c 'from distutils.sysconfig import get_python_lib; print get_python_lib()'); \
	mkdir -p debian/tmp/${PYDIR}; \
	cp -a objdir/api/$python/* debian/tmp/${PYDIR}; \
done
make[2]: Leaving directory '/<<PKGBUILDDIR>>'
   dh_install -a -O--parallel -O--list-missing
   dh_installdocs -a -O--parallel -O--list-missing
   dh_installchangelogs -a -O--parallel -O--list-missing
   dh_installexamples -a -O--parallel -O--list-missing
   dh_installman -a -O--parallel -O--list-missing
   dh_python2 -a -O--parallel -O--list-missing
I: dh_python2 fs:322: renaming _ExactImage.so to _ExactImage.arm-linux-gnueabihf.so
   dh_installmime -a -O--parallel -O--list-missing
   dh_lintian -a -O--parallel -O--list-missing
   dh_perl -a -O--parallel -O--list-missing
   dh_link -a -O--parallel -O--list-missing
   dh_strip_nondeterminism -a -O--parallel -O--list-missing
   dh_compress -a -O--parallel -O--list-missing
   dh_fixperms -a -O--parallel -O--list-missing
make[1]: Leaving directory '/<<PKGBUILDDIR>>'
   debian/rules override_dh_strip
make[1]: Entering directory '/<<PKGBUILDDIR>>'
dh_strip -a --ddeb-migration='exactimage-dbg (<< 0.9.1-10~)'
make[1]: Leaving directory '/<<PKGBUILDDIR>>'
   dh_makeshlibs -a -O--parallel -O--list-missing
   debian/rules override_dh_shlibdeps
make[1]: Entering directory '/<<PKGBUILDDIR>>'
dh_shlibdeps
dpkg-shlibdeps: warning: debian/edisplay/usr/bin/edisplay contains an unresolvable reference to symbol __aeabi_atexit@CXXABI_ARM_1.3.3: it's probably a plugin
dpkg-shlibdeps: warning: package could avoid a useless dependency if debian/edisplay/usr/bin/edisplay was not linked against libpthread.so.0 (it uses none of the library's symbols)
dpkg-shlibdeps: warning: package could avoid a useless dependency if debian/edisplay/usr/bin/edisplay was not linked against libXrender.so.1 (it uses none of the library's symbols)
dpkg-shlibdeps: warning: package could avoid a useless dependency if debian/edisplay/usr/bin/edisplay was not linked against libfreetype.so.6 (it uses none of the library's symbols)
dpkg-shlibdeps: warning: debian/exactimage/usr/bin/econvert contains an unresolvable reference to symbol __aeabi_atexit@CXXABI_ARM_1.3.3: it's probably a plugin
dpkg-shlibdeps: warning: debian/exactimage/usr/bin/edentify contains an unresolvable reference to symbol __aeabi_atexit@CXXABI_ARM_1.3.3: it's probably a plugin
dpkg-shlibdeps: warning: debian/exactimage/usr/bin/empty-page contains an unresolvable reference to symbol __aeabi_atexit@CXXABI_ARM_1.3.3: it's probably a plugin
dpkg-shlibdeps: warning: debian/exactimage/usr/bin/bardecode contains an unresolvable reference to symbol __aeabi_atexit@CXXABI_ARM_1.3.3: it's probably a plugin
dpkg-shlibdeps: warning: debian/exactimage/usr/bin/hocr2pdf contains an unresolvable reference to symbol __aeabi_atexit@CXXABI_ARM_1.3.3: it's probably a plugin
dpkg-shlibdeps: warning: debian/exactimage/usr/bin/optimize2bw contains an unresolvable reference to symbol __aeabi_atexit@CXXABI_ARM_1.3.3: it's probably a plugin
dpkg-shlibdeps: warning: debian/exactimage/usr/bin/e2mtiff contains an unresolvable reference to symbol __aeabi_atexit@CXXABI_ARM_1.3.3: it's probably a plugin
dpkg-shlibdeps: warning: package could avoid a useless dependency if debian/exactimage/usr/bin/econvert debian/exactimage/usr/bin/edentify debian/exactimage/usr/bin/empty-page debian/exactimage/usr/bin/bardecode debian/exactimage/usr/bin/hocr2pdf debian/exactimage/usr/bin/optimize2bw debian/exactimage/usr/bin/e2mtiff were not linked against libpthread.so.0 (they use none of the library's symbols)
sed -i -e '/shlibs:Depends.*\(libevas[^ ]*\).*/ { p; s//evas:Depends=\1-engines-x/; b }; /^evas:Depends=/d' debian/*.substvars
make[1]: Leaving directory '/<<PKGBUILDDIR>>'
   dh_installdeb -a -O--parallel -O--list-missing
   dh_gencontrol -a -O--parallel -O--list-missing
dpkg-gencontrol: warning: package python-exactimage: unused substitution variable ${python:Versions}
dpkg-gencontrol: warning: package python-exactimage: unused substitution variable ${python:Versions}
   dh_md5sums -a -O--parallel -O--list-missing
   dh_builddeb -a -O--parallel -O--list-missing
dpkg-deb: building package 'edisplay-dbgsym' in '../edisplay-dbgsym_0.9.2-1_armhf.deb'.
dpkg-deb: building package 'exactimage-dbgsym' in '../exactimage-dbgsym_0.9.2-1_armhf.deb'.
dpkg-deb: building package 'libexactimage-perl-dbgsym' in '../libexactimage-perl-dbgsym_0.9.2-1_armhf.deb'.
dpkg-deb: building package 'python-exactimage-dbgsym' in '../python-exactimage-dbgsym_0.9.2-1_armhf.deb'.
dpkg-deb: building package 'python-exactimage' in '../python-exactimage_0.9.2-1_armhf.deb'.
dpkg-deb: building package 'libexactimage-perl' in '../libexactimage-perl_0.9.2-1_armhf.deb'.
dpkg-deb: building package 'edisplay' in '../edisplay_0.9.2-1_armhf.deb'.
dpkg-deb: building package 'exactimage' in '../exactimage_0.9.2-1_armhf.deb'.
 dpkg-genbuildinfo --build=any
 dpkg-genchanges --build=any -mRaspbian wandboard test autobuilder <root@raspbian.org> >../exactimage_0.9.2-1_armhf.changes
dpkg-genchanges: info: binary-only arch-specific upload (source code and arch-indep packages not included)
 dpkg-source --after-build exactimage-0.9.2
dpkg-buildpackage: info: binary-only upload (no source included)
--------------------------------------------------------------------------------
Build finished at 2017-06-27T05:52:50Z

Finished
--------

I: Built successfully

+------------------------------------------------------------------------------+
| Post Build Chroot                                                            |
+------------------------------------------------------------------------------+


+------------------------------------------------------------------------------+
| Changes                                                                      |
+------------------------------------------------------------------------------+


exactimage_0.9.2-1_armhf.changes:
---------------------------------

Format: 1.8
Date: Thu, 22 Jun 2017 09:44:18 +0200
Source: exactimage
Binary: edisplay exactimage libexactimage-perl python-exactimage
Architecture: armhf
Version: 0.9.2-1
Distribution: buster-staging
Urgency: medium
Maintainer: Raspbian wandboard test autobuilder <root@raspbian.org>
Changed-By: Sven Eckelmann <sven@narfation.org>
Description:
 edisplay   - fast image manipulation programs (image viewer)
 exactimage - fast image manipulation programs
 libexactimage-perl - fast image manipulation library (Perl bindings)
 python-exactimage - fast image manipulation library (Python bindings)
Changes:
 exactimage (0.9.2-1) unstable; urgency=medium
 .
   * debian/control:
     - Mark libexactimage-perl and python-exactimage as Multi-Arch: same
   * debian/patches:
     - Remove upstream merged
       + Add-missing-agg-includes.patch
       + Avoid-overflow-in-ljpeg_start.patch
       + Build-jpeg-functionality-for-libjpeg8.patch
       + Decode-image-before-accessing-the-stride-attribute-f.patch
       + Encode-Ren-as-UTF-8.patch
       + Fix-FTBFS-with-libpng-1.5.patch
       + Fix-memory-leak-when-switching-between-images-in-edi.patch
       + Link-against-libgif-instead-of-deprecated-libungif.patch
       + Sort-X_SRCS-to-reduce-noise-in-reproducible-diff.patch
       + fixed-dcraw-CVE-fix-to-be-able-to-load-dcraw-images.patch
       + fixed-loading-absolute-filenames-with-colon-was-parsed-as.patch
     - Rebase patches on top of 0.9.2:
       + Avoid-infinite-loops-generated-by-GCC-4.8-caused-by-.patch
       + Build-as-C-98-code-to-avoid-errors-when-compiling-as-C-11.patch
       + Disable-dead-code-that-is-causing-compilation-errors.patch
       + Disable-unused-Evas-Helper-function-to-avoid-FTBFS.patch
       + Don-t-compile-dynamic-shared-objects-as-PIE.patch
       + Drop-date-to-make-build-reproducible.patch
       + Enforce-simple-verbose-build-for-blhc.patch
       + Fix-CVE-2015-8366-Index-overflow-in-smal_decode_segment.patch
       + Fix-buffer-overflow-when-decoding-code128-code_set_c.patch
       + Fix-typo-s-optinally-optionally.patch
       + Fix-typo-s-sufficently-sufficiently.patch
       + Remove-dead-timer-code-which-causes-FTBFS.patch
       + Respect-CFLAGS-from-the-environment.patch
       + Use-PIC-version-of-static-AGG-library.patch
       + giflib5.patch
     - Add Remove-obsolete-path-reorientation-code-fixes-nonzero-fil.patch,
       Remove obsolete path reorientation code (fixes nonzero fill)
   * debian/copyright:
     - Update copyright years
Checksums-Sha1:
 f80357b3e327330e352f358181c6c07579d70b17 1925738 edisplay-dbgsym_0.9.2-1_armhf.deb
 9fb175c37b3a08d0c959decc7eb513275aaeddcb 244312 edisplay_0.9.2-1_armhf.deb
 2340006b61bd697fa1dcad81562676d1855633ed 13795714 exactimage-dbgsym_0.9.2-1_armhf.deb
 900a6942007aa082d7e6078d5f145595fde8f489 10480 exactimage_0.9.2-1_armhf.buildinfo
 b939a6eb957daa07bb039e4920f76725d556eafe 563622 exactimage_0.9.2-1_armhf.deb
 8f9e31610922061199ec183fe1df7840d5ba868e 1371550 libexactimage-perl-dbgsym_0.9.2-1_armhf.deb
 860c627e134b99d80a48a8baf527e79336306230 296564 libexactimage-perl_0.9.2-1_armhf.deb
 71c56fa1b26e8e83212c954a584bbcd11111d6eb 1316448 python-exactimage-dbgsym_0.9.2-1_armhf.deb
 0b06776c4f2aba47fc0262566eab86b4f91081e7 286126 python-exactimage_0.9.2-1_armhf.deb
Checksums-Sha256:
 3394cdb40f8c059f5d873cf94a0cfd3884a7431f260225bcf6f8149981c432d9 1925738 edisplay-dbgsym_0.9.2-1_armhf.deb
 aa0e44f6aed95b5b5de233c5f7272f256d3c24b0452266a4c20ca25eaa2fee86 244312 edisplay_0.9.2-1_armhf.deb
 15117d8d407e22c6d111cc1c49bf3637d692bfb621a266841e860e6ecbf7d5dc 13795714 exactimage-dbgsym_0.9.2-1_armhf.deb
 d5be5cb54c97d5c70cdf08c7b161cb03a044f4231f8f309507dc219cca547fb1 10480 exactimage_0.9.2-1_armhf.buildinfo
 5c75f3db58f16c00f3ee73ddfa4f09b8c95cfc5bf271b54113ea5f76432f9e2a 563622 exactimage_0.9.2-1_armhf.deb
 8d7a7c37dc93e446740f50b193c877d58634d6e8d6212ab03c2d27a06293ff33 1371550 libexactimage-perl-dbgsym_0.9.2-1_armhf.deb
 65efa7a31ee77aefa0eee1f24534761f1730f0c2640da78558662c51da82258e 296564 libexactimage-perl_0.9.2-1_armhf.deb
 a7f729df986a77ae0b36eb15bf3b9fcff0a2a7241115837b6c267939640f7d70 1316448 python-exactimage-dbgsym_0.9.2-1_armhf.deb
 7cb40a1616c58140caa43c450f5eefe3e7fc30fcdc6e5b9d0b76a953c8f98132 286126 python-exactimage_0.9.2-1_armhf.deb
Files:
 1e2fdf0bb6fbb2b117e8cc0995c12b68 1925738 debug extra edisplay-dbgsym_0.9.2-1_armhf.deb
 006585ea8843b98e67e7ac37228c3ab7 244312 graphics optional edisplay_0.9.2-1_armhf.deb
 9e6441cdce8b5ab714be78d2e7287cea 13795714 debug extra exactimage-dbgsym_0.9.2-1_armhf.deb
 a22f93c993880dd993f1386c266b0594 10480 graphics optional exactimage_0.9.2-1_armhf.buildinfo
 2a29e3d5ae6830ff2217dc512dbf6c03 563622 graphics optional exactimage_0.9.2-1_armhf.deb
 4961e6109660778777e761f895ac310d 1371550 debug extra libexactimage-perl-dbgsym_0.9.2-1_armhf.deb
 07f4e8560b261fbccc8761a5931852d9 296564 perl optional libexactimage-perl_0.9.2-1_armhf.deb
 3f81089fa3b9a6525405edf9b3e8c4e3 1316448 debug extra python-exactimage-dbgsym_0.9.2-1_armhf.deb
 9f3cb0d5da4147bf20f70b8964a895c5 286126 python optional python-exactimage_0.9.2-1_armhf.deb

+------------------------------------------------------------------------------+
| Package contents                                                             |
+------------------------------------------------------------------------------+


edisplay-dbgsym_0.9.2-1_armhf.deb
---------------------------------

 new debian package, version 2.0.
 size 1925738 bytes: control archive=506 bytes.
     470 bytes,    15 lines      control              
     106 bytes,     1 lines      md5sums              
 Package: edisplay-dbgsym
 Source: exactimage
 Version: 0.9.2-1
 Auto-Built-Package: debug-symbols
 Architecture: armhf
 Maintainer: Sven Eckelmann <sven@narfation.org>
 Installed-Size: 1994
 Depends: edisplay (= 0.9.2-1)
 Breaks: exactimage-dbg (<< 0.9.1-10~)
 Replaces: exactimage-dbg (<< 0.9.1-10~)
 Section: debug
 Priority: extra
 Homepage: https://exactcode.com/opensource/exactimage/
 Description: Debug symbols for edisplay
 Build-Ids: e20ec5f4bea2bdbbc4f4e41a3c06cba92ea2a83a

drwxr-xr-x root/root         0 2017-06-22 07:44 ./
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/e2/
-rw-r--r-- root/root   2030816 2017-06-22 07:44 ./usr/lib/debug/.build-id/e2/0ec5f4bea2bdbbc4f4e41a3c06cba92ea2a83a.debug
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/
lrwxrwxrwx root/root         0 2017-06-22 07:44 ./usr/share/doc/edisplay-dbgsym -> edisplay


edisplay_0.9.2-1_armhf.deb
--------------------------

 new debian package, version 2.0.
 size 244312 bytes: control archive=923 bytes.
     904 bytes,    16 lines      control              
     398 bytes,     6 lines      md5sums              
 Package: edisplay
 Source: exactimage
 Version: 0.9.2-1
 Architecture: armhf
 Maintainer: Sven Eckelmann <sven@narfation.org>
 Installed-Size: 591
 Depends: libevas1-engines-x, libc6 (>= 2.11), libevas1 (>= 1.7.7), libexpat1 (>= 2.0.1), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.0), libgif7 (>= 5.1), libgomp1 (>= 4.9), libilmbase12 (>= 2.2.0), libjpeg62-turbo (>= 1.3.1), libopenexr22, libpng16-16 (>= 1.6.2-1), libstdc++6 (>= 5.2), libtiff5 (>= 4.0.3), libx11-6, libxrender1, zlib1g (>= 1:1.1.4)
 Section: graphics
 Priority: optional
 Homepage: https://exactcode.com/opensource/exactimage/
 Description: fast image manipulation programs (image viewer)
  ExactImage is a fast C++ image processing library. Unlike many other library
  frameworks it allows operation in several color spaces and bit depths
  natively, resulting in low memory and computational requirements.
  .
  This package contains the image viewer.

drwxr-xr-x root/root         0 2017-06-22 07:44 ./
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/bin/
-rwxr-xr-x root/root    562612 2017-06-22 07:44 ./usr/bin/edisplay
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/mime/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/mime/packages/
-rw-r--r-- root/root       608 2017-06-22 07:44 ./usr/lib/mime/packages/edisplay
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/edisplay/
-rw-r--r-- root/root      6849 2017-06-22 07:44 ./usr/share/doc/edisplay/changelog.Debian.gz
-rw-r--r-- root/root     15481 2017-06-22 07:44 ./usr/share/doc/edisplay/copyright
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/lintian/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/lintian/overrides/
-rw-r--r-- root/root        71 2017-06-22 07:44 ./usr/share/lintian/overrides/edisplay
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/man/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/man/man1/
-rw-r--r-- root/root      1536 2017-06-22 07:44 ./usr/share/man/man1/edisplay.1.gz


exactimage-dbgsym_0.9.2-1_armhf.deb
-----------------------------------

 new debian package, version 2.0.
 size 13795714 bytes: control archive=833 bytes.
     723 bytes,    15 lines      control              
     742 bytes,     7 lines      md5sums              
 Package: exactimage-dbgsym
 Source: exactimage
 Version: 0.9.2-1
 Auto-Built-Package: debug-symbols
 Architecture: armhf
 Maintainer: Sven Eckelmann <sven@narfation.org>
 Installed-Size: 14241
 Depends: exactimage (= 0.9.2-1)
 Breaks: exactimage-dbg (<< 0.9.1-10~)
 Replaces: exactimage-dbg (<< 0.9.1-10~)
 Section: debug
 Priority: extra
 Homepage: https://exactcode.com/opensource/exactimage/
 Description: Debug symbols for exactimage
 Build-Ids: 4cc28a229798bc79dd43f4dd208116f3d67d98a3 5c1b8660387e762281bf9a7e25e068c89e712409 a81d5110cc8f1683d2a35eaf0dcab2c1d2e8586f b02084ca5c1bfc88c51a95f10f815847a264b341 db26dc8099c440d080fe9b6da94490e05e830375 e5f73bed1e98ee451d7e7c61ccd84e2f02f2aac5 ed196f4b292c785cef9c1f9c809b3e87a55728d2

drwxr-xr-x root/root         0 2017-06-22 07:44 ./
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/4c/
-rw-r--r-- root/root   2026784 2017-06-22 07:44 ./usr/lib/debug/.build-id/4c/c28a229798bc79dd43f4dd208116f3d67d98a3.debug
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/5c/
-rw-r--r-- root/root   1990856 2017-06-22 07:44 ./usr/lib/debug/.build-id/5c/1b8660387e762281bf9a7e25e068c89e712409.debug
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/a8/
-rw-r--r-- root/root   2131176 2017-06-22 07:44 ./usr/lib/debug/.build-id/a8/1d5110cc8f1683d2a35eaf0dcab2c1d2e8586f.debug
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/b0/
-rw-r--r-- root/root   2028920 2017-06-22 07:44 ./usr/lib/debug/.build-id/b0/2084ca5c1bfc88c51a95f10f815847a264b341.debug
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/db/
-rw-r--r-- root/root   2058940 2017-06-22 07:44 ./usr/lib/debug/.build-id/db/26dc8099c440d080fe9b6da94490e05e830375.debug
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/e5/
-rw-r--r-- root/root   2340752 2017-06-22 07:44 ./usr/lib/debug/.build-id/e5/f73bed1e98ee451d7e7c61ccd84e2f02f2aac5.debug
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/ed/
-rw-r--r-- root/root   1985472 2017-06-22 07:44 ./usr/lib/debug/.build-id/ed/196f4b292c785cef9c1f9c809b3e87a55728d2.debug
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/
lrwxrwxrwx root/root         0 2017-06-22 07:44 ./usr/share/doc/exactimage-dbgsym -> exactimage


exactimage_0.9.2-1_armhf.deb
----------------------------

 new debian package, version 2.0.
 size 563622 bytes: control archive=1254 bytes.
     827 bytes,    16 lines      control              
    1190 bytes,    19 lines      md5sums              
 Package: exactimage
 Version: 0.9.2-1
 Architecture: armhf
 Maintainer: Sven Eckelmann <sven@narfation.org>
 Installed-Size: 4194
 Depends: libc6 (>= 2.11), libexpat1 (>= 2.0.1), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.0), libgif7 (>= 5.1), libgomp1 (>= 4.9), libilmbase12 (>= 2.2.0), libjpeg62-turbo (>= 1.3.1), libopenexr22, libpng16-16 (>= 1.6.2-1), libstdc++6 (>= 5.2), libtiff5 (>= 4.0.3), zlib1g (>= 1:1.1.4)
 Recommends: edisplay
 Section: graphics
 Priority: optional
 Homepage: https://exactcode.com/opensource/exactimage/
 Description: fast image manipulation programs
  ExactImage is a fast C++ image processing library. Unlike many other library
  frameworks it allows operation in several color spaces and bit depths
  natively, resulting in low memory and computational requirements.
  .
  This package contains the utilities.

drwxr-xr-x root/root         0 2017-06-22 07:44 ./
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/bin/
-rwxr-xr-x root/root    603556 2017-06-22 07:44 ./usr/bin/bardecode
-rwxr-xr-x root/root    542116 2017-06-22 07:44 ./usr/bin/e2mtiff
-rwxr-xr-x root/root    791972 2017-06-22 07:44 ./usr/bin/econvert
-rwxr-xr-x root/root    546212 2017-06-22 07:44 ./usr/bin/edentify
-rwxr-xr-x root/root    574884 2017-06-22 07:44 ./usr/bin/empty-page
-rwxr-xr-x root/root    574892 2017-06-22 07:44 ./usr/bin/hocr2pdf
-rwxr-xr-x root/root    599460 2017-06-22 07:44 ./usr/bin/optimize2bw
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/exactimage/
-rw-r--r-- root/root      1430 2008-12-17 17:20 ./usr/share/doc/exactimage/TODO
-rw-r--r-- root/root      6849 2017-06-22 07:44 ./usr/share/doc/exactimage/changelog.Debian.gz
-rw-r--r-- root/root     15481 2017-06-22 07:44 ./usr/share/doc/exactimage/copyright
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/lintian/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/lintian/overrides/
-rw-r--r-- root/root        73 2017-06-22 07:44 ./usr/share/lintian/overrides/exactimage
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/man/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/man/man1/
-rw-r--r-- root/root      1510 2017-06-22 07:44 ./usr/share/man/man1/bardecode.1.gz
-rw-r--r-- root/root      1203 2017-06-22 07:44 ./usr/share/man/man1/e2mtiff.1.gz
-rw-r--r-- root/root      3735 2017-06-22 07:44 ./usr/share/man/man1/econvert.1.gz
-rw-r--r-- root/root      1607 2017-06-22 07:44 ./usr/share/man/man1/edentify.1.gz
-rw-r--r-- root/root      1525 2017-06-22 07:44 ./usr/share/man/man1/empty-page.1.gz
-rw-r--r-- root/root      1666 2017-06-22 07:44 ./usr/share/man/man1/hocr2pdf.1.gz
-rw-r--r-- root/root      1597 2017-06-22 07:44 ./usr/share/man/man1/optimize2bw.1.gz
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/man/man7/
-rw-r--r-- root/root      1345 2017-06-22 07:44 ./usr/share/man/man7/exactimage.7.gz


libexactimage-perl-dbgsym_0.9.2-1_armhf.deb
-------------------------------------------

 new debian package, version 2.0.
 size 1371550 bytes: control archive=525 bytes.
     517 bytes,    16 lines      control              
     106 bytes,     1 lines      md5sums              
 Package: libexactimage-perl-dbgsym
 Source: exactimage
 Version: 0.9.2-1
 Auto-Built-Package: debug-symbols
 Architecture: armhf
 Maintainer: Sven Eckelmann <sven@narfation.org>
 Installed-Size: 1466
 Depends: libexactimage-perl (= 0.9.2-1)
 Breaks: exactimage-dbg (<< 0.9.1-10~)
 Replaces: exactimage-dbg (<< 0.9.1-10~)
 Section: debug
 Priority: extra
 Multi-Arch: same
 Homepage: https://exactcode.com/opensource/exactimage/
 Description: Debug symbols for libexactimage-perl
 Build-Ids: ff40891b99114732e5fbc5c0e79f54d464f3b492

drwxr-xr-x root/root         0 2017-06-22 07:44 ./
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/ff/
-rw-r--r-- root/root   1490172 2017-06-22 07:44 ./usr/lib/debug/.build-id/ff/40891b99114732e5fbc5c0e79f54d464f3b492.debug
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/
lrwxrwxrwx root/root         0 2017-06-22 07:44 ./usr/share/doc/libexactimage-perl-dbgsym -> libexactimage-perl


libexactimage-perl_0.9.2-1_armhf.deb
------------------------------------

 new debian package, version 2.0.
 size 296564 bytes: control archive=975 bytes.
     924 bytes,    19 lines      control              
     587 bytes,     7 lines      md5sums              
 Package: libexactimage-perl
 Source: exactimage
 Version: 0.9.2-1
 Architecture: armhf
 Maintainer: Sven Eckelmann <sven@narfation.org>
 Installed-Size: 823
 Depends: perl (>= 5.24.1-4), perlapi-5.24.1, libc6 (>= 2.11), libexpat1 (>= 2.0.1), libgcc1 (>= 1:4.0), libgif7 (>= 5.1), libilmbase12 (>= 2.2.0), libjpeg62-turbo (>= 1.3.1), libopenexr22, libpng16-16 (>= 1.6.2-1), libstdc++6 (>= 5.2), libtiff5 (>= 4.0.3), zlib1g (>= 1:1.1.4)
 Breaks: exactimage-perl (<< 0.8)
 Replaces: exactimage-perl (<< 0.8)
 Section: perl
 Priority: optional
 Multi-Arch: same
 Homepage: https://exactcode.com/opensource/exactimage/
 Description: fast image manipulation library (Perl bindings)
  ExactImage is a fast C++ image processing library. Unlike many other library
  frameworks it allows operation in several color spaces and bit depths
  natively, resulting in low memory and computational requirements.
  .
  This package contains the Perl bindings.

drwxr-xr-x root/root         0 2017-06-22 07:44 ./
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/arm-linux-gnueabihf/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/arm-linux-gnueabihf/perl5/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/arm-linux-gnueabihf/perl5/5.24/
-rw-r--r-- root/root      5135 2017-06-22 07:44 ./usr/lib/arm-linux-gnueabihf/perl5/5.24/ExactImage.pm
-rw-r--r-- root/root    792408 2017-06-22 07:44 ./usr/lib/arm-linux-gnueabihf/perl5/5.24/ExactImage.so
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/libexactimage-perl/
-rw-r--r-- root/root      6849 2017-06-22 07:44 ./usr/share/doc/libexactimage-perl/changelog.Debian.gz
-rw-r--r-- root/root     15481 2017-06-22 07:44 ./usr/share/doc/libexactimage-perl/copyright
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/libexactimage-perl/examples/
-rw-r--r-- root/root      1384 2009-06-15 10:48 ./usr/share/doc/libexactimage-perl/examples/fuzz.pl
-rw-r--r-- root/root      3839 2010-09-16 18:12 ./usr/share/doc/libexactimage-perl/examples/test.pl
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/lintian/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/lintian/overrides/
-rw-r--r-- root/root        81 2017-06-22 07:44 ./usr/share/lintian/overrides/libexactimage-perl


python-exactimage-dbgsym_0.9.2-1_armhf.deb
------------------------------------------

 new debian package, version 2.0.
 size 1316448 bytes: control archive=524 bytes.
     514 bytes,    16 lines      control              
     106 bytes,     1 lines      md5sums              
 Package: python-exactimage-dbgsym
 Source: exactimage
 Version: 0.9.2-1
 Auto-Built-Package: debug-symbols
 Architecture: armhf
 Maintainer: Sven Eckelmann <sven@narfation.org>
 Installed-Size: 1411
 Depends: python-exactimage (= 0.9.2-1)
 Breaks: exactimage-dbg (<< 0.9.1-10~)
 Replaces: exactimage-dbg (<< 0.9.1-10~)
 Section: debug
 Priority: extra
 Multi-Arch: same
 Homepage: https://exactcode.com/opensource/exactimage/
 Description: Debug symbols for python-exactimage
 Build-Ids: 84ca84f35359c849ec422e542e1aa1123539ebf0

drwxr-xr-x root/root         0 2017-06-22 07:44 ./
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/debug/.build-id/84/
-rw-r--r-- root/root   1434444 2017-06-22 07:44 ./usr/lib/debug/.build-id/84/ca84f35359c849ec422e542e1aa1123539ebf0.debug
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/
lrwxrwxrwx root/root         0 2017-06-22 07:44 ./usr/share/doc/python-exactimage-dbgsym -> python-exactimage


python-exactimage_0.9.2-1_armhf.deb
-----------------------------------

 new debian package, version 2.0.
 size 286126 bytes: control archive=1162 bytes.
     938 bytes,    18 lines      control              
     506 bytes,     6 lines      md5sums              
     167 bytes,     9 lines   *  postinst             #!/bin/sh
     271 bytes,    14 lines   *  prerm                #!/bin/sh
 Package: python-exactimage
 Source: exactimage
 Version: 0.9.2-1
 Architecture: armhf
 Maintainer: Sven Eckelmann <sven@narfation.org>
 Installed-Size: 778
 Depends: python (<< 2.8), python (>= 2.7~), python:any (<< 2.8), python:any (>= 2.7.5-5~), libc6 (>= 2.11), libexpat1 (>= 2.0.1), libgcc1 (>= 1:4.0), libgif7 (>= 5.1), libilmbase12 (>= 2.2.0), libjpeg62-turbo (>= 1.3.1), libopenexr22, libpng16-16 (>= 1.6.2-1), libstdc++6 (>= 5.2), libtiff5 (>= 4.0.3), zlib1g (>= 1:1.1.4)
 Provides: python2.7-exactimage
 Section: python
 Priority: optional
 Multi-Arch: same
 Homepage: https://exactcode.com/opensource/exactimage/
 Description: fast image manipulation library (Python bindings)
  ExactImage is a fast C++ image processing library. Unlike many other library
  frameworks it allows operation in several color spaces and bit depths
  natively, resulting in low memory and computational requirements.
  .
  This package contains the Python bindings.

drwxr-xr-x root/root         0 2017-06-22 07:44 ./
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/python2.7/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/lib/python2.7/dist-packages/
-rw-r--r-- root/root     13437 2017-06-22 07:44 ./usr/lib/python2.7/dist-packages/ExactImage.py
-rw-r--r-- root/root    740824 2017-06-22 07:44 ./usr/lib/python2.7/dist-packages/_ExactImage.arm-linux-gnueabihf.so
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/python-exactimage/
-rw-r--r-- root/root      6849 2017-06-22 07:44 ./usr/share/doc/python-exactimage/changelog.Debian.gz
-rw-r--r-- root/root     15481 2017-06-22 07:44 ./usr/share/doc/python-exactimage/copyright
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/doc/python-exactimage/examples/
-rw-r--r-- root/root      1653 2010-09-16 18:12 ./usr/share/doc/python-exactimage/examples/test.py
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/lintian/
drwxr-xr-x root/root         0 2017-06-22 07:44 ./usr/share/lintian/overrides/
-rw-r--r-- root/root        80 2017-06-22 07:44 ./usr/share/lintian/overrides/python-exactimage


+------------------------------------------------------------------------------+
| Post Build                                                                   |
+------------------------------------------------------------------------------+


+------------------------------------------------------------------------------+
| Cleanup                                                                      |
+------------------------------------------------------------------------------+

Purging /<<BUILDDIR>>
Not cleaning session: cloned chroot in use

+------------------------------------------------------------------------------+
| Summary                                                                      |
+------------------------------------------------------------------------------+

Build Architecture: armhf
Build-Space: 217740
Build-Time: 635
Distribution: buster-staging
Host Architecture: armhf
Install-Time: 1382
Job: exactimage_0.9.2-1
Machine Architecture: armhf
Package: exactimage
Package-Time: 2063
Source-Version: 0.9.2-1
Space: 217740
Status: successful
Version: 0.9.2-1
--------------------------------------------------------------------------------
Finished at 2017-06-27T05:52:50Z
Build needed 00:34:23, 217740k disc space